JS逆向 AST 抽象语法树解析与实践

简介: JS逆向 AST 抽象语法树解析与实践

🧩 JS逆向 AST 抽象语法树解析与实践

🔍 什么是 AST 技术?

抽象语法树(Abstract Syntax Tree,AST)是一种以树状结构表示程序源代码的方式,它将代码中的每个组成部分表示为树的一个节点。AST 是编译器和解释器中的重要概念,它用于将源代码转换为计算机能够理解的形式。AST 的主要作用是将源代码中的语法结构转化为树形结构,便于对代码进行分析、转换和优化。

在 JavaScript 中,AST 是通过解析器(如 acornesprima)生成的。这些解析器会将 JavaScript 代码转换为 AST,随后可以通过 AST 对代码进行深入分析或转换。

AST 示例

以下是一个较复杂的 JavaScript 代码示例及其对应的 AST:

// JavaScript 代码示例
function add(a, b) {
  const sum = a + b;
  return sum;
}

const result = add(10, 20);
console.log(result);

在这个代码示例中,函数 add 定义了两个参数 ab,并返回它们的和。代码的 AST 可能如下所示:

Program
  ├── FunctionDeclaration (add)
  │    ├── Parameters
  │    │    ├── Identifier (a)
  │    │    └── Identifier (b)
  │    ├── BlockStatement
  │    │    ├── VariableDeclaration (const)
  │    │    │    ├── VariableDeclarator (sum)
  │    │    │    │    └── BinaryExpression (+)
  │    │    │    │         ├── Identifier (a)
  │    │    │    │         └── Identifier (b)
  │    │    └── ReturnStatement
  │    │         └── Identifier (sum)
  ├── VariableDeclaration (const)
  │    ├── VariableDeclarator (result)
  │    │    └── CallExpression (add)
  │    │         ├── Literal (10)
  │    │         └── Literal (20)
  └── ExpressionStatement (console.log)
       └── Identifier (result)

🛠️ Parser API 学习

JavaScript 提供了一些工具和库,用于解析源代码并生成 AST。其中,acornesprima 是最常用的解析器库。acorn 是一个轻量级的解析器,具有高效且快速的特点,能够将 JavaScript 代码解析为 AST。

使用 acorn 解析 JavaScript 代码

以下是如何使用 acorn 解析 JavaScript 代码并输出 AST 的示例:

const acorn = require('acorn');

// 需要解析的 JavaScript 代码
const code = `
function add(a, b) {
  const sum = a + b;
  return sum;
}

const result = add(10, 20);
console.log(result);
`;

// 使用 acorn 解析代码
const ast = acorn.parse(code, { ecmaVersion: 2020 });

// 输出 AST
console.log(JSON.stringify(ast, null, 2));

在这个示例中,我们使用 acorn.parse 方法将 JavaScript 代码解析为 AST。ecmaVersion 选项指定了 ECMAScript 的版本,确保解析器能够正确处理不同版本的语法。JSON.stringify 方法用于将 AST 对象转换为 JSON 字符串,以便于阅读和调试。

acorn 配置选项

acorn 解析器提供了多种配置选项,允许我们根据需要调整解析行为:

const ast = acorn.parse(code, {
  ecmaVersion: 2020,  // ECMAScript 版本
  sourceType: 'module', // 支持 ES6 模块
  locations: true,     // 启用位置信息
  onComment: (block, text, start, end) => {
    console.log(`Comment: ${text}`);
  }
});
  • ecmaVersion: 指定 ECMAScript 的版本,例如 2020。
  • sourceType: 可以是 scriptmodule,指定源代码类型。
  • locations: 启用位置信息以便于调试。
  • onComment: 回调函数,用于处理代码中的注释。

🔍 traverse 库学习

traverse 是一个用于遍历和操作 AST 的库,它可以帮助我们对 AST 进行各种操作,如遍历、修改和转换。traverse 提供了一种简洁的方式来访问 AST 的各个部分。

安装 traverse

npm install traverse

使用 traverse 遍历 AST

以下是如何使用 traverse 库遍历 AST 的示例:

const traverse = require('traverse');
const acorn = require('acorn');

// 解析 JavaScript 代码
const code = `
function add(a, b) {
  const sum = a + b;
  return sum;
}

const result = add(10, 20);
console.log(result);
`;
const ast = acorn.parse(code, { ecmaVersion: 2020 });

// 遍历 AST
traverse(ast).forEach(function (node) {
    if (node.type === 'Identifier') {
        console.log(`Found identifier: ${node.name}`);
    }
});

在这个示例中,我们使用 traverse 库遍历 AST,并打印出所有标识符节点的名称。traverse 提供了一种简洁的方式来访问和操作 AST 的各个部分。traverse 支持多种遍历策略,可以根据需要定制遍历行为。

自定义遍历策略

traverse 允许我们定义自定义遍历策略,以满足特定需求:

