WASM逆向分析
wasm是基于堆栈的虚拟机的二进制指令格式。在这次比赛中遇到,记录一下。
IDA反编译插件
下载地址:https://github.com/fireeye/idawasm
食用方法:
- install the python module:
python.exe setup.py install
- manually install the WebAssembly file loader:
mv loaders\wasm_loader.py %IDADIR%\loaders\wasm_loader.py
- manually install the WebAssembly processor:
mv procs\wasm_proc.py %IDADIR%\procs\wasm_proc.py
WASM编译环境搭建
git clone https://github.com/juj/emsdk.git cd emsdk ./emsdk install --build=Release sdk-incoming-64bit binaryen-master-64bit ./emsdk activate --global --build=Release sdk-incoming-64bit binaryen-master-64bit source ./emsdk_env.sh
编译C为WASM
emcc biu.c -s WASM=1 -o biu.html -g4 -O2
-s WASM=1指定输出为wasm形式,Emscripten默认为asm.js的形式
-o biu.html可以指定生成html文件、以及wasm文件
-g4指定debug信息等级,详情看—-help
-O2指定优化等级,详情看—-help
WABT工具包
WABT(我们将其称为“ wabbit”)是用于WebAssembly的一套工具,包括:
- wat2wasm:从 WebAssembly文本格式转换为 WebAssembly二进制格式
- wasm2wat: wat2wasm的逆函数,从二进制格式转换回文本格式(也称为.wat)
- wasm-objdump:显示有关wasm二进制文件的信息。与objdump类似。
- wasm-interp:使用基于堆栈的解释器解码并运行WebAssembly二进制文件
- wasm-decompile:将wasm二进制文件反编译为可读的类似C的语法。
- wat- desugar:解析规范解释程序支持的.wat文本格式(S表达式,平面语法或混合格式)并打印“规范”平面格式
- wasm2c:将WebAssembly二进制文件转换为C源代码和标头
- wasm-strip:删除WebAssembly二进制文件的部分
- wasm-validate:验证WebAssembly二进制格式的文件
- wast2json:将wasm spec测试格式的文件转换为JSON文件和关联的wasm二进制文件
- wasm-opcodecnt:计算指令的操作码使用量
- spectest-interp:读取Spectest JSON文件,然后在解释器中运行其测试
将wasm转换为C语言,主要用到wasm2c
食用方法
git clone --recursive https://github.com/WebAssembly/wabt cd wabt mkdir build cd build cmake .. cmake --build .
wasm2c使用
测试文件:https://lanzous.com/id1pybe
/home/ubuntu/wabt/build/wasm2c chall.wasm -o out.c
将chall.wasm转换为out.c
此时的C代码并不直观。
优化
将之前反编译出来的wasm.c,wasm.h,以及wabt项目内的wasm-rt.h,wasm-rt-impl.c,wasm-rt-impl.h三个文件放到同一个文件夹。
gcc -c out.c -o out.o
这样得到的源文件在IDA中分析就会轻松一些
i32_load形式的函数为取值函数,第一个参数为取值对象,第二个参数为偏移
i32_store形式的函数为操作存储函数,第一个参数为存储对象,第二个参数为存储位置,第三个参数为操作方式
动态调用
Python开启服务器
全局安装
npm i http-server -g
快速使用
http-server
默认端口8080,指定端口
http-server <path> -a 127.0.0.1 -p 8090
如果路径中有index.html,默认为主页
HTML调用
参考:https://developer.mozilla.org/zh-CN/docs/WebAssembly/Using_the_JavaScript_API
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Simple template</title> <script> fetch(‘chall.wasm‘) .then(res => res.arrayBuffer() ).then(bytes => WebAssembly.instantiate(bytes, importObject) ).then(results => { results.instance.exports.exported_func(); }); </script> </head> <body> </body> </html>
chall.wasm放在与index.html同目录