概述
vmpwm即模拟虚拟机实现的程序,主要考察对程序的逆向能力
特征是模拟的栈结构,伪机器码,还有pc寄存器和sp寄存器
分析的重点就聚焦于找出栈和上述寄存器是如何进行实现的
从实战分析伪机器码
例题分别是iscc2025的vmpwn和minipwn
vmpwn
先来看main
函数,不难看出这里op
函数就是对输入的伪机器码进行处理的部分,我们先进入op函数看看
这里是已经进行修复过的,那就这里而言push
和pop
是如何分析出来的呢
进入函数就是一个大大的Stack,非常没有含金量啊,但这个栈具体是在哪里呢?我们来看bss段
这里a1+0x28处储存的就是main
函数里malloc
返回的指针,所以这里是通过堆来模拟的栈那么a1+0x40自然就是模拟的栈底了
接着来看这里AAAA函数(我当时随便改的函数名)频繁出现,会是做什么的呢
v1是储存的存储我们输入的指针,那v2是什么呢,推测是0.
空口无凭,我们通过调试看看
这里v2处是0,运行之后v2++,然后返回v1偏移v2地址的数据
到这里就可以推测出这是在模拟pc寄存器了,通过这个函数来获取下一条执行的指令和下一个操作数
这里再列举一下程序模拟的操作:
1 |
|
minipwn
还是先来看main
函数
这里虽然已经重命名过了但还是当作不知道先
可以看出这里有两个输入,会是什么呢,先进vm函数瞧一瞧
这里对input的+=操作都能够起到pc寄存器的功能
先来看bss段
*(&a3 + 8) = _mm_loadh_ps(&stack);
这行代码将buf指针写入*(&a3+8)处,将buf下面那个指针写入*(&a4)处
这样再来看case 1和case 2分支就能判断出是模拟的pop
和push
指令了,main函数那里的输入就是对栈的初始化
这两个分支里的switch函数对应的是pop
或push
的操作对象
分别是:
- a1
- *(&a1 + 1)
- a2
- *(&a2 + 1)
- a3
- *(&a4 + 1)
- a4-8(栈顶指针)
接下来看case 3和case 4分支:
这里模拟的是save
和load
指令
在save过后会将pc寄存器指向如图所示的指令
后面几个分支分别为
case 5:以a1,(&a1+8),a2,a3为rax,rbx,rcx,rdx寄存器调用syscall
case 6:将指定操作对象归零
case 7:inc 8
case 8:dec 8
所以在save过后会先清零寄存器后通过syscall调用read函数后立即回到case 4分支执行load
这里在对状态的处理时还专门分配了一片区域,见过一次后应该不难看出来
漏洞角度
vmpwn
这里是有一个数组越界漏洞,可以通过将数组的索引设为负的来访问数组外的数据,以此来泄露libc通过case a或case b分支得到system和binsh来getshell
minipwn
这里是一个溢出漏洞,在save保存后进行的输入时可以将load中v5处写入0就可以实现在load中将flag赋值为0然后操作四个寄存器调用syscall执行execve(‘/bin/sh’,0,0)来getshell
总结
这种类型的要点就是
- 找出pc寄存器是如何实现的
- 找出栈是如何实现的
- 分析每条指令具体执行的操作是什么