WebAssembly 逆向分析:反编译与内存篡改实战
前言:Wasm 不是加密,只是二进制
WebAssembly 是一种基于堆栈虚拟机的二进制指令格式。它类似于汇编语言,但比 x86 汇编更抽象。
浏览器加载 .wasm 文件,编译为机器码运行。
逆向 Wasm 的两种核心思路
- 静态分析:将
.wasm反汇编为.wat(WebAssembly Text) 或伪 C 代码,分析逻辑。 - 动态调试:利用浏览器开发者工具挂载断点,或直接修改
WebAssembly.Memory(线性内存)。
Wasm 加载与逆向流程
- 下载
game.wasm - 解码 Imports (函数/内存)
- 读写操作
- 工具:
wasm2wat生成可读汇编代码 (.wat) - 工具:Console 直接修改数值
一、兵器库:逆向工具准备
在开始之前,你需要准备以下工具:
- 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 的实例对象。通常在全局变量或者 对象中。


