-
Notifications
You must be signed in to change notification settings - Fork 70
3.3. Running arbitrary code inside Sandbox (SSVM)
The deobfuscator includes a powerful sandboxed execution environment called SSVM that allows you to execute Java bytecode safely during the deobfuscation process. This is extremely useful for dynamic analysis, decryption routines, and runtime value calculation.
There are two ways to obtain a SandBox instance:
import uwu.narumi.deobfuscator.api.execution.SandBox;
import uwu.narumi.deobfuscator.api.context.Context;
public class MyTransformer extends Transformer {
private SandBox sandBox = null;
@Override
protected void transform() throws Exception {
// Lazily initialize sandbox
if (sandBox == null) {
this.sandBox = new SandBox(context());
}
// Use sandbox here...
}
}The global instance is shared across transformers and is automatically managed by the deobfuscator context. Important: the global sandbox already has all classes from the JAR loaded.
import uwu.narumi.deobfuscator.api.execution.SandBox;
public class MyTransformer extends Transformer {
@Override
protected void transform() throws Exception {
// Use the global sandbox instance from context
SandBox sandBox = context().getSandBox();
// Use sandbox here...
}
}-
SandBox - A wrapper for
VirtualMachinewith useful utilities - VirtualMachine - Main execution environment
- InvocationUtil - Utility for method invocations
- MemoryManager - Manages object memory and references
- Helper - Loads classes into the sandbox
import dev.xdark.ssvm.mirror.type.InstanceClass;
// Load a class by its canonical name
InstanceClass clazz = sandBox.getHelper().loadClass("com.example.MyClass");
// Alternative: Load from ClassWrapper
ClassWrapper wrapper = context().getClassesMap().get("com/example/MyClass");
InstanceClass clazz = sandBox.getHelper().loadClass(wrapper.canonicalName());import dev.xdark.ssvm.invoke.Argument;
// Example: Invoke a decryption method
// Original bytecode: invokestatic MyClass.decrypt (JJ)J
long result = sandBox.getInvocationUtil().invokeLong(
clazz.getMethod("decrypt", "(JJ)J"), // Method signature
Argument.int64(1234567890L), // First long argument
Argument.int64(9876543210L) // Second long argument
);
// For methods returning objects
ObjectValue objResult = sandBox.getInvocationUtil().invokeReference(
clazz.getMethod("createDecrypter", "(JJLjava/lang/Object;)LDecrypter;"),
Argument.int64(key1),
Argument.int64(key2),
Argument.reference(sandBox.getMemoryManager().nullValue()) // null parameter
);// Get the class of an instance
InstanceClass instanceClass = (InstanceClass) sandBox.getMemoryManager().readClass(objectInstance);
// Invoke instance methods
long decryptedValue = sandBox.getInvocationUtil().invokeLong(
instanceClass.getMethod("decrypt", "(J)J"),
Argument.reference(objectInstance), // 'this' reference
Argument.int64(encryptedValue) // Method parameter
);- Static Analysis Preferred: Use SSVM only when static analysis is insufficient
- Performance Cost: Sandbox execution is slower than static bytecode analysis
- Dependency Requirements: All required classes must be available in the context
The SSVM sandbox is a powerful tool for dynamic analysis, but should be used judiciously in combination with static analysis techniques for optimal performance and reliability.
For more examples about SSVM capabilities:
- SSVM Examples - An example from SSVM repo.
- SSVM Test Suite - Test cases from SSVM repo
Also, the SSVM has pretty much every class documented in detail, so you just need to Ctrl+Click on the class that you want to understand and read its javadocs.