diff options
Diffstat (limited to 'src/main/java/cuchaz/enigma/Deobfuscator.java')
| -rw-r--r-- | src/main/java/cuchaz/enigma/Deobfuscator.java | 120 |
1 files changed, 58 insertions, 62 deletions
diff --git a/src/main/java/cuchaz/enigma/Deobfuscator.java b/src/main/java/cuchaz/enigma/Deobfuscator.java index f917deb..d22260f 100644 --- a/src/main/java/cuchaz/enigma/Deobfuscator.java +++ b/src/main/java/cuchaz/enigma/Deobfuscator.java | |||
| @@ -47,50 +47,46 @@ public class Deobfuscator { | |||
| 47 | void onProgress(int numDone, String message); | 47 | void onProgress(int numDone, String message); |
| 48 | } | 48 | } |
| 49 | 49 | ||
| 50 | private JarFile m_jar; | 50 | private JarFile jar; |
| 51 | private DecompilerSettings m_settings; | 51 | private DecompilerSettings settings; |
| 52 | private JarIndex m_jarIndex; | 52 | private JarIndex jarIndex; |
| 53 | private Mappings m_mappings; | 53 | private Mappings mappings; |
| 54 | private MappingsRenamer m_renamer; | 54 | private MappingsRenamer renamer; |
| 55 | private Map<TranslationDirection, Translator> m_translatorCache; | 55 | private Map<TranslationDirection, Translator> translatorCache; |
| 56 | 56 | ||
| 57 | public Deobfuscator(JarFile jar) throws IOException { | 57 | public Deobfuscator(JarFile jar) { |
| 58 | m_jar = jar; | 58 | this.jar = jar; |
| 59 | 59 | ||
| 60 | // build the jar index | 60 | // build the jar index |
| 61 | m_jarIndex = new JarIndex(); | 61 | this.jarIndex = new JarIndex(); |
| 62 | m_jarIndex.indexJar(m_jar, true); | 62 | this.jarIndex.indexJar(this.jar, true); |
| 63 | 63 | ||
| 64 | // config the decompiler | 64 | // config the decompiler |
| 65 | m_settings = DecompilerSettings.javaDefaults(); | 65 | this.settings = DecompilerSettings.javaDefaults(); |
| 66 | m_settings.setMergeVariables(true); | 66 | this.settings.setMergeVariables(true); |
| 67 | m_settings.setForceExplicitImports(true); | 67 | this.settings.setForceExplicitImports(true); |
| 68 | m_settings.setForceExplicitTypeArguments(true); | 68 | this.settings.setForceExplicitTypeArguments(true); |
| 69 | m_settings.setShowDebugLineNumbers(true); | 69 | this.settings.setShowDebugLineNumbers(true); |
| 70 | // DEBUG | 70 | // DEBUG |
| 71 | //m_settings.setShowSyntheticMembers(true); | 71 | //this.settings.setShowSyntheticMembers(true); |
| 72 | 72 | ||
| 73 | // init defaults | 73 | // init defaults |
| 74 | m_translatorCache = Maps.newTreeMap(); | 74 | this.translatorCache = Maps.newTreeMap(); |
| 75 | 75 | ||
| 76 | // init mappings | 76 | // init mappings |
| 77 | setMappings(new Mappings()); | 77 | setMappings(new Mappings()); |
| 78 | } | 78 | } |
| 79 | 79 | ||
| 80 | public JarFile getJar() { | ||
| 81 | return m_jar; | ||
| 82 | } | ||
| 83 | |||
| 84 | public String getJarName() { | 80 | public String getJarName() { |
| 85 | return m_jar.getName(); | 81 | return this.jar.getName(); |
| 86 | } | 82 | } |
| 87 | 83 | ||
| 88 | public JarIndex getJarIndex() { | 84 | public JarIndex getJarIndex() { |
| 89 | return m_jarIndex; | 85 | return this.jarIndex; |
| 90 | } | 86 | } |
| 91 | 87 | ||
| 92 | public Mappings getMappings() { | 88 | public Mappings getMappings() { |
| 93 | return m_mappings; | 89 | return this.mappings; |
| 94 | } | 90 | } |
| 95 | 91 | ||
| 96 | public void setMappings(Mappings val) { | 92 | public void setMappings(Mappings val) { |
| @@ -103,7 +99,7 @@ public class Deobfuscator { | |||
| 103 | } | 99 | } |
| 104 | 100 | ||
| 105 | // drop mappings that don't match the jar | 101 | // drop mappings that don't match the jar |
| 106 | MappingsChecker checker = new MappingsChecker(m_jarIndex); | 102 | MappingsChecker checker = new MappingsChecker(this.jarIndex); |
| 107 | checker.dropBrokenMappings(val); | 103 | checker.dropBrokenMappings(val); |
| 108 | if (warnAboutDrops) { | 104 | if (warnAboutDrops) { |
| 109 | for (java.util.Map.Entry<ClassEntry, ClassMapping> mapping : checker.getDroppedClassMappings().entrySet()) { | 105 | for (java.util.Map.Entry<ClassEntry, ClassMapping> mapping : checker.getDroppedClassMappings().entrySet()) { |
| @@ -120,22 +116,22 @@ public class Deobfuscator { | |||
| 120 | } | 116 | } |
| 121 | } | 117 | } |
| 122 | 118 | ||
| 123 | m_mappings = val; | 119 | this.mappings = val; |
| 124 | m_renamer = new MappingsRenamer(m_jarIndex, val); | 120 | this.renamer = new MappingsRenamer(this.jarIndex, val); |
| 125 | m_translatorCache.clear(); | 121 | this.translatorCache.clear(); |
| 126 | } | 122 | } |
| 127 | 123 | ||
| 128 | public Translator getTranslator(TranslationDirection direction) { | 124 | public Translator getTranslator(TranslationDirection direction) { |
| 129 | Translator translator = m_translatorCache.get(direction); | 125 | Translator translator = this.translatorCache.get(direction); |
| 130 | if (translator == null) { | 126 | if (translator == null) { |
| 131 | translator = m_mappings.getTranslator(direction, m_jarIndex.getTranslationIndex()); | 127 | translator = this.mappings.getTranslator(direction, this.jarIndex.getTranslationIndex()); |
| 132 | m_translatorCache.put(direction, translator); | 128 | this.translatorCache.put(direction, translator); |
| 133 | } | 129 | } |
| 134 | return translator; | 130 | return translator; |
| 135 | } | 131 | } |
| 136 | 132 | ||
| 137 | public void getSeparatedClasses(List<ClassEntry> obfClasses, List<ClassEntry> deobfClasses) { | 133 | public void getSeparatedClasses(List<ClassEntry> obfClasses, List<ClassEntry> deobfClasses) { |
| 138 | for (ClassEntry obfClassEntry : m_jarIndex.getObfClassEntries()) { | 134 | for (ClassEntry obfClassEntry : this.jarIndex.getObfClassEntries()) { |
| 139 | // skip inner classes | 135 | // skip inner classes |
| 140 | if (obfClassEntry.isInnerClass()) { | 136 | if (obfClassEntry.isInnerClass()) { |
| 141 | continue; | 137 | continue; |
| @@ -166,19 +162,19 @@ public class Deobfuscator { | |||
| 166 | String deobfClassName = className; | 162 | String deobfClassName = className; |
| 167 | 163 | ||
| 168 | // if it wasn't actually deobf, then we can find a mapping for it and get the deobf name | 164 | // if it wasn't actually deobf, then we can find a mapping for it and get the deobf name |
| 169 | ClassMapping classMapping = m_mappings.getClassByObf(className); | 165 | ClassMapping classMapping = this.mappings.getClassByObf(className); |
| 170 | if (classMapping != null && classMapping.getDeobfName() != null) { | 166 | if (classMapping != null && classMapping.getDeobfName() != null) { |
| 171 | deobfClassName = classMapping.getDeobfName(); | 167 | deobfClassName = classMapping.getDeobfName(); |
| 172 | } | 168 | } |
| 173 | 169 | ||
| 174 | // set the type loader | 170 | // set the type loader |
| 175 | TranslatingTypeLoader loader = new TranslatingTypeLoader( | 171 | TranslatingTypeLoader loader = new TranslatingTypeLoader( |
| 176 | m_jar, | 172 | this.jar, |
| 177 | m_jarIndex, | 173 | this.jarIndex, |
| 178 | getTranslator(TranslationDirection.Obfuscating), | 174 | getTranslator(TranslationDirection.Obfuscating), |
| 179 | getTranslator(TranslationDirection.Deobfuscating) | 175 | getTranslator(TranslationDirection.Deobfuscating) |
| 180 | ); | 176 | ); |
| 181 | m_settings.setTypeLoader(loader); | 177 | this.settings.setTypeLoader(loader); |
| 182 | 178 | ||
| 183 | // see if procyon can find the type | 179 | // see if procyon can find the type |
| 184 | TypeReference type = new MetadataSystem(loader).lookupType(deobfClassName); | 180 | TypeReference type = new MetadataSystem(loader).lookupType(deobfClassName); |
| @@ -192,7 +188,7 @@ public class Deobfuscator { | |||
| 192 | // decompile it! | 188 | // decompile it! |
| 193 | DecompilerContext context = new DecompilerContext(); | 189 | DecompilerContext context = new DecompilerContext(); |
| 194 | context.setCurrentType(resolvedType); | 190 | context.setCurrentType(resolvedType); |
| 195 | context.setSettings(m_settings); | 191 | context.setSettings(this.settings); |
| 196 | AstBuilder builder = new AstBuilder(context); | 192 | AstBuilder builder = new AstBuilder(context); |
| 197 | builder.addType(resolvedType); | 193 | builder.addType(resolvedType); |
| 198 | builder.runTransformations(null); | 194 | builder.runTransformations(null); |
| @@ -225,7 +221,7 @@ public class Deobfuscator { | |||
| 225 | Entry obfEntry = obfuscateEntry(deobfReference.entry); | 221 | Entry obfEntry = obfuscateEntry(deobfReference.entry); |
| 226 | 222 | ||
| 227 | // try to resolve the class | 223 | // try to resolve the class |
| 228 | ClassEntry resolvedObfClassEntry = m_jarIndex.getTranslationIndex().resolveEntryClass(obfEntry); | 224 | ClassEntry resolvedObfClassEntry = this.jarIndex.getTranslationIndex().resolveEntryClass(obfEntry); |
| 229 | if (resolvedObfClassEntry != null && !resolvedObfClassEntry.equals(obfEntry.getClassEntry())) { | 225 | if (resolvedObfClassEntry != null && !resolvedObfClassEntry.equals(obfEntry.getClassEntry())) { |
| 230 | // change the class of the entry | 226 | // change the class of the entry |
| 231 | obfEntry = obfEntry.cloneToNewClass(resolvedObfClassEntry); | 227 | obfEntry = obfEntry.cloneToNewClass(resolvedObfClassEntry); |
| @@ -246,14 +242,14 @@ public class Deobfuscator { | |||
| 246 | // render the AST into source | 242 | // render the AST into source |
| 247 | StringWriter buf = new StringWriter(); | 243 | StringWriter buf = new StringWriter(); |
| 248 | sourceTree.acceptVisitor(new InsertParenthesesVisitor(), null); | 244 | sourceTree.acceptVisitor(new InsertParenthesesVisitor(), null); |
| 249 | sourceTree.acceptVisitor(new JavaOutputVisitor(new PlainTextOutput(buf), m_settings), null); | 245 | sourceTree.acceptVisitor(new JavaOutputVisitor(new PlainTextOutput(buf), this.settings), null); |
| 250 | return buf.toString(); | 246 | return buf.toString(); |
| 251 | } | 247 | } |
| 252 | 248 | ||
| 253 | public void writeSources(File dirOut, ProgressListener progress) throws IOException { | 249 | public void writeSources(File dirOut, ProgressListener progress) { |
| 254 | // get the classes to decompile | 250 | // get the classes to decompile |
| 255 | Set<ClassEntry> classEntries = Sets.newHashSet(); | 251 | Set<ClassEntry> classEntries = Sets.newHashSet(); |
| 256 | for (ClassEntry obfClassEntry : m_jarIndex.getObfClassEntries()) { | 252 | for (ClassEntry obfClassEntry : this.jarIndex.getObfClassEntries()) { |
| 257 | // skip inner classes | 253 | // skip inner classes |
| 258 | if (obfClassEntry.isInnerClass()) { | 254 | if (obfClassEntry.isInnerClass()) { |
| 259 | continue; | 255 | continue; |
| @@ -298,8 +294,8 @@ public class Deobfuscator { | |||
| 298 | 294 | ||
| 299 | public void writeJar(File out, ProgressListener progress) { | 295 | public void writeJar(File out, ProgressListener progress) { |
| 300 | final TranslatingTypeLoader loader = new TranslatingTypeLoader( | 296 | final TranslatingTypeLoader loader = new TranslatingTypeLoader( |
| 301 | m_jar, | 297 | this.jar, |
| 302 | m_jarIndex, | 298 | this.jarIndex, |
| 303 | getTranslator(TranslationDirection.Obfuscating), | 299 | getTranslator(TranslationDirection.Obfuscating), |
| 304 | getTranslator(TranslationDirection.Deobfuscating) | 300 | getTranslator(TranslationDirection.Deobfuscating) |
| 305 | ); | 301 | ); |
| @@ -321,11 +317,11 @@ public class Deobfuscator { | |||
| 321 | private void transformJar(File out, ProgressListener progress, ClassTransformer transformer) { | 317 | private void transformJar(File out, ProgressListener progress, ClassTransformer transformer) { |
| 322 | try (JarOutputStream outJar = new JarOutputStream(new FileOutputStream(out))) { | 318 | try (JarOutputStream outJar = new JarOutputStream(new FileOutputStream(out))) { |
| 323 | if (progress != null) { | 319 | if (progress != null) { |
| 324 | progress.init(JarClassIterator.getClassEntries(m_jar).size(), "Transforming classes..."); | 320 | progress.init(JarClassIterator.getClassEntries(this.jar).size(), "Transforming classes..."); |
| 325 | } | 321 | } |
| 326 | 322 | ||
| 327 | int i = 0; | 323 | int i = 0; |
| 328 | for (CtClass c : JarClassIterator.classes(m_jar)) { | 324 | for (CtClass c : JarClassIterator.classes(this.jar)) { |
| 329 | if (progress != null) { | 325 | if (progress != null) { |
| 330 | progress.onProgress(i++, c.getName()); | 326 | progress.onProgress(i++, c.getName()); |
| 331 | } | 327 | } |
| @@ -410,7 +406,7 @@ public class Deobfuscator { | |||
| 410 | } | 406 | } |
| 411 | } | 407 | } |
| 412 | 408 | ||
| 413 | return m_jarIndex.containsObfEntry(obfEntry); | 409 | return this.jarIndex.containsObfEntry(obfEntry); |
| 414 | } | 410 | } |
| 415 | 411 | ||
| 416 | public boolean isRenameable(EntryReference<Entry, Entry> obfReference) { | 412 | public boolean isRenameable(EntryReference<Entry, Entry> obfReference) { |
| @@ -423,7 +419,7 @@ public class Deobfuscator { | |||
| 423 | Translator translator = getTranslator(TranslationDirection.Deobfuscating); | 419 | Translator translator = getTranslator(TranslationDirection.Deobfuscating); |
| 424 | if (obfEntry instanceof ClassEntry) { | 420 | if (obfEntry instanceof ClassEntry) { |
| 425 | ClassEntry obfClass = (ClassEntry) obfEntry; | 421 | ClassEntry obfClass = (ClassEntry) obfEntry; |
| 426 | List<ClassMapping> mappingChain = m_mappings.getClassMappingChain(obfClass); | 422 | List<ClassMapping> mappingChain = this.mappings.getClassMappingChain(obfClass); |
| 427 | ClassMapping classMapping = mappingChain.get(mappingChain.size() - 1); | 423 | ClassMapping classMapping = mappingChain.get(mappingChain.size() - 1); |
| 428 | return classMapping != null && classMapping.getDeobfName() != null; | 424 | return classMapping != null && classMapping.getDeobfName() != null; |
| 429 | } else if (obfEntry instanceof FieldEntry) { | 425 | } else if (obfEntry instanceof FieldEntry) { |
| @@ -442,58 +438,58 @@ public class Deobfuscator { | |||
| 442 | 438 | ||
| 443 | public void rename(Entry obfEntry, String newName) { | 439 | public void rename(Entry obfEntry, String newName) { |
| 444 | if (obfEntry instanceof ClassEntry) { | 440 | if (obfEntry instanceof ClassEntry) { |
| 445 | m_renamer.setClassName((ClassEntry) obfEntry, Descriptor.toJvmName(newName)); | 441 | this.renamer.setClassName((ClassEntry) obfEntry, Descriptor.toJvmName(newName)); |
| 446 | } else if (obfEntry instanceof FieldEntry) { | 442 | } else if (obfEntry instanceof FieldEntry) { |
| 447 | m_renamer.setFieldName((FieldEntry) obfEntry, newName); | 443 | this.renamer.setFieldName((FieldEntry) obfEntry, newName); |
| 448 | } else if (obfEntry instanceof MethodEntry) { | 444 | } else if (obfEntry instanceof MethodEntry) { |
| 449 | m_renamer.setMethodTreeName((MethodEntry) obfEntry, newName); | 445 | this.renamer.setMethodTreeName((MethodEntry) obfEntry, newName); |
| 450 | } else if (obfEntry instanceof ConstructorEntry) { | 446 | } else if (obfEntry instanceof ConstructorEntry) { |
| 451 | throw new IllegalArgumentException("Cannot rename constructors"); | 447 | throw new IllegalArgumentException("Cannot rename constructors"); |
| 452 | } else if (obfEntry instanceof ArgumentEntry) { | 448 | } else if (obfEntry instanceof ArgumentEntry) { |
| 453 | m_renamer.setArgumentName((ArgumentEntry) obfEntry, newName); | 449 | this.renamer.setArgumentName((ArgumentEntry) obfEntry, newName); |
| 454 | } else { | 450 | } else { |
| 455 | throw new Error("Unknown entry type: " + obfEntry.getClass().getName()); | 451 | throw new Error("Unknown entry type: " + obfEntry.getClass().getName()); |
| 456 | } | 452 | } |
| 457 | 453 | ||
| 458 | // clear caches | 454 | // clear caches |
| 459 | m_translatorCache.clear(); | 455 | this.translatorCache.clear(); |
| 460 | } | 456 | } |
| 461 | 457 | ||
| 462 | public void removeMapping(Entry obfEntry) { | 458 | public void removeMapping(Entry obfEntry) { |
| 463 | if (obfEntry instanceof ClassEntry) { | 459 | if (obfEntry instanceof ClassEntry) { |
| 464 | m_renamer.removeClassMapping((ClassEntry) obfEntry); | 460 | this.renamer.removeClassMapping((ClassEntry) obfEntry); |
| 465 | } else if (obfEntry instanceof FieldEntry) { | 461 | } else if (obfEntry instanceof FieldEntry) { |
| 466 | m_renamer.removeFieldMapping((FieldEntry) obfEntry); | 462 | this.renamer.removeFieldMapping((FieldEntry) obfEntry); |
| 467 | } else if (obfEntry instanceof MethodEntry) { | 463 | } else if (obfEntry instanceof MethodEntry) { |
| 468 | m_renamer.removeMethodTreeMapping((MethodEntry) obfEntry); | 464 | this.renamer.removeMethodTreeMapping((MethodEntry) obfEntry); |
| 469 | } else if (obfEntry instanceof ConstructorEntry) { | 465 | } else if (obfEntry instanceof ConstructorEntry) { |
| 470 | throw new IllegalArgumentException("Cannot rename constructors"); | 466 | throw new IllegalArgumentException("Cannot rename constructors"); |
| 471 | } else if (obfEntry instanceof ArgumentEntry) { | 467 | } else if (obfEntry instanceof ArgumentEntry) { |
| 472 | m_renamer.removeArgumentMapping((ArgumentEntry) obfEntry); | 468 | this.renamer.removeArgumentMapping((ArgumentEntry) obfEntry); |
| 473 | } else { | 469 | } else { |
| 474 | throw new Error("Unknown entry type: " + obfEntry); | 470 | throw new Error("Unknown entry type: " + obfEntry); |
| 475 | } | 471 | } |
| 476 | 472 | ||
| 477 | // clear caches | 473 | // clear caches |
| 478 | m_translatorCache.clear(); | 474 | this.translatorCache.clear(); |
| 479 | } | 475 | } |
| 480 | 476 | ||
| 481 | public void markAsDeobfuscated(Entry obfEntry) { | 477 | public void markAsDeobfuscated(Entry obfEntry) { |
| 482 | if (obfEntry instanceof ClassEntry) { | 478 | if (obfEntry instanceof ClassEntry) { |
| 483 | m_renamer.markClassAsDeobfuscated((ClassEntry) obfEntry); | 479 | this.renamer.markClassAsDeobfuscated((ClassEntry) obfEntry); |
| 484 | } else if (obfEntry instanceof FieldEntry) { | 480 | } else if (obfEntry instanceof FieldEntry) { |
| 485 | m_renamer.markFieldAsDeobfuscated((FieldEntry) obfEntry); | 481 | this.renamer.markFieldAsDeobfuscated((FieldEntry) obfEntry); |
| 486 | } else if (obfEntry instanceof MethodEntry) { | 482 | } else if (obfEntry instanceof MethodEntry) { |
| 487 | m_renamer.markMethodTreeAsDeobfuscated((MethodEntry) obfEntry); | 483 | this.renamer.markMethodTreeAsDeobfuscated((MethodEntry) obfEntry); |
| 488 | } else if (obfEntry instanceof ConstructorEntry) { | 484 | } else if (obfEntry instanceof ConstructorEntry) { |
| 489 | throw new IllegalArgumentException("Cannot rename constructors"); | 485 | throw new IllegalArgumentException("Cannot rename constructors"); |
| 490 | } else if (obfEntry instanceof ArgumentEntry) { | 486 | } else if (obfEntry instanceof ArgumentEntry) { |
| 491 | m_renamer.markArgumentAsDeobfuscated((ArgumentEntry) obfEntry); | 487 | this.renamer.markArgumentAsDeobfuscated((ArgumentEntry) obfEntry); |
| 492 | } else { | 488 | } else { |
| 493 | throw new Error("Unknown entry type: " + obfEntry); | 489 | throw new Error("Unknown entry type: " + obfEntry); |
| 494 | } | 490 | } |
| 495 | 491 | ||
| 496 | // clear caches | 492 | // clear caches |
| 497 | m_translatorCache.clear(); | 493 | this.translatorCache.clear(); |
| 498 | } | 494 | } |
| 499 | } | 495 | } |