mirror of
https://github.com/frohoff/ysoserial.git
synced 2026-09-22 07:00:44 +08:00
refactors
This commit is contained in:
@@ -1,25 +0,0 @@
|
||||
name: Java CI
|
||||
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Set up JDK 1.8
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 1.8
|
||||
- name: Build with Maven
|
||||
run: mvn -B package --file pom.xml
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/[email protected]
|
||||
with:
|
||||
# Artifact name
|
||||
name: ysoserial
|
||||
# Directory containing files to upload
|
||||
path: /home/runner/work/ysoserial/ysoserial/target/
|
||||
@@ -2,10 +2,21 @@ package ysoserial;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
public class CiTest {
|
||||
@Test
|
||||
public void test() {
|
||||
System.out.println("System.getProperties(): " + System.getProperties());
|
||||
System.out.println("System.getenv(): " + System.getenv());
|
||||
for (Map.Entry<Object,Object> e : new TreeMap<Object,Object>(System.getProperties()).entrySet()) {
|
||||
System.out.println("System property " + e.getKey() + " : " + e.getValue());
|
||||
}
|
||||
for (Map.Entry<String,String> e : new TreeMap<String,String>(System.getenv()).entrySet()) {
|
||||
System.out.println("System env " + e.getKey() + " : " + e.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
new CiTest().test();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,9 +5,11 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
@@ -33,6 +35,7 @@ import ysoserial.payloads.annotation.Dependencies;
|
||||
import ysoserial.payloads.annotation.PayloadTest;
|
||||
import ysoserial.payloads.util.ClassFiles;
|
||||
import ysoserial.test.util.Logging;
|
||||
import ysoserial.test.util.OpenURLClassLoader;
|
||||
import ysoserial.test.util.PayloadListener;
|
||||
import ysoserial.test.util.StdIoRedirection;
|
||||
|
||||
@@ -71,7 +74,7 @@ public class PayloadsTest {
|
||||
}
|
||||
|
||||
|
||||
public static void testPayload ( final Class<? extends ObjectPayload<?>> payloadClass, final Class<?>[] addlClassesForClassLoader )
|
||||
public static void testPayload(final Class<? extends ObjectPayload<?>> payloadClass, final Class<?>[] addlClassesForClassLoader)
|
||||
throws Exception {
|
||||
System.out.println("Testing payload: " + payloadClass.getName());
|
||||
|
||||
@@ -140,11 +143,8 @@ public class PayloadsTest {
|
||||
}
|
||||
if (ex != null) throw ex;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static Callable<byte[]> makeSerializeCallable ( final Class<? extends ObjectPayload<?>> payloadClass, final String command ) {
|
||||
return new Callable<byte[]>() {
|
||||
|
||||
@@ -158,7 +158,6 @@ public class PayloadsTest {
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
private static Callable<Object> makeDeserializeCallable ( PayloadTest t, final Class<?>[] addlClassesForClassLoader, final String[] deps,
|
||||
final byte[] serialized, final Class<?> customDeserializer ) {
|
||||
return new Callable<Object>() {
|
||||
@@ -169,14 +168,12 @@ public class PayloadsTest {
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
private static boolean checkPrecondition ( Class<? extends ObjectPayload<?>> pc, String precondition )
|
||||
throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
|
||||
Method precondMethod = pc.getMethod(precondition);
|
||||
return (Boolean) precondMethod.invoke(null);
|
||||
}
|
||||
|
||||
|
||||
private static String[] buildDeps ( final Class<? extends ObjectPayload<?>> payloadClass ) throws Exception {
|
||||
String[] baseDeps;
|
||||
if ( DynamicDependencies.class.isAssignableFrom(payloadClass) ) {
|
||||
@@ -193,9 +190,52 @@ public class PayloadsTest {
|
||||
return baseDeps;
|
||||
}
|
||||
|
||||
|
||||
static Object deserializeWithDependencies ( byte[] serialized, final String[] dependencies, final Class<?>[] classDependencies, final Class<?> customDeserializer )
|
||||
static Object deserializeWithDependencies(byte[] serialized, final String[] dependencies, final Class<?>[] classDependencies, final Class<?> customDeserializer)
|
||||
throws Exception {
|
||||
URL[] urls = getDependencyUrls(dependencies);
|
||||
|
||||
Map<String, byte[]> addlClasses = new HashMap<String, byte[]>();
|
||||
|
||||
for ( Class<?> clazz : classDependencies ) {
|
||||
byte[] classAsBytes = ClassFiles.classAsBytes(clazz);
|
||||
addlClasses.put(clazz.getName(), classAsBytes);
|
||||
}
|
||||
addlClasses.put(Deserializer.class.getName(), ClassFiles.classAsBytes(Deserializer.class));
|
||||
|
||||
if (customDeserializer != null) {
|
||||
try {
|
||||
Method method = customDeserializer.getMethod("getExtraDependencies");
|
||||
for (Class extra : (Class[]) method.invoke(null)) {
|
||||
addlClasses.put(extra.getName(), ClassFiles.classAsBytes(extra));
|
||||
}
|
||||
} catch (NoSuchMethodException e) {}
|
||||
|
||||
addlClasses.put(customDeserializer.getName(), ClassFiles.classAsBytes(customDeserializer));
|
||||
}
|
||||
|
||||
OpenURLClassLoader isolatedClassLoader = new OpenURLClassLoader(urls, null);
|
||||
for (Map.Entry<String, byte[]> e : addlClasses.entrySet()) {
|
||||
isolatedClassLoader.defineNewClass(e.getKey(), e.getValue());
|
||||
}
|
||||
|
||||
Class<?> deserializerClass = isolatedClassLoader.loadClass(customDeserializer != null ? customDeserializer.getName() : Deserializer.class.getName());
|
||||
Callable<Object> deserializer = (Callable<Object>) deserializerClass.getConstructors()[0].newInstance(serialized);
|
||||
|
||||
// set CCL for Clojure https://groups.google.com/forum/#!topic/clojure/F3ERon6Fye0
|
||||
return callWithContextClassLoader(isolatedClassLoader, deserializer);
|
||||
}
|
||||
|
||||
private static Object callWithContextClassLoader(ClassLoader classLoader, Callable<Object> callable) throws Exception {
|
||||
ClassLoader ccl = Thread.currentThread().getContextClassLoader();
|
||||
Thread.currentThread().setContextClassLoader(classLoader);
|
||||
try {
|
||||
return callable.call();
|
||||
} finally {
|
||||
Thread.currentThread().setContextClassLoader(ccl);
|
||||
}
|
||||
}
|
||||
|
||||
private static URL[] getDependencyUrls(String[] dependencies) throws MalformedURLException {
|
||||
File[] jars = dependencies.length > 0
|
||||
? Maven.configureResolver()
|
||||
.withMavenCentralRepo(true)
|
||||
@@ -206,46 +246,7 @@ public class PayloadsTest {
|
||||
for ( int i = 0; i < jars.length; i++ ) {
|
||||
urls[ i ] = jars[ i ].toURI().toURL();
|
||||
}
|
||||
|
||||
URLClassLoader isolatedClassLoader = new URLClassLoader(urls, null) {
|
||||
|
||||
{
|
||||
for ( Class<?> clazz : classDependencies ) {
|
||||
byte[] classAsBytes = ClassFiles.classAsBytes(clazz);
|
||||
defineClass(clazz.getName(), classAsBytes, 0, classAsBytes.length);
|
||||
}
|
||||
byte[] deserializerClassBytes = ClassFiles.classAsBytes(Deserializer.class);
|
||||
defineClass(Deserializer.class.getName(), deserializerClassBytes, 0, deserializerClassBytes.length);
|
||||
|
||||
if ( customDeserializer != null ) {
|
||||
|
||||
try {
|
||||
Method method = customDeserializer.getMethod("getExtraDependencies");
|
||||
for ( Class extra : (Class[])method.invoke(null)) {
|
||||
deserializerClassBytes = ClassFiles.classAsBytes(extra);
|
||||
defineClass(extra.getName(), deserializerClassBytes, 0, deserializerClassBytes.length);
|
||||
}
|
||||
} catch ( NoSuchMethodException e ) { }
|
||||
|
||||
deserializerClassBytes = ClassFiles.classAsBytes(customDeserializer);
|
||||
defineClass(customDeserializer.getName(), deserializerClassBytes, 0, deserializerClassBytes.length);
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
Class<?> deserializerClass = isolatedClassLoader.loadClass(customDeserializer != null ? customDeserializer.getName() : Deserializer.class.getName());
|
||||
Callable<Object> deserializer = (Callable<Object>) deserializerClass.getConstructors()[ 0 ].newInstance(serialized);
|
||||
|
||||
ClassLoader ccl = Thread.currentThread().getContextClassLoader();
|
||||
try {
|
||||
// set CCL for Clojure https://groups.google.com/forum/#!topic/clojure/F3ERon6Fye0
|
||||
Thread.currentThread().setContextClassLoader(isolatedClassLoader);
|
||||
final Object obj = deserializer.call();
|
||||
return obj;
|
||||
} finally {
|
||||
Thread.currentThread().setContextClassLoader(ccl);
|
||||
}
|
||||
return urls;
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package ysoserial.test.util;
|
||||
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
|
||||
public class OpenURLClassLoader extends URLClassLoader {
|
||||
public OpenURLClassLoader(URL[] urls, ClassLoader parent) {
|
||||
super(urls, parent);
|
||||
}
|
||||
|
||||
public Class<?> defineNewClass(String name, byte[] b) {
|
||||
return defineClass(name, b, 0, b.length);
|
||||
}
|
||||
}
|
||||
@@ -3,10 +3,10 @@ package ysoserial.test.util;
|
||||
import org.junit.runner.Description;
|
||||
import org.junit.runner.notification.Failure;
|
||||
import org.junit.runner.notification.RunListener;
|
||||
import ysoserial.Strings;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
public class PayloadListener extends RunListener {
|
||||
public enum Status {
|
||||
@@ -25,7 +25,7 @@ public class PayloadListener extends RunListener {
|
||||
|
||||
@Override
|
||||
public void testStarted(Description description) throws Exception {
|
||||
System.out.println(getPayload(description.getDisplayName()) + ": STARTED");
|
||||
// System.out.println(getPayload(description.getDisplayName()) + ": STARTED");
|
||||
|
||||
statuses.put(description, Status.SUCCESS);
|
||||
|
||||
@@ -46,8 +46,34 @@ public class PayloadListener extends RunListener {
|
||||
StdIoRedirection.restoreStreams();
|
||||
|
||||
Status status = statuses.get(description);
|
||||
System.out.println(getPayload(description.getDisplayName()) + ": " + status);
|
||||
if (status == Status.FAILURE) System.err.println(outs.get(description).toString());
|
||||
String payload = getPayload(description.getDisplayName());
|
||||
String out = outs.get(description).toString();
|
||||
|
||||
Map<String,String> props = new HashMap<String, String>();
|
||||
props.put("payload", payload);
|
||||
props.put("status", status.toString());
|
||||
// props.put("out", out);
|
||||
for (String k : Arrays.asList("java.version", "java.vendor", "java.vm.version", "java.runtime.version", "os.arch", "os.name", "os.version")) {
|
||||
props.put(k, System.getProperty(k));
|
||||
}
|
||||
|
||||
List<String> pairs = new ArrayList<String>();
|
||||
for (Map.Entry<String, String> e : props.entrySet()) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("\"")
|
||||
.append(e.getKey().replace("\\", "\\\\").replace("\"", "\\\""))
|
||||
.append("\"")
|
||||
.append(": ")
|
||||
.append("\"")
|
||||
.append(e.getValue().replace("\\", "\\\\").replace("\"", "\\\"").replace("\n", "\\n").replace("\r", "\\r").replace("\t", "\\t").replace("\b", "\\b"))
|
||||
.append("\"");
|
||||
pairs.add(sb.toString());
|
||||
}
|
||||
|
||||
String obj = "{" + Strings.join(pairs, ", ", "", "") + "}";
|
||||
|
||||
System.out.println(obj);
|
||||
// System.out.println(payload + ": " + status);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -5,6 +5,7 @@ import javassist.util.proxy.ProxyFactory;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user