WebAssembly 本质是二进制指令集
WebAssembly 是一种基于堆栈虚拟机的二进制指令格式。它类似于汇编语言,但比 x86 汇编更抽象。浏览器加载 .wasm 文件后,会将其编译为机器码运行。
逆向 Wasm 的两种核心思路:
- 静态分析:将
.wasm反汇编为.wat(WebAssembly Text) 或伪 C 代码,分析逻辑。 - 动态调试:利用浏览器开发者工具挂载断点,或直接修改
WebAssembly.Memory(线性内存)。
Wasm 加载与逆向流程:
flowchart TD
A[服务器] -->|game.wasm| B(浏览器)
B --> C[Wasm 模块实例化]
C --> D{JS 胶水代码}
D --> E[Imports 函数/内存]
E --> F[线性内存 ArrayBuffer]
F --> G[读写操作]
H[wasm2wat] --> I[可读汇编 .wat]
J[Console] --> K[直接修改数值]
一、兵器库:逆向工具准备
在开始之前,你需要准备以下工具:
- 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 掉了,只显示 func $f12,你需要根据上下文推断其作用。
三、实战第二步:内存篡改 (Memory Hacking)
Wasm 的内存模型非常简单:它就是一个巨大的、线性的 JavaScript ArrayBuffer。这意味着,JS 可以随意读写 Wasm 的内存!这是最简单的破解方式。
1. 定位内存对象
在 Chrome Console 中,寻找 Wasm 的实例对象。通常在全局变量或者 imports 对象中。


