栈溢出攻击系列:shellcode在linux x86 64位攻击获得root权限(一)函数如何执行

栈溢出网上已经有很多的例子了,但是很少会涉及到在64位的和操作系统linux相关的,而最近刚好在一直研究这个,所以写着一系列博文,一来是为了帮助自己记忆,二来也是为了更多的大家互相探讨。

寄存器

X86-64有16个64位寄存器,分别是:%rax,%rbx,%rcx,%rdx,%esi,%edi,%rbp,%rsp,%r8,%r9,%r10,%r11,%r12,%r13,%r14,%r15。其中:
%rax 作为函数返回值使用
%rsp 栈指针寄存器,指向栈顶
%rdi,%rsi,%rdx,%rcx,%r8,%r9 用作函数参数,依次对应第1参数,第2参数,第3参数 一一匹配

%rbx,%rbp,%r12,%r13,%14,%15 用作数据存储,callee-save 调用子函数前要保存到栈中

%r10,%r11  用作数据存储 caller-save 调用前要先保存原值到栈中


栈的结构

这是32位的栈地址布局。, 32位和64位的区别主要在于寄存器的区别,原来ebp esp 指针寄存器 编程rbp, rsp

返回的地址 
上一个栈的地址<--rbp
参数n 
...  
参数1<--rsp

3个重要的指针寄存器 rbp, rsp, rip 

前提:现在函数A调用函数B

rbp: 当前函数栈B的起始位置

rsp: 当前函数栈B的底位置

rip: 当前执行到函数的地址位置

函数的进入和返回

3个汇编指令

1. call address

这个指令很简单,就是调用函数的地址

push %rip 把rip的地址保存进栈中,实际上就是当前运行到的地址

jmp address  把下个调用函数的地址给rip

上上一个栈的起始地址<--rbp
上一个栈的参数n 
...  
上一个栈的参数1 
上一个栈的rip的值 
 <--rsp

而保存rbp的值是在进入函数后push %rsp 实现的。


2. leaveq

指令相当于

move %rbp %rsp 把rsp指针指向rbp

pop %rbp  把栈里值赋予rbp, 同时rsp指向上一个地址,也就是rsp现在指向栈结构图中的 返回的地址

上上一个栈的运行到的地址 
上上一个栈的起始地址<--rbp
上一个栈的参数n 
... 
上一个栈参数1 
上一个栈的运行到的地址<--rsp
上一个栈的起始地址 
参数n 
... 
参数1 


3. ret

指令相当于

pop %rip 把返回的地址赋予rip, rsp 指向上一个地址

上上一个栈的运行到的地址 
上上一个栈的起始地址<--rbp
上一个栈的参数n 
... 
上一个栈参数1<--rsp
上一个栈的运行到的地址 
上一个栈的起始地址 
参数n 
... 
参数1 

通过3后,大家可以看到整个函数完成退出,而栈指针也回到了调用函数的栈中。这样完整的函数调用就完成了,也完成了进栈出栈的过程。



  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值