我有一个看起来像这样的程序
测试程序:
#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_FORTIFY_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%p”
我得到一个看起来像这样的输出
AAAA 0xffffd3cb 0x40 0x8048d3c 0x41414141 0x2e702520 0x252e7025 0x70252e70 0x2e70252e 0x252e7025 0x70252e70
我知道HEX中的A = 0x41。所以我猜测缓冲区的起始地址对应于第4%p。 我只是想知道它周围的东西是什么意思。我得到了一个看起来像这样的堆栈图。我知道0x8048d3c对应于返回地址,但有些东西没有对齐
高内存地址
低内存地址
有人可以详细说明我这样做会发生什么事吗?
答案 0 :(得分:2)
如果使用选项-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".
函数的返回地址以及保存的基指针超出了输出范围。