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
首先通过溢出把一堆数据写在栈上,此时返回地址覆盖为 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
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 //
栈迁移一般用于栈溢出的溢出长度不够,只能进行栈迁移
esp | addr2 |
addr1 | |
ebp | addr3 |
重新 leave ret:
esp = ebp
ebp = addr3
栈的基址地址就是addr3了
mov esp ebp
pop ebp
ret
leave == mov esp,ebp_;pop ebp;_ret == pop eip #弹出栈顶数据给eip寄存器