先看程序
64位程序,没开什么保护,且有可读可写权限
这里get_s函数存在溢出,可以读入agrv个字节的数据到s中,但是没有规定agrv的大小,所以我们可以用这个来进行栈溢出(补充一下gets和get_s函数,gets(str1)是读入数据到str1里面,get_s(str1,size)是读入size长度的数据到str1中)
回归题目,这题看到右边存在fun函数,进去看看可以发现system(/bin/sh),那我们思路就是栈溢出,把返回地址改为system函数地址
但是要注意,这里地址可以有俩种选择,先说第一种
我们这里地址填为0x40018A,因为我们直接填fun函数起始地址,你会发现程序报错,因为这里打破了栈平衡(函数栈平衡可以粗略理解为在retn指令完成前,rsp要指向它刚来的位置,但是看这个汇编代码会发现,到retn指令结束时都没有将rsp调回原处,这里压入了一个参数,使用了整型寄存器rdi,rsp向下移动4字节,但是当程序执行到retn时都没有将rsp上移,所以要跳过push和move指令,也就不能用fun函数,更深入可以去看栈平衡相关文章)回到这题,我们脚本思路也出来了
这里另外一种思路就是添加一个ret在payload里面,然后可以直接执行fun函数
payload中的堆栈平衡简单来说,就是要保证payload的字节数是16的倍数。而p64是将地址转为8字节的字符串,所以payload中得保证p64是偶数倍,就能满足堆栈平衡
ret代表ret指令的地址,可以直接在IDA里面任意找一个,也可以用ROPgadget来找】,因为ret的多少不会影响到函数的执行逻辑,所以用其来平衡
参考文献:http://t.csdnimg.cn/RVgeG
这里第一种方法不用考虑栈平衡,因为没有出栈入栈的操作,但是第二种就需要考虑栈平衡,因为fun函数里面有push , mov 等操作
以上为个人理解,不对之处希望师傅们指正