骑麦兜看落日

[Asm]WASM初步

字数统计: 1.1k阅读时长: 4 min
2019/01/13 Share

前言

WebAssembly/wasm WebAssembly 或者 wasm 是一个可移植、体积小、加载快并且兼容 Web 的全新格式

WebAssembly是一种运行在现代网络浏览器中的新型代码,并且提供新的性能特性和效果。它设计的目的不是为了手写代码而是为诸如C、C++和Rust等低级源语言提供一个高效的编译目标。

对于网络平台而言,这具有巨大的意义——这为客户端app提供了一种在网络平台以接近本地速度的方式运行多种语言编写的代码的方式;在这之前,客户端app是不可能做到的。

而且,你在不知道如何编写WebAssembly代码的情况下就可以使用它。WebAssembly的模块可以被导入的到一个网络app(或Node.js)中,并且暴露出供JavaScript使用的WebAssembly函数。JavaScript框架不但可以使用WebAssembly获得巨大性能优势和新特性,而且还能使得各种功能保持对网络开发者的易用性。

环境搭建

编译wasm文件需要emsc

1
2
3
4
5
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

编译wasm

通过如下命令将c文件编译为wasm文件

1
emcc test.c -s WASM=1 -o test.html -g4 -O2

其中

-s WASM=1指定输出为wasm形式,Emscripten默认为asm.js的形式

-o test.html可以指定生成html文件、以及wasm文件

-g4指定debug信息等级,详情看—-help

-O2指定优化等级,详情看—-help

wasm文本格式

为了能够让人类阅读和编辑WebAssembly,wasm二进制格式提供了相应的文本表示。这是一种用来在文本编辑器、浏览器开发者工具等工具中显示的中间形式。

文本格式被表示为S-表达式,S-表达式类似于Lisp语言

wabt工具包

wabt是wasm的一组工具包,可以通过其中的wat2wasmwasm2watwasm2c等工具进行wasm、wat和c之间的转换

安装

1
2
3
4
5
6
git clone --recursive https://github.com/WebAssembly/wabt
cd wabt
mkdir build
cd build
cmake ..
cmake --build .

运行

1
2
3
out/wat2wasm test.wat -o test.wasm
out/wasm2wat test.wasm -o test.wat
wasm2c test.wasm -o test.c

虽然导出的wat文件和c文件还是很难看(头铁还是能看的),但是可以比较方便的找到wasm的各个段以及符号

文件格式

语义

js与c的交互

逆向分析

因为我们可以通过wasm2c得到对应c文件,所以可以编译成二进制文件交给ida去分析,这里参考一篇博文https://xz.aliyun.com/t/5170#toc-5

先生成c文件

1
wasm2c test.wasm -o test.c

然后编译成二进制文件,需要将.c文件、.h文件以及wabt项目内的wasm-rt.hwasm-rt-impl.cwasm-rt-impl.h文件放在同一目录内

1
gcc -c test.c -o test.o

动态调试

目前firefox和Chrome浏览器都支持wasm动态调试,firefox的动态调试功能更强,比如可以进行源码调试,不过我个人比较喜欢用Chrome,因为Chrome将每个wasm函数单独列了出来,方便调试,并且可以看到栈,这个我在firefox中没有找到

动态调试wasm文件通常需要开启一个http服务

1
python -m SimpleHTTPServer

然后浏览器载入url

1
http://0.0.0.0:8000/test.html

这个时候在开发者工具中查看Sources,可以看到相应的胶水代码和wasm文本格式代码

在Chrome中,将每个函数都单独列了出来,wasm文件最后的数字代表函数名,不过即使是我们自己写的函数可能也判断不出来谁是谁,这个时候可以用上边提到的wasm2c或wasm2wat工具,在反编译的c文件中,可以直接通过函数签名来找对应位置的函数,其实有一个比较简单的方法是我们自己定义的函数通常是从24开始的,不过这对于逆向来说可能没有卵用.

接下来具体的调试其实和js调试一样,在Scope中可以看到相应的线性内存区,locals,stack等的值

同时,由于胶水代码将wasm的所有操作封装在了全局对象Module中,我们还可以直接在控制台调用wasm导出的函数,只需要调用Module._test()或直接调用_test(),然后在相应函数下断点就可以愉快的调试了


相关资料

CATALOG
  1. 1. 前言
  2. 2. 环境搭建
  3. 3. 编译wasm
  4. 4. wasm文本格式
  5. 5. wabt工具包
  6. 6. 文件格式
  7. 7. 语义
  8. 8. js与c的交互
  9. 9. 逆向分析
  10. 10. 动态调试
  11. 11. 相关资料