栈上局部变量的地址

Posted

技术标签:

【中文标题】栈上局部变量的地址【英文标题】:Address of local variable on stack 【发布时间】:2018-01-15 20:42:17 【问题描述】:

我写了一点 C 代码,在 GDB 中打开,在exploit = (long long *)&exploit+2; 行下断点,然后运行程序。

#include<stdio.h>

char Shellcode[] = "\x48\xc7\xc0\x01\x00\x00\x00"
                   "\x48\xc7\xc3\x1a\x00\x00\x00"
                   "\xcd\x80";

int main()

        long long *exploit;
        exploit = (long long *)&exploit+2;
        *exploit = (long long)Shellcode;
        return 0;

由于断点设置在exploit = (long long *)&amp;exploit+2;行,GDB在执行该行之前停止程序的执行,这意味着只有long long *exploit;行已被执行,这使得exploit存在。

此时我期望exploit 驻留在堆栈顶部,因为它是唯一的局部变量,并且局部变量在调用函数后仍留在堆栈顶部(如果我错了,请纠正我)。事实证明并非如此。

(gdb) print /x &exploit 
$2 = 0x7fffffffdfe8
(gdb) x/6xg $rsp
0x7fffffffdff0: 0x0000555555554690      0x00007ffff7a5a2b1
0x7fffffffe000: 0x0000000000040000      0x00007fffffffe0d8
0x7fffffffe010: 0x00000001f7b9b288      0x0000555555554660

我们可以看到元素的顶部是0x7fffffffdff0,而exploit的地址在0x7fffffffdfe8的堆栈指针上方8个字节(上面?怎么可能?)。谁能给我解释一下?

编辑:

反汇编main函数给出:

0x555555554660 <main>           push   %rbp                                                                                                                         │
   │0x555555554661 <main+1>         mov    %rsp,%rbp                                                                                                                    │
B+>│0x555555554664 <main+4>         lea    -0x8(%rbp),%rax                                                                                                              │
   │0x555555554668 <main+8>         add    $0x10,%rax                                                                                                                   │
   │0x55555555466c <main+12>        mov    %rax,-0x8(%rbp)                                                                                                              │
   │0x555555554670 <main+16>        mov    -0x8(%rbp),%rax                                                                                                              │
   │0x555555554674 <main+20>        lea    0x2009b5(%rip),%rdx        # 0x555555755030 <Shellcode>                                                                      │
   │0x55555555467b <main+27>        mov    %rdx,(%rax)                                                                                                                  │
   │0x55555555467e <main+30>        mov    $0x0,%eax                                                                                                                    │
   │0x555555554683 <main+35>        pop    %rbp                                                                                                                         │
   │0x555555554684 <main+36>        retq

Edit-2:这段代码有什么作用?

如果变量exploit 位于栈顶(正如我所预测的那样),那么exploit 下面的接下来的8 个字节将是RBP,后跟__libc_start_main() 函数中指令的返回地址(The设置程序执行环境的函数,调用main(),然后在执行后清理混乱)。

exploit = (long long *)&amp;exploit+2; 会转移并使漏洞利用指向我提到的返回地址,*exploit = (long long)Shellcode; 会用Shellcode 的地址覆盖返回地址。由于Shellcode 是预先检查的指令的操作码并且可由处理器读取,因此一旦程序完成执行并尝试使用返回地址返回到 __libc_start_main() 就会执行它,前提是 DEP 已关闭.

【问题讨论】:

C 语言对堆栈一无所知。您的堆栈如何工作取决于架构。你说的是哪种架构? 现在您可以看到您的变量位于 [RBP]-8 即预期地址。 也许因为你没有调用任何其他函数,优化器移除了堆栈指针的增加(和减少)。 sysv abi提供了一个128字节的红色区域,无需调整堆栈指针即可使用。 没有“按计划”,因为程序包含多个未定义行为的情况。 【参考方案1】:

SYS V ABI 引入了许多优化,包括(如Jester pointed out)Red zone - 1 堆栈指针下方的 128 字节区域,任何异步处理程序都不会触及。 在叶函数的情况下,编译器可以使用红色区域来存储局部变量,而无需移动rsp


1 请注意,您似乎对堆栈指针的“上方”和“下方”使用了相反的术语。

【讨论】:

感谢您指出这些链接。我在寻找资源而不是实际答案。 :)

以上是关于栈上局部变量的地址的主要内容,如果未能解决你的问题,请参考以下文章

static的用法,全局变量与局部变量

Java 变量类型

Java变量类型

java语言中,类的成员变量分配在哪个内存区?

JAVA_01

静态变量全局变量和局部变量