brainstorming
brainstorming
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or planning anything new, in software or out of it (a talk, a business, a renovation).
re-wasmWASM 逆向:格式解析、wasm2wat、浏览器侧。触发词:WASM、wasm、WebAssembly、wat
Independent GitHub snapshot · Automated classification · Original documentation governs
WebAssembly.instantiate / WebAssembly.Module / .wasm fetch 出现的样本——wasm 与 JS 胶水一体分析wasm2wat 读 WAT 即可,无需完整流程参考 [[re-analyze/platform-tips]]——wasm 解析/反编译为静态步骤,免沙箱;动态运行(wasmtime/wasm3/浏览器加载)按最高原则进沙箱(至少断网)。
apt install wabt;Fedora: dnf install wabt;Arch: pacman -S wabtbrew install wabt;Windows: choco install wabt 或 GitHub WebAssembly/wabt release 的 bin 目录wasm2wat --version && wasm-decompile --version && wasm-objdump --version~/.wasmtime/bin): curl https://wasmtime.dev/install.sh -sSf | bashpacman -S wasmtime;macOS: brew install wasmtime;Windows: winget install BytecodeAlliance.Wasmtimewasmtime --versionbrew install wasm3wasm3/wasm3 release 下载对应平台单文件二进制,或源码构建: git clone --depth 1 https://github.com/wasm3/wasm3 && cmake -B build -S wasm3 && cmake --build buildwasm3 --versionapt install chromium(Chrome 用官方 deb);Fedora dnf install chromium;Arch pacman -S chromium;macOS brew install --cask google-chrome;Windows 官方安装器F12 打开 DevTools → Sources 面板能展开 .wasm 文件python3 -m http.server 8000apt install binaryen;Fedora: dnf install binaryen;Arch: pacman -S binaryenbrew install binaryen;Windows: choco install binaryen 或 GitHub WebAssembly/binaryen releasewasm-opt --version按顺序执行,每步记录证据(路径 + sha256,见 [[re-triage]])。
识别 wasm 模块:
file sample.wasm # "WebAssembly (wasm) binary module version 0x1 (MVP)"
xxd sample.wasm | head -1 # 魔数 00 61 73 6D(\0asm)+ 版本 01 00 00 00
\0asm(00 61 73 6D)+ 版本 01 00 00 00 = 标准 wasm;不符 → 不是 wasm(可能加密/混淆/损坏,见坑 3)atob(...) 的 base64 串、JS 里 Uint8Array([0,97,115,109,...]) 数组字面量WebAssembly.instantiate / WebAssembly.Module / .wasm fetch 出现即 wasm 载荷(JS 胶水走 [[re-script-deob]])section 解析(wasm-objdump / wasm2wat):
wasm-objdump -x sample.wasm # 全部 section:Type/Import/Function/Table/Memory/Global/Export/Code/Data
wasm-objdump -h sample.wasm # 只列 section 摘要
wasm2wat sample.wasm -o sample.wat # 二进制 → WAT 文本(有扩展指令时加 --enable-all)
wasm-objdump -d sample.wasm # 反汇编全部函数体(WAT 风格指令)
反编译(wasm-decompile):
wasm-decompile sample.wasm -o sample.c # 类 C 伪码(可读性优先)
wasm2wat 产出的 WAT 为准精读(export "checkPassword" ...) → JS 侧 instance.exports.checkPassword;import 的函数 → 到 JS 胶水找实现(坑 2)wasm-objdump -s sample.wasm dump 全部 section 原始内容(hex dump,含 Data 段;Data section 亦可从 -x 输出读);WAT 里找 (data (i32.const 偏移) "字符串"),把代码里 i32.const 偏移 映射回字符串(坑 1)浏览器侧(DevTools Sources / JS 调用面):
.wasm 文件:Chrome 自动给出反编译伪代码视图,可下断点、单步,Scope 面板看 wasm 局部变量,Call Stack 同时显示 JS↔wasm 帧WebAssembly.instantiate(bytes, importObject) 的 importObject 定义了 wasm 的 import 实现;instance.exports.xxx(...) 是 wasm 对外函数——在 JS 调用点下断点,单步进入 wasm 帧观察入参/返回值--headless --remote-debugging-port=9222),或 Node WebAssembly.instantiate 等价复现调用动态(wasmtime + 插桩/黑盒差分):
wasmtime run sample.wasm # WASI 程序(需 _start 导出)
wasmtime run --invoke checkPassword sample.wasm '"test"' # 直调导出函数(参数按 JSON 解析)
wasmtime run --dir . --env FLAG=xxx sample.wasm # 显式授权 WASI 文件/环境能力
wasm3 sample.wasm checkPassword test # 无 WASI 模块用 wasm3(参数原样)
wasm-objdump -d 静态指令 + --invoke 黑盒差分——同一导出函数喂不同输入,观察输出变化定位分支/校验逻辑strace -f wasmtime run sample.wasm(坑 5,走 [[re-tracing]])const { instance } = await WebAssembly.instantiate(bytes, imports);
console.log(instance.exports.f(1n, 2n)); // i64 必须 BigInt(坑 4)
strace -f wasmtime run 观察系统调用边界i32.const 偏移 数字,grep 不到任何明文;原因——wasm 没有字符串类型,字符串常量存 Data 段、代码用内存地址引用;对策——wasm-objdump -s sample.wasm dump 全部 section 原始内容(hex dump,Data 段在其中;也可从 -x 输出读 Data section)(WAT 里看 (data (i32.const 偏移) "…")),把偏移映射回引用处WebAssembly.instantiate(bytes, { env: {...} })),敏感逻辑在 JS 侧;对策——wasm-objdump -x 列出 Import section → 到 JS 胶水代码找对应实现([[re-script-deob]])——wasm 只证明"调用了什么",不证明"它做了什么"select 噪音,字符串被切碎/加密,函数名全抹;原因——混淆器做控制流平坦化 + 字符串加密 + 名称抹除;对策——binaryen 逐遍优化还原平坦化:wasm-opt --flatten --simplify-locals --vacuum --dce -O3 多轮迭代;字符串加密需定位解密逻辑(思路同 [[re-deobfuscate]],注意解密函数可能是 import——回到坑 2)TypeError: Cannot convert a BigInt value to a number,或 i64 参数静默截断;原因——i64 参数/返回值在 JS↔wasm 边界只能走 BigInt(Number 仅 2^53 精度);对策——JS 侧 instance.exports.f(1n, 2n) 传 BigInt;wasmtime --invoke 参数按 JSON 解析不支持 BigInt——需要时写 node 胶水;复刻算法用 Python int / JS BigInt,别用 Numberunknown import: wasi_snapshot_preview1.…,或浏览器与运行时行为不一致;原因——WASI 程序通过 import wasi_snapshot_preview1 拿文件/时钟/随机数/网络能力,运行时未授权该能力即失败;浏览器里宿主 import 是 JS 而非 WASI,同一模块两端行为可以不同;对策——wasm-objdump -x 看 Import 段确认用到的 WASI 函数 → wasmtime run --dir . --env K=v 显式授权 → strace -f wasmtime run 观察实际系统调用([[re-tracing]]);结论标注运行环境(browser vs wasi)