Find the answer to your Linux question:
Results 1 to 7 of 7
I was wondering if there's a way for a process to READ (not write to) the memory of another process? I've skimmed some stuff about shared memory, but it seems ...
Enjoy an ad free experience by logging in. Not a member yet? Register.
  1. #1
    Just Joined!
    Join Date
    Dec 2005
    Posts
    4

    Reading memory of other processes?


    I was wondering if there's a way for a process to READ (not write to) the memory of another process? I've skimmed some stuff about shared memory, but it seems that both processes have to agree to use the shared memory beforehand, which isn't what I want. Obviously, if I try to normally make a pointer to some protected memory, I get a segfault. Do I have to call some kernel function, or... I have no idea. Note that I *ONLY* want to read the memory, not set up a weird shared memory link or whatever. Sorry if I sound dumb.

    Thanks a lot in advance!

  2. #2
    Just Joined!
    Join Date
    Oct 2005
    Location
    Mass
    Posts
    52
    http://www.tldp.org/LDP/lpg/node33.h...40000000000000

    look at little close at the system v ipc .. you can set permissions to memory sections in much the same way

    you can also take a loot at reader semaphores.. those are useful.. kinda
    http://www.linuxjournal.com/node/5833/print

  3. #3
    Just Joined!
    Join Date
    Dec 2005
    Posts
    4
    Thank you very much, but I'm still stuck. I've now read a lot on IPC, message queues, semaphores and shared memory, but as far as I can tell, they all require both processes to agree to communicate beforehand. I'm writing more of an observer application, that'll read the memory of other processes without any agreement between them (as root, of course). There are some functions perfect for this in the Win32 API, such as ReadProcessMemory(), as demonstrated in this article. Is there anything as, well, convenient as that in Linux?

  4. #4
    Linux Guru
    Join Date
    Oct 2001
    Location
    Täby, Sweden
    Posts
    7,578
    The way to do this is with ptrace. I've written a short program to dump regions of memory from a process previously, so I'll just attach it here so that you can see how it works:
    Code:
    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <sys/ptrace.h>
    #include <errno.h>
    
    unsigned char buf[1024];
    
    int main(int argc, unsigned char **argv)
    {
        pid_t pid;
        unsigned long addr1, addr2;
        int buf;
        
        if(argc < 4)
        {
    	fprintf(stderr, "Not enough args\n");
    	return(1);
        }
        pid = strtol(argv[1], NULL, 0);
        addr1 = (unsigned long)strtoll(argv[2], NULL, 0);
        addr2 = (unsigned long)strtoll(argv[3], NULL, 0);
        if(ptrace(PTRACE_ATTACH, pid, NULL, NULL))
        {
    	perror("PTRACE_ATTACH");
    	return(1);
        }
        for(; addr1 < addr2; addr1 += sizeof(int))
        {
    	errno = 0;
    	if(((buf = ptrace(PTRACE_PEEKDATA, pid, (void *)addr1, NULL)) == -1) && errno)
    	{
    	    perror("PTRACE_PEEKDATA");
    	    if(ptrace(PTRACE_DETACH, pid, NULL, NULL))
    		perror("PTRACE_DETACH");
    	    return(1);
    	}
    	if(write(1, &buf, sizeof(buf)) != 4)
    	{
    	    perror("write");
    	    if(ptrace(PTRACE_DETACH, pid, NULL, NULL))
    		perror("PTRACE_DETACH");
    	    return(1);
    	}
        }
        if(ptrace(PTRACE_DETACH, pid, NULL, NULL))
        {
    	perror("PTRACE_DETACH");
    	return(1);
        }
        return(0);
    }
    It was a long time since I wrote it, so I don't really recall what I used it for anymore, but for example, you could use it to dump all the data sections of a process by calling it from a shell command like this:
    Code:
    grep rw-p /proc/$$/maps | sed -n 's/^\([0-9a-f]*\)-\([0-9a-f]*\) .*$/\1 \2/p' | while read start stop; do ~/src/utils/dumpmem $$ 0x$start 0x$stop >/tmp/mem$start; done
    Do keep in mind, however, that the algorithm for authorizing processes to ptrace other processes is quite complex, so don't be all too surprised if you get errors you don't expect. Read the manpage twice or thrice, and if that doesn't help, check the kernel source to see the exact algorithm.

  5. #5
    Just Joined!
    Join Date
    Dec 2005
    Posts
    4
    Thanks a lot, your code is awesome! But I just have a couple of questions:

    1) Why do you have <tt>unsigned char buf[1024]</tt>, when it seems to get overridden by <tt>int buf</tt> a few lines later? I deleted the first line and the program ran just fine.

    2) How come it only reads memory pages with rw-p permissions? I tried a few other permissions and it ran just fine as well. Are there some permissions settings that the app can't read?

    These may be stupid questions, but they're interesting to me. Thanks again for all your help.

  6. #6
    Just Joined!
    Join Date
    Dec 2005
    Posts
    4

    Cool

    Wait a minute... I did a bit of digging and found out that /proc/<PID>/maps actually contains the locations of memory-mapped files. This isn't quite what I wanted. What I meant was if a running program changes the value of one of its internal variables, I want to see that variable's value from an outside process (though not necessarily change it).

    But your ptrace thing gave me an idea: could I make another process the child of my process (using ptrace), and then tell it to make its entire memory a shared memory segment that my process could access? Or can my process access its child process' memory without it being explicitly shared? Is there a better solution? I'm just guessing here.

    Thanks again in advance!

  7. #7
    Linux Guru
    Join Date
    Oct 2001
    Location
    Täby, Sweden
    Posts
    7,578
    It seems that there is something you don't really understand. I'm going to take a few shots in the dark at explaining a few things, and see if that clears it up for you.

    In Linux, all memory in a process is memory-mapped files. The pages that malloc() uses (the heap) are simply mmapped from /dev/zero (actually, mmapping using MAP_ANONYMOUS, but that's just an alias for mmapping /dev/zero without actually having to open /dev/zero).

    Besides, I only used /proc/$pid/maps for the example using a shell command. You can specify perfectly arbitrary parameters without having to worry -- they don't need to match an entry in /proc/$pid/maps. It's just that if you don't read from an address that is listed in /proc/$pid/maps, there won't be any mapped memory to read anyway (as per the previous paragraph). If the actual child process would try to read from such an address, it would segfault. (Ptrace would just return EFAULT)

    If you'd like to read a variable from a process, you'll need to first find out where it is. A few qualified guesses are somewhere in either the file-mapped segment from the ELF file's .data segment, the heap, or the stack. Regardlessly, if you can just instruct your child process to send the address of the variable, you would just have to use that address when calling ptrace.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •