copagent主要用于内存马查杀。
1.生成agent.jar

2.将其拷贝进入cop的resources文件夹中

3.生成cop.jar

将刚才的agent.jar,拷贝到resrouces文件夹。

打包jar

1.cop
注入进程jvm进程
2.agent
扫描进程
1.启动cop.jar
1.1 释放agent.jar
1.2.再次启动cop.jar进程,进入到cop模块的注入流程
- //解析参数
- try {
- Options options = new Options();
- options.addOption("h", "help", false, "print options information");
- options.addOption("v", "version", false, "print the version of copagent");
- options.addOption("p", "pid", true, "attach jvm process pid");
- options.addOption("c", "class", true, "class name regex to dump");
-
- CommandLineParser parser = new DefaultParser();
- CommandLine cmdLine = parser.parse(options, args);
-
- if (cmdLine.hasOption("version")) {
- AnsiLog.info("Version : " + version_info.get("Project-Version") + "\nBuild Time: " + version_info.get("Build-Time") + "\n");
- System.exit(0);
- } else if (cmdLine.hasOption("help")) {
- new HelpFormatter().printHelp("java -jar copagent.jar", options, true);
- System.exit(0);
- }
- if(cmdLine.hasOption("class")){
- filterClassName = cmdLine.getOptionValue("class");
- }
- if (cmdLine.hasOption("pid")) {
- String input_pid = cmdLine.getOptionValue("pid");
- pid = Long.parseLong(input_pid);
- jvm_pid = Long.toString(pid);
- }
- else {
- AnsiLog.info( AnsiLog.red("Version") + " : " + AnsiLog.yellow(version_info.get("Project-Version")));
- AnsiLog.info(AnsiLog.red("Build Time")+ " : " + AnsiLog.yellow(version_info.get("Build-Time")));
-
- // select jvm process pid
- try {
- pid = ProcessUtils.select(false, -1, null);
- } catch (InputMismatchException e) {
- AnsiLog.warn("Please input an integer to select pid.");
- System.exit(1);
- }
- if (pid < 0) {
- AnsiLog.error("Please select an available pid.");
- System.exit(1);
- }
- jvm_pid = Long.toString(pid);
- }
- } catch (Throwable e) {
- AnsiLog.error("Failed to parse options\n" + e.getMessage());
- System.exit(0);
- }
-
- // 释放agent.jar流程
- if(! agent_work_directory.exists()){
- if(! PathUtils.createDirectory(agent_work_directory)){
- AnsiLog.warn("Create directory {} failed, use {}", agent_work_directory.getAbsolutePath(), PathUtils.getTempDirectory().getAbsolutePath());
- agent_work_directory = PathUtils.getTempDirectory();
- }
- }
-
- attach_jar_path = new File(agent_work_directory, "agent.jar").getAbsolutePath();
-
- //从自身jar包资源,释放agent.jar
- if(! new File(attach_jar_path).exists()){
- PathUtils.copyResources("/agent.jar", new File(attach_jar_path));
-
- if(! new File(attach_jar_path).exists()){
- AnsiLog.error("Create agent.jar file [{}] failed !", attach_jar_path);
- System.exit(1);
- }
- }
-
- /*
- * java <opts> -jar cop.jar <pid> </path/to/agent.jar> <dumpClassName>
- * */
- List<String> opts = new ArrayList<String>();
- opts.add("-jar");
- opts.add(current_jar_path);
- opts.add(jvm_pid);
- opts.add(attach_jar_path);
- opts.add(filterClassName);
-
- // real start cop.jar process
- ProcessUtils.startProcess(pid, opts);
- }
启动进程参数列表如下:
其中-Xbootclasspath表示搜索类路径,之后会启动agent.jar包,传递pid,需要注入的agent.jar路径,不扫描的排出类,boot_flag表示开启注入功能
0 = "C:\Program Files\Java\jdk1.8.0_301\jre\..\bin\java.exe"
1 = "-Xbootclasspath/a:C:\Program Files\Java\jdk1.8.0_301\jre\..\lib\tools.jar"
2 = "-jar"
3 = "C:\Users\test\Desktop\copagent-master\cop\target\agent.jar"
4 = "12228"
5 = "C:\Users\test\Desktop\copagent-master\cop\target\.copagent\agent.jar"
6 = "[unknown]"
7 = "bootstart_flag"
3.注入agent.jar进入JVM进程,上述步骤
- if(is_boot_start || is_greater_than_jre9 ){
- //注入流程
- jvm_pid = args[0];
- attach_jar_path = args[1];
- if(args.length >= 3){
- filterClassName = args[2];
- }
- AnsiLog.info("Try to attach process " + jvm_pid + ", please wait a moment ...");
-
- attach(jvm_pid, attach_jar_path, filterClassName);
-
- AnsiLog.info("Attach process {} finished .", jvm_pid);
- AnsiLog.info("Result store in : {}", new File(agent_work_directory, "result.txt"));
- System.exit(0);
- }else{
注入代码 如下
- public static void attach(String jvm_pid, String agent_jar_path, String filterClass) throws Exception{
- VirtualMachine virtualMachine = null;
- VirtualMachineDescriptor virtualMachineDescriptor = null;
- for (VirtualMachineDescriptor descriptor : VirtualMachine.list()) {
- String pid = descriptor.id();
- if (pid.equals(jvm_pid)) {
- virtualMachineDescriptor = descriptor;
- break;
- }
- }
- try{
- if (null == virtualMachineDescriptor) {
- virtualMachine = VirtualMachine.attach(jvm_pid);
- } else {
- virtualMachine = VirtualMachine.attach(virtualMachineDescriptor);
- }
- Properties targetSystemProperties = virtualMachine.getSystemProperties();
- String targetJavaVersion = JavaVersionUtils.javaVersionStr(targetSystemProperties);
- String currentJavaVersion = JavaVersionUtils.javaVersionStr();
- if (targetJavaVersion != null && currentJavaVersion != null) {
- if (!targetJavaVersion.equals(currentJavaVersion)) {
- AnsiLog.warn("Current VM java version: {} do not match target VM java version: {}, attach may fail.", currentJavaVersion, targetJavaVersion);
- AnsiLog.warn("Target VM JAVA_HOME is {}, copagent JAVA_HOME is {}, try to set the same JAVA_HOME.", targetSystemProperties.getProperty("java.home"), System.getProperty("java.home"));
- }
- }
- virtualMachine.loadAgent(agent_jar_path, filterClass);
- }catch (Throwable t){
- t.printStackTrace();
- } finally {
- if (null != virtualMachine) {
- virtualMachine.detach();
- }
- }
- }
通过下列两个API函数来完成java agent的加载
VirtualMachine.attach()
virtualMachine.loadAgent(agent_jar_path, filterClass);