Read/write /proc/<pid>/mem from java code on Android platform

2.2k views Asked by At

I want to read and write memory from ptaced child process (/proc/pid/mem) on Android. Before read/write i attached to process using ptrace (Status=4991, WIFSTOPPED(Status)=true).

int lSize = (int) (pAddressEnd - pAddressStart);
ByteBuffer lByteBuffer = ByteBuffer.allocate(lSize);
RandomAccessFile lRandomAccessFile = null;
try {
    lRandomAccessFile = new RandomAccessFile(mFileName, "r");
    lRandomAccessFile.getChannel().read(lByteBuffer, pAddressStart);

    lRandomAccessFile.close();
} catch (FileNotFoundException e) {
    throw new RuntimeException(e);
} catch (IOException e) {
    throw new RuntimeException(e);
}
...

Sometimes memory access passes correctly, but sometimes it throw exception:

java.lang.RuntimeException: java.io.IOException: pread failed: EIO (I/O error)
        ...
        at java.lang.Thread.run(Thread.java:841)
Caused by: java.io.IOException: pread failed: EIO (I/O error)
        at java.nio.FileChannelImpl.readImpl(FileChannelImpl.java:315)
        at java.nio.FileChannelImpl.read(FileChannelImpl.java:283)
        at test.Process$Mem.readByteBuffer(Process.java:285)
        ... 33 more
Caused by: libcore.io.ErrnoException: pread failed: EIO (I/O error)
        at libcore.io.Posix.preadBytes(Native Method)
        at libcore.io.Posix.pread(Posix.java:99)
        at libcore.io.BlockGuardOs.pread(BlockGuardOs.java:124)
        at java.nio.FileChannelImpl.readImpl(FileChannelImpl.java:305)
        ... 35 more

Attempt to write memory always throw exception.

Can I use the method RandomAccessFile.getChannel().read() for reading a memory? And RandomAccessFile.getChannel().write() for writing memory? How use it correct?

1

There are 1 answers

1
David Given On BEST ANSWER

You'll get EIO when trying to read from memory which the child process doesn't have mapped --- for example, anything around NULL. That's perfectly normal. (See the mem man page for more information.) So if you're following broken pointers in the child's address space, you need to be able to handle this.

If you're getting an IO error when you expect the child process' memory to actually exist, that's a bit weirder. There may be some odd interaction between /dev/X/mem and ptrace when the child process is stopped. I would suggest investigating PTRACE_PEEKDATA as an alternative way to read the child process' memory. It's much slower but potentially more reliable --- if /dev/X/mem fails, try PTRACE_PEEKDATA and see what it says. I'm assuming you have Java bindings for ptrace.