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.
source to share
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.
source to share