ROP
ret2text:使用原本程序的代码片段
ret2lib:使用到执行时载入的shared library
使用return来组合出所需要的功能,巧妙选择要return的位置,寄存器,内存,syscall等。
Jump to Shellcode
使用ret2text的技巧,call到gets,再跳到新的shellcode,比如demo中有gets,所以存在溢出,制造shellcode溢出main函数的ret
这里巧妙将main的ret溢出为gets函数,为了payload执行shell,操作思路是溢出返回的gets函数,参数返回值均为一个可写可执行的地方,然后将shell相关操作gets到这个位置,gets返回地址仍然是此地址,则返回时就执行了此shell。
操作可以使用pwntool,结合gdb,方便操作。
以下部分截图是课程前一个remote-shell-expoilt的截图,与demo2原理一样,所以就不重复截图了
关于gdb调试
idof xxx(process名),得到pid,然后attach
、
关于生成fuss字符串
scylic可以生成fuzzing字符串,根据栈上的值确定覆盖到了哪里。
p32的作用是改成litter-ending
然后如下就能确定是哪里了
关于gets函数获取
然后elf.symbols['gets']可以帮忙找到gets函数地址
关于gets函数参数(shellcode)放置位置
位置为了方便一般放在global位置(堆栈地址每次执行程序会变化),所以我们选择bss段,因为一般申请内存按页,只用前半部分,所以参数写到一段bss靠后比如0x100的位置
elf.bss()可以拿到bss段
然后一般为了确认送到合法地址用0xff0xff0xff为不合法
0xeb0xf1为无限循环
Gadget
因为很多时候pc设置了DEP保护,我们要绕过,技术就是rop,构造rop链,思路如下
就是找到rop片段代码:"pop 寄存器,xxx,ret"的位置,如此shellcode代码为比如"rop片段代码地址,想要让寄存器保存的值",这样再将shellcode覆盖了栈之后,执行时候就会构造成我们的代码
例子
就是自组一个system call,要至少有int 0x80(execve),参数
使用ROPgadget,ROPgadget --binary ./test > gadgets
所以要找的就是一堆pop xxx,可以把想放的值传进去
如果能找到最好,找不到比如pop eax,只能凑了,比如读指令,call gets然后把指令放进去,就是找如上的代码进行拼凑shellcode。
另外shellcraft可以直接出shellcode,此外shellcode不要出现0,很可能会被截断。
关于答题
题目测试一般使用nacat及nc
ncat -vc -kl(k是保活,l是端口)-v:显示命令执行debug,c是执行那个程序
然后nc连接
echo xxx | ./yyy 将xxx结果输入到yyy
参考资料
bamboofox教程