首先,开启地址随机化,观察buf的地址:
注意到bufn的差别巨大,也就是说滑动攻击(利用一堆空指令来增加命中率)的方法无效。那么只能另寻它路。
在getbufn的ret处打上断点,观察各寄存器的值:
注意到rdi中保存的就是bufn的地址,故自然产生一个想法,只需要执行“jmp rdi”即可。发现二进制位ff e7,所以思路就为找到内存中0xe7ff的段即可。
在gdb中先执行info proc mappings,找到可执行代码段,即下图的r-xp段:
在可执行代码段中寻找jmp rdi:
可惜没有找到,原因是代码段实在是太短,找到需要的指令的可能性极低。接下来有两种思路,一种是修改源代码,第二种是把动态链接改成静态链接。
在这我采用第二种方法,即把编译选项改为:
这里我用了一个软件叫ROPgadget,可以很方便的查找指令,支持模糊查找等筛选方法,而且自动在可执行代码段中查找,十分方便。采用ROP(Return Oriented Programming)的思路,找小gadget:
接下来就需要发挥奇思妙想了。容易注意到,getbufn中ret后,%rsp指向返回地址-1,而我们能修改的不仅仅是getbufn的栈帧,实际上考虑到在testn中调用getbufn后并不会再用到很多局部变量,所以我们也可以破坏testn的栈帧。
一言以蔽之:只需要把所需指令从testn的%rsp开始存,修改返回地址为“push rsp;ret”即可,注意需要恢复rbp的值。
攻击字符串如下:
直接执行,攻击成功!