VM Pwn记录
之前有听说,最近的hws见过一次,感觉比较有意思,花时间学一学
vmpwn的题目会比一般的pwn题逆向量上大不少,稳定发挥的话直观上可以有个一两千行的伪代码吧,虽然while循环占据了一大半,但是工作量还是比较大的
我的做法都是先猜,根据局部的虚拟指令集去猜cp,sp之类的关键寄存器,然后逆向输入解码的流程,搞明白其虚拟指令集的具体作用,然后再去找漏洞。而且vmpwn的漏洞一般比较容易,主要考虑越界读写以及虚拟堆栈上的残余指针,难度还是集中在逆向上
而且下面做的指令集的vm给我的感觉就是在做计组实验,做标注的时候还复习了一遍risc-v指令?
还有一种类型是模拟高级语言的题,hws那道就是模拟C的编译器,这一类的题目会比汇编指令的自由度大一点,也更难一些
[OGeek2019 Final]OVM
这题算是vm题最简单的那种了,逆向量很低,开局让你输入PC SP,这里没啥注意的,后面中断指令对SP有个检测,给个1就好了,然后输入全部在memory那一块
重点关注输入到执行的转码
1 | tar_reg_num = (a1 & 0xF0000u) >> 16; |
这里的变量名已经根据后面的操作改过了
部分指令如下
1 | 0x70 : add |
其中load,store满足了我们读写内存的需求,并且该题的漏洞在于读写的区间没做限制,导致可以读写到memory之外的内存。调试我们可以发现memory上面是got表,于是可以利用越界读来获取libc基址,然后由于主程序最后free了在memory附近的指针,考虑通过越界写把指针改成__free_hook-0x8
,结束后做一次读写往chunk里填/bin/sh\x00+p64(system)
即可
exp
1 | from pwn import * |
[网鼎杯2020]boom2
一开始分配了一片比较大的空间,然后两个局部变量存了这个地址的偏移,联想到栈,通过读后面的指令发现都有涉及这两变量的变化,一开始还不确定,然后我看到了一段这个
1 | v_sp = (void **)(v_bp + 1); |
你把bp,sp带进去会发现就是一个leave_ret
之后就是逆指令了,这里得细心一点,一开始看太快了,有个指令的作用想当然了,然后打了一个十分复杂的流程结果超过了输入的量。后面重新逆才发现这个点逆错了,而且是个比较关键的代码
我先看了*--v_sp = reg;
然后看到了下面这个
1 | v9 = (__int64 **)v_sp++;//1 |
然后果断标注push pop
后划走,而这里实际上可以实现任意地址写,,,一开始逆错了找了个极其阴间的任意地址写,然后导致输入超了
1 | v10 = v_sp++; |
并且标注1那里用到了多级指针,看不明白的可以直接看汇编,很容易懂,直接视作一个指针就行
指令的逆向如下
1 | 0x00 : lea reg stack[i] |
漏洞在于虚拟栈上存了真实栈上的地址,伪代码上没看出来,上手调试发现的。那就比较容易了,用这个地址算出main函数的bp+0x8
,任意地址读可以拿到libc基址,然后把og写到这个bp+0x8
上就行
exp
1 | from pwn import * |
[CISCN 2019 Qual]virtual
也是一道比较简单的问题,但是逆向的难度比上面高一点,函数稍微有点多,逆向能力太菜了,指令逻辑根本逆不太清,还是后面根据回显把每个指令过程猜了个差不多。洞极其好找,虚拟栈越界写,改掉指针劫持puts的got表,我用og和system都打了一遍本地都ok,但是远程通不了,不知道什么玄学原因没管了
exp
1 | from pwn import * |
- Post title:VM Pwn记录
- Post author:hash_hash
- Create time:2023-01-14 21:11:11
- Post link:https://hash-hash.github.io/2023/01/14/VM-Pwn记录/
- Copyright Notice:All articles in this blog are licensed under BY-NC-SA unless stating additionally.