Note that there are some explanatory texts on larger screens.

plurals
  1. POIO Error when reading /proc/$pid/mem after ptrace
    primarykey
    data
    text
    <p>I'm writing a program to replace a string of bytes in the memory of another process. It needs to be written in C, as my target platform doesn't support any higher level languages. </p> <p>Initially, rather than jumping straight to memory modification, I'm simply trying to read memory into a buffer, so that I can identify the offset at which the string of bytes resides, such that I can then start to modify it. </p> <p>I've read every stack overflow question and code example I can find, alongside man pages and some general trial and error. My C is a little rusty, and so this is proving rather challenging. The examples I've read seem to take two differing approaches:</p> <ul> <li>ptrace_attatch to the target process, use multiple calls to ptrace_peekdata to read (int) sized chunks of memory from offset.</li> </ul> <p>or</p> <ul> <li>ptrace_attatch, open /proc/pid/mem, and use the offsets outlined in /proc/pid/maps to lseek and read() out a given number of bytes.</li> </ul> <p>Here's my code.</p> <p>program to attatch to:</p> <pre><code>#include &lt;stdio.h&gt; int main(int argc, char *argv[]){ printf("Spinning up....\n"); char changeme[6] = "AAAAA"; printf("ready for change....\n"); getchar(); printf("changeme is %s\n", changeme); return 0; } </code></pre> <p>program for dumping memory:</p> <pre><code>#include &lt;stdio.h&gt; #include &lt;stdlib.h&gt; #include &lt;string.h&gt; #include &lt;sys/ptrace.h&gt; #include &lt;sys/types.h&gt; #include &lt;sys/wait.h&gt; #include &lt;sys/user.h&gt; #include &lt;sys/syscall.h&gt; #include &lt;unistd.h&gt; #include &lt;limits.h&gt; #include &lt;stdint.h&gt; #include &lt;fcntl.h&gt; #include &lt;wait.h&gt; #include &lt;errno.h&gt; int main(int argc, char *argv[]){ char mempath[PATH_MAX]; uintptr_t const address = strtoul(argv[2], NULL, 0); int waitval = 0; pid_t target_process = atoi(argv[1]); struct user_regs_struct regs; int readbytes = 0; if (ptrace(PTRACE_ATTACH,target_process,NULL,NULL)) perror("attach"); printf("attatched!\n"); waitpid(target_process, NULL, 0); sprintf(mempath, "/proc/%s/mem", argv[1]); printf("ready! opening %s\n", mempath); int memfd = open(mempath, O_RDONLY); printf("memfd = %d\n", memfd); char *outbuf = malloc(_SC_PAGE_SIZE); printf("trying to read %d bytes from offset %lu\n",_SC_PAGE_SIZE,address); if (outbuf){ lseek(memfd, address, SEEK_SET); readbytes = read(memfd, outbuf, _SC_PAGE_SIZE); if (_SC_PAGE_SIZE == readbytes) printf("read success! - %s\n", outbuf); else printf("readfailed! read %d bytes: %s\n", readbytes, outbuf); printf("oh noes! %s\n", strerror(errno)); free(outbuf); } return 0; } </code></pre> <p>And the terminal output:</p> <p>terminal 1:</p> <pre><code>[10:59] tel0s@Relentless:~/research$ ./changeme Spinning up.... ready for change.... </code></pre> <p>terminal 2:</p> <pre><code>[11:35] tel0s@Relentless:~/research$ ps aux | grep changeme tel0s 7763 0.0 0.0 4076 352 pts/2 S+ 10:59 0:00 ./changeme tel0s 8297 0.0 0.0 8948 928 pts/1 S+ 11:35 0:00 grep --colour=auto changeme [11:35] tel0s@Relentless:~/research$ cat /proc/7763/maps 00400000-00401000 r-xp 00000000 fd:00 2260791 /home/tel0s/research/changeme 00600000-00601000 r--p 00000000 fd:00 2260791 /home/tel0s/research/changeme 00601000-00602000 rw-p 00001000 fd:00 2260791 /home/tel0s/research/changeme 7fb2cfc56000-7fb2cfdf7000 r-xp 00000000 fd:00 4890420 /lib64/libc-2.17.so 7fb2cfdf7000-7fb2cfff6000 ---p 001a1000 fd:00 4890420 /lib64/libc-2.17.so 7fb2cfff6000-7fb2cfffa000 r--p 001a0000 fd:00 4890420 /lib64/libc-2.17.so 7fb2cfffa000-7fb2cfffc000 rw-p 001a4000 fd:00 4890420 /lib64/libc-2.17.so 7fb2cfffc000-7fb2d0000000 rw-p 00000000 00:00 0 7fb2d0000000-7fb2d0022000 r-xp 00000000 fd:00 4888842 /lib64/ld-2.17.so 7fb2d01f2000-7fb2d01f5000 rw-p 00000000 00:00 0 7fb2d021e000-7fb2d0221000 rw-p 00000000 00:00 0 7fb2d0221000-7fb2d0222000 r--p 00021000 fd:00 4888842 /lib64/ld-2.17.so 7fb2d0222000-7fb2d0223000 rw-p 00022000 fd:00 4888842 /lib64/ld-2.17.so 7fb2d0223000-7fb2d0224000 rw-p 00000000 00:00 0 7fff03290000-7fff032b1000 rw-p 00000000 00:00 0 [stack] 7fff03394000-7fff03395000 r-xp 00000000 00:00 0 [vdso] ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall] [11:36] tel0s@Relentless:~/research$ sudo ./writeprocmem 7763 400000 attatched! ready! opening /proc/7763/mem memfd = 3 trying to read 30 bytes from offset 400000 readfailed! read -1 bytes: oh noes! Input/output error </code></pre> <p>My immediate thoughts for possible reasons are:</p> <ul> <li>I've totally borked my logic, and I'm not using Ptrace correctly.</li> <li>My changeme program is in a strange state because of gets() and that's why im failing to read (I tried with an instance of bash, and i had the same output however)</li> <li>I'm not casting/using the right type for my offsets, and that's why the read is failing</li> </ul> <p>Any help would be excellent, and I'd rather answers outlined what mistakes I'm making, rather than just giving me working code outright, as I want to understand this fundamentally, not just make my code functional.</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload