在运行的进程中添加执行系统调用

本文介绍了如何使用ptrace跟踪目标进程,注入代码并执行系统调用。通过结合/proc/PID/maps和/proc/PID/mem文件,使用pread和pwrite系统调用来修改目标进程的内存,实现代码注入。文章详细讲解了注入代码的过程,包括选择代码执行位置、写入系统调用指令以及恢复现场。
摘要由CSDN通过智能技术生成

导语:

相信大家对GDB都不陌生,GDB原理也能说个一二,什么ptrace、调试寄存器等说的头头是道,也有很多朋友用ptrace亲手实现过简单的gdb调试功能。今天就让我用一种简单的方式,在目标进程添加一个系统调用并执行。

需要解决的问题有:


  • 如何跟踪目标进程;
  • 如何注入代码;
  • 输入什么代码;
  • 如何让目标进程执行注入的代码;
  • 如何恢复现场;

如何跟踪目标进程 - ptrace

#include <sys/ptrace.h>
long ptrace(enum __ptrace_request request, pid_t pid,
           void *addr, void *data);

从ptrace函数声明看出,需要我们传入一个请求枚举值,我们要用到的是:

PTRACE_ATTACH - 跟踪一个进程,被跟踪进程将会因此停止运行
PTRACE_GETREGS - 获取被跟踪进程所有寄存器信息
PTRACE_SETREGS - 设置被跟踪进程所有寄存器信息
PTRACE_CONT - 使被跟踪进程继续运行
PTRACE_DETACH - 取消跟踪目标进程

如何注入代码


为了简单,我们只是简单的注入一个系统调用,所以需要写入的东西并不多,可以使用当前进程现有的地址空间已经映射的内存区域,比如说libc开始映射的位置(其实这个位置并不重要,随便一个代码段就可以),但需要注意的是,在替换代码->执行代码这两步结束后,别忘了最后一步,将原始代码替换回去。

那么如何注入代码呢?

我们看两个系统调用:

#include <unistd.h>
ssize_t pread(int fd, void *buf, size_t count, off_t offset);
ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset);

再看两个proc文件系统下的文件/proc/PID/mem和/proc/PID/maps。

将上面两个proc文件和两个系统调用结合起来,就可以访问和修改目标进程的内存。

/proc/PID/maps


这个文件大家比较熟悉了,先看看他长啥样:

上面每一部分都是一个非常重要的知识点,比如:vDSO、vsyscall、vvar等,这个文件保存了一个进程镜像的布局,通过展现每个内存映射来实现,熟悉内核的朋友可能很熟悉VMA,没错,上面的每一行都是一个VMA结构(关于内核VMA本文当然也不介绍,内容太多泰国庞杂)。

这里先简单提一嘴,我们可以选地址范围为7fc0530b2000-7fc0530de000的libc的vma作为在目标进程执行系统调用的“中转”,也就是说,每次我们想要在目标进程中执行一个系统调用时,先将这个libc的vma对应的大小的内存保存起来,然后将程序写入这个vma起始位置,然后跳转到那个位置执行,最后,将第一步保存的代码写回到这个vma对应位置。

/proc/PID/mem


这个文件怎么解释呢?不好解释,还是看内核代码吧!

首先,每个进程都有一个/proc/PID/mem文件,在内核源码中,定位到代码 fs/proc/base.c,在创建新的进程时候,都会创建一个新的/proc/PID/mem文件。

REG("mem",        S_IRUSR|S_IWUSR, proc_mem_operations),

对应的操作符(只关注打开,读,写):

static int mem_open(struct inode *inode, struct file *file)
{
  int ret = __mem_open(inode, file, PTRACE_MODE_ATTACH);

  /* OK to pass negative loff_t, we can catch out-of-range */
  file->f_mode |= FMODE_UNSIGNED_OFFSET;

  return ret;
}

static ssize_t mem_read(struct file *file, char __user *buf,
      size_t count, loff_t *ppos)
{
  return mem_rw(file, buf, count, ppos, 0);
}

static ssize_t mem_write(struct file *file, const char __user 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值