32位应用
32位ELF的参数直接放到栈中。
先找到一个EFF程序,用IDA打开F5
,发现了fgets缓冲区溢出利用点:
溢出长度为:0x28 + 0x4 = 0x2C
。
Shift+F12查找可以利用的字符串:
这俩看着能用:
usefulString db '/bin/cat flag.txt',0
地址0x0804A030
,没有被其他函数调用,要想办法调用这串字符,可以利用_system调用。usefulFunction调用了/bin/ls
:
双击查看_system函数的.plt
表内容:
0x08048430
是我们要调用的_system的地址。
开启pwngdb,finish、ni一顿操作,调试到pwnme函数ret位置,查看esp内存已经指向system@plt地址。
64位应用
64位ELF的参数先放入rdi/rsi/rdx/rcx/r8/r9
,最后才放入栈中。
找到溢出点:
溢出长度:0x20+0x8=0x28
。
Shift+F12
查找可以利用的字符串:
跟上一个例子一样,查找system的.plt
地址0x4005E0
:
usefulString
字符串地址0x601060
:
由于64位程序处理参数没有直接放入栈中,所以不能用32位程序的处理方式,需要用到ROP,查找类似如下代码的位置,以绕过传参寄存器的限制,一般是绕过第一个寄存器rdi
:
这里有专门的查找工具Ropgadget:
--binary
指定要查找的二进制文件。
--only
指定要查找的指令。
我们找到了。快捷键G:跳转
打开字节码(每条指令最多显示5个字节码):
选中0x400882行的pop,点击按键两次u转为数据,然后选中5F,按键C转化为指令,即可看到pop rdi;retn
:
大佬画的栈图(ROP原理):
exp:
rdi
寄存器成功被修改: