我正在尝试为我的安全类进行缓冲区溢出,我们不允许调用任何函数,我们需要跳转到秘密函数并返回 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
返回时,它实际上是现在从主要返回,但它无法完成return 0;
所以秘密应该是:
int secret()
{
printf("now inside secret()!n");
return 0;
}
免责声明:"....我想。