1

情况

你好,我有2个问题。
情况是我正在为 Windows 编写一个 Java API,它还提供了将代码注入进程然后操作目标的工具。我已经实现了injection-part,例如将一个 jar 注入另一个 jar。此时我的 jar 被调用(而目标已经在运行时)并在一个完整的静态上下文中启动。

目标和问题

从这里我有两个目标:

  1. 我想与目标对象交互,因此我需要引用。对于许多对象来说,这已经成为可能,因为它们提供对其实例的静态访问。例如awt.Frames#getFrames()提供对所有创建的 Frame 对象的访问。但是如果有可能访问堆上的任意对象,那就太棒了。类似“ Heap#getAllObjectInstances() ”的东西。
  2. 给定一个对象实例,我想连接到该对象的任意函数。例如,每当调用BufferStrategy#show()时,我希望它首先调用另一个方法。

所以我将问题总结如下:

  1. 如何从静态上下文中获取任意对象引用?
  2. 如何连接任意函数?

评论

到目前为止我所做的,评论和想法:

  1. JDI (Java 调试器接口)通过VirtualMachine#allClasses() -> ReferenceType#instances(0)提供了这样的方法。但是 JDI 需要使用额外的调试参数来启动目标 JVM ,这对我来说是没有选择的。可以深入到低级别并使用内存工具分析堆,但我希望有人知道更高级的方法。使用 Windows API 对我来说是一种选择,因为我熟悉JNA/JNI,但我不知道这样的工具。
  2. 最后的手段是使用IAT与 C 代码挂钩,这是一种非常低级的方法,我想避免这种. 我可以假设此时有一个对象引用,也许反射 API是否提供了一种更改对象方​​法的方法?或者至少简单地提供一个挂钩机制?

请注意,更改目标代码当然不是我的选择。并且它已经在运行时,因此 ByteCode-Manipulation 也可能是一种选择。

设想

这会派上用场的场景:
目标是一个游戏,部署为 jar。它使用BufferStrategy类以Double-Buffer-Strategy呈现。它使用BufferStrategy#show()显示图像。我们将我们的 jar 注入到游戏中,并喜欢绘制带有附加信息的叠加层。为此,我们获得了对使用过的BufferStrategy的引用并连接到它的show方法。这样每次调用时它都会调用我们的 drawOverlay 方法,然后我们传回原始的show-method

4

1 回答 1

4

您需要的是 JVMTI 代理 - 一个使用JVM 工具接口的本机库。

可以使用Attach API 将代理动态附加到正在运行的 VM 。
请参阅VirtualMachine.loadAgentPath

  1. 要获取给定类的所有实例,请使用 JVMTI IterateOverInstancesOfClass函数。
    有关详细信息,请参阅相关问题

  2. 要拦截外部类的方法,您需要 JVMTI RetransformClasses API。同样可以通过使用 Java 级别的检测 API 来实现,请参阅Instrumentation.retransformClasses

JVMTI 级别的方法拦截示例参考demo/jvmti/mtraceOracle JDK demos and samples 包。

使用Byte Buddy之类的字节码操作库,Java 级别的检测将更容易。

于 2016-06-27T00:21:17.770 回答