前言:Wasm 不是加密,只是二进制
WebAssembly 是一种基于堆栈虚拟机的二进制指令格式。它类似于汇编语言,但比 x86 汇编更抽象。浏览器加载 .wasm 文件后,会将其编译为机器码运行。
逆向 Wasm 的核心思路主要有两种:
- 静态分析:将
.wasm反汇编为.wat(WebAssembly Text) 或伪 C 代码,分析逻辑。 - 动态调试:利用浏览器开发者工具挂载断点,或直接修改
WebAssembly.Memory(线性内存)。
Wasm 加载与逆向流程
整个流程通常从下载游戏资源开始。首先获取 game.wasm 文件,通过工具解码并处理 Imports(函数/内存)。在服务器端,Wasm 二进制被传输到浏览器;在客户端,JS 胶水代码实例化模块对象,暴露出线性内存(ArrayBuffer)。此时,我们可以通过工具如 wasm2wat 将其转换为可读的汇编代码,或者直接通过 Console 操作内存数值。
一、兵器库:逆向工具准备
在开始之前,你需要准备好以下工具:
- Chrome 浏览器:最强大的 Wasm 调试器,内置了完善的 DevTools。
- 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 对象中。