traverse(ast).forEach(function (node) {
    if (node.type === 'FunctionDeclaration') {
        console.log(`Found function declaration: ${node.id.name}`);
    } else if (node.type === 'VariableDeclarator') {
        console.log(`Found variable declarator: ${node.id.name}`);
    }
});

在这个示例中,我们定制了遍历策略,以便分别处理函数声明和变量声明节点。

🧩 字符串和编码还原

在处理 JavaScript 代码时,我们常常需要对字符串和编码进行还原。字符串可能包含转义字符、Unicode 编码等,需要对其进行解析和还原。

字符串解码

JavaScript 字符串中可能包含转义字符,例如 Unicode 转义序列。我们可以使用 JSON.parse 方法将这些转义字符还原为普通字符串:

// 原始字符串
const encodedString = '\\u0048\\u0065\\u006C\\u006C\\u006F';

// 将转义字符还原为普通字符串
const decodedString = JSON.parse(`"${encodedString}"`);

console.log(decodedString); // 输出: Hello

在这个示例中,我们将包含 Unicode 转义序列的字符串 \\u0048\\u0065\\u006C\\u006C\\u006F 还原为普通字符串 Hello。这种方法对于处理编码和转义字符非常有效。

编码还原

URL 编码是一种常见的编码方式,我们可以使用 decodeURIComponent 方法将其还原为普通字符串:

// URL 编码字符串
const encodedURI = 'Hello%20World%21';

// 还原为普通字符串
const decodedURI = decodeURIComponent(encodedURI);

console.log(decodedURI); // 输出: Hello World!

🛠️ 通用常量还原

在 JavaScript 代码中,常量的还原通常涉及将常量值恢复为其原始形式。常量可能以不同的格式存在,如十六进制、二进制等。

十六进制常量还原

// 十六进制常量
const hexValue = 0x1A3F;

// 还原为十进制
const decimalValue = hexValue;

console.log(decimalValue); // 输出: 6719

在这个示例中,我们将十六进制常量 0x1A3F 还原为其十进制值 6719。十六进制常量在 JavaScript 中经常用于表示颜色值、内存地址等。

二进制常量还原

// 二进制常量
const binaryValue = 0b101010;

// 还原为十进制
const decimalValue = binaryValue;

console.log(decimalValue); // 输出: 42

在这个示例中,我们将二进制常量 0b101010 还原为其十进制值 42。二进制常量在 JavaScript 中用于表示位操作或二进制数据。

🧩 evaluate 方法学习

evaluate 方法通常用于执行或计算表达式。它可以在 JavaScript 代码中动态执行表达式并返回结果。使用 eval 方法时要特别

小心,因为它可以执行任意代码,可能导致安全问题。

使用 eval 执行代码

const expression = '2 + 3 * 4';

// 使用 eval 执行表达式
const result = eval(expression);

console.log(result); // 输出: 14

在这个示例中,我们使用 eval 执行一个简单的数学表达式,并输出结果。eval 可以动态地执行任意 JavaScript 代码,因此使用时需谨慎。

使用 Function 构造函数

为了避免使用 eval,可以使用 Function 构造函数动态地创建和执行代码:

const expression = '2 + 3 * 4';

// 使用 Function 构造函数执行表达式
const result = new Function('return ' + expression)();

console.log(result); // 输出: 14

Function 构造函数提供了一种更安全的方式来动态执行代码,但仍然需要确保代码的安全性。

🔍 实战解 OB 高级混淆

在实际应用中,我们可能会遇到 JavaScript 代码的高级混淆技术,这些技术可以使代码难以理解。以下是如何解混淆高级混淆代码的示例:

解混淆示例

高级混淆技术可能涉及到复杂的函数调用、字符串加密等。以下是一个解混淆示例:

// 混淆代码示例
const obfuscatedCode = `
(function() {
    var _0x1a2b = ['\x66\x6F\x6F', '\x62\x61\x72', '\x62\x61\x7A'];
    var _0x1234 = function(_0x5678) {
        return _0x1a2b[_0x5678];
    };
    console.log(_0x1234(0));
})();
`;

// 还原混淆代码
const restoredCode = `
(function() {
    var _0x1a2b = ['foo', 'bar', 'baz'];
    var _0x1234 = function(index) {
        return _0x1a2b[index];
    };
    console.log(_0x1234(0));
})();
`;

console.log(restoredCode); // 输出: 还原后的代码

在这个示例中,混淆代码使用了十六进制表示的字符串和函数调用。我们将混淆代码还原为更易读的形式,使其更容易理解。

极验 JS 实战解混淆

极验验证码是一种常见的防护技术,它通过混淆 JavaScript 代码来防止自动化访问。以下是如何解混淆极验 JS 代码的示例:

