我正在为课程作业进行堆栈式练习,我已经完成了作业,但有一个方面我不明白。
以下是目标计划:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int bar(char *arg, char *out)
{
strcpy(out, arg);
return 0;
}
void foo(char *argv[])
{
char buf[256];
bar(argv[1], buf);
}
int main(int argc, char *argv[])
{
if (argc != 2)
{
fprintf(stderr, "target1: argc != 2\n");
exit(EXIT_FAILURE);
}
foo(argv);
return 0;
}
以下是用于编译它的命令,在运行x86
的{{1}}虚拟机上,Ubuntu 12.04
已禁用。
ASLR
当我查看堆栈中此程序的内存时,我发现gcc -ggdb -m32 -g -std=c99 -D_GNU_SOURCE -fno-stack-protector -m32 target1.c -o target1
execstack -s target1
的地址为buf
。此外,保存的帧指针存储在0xbffffc40
,返回地址存储在0xbffffd48
。
这些具体地址不相关,但我观察到即使0xbffffd4c
只有buf
长度,距离256
也是如此。符号上,此计算为0xbffffd48 - 0xbffffc40 = 264
。
为什么$fp - buf
的末尾与堆栈中存储的帧指针之间有8
个额外字节?
以下是函数buf
的一些反汇编。我已经检查了它,但我没有看到该内存区域的任何明显用法,除非它是隐式的(即某些指令的副作用)。
foo
答案 0 :(得分:3)
Basile Starynkevitch因提及alignment
而获奖。
事实证明gcc 4.7.2
默认将帧边界与4字边界对齐。在32位仿真硬件上,即16字节。由于保存的帧指针和保存的指令指针只占用8个字节,编译器在buf
结束后再放入8个字节,使堆栈帧的顶部与16字节边界对齐。
使用以下附加编译器标志,8个字节消失,因为8个字节足以对齐2个字的边界。
-mpreferred-stack-boundary=2