I have the following Array of bytes:
?? ?? 00 00 ?? ?? 00 00 ?? ?? 00 00 ?? ?? 00 00 F1 FF FF FF ?? 00 00 00 0? 00 00 00 ?? 00 00 00 0? 00 00 00 0? 00 00 00 00 ?? ?? 47
I have implemented a java code that finds the pattern to retrieve its address. However, my method is extremely slow and takes up to minutes to find a matching pattern. The way how my code works is as follows (I'm using jna library):
1- dump/retrieve 2048 bytes.
2- search for the pattern using boyer-moore algorithm in the 2048 bytes.
3- retrieve the next 2048 bytes and apply the boyer-moore algorithm (repeats until a matching pattern is found)
3- once the pattern is found, give me the address.
Code snippet:
public void setTimeAddress() {
String pattern;
for (long i = 0x01000000; i <= 0x040000000; i += 2048) {
pattern = readMemory(process, i, 2048).dump();
if (search(pattern.toCharArray())) {
address = i - shift;
System.out.println(address);
break;
}
}
}
private Memory readMemory(Pointer process, long address, int bytesToRead) {
IntByReference read = new IntByReference(0);
Memory output = new Memory(bytesToRead);
kernel32.ReadProcessMemory(process, address, output, bytesToRead, read);
return output;
}
Can someone recommend a faster/effiecient way of implementing this?
Every time you cross the Java/Native barrier you incur some latency. The way you've structured your code, you're doing multiple unnecessary reads.
You are creating a new Memory()
object each time in the loop. This has some minor overhead on the Java side (creating a new object and allocating heap memory for it, but you are also allocating native memory of the same size, that you will never use! You can improve your code significantly by allocating a single object once and then repeatedly reading the native memory into the same object's Java-side memory. (You could also pull the IntByReference()
initialization out of the loop as well as that's another native 4-byte allocation that you're wasting each iteration.)
As another point, you are incurring overhead translating the block of memory into an array of characters by means of a formatted String that you send to your search function. I'm not sure how you've written your search()
function, but I do know the output of dump()
is going to require a lot more manipulation of characters in a hex string and handling carriage returns, and is probably less efficient than simple numerical comparison of bytes. I'd strongly recommend reading a byte[]
array from the retrieved memory and then running your algorithm against those bytes.
Finally, is there a reason you've chosen 2048 as the size to read? You'll have fewer Java/Native reads if you can grab a bigger chunk at a time. I'd recommend at least 4096, the usual memory page size, or multiples of 4096.