// 极验混淆代码示例
const geetestObfuscatedCode = `
(function() {
    var _0x1a2b = ['\x62\x79\x70\x61\x73\x73', '\x6c\x6f\x67'];
    console.log(_0x1a2b[0]);
})();
`;
// 还原混淆代码
const geetestRestoredCode = `
(function() {
    var _0x1a2b = ['bypass', 'log'];
    console.log(_0x1a2b[0]);
})();
`;
console.log(geetestRestoredCode); // 输出: 还原后的代码
目录
相关文章
|
10月前
|
前端开发 算法 API
构建高性能图像处理Web应用:Next.js与TailwindCSS实践
本文分享了构建在线图像黑白转换工具的技术实践,涵盖技术栈选择、架构设计与性能优化。项目采用Next.js提供优秀的SSR性能和SEO支持,TailwindCSS加速UI开发,WebAssembly实现高性能图像处理算法。通过渐进式处理、WebWorker隔离及内存管理等策略,解决大图像处理性能瓶颈,并确保跨浏览器兼容性和移动设备优化。实际应用案例展示了其即时处理、高质量输出和客户端隐私保护等特点。未来计划引入WebGPU加速、AI增强等功能,进一步提升用户体验。此技术栈为Web图像处理应用提供了高效可行的解决方案。
|
6月前
|
JavaScript 前端开发 IDE
TypeScript vs. JavaScript:技术对比与核心差异解析
TypeScript 作为 JavaScript 的超集,通过静态类型系统、编译时错误检测和强大的工具链支持,显著提升代码质量与可维护性,尤其适用于中大型项目和团队协作。相较之下,JavaScript 更灵活,适合快速原型开发。本文从类型系统、错误检测、工具支持等多维度对比两者差异,并提供技术选型建议,助力开发者合理选择。
1291 1
|
6月前
|
JavaScript 前端开发 开发者
Nest.js控制器深度解析:路由与请求处理的高级特性
以上就是对 NestJS 控制层高级特性深度解析:从基本概念到异步支持再到更复杂场景下拦截其与管道等功能性组件运用都有所涉及,希望能够帮助开发者更好地理解和运用 NestJS 进行高效开发工作。
433 15
|
6月前
|
存储 JavaScript 前端开发
JavaScript 语法全面解析
JavaScript 语法体系丰富且不断更新,从基础的变量声明、数据类型,到复杂的函数、对象、异步语法,每个知识点都需要开发者深入理解并灵活运用。本文梳理的 JS 语法核心内容,可为开发者提供系统的学习框架,后续还需通过大量实践(如编写交互组件、实现业务逻辑)巩固知识,逐步提升 JS 编程能力,应对前端开发中的各类挑战。
|
9月前
|
机器学习/深度学习 JavaScript 前端开发
JS进阶教程:递归函数原理与篇例解析
通过对这些代码示例的学习,我们已经了解了递归的原理以及递归在JS中的应用方法。递归虽然有着理论升华,但弄清它的核心思想并不难。举个随手可见的例子,火影鸣人做的影分身,你看到的都是同一个鸣人,但他们的行为却能在全局产生影响,这不就是递归吗?雾里看花,透过其间你或许已经深入了递归的魅力之中。
370 19
|
11月前
|
前端开发 JavaScript Java
【Java进阶】JavaScript电灯开关实例:从理论到实践
这个例子展示了JavaScript的基本功能,包括操作HTML元素,监听事件,以及改变元素的样式。通过学习和理解这个例子,你可以了解到JavaScript在网页中的应用,以及如何使用JavaScript来创建交互式的网页。
220 13
|
10月前
|
JSON 前端开发 Serverless
Mock.js 语法结构全解析
Mock.js 的语法规范介绍,从数据模板定义规范和数据占位符定义规范俩部分介绍, 让你更好的使用 Mock.js 来模拟数据并提高开发效率。
|
数据采集 前端开发 JavaScript
金融数据分析:解析JavaScript渲染的隐藏表格
本文详解了如何使用Python与Selenium结合代理IP技术,从金融网站(如东方财富网)抓取由JavaScript渲染的隐藏表格数据。内容涵盖环境搭建、代理配置、模拟用户行为、数据解析与分析等关键步骤。通过设置Cookie和User-Agent,突破反爬机制;借助Selenium等待页面渲染,精准定位动态数据。同时,提供了常见错误解决方案及延伸练习,帮助读者掌握金融数据采集的核心技能,为投资决策提供支持。注意规避动态加载、代理验证及元素定位等潜在陷阱,确保数据抓取高效稳定。
413 17
|
10月前
|
人工智能 监控 前端开发
基于 Next.js 的书法字体生成工具架构设计与 SSR 优化实践
本项目是一款书法字体生成工具,采用 Next.js 14(App Router)与 Tailwind CSS 构建前端,阿里云 Serverless 部署后端。通过混合渲染策略(SSG/SSR/CSR)、Web Worker 异步计算及 CDN 字体分片加载优化性能。服务端借助阿里云函数计算处理计算密集型任务,将平均耗时从 1200ms 降至 280ms,支持 1000+ QPS。动态路由与 ARMS 监控提升工程化水平,未来计划引入 WebGPU 和 AI 字体风格迁移技术,进一步优化用户体验。

热门文章

最新文章

推荐镜像

更多
  • DNS