天天看点

向任意java进程植入任意java代码(以kill目标java进程为例)

如何将代码植入已知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)

**
 * 死循环测试程序,保证进程不结束。
 * @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程序中的数据.

      ....