WebAssembly Reverse

WASM

WASM 开发环境

Emscripten SDK 主流的 WASM 开发环境, 本文基于 Emscripten 环境编写

安装 Emscripten

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Get the emsdk repo
git clone https://github.com/emscripten-core/emsdk.git

# Enter that directory
cd emsdk

# Fetch the latest version of the emsdk (not needed the first time you clone)
git pull

# Download and install the latest SDK tools.
./emsdk install latest

# Make the "latest" SDK "active" for the current user. (writes .emscripten file)
./emsdk activate latest

# Activate PATH and other environment variables in the current terminal
source ./emsdk_env.sh

编译 Hello world

1.c

1
2
3
4
5
6
7
8
#include <stdio.h>
int main() {
int d;
printf("hello world.\n");
scanf("%d", &d);
printf("your input: %d\n", d);
return 0;
}

编译并生成运行 html 页面

1
emcc 1.c -o 1.html

编译后当前目录下会生成三个文件: 1.html 1.js 1.wasm

目前主流的浏览器不支持 file:// XHR 请求,因此要把这些文件放到 http server 上。

js 与 wasm 的交互

通过js 层的 ccallcwarp 调用 wasm 中的 C 函数

1
2
3
4
5
6
#include <math.h>
extern "C" { // to disable name-mangle
int int_sqrt(int x) {
return sqrt(x);
}
}

编译命令

1
emcc 1.cpp -o 1.html -s EXPORTED_FUNCTIONS='["_int_sqrt", "_main"]' -s EXPORTED_RUNTIME_METHODS='["ccall","cwrap"]'

调用接口

1
2
3
int_sqrt = Module.cwrap('int_sqrt', 'number', ['number'])
int_sqrt(12)
int_sqrt(28)
1
2
3
4
var result = Module.ccall('int_sqrt', // name of C function
'number', // return type
['number'], // argument types
[28]); // arguments

一些基本的文件

.wasm 二进制形式的代码

.wat 文本形式(text format)的代码文件

wasm2wat 可以将 .wasm 文件转换成 .wat 文件。

WASM 静态分析

WABT 是 WebAssembly 的二进制工具包

git 仓库地址:

1
git@github.com:WebAssembly/wabt.git

编译方法

1
2
3
4
5
6
7
git clone git@github.com:WebAssembly/wabt.git
cd wabt
git submodule update --init
mkdir build
cd build
cmake ..
make -j8

基本用法

1
2
wasm2wat 1.wasm -o test.wat # Parse from binary to text format
wasm2c 1.wasm -o test.c # decompile to c

wasm2c 反编译出来的 C 效果不是很好,可以用 gcc 编译 test.c,然后用 IDA 分析输出文件。

⚠️⚠️⚠️ wasm2c 的输出文件名一定不能是数字开头,否则 GCC 编译会出问题。

gcc 编译方法

  1. 复制 wabt/wasm2c 下的头文件到 test.c 目录
  2. 用 gcc 编译
1
gcc -c test.c -o test.out

效果

1
2
3
4
5
int strmlen(char * s) {
size_t cnt = 0;
while ( *(s++) ) cnt += 1;
return cnt;
}

用 IDA 逆向分析效果如下

还是比较清晰的。

调试方法

一般没有源码只能用 ChromeDevTool 调试。

DevTool 里面可以直接对 wasm 下断点。

查看内存

Chrome 版本 Chrome 91 以上支持 Memory Inspect

点击 【Scope】 中 memory 旁边的内存图标可以打开 memory panel,输入地址即可查看。

参考链接

[1] Download and install Emscripten “https://emscripten.org/docs/getting_started/downloads.html#sdk-download-and-install"
[2] Emscripten Tutorial “https://emscripten.org/docs/getting_started/Tutorial.html"
[3] Interacting with code “https://emscripten.org/docs/porting/connecting_cpp_and_javascript/Interacting-with-code.html"
[4] 一种Wasm逆向静态分析方法 “https://xz.aliyun.com/t/5170"


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!