Skip to content

Commit

Permalink
Fix jar -> directory output and add test from #89
Browse files Browse the repository at this point in the history
  • Loading branch information
sencrash committed Sep 21, 2024
1 parent ff0cf97 commit 31fbcf6
Show file tree
Hide file tree
Showing 12 changed files with 1,578 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ private void saveClassesToDir() {
try {
byte[] data = classWrapper.compileToBytes(this.context);

Path path = this.options.outputDir().resolve(classWrapper.getPathInJar() + ".class");
Path path = this.options.outputDir().resolve(classWrapper.getPathInJar());
Files.createDirectories(path.getParent());
Files.write(path, data);
} catch (Exception e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,5 +81,10 @@ protected void registerAll() {
Source.of("zkm/sample2/SimpleLongDecrypter", false),
Source.of("zkm/sample2/FallbackLongDecrypter", false)
);

register("Zelix (21) Snake Game", InputType.CUSTOM_JAR,
List.of(ComposedZelixTransformer::new),
Source.of("SnakeGame")
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@
*/
public class AssertingResultSaver implements IResultSaver {

private final TestDeobfuscationBase.InputType inputType;
private final String jarRelativePath;
private final Path root;

private boolean savedContent = false;

public AssertingResultSaver(TestDeobfuscationBase.InputType inputType, String jarRelativePath) {
this.inputType = inputType;
this.jarRelativePath = jarRelativePath;
this.root = inputType == TestDeobfuscationBase.InputType.CUSTOM_JAR
? TestDeobfuscationBase.RESULTS_CLASSES_PATH.resolve(inputType.directory()).resolve(jarRelativePath)
: TestDeobfuscationBase.RESULTS_CLASSES_PATH.resolve(inputType.directory());

}

@Override
Expand All @@ -42,9 +43,12 @@ public void saveClassFile(String path, String qualifiedName, String entryName, S
// Replace CRLF with LF
content = content.replace("\r\n", "\n");

Path saveTo = this.inputType == TestDeobfuscationBase.InputType.CUSTOM_JAR
? TestDeobfuscationBase.RESULTS_CLASSES_PATH.resolve(inputType.directory()).resolve(this.jarRelativePath).resolve(entryName + ".dec")
: TestDeobfuscationBase.RESULTS_CLASSES_PATH.resolve(inputType.directory()).resolve(entryName + ".dec");
// The Vineflower implementations of IContextSource append .java
if (entryName.endsWith(".java")) {
entryName = entryName.substring(0, entryName.length() - 5);
}

Path saveTo = this.root.resolve(entryName + ".dec");

try {
if (Files.exists(saveTo)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,10 @@ public abstract class TestDeobfuscationBase {
/**
* Register input files for testing
*
* @param testName Test name
* @param inputType Input type. See enum optionsConsumer.
* @param testName Test name
* @param inputType Input type. See enum optionsConsumer.
* @param transformers Transformers to use
* @param sources You can choose one class or multiple classes for testing
* @param sources You can choose one class or multiple classes for testing
*/
protected void register(String testName, InputType inputType, List<Supplier<Transformer>> transformers, Source... sources) {
this.registeredTests.add(new RegisteredTest(testName, inputType, transformers, sources));
Expand Down Expand Up @@ -90,7 +90,7 @@ private void runTest() {
DeobfuscatorOptions.Builder optionsBuilder = DeobfuscatorOptions.builder()
.transformers(this.transformers.toArray(new Supplier[0]));

Path inputDir = null;
Path decompilerInputDir = DEOBFUSCATED_CLASSES_PATH.resolve(this.inputType.directory());
String jarSource = null;

// Get sources paths
Expand All @@ -101,13 +101,13 @@ private void runTest() {

jarSource = sources[0].sourceName;

Path relativePath = Path.of(this.inputType.directory(), sources[0] + ".jar");
Path relativePath = Path.of(this.inputType.directory(), jarSource);

// Add jar input
Path inputJarPath = COMPILED_CLASSES_PATH.resolve(relativePath);
Path inputJarPath = COMPILED_CLASSES_PATH.resolve(relativePath + ".jar");
optionsBuilder.inputJar(inputJarPath);

inputDir = DEOBFUSCATED_CLASSES_PATH.resolve(relativePath);
decompilerInputDir = decompilerInputDir.resolve(jarSource);
} else {
for (Source source : sources) {
Path compiledClassPath = COMPILED_CLASSES_PATH.resolve(this.inputType.directory()).resolve(source.sourceName + ".class");
Expand All @@ -118,14 +118,14 @@ private void runTest() {
}

// Add class
optionsBuilder.clazz(compiledClassPath, source.sourceName);
optionsBuilder.clazz(compiledClassPath, source.sourceName + ".class");
}
}

// Last configurations
optionsBuilder
.outputJar(null)
.outputDir(DEOBFUSCATED_CLASSES_PATH.resolve(this.inputType.directory()));
.outputDir(decompilerInputDir);

// Build and run deobfuscator!
Deobfuscator.from(optionsBuilder.build()).start();
Expand All @@ -146,14 +146,14 @@ private void runTest() {
}

// Assert output
this.assertOutput(contextSources, inputDir, jarSource);
this.assertOutput(contextSources, decompilerInputDir, jarSource);
}

/**
* Asserts output of a decompilation result
*
* @param contextSources Classes to be decompiled
* @param inputDir Optionally you can give a whole directory to decompile.
* @param contextSources Classes to be decompiled
* @param inputDir Optionally you can give a whole directory to decompile.
* @param jarRelativePath Specifies a relative path in save directory. Only used for jars
*/
private void assertOutput(List<IContextSource> contextSources, @Nullable Path inputDir, @Nullable String jarRelativePath) {
Expand Down Expand Up @@ -208,7 +208,7 @@ public String directory() {

/**
* @param sourceName Class or jar path
* @param decompile Should decompile this source. Does not work with {@link InputType#CUSTOM_JAR}
* @param decompile Should decompile this source. Does not work with {@link InputType#CUSTOM_JAR}
*/
public record Source(String sourceName, boolean decompile) {
public static Source of(String source, boolean decompile) {
Expand Down
Binary file added testData/compiled/custom-jars/SnakeGame.jar
Binary file not shown.
221 changes: 221 additions & 0 deletions testData/results/custom-jars/SnakeGame/Main.dec
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
public class Main {
private static final String a;
private static final long[] b;
private static final Integer[] c;

public static void main(String[] var0) {
long var1 = 53836601486112L;
e var3 = new e();
var3.setTitle(a);
var3.setSize(a(23704, 8408508685984484905L), a(21193, 5113680640368394361L));
var3.setVisible(true);
var3.setDefaultCloseOperation(3);
}

// $VF: Irreducible bytecode was duplicated to produce valid code
static {
char[] var10001 = "K9,%\u0001".toCharArray();
int var10003 = var10001.length;
int var8 = 0;
char[] var29 = var10001;
int var18 = var10003;
char[] var35;
int var10004;
char var10005;
byte var10006;
if (var10003 <= 1) {
var35 = var10001;
var10004 = var8;
var10005 = var10001[var8];
switch (var8 % 7) {
case 0:
var10006 = 24;
break;
case 1:
var10006 = 87;
break;
case 2:
var10006 = 77;
break;
case 3:
var10006 = 78;
break;
case 4:
var10006 = 100;
break;
case 5:
var10006 = 22;
break;
default:
var10006 = 62;
}
} else {
var29 = var10001;
var18 = var10003;
if (var10003 <= var8) {
String var44 = new String(var10001).intern();
byte var25 = -1;
a = var44;
long var9 = 75645303560601L;
long[] var14 = new long[2];
int var11 = 0;
String var12 = "\u0098wSód\u0081ØÌpÐ\u0018\"\r\u0096Ö\u009c";
byte var13 = 16;
byte var10 = 0;

do {
byte var26 = var10;
var10 += 8;
byte[] var15 = var12.substring(var26, var10).getBytes("ISO-8859-1");
int var27 = var11++;
long var47 = (
((long)var15[0] & 255L) << 56
| ((long)var15[1] & 255L) << 48
| ((long)var15[2] & 255L) << 40
| ((long)var15[3] & 255L) << 32
| ((long)var15[4] & 255L) << 24
| ((long)var15[5] & 255L) << 16
| ((long)var15[6] & 255L) << 8
| (long)var15[7] & 255L
)
^ var9;
byte var45 = -1;
var14[var27] = var47;
} while (var10 < var13);

b = var14;
c = new Integer[2];
return;
}

var35 = var10001;
var10004 = var8;
var10005 = var10001[var8];
switch (var8 % 7) {
case 0:
var10006 = 24;
break;
case 1:
var10006 = 87;
break;
case 2:
var10006 = 77;
break;
case 3:
var10006 = 78;
break;
case 4:
var10006 = 100;
break;
case 5:
var10006 = 22;
break;
default:
var10006 = 62;
}
}

while (true) {
var35[var10004] = (char)(var10005 ^ var10006);
var8++;
if (var18 == 0) {
var10004 = var18;
var35 = var29;
var10005 = var29[var18];
switch (var8 % 7) {
case 0:
var10006 = 24;
break;
case 1:
var10006 = 87;
break;
case 2:
var10006 = 77;
break;
case 3:
var10006 = 78;
break;
case 4:
var10006 = 100;
break;
case 5:
var10006 = 22;
break;
default:
var10006 = 62;
}
} else {
if (var18 <= var8) {
String var42 = new String(var29).intern();
byte var22 = -1;
a = var42;
long var0 = 75645303560601L;
long[] var6 = new long[2];
int var3 = 0;
String var4 = "\u0098wSód\u0081ØÌpÐ\u0018\"\r\u0096Ö\u009c";
byte var5 = 16;
byte var2 = 0;

do {
byte var23 = var2;
var2 += 8;
byte[] var7 = var4.substring(var23, var2).getBytes("ISO-8859-1");
int var24 = var3++;
long var46 = (
((long)var7[0] & 255L) << 56
| ((long)var7[1] & 255L) << 48
| ((long)var7[2] & 255L) << 40
| ((long)var7[3] & 255L) << 32
| ((long)var7[4] & 255L) << 24
| ((long)var7[5] & 255L) << 16
| ((long)var7[6] & 255L) << 8
| (long)var7[7] & 255L
)
^ var0;
byte var43 = -1;
var6[var24] = var46;
} while (var2 < var5);

b = var6;
c = new Integer[2];
return;
}

var35 = var29;
var10004 = var8;
var10005 = var29[var8];
switch (var8 % 7) {
case 0:
var10006 = 24;
break;
case 1:
var10006 = 87;
break;
case 2:
var10006 = 77;
break;
case 3:
var10006 = 78;
break;
case 4:
var10006 = 100;
break;
case 5:
var10006 = 22;
break;
default:
var10006 = 62;
}
}
}
}

private static int a(int var0, long var1) {
int var3 = var0 ^ (int)(var1 & 32767L) ^ 4784;
if (c[var3] == null) {
c[var3] = (int)(b[var3] ^ var1);
}

return c[var3];
}
}
Loading

0 comments on commit 31fbcf6

Please sign in to comment.