put函数的调用:

payload = padding+pop_rdi(put参数存在rdi寄存器中, 64位)+put_got_addr(寻找libc)+put_plt_addr(调用puts 函数)+ret_addr

Write函数调用

payload = padding+write_plt+ret_addr+IO_put(标准输出,1)+write_got_addr(输出的目标)+env(4)

System函数调用

payload = padding+system_addr+ret_addr+bin_sh_str

ret2cus

栈利用 - 图1

首先通过溢出把一堆数据写在栈上,此时返回地址覆盖为 gadgets1,调用 gaegets1 的时候 rsp+8 通过 gadgets1 把栈上的数据写在寄存器里面,同时把 rsp 再加一下让程序返回到 gadgets2

gadgets2 会把之前寄存器上存的数据放在需要的寄存器上(参数存放顺序:RDI, RSI, RDX, RCX, R8 和 R9)

把 write 函数需要的参数部署好之后通过 call (r12+rbx*8) 之前把 rbx 设置成了 0,当程序执行完 write 函数以后会自己回到这里(因为是 call,正常调用)所以不用管返回地址,继续执行,此时还会执行 gadgets1 上面那张图那样子,gadgets1 里面有一段 add rsp,38h 所以还要填充 38h 个字节把这一段填充掉,使得程序返回的时候是我们写在栈上的 main_addr

ret2cus

SYSCALL

32位:
  传参方式:首先将系统调用号 传入 eax,然后将参数 从左到右 依次存入 ebx,ecx,edx寄存器中,返回值存在eax寄存器
  调用号:sys_read 的调用号 为 3 sys_write 的调用号 为 4
  调用方式: 使用 int 80h 中断进行系统调用
64位:
  传参方式:首先将系统调用号 传入 rax,然后将参数 从左到右 依次存入 rdi,rsi,rdx寄存器中,返回值存在rax寄存器
  调用号:sys_read 的调用号 为 0 sys_write 的调用号 为 1
  stub_execve 的调用号 为 59 stub_rt_sigreturn 的调用号 为 15
  调用方式: 使用 syscall 进行系统调用
$rax==59
$rdi==“/bin/sh”
$rsi==0
$rdx==0
syscall
**

printf

64位调用
$rdi = fmt_str
$r15 = 0
$rsi = 数值
**

栈迁移

leave ret指令:
mov esp sbp
pop ebp //

栈利用 - 图2

栈迁移一般用于栈溢出的溢出长度不够,只能进行栈迁移


esp addr2
addr1
ebp addr3

重新 leave ret:
esp = ebp
ebp = addr3

栈的基址地址就是addr3了

mov esp ebp
栈利用 - 图3

pop ebp
栈利用 - 图4

ret
栈利用 - 图5

leave == mov esp,ebp_;pop ebp;_ret == pop eip #弹出栈顶数据给eip寄存器