如何将代码植入已知java进程id(pid)并执行?
自jdk 1.6以来,java提供一种java进程间通信的技术.此技术可以实现将任意代码通过代理方式植入到正在运行的jvm中并执行.
注意: attach相关技术被封装在JAVA_HOME/lib/tools.jar这个jar包中,默认情况下这个jar不被加载再jdk的classpath路径中.
需要我们自己手动将其添加到当前classpath.
开始:
1. 准备一个能够一直运行的java程序运行并获取其pid.(获取java进程pid方式:在cmd控制台输入"jps -l" 指令得出对应pid)
2. 新建一个attach-util 的java项目,同时引入javassist相关依赖.
(1) 新建一个AgentUtil类 (该类是attach代理执行注入代码的类),实现这个方法:public static void agentmain(String args, Instrumentation inst)
其中"com.vdata.attach.AgentUtil" 是完整的类名,根据实际情况自己修改包名,类名等.
3. 写一个带有main函数的类:
总结: 此技术出发点是让外面的进程能够很好的监视jvm的内存情况,但是也是存在安全性的技术.比如:
可以注入任意代码到正在执行的java进程.
可以将正在运行的java程序中的全部Class输出到磁盘,进行反编译得到全部源码.
可以植入后门木马.
可以copy java程序中的数据.
....
自jdk 1.6以来,java提供一种java进程间通信的技术.此技术可以实现将任意代码通过代理方式植入到正在运行的jvm中并执行.
注意: attach相关技术被封装在JAVA_HOME/lib/tools.jar这个jar包中,默认情况下这个jar不被加载再jdk的classpath路径中.
需要我们自己手动将其添加到当前classpath.
开始:
1. 准备一个能够一直运行的java程序运行并获取其pid.(获取java进程pid方式:在cmd控制台输入"jps -l" 指令得出对应pid)
**
* 死循环测试程序,保证进程不结束。
* @author xiaoming
*/
public class WhileTrueTest {
public static void main(String[] args) {
System.out.println("死循环测试...");
while(true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
2. 新建一个attach-util 的java项目,同时引入javassist相关依赖.
(1) 新建一个AgentUtil类 (该类是attach代理执行注入代码的类),实现这个方法:public static void agentmain(String args, Instrumentation inst)
import java.lang.instrument.Instrumentation;
import java.lang.reflect.Method;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.CtNewMethod;
public class AgentUtil {
public static void agentmain(String args, Instrumentation inst) // 这个方法必须这么写,否则无法执行注入
{
// 使用java ssist技术向 tem添加一个自定义方法(植入方法)
try {
ClassPool classPool = ClassPool.getDefault();
CtClass ctClass = classPool.makeClass("ExcutJavaCode$tem01");
// 创建一个Method对象temMethod.
StringBuilder sb = new StringBuilder();
sb.append("public void run(){");
sb.append(" System.exit(0);"); // 让目标进程结束
sb.append("}");
CtMethod temMethod = CtNewMethod.make(sb.toString(), ctClass);
// 把方法注入到ctClass中
ctClass.addMethod(temMethod);
// 反射执行temMethod方法.
Class objClass = ctClass.toClass();// 获取java的Class对象
Object obj = objClass.newInstance();
objClass.getMethod("run", null).invoke(obj);
} catch (Exception e) {
e.printStackTrace();
}
}
}
(2) 将attach-util项目打成jar包.随后打开attach-util在 MANIFEST.MF 文件中添加
Agent-Class: com.vdata.attach.AgentUtil
注意: 次步骤必须做,否则无法执行attach注入.其中"com.vdata.attach.AgentUtil" 是完整的类名,根据实际情况自己修改包名,类名等.
3. 写一个带有main函数的类:
public class Main {
public static void main(String[] args) throws Exception {
VirtualMachine vm = VirtualMachine.attach("4572");// "4572" 是目标java进程pid
vm.loadAgent("C:\\test\\attach-util.jar", "hello");// "C:\\test\\attach-util.jar" 是第2步骤生成的attach-util.jar完整路径 "hello"是其他参数(可以通过此参数传入各种数据)
//vm.detach(); // 该方法是使ttach-util.jar脱离目标进程,此实验目的是让对方进程结束,所以此步骤每意义.
}
}
总结: 此技术出发点是让外面的进程能够很好的监视jvm的内存情况,但是也是存在安全性的技术.比如:
可以注入任意代码到正在执行的java进程.
可以将正在运行的java程序中的全部Class输出到磁盘,进行反编译得到全部源码.
可以植入后门木马.
可以copy java程序中的数据.
....