我有个程序是这样的
测试程序:

#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/

10-11 23:12
查看更多