VMpwn入门学习
这里将以一道入门级别的vmpwn题目简单学习一下
知识点
题目会模拟指令,根据题目意思解题即可,而且这类的题目往往存在数组溢出的问题
例题1:[OGeek2019 Final]OVM
分析
1 | int __fastcall main(int argc, const char **argv, const char **envp) |
这里面的操作数,pc sp在这题中没有什么作用,size决定后面的输入的循环的次数
主要函数
现在我们来逆向这题的重点,execute函数
1 | ssize_t __fastcall execute(int opcode) |
这里把我们输入的int类型(32位)转化为各个相当于寄存器的值,在对这些值根据函数中的逻辑进行编码操作
这是大概逆向出来的样子
1 | 0x10: reg[high]=reg[small] //也就是低八位 |
可以数组内部填入负数从而使达到越界访问
一些逆向中的代码解释
1 | high = (opcode & 0xF0000u) >> 16; //16-20 |
思路
那么我们知道了这样的过程怎么进行操作呢
这题有个关键的数组就是memory数组
1 | got:0000000000201F78 stdout_ptr dq offset stdout ; DATA XREF: main+36↑r |
- memory在静态分析中,上面的函数存在got,而我们在execute中可以直接修改这个数组
- 我们便可以先把reg的某个地方存放ptr表,就可以把got表打印出来了
- 又因为这是2.23,我们可以直接修改函数的free_hook
- 我们可以把堆快存放的地址改成free_hook,利用主函数后面的写功能完成这个函数
- 接着把free改成system,实现getshell
EXP的编写
先算出memory距离stdin_ptr为56个数组
1 | def opcode(desk,high,middle,small): |
我们算出来偏移,接着我们要把stdin的地址改成__free_hook
gdb计算出偏移
1 | sl(opcode(0x10,0,0,1)) #reg[0]=1 |
再把堆快改到对free_hook前面8个字节
1 | sl(opcode(0x10,0,0,8)) #reg[0]=8 |
后面只需算出地址即可
1 |
|
exp
1 | from pwn import * |
参考文章
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 鱼非愚!
评论