Address of a local variable on the stack

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

and ran the program.

#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;
}

      

Since the breakpoint is set on a line exploit = (long long *)&exploit+2;

, GDB stops program execution before executing that line, which means that only the line long long *exploit;

that yields was executed exploit

.

At this point, I expected exploit

to be at the top of the stack, because the only local variable and local variables remain at the top of the stack after the function call (correct me if I'm wrong). It turns out that this is 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, the top of the element 0x7fffffffdff0

, and the exploit address is 8 bytes above the stack pointer (above? How can this be?) In 0x7fffffffdfe8

. Can someone explain this 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

is at the top of the stack (as I predicted it would be), the next 8 bytes below exploit

will be RBP, followed by the return address of the instruction in the __libc_start_main () function (The which sets the environment for the program to run, calls main (), and then clears mess after execution).

exploit = (long long *)&exploit+2;

will shift and force the exploit to specify the return address I mentioned and *exploit = (long long)Shellcode;

will overwrite the return address with the address Shellcode

. Since Shellcode

these are opcodes with preprocessed instructions and can be read by the processor, it will execute after the program finishes executing and tries to return to __libc_start_main () using the return address, provided DEP is off.

+3


source to share


1 answer


The SYS V ABI introduced a number of optimizations, including (as Jester noted ) the Red Zone - an area of ​​128 bytes below 1 stack pointer that is not touched by any asynchronous handler.
In the case of a leaf function, the compiler can use the Red Zone to store local variables without moving rsp

.




1 Note that you are using the reverse terminology for the above and below stack pointers.

+3


source







All Articles