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

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: 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); // 输出: 还原后的代码
目录
相关文章
|
1月前
|
存储 缓存 安全
Java内存模型深度解析:从理论到实践####
【10月更文挑战第21天】 本文深入探讨了Java内存模型(JMM)的核心概念与底层机制,通过剖析其设计原理、内存可见性问题及其解决方案,结合具体代码示例,帮助读者构建对JMM的全面理解。不同于传统的摘要概述,我们将直接以故事化手法引入,让读者在轻松的情境中领略JMM的精髓。 ####
38 6
|
27天前
|
运维 持续交付 云计算
深入解析云计算中的微服务架构:原理、优势与实践
深入解析云计算中的微服务架构:原理、优势与实践
61 1
|
1月前
|
消息中间件 存储 缓存
十万订单每秒热点数据架构优化实践深度解析
【11月更文挑战第20天】随着互联网技术的飞速发展,电子商务平台在高峰时段需要处理海量订单,这对系统的性能、稳定性和扩展性提出了极高的要求。尤其是在“双十一”、“618”等大型促销活动中,每秒需要处理数万甚至数十万笔订单,这对系统的热点数据处理能力构成了严峻挑战。本文将深入探讨如何优化架构以应对每秒十万订单级别的热点数据处理,从历史背景、功能点、业务场景、底层原理以及使用Java模拟示例等多个维度进行剖析。
55 8
|
20天前
|
机器学习/深度学习 人工智能 算法
深入解析图神经网络:Graph Transformer的算法基础与工程实践
Graph Transformer是一种结合了Transformer自注意力机制与图神经网络(GNNs)特点的神经网络模型,专为处理图结构数据而设计。它通过改进的数据表示方法、自注意力机制、拉普拉斯位置编码、消息传递与聚合机制等核心技术,实现了对图中节点间关系信息的高效处理及长程依赖关系的捕捉,显著提升了图相关任务的性能。本文详细解析了Graph Transformer的技术原理、实现细节及应用场景,并通过图书推荐系统的实例,展示了其在实际问题解决中的强大能力。
115 30
|
20天前
|
存储 网络协议 编译器
【C语言】深入解析C语言结构体:定义、声明与高级应用实践
通过根据需求合理选择结构体定义和声明的放置位置,并灵活结合动态内存分配、内存优化和数据结构设计,可以显著提高代码的可维护性和运行效率。在实际开发中,建议遵循以下原则: - **模块化设计**:尽可能封装实现细节,减少模块间的耦合。 - **内存管理**:明确动态分配与释放的责任,防止资源泄漏。 - **优化顺序**:合理排列结构体成员以减少内存占用。
104 14
|
15天前
|
存储 网络架构
Next.js 实战 (四):i18n 国际化的最优方案实践
这篇文章介绍了Next.js国际化方案,作者对比了网上常见的方案并提出了自己的需求:不破坏应用程序的目录结构和路由。文章推荐使用next-intl库来实现国际化,并提供了详细的安装步骤和代码示例。作者实现了国际化切换时不改变路由,并把当前语言的key存储到浏览器cookie中,使得刷新浏览器后语言不会失效。最后,文章总结了这种国际化方案的优势,并提供Github仓库链接供读者参考。
|
24天前
|
存储 算法
深入解析PID控制算法:从理论到实践的完整指南
前言 大家好,今天我们介绍一下经典控制理论中的PID控制算法,并着重讲解该算法的编码实现,为实现后续的倒立摆样例内容做准备。 众所周知,掌握了 PID ,就相当于进入了控制工程的大门,也能为更高阶的控制理论学习打下基础。 在很多的自动化控制领域。都会遇到PID控制算法,这种算法具有很好的控制模式,可以让系统具有很好的鲁棒性。 基本介绍 PID 深入理解 (1)闭环控制系统:讲解 PID 之前,我们先解释什么是闭环控制系统。简单说就是一个有输入有输出的系统,输入能影响输出。一般情况下,人们也称输出为反馈,因此也叫闭环反馈控制系统。比如恒温水池,输入就是加热功率,输出就是水温度;比如冷库,
192 15
|
26天前
|
弹性计算 持续交付 API
构建高效后端服务:微服务架构的深度解析与实践
在当今快速发展的软件行业中,构建高效、可扩展且易于维护的后端服务是每个技术团队的追求。本文将深入探讨微服务架构的核心概念、设计原则及其在实际项目中的应用,通过具体案例分析,展示如何利用微服务架构解决传统单体应用面临的挑战,提升系统的灵活性和响应速度。我们将从微服务的拆分策略、通信机制、服务发现、配置管理、以及持续集成/持续部署(CI/CD)等方面进行全面剖析,旨在为读者提供一套实用的微服务实施指南。
|
20天前
|
存储 缓存 Python
Python中的装饰器深度解析与实践
在Python的世界里,装饰器如同一位神秘的魔法师,它拥有改变函数行为的能力。本文将揭开装饰器的神秘面纱,通过直观的代码示例,引导你理解其工作原理,并掌握如何在实际项目中灵活运用这一强大的工具。从基础到进阶,我们将一起探索装饰器的魅力所在。
|
21天前
|
机器学习/深度学习 搜索推荐 API
淘宝/天猫按图搜索(拍立淘)API的深度解析与应用实践
在数字化时代,电商行业迅速发展,个性化、便捷性和高效性成为消费者新需求。淘宝/天猫推出的拍立淘API,利用图像识别技术,提供精准的购物搜索体验。本文深入探讨其原理、优势、应用场景及实现方法,助力电商技术和用户体验提升。

推荐镜像

更多