-
-
[原创]webassembly-1.使用ollvm和wasi-sdk混淆
-
发表于:
2024-2-25 07:07
3926
-
[原创]webassembly-1.使用ollvm和wasi-sdk混淆
标签: webassembly混淆
webassmebly作为新型平台越来越受到重视,其中WASM的混淆也尤为重要。本文介绍一种简单的混淆方法在ubuntu22.04下使用,并且使用wasi-sdk的类C库,混淆的WASM程序可以使用C库函数实现类似功能。
1. 下载ollvm并编译安装
原始的ollvm版本已经年久失修,跟不上新版本的开发,如果使用会遇到很多bug,这里我采用一个修改版的ollvm,
github地址:[Pluto-Obfuscator][1]
下载:
git clone https://github.com/xubenji/Pluto-Obfuscator
下载好以后需要编译安装,
进入项目目录,直接执行
bash build.sh
就可以编译安装ollvm了(确保机器中有编译工具,cmake,ninja-build,g++等),这里build.sh我已经修改好了,编译安装以后的ollvm支持编译C代码到WASM。
在/Pluto-Obfuscator/build/bin文件夹下就是编译好的工具。
进入此目录,使用编译好的clang将C文件编译为wasm,以下是编译命令:
1 2 3 | / root / Pluto - Obfuscator / build / bin / clang \
- - target = wasm32 - nostdlib - Wl, - - no - entry\
- Wl, - - export - all - g - O0 loop.c - o loop.wasm
|
这个时候会出现以下错误:
1 2 | clang - 12 : error: unable to execute command: Executable "wasm-ld" doesn't exist!
clang - 12 : error: linker command failed with exit code 1 (use - v to see invocation)
|
2. 拆解编译流程,使用wasi-sdk中的链接器
我们使用wasi-sdk中的clang编译此文件并且看看链接部分的命令是什么。
下载wasi-sdk:
1 2 | wget https: / / github.com / WebAssembly / wasi - sdk / releases / download / wasi - sdk - 21 / wasi - sdk - 21.0 - linux.tar.gz
tar - xzvf wasi - sdk - 21.0 - linux.tar.gz
|
loop.c内容如下:
1 2 3 4 5 6 7 8 9 10 | int main(){
int n1 = 10 ;
int n2 = 20 ;
if (n1 > 0 ){
for ( int i = 0 ; i < n2; i + + ){
n1 + = n2;
}
}
return n1;
}
|
(其实函数名是不是main没有关系)
使用wasi-sdk中的clang和相同的命令编译loop.c,但是加上-v选项。
1 2 3 | / root / wasi - sdk - 21.0 / bin / clang - v \
- - target = wasm32 - nostdlib - Wl, - - no - entry\
- Wl, - - export - all - g - O0 loop.c - o loop.wasm
|
运行后得到如下输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 | root@localhost:~
clang version 17.0 . 6
Target: wasm32
Thread model: posix
InstalledDir: / root / wasi - sdk - 21.0 / bin
"/root/wasi-sdk-21.0/bin/clang-17" - cc1 - triple wasm32 - emit - obj - mrelax - all - dumpdir loop.wasm - - disable - free - clear - ast - before - backend - disable - llvm - verifier - discard - value - names - main - file - name loop.c - mrelocation - model static - mframe - pointer = none - ffp - contract = on - fno - rounding - math - mconstructor - aliases - target - cpu generic - fvisibility = hidden - debug - info - kind = constructor - dwarf - version = 4 - debugger - tuning = gdb - v - fcoverage - compilation - dir = / root - resource - dir / root / wasi - sdk - 21.0 / lib / clang / 17 - isysroot / root / wasi - sdk - 21.0 / bin / .. / share / wasi - sysroot - internal - isystem / root / wasi - sdk - 21.0 / lib / clang / 17 / include - internal - isystem / root / wasi - sdk - 21.0 / bin / .. / share / wasi - sysroot / include - O0 - fdebug - compilation - dir = / root - ferror - limit 19 - fgnuc - version = 4.2 . 1 - fcolor - diagnostics - o / tmp / loop - 34b990 .o - x c loop.c
clang - cc1 version 17.0 . 6 based upon LLVM 17.0 . 6 default target wasm32 - wasi
/ root / wasi - sdk - 21.0 / lib / clang / 17 / include
/ root / wasi - sdk - 21.0 / bin / .. / share / wasi - sysroot / include
End of search list .
"/root/wasi-sdk-21.0/bin/wasm-ld" - m wasm32 - L / root / wasi - sdk - 21.0 / bin / .. / share / wasi - sysroot / lib - - no - entry - - export - all / tmp / loop - 34b990 .o - o loop.wasm
|
注意到这条命令就是链接命令:
1 | "/root/wasi-sdk-21.0/bin/wasm-ld" - m wasm32 - L / root / wasi - sdk - 21.0 / bin / .. / share / wasi - sysroot / lib - - no - entry - - export - all / tmp / loop - 34b990 .o - o loop.wasm
|
因为编译安装的clang中没有设置wasm-ld的地址,所以clang找不到链接器,一种办法是设置环境变量,一种办法是直接使用wasi-sdk中的链接器,有一些版本的clang可能会提示找不到wasm-ld-14,wasm-ld-13等等,考虑到这种情况设置环境变量可能不太好,直接独立使用sdk中的wasm-ld会更好。
所以我们修改一下链接命令得到如下:
1 | "/root/wasi-sdk-21.0/bin/wasm-ld" - m wasm32 - L / root / wasi - sdk - 21.0 / bin / .. / share / wasi - sysroot / lib - - no - entry - - export - all / root / loop.o - o / root / loop.wasm
|
编译命令也要先编译为.o文件才行:
这是修改后的编译命令:
1 2 3 | / root / Pluto - Obfuscator / build / bin / clang \
- - target = wasm32 - nostdlib - Wl, - - no - entry\
- Wl, - - export - all - g - O0 loop.c - c - o loop.o
|
整合到一起就能编译loop.c到loop.wasm了。
使用runtime运行loop.wasm, 得不到任何结果,因为我们没有一些输出信息, 但是加入标准库以后clang会提示找不到c库。
1 2 | root@localhost:~ / wasmtime - v17. 0.1 - x86_64 - linux
root@localhost:~ / wasmtime - v17. 0.1 - x86_64 - linux
|
3. 使用wasi-sdk中模拟的标准C库输出信息,并开启混淆
在loop.c中加入打印代码:
1 2 3 4 5 6 7 8 9 10 11 12 | int main(){
printf( "hello world\n" );
int n1 = 10 ;
int n2 = 20 ;
if (n1 > 0 ){
for ( int i = 0 ; i < n2; i + + ){
n1 + = n2;
}
}
return 0 ;
}
|
编译这个C文件需要指定C库的地址,使用wasi-sdk中的clang编译文件命令如下:
1 | root@localhost:~ / wasi - sdk - 21.0 / bin
|
同上我们使用-v选项查看整个链接过程,得到如下信息:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | root@localhost:~ / wasi - sdk - 21.0 / bin
clang version 17.0 . 6
Target: wasm32 - unknown - wasi
Thread model: posix
InstalledDir: / root / wasi - sdk - 21.0 / bin / .
"/root/wasi-sdk-21.0/bin/clang-17" - cc1 - triple wasm32 - unknown - wasi - emit - obj - mrelax - all - dumpdir / root / loop.wasm - - disable - free - clear - ast - before - backend - disable - llvm - verifier - discard - value - names - main - file - name loop.c - mrelocation - model static - mframe - pointer = none - ffp - contract = on - fno - rounding - math - mconstructor - aliases - target - cpu generic - fvisibility = hidden - debugger - tuning = gdb - v - fcoverage - compilation - dir = / root / wasi - sdk - 21.0 / bin - resource - dir / root / wasi - sdk - 21.0 / lib / clang / 17 - isysroot / root / wasi - sdk - 21.0 / share / wasi - sysroot / - internal - isystem / root / wasi - sdk - 21.0 / lib / clang / 17 / include - internal - isystem / root / wasi - sdk - 21.0 / share / wasi - sysroot / / include / wasm32 - wasi - internal - isystem / root / wasi - sdk - 21.0 / share / wasi - sysroot / / include - fdebug - compilation - dir = / root / wasi - sdk - 21.0 / bin - ferror - limit 19 - fgnuc - version = 4.2 . 1 - fcolor - diagnostics - o / tmp / loop - c1b686.o - x c / root / loop.c
clang - cc1 version 17.0 . 6 based upon LLVM 17.0 . 6 default target wasm32 - wasi
ignoring nonexistent directory "/root/wasi-sdk-21.0/share/wasi-sysroot//include/wasm32-wasi"
/ root / wasi - sdk - 21.0 / lib / clang / 17 / include
/ root / wasi - sdk - 21.0 / share / wasi - sysroot / / include
End of search list .
"/root/wasi-sdk-21.0/bin/./wasm-ld" - m wasm32 - L / root / wasi - sdk - 21.0 / share / wasi - sysroot / / lib / wasm32 - wasi / root / wasi - sdk - 21.0 / share / wasi - sysroot / / lib / wasm32 - wasi / crt1 - command.o / tmp / loop - c1b686.o - lc / root / wasi - sdk - 21.0 / lib / clang / 17 / lib / wasi / libclang_rt.builtins - wasm32.a - o / root / loop.wasm
|
使用ollvm中的clang先将文件编译为。o文件,然后链接为wasm文件。
1 2 3 | / root / Pluto - Obfuscator / build / bin / clang - O0 - - target = wasm32 - wasi - - sysroot = / root / wasi - sdk - 21.0 / share / wasi - sysroot / loop.c - c - o loop.o
"/root/wasi-sdk-21.0/bin/./wasm-ld" - m wasm32 - L / root / wasi - sdk - 21.0 / share / wasi - sysroot / / lib / wasm32 - wasi / root / wasi - sdk - 21.0 / share / wasi - sysroot / / lib / wasm32 - wasi / crt1 - command.o / root / loop.o - lc / root / wasi - sdk - 21.0 / lib / clang / 17 / lib / wasi / libclang_rt.builtins - wasm32.a - o / root / loop.wasm
|
使用wasmtime运行如下:
1 2 | root@localhost:~ / wasmtime - v17. 0.1 - x86_64 - linux
hello world
|
这样我们就可以开启ollvm flattning混淆了,命令如下:
1 | / root / Pluto - Obfuscator / build / bin / clang - mllvm - fla - O0 - - target = wasm32 - wasi - - sysroot = / root / wasi - sdk - 21.0 / share / wasi - sysroot / loop.c - c - o loop.o
|
混淆前的loop.wasm和混淆后的loop_fla.wasm在ghidra中对比效果:
loop.wasm(未混淆):
loop_fla.wasm(已混淆):
ollvm中有许多其他混淆选项也可以试试~
[1]: https://github.com/xubenji/Pluto-Obfuscator
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
最后于 2024-2-25 07:23
被北美老徐编辑
,原因: 更改小标题