做追星网站效果图,河南郑州网站建设,金华企业制作网站,四川省商投建设公司官网一、WASM 是什么#xff1f;
WebAssembly (WASM) 是一种运行在浏览器中的“类二进制代码”#xff0c;它可以使用如 C/C/Rust 编写#xff0c;编译为 .wasm 文件#xff0c;被 JS 调用执行。其主要优势#xff1a; 运行速度快#xff08;接近原生#xff09; 加密逻辑…一、WASM 是什么
WebAssembly (WASM) 是一种运行在浏览器中的“类二进制代码”它可以使用如 C/C/Rust 编写编译为 .wasm 文件被 JS 调用执行。其主要优势 运行速度快接近原生 加密逻辑隐蔽不容易直接查看源码 可与 JavaScript 双向交互 二、WASM JS 混合逆向整体思路图
[网页源码] │└── [JS逻辑调度层]│├── import .wasm 文件├── 调用 wasm 导出函数└── 处理参数/结果加密/解密│↓[.wasm 文件]真正加密/校验逻辑我们分析的目标搞懂 JS 调用了哪些 wasm 函数、传了什么参数、返回了什么值是否涉及加密、签名或校验逻辑。 三、常见混合场景举例
场景描述滑动验证码验证wasm 处理行为轨迹 hash 签名参数加密处理JS wasm 混合加密最终请求参数游戏逻辑校验wasm 实现核心计算如坐标验证防爬参数计算加密算法藏在 wasmJS 仅为中转 四、实战分析流程
从初始页面到还原算法我们以一个真实例子为线索展开如极验、某电商参数加密
步骤 1识别 WASM 文件
方法 打开 Chrome DevTools → Network 面板 → 过滤 .wasm 或 Sources → WASM 区看到模块名如 main.wasm 搜索 JS 关键字
WebAssembly.instantiateStreaming()
WebAssembly.instantiate()
WebAssembly.compile()有时候 wasm 会 base64 编码后再 decode 导入也要留心。
步骤 2找 JS 调用 wasm 的代码
这步是关键中的关键 搜索 .exports.如
instance.exports.encrypt(a, b);或是通过中转函数
let wasmFunc Module.cwrap(encrypt, string, [string]);
let result wasmFunc(abc123);这时我们要Hook这些调用点打印 wasm 函数名、参数与返回值。
步骤 3在浏览器中 Hook wasm 调用调试级别
方法 1常规断点
// 设置断点在 JS 中的中转调用点
instance.exports.encrypt()方法 2高级用 Chrome 的 DevTools → WebAssembly 面板 查看所有导出函数 添加 breakpoint 调试 甚至可以单步进入 wasm 指令层类似汇编
方法 3控制台打印
let oldFunc instance.exports.encrypt; // 保存原始的 WebAssembly 导出函数 encrypt防止被覆盖后无法调用原始逻辑
instance.exports.encrypt function(a, b) { // 用自定义函数覆盖 encrypt实现 hook 操作console.log([WASM Call] a , a, b , b); // 打印输入参数用于观察调用时传入的值let ret oldFunc(a, b); // 调用原始 encrypt 函数获取加密结果console.log(result , ret); // 打印加密结果用于调试返回值return ret; // 返回原始函数的结果保持原有功能不变
}作用拦截 WASM 的 encrypt 函数调用在调用前后打印参数与结果方便调试或逆向分析。
步骤 4反编译 .wasm 文件
对于核心算法的还原需要反编译 .wasm 二进制文件。
方式一使用 wasm2wat 转为人类可读的 WAT 格式
安装 wabt 工具
wasm2wat main.wasm -o main.wat转为 .wat 后可以看到类似汇编风格的中间代码
(func $encrypt (param $p0 i32) (result i32)...i32.const 32call $malloc...return
)可以看到函数名 $encrypt、变量、常量、调用关系
方式二用 Ghidra 分析 .wasm图形化反汇编 安装 Ghidra 导入 .wasm 文件 自动识别函数结构 可重命名函数并跟踪调用链 还能 patch 重编译
步骤 5动态还原算法流程 通过 JS 确认入口函数和参数含义 在浏览器中下断点观察加密前的原始参数 通过反编译观察关键计算逻辑 将 WASM 算法还原为 JS/py 代码脱离浏览器使用 五、最终目标还原加密算法 / 重写 wasm 逻辑
例如一个混合加密的场景简化
let wasm await WebAssembly.instantiate(...); // 异步实例化一个 WebAssembly 模块返回 { module, instance } 对象
let base abc123; // 定义一个输入字符串可能是要加密或参与加密的原始数据
let sig wasm.instance.exports.encrypt(base.length, getPointer(base));
// 调用 WASM 中导出的 encrypt 函数传入两个参数
// - base.length 是字符串的长度即 6通常传给加密函数让其知道要处理多少字节
// - getPointer(base) 是一个辅助函数用于将 JS 字符串写入 WASM 内存并返回它在 WASM 内存中的偏移地址指针
// 返回值 sig 是 encrypt 的执行结果通常是加密后的值可能是数字、指针、或者通过内存读取后的数据我们最终目标就是 在 Python 或 Node.js 中模拟 encrypt() 的逻辑 不再依赖 wasm 文件或 JS 页面
getPointer(base) 通常是这样定义的用于将 JS 的字符串数据写入 WebAssembly 的内存
function getPointer(str) {const encoder new TextEncoder(); // 创建一个 UTF-8 编码器const bytes encoder.encode(str); // 将字符串编码成 Uint8Array二进制字节const ptr wasm.instance.exports.malloc(bytes.length); // 调用 WASM 导出的 malloc 函数申请内存空间const mem new Uint8Array(wasm.instance.exports.memory.buffer, ptr, bytes.length); // 从 WASM 的 memory 中获取内存视图范围是 [ptr, ptrlength)mem.set(bytes); // 将字符串字节写入 WASM 内存return ptr; // 返回在 WASM 内存中的起始地址用于作为 encrypt 参数
}小技巧与实战建议 常见 WASM 导出函数名_encrypt, _decode, _crc, _check_sig, verify, hashX 函数名有时会被混淆但参数顺序/数量往往可推断含义 JS 与 WASM 通信通常通过 Linear Memory需分析 getUint8Array / getStringFromPointer 类函数 可以用 Frida 等工具实现 Hook 并动态替换返回值绕过 wasm 加密