JNA

时间:2015-08-02 21:09:16

标签: java jna

我正在编写一个游戏黑客,它使用内存操作来工作,并决定用Java进行FUD方面的操作(原生黑客几乎可以立即被检测到)。

我有这个方法从windows调用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); 有时执行约0-5 + ms

KERNEL32.ReadProcessMemory(process, address, output, bytesToRead, 0); 执行时也需要大约0-5 + ms。

读取它的程序每个周期调用这些方法大约1k次(16ms周期)。

编辑:我写了一个基本的测试类来测试5000次调用的时间

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;
}

}

是否还有其他方法可以执行readMemory方法,以便执行所有5000次调用所需的时间少于32ms?

2 个答案:

答案 0 :(得分:2)

你想在32ms内完成5000次通话。这大约是每通话6便士。你能用纯C代码(不涉及Java)吗?你能用原始的JNI做到吗?如果没有,试图让它与JNA一起工作没有多大意义。您不仅需要进行数据传输,还需要一些时间来处理数据。

Memory只是一个malloc'ed内存块的J​​ava表示,可以在GC上释放。预分配所需的不同块的数量,或创建直接NIO缓冲区(这可能允许更有效地调整本机后备内存)。

预分配后,请确保您使用直接映射,然后再次进行配置文件以查看您花时间的位置。

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);
}

使用long取代Pointer,而不是YMMV,可能获得一些收益,并始终衡量增加复杂性的影响。

答案 1 :(得分:1)

首先,我总是用C / C ++编写内存处理。但是如果您需要在Java中进行,我会考虑创建一个内存实例并将其作为参数传递,这将避免堆构造/处理例程。

类似的东西:

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;
}

类似的东西 - 不确定您是否有权修改内存大小,但理想情况下,它可以创建容纳所有结果的存储空间,并设置每次调用实际存储的数量。这应该避免代价高昂的堆工作。

相关问题