追踪进程的写入内存。

6

我正在尝试使用Linux中的ptrace。我正尝试使用/proc/pid/mem接口写入被跟踪进程的内存。

我用于完成此任务的函数是:

void write_proc(pid_t child, unsigned long int addr) {

  char mem_file_name[100];
  char buf[10]="hope";
  int mem_fd;


  memset( (void*)mem_file_name, 0, 100);
  memset( (void *)buf, 0, 10);

  sprintf(mem_file_name, "/proc/%d/mem", child);
  mem_fd = open(mem_file_name, O_RDONLY);
  lseek(mem_fd, addr , SEEK_SET);

  if (write(mem_fd, buf, 5) < 0 )
    perror("Writing");

  return;

}

但是我总是会遇到错误:写入:坏的文件描述符。

使用这种方法编写跟踪进程是否可行?


你为什么要问这个问题?你使用ptrace的用例是什么? - Basile Starynkevitch
2个回答

4

您正在以只读模式(O_RDONLY)打开文件。建议尝试改用 O_RDWR

  mem_fd = open(mem_file_name, O_RDWR);

然而,从man proc中并不清楚这将起作用:
   /proc/[pid]/mem
          This  file can be used to access the pages of a process's memory
          through open(2), read(2), and lseek(2).

编辑:

我也很好奇,所以我使用直接的ptrace()构建了这个示例:

#include <sys/ptrace.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

#define SHOW(call) ({ int _ret = (int)(call); printf("%s -> %d\n", #call, _ret); if (_ret < 0) { perror(NULL); }})

char changeme[] = "This is  a test";

int main (void)
{
  pid_t pid = fork();
  int ret;
  int i;
  union {
    char cdata[8];
    int64_t data;
  } u = { "Hijacked" };

  switch (pid) {
  case 0: /* child */
    sleep(1);
    printf("Message: %s\n", changeme);
    exit(0);

  case -1:
    perror("fork");
    exit(1);
    break;

  default: /* parent */
    SHOW(ptrace(PTRACE_ATTACH, pid, 0, 0));
    SHOW(ptrace(PTRACE_POKEDATA, pid, changeme, u.data));
    SHOW(ptrace(PTRACE_CONT, pid, 0, 0));
    wait(NULL);
    break;
  }

  return 0;
}

我不确定它是否有效...也许使用mmap映射该文件会更好...但是,在打开时需要O_RDWR(但对于/proc/*pid/mem可能无效...我不知道...) - Basile Starynkevitch
3
你是正确的。唯一的问题是我在只读模式下打开了文件。复制和粘贴是大多数错误的源泉...哈哈哈! 谢谢! 然而,PTRACE_POKEDATA不是一个好的解决方案,你每次只能写入4个(x32)或8个(x64)。 这个问题的最佳解决方案是:http://man7.org/linux/man-pages/man2/process_vm_readv.2.html。 - Giuseppe Pes

2

ptrace(2)是一种非常奥秘的系统调用,仅由调试器等工具使用。

当被跟踪的进程停止时,文档中记录的PTRACE_POKEDATA请求到ptrace应该可以工作,并且使您能够写入被跟踪进程的内存。我不知道是否可以写入(或mmap/proc/$pid/mem

在谷歌上搜索linux write /proc /mem,我发现特别有这篇文章,其中建议/proc/$pid/mem被设计成只读的,但最近的内核可能已经将其变为可写的。但最近的内核源码树中的Documentation/filesystems/proc.txt没有提供太多信息。

我会小心地在/proc/$pid/mem上进行写操作;如果它可以工作(并且可能不行),那么它很可能与内核版本有关。

也许/proc/$pid/mem文件的一些段可以使用mmap(但我不确定)。您试过了吗?

相比之下,PTRACE_POKEDATA应该可以工作(在Linux出现之前,它已经存在于SunOS和许多其他Unix中)。当然,它相当慢。


1
Ptrace_POKEDATA提供了传输数据的低带宽。当你说要小心使用这种方法时,你是正确的。这种方法存在一些混淆,因为当写入被跟踪进程的内存的可能性被引入内核中时,就会出现错误。有关更多信息,请查看此链接: http://lwn.net/Articles/476947/ - Giuseppe Pes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接