Ret2shellcode

当bss段没有足够权限时,可以使用mprotect来修改权限

因为需要在一次溢出中利用多个函数,所以要找到gadgetspop esi;pop edi;pop ebp;ret;

payload布局为:

mprotect函数+pop *;ret+参数1\2\3+返回地址[read函数]+pop *;ret+参数1\2\3+返回地址[shellcode_addr]

Ret2syscall

能找到四个寄存器eax,ebx,ecx,edx和ret地址int 0x80可以直接使用
好处:可以不用泄露libc,一步直达shell

Ret2libc

32位

可以不用释放寄存器,因为靠近call的就是第一个参数,以此类推,所以栈结构应为
str+system+返回地址+参数1+[参数2]

64位

分别在rdi,rsi,rdx,rcx,r8,r9中存放参数,所以在调用完函数后要找到对应pop *;ret的代码片段来保持栈平衡,结构应为
str+pop rdi;ret+参数+system+返回地址
(当找不到足够的pop *;ret时,可以使用ret2csu的方式来构造payload)

call 指令与 ret 的区别

call指令:

  1. 先把下一句指令的地址压入栈顶 rsp+=8
  2. 跳转到call后面跟的地址上去

ret指令:

  1. 跳转到esp/rsp所指的地址(之前的call压入的)

  2. esp/rsp-=8

32位的payload之所以返回地址在倒数第二个上面,是因为system函数使用完后参数不用再pop,也就不会ret,而没有这个ret的话,esp指向的地址就不会-8,而是+8 所以才要把返回的地址放到system参数的后面
而64,因为当system函数执行完,在返回到函数的入口点之前要pop掉各寄存器,并且要在后面跟上ret,以便用ret直接跳转到rsp(返回地址)上,这也就是为什么64位的返回地址要放到最后面的原因。
好处:只要能泄露libc就可以拿到shell

ret2csu

能找到pop rdi,rsi,rdx;ret的代码片段就可以直接构造payload,栈结构为
str+G1+8+rbx+rbp+r12+r13+r14+r15+G2+56*A+返回地址