使用ret2reg攻击绕过地址混淆
什么是ret2reg
ret2reg攻击绕过地址混淆,即return-to-register,返回到寄存地址执行 的攻击方法。
ret2reg方法核心是:找到寄存器与缓冲区地址的确定性关系,然后从程序中搜索call reg/jmp reg这样的指令;如果两者条件满足,则
- 分析和调试汇编,看溢出函返回时哪个寄存值指向溢出缓冲区空间
- 然后反编译二进制,查找call reg 或者jmp reg指令,将该指令所在的地址注入到 EIP
- 再在reg指向的空间上注入Shellcode
此攻击方法之所以能成功,是因为函数内部实现时,溢出的缓冲区地址通常会加载到某个寄存器上,在后在的运行过程中不会修改。尽管栈空间具有随机性,但该寄存器的值与缓冲区地址的关系是确定的,在随机地址之上,建立了必然的地址关系。一句话就是 在随机性上找到地址的确定性关系。
利用步骤
- 对准EIP
第一步首先是对准EIP,我们输入数据引发溢出,覆盖EIP。 - 确定哪个寄存器与缓冲区有确定性的关系
如果你一步一步地按ret2addr攻击方法操作并攻击成功,那么你会发现此时的esp就是指向注入EIP的下一个地址。如果你能在程序中找到call esp或者jmp esp(64位的为rsp)这样的指令,就可以将EIP注入该指令地址,并且在EIP后面注入shellcode,那就彻底绕过地址混淆保护方法。
例子
这是一道cctf2015的一道题,我们用IDA打开后直接查看伪代码。
从上面的伪代码我们可以看出,我们输入的数据全部拷贝到了V6。接下来我们在gdb下调试这个ELF文件。
查看保护
checksec可以看到程序没有没有打开任何保护措施,现在唯一需要解决的就是系统自带的ASLR,(注意,使用gdb调试时,每次看到的栈地址可能是不变的,这并不代表系统没有打开ASLR,gdb调试时会自动关闭ASLR)
我们首先输入40个测试字符A进行测试,发现没有发生溢出。
接下来我们输入80个A发现出现了溢出。
可以看出从第四十个字节开始的八个字节就会覆盖返回地址
然后我们还需要一个跳板作为返回地址 。使用jmpcall rsp。rsp是栈指针寄存器,64位。指向栈顶。相当于32位汇编里的esp,16位的sp。
我们就采用第一个地址。
最后我们需要一个shellcode,这可以通过msf生成,也可以在exploit.db上下载。
exp如下:
成功拿到shell