0x1
第一次接触到wasm,又是被装环境ex到的一天,跟着官方README.md安装都给我报错了,做实离谱,自己添加了一些参数才下载完;之后就开始去学习wasm逆向知识。学到了一些有关Chrome调试的操作。
正好极客大挑战出了一个xorwasm,真的舒坦,直接平稳过渡。
0x2
打开zip,得到三个文件,一个html,一个js,一个wasm,标准的wasm三件套。
个人处理方式
- 先获得能被ida反编译且可读性较高的文件,通过ida分析大致操作,
- 如果简单就直接推出flag,反之通过Chrome调试去分析,通过设置断点,多次调试确定判断位置,动调分析。
wasm2c下载后,通过wasm2c将wasm转换成.c文件和.h文件(进入到calc目录
[wasm2c目录] [文件名.wasm] -o [转换后的文件名.c]
虽然获得的.c文件已经可以分析了,但是分析起来还是比较难受,可以进一步优化一下,将转换出来的两个文件和wasm-rt.h,wasm-rt-impl.c,wasm-rt-impl.h放在一起
后面三个文件在下载的工具wabt/wasm2c文件夹中
进入到文件夹,通过gcc编译将.c文件进一步转换为.o文件,提高反汇编后的可读性。
gcc -c wasm.c -o calc.o
这样就会获得一个.o文件,这时候拖入ida进行反编译。
在init_memory发现这一串数据,肯定是有用的,先留着
找主函数ing…
__int64 (__fastcall *init_exports())()
{
__int64 (__fastcall *result)(); // rax
Z_e = (__int64)&w2c_e;
Z_fZ_vv = (__int64)w2c_f;
Z_gZ_iii = (__int64)w2c_g;
Z_hZ_ii = (__int64)w2c_h;
Z_i = (__int64)&w2c_i;
Z_jZ_iv = (__int64)w2c_j;
Z_kZ_vi = (__int64)w2c_k;
result = w2c_l;
Z_lZ_ii = (__int64)w2c_l;
return result;
}
在这里面函数挨个看了一下,最可疑的就是为w2c_h函数
_BOOL8 __fastcall w2c_h(unsigned int a1)
{
unsigned int v1; // eax
int v3; // [rsp+Ch] [rbp-14h]
unsigned int v4; // [rsp+10h] [rbp-10h]
if ( ++wasm_rt_call_stack_depth > 0x1F4u )
wasm_rt_trap(7LL);
w2c_g0 -= 128;
v4 = w2c_g0;
w2c_f81(a1, (unsigned int)w2c_g0);
v3 = w2c_f45(v4);
if ( v3 )
v1 = 0x43D;
else
v1 = 0x435;
w2c_f29(v1);
w2c_g0 = v4 + 128;
--wasm_rt_call_stack_depth;
return v3 == 0;
}
0x400多的数一般是字符串的偏移量(忘记在哪里看到的知识点了,可能有错
0x31EE0-0x400+0x43D=0x31F1D
正好对应字符串”Oops….something wrong”
并且在w2c_f81函数中找到了0x421,按照上面的计算方法对应着”length is not valid”,基本确定上面就是主函数
主函数内的大致:输值,判断长度,加密,比较,打印正确或者错误。
之后进行动调
动调需要使用浏览器调试,先在本地起一个简易的服务器
先进入需要调试文件的文件夹
python -m http.server -b localhost
然后在浏览器输入网址:
http://localhost:8000/calc.html
F12,选择Sources,在calc.html判断位置下断
递步后会跑到calc.wasm中,在calc.wasm设置断点多次调试确定使用位置
当运行过func29后,屏幕会显示字符串,再根据之前ida查看的内容,基本可以推测出,func81为加密函数,func45为比较函数,func29则为输出函数。其中参数var0用于判断,var1为我们输入的数据。
可以在调试器右上角的watch中设置这两个参数,用于查看内容
不知道为什么
为了更好的理解中间加密过程,从大师傅写的wp那里获得了一个js脚本,用于分析输入值的变化。
第一次只输入一个值A
第二次输入两个值AA
这里值需要颠倒一下顺序,我卡在这里了好久….
以此类推,可以得到规律
flag[0] | flag[1]<<7 | flag[2]<<14 ....
根据上面ida获取的数据写脚本
cmp_data = [0xF3, 0x39, 0x4C, 0x3A, 0xFE, 0xE6, 0x63, 0xE2, 0xF6, 0x6C, 0x3E, 0x0F, 0x8B, 0x67, 0x77][::-1]
s = ''.join(bin(a)[2:].zfill(8) for a in cmp_data)[1:]
for i in range(0, len(s), 7):
print(chr(int(s[i:i+7], 2)), end='')
直接引用的大佬的wp脚本,关于python写脚本的知识点++
得到flag:
flag{w3bass3mb1y_cR0ss}