前言
WebAssembly 是一种基于堆栈虚拟机的二进制指令格式,类似于汇编语言但更抽象。浏览器加载 .wasm 文件后将其编译为机器码运行。
逆向 Wasm 的核心思路主要有两种:
- 静态分析:将
.wasm反汇编为.wat(WebAssembly Text) 或伪 C 代码,分析逻辑。 - 动态调试:利用浏览器开发者工具挂载断点,或直接修改
WebAssembly.Memory(线性内存)。
流程图示意
[下载 game.wasm] -> [解码 Imports/内存] -> [JS 胶水代码实例化]
| |
v v
[服务器] [浏览器 Console]
| |
+------------> [Wasm 模块] <-------------------+
|
[读写线性内存 / 反汇编 .wat]
一、工具准备
在开始之前,你需要准备以下工具:
- Chrome 浏览器:最强大的 Wasm 调试器。
- WABT (The WebAssembly Binary Toolkit):
wasm2wat: 将二进制转为人类可读的文本格式(S-表达式)。wat2wasm: 将修改后的文本重新编译为二进制。
- Ghidra (可选):安装 Wasm 插件后,可以生成伪 C 代码辅助分析。
二、捕获与反编译
假设我们正在玩一个网页小游戏,每次点击按钮,金币 +1。我们要把它改成 +1000。
1. 获取 Wasm 文件
打开 Chrome DevTools -> Network 面板,刷新页面,过滤 .wasm。找到 game.wasm 并下载。
2. 转化为可读代码 (WAT)
使用 wasm2wat 工具:
wasm2wat game.wasm -o game.wat
打开 game.wat,你会看到类似这样的代码:
(module
(import "env" "memory" (memory $0 1))
(func $add_gold (param $p0 i32) (result i32)
(local $l0 i32)
local.get $p0 ;; 获取参数(当前金币)
i32.const 1 ;; 加载常量 1
i32.add ;; 执行加法
local.set $l0 ;; 存入局部变量
local.get $l0 ;; 返回结果
)
(export "add_gold" (func $add_gold))
)
注:真实环境中的函数名通常被 stripped 掉了,只显示 ,你需要根据上下文推断。


