我正在编写一个游戏黑客,它使用内存操作来工作,并决定用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?
答案 0 :(得分:2)
你想在32ms内完成5000次通话。这大约是每通话6便士。你能用纯C
代码(不涉及Java)吗?你能用原始的JNI做到吗?如果没有,试图让它与JNA一起工作没有多大意义。您不仅需要进行数据传输,还需要一些时间来处理数据。
Memory
只是一个malloc
'ed内存块的Java表示,可以在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;
}
类似的东西 - 不确定您是否有权修改内存大小,但理想情况下,它可以创建容纳所有结果的存储空间,并设置每次调用实际存储的数量。这应该避免代价高昂的堆工作。