From 1bb55841fbabafb1ff65dfbc5e5dcfdfa28b6d5e Mon Sep 17 00:00:00 2001 From: EpicPlayerA10 Date: Sun, 8 Sep 2024 16:39:33 +0200 Subject: [PATCH] Test sandbox security --- .../deobfuscator/api/helper/AsmHelper.java | 5 +++++ .../deobfuscator/TestDeobfuscation.java | 4 ++++ .../base/TestDeobfuscationBase.java | 21 ++++++++++++++++--- .../TestSandboxSecurityTransformer.java | 19 +++++++++++++++++ .../src/main/java/TestSandboxSecurity.java | 17 +++++++++++++++ 5 files changed, 63 insertions(+), 3 deletions(-) create mode 100644 deobfuscator-impl/src/test/java/uwu/narumi/deobfuscator/transformer/TestSandboxSecurityTransformer.java create mode 100644 testData/src/java/src/main/java/TestSandboxSecurity.java diff --git a/deobfuscator-api/src/main/java/uwu/narumi/deobfuscator/api/helper/AsmHelper.java b/deobfuscator-api/src/main/java/uwu/narumi/deobfuscator/api/helper/AsmHelper.java index c251bef..360d825 100644 --- a/deobfuscator-api/src/main/java/uwu/narumi/deobfuscator/api/helper/AsmHelper.java +++ b/deobfuscator-api/src/main/java/uwu/narumi/deobfuscator/api/helper/AsmHelper.java @@ -6,6 +6,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Unmodifiable; import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.NamedOpcodes; import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; import org.objectweb.asm.tree.*; @@ -168,6 +169,10 @@ public static Map> analyzeSource( return Collections.unmodifiableMap(frames); } + public static List prettyInsnList(InsnList insnList) { + return Arrays.stream(insnList.toArray()).map(insn -> NamedOpcodes.map(insn.getOpcode())).toList(); + } + /** * Convert constant value to instruction that represents this constant * diff --git a/deobfuscator-impl/src/test/java/uwu/narumi/deobfuscator/TestDeobfuscation.java b/deobfuscator-impl/src/test/java/uwu/narumi/deobfuscator/TestDeobfuscation.java index e7ce53c..c24564a 100644 --- a/deobfuscator-impl/src/test/java/uwu/narumi/deobfuscator/TestDeobfuscation.java +++ b/deobfuscator-impl/src/test/java/uwu/narumi/deobfuscator/TestDeobfuscation.java @@ -7,6 +7,7 @@ import uwu.narumi.deobfuscator.core.other.impl.pool.InlineStaticFieldTransformer; import uwu.narumi.deobfuscator.core.other.impl.universal.UniversalNumberTransformer; import uwu.narumi.deobfuscator.base.TestDeobfuscationBase; +import uwu.narumi.deobfuscator.transformer.TestSandboxSecurityTransformer; import java.util.List; @@ -24,6 +25,9 @@ protected void registerAll() { register("Inline static fields", InputType.JAVA_CODE, List.of(InlineStaticFieldTransformer::new), Source.of("TestInlineStaticFields")); register("Inline static fields with modification", InputType.JAVA_CODE, List.of(InlineStaticFieldTransformer::new), Source.of("TestInlineStaticFieldsWithModification")); + // Sandbox security. Should throw + registerThrows("Sandbox security", InputType.JAVA_CODE, List.of(TestSandboxSecurityTransformer::new), Source.of("TestSandboxSecurity")); + // Samples register("Some flow obf sample", InputType.CUSTOM_CLASS, List.of(ComposedGeneralFlowTransformer::new), Source.of("FlowObfSample")); diff --git a/deobfuscator-impl/src/test/java/uwu/narumi/deobfuscator/base/TestDeobfuscationBase.java b/deobfuscator-impl/src/test/java/uwu/narumi/deobfuscator/base/TestDeobfuscationBase.java index 73c801d..46a1b22 100644 --- a/deobfuscator-impl/src/test/java/uwu/narumi/deobfuscator/base/TestDeobfuscationBase.java +++ b/deobfuscator-impl/src/test/java/uwu/narumi/deobfuscator/base/TestDeobfuscationBase.java @@ -1,5 +1,6 @@ package uwu.narumi.deobfuscator.base; +import com.sun.jdi.InvocationException; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.core.config.Configurator; import org.jetbrains.annotations.Nullable; @@ -24,6 +25,8 @@ import java.util.function.Supplier; import java.util.stream.Stream; +import static org.junit.jupiter.api.Assertions.*; + @Timeout(60) public abstract class TestDeobfuscationBase { public static final Path TEST_DATA_PATH = Path.of("..", "testData"); @@ -47,8 +50,11 @@ public abstract class TestDeobfuscationBase { * @param sources You can choose one class or multiple classes for testing */ protected void register(String testName, InputType inputType, List> transformers, Source... sources) { - // Register - this.registeredTests.add(new RegisteredTest(testName, inputType, transformers, sources)); + this.registeredTests.add(new RegisteredTest(testName, false, inputType, transformers, sources)); + } + + protected void registerThrows(String testName, InputType inputType, List> transformers, Source... sources) { + this.registeredTests.add(new RegisteredTest(testName, true, inputType, transformers, sources)); } @BeforeAll @@ -72,6 +78,7 @@ public Stream testDeobfuscation() { */ public record RegisteredTest( String testName, + boolean throwable, InputType inputType, List> transformers, Source[] sources @@ -129,7 +136,15 @@ private void runTest() { .outputDir(DEOBFUSCATED_CLASSES_PATH.resolve(this.inputType.directory())); // Build and run deobfuscator! - Deobfuscator.from(optionsBuilder.build()).start(); + if (this.throwable) { + assertThrows(RuntimeException.class, () -> { + Deobfuscator.from(optionsBuilder.build()).start(); + }); + // If the deobfuscator throws an exception, then there is no output. Return + return; + } else { + Deobfuscator.from(optionsBuilder.build()).start(); + } // Init context sources List contextSources = new ArrayList<>(); diff --git a/deobfuscator-impl/src/test/java/uwu/narumi/deobfuscator/transformer/TestSandboxSecurityTransformer.java b/deobfuscator-impl/src/test/java/uwu/narumi/deobfuscator/transformer/TestSandboxSecurityTransformer.java new file mode 100644 index 0000000..f8d2d3c --- /dev/null +++ b/deobfuscator-impl/src/test/java/uwu/narumi/deobfuscator/transformer/TestSandboxSecurityTransformer.java @@ -0,0 +1,19 @@ +package uwu.narumi.deobfuscator.transformer; + +import uwu.narumi.deobfuscator.api.asm.ClassWrapper; +import uwu.narumi.deobfuscator.api.context.Context; +import uwu.narumi.deobfuscator.api.execution.SandboxClassLoader; +import uwu.narumi.deobfuscator.api.transformer.Transformer; + +import java.lang.reflect.Method; + +public class TestSandboxSecurityTransformer extends Transformer { + @Override + protected void transform(ClassWrapper scope, Context context) throws Exception { + SandboxClassLoader sandboxClassLoader = new SandboxClassLoader(context); + Class clazz = Class.forName("TestSandboxSecurity", true, sandboxClassLoader); + Method method = clazz.getDeclaredMethod("test"); + // Invoke test method + method.invoke(null); + } +} diff --git a/testData/src/java/src/main/java/TestSandboxSecurity.java b/testData/src/java/src/main/java/TestSandboxSecurity.java new file mode 100644 index 0000000..5072332 --- /dev/null +++ b/testData/src/java/src/main/java/TestSandboxSecurity.java @@ -0,0 +1,17 @@ +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + +public class TestSandboxSecurity { + public static int test() { + int a = 3; + int b = 4; + int result = a + b; + try { + Files.createFile(Path.of("test.txt")); + } catch (IOException e) { + throw new RuntimeException(e); + } + return result; + } +}