我试图理解缓冲区溢出的概念,并且我无法计算填充到堆栈中的数据量,因此它会正确溢出。假设我给出了一些代码(这不是我的代码,是的,它来自一个类,但这不是一个分级的分配): 目标是让条件执行。
#include <stdio.h>
#include <string.h>
void foo(char *s) {
char buf[4];
strcpy(buf, s);
printf("You entered: [%s]", buf);
fflush(stdout);
}
void bar() {
printf("\n\nWhat? I was not supposed to be called!\n\n");
fflush(stdout);
}
int main(int argc, char *argv[]) {
if (argc != 2) {
printf("Usage: %s some_string", argv[0]);
return 2;
}
foo(argv[1]);
return 0;
}
当我反汇编酒吧时,我得到了酒吧的起始地址:
(gdb) disas bar
Dump of assembler code for function bar:
0x000000000040062d <+0>: push %rbp
我被告知需要将28个字节的数据填充到缓冲区中,最后4个字节需要为\x2d\x06\x04\x00
。你在哪里得到24个字节来知道有多少随机数据。
一般而言,我最感兴趣的是如何概括和解决任何问题。
如何计算填充堆栈帧所需的字节数,然后覆盖函数的返回地址?
注意:这是用C语言编写的,用GCC 4.4.7编译
答案 0 :(得分:1)
从单个C代码中,您可以获得不同的结果。
void foo(char *s) {
char buf[4];
strcpy(buf, s);
printf("You entered: [%s]", buf);
fflush(stdout);
}
编译器可以输出
ADD SP, 4 // space for buf
PUSH SP-12 // address of string 's'
PUSH SP-8 // address of SP (4 + space for s)
call strcpy
push literal_You_entered
push SP-8
call printf
...
或者它可能想要一个堆栈帧。
PUSH Frame
MOVE SP, Frame
ADD SP, 4 // space for buf
....
或者它可能需要保存寄存器
PUSH Frame
MOVE SP, Frame
PUSH Reg1
PUSH Reg2
ADD SP, 4 // space for buf
这可以基于编译器的优化设置。在每种情况下,这都会移动值。
尝试像'\x01\x02\x03\x04\.....\xfe\xff'
这样的魔术缓冲区。
您获得的分段错误应该显示重要字节的位置。 0x08090a0b处的访问冲突将描述哪些字节是返回。
覆盖帧指针(FP)意味着您可以修改调用函数中的行为,这也可能对您有所帮助。
答案 1 :(得分:-1)
如何计算填充堆栈帧所需的字节数,然后覆盖函数的返回地址?
您可以通过学习您尝试利用的体系结构中的堆栈框架布局以及编译器如何将变量放入堆栈框架来实现。 28个字节恰好是第一个变量的位置与您正在使用的特定体系结构的堆栈帧中的返回地址之间的差异。