Search code examples
javamemoryjna

JNA Invalid memory access When Running With 32bit JVM


Hello I recently ran into an issue with a JNA program I am writing.

If I run the following code with a 64bit JVM it runs fun:

public final class UWot {

    public static void main(String[] args) {
        final int size = 4;

        GameProcess process = Processes.get("csgo.exe");

        ByteBuffer buff = Buffers.allocate(size).order(ByteOrder.nativeOrder());
        Kernel32Direct.ReadProcessMemory(process.handle().getPointer(), 0x178832cc, buff, size, 0);

        System.out.println(buff.getInt());
    }

}

But if I run the same code with a 32bit JVM I get the following error:

Exception in thread "main" java.lang.Error: Invalid memory access
at baro.natives.Kernel32Direct.ReadProcessMemory(Native Method)
at temp.hi.main(UWot.java:20)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)

Here is my read process memory method:

public final class Kernel32Direct {

    public static native int ReadProcessMemory(Pointer process, long address, ByteBuffer memory, int size, int written);

    static {
        Native.register(NativeLibrary.getInstance("Kernel32", W32APIOptions.UNICODE_OPTIONS));
    }

}

Edit so it turns out the 32bit jvm was trying to use Kernel32 which is a 64bit library since I'm using a 64bit os and they don't agree with each other.

So the new question is, could it be possible via JNA direct mapping to specify to use a 32bit kernel32 (in syswow64) if they are running with a 32bit JVM, or use the 64bit kernel32 (in system32) if they are using 64bit JVM?


Solution

  • I fixed this issue myself by changing address from long to Pointer. I assume it's due to the long size difference between Java and C

    Changed:

       public static native int ReadProcessMemory(Pointer process, long address, ByteBuffer memory, int size, int written);
    

    To:

       public static native boolean ReadProcessMemory(Pointer process, Pointer address, ByteBuffer memory, int size, int written);