Address of local variable on stack

I wrote a little C code, opened it in GDB, put a breakpoint on line exploit = (long long *)&exploit+2; and run the program.

#include<stdio.h>

char Shellcode[] = "x48xc7xc0x01x00x00x00"
                   "x48xc7xc3x1ax00x00x00"
                   "xcdx80";

int main()
{
        long long *exploit;
        exploit = (long long *)&exploit+2;
        *exploit = (long long)Shellcode;
        return 0;
}

Since the breakpoint is set on line exploit = (long long *)&exploit+2; , GDB stops the execution of program before executing that line and it'd mean that only the line long long *exploit; , which brings exploit into existence has been executed.

At this point I was expecting exploit to reside on the top of the stack because it's the only local variable and local variables stay on the top of stack after calling a function(Please correct me if I'm wrong). Turns out it's not the case.

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

As we can see that the top of the element is 0x7fffffffdff0 while the address of exploit is 8 bytes above the stack pointer(Above? How could it be?) at 0x7fffffffdfe8 . Can someone explain it to me?

Edit:

disassembling the main function gives:

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: What does this code do?

If the variable exploit resides at the top of stack(as I predicted it to be), the next 8 bytes below exploit would be RBP followed by the return address of an instruction in __libc_start_main() function(The function that sets up environment for execution of program, calls main(), and then cleans up the mess after execution).

exploit = (long long *)&exploit+2; would shift and make the exploit to point the return address I mentioned and *exploit = (long long)Shellcode; would overwrite the return address with the address of Shellcode . Since the Shellcode is opcodes of pre-examined instructions and is readable by the processor, it'd be executed once the program finishes executing and tries to get back to __libc_start_main() using the return address, provided that the DEP is turned off.


The SYS V ABI introduced a number of optimisations, including (as Jester pointed out) the Red zone - a 128 bytes area below1 the stack pointer that is not touched by any asynchronous handler.
In the case of a leaf function, the compiler can use the Red zone for storing the local variables without moving rsp .


1 Note that you appear to use the inverse terminology for what is "above" and "below" the stack pointer.

链接地址: http://www.djcxy.com/p/80368.html

上一篇: 函数局部变量如何从堆栈中访问?

下一篇: 堆栈上局部变量的地址