esrever-mv
简单来说,就是被丢了道vm的题,说没writeup。搜了搜确实没有,于是摸了摸,发现适合入门。
查看调用栈
程序读取输入时,查看调用
1 | (gdb) bt |
分析流程
拖入ida
- #0 0x00000000004402b0
- 发现是_read
- #1 0x0000000000400ae1
- 发现是判断
[rdi+10008h]
为0或1来进行read或write
- 发现是判断
- #2 0x00000000004010ba
- 逻辑图看起来像是vm解析执行的函数
- 发现字符串
"[MESSAGE] vm halt\n"
- case为29(0x1d)
- #3 0x0000000000400659
- 发现分支中含有字符串
"Failed to create vm"
- 上方调用了两个静态变量,猜测为虚拟机代码、flag数据
- 发现分支中含有字符串
- #4 0x0000000000401e26
- libc
详细分析
分析#3所在的函数
分析#3所在函数sub_4005F0
所调用的五个函数(#3为调用的第4个函数)
- 都调用了*[rsp+28h+var_18]*,猜测var_18为vm
- #3之上的两个函数功能是将两个静态变量复制到0x4000与0x6000.
- #3最上方的函数之后有判断是否成功,且失败会提示
"Failed to create vm"
,则猜测为创建vm的函数 - #3之下的函数判断为销毁虚拟机
分析#2所在的虚拟机执行函数
分析#2所在的虚拟机执行函数
[rbx+10026h]
自增4,推断为ip.且由此判断vm指令为定长,长度为4.- 发现循环判断
rdi+8
.推断为解释器执行内存位置 - 推断指令为
db opcode,db args[1],dw args[2]
,其中args[1]的高四位为一个参数(r8b),低四位为一个参数(r10d),args[2]为一个参数(r11d) - 分析opcode为0x1时发现,
[rdi+10018h]
为vm寄存器首地址
1 | .text:0000000000400FBB 48 8D AF 18 00+ lea rbp, [rdi+10018h] |
分析opcode
分析调用的0x1d
简单来说就是判断[rdi+10008h]的值
- 为1,则将[rdi+1000Ah]的值调用write输出
- 为0,则将调用read,并将输入的值填充到[rbx+10018h].
1 | .text:00000000004010B0 loc_4010B0: ; CODE XREF: _zz_execute+A7↑j |
分析0x1
简单来说就是: [rdi+10018h+t12]=-[rdi+10018h+t22]
1 | .text:0000000000400FBB 48 8D AF 18 00+ lea rbp, [rdi+10018h] |
分析其他
同上,以此类推。根据执行的vm代码,只需要分析0x1e,0x17,0x03,0x13,0x1d,0x19,0x18,0x0f,0x03,0x01,0x0a,0x11
这12个opcode即可。
分析vm代码
vm数据段(vm:0x6000)(.data:00000000006CC0A0)
vm代码段(vm:0x4000)(.data:00000000006CC0E0)
1 | case_0x1e, t0__t0, 0 ;t0=rand() \ |
其他
然而,差不多搞完了才发现作者把writeup都丢到脸上了:gayhub