diff options
| author | 2018-12-08 11:21:18 +0100 | |
|---|---|---|
| committer | 2018-12-08 11:21:18 +0100 | |
| commit | 4bc3afe4ff08b9f0c08952ec7f6e0ac930280cc5 (patch) | |
| tree | 99e43aa385d7fa1248c7fe474c022db55c364592 /src/main/java/cuchaz/enigma/Deobfuscator.java | |
| parent | work around Procyon weirdness (diff) | |
| download | enigma-fork-4bc3afe4ff08b9f0c08952ec7f6e0ac930280cc5.tar.gz enigma-fork-4bc3afe4ff08b9f0c08952ec7f6e0ac930280cc5.tar.xz enigma-fork-4bc3afe4ff08b9f0c08952ec7f6e0ac930280cc5.zip | |
add barebones plugin framework, cleanup
Diffstat (limited to 'src/main/java/cuchaz/enigma/Deobfuscator.java')
| -rw-r--r-- | src/main/java/cuchaz/enigma/Deobfuscator.java | 63 |
1 files changed, 27 insertions, 36 deletions
diff --git a/src/main/java/cuchaz/enigma/Deobfuscator.java b/src/main/java/cuchaz/enigma/Deobfuscator.java index 465c1ec..c199225 100644 --- a/src/main/java/cuchaz/enigma/Deobfuscator.java +++ b/src/main/java/cuchaz/enigma/Deobfuscator.java | |||
| @@ -28,8 +28,7 @@ import com.strobel.decompiler.languages.java.ast.CompilationUnit; | |||
| 28 | import com.strobel.decompiler.languages.java.ast.InsertParenthesesVisitor; | 28 | import com.strobel.decompiler.languages.java.ast.InsertParenthesesVisitor; |
| 29 | import com.strobel.decompiler.languages.java.ast.transforms.IAstTransform; | 29 | import com.strobel.decompiler.languages.java.ast.transforms.IAstTransform; |
| 30 | import cuchaz.enigma.analysis.*; | 30 | import cuchaz.enigma.analysis.*; |
| 31 | import cuchaz.enigma.bytecode.ClassProtectifier; | 31 | import cuchaz.enigma.api.EnigmaPlugin; |
| 32 | import cuchaz.enigma.bytecode.ClassPublifier; | ||
| 33 | import cuchaz.enigma.mapping.*; | 32 | import cuchaz.enigma.mapping.*; |
| 34 | import cuchaz.enigma.mapping.entry.*; | 33 | import cuchaz.enigma.mapping.entry.*; |
| 35 | import cuchaz.enigma.throwables.IllegalNameException; | 34 | import cuchaz.enigma.throwables.IllegalNameException; |
| @@ -40,19 +39,20 @@ import oml.ast.transformers.ObfuscatedEnumSwitchRewriterTransform; | |||
| 40 | import oml.ast.transformers.RemoveObjectCasts; | 39 | import oml.ast.transformers.RemoveObjectCasts; |
| 41 | import oml.ast.transformers.VarargsFixer; | 40 | import oml.ast.transformers.VarargsFixer; |
| 42 | import org.objectweb.asm.ClassWriter; | 41 | import org.objectweb.asm.ClassWriter; |
| 43 | import org.objectweb.asm.Opcodes; | ||
| 44 | import org.objectweb.asm.tree.ClassNode; | 42 | import org.objectweb.asm.tree.ClassNode; |
| 45 | 43 | ||
| 46 | import java.io.*; | 44 | import java.io.*; |
| 47 | import java.util.*; | 45 | import java.util.*; |
| 48 | import java.util.concurrent.ConcurrentHashMap; | 46 | import java.util.concurrent.ConcurrentHashMap; |
| 49 | import java.util.concurrent.atomic.AtomicInteger; | 47 | import java.util.concurrent.atomic.AtomicInteger; |
| 48 | import java.util.function.Consumer; | ||
| 50 | import java.util.jar.JarEntry; | 49 | import java.util.jar.JarEntry; |
| 51 | import java.util.jar.JarFile; | 50 | import java.util.jar.JarFile; |
| 52 | import java.util.jar.JarOutputStream; | 51 | import java.util.jar.JarOutputStream; |
| 53 | 52 | ||
| 54 | public class Deobfuscator { | 53 | public class Deobfuscator { |
| 55 | 54 | ||
| 55 | private final ServiceLoader<EnigmaPlugin> plugins = ServiceLoader.load(EnigmaPlugin.class); | ||
| 56 | private final ReferencedEntryPool entryPool = new ReferencedEntryPool(); | 56 | private final ReferencedEntryPool entryPool = new ReferencedEntryPool(); |
| 57 | private final ParsedJar parsedJar; | 57 | private final ParsedJar parsedJar; |
| 58 | private final DecompilerSettings settings; | 58 | private final DecompilerSettings settings; |
| @@ -61,13 +61,20 @@ public class Deobfuscator { | |||
| 61 | private final Map<TranslationDirection, Translator> translatorCache; | 61 | private final Map<TranslationDirection, Translator> translatorCache; |
| 62 | private Mappings mappings; | 62 | private Mappings mappings; |
| 63 | 63 | ||
| 64 | public Deobfuscator(ParsedJar jar) { | 64 | public Deobfuscator(ParsedJar jar, Consumer<String> listener) { |
| 65 | this.parsedJar = jar; | 65 | this.parsedJar = jar; |
| 66 | 66 | ||
| 67 | // build the jar index | 67 | // build the jar index |
| 68 | listener.accept("Indexing JAR..."); | ||
| 68 | this.jarIndex = new JarIndex(entryPool); | 69 | this.jarIndex = new JarIndex(entryPool); |
| 69 | this.jarIndex.indexJar(this.parsedJar, true); | 70 | this.jarIndex.indexJar(this.parsedJar, true); |
| 70 | 71 | ||
| 72 | listener.accept("Initializing plugins..."); | ||
| 73 | for (EnigmaPlugin plugin : getPlugins()) { | ||
| 74 | plugin.onClassesLoaded(parsedJar.getClassDataMap(), parsedJar::getClassNode); | ||
| 75 | } | ||
| 76 | |||
| 77 | listener.accept("Preparing..."); | ||
| 71 | // config the decompiler | 78 | // config the decompiler |
| 72 | this.settings = DecompilerSettings.javaDefaults(); | 79 | this.settings = DecompilerSettings.javaDefaults(); |
| 73 | this.settings.setMergeVariables(Utils.getSystemPropertyAsBoolean("enigma.mergeVariables", true)); | 80 | this.settings.setMergeVariables(Utils.getSystemPropertyAsBoolean("enigma.mergeVariables", true)); |
| @@ -85,8 +92,20 @@ public class Deobfuscator { | |||
| 85 | setMappings(new Mappings()); | 92 | setMappings(new Mappings()); |
| 86 | } | 93 | } |
| 87 | 94 | ||
| 88 | public Deobfuscator(JarFile jar) throws IOException { | 95 | public Deobfuscator(JarFile jar, Consumer<String> listener) throws IOException { |
| 89 | this(new ParsedJar(jar)); | 96 | this(new ParsedJar(jar), listener); |
| 97 | } | ||
| 98 | |||
| 99 | public Deobfuscator(ParsedJar jar) throws IOException { | ||
| 100 | this(jar, (msg) -> {}); | ||
| 101 | } | ||
| 102 | |||
| 103 | public Deobfuscator(JarFile jar) throws IOException { | ||
| 104 | this(jar, (msg) -> {}); | ||
| 105 | } | ||
| 106 | |||
| 107 | public ServiceLoader<EnigmaPlugin> getPlugins() { | ||
| 108 | return plugins; | ||
| 90 | } | 109 | } |
| 91 | 110 | ||
| 92 | public ParsedJar getJar() { | 111 | public ParsedJar getJar() { |
| @@ -442,20 +461,6 @@ public class Deobfuscator { | |||
| 442 | transformJar(out, progress, createTypeLoader()::transformInto); | 461 | transformJar(out, progress, createTypeLoader()::transformInto); |
| 443 | } | 462 | } |
| 444 | 463 | ||
| 445 | public void protectifyJar(File out, ProgressListener progress) { | ||
| 446 | transformJar(out, progress, (node, writer) -> { | ||
| 447 | node.accept(new ClassProtectifier(Opcodes.ASM5, writer)); | ||
| 448 | return node.name; | ||
| 449 | }); | ||
| 450 | } | ||
| 451 | |||
| 452 | public void publifyJar(File out, ProgressListener progress) { | ||
| 453 | transformJar(out, progress, (node, writer) -> { | ||
| 454 | node.accept(new ClassPublifier(Opcodes.ASM5, writer)); | ||
| 455 | return node.name; | ||
| 456 | }); | ||
| 457 | } | ||
| 458 | |||
| 459 | public void transformJar(File out, ProgressListener progress, ClassTransformer transformer) { | 464 | public void transformJar(File out, ProgressListener progress, ClassTransformer transformer) { |
| 460 | try (JarOutputStream outJar = new JarOutputStream(new FileOutputStream(out))) { | 465 | try (JarOutputStream outJar = new JarOutputStream(new FileOutputStream(out))) { |
| 461 | if (progress != null) { | 466 | if (progress != null) { |
| @@ -463,7 +468,7 @@ public class Deobfuscator { | |||
| 463 | } | 468 | } |
| 464 | 469 | ||
| 465 | AtomicInteger i = new AtomicInteger(); | 470 | AtomicInteger i = new AtomicInteger(); |
| 466 | parsedJar.visit(node -> { | 471 | parsedJar.visitNode(node -> { |
| 467 | if (progress != null) { | 472 | if (progress != null) { |
| 468 | progress.onProgress(i.getAndIncrement(), node.name); | 473 | progress.onProgress(i.getAndIncrement(), node.name); |
| 469 | } | 474 | } |
| @@ -524,13 +529,7 @@ public class Deobfuscator { | |||
| 524 | } | 529 | } |
| 525 | 530 | ||
| 526 | public boolean isObfuscatedIdentifier(Entry obfEntry) { | 531 | public boolean isObfuscatedIdentifier(Entry obfEntry) { |
| 527 | return isObfuscatedIdentifier(obfEntry, false); | ||
| 528 | } | ||
| 529 | |||
| 530 | public boolean isObfuscatedIdentifier(Entry obfEntry, boolean hack) { | ||
| 531 | |||
| 532 | if (obfEntry instanceof MethodEntry) { | 532 | if (obfEntry instanceof MethodEntry) { |
| 533 | |||
| 534 | // HACKHACK: Object methods are not obfuscated identifiers | 533 | // HACKHACK: Object methods are not obfuscated identifiers |
| 535 | MethodEntry obfMethodEntry = (MethodEntry) obfEntry; | 534 | MethodEntry obfMethodEntry = (MethodEntry) obfEntry; |
| 536 | String name = obfMethodEntry.getName(); | 535 | String name = obfMethodEntry.getName(); |
| @@ -558,21 +557,13 @@ public class Deobfuscator { | |||
| 558 | } else if (name.equals("wait") && sig.equals("(JI)V")) { | 557 | } else if (name.equals("wait") && sig.equals("(JI)V")) { |
| 559 | return false; | 558 | return false; |
| 560 | } | 559 | } |
| 561 | |||
| 562 | // FIXME: HACK EVEN MORE HACK! | ||
| 563 | if (hack && this.jarIndex.containsObfEntry(obfEntry.getOwnerClassEntry())) | ||
| 564 | return true; | ||
| 565 | } | 560 | } |
| 566 | 561 | ||
| 567 | return this.jarIndex.containsObfEntry(obfEntry); | 562 | return this.jarIndex.containsObfEntry(obfEntry); |
| 568 | } | 563 | } |
| 569 | 564 | ||
| 570 | public boolean isRenameable(EntryReference<Entry, Entry> obfReference, boolean activeHack) { | ||
| 571 | return obfReference.isNamed() && isObfuscatedIdentifier(obfReference.getNameableEntry(), activeHack); | ||
| 572 | } | ||
| 573 | |||
| 574 | public boolean isRenameable(EntryReference<Entry, Entry> obfReference) { | 565 | public boolean isRenameable(EntryReference<Entry, Entry> obfReference) { |
| 575 | return isRenameable(obfReference, false); | 566 | return obfReference.isNamed() && isObfuscatedIdentifier(obfReference.getNameableEntry()); |
| 576 | } | 567 | } |
| 577 | 568 | ||
| 578 | public boolean hasDeobfuscatedName(Entry obfEntry) { | 569 | public boolean hasDeobfuscatedName(Entry obfEntry) { |