Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Writing memory of the traced process.

I am playing around with ptrace in linux. I am trying to write the memory of the traced process using /proc/pid/mem interface.

the function I ma using for accomplish this task is :

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;

}

But I always get the error : Writing: Bad file descriptor.

Is it possible to write the traced process using this method?

like image 638
Giuseppe Pes Avatar asked Mar 23 '13 10:03

Giuseppe Pes


2 Answers

You are opening the file in read-only mode (O_RDONLY). I'd suggest trying again with O_RDWR instead:

  mem_fd = open(mem_file_name, O_RDWR);

However, from man proc it's not clear this will work:

   /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).

EDIT:

I was curious too, so I put together this example using just ptrace() directly:

#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;
}
like image 191
FatalError Avatar answered Oct 22 '22 13:10

FatalError


ptrace(2) is a very arcane syscall, only used by debuggers and the like.

For sure, the documented PTRACE_POKEDATA request to ptrace should work (when the traced process is stopped) and gives you the ability to write into the memory of the traced process. I don't know if writing (or mmap-ing) to /proc/$pid/mem should work or not.

Googling on linux write /proc /mem give me notably this which suggests that /proc/$pid/mem was designed to be read-only, but might have been made writable in recent kernels. But recent Documentation/filesystems/proc.txt from kernel source tree don't say much.

I would be cautious about writing on /proc/$pid/mem; if it works (and it might not) it probably is very kernel version specific.

Perhaps mmap-ing some segments of that /proc/$pid/mem file does work (but I don't know). Have you tried that?

In contrast, PTRACE_POKEDATA should work (it has existed in SunOS and many other Unixes before Linux existed). Of course, it is fairly slow.

like image 42
Basile Starynkevitch Avatar answered Oct 22 '22 14:10

Basile Starynkevitch