Search code examples
javalinuxjna

Java JNA Read Process Memory Linux


I'm trying to make a Java library to read/write memory values to processes on linux.

Every time I read a value, ptrace returns -1, and I read a different int everytime.

Here is my main class code:

public final class Main {

public static void main(String... args) {
    // 10702 ?        00:00:00 idea.sh
    Memory buffer = new Memory(4);
    System.out.println(ptrace.ptrace(1, 10702, new Pointer(0x7f1f80e81fb8L), buffer));
    System.out.println(buffer.getInt(0));
}

}

That outputs:

-1
2014720320

Here is my ptrace class:

public class ptrace {

static {
    Native.register(NativeLibrary.getInstance("c"));
}

public static native long ptrace(/*enum __ptrace_request*/ int request,
                           /*pid_t*/ int pid,
                                 Pointer addr,
                                 Pointer data);
}

Can anyone tell me why it fails to read the value at that Pointer?


Solution

  • You need to "attach" the running process to be able to read/write and be root as well when it's not your process (PTRACE_TRACEME).

    E.g :

    main:

    //@see http://linux.die.net/include/sys/ptrace.h
    private static final int PTRACE_PEEKDATA = 2;
    private static final int PTRACE_ATTACH = 16;
    private static final int PTRACE_DETACH = 17;
    
    public static void main(String[] args) {
        int pid = 1015;
    
        try {
            ptrace.ptrace(PTRACE_ATTACH, pid, null, null);
            Memory buffer = new Memory(4);
            ptrace.ptrace(PTRACE_PEEKDATA, pid, new Pointer(0x7f27d6575000L), buffer);
            System.out.println(buffer.getChar(0));
        } catch (LastErrorException ex) {
            ex.printStackTrace();
        } finally {
            ptrace.ptrace(PTRACE_DETACH, pid, null, null);
        }
    

    ptrace.java :

    public class ptrace {
    
        static {
            Native.register(NativeLibrary.getInstance("c"));
        }
    
        public static native long ptrace(/*enum __ptrace_request*/int request,
                /*pid_t*/ int pid,
                Pointer addr,
                Pointer data) throws LastErrorException;
    }
    

    You can found more info on how to use ptrace here

    LastErrorException is here just to get "errno". You can use ̀Native.getLastError() instead of Exception.

    StackTace E.g:

    com.sun.jna.LastErrorException: [1] (
    at cg.ptrace.ptrace(Native Method)
    at cg.Cg.main(Cg.java:123)

    shell :

    $ errno 1
    EPERM 1 Operation not permitted