我正在尝试为我的安全性类进行缓冲区溢出,不允许调用任何函数,我们需要跳转到秘密函数,并且还应返回0且不会出现分段错误。我在下面编写了代码,并成功跳入了秘密,但是我遇到了段错误。如何成功终止程序?或者当我尝试不更改任何内容时,也可以只写一个地址而不是for循环。
#include <stdio.h>
void secret()
{
printf("now inside secret()!\n");
}
void entrance()
{
int doNotTouch[10];
// can only modify this section BEGIN
// cant call secret(), maybe use secret (pointer to function)
for (int i = 0; i < 14; i++) {
*(doNotTouch + i) = (int) &secret;
}
// can only modify this section END
printf("now inside entrance()!\n");
}
int main (int argc, char *argv[])
{
entrance();
return 0;
}
在某些半汇编程序中,假设使用某种x86。 (BP是用于EBP或RBP的伪代码,假设您实际上并未针对16位模式进行编译。可能是32位模式,因此int
与返回地址的宽度相同。)
; entrance:
; - stack has return address to main
push bp ; decrement SP by a pointer width
mov bp,sp
sub sp, 10*sizeof(int) ; reserve space for an array
;....
; doNotTouch[0] is probably at [bp - 10*sizeof(int)]
[循环到14时,首先覆盖i == 10处的已保存bp,然后返回到main的返回地址(这是正确的),然后覆盖更多的地址,最终导致seg错误。因此,您只需要执行*(doNotTouch + 11) = (int) &secret;
-假设int是函数指针的大小。 (或者,如果编译器为堆栈对齐或自己使用留下空白,则可能要多一点。在调试版本中,其他本地变量将具有堆栈插槽。覆盖它们可能会导致无限循环,超出范围。)
然后跟随您的printf,然后函数返回,但它不返回main而是“跳转”到secret
。
secret
返回时,实际上现在是main的返回,但它无法执行return 0;
所以秘密应该是:
int secret()
{
printf("now inside secret()!\n");
return 0;
}
免责声明:“ ....我认为。”