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上一篇: 函数局部变量如何从堆栈中访问?
下一篇: 堆栈上局部变量的地址