C 堆栈帧跟踪

标签 c linux gcc stack

我正在尝试堆栈粉碎以跟随我的安全文本。代码如下。现在,我有几个问题,在盯着这个看了几个小时后我无法自己调和,任何解释将不胜感激:

  • 根据 System V x86_64 ABI ( http://www.x86-64.org/documentation/abi.pdf ),参数以相反的顺序被压入堆栈,但 6、5 和 4(c、b 和 a)似乎位于 0x7fffffffdf40,分别为 0x7fffffffdf44 和 0x7fffffffdf48。或者我在看 这是错误的,这些是实际值?我感到困惑的原因是堆栈在内存中向下增长,但是 large_string 首先被声明和初始化但似乎具有比 a、b 或 c (0x7fffffffde40) 更低的地址,如果这些是实际的内存位置。

  • 如果调用 function() 的参数被压入栈中 0x7fffffffdf40 左右,那么返回地址不应该也被压入此处吗?我没有看到与似乎是返回地址的 4、5 或 6 相邻的任何内容,所以我认为这些是实际的变量内存位置?

  • 也许以下内容相距不远?:main() 的框架位于 0x7fffffffdf40,function() 位于 0xfffffffde1c?

代码:

  #include <stdio.h>
  #include <string.h>

  void function_1(char *str, int a, int b, int c){
    char buffer[16] = "AAAAAAAAAAAAAAAA";
    //
    strcpy(buffer, str);
    //
  }

  void function(char *ls, int a, int b, int c){
    a -= 3;
    b -= 3;
    c -= 3;
    function_1(ls, a, b, c);
  }

  int main(){
    char large_string[256];
    int i;
    for(i = 0; i < 255; i++)
      large_string[i] = 'A';
    int a = 4, b = 5, c = 6;
    function(large_string, a, b, c);
  }             

调试器跟踪信息:

Breakpoint 1, function_1 (str=0x7fffffffde40 'A' <repeats 200 times>..., a=1, b=2, c=3) at test.c:7
7     strcpy(buffer, str);
(gdb) print main
$1 = {int ()} 0x4005ab <main>
(gdb) print function
$2 = {void (char *, int, int, int)} 0x400573 <function>
(gdb) print function_1
$3 = {void (char *, int, int, int)} 0x40052d <function_1>
(gdb) x /500xg 0x7fffffffdd00
0x7fffffffdd00: 0x00007fffffffdd80  0x000000006562b026
0x7fffffffdd10: 0x0000000000000000  0x0000000000000001
0x7fffffffdd20: 0x00007ffff7ffe788  0x00007ffff7de4678
0x7fffffffdd30: 0x0000000000000000  0x00007fffffffdd70
0x7fffffffdd40: 0x00007ffff7ffa160  0x00007fffffffde80
0x7fffffffdd50: 0x00007ffff7ffa1d8  0x00007fffffffde70
0x7fffffffdd60: 0x0000000000000000  0x00007ffff7de3e9c
0x7fffffffdd70: 0x0000000000000000  0x00000000f63d4e2e
0x7fffffffdd80: 0x0000000000000001  0x0000000000000003
0x7fffffffdd90: 0x00007ffff7ff99c8  0x00007ffff7de4816
0x7fffffffdda0: 0x0000000000000000  0x00007fffffffdde0
0x7fffffffddb0: 0x00007ffff7a18d28  0x00007fffffffdef0
0x7fffffffddc0: 0x00007ffff7a251a8  0x0000000003d8f538
0x7fffffffddd0: 0x00007fffffffdee0  0x00000003f7ffeae8
0x7fffffffdde0: 0x0000000100000002  0x00007fffffffde40
0x7fffffffddf0: 0x4141414141414141  0x4141414141414141
0x7fffffffde00: 0x00007fffffffde30  0x00000000004005a9
0x7fffffffde10: 0x0000000100000000  0x0000000300000830
0x7fffffffde20: 0x0000000100000002  0x00007fffffffde40
0x7fffffffde30: 0x00007fffffffdf50  0x0000000000400606
0x7fffffffde40: 0x4141414141414141  0x4141414141414141
0x7fffffffde50: 0x4141414141414141  0x4141414141414141
0x7fffffffde60: 0x4141414141414141  0x4141414141414141
0x7fffffffde70: 0x4141414141414141  0x4141414141414141
0x7fffffffde80: 0x4141414141414141  0x4141414141414141
0x7fffffffde90: 0x4141414141414141  0x4141414141414141
0x7fffffffdea0: 0x4141414141414141  0x4141414141414141
0x7fffffffdeb0: 0x4141414141414141  0x4141414141414141
0x7fffffffdec0: 0x4141414141414141  0x4141414141414141
0x7fffffffded0: 0x4141414141414141  0x4141414141414141
0x7fffffffdee0: 0x4141414141414141  0x4141414141414141
0x7fffffffdef0: 0x4141414141414141  0x4141414141414141
0x7fffffffdf00: 0x4141414141414141  0x4141414141414141
0x7fffffffdf10: 0x4141414141414141  0x4141414141414141
0x7fffffffdf20: 0x4141414141414141  0x4141414141414141
0x7fffffffdf30: 0x4141414141414141  0x0041414141414141
---Type <return> to continue, or q <return> to quit---
0x7fffffffdf40: 0x0000000500000006  0x000000ff00000004
0x7fffffffdf50: 0x0000000000000000  0x00007ffff7a36ec5
0x7fffffffdf60: 0x0000000000000000  0x00007fffffffe038
0x7fffffffdf70: 0x0000000100000000  0x00000000004005ab
0x7fffffffdf80: 0x0000000000000000  0x9222f893ea203108
0x7fffffffdf90: 0x0000000000400440  0x00007fffffffe030
0x7fffffffdfa0: 0x0000000000000000  0x0000000000000000
0x7fffffffdfb0: 0x6ddd076c54e03108  0x6ddd17d536da3108
0x7fffffffdfc0: 0x0000000000000000  0x0000000000000000
0x7fffffffdfd0: 0x0000000000000000  0x0000000000400610
0x7fffffffdfe0: 0x00007fffffffe038  0x0000000000000001
0x7fffffffdff0: 0x0000000000000000  0x0000000000000000
0x7fffffffe000: 0x0000000000400440  0x00007fffffffe030
0x7fffffffe010: 0x0000000000000000  0x0000000000400469
0x7fffffffe020: 0x00007fffffffe028  0x000000000000001c
0x7fffffffe030: 0x0000000000000001  0x00007fffffffe359
0x7fffffffe040: 0x0000000000000000  0x00007fffffffe384
0x7fffffffe050: 0x00007fffffffe38f  0x00007fffffffe3a1
0x7fffffffe060: 0x00007fffffffe3b4  0x00007fffffffe3ca
0x7fffffffe070: 0x00007fffffffe3e0  0x00007fffffffe3f6
0x7fffffffe080: 0x00007fffffffe406  0x00007fffffffe411
0x7fffffffe090: 0x00007fffffffe461  0x00007fffffffe49a
0x7fffffffe0a0: 0x00007fffffffe4a6  0x00007fffffffe9c7
0x7fffffffe0b0: 0x00007fffffffe9f6  0x00007fffffffea27
0x7fffffffe0c0: 0x00007fffffffea33  0x00007fffffffea5e
0x7fffffffe0d0: 0x00007fffffffea73  0x00007fffffffebcc
0x7fffffffe0e0: 0x00007fffffffebe1  0x00007fffffffebec
0x7fffffffe0f0: 0x00007fffffffebfd  0x00007fffffffec27
0x7fffffffe100: 0x00007fffffffec42  0x00007fffffffec56
0x7fffffffe110: 0x00007fffffffec60  0x00007fffffffec71
0x7fffffffe120: 0x00007fffffffec88  0x00007fffffffecbc
0x7fffffffe130: 0x00007fffffffecc8  0x00007fffffffecd1
0x7fffffffe140: 0x00007fffffffece5  0x00007fffffffeced
0x7fffffffe150: 0x00007fffffffecff  0x00007fffffffed0e
0x7fffffffe160: 0x00007fffffffed33  0x00007fffffffed51
0x7fffffffe170: 0x00007fffffffed6c  0x00007fffffffed7e
---Type <return> to continue, or q <return> to quit---q
Quit

最佳答案

我不确定你从哪里得到的参数被压入堆栈。当然,有些论点是,但不是你的情况。四个参数,全部为 64 位或更小,在寄存器中传递。

您在堆栈上看到的参数不是传递给 function_1 的参数。它们是传递给 function 的参数,存储在堆栈中,因此它可以将它们传递给 function_1。根据证据,我假设您在此处进行编译而没有进行优化,否则您根本看不到任何函数调用。

我相信您的其他误解可以立即得到解决。

关于C 堆栈帧跟踪,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37638037/

相关文章:

c - Eclipse C/C++ (CDT) 添加 -l 选项(链接数学模块)gcc -lm

编译器错误 : "Expected ;" error in C struct

android - 使用 Cygwin 创建 .SO 文件时出错

c - 将结构写入二进制文件,然后读取文件并打印数据。

linux - KDE 登录屏幕上预填的用户名存储在哪里

c - Linux 中无效的信号处理库

C 程序问题 "pointer being freed was not allocated"

linux - xargs -0 产生新行

linux - 在 make 文件中正常分配和导出分配之间的区别

visual-studio-2008 - 使用 VS 2008 和 GCC 时对 __VA_ARGS__ 不同处理的问题