局部变量在栈上的地址
Address of local variable on stack
我写了一点 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 *)&exploit+2;
,GDB 在执行该行之前停止程序的执行,这意味着只有行 long long *exploit;
,它带来 exploit
into existence 已执行。
此时我期望 exploit
驻留在栈顶,因为它是唯一的局部变量,并且局部变量在调用函数后留在栈顶(如果我'我错了)。事实并非如此。
(gdb) print /x &exploit
= 0x7fffffffdfe8
(gdb) x/6xg $rsp
0x7fffffffdff0: 0x0000555555554690 0x00007ffff7a5a2b1
0x7fffffffe000: 0x0000000000040000 0x00007fffffffe0d8
0x7fffffffe010: 0x00000001f7b9b288 0x0000555555554660
我们可以看到元素的顶部是0x7fffffffdff0
,而漏洞利用的地址是堆栈指针上方8个字节(在上面?怎么可能?)在0x7fffffffdfe8
。有人可以给我解释一下吗?
编辑:
反汇编主要功能给出:
0x555555554660 <main> push %rbp │
│0x555555554661 <main+1> mov %rsp,%rbp │
B+>│0x555555554664 <main+4> lea -0x8(%rbp),%rax │
│0x555555554668 <main+8> add [=12=]x10,%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 [=12=]x0,%eax │
│0x555555554683 <main+35> pop %rbp │
│0x555555554684 <main+36> retq
Edit-2:这段代码是做什么的?
如果变量 exploit
位于栈顶(正如我预测的那样),exploit
下面接下来的 8 个字节将是 RBP,然后是 return 地址__libc_start_main()函数中的一条指令(该函数为程序的执行设置环境,调用main(),然后在执行后清理混乱)。
exploit = (long long *)&exploit+2;
会转移并利用漏洞指向我提到的 return 地址,而 *exploit = (long long)Shellcode;
会用 [=24= 的地址覆盖 return 地址].由于 Shellcode
是预检指令的操作码并且可由处理器读取,一旦程序完成执行并尝试使用 [=50= 返回 __libc_start_main() ] 地址,前提是 DEP 已关闭。
我写了一点 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 *)&exploit+2;
,GDB 在执行该行之前停止程序的执行,这意味着只有行 long long *exploit;
,它带来 exploit
into existence 已执行。
此时我期望 exploit
驻留在栈顶,因为它是唯一的局部变量,并且局部变量在调用函数后留在栈顶(如果我'我错了)。事实并非如此。
(gdb) print /x &exploit
= 0x7fffffffdfe8
(gdb) x/6xg $rsp
0x7fffffffdff0: 0x0000555555554690 0x00007ffff7a5a2b1
0x7fffffffe000: 0x0000000000040000 0x00007fffffffe0d8
0x7fffffffe010: 0x00000001f7b9b288 0x0000555555554660
我们可以看到元素的顶部是0x7fffffffdff0
,而漏洞利用的地址是堆栈指针上方8个字节(在上面?怎么可能?)在0x7fffffffdfe8
。有人可以给我解释一下吗?
编辑:
反汇编主要功能给出:
0x555555554660 <main> push %rbp │
│0x555555554661 <main+1> mov %rsp,%rbp │
B+>│0x555555554664 <main+4> lea -0x8(%rbp),%rax │
│0x555555554668 <main+8> add [=12=]x10,%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 [=12=]x0,%eax │
│0x555555554683 <main+35> pop %rbp │
│0x555555554684 <main+36> retq
Edit-2:这段代码是做什么的?
如果变量 exploit
位于栈顶(正如我预测的那样),exploit
下面接下来的 8 个字节将是 RBP,然后是 return 地址__libc_start_main()函数中的一条指令(该函数为程序的执行设置环境,调用main(),然后在执行后清理混乱)。
exploit = (long long *)&exploit+2;
会转移并利用漏洞指向我提到的 return 地址,而 *exploit = (long long)Shellcode;
会用 [=24= 的地址覆盖 return 地址].由于 Shellcode
是预检指令的操作码并且可由处理器读取,一旦程序完成执行并尝试使用 [=50= 返回 __libc_start_main() ] 地址,前提是 DEP 已关闭。