我想学习如何创建一个可注入的java字节码片段,并将其注入已编译的java程序中,以便在执行所述程序时运行。 它不必是动态的,并且在运行时,只要给定编译的java程序注入额外的代码。
现在,我知道有很多现有的工具,比如Javassist和ASM。但是这个行为本身并不是我的目标,我想知道它是如何完成的,所以我想学习如何在没有这些工具的情况下 。
例如:如何从源字节码中删除多余的代码,将其注入目标代码等等。
最好的答案是一个或多个简单的源代码或伪代码。 在学习并成功完成此操作之后,我将开始搜索有关如何对Linux可执行二进制文件执行此操作的信息,因此以这种方式添加更多信息也将非常有用和赞赏。
答案 0 :(得分:2)
首先,Java类文件一旦加载就基本上是不可变的,所以你真正要问的是如何手动创建和修改类文件。
答案是阅读JVM规范。这就是我开始使用字节码的方法。阅读完规范之后,我在十六进制编辑器中手工编写了几个简单的类文件,然后用它来看看它是如何工作的。当然,这对于正常使用来说并不实用,所以后来我写了一个汇编程序。这并不难。
顺便说一下,the source code for my assembler只有大约1k行代码,因此排序比Javaassist少得多。
答案 1 :(得分:0)
通常,这是通过读取字节码(或Linux可执行文件),将其转换为某种形式的中间表示(IR),在IR上执行其他转换,并将其转换回原始格式来完成的。
如果将IR转换回Java源代码,您将获得Java的反编译器。如果您对IR执行分析,操作它(添加,删除,重写等)并将转换后的IR转换回字节码格式,您将得到您所描述的内容。
有关如何将字节码转换为IR的详细算法,请参阅http://suif.stanford.edu/~jwhaley/papers/mastersthesis.pdf的第3.3节和https://courses.cs.washington.edu/courses/cse501/01wi/project/sable-thesis.pdf的第3节
答案 2 :(得分:0)
Javassist本质上是反编译和编译代码,这就是为什么那里有很多代码的原因。 而且你不会在javassist中找到你正在寻找的类型代码注入。所以“Go read javassist”是一个相当愚蠢的建议。
如果要将代码放入特定位置(例如在start或构造函数中) 您可以通过阅读JVM文档来了解如何找到该位置。
然而正如锑提到的,你正在寻找字节码知识,所以这里是: http://arhipov.blogspot.com.au/2011/01/java-bytecode-fundamentals.html
如果要注入一段字节码,可以找到main()的开头并将代码粘贴到那里。它将是200-300 LOC MAX。
使用linux二进制文件会更容易,请阅读: http://www.skyfree.org/linux/references/ELF_Format.pdf