我要利用的函数基本上是这样的:
int getbufn()
{
char buf[512];
Gets(buf);
return 1;
}
当我运行主程序时,该函数会执行5次,每次buf的位置和%ebp的位置都会改变。我的任务是将一个特定的十六进制值,比如0xFFFFFFFF,放入一个变量中,然后主程序每次都会检查那个变量是否存在。如果存在,它会再次执行,直到所有5次都完成并且程序安静地退出。我的问题在于,在检查十六进制值之前,还要检查另一个常数值,比如0x12345678。如果我已经破坏了0x12345678并且它不存在,程序就会崩溃。
我已经知道0x12345678存储在-0x10(%ebp)中,所以我知道它基于%ebp并且每次都知道%ebp的地址,但是我只能使利用代码第一次工作。我通过nopsled-ing 496个字节,并在其中包含这个字节格式的机器代码来做到这一点:
mov 0xFFFFFFFF, %eax
movl address old ebp, %ebp
push correct return adress in function main
ret
这段代码最终会变成5个单词和一个返回long类型的字节,我使用0x313131填充它使其长度为6个单词。此时我的攻击字符串长达520字节,刚好是%ebp下面的缓冲区大小,因此我加上旧ebp地址以及nopsled中某个地址的值,覆盖了%ebp的当前值以及getbufn函数的返回地址。问题在于当程序第二次执行时,%ebp的地址比先前的地址低了0x10,因此我的解除错误%ebp的方式无效,main函数检测到0x12345678不在-0x10(%ebp)处。如何修复%ebp的错误?
movl
,而是将%esp复制到%ebp中,并在其上添加偏移量? - pmdj