跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
JavaScript大前端算法

WebAssembly 逆向分析:反编译与内存篡改实战

介绍 WebAssembly(Wasm)的逆向分析方法。Wasm 是二进制指令格式,非加密手段。核心思路包括静态分析(反编译为 WAT 或伪代码)和动态调试(修改线性内存)。工具涵盖 Chrome 浏览器、WABT 套件及 Ghidra。实战步骤涉及捕获 wasm 文件、转化为可读代码、定位内存地址并篡改数值,或通过修改 WAT 代码重编译进行补丁。防御方面建议去除符号、控制流平坦化及服务器端校验关键数据。掌握这些技术有助于理解网页高性能黑盒背后的逻辑。

清心发布于 2026/4/5更新于 2026/5/2432 浏览
WebAssembly 逆向分析:反编译与内存篡改实战

WebAssembly 逆向分析:反编译与内存篡改实战

前言:Wasm 不是加密,只是二进制

WebAssembly 是一种基于堆栈虚拟机的二进制指令格式。它类似于汇编语言,但比 x86 汇编更抽象。 浏览器加载 .wasm 文件,编译为机器码运行。

逆向 Wasm 的两种核心思路

  1. 静态分析:将 .wasm 反汇编为 .wat (WebAssembly Text) 或伪 C 代码,分析逻辑。
  2. 动态调试:利用浏览器开发者工具挂载断点,或直接修改 WebAssembly.Memory(线性内存)。

Wasm 加载与逆向流程

  1. 下载 game.wasm
  2. 解码 Imports (函数/内存)
  3. 读写操作
  4. 工具:wasm2wat 生成可读汇编代码 (.wat)
  5. 工具:Console 直接修改数值

一、兵器库:逆向工具准备

在开始之前,你需要准备以下工具:

  1. Chrome 浏览器:最强大的 Wasm 调试器。
  2. WABT (The WebAssembly Binary Toolkit):
    • wasm2wat: 将二进制转为人类可读的文本格式(S-表达式)。
    • wat2wasm: 将修改后的文本重新编译为二进制。
  3. 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
// 假设游戏把实例挂载到了 window.gameInstance
const memBuffer = window.gameInstance.exports.memory.buffer;
const memView = new Int32Array(memBuffer);

2. 搜索数值 (CE 搜内存法)

就像使用 Cheat Engine 一样:

  1. 当前金币是 100。
  2. 在 Console 输入:memView.forEach((v, i) => { if(v===100) console.log(i) }) -> 得到索引 1024。
  3. 玩游戏,金币变成 101。
  4. 检查索引 1024 的值:memView[1024] -> 确实是 101。
  5. 找到地址了!

3. 修改数值

// 直接把金币改成 999999
memView[1024]=999999;

页面上的金币瞬间暴涨。


四、实战第三步:二进制补丁 (Binary Patching)

如果金币逻辑没有暴露在全局内存中,或者是纯栈操作,我们就需要修改代码本身(Patch)。

1. 修改 WAT 代码

回到刚才反编译的 game.wat 文件。 找到加法逻辑:

local.get $p0 i32.const 1;; <--- 这里是增加的数量 i32.add 

我们将 1 修改为 1000:

local.get $p0 i32.const 1000;; <--- 修改为 1000 i32.add 

2. 重编译为 Wasm

wat2wasm game.wat -o game_hacked.wasm 

3. 替换运行 (浏览器端 Hook)

我们不能直接替换服务器文件,但我们可以通过 Chrome 的 Local Overrides 功能,或者写一个 TamperMonkey 脚本来拦截网络请求。

TamperMonkey 脚本思路:

const originalFetch = window.fetch;
window.fetch=async function(url, options){
    if(url.includes('game.wasm')){
        // 拦截请求,返回我们修改过的二进制数据
        const response = await originalFetch('http://localhost:8000/game_hacked.wasm');
        return response;
    }
    return originalFetch(url, options);
};

刷新网页,点击按钮,金币直接 +1000!


五、防御:开发者如何保护 Wasm?

看到这里,你可能会觉得 Wasm 在裸奔。作为开发者,如何防御?

  1. Strip Symbols:发布时务必去除调试符号(函数名、变量名),让逆向者面对 $func1, $func2 抓狂。
  2. 控制流平坦化 (Control Flow Flattening):使用 LLVM 的混淆插件(如 Obfuscator-LLVM),把清晰的 if-else 变成复杂的 switch 跳转,破坏代码结构。
  3. 服务器校验:永远不要相信客户端。 像金币这种关键数据,Wasm 只能做展示,计算和存储必须在服务器端完成。

总结

Wasm 逆向正处于一个蓝海阶段。 它既不像 x86 汇编那样指令繁杂,也不像 JS 那样容易被混淆成乱码。 掌握了 wasm2wat 和线性内存的原理,你就能看穿网页中那些'高性能黑盒'背后的秘密。

下一步建议: 找一个简单的在线 CTF 题目(WebAssembly 类),尝试不看 Writeup,使用 Chrome DevTools 的断点功能,追踪一个加密函数的输入输出,逆向出它的 Flag。

目录

  1. WebAssembly 逆向分析:反编译与内存篡改实战
  2. 前言:Wasm 不是加密,只是二进制
  3. 逆向 Wasm 的两种核心思路
  4. Wasm 加载与逆向流程
  5. 一、兵器库:逆向工具准备
  6. 二、实战第一步:捕获与反编译
  7. 1. 获取 Wasm 文件
  8. 2. 转化为可读代码 (WAT)
  9. 三、实战第二步:内存篡改 (Memory Hacking)
  10. 1. 定位内存对象
  11. 2. 搜索数值 (CE 搜内存法)
  12. 3. 修改数值
  13. 四、实战第三步:二进制补丁 (Binary Patching)
  14. 1. 修改 WAT 代码
  15. 2. 重编译为 Wasm
  16. 3. 替换运行 (浏览器端 Hook)
  17. 五、防御:开发者如何保护 Wasm?
  18. 总结
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • Python 核心知识点汇总:装饰器、数据结构与版本差异
  • CISP-PTE 认证含金量及报考指南
  • 网络安全应急响应流程与方法论
  • 腿式机器人 IMU 融合与状态估计实战解析
  • Java 核心面试知识点汇总:基础、并发、JVM、数据库与中间件
  • Java Web 开发基础:Spring Web MVC 核心解析
  • 本地部署多模态大模型:Open-WebUI 与 Dify 智能体实战
  • 2024 中国 AI 大模型场景探索与应用趋势深度解析
  • C++ 核心概念与面试知识点梳理
  • LangChain 核心概念:Chain 与 LCEL 实战解析
  • Transformer 架构原理与自注意力机制详解
  • 无人机 Remote ID Beacon 帧字段详解
  • Vue3 与 Python 教育机构题包任务分配系统设计
  • Docker 架构与核心原理深度解析:容器实现机制详解
  • Python 编程中常用的十大核心依赖库
  • 使用 MybatisPlus 将百度天气数据持久化至 PostgreSQL
  • 国内建筑与室内设计 AI 工具实测:十款主流平台深度解析
  • Browser-use:Python 智能浏览器自动化 AI 工具实战
  • VsCode 远程调用 Claude Agent 报错无效请求?参数配置排查指南
  • 大模型与机器学习学习路线及核心书籍推荐

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online