Search code examples
javajvmreverse-engineeringheap-memoryjdi

Java: Method hooking & Finding object instances


Situation

Hi, I have 2 problems.
The situation is that I'm writing a Java API for Windows that also provides tools for injecting code into a process and then manipulate the target. I have already implemented the injection-part, for example injecting a jar into another jar. At this point my jar gets called (while the target already is at runtime) and starts in a complete static context.

Goals & problems

From here I have two goals:

  1. I'd like to interact with the targets objects, thus I need references. For many objects this is already possible because they provide static access to their instances. For example awt.Frames#getFrames() provides access to all created Frame objects. But it would be awesome if there is a possibility to get access to arbitrary objects on the heap. Something like 'Heap#getAllObjectInstances()'.
  2. Given an object instance, I'd like to hook up onto arbitrary functions of this object. For example whenever BufferStrategy#show() gets called, I want it to call another method first.

So I summarize the problems as follows:

  1. How to get arbitrary object references from a static context?
  2. How to hook up onto arbitrary functions?

Remarks

What I've done so far, remarks and ideas:

  1. The JDI (Java Debugger Interface) provides such a method via VirtualMachine#allClasses() -> ReferenceType#instances(0). But the JDI needs the target JVM to be started with additional debug parameter which is no option for me. One could go down to low-level and analyze the heap with memory tools, but I hope someone knows a more high-level approach. Using the Windows API would be an option for me as I'm familiar with JNA/JNI, but I don't know such a tool.
  2. The last resort would be to use IAT hooking with C-Code, a very low-level approach, I'd like to avoid this. As I can assume having a object reference at this point, maybe does the Reflection API provide a method to change an objects method? Or at least simply provide a hooking mechanism?

Be aware that changing the targeted code certainly is no option for me. And that it is already at runtime, thus ByteCode-Manipulation could also be an option.

Scenario

A scenario where this would come in handy:
The target is a game, deployed as jar. It renders with a Double-Buffer-Strategy, using the BufferStrategy class. It displays the image with BufferStrategy#show(). We inject our jar inside the game and like to draw an overlay with additional information. For this we get an reference to the used BufferStrategy and hook up onto its show-method. So that it calls our drawOverlay-method everytime it gets called, then we pass back to the original show-method.


Solution

  • What you need is JVMTI agent - a native library that makes use of JVM Tool Interface.

    Agents can be attached dynamically to a running VM using the Attach API.
    See VirtualMachine.loadAgentPath.

    1. To get all instances of a given class use JVMTI IterateOverInstancesOfClass function.
      See the related question for details.

    2. To intercept a method of a foreign class you'll need JVMTI RetransformClasses API. The same can be also achieved by using Java-level instrumentation API, see Instrumentation.retransformClasses.

    For the example of JVMTI-level method interception refer to demo/jvmti/mtrace from Oracle JDK demos and samples package.

    Java-level instrumentation will be easier with bytecode manipulation libraries like Byte Buddy.