Kernel32.INSTANCE.ReadProcessMemory REALLY Slow In JNA

半世苍凉 提交于 2020-01-02 11:43:16

问题


I'm writing a game hack which uses memory manipulation to work and decided to do it in Java for the FUD aspect (native hacks can be detected almost immediatly).

I have this method which reads a memory object from the windows call ReadProcessMemory

public static Memory readMemory(Pointer process, long address, int bytesToRead) {
    Memory output = new Memory(bytesToRead);
    KERNEL32.ReadProcessMemory(process, address, output, bytesToRead, 0);
    return output;
}

Memory output = new Memory(bytesToRead); Takes about 0-5+ms to execute sometimes

KERNEL32.ReadProcessMemory(process, address, output, bytesToRead, 0); Takes about 0-5+ms as well to execute.

The program that reads this calls these methods about 1k times per cycle (16ms cycles).

Edit: I wrote a basic test class to test how long 5000 calls would be

public final class Test {
public static final int AMOUNT_OF_CALLS = 5000;

public static void main(String[] args) throws InterruptedException {
    long start = System.currentTimeMillis();
    for (int i = 0; i < AMOUNT_OF_CALLS; i++) {
        Memory m = readMemory(new Pointer(1), 0xFFFFFFF, ThreadLocalRandom.current().nextInt(1, 8)); //Random between a byte read, or long
        m.dispose();
    }
    System.out.println("Took " + (System.currentTimeMillis() - start) + "ms todo " + AMOUNT_OF_CALLS + " readMemory calls.");
}

public static Memory readMemory(Pointer process, long address, int bytesToRead) {
    Memory output = new Memory(bytesToRead);
    Kernel32.INSTANCE.ReadProcessMemory(process, address, output, bytesToRead, 0);
    return output;
}

}

Is there any other way of doing the readMemory method so that it takes less than 32ms to execute all 5000calls?


回答1:


You want to do 5000 calls in 32ms. That's roughly 6us per call. Can you do that in pure C code (no Java involved)? Can you do that in raw JNI? If not, there's not much point in trying to get it to work with JNA. Not only do you have to do the data transfer, but you need some time to do processing of that data.

Memory is just a Java representation of a malloc'ed chunk of memory that gets freed on GC. Pre-allocate the number of different blocks that you need, or create a direct NIO buffer (which may allow tweaks to the native backing memory more efficiently).

After pre-allocation, make sure you're using direct mapping, then profile again to see where you're spending time.

public class MyKernel32 {
    static { Native.register(NativeLibrary.getInstance("kernel32", W32APIOptions.DEFAULT_OPTIONS)); }
    public static native long ReadProcessMemory(HANDLE process, long address, Pointer buffer, int size, IntByReference numRead);
}

You might get some gains by using long in place of Pointer, but YMMV, and always measure the effects of added complexity.




回答2:


Firstly, I would always write memory handling in C/C++. But if you need to do it in Java, I would consider Creating one memory instance and pass it as a parameter, this will avoid the heap construction/disposal routines.

Something like:

public static void main(String[] args) throws InterruptedException {
    long start = System.currentTimeMillis();
    final Memory output = new Memory(8);
    for (int i = 0; i < AMOUNT_OF_CALLS; i++) {
        Memory m = readMemory(new Pointer(1), 0xFFFFFFF, ThreadLocalRandom.current().nextInt(1, 8), memory); //Random between a byte read, or long
    }
    System.out.println("Took " + (System.currentTimeMillis() - start) + "ms todo " + AMOUNT_OF_CALLS + " readMemory calls.");
}

public static Memory readMemory(Pointer process, long address, int bytesToRead, final Memory output) {
    output.setSize( bytesToRead ) ;
    KERNEL32.ReadProcessMemory(process, address, output, bytesToRead, 0);
    return output;
}

Something like that - not sure if you have access to modify the Memory size or not, but ideally it could create storage that will accommodate all your results and you set the amount actually stored for each call. This should avoid costly heap work.



来源:https://stackoverflow.com/questions/31776620/kernel32-instance-readprocessmemory-really-slow-in-jna

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!