我有个程序是这样的
测试程序:
#include <stdio.h>
void foo(char *input)
{
char buffer[64];
strncpy(buffer, input, sizeof(buffer));
printf(buffer);
}
int main(int argc, char **argv)
{
foo(argv[1]);
}
我在关闭所有堆栈相关保护的情况下编译程序。
gcc fmthck.c-w-m32-O0-ggdb-std=c99-static-D\u FORTIFY\u SOURCE=0-fno pie-Wno format-Wno format security-fno stack protector-z norelro-z execstack-o hacks
sudo sysctl-w kernel.randomize_va_space=0
然后我为编译后的程序提供以下参数:
./hacks“AAAA%p%p%p%p%p%p%p%p%p”
我得到的结果是这样的
AAAA 0xffffd3cb 0x40 0x8048d3c 0x414141 0x2e702520 0x252e7025 0x70252e70 0x2e70252e 0x252e7025 0x70252e70
我知道A=0x41是十六进制的。所以我猜缓冲区的起始地址对应于4%的p。我只是想知道它周围的东西是什么意思。我得到了一个这样的堆栈图。我知道0x8048d3c对应于返回地址,但是有些东西没有对齐
高内存地址
输入参数
返回地址
保存的帧指针
局部变量
保存的寄存器
低内存地址
有人能在我做这个的时候详细说明一下这堆东西是怎么回事吗?
最佳答案
如果使用选项-S编译程序,编译器将生成可供检查的程序集输出。在您的情况下,相关生成的代码是:
foo:
pushl %ebp
movl %esp, %ebp
subl $88, %esp
movl $64, 8(%esp)
movl 8(%ebp), %eax
movl %eax, 4(%esp)
leal -72(%ebp), %eax
movl %eax, (%esp)
call strncpy
leal -72(%ebp), %eax
movl %eax, (%esp)
call printf
你的产出是
AAAA 0xffffd3cb 0x40 0x8048d3c 0x41414141 0x2e702520 0x252e7025 0x70252e70 0x2e70252e 0x252e7025 0x70252e70
必须在调用
printf
时将其解释为系统堆栈的一部分。输出的含义是:AAAA == string from argument printed by printf
0xffffd3cb == garbage left from previous function invocation, in fact the input argument argv[1] previously sent to `strncpy`
0x40 == garbage left from previous function invocation, in fact it is the constant 64 previously sent to strncpy
0x8048d3c == ??? I don't know why gcc left this unused space.
0x41414141 0x2e70252 ... is the content of local variable `buffer` which contains the string "AAAA %p %p %p %p %p %p %p %p %p %p".
函数的返回地址以及保存的基指针超出了输出范围。
关于c - 32位Intel堆栈帧格式字符串利用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/21649664/