From 268e8bd3a292162c215723638665e32415207c28 Mon Sep 17 00:00:00 2001 From: Thiakil Date: Thu, 12 Jul 2018 07:35:04 +0800 Subject: remove raw casts to Object --- src/main/java/cuchaz/enigma/Deobfuscator.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/main/java/cuchaz') diff --git a/src/main/java/cuchaz/enigma/Deobfuscator.java b/src/main/java/cuchaz/enigma/Deobfuscator.java index 6ea1c40..5b21011 100644 --- a/src/main/java/cuchaz/enigma/Deobfuscator.java +++ b/src/main/java/cuchaz/enigma/Deobfuscator.java @@ -34,6 +34,7 @@ import cuchaz.enigma.mapping.entry.*; import cuchaz.enigma.throwables.IllegalNameException; import cuchaz.enigma.utils.Utils; import oml.ast.transformers.ObfuscatedEnumSwitchRewriterTransform; +import oml.ast.transformers.RemoveObjectCasts; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.Opcodes; import org.objectweb.asm.tree.ClassNode; @@ -661,7 +662,8 @@ public class Deobfuscator { public static void runCustomTransforms(AstBuilder builder, DecompilerContext context){ List transformers = Arrays.asList( - new ObfuscatedEnumSwitchRewriterTransform(context) + new ObfuscatedEnumSwitchRewriterTransform(context), + new RemoveObjectCasts(context) ); for (IAstTransform transform : transformers){ transform.run(builder.getCompilationUnit()); -- cgit v1.2.3 From 4a8ee4303ca1ab82da9499181122bfd7e3214a05 Mon Sep 17 00:00:00 2001 From: Thiakil Date: Fri, 20 Jul 2018 12:14:38 +0800 Subject: recursively check ClassMapping dirty state --- src/main/java/cuchaz/enigma/mapping/ClassMapping.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'src/main/java/cuchaz') diff --git a/src/main/java/cuchaz/enigma/mapping/ClassMapping.java b/src/main/java/cuchaz/enigma/mapping/ClassMapping.java index 8f3f2b2..369ba8c 100644 --- a/src/main/java/cuchaz/enigma/mapping/ClassMapping.java +++ b/src/main/java/cuchaz/enigma/mapping/ClassMapping.java @@ -526,7 +526,16 @@ public class ClassMapping implements Comparable { } public boolean isDirty() { - return isDirty; + return isDirty || areInnersDirty(); + } + + private boolean areInnersDirty(){ + for (ClassMapping c : this.innerClasses()){ + if (c.isDirty()){ + return true; + } + } + return false; } public void resetDirty() { -- cgit v1.2.3 From c8e894dfa1485214ed3d4636e3a54689d722d439 Mon Sep 17 00:00:00 2001 From: modmuss50 Date: Sun, 22 Jul 2018 23:29:42 +0100 Subject: Fixed setBridged resetting the viability --- src/main/java/cuchaz/enigma/bytecode/AccessFlags.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main/java/cuchaz') diff --git a/src/main/java/cuchaz/enigma/bytecode/AccessFlags.java b/src/main/java/cuchaz/enigma/bytecode/AccessFlags.java index 21b2489..0bfc59b 100644 --- a/src/main/java/cuchaz/enigma/bytecode/AccessFlags.java +++ b/src/main/java/cuchaz/enigma/bytecode/AccessFlags.java @@ -51,7 +51,7 @@ public class AccessFlags { } public AccessFlags setBridged() { - this.setVisibility(Opcodes.ACC_BRIDGE); + flags |= Opcodes.ACC_BRIDGE; return this; } -- cgit v1.2.3 From 714c0297c2e4e389ac52c6378b590b77c7058594 Mon Sep 17 00:00:00 2001 From: modmuss50 Date: Sun, 22 Jul 2018 23:38:02 +0100 Subject: Make rebuildMethodNames use parallelStream's should improve the speed a lot let me know if it breaks anything --- src/main/java/cuchaz/enigma/Deobfuscator.java | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'src/main/java/cuchaz') diff --git a/src/main/java/cuchaz/enigma/Deobfuscator.java b/src/main/java/cuchaz/enigma/Deobfuscator.java index 5b21011..599387e 100644 --- a/src/main/java/cuchaz/enigma/Deobfuscator.java +++ b/src/main/java/cuchaz/enigma/Deobfuscator.java @@ -340,28 +340,28 @@ public class Deobfuscator { } public void rebuildMethodNames(ProgressListener progress) { - int i = 0; + final AtomicInteger i = new AtomicInteger(); Map> renameClassMap = new HashMap<>(); progress.init(getMappings().classes().size() * 3, "Rebuilding method names"); - for (ClassMapping classMapping : Lists.newArrayList(getMappings().classes())) { - progress.onProgress(i++, classMapping.getDeobfName()); + Lists.newArrayList(getMappings().classes()).parallelStream().forEach(classMapping -> { + progress.onProgress(i.getAndIncrement(), classMapping.getDeobfName()); rebuildMethodNames(classMapping, renameClassMap); - } + }); - for (Map.Entry> renameClassMapEntry : renameClassMap.entrySet()) { - progress.onProgress(i++, renameClassMapEntry.getKey().getDeobfName()); + renameClassMap.entrySet().parallelStream().forEach(renameClassMapEntry -> { + progress.onProgress(i.getAndIncrement(), renameClassMapEntry.getKey().getDeobfName()); for (Map.Entry entry : renameClassMapEntry.getValue().entrySet()) { Entry obfEntry = entry.getKey(); removeMapping(obfEntry); } - } + }); - for (Map.Entry> renameClassMapEntry : renameClassMap.entrySet()) { - progress.onProgress(i++, renameClassMapEntry.getKey().getDeobfName()); + renameClassMap.entrySet().parallelStream().forEach(renameClassMapEntry -> { + progress.onProgress(i.getAndIncrement(), renameClassMapEntry.getKey().getDeobfName()); for (Map.Entry entry : renameClassMapEntry.getValue().entrySet()) { Entry obfEntry = entry.getKey(); @@ -373,7 +373,7 @@ public class Deobfuscator { System.out.println("WARNING: " + exception.getMessage()); } } - } + }); } private void rebuildMethodNames(ClassMapping classMapping, Map> renameClassMap) { -- cgit v1.2.3 From 49e696255e9b623535679f228384ea45d4f89cfd Mon Sep 17 00:00:00 2001 From: Thiakil Date: Mon, 23 Jul 2018 12:41:19 +0800 Subject: fix source index tokens for inner classes that are not mapped --- src/main/java/cuchaz/enigma/analysis/SourceIndex.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'src/main/java/cuchaz') diff --git a/src/main/java/cuchaz/enigma/analysis/SourceIndex.java b/src/main/java/cuchaz/enigma/analysis/SourceIndex.java index 14b2e76..78195cb 100644 --- a/src/main/java/cuchaz/enigma/analysis/SourceIndex.java +++ b/src/main/java/cuchaz/enigma/analysis/SourceIndex.java @@ -17,15 +17,19 @@ import com.google.common.collect.Maps; import com.google.common.collect.Multimap; import com.strobel.decompiler.languages.Region; import com.strobel.decompiler.languages.java.ast.AstNode; +import com.strobel.decompiler.languages.java.ast.ConstructorDeclaration; import com.strobel.decompiler.languages.java.ast.Identifier; +import com.strobel.decompiler.languages.java.ast.TypeDeclaration; import cuchaz.enigma.mapping.entry.Entry; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.TreeMap; +import java.util.regex.Pattern; public class SourceIndex { + private static Pattern ANONYMOUS_INNER = Pattern.compile("\\$\\d+$"); private String source; private TreeMap> tokenToReference; @@ -81,6 +85,14 @@ public class SourceIndex { return null; } + if (node instanceof Identifier && name.indexOf('$') >=0 && node.getParent() instanceof ConstructorDeclaration && name.lastIndexOf('$') >= 0 && !ANONYMOUS_INNER.matcher(name).matches()){ + TypeDeclaration type = node.getParent().getParent() instanceof TypeDeclaration ? (TypeDeclaration) node.getParent().getParent() : null; + if (type != null){ + name = type.getName(); + token.end = token.start + name.length(); + } + } + // DEBUG // System.out.println( String.format( "%s \"%s\" region: %s", node.getNodeType(), name, region ) ); -- cgit v1.2.3 From 8c5d13ed87f92e982a3de489543f77da8a06d7ff Mon Sep 17 00:00:00 2001 From: Thiakil Date: Mon, 23 Jul 2018 13:07:16 +0800 Subject: remove injected DUP + getClass() + POP instructions --- .../java/cuchaz/enigma/TranslatingTypeLoader.java | 28 ++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'src/main/java/cuchaz') diff --git a/src/main/java/cuchaz/enigma/TranslatingTypeLoader.java b/src/main/java/cuchaz/enigma/TranslatingTypeLoader.java index eb780ee..8300f21 100644 --- a/src/main/java/cuchaz/enigma/TranslatingTypeLoader.java +++ b/src/main/java/cuchaz/enigma/TranslatingTypeLoader.java @@ -22,7 +22,10 @@ import cuchaz.enigma.mapping.entry.ReferencedEntryPool; import cuchaz.enigma.mapping.Translator; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.Opcodes; +import org.objectweb.asm.tree.AbstractInsnNode; import org.objectweb.asm.tree.ClassNode; +import org.objectweb.asm.tree.MethodInsnNode; +import org.objectweb.asm.tree.MethodNode; import java.util.List; @@ -89,6 +92,31 @@ public class TranslatingTypeLoader extends CachingTypeLoader implements ITransla return null; } + + // remove .getClass() calls that are seemingly injected + // DUP + // INVOKEVIRTUAL java/lang/Object.getClass ()Ljava/lang/Class; + // POP + for (MethodNode methodNode : node.methods){ + AbstractInsnNode insnNode = methodNode.instructions.getFirst(); + while (insnNode != null){ + if (insnNode instanceof MethodInsnNode && insnNode.getOpcode() == Opcodes.INVOKEVIRTUAL){ + MethodInsnNode methodInsnNode = (MethodInsnNode)insnNode; + if (methodInsnNode.name.equals("getClass") && methodInsnNode.owner.equals("java/lang/Object") && methodInsnNode.desc.equals("()Ljava/lang/Class")){ + AbstractInsnNode previous = methodInsnNode.getPrevious(); + AbstractInsnNode next = methodInsnNode.getNext(); + if (previous.getOpcode() == Opcodes.DUP && next.getOpcode() == Opcodes.POP){ + insnNode = previous.getPrevious();//reset the iterator so it gets the new next instruction + methodNode.instructions.remove(previous); + methodNode.instructions.remove(methodInsnNode); + methodNode.instructions.remove(next); + } + } + } + insnNode = insnNode.getNext(); + } + } + ClassWriter writer = new ClassWriter(0); transformInto(node, writer); -- cgit v1.2.3 From 7f914aa5d50f151ceff74f0764c9eafb2bebfd9a Mon Sep 17 00:00:00 2001 From: Thiakil Date: Mon, 23 Jul 2018 13:22:33 +0800 Subject: add support for the extra loader --- src/main/java/cuchaz/enigma/CachingClasspathTypeLoader.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'src/main/java/cuchaz') diff --git a/src/main/java/cuchaz/enigma/CachingClasspathTypeLoader.java b/src/main/java/cuchaz/enigma/CachingClasspathTypeLoader.java index 58682e2..fe13321 100644 --- a/src/main/java/cuchaz/enigma/CachingClasspathTypeLoader.java +++ b/src/main/java/cuchaz/enigma/CachingClasspathTypeLoader.java @@ -8,6 +8,12 @@ import com.strobel.assembler.metadata.ITypeLoader; * Caching version of {@link ClasspathTypeLoader} */ public class CachingClasspathTypeLoader extends CachingTypeLoader { + private static ITypeLoader extraClassPathLoader = null; + + public static void setExtraClassPathLoader(ITypeLoader loader){ + extraClassPathLoader = loader; + } + private final ITypeLoader classpathLoader = new ClasspathTypeLoader(); protected byte[] doLoad(String className) { @@ -15,6 +21,12 @@ public class CachingClasspathTypeLoader extends CachingTypeLoader { if (classpathLoader.tryLoadType(className, parentBuf)) { return parentBuf.array(); } + if (extraClassPathLoader != null){ + parentBuf.reset(); + if (extraClassPathLoader.tryLoadType(className, parentBuf)){ + return parentBuf.array(); + } + } return EMPTY_ARRAY;//need to return *something* as null means no store } } -- cgit v1.2.3 From 9085c79abc2eb96f232757a803ab1b5f8359eda8 Mon Sep 17 00:00:00 2001 From: Thiakil Date: Mon, 23 Jul 2018 15:14:19 +0800 Subject: missed a semicolon --- src/main/java/cuchaz/enigma/TranslatingTypeLoader.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main/java/cuchaz') diff --git a/src/main/java/cuchaz/enigma/TranslatingTypeLoader.java b/src/main/java/cuchaz/enigma/TranslatingTypeLoader.java index 8300f21..42ceec4 100644 --- a/src/main/java/cuchaz/enigma/TranslatingTypeLoader.java +++ b/src/main/java/cuchaz/enigma/TranslatingTypeLoader.java @@ -102,7 +102,7 @@ public class TranslatingTypeLoader extends CachingTypeLoader implements ITransla while (insnNode != null){ if (insnNode instanceof MethodInsnNode && insnNode.getOpcode() == Opcodes.INVOKEVIRTUAL){ MethodInsnNode methodInsnNode = (MethodInsnNode)insnNode; - if (methodInsnNode.name.equals("getClass") && methodInsnNode.owner.equals("java/lang/Object") && methodInsnNode.desc.equals("()Ljava/lang/Class")){ + if (methodInsnNode.name.equals("getClass") && methodInsnNode.owner.equals("java/lang/Object") && methodInsnNode.desc.equals("()Ljava/lang/Class;")){ AbstractInsnNode previous = methodInsnNode.getPrevious(); AbstractInsnNode next = methodInsnNode.getNext(); if (previous.getOpcode() == Opcodes.DUP && next.getOpcode() == Opcodes.POP){ -- cgit v1.2.3 From 8537f73abcf45e4380cf86d29404f61f0c9d88fe Mon Sep 17 00:00:00 2001 From: Thiakil Date: Tue, 24 Jul 2018 22:36:08 +0800 Subject: more custom source transformers --- src/main/java/cuchaz/enigma/Deobfuscator.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src/main/java/cuchaz') diff --git a/src/main/java/cuchaz/enigma/Deobfuscator.java b/src/main/java/cuchaz/enigma/Deobfuscator.java index 599387e..2642424 100644 --- a/src/main/java/cuchaz/enigma/Deobfuscator.java +++ b/src/main/java/cuchaz/enigma/Deobfuscator.java @@ -33,8 +33,11 @@ import cuchaz.enigma.mapping.*; import cuchaz.enigma.mapping.entry.*; import cuchaz.enigma.throwables.IllegalNameException; import cuchaz.enigma.utils.Utils; +import oml.ast.transformers.InvalidIdentifierFix; +import oml.ast.transformers.Java8Generics; import oml.ast.transformers.ObfuscatedEnumSwitchRewriterTransform; import oml.ast.transformers.RemoveObjectCasts; +import oml.ast.transformers.VaragsFixer; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.Opcodes; import org.objectweb.asm.tree.ClassNode; @@ -663,7 +666,10 @@ public class Deobfuscator { public static void runCustomTransforms(AstBuilder builder, DecompilerContext context){ List transformers = Arrays.asList( new ObfuscatedEnumSwitchRewriterTransform(context), - new RemoveObjectCasts(context) + new VaragsFixer(context), + new RemoveObjectCasts(context), + new Java8Generics(), + new InvalidIdentifierFix() ); for (IAstTransform transform : transformers){ transform.run(builder.getCompilationUnit()); -- cgit v1.2.3 From 34df974decb5f934ce87ad801f5dadea8c905f43 Mon Sep 17 00:00:00 2001 From: Thiakil Date: Tue, 24 Jul 2018 22:36:35 +0800 Subject: match the keybind to what the UI says --- src/main/java/cuchaz/enigma/gui/panels/PanelEditor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main/java/cuchaz') diff --git a/src/main/java/cuchaz/enigma/gui/panels/PanelEditor.java b/src/main/java/cuchaz/enigma/gui/panels/PanelEditor.java index fd30e38..ffceae1 100644 --- a/src/main/java/cuchaz/enigma/gui/panels/PanelEditor.java +++ b/src/main/java/cuchaz/enigma/gui/panels/PanelEditor.java @@ -56,7 +56,7 @@ public class PanelEditor extends JEditorPane { gui.popupMenu.showCallsMenu.doClick(); break; - case KeyEvent.VK_T: + case KeyEvent.VK_O: gui.popupMenu.toggleMappingMenu.doClick(); break; case KeyEvent.VK_F5: -- cgit v1.2.3 From 0993c18bc44b35fad25af05f50c7efde3e85fec4 Mon Sep 17 00:00:00 2001 From: Thiakil Date: Tue, 24 Jul 2018 22:40:03 +0800 Subject: use a common metadata (no-retry) instance to decompile all the files, similar to the procyon standalone decompiler --- src/main/java/cuchaz/enigma/Deobfuscator.java | 39 +++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) (limited to 'src/main/java/cuchaz') diff --git a/src/main/java/cuchaz/enigma/Deobfuscator.java b/src/main/java/cuchaz/enigma/Deobfuscator.java index 2642424..f42b59f 100644 --- a/src/main/java/cuchaz/enigma/Deobfuscator.java +++ b/src/main/java/cuchaz/enigma/Deobfuscator.java @@ -15,6 +15,7 @@ import com.google.common.base.Stopwatch; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Sets; +import com.strobel.assembler.metadata.ITypeLoader; import com.strobel.assembler.metadata.MetadataSystem; import com.strobel.assembler.metadata.TypeDefinition; import com.strobel.assembler.metadata.TypeReference; @@ -44,6 +45,7 @@ import org.objectweb.asm.tree.ClassNode; import java.io.*; import java.util.*; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicInteger; import java.util.jar.JarEntry; import java.util.jar.JarFile; @@ -173,6 +175,10 @@ public class Deobfuscator { } public CompilationUnit getSourceTree(String className, ITranslatingTypeLoader loader) { + return getSourceTree(className, loader, new NoRetryMetadataSystem(loader)); + } + + public CompilationUnit getSourceTree(String className, ITranslatingTypeLoader loader, MetadataSystem metadataSystem) { // we don't know if this class name is obfuscated or deobfuscated // we need to tell the decompiler the deobfuscated name so it doesn't get freaked out @@ -191,7 +197,7 @@ public class Deobfuscator { this.settings.setTypeLoader(loader); // see if procyon can find the desc - TypeReference type = new MetadataSystem(loader).lookupType(deobfClassName); + TypeReference type = metadataSystem.lookupType(deobfClassName); if (type == null) { throw new Error(String.format("Unable to find desc: %s (deobf: %s)\nTried class names: %s", className, deobfClassName, loader.getClassNamesToTry(deobfClassName) @@ -281,6 +287,9 @@ public class Deobfuscator { //synchronized to make sure the parallelStream doesn't CME with the cache ITranslatingTypeLoader typeLoader = new SynchronizedTypeLoader(createTypeLoader()); + MetadataSystem metadataSystem = new NoRetryMetadataSystem(typeLoader); + metadataSystem.setEagerMethodLoadingEnabled(true);//ensures methods are loaded on classload and prevents race conditions + // DEOBFUSCATE ALL THE THINGS!! @_@ Stopwatch stopwatch = Stopwatch.createStarted(); AtomicInteger count = new AtomicInteger(); @@ -292,7 +301,7 @@ public class Deobfuscator { try { // get the source - CompilationUnit sourceTree = getSourceTree(obfClassEntry.getName(), typeLoader); + CompilationUnit sourceTree = getSourceTree(obfClassEntry.getName(), typeLoader, metadataSystem); // write the file File file = new File(dirOut, deobfClassEntry.getName().replace('.', '/') + ".java"); @@ -686,4 +695,30 @@ public class Deobfuscator { String transform(ClassNode node, ClassWriter writer); } + public static class NoRetryMetadataSystem extends MetadataSystem { + private final Set _failedTypes = Collections.newSetFromMap(new ConcurrentHashMap<>()); + + public NoRetryMetadataSystem(final ITypeLoader typeLoader) { + super(typeLoader); + } + + @Override + protected synchronized TypeDefinition resolveType(final String descriptor, final boolean mightBePrimitive) { + if (_failedTypes.contains(descriptor)) { + return null; + } + + final TypeDefinition result = super.resolveType(descriptor, mightBePrimitive); + + if (result == null) { + _failedTypes.add(descriptor); + } + + return result; + } + + public synchronized TypeDefinition resolve(final TypeReference type) { + return super.resolve(type); + } + } } -- cgit v1.2.3 From 6fd948d323e3819d4fe7f15fbf64113d55de24b4 Mon Sep 17 00:00:00 2001 From: Thiakil Date: Tue, 24 Jul 2018 22:40:51 +0800 Subject: "make sure this is actually a field" properly --- src/main/java/cuchaz/enigma/analysis/SourceIndexMethodVisitor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main/java/cuchaz') diff --git a/src/main/java/cuchaz/enigma/analysis/SourceIndexMethodVisitor.java b/src/main/java/cuchaz/enigma/analysis/SourceIndexMethodVisitor.java index 83fe296..83e5e04 100644 --- a/src/main/java/cuchaz/enigma/analysis/SourceIndexMethodVisitor.java +++ b/src/main/java/cuchaz/enigma/analysis/SourceIndexMethodVisitor.java @@ -76,7 +76,7 @@ public class SourceIndexMethodVisitor extends SourceIndexVisitor { @Override public Void visitMemberReferenceExpression(MemberReferenceExpression node, SourceIndex index) { MemberReference ref = node.getUserData(Keys.MEMBER_REFERENCE); - if (ref != null) { + if (ref instanceof FieldReference) { // make sure this is actually a field String erasedSignature = ref.getErasedSignature(); if (erasedSignature.indexOf('(') >= 0) { -- cgit v1.2.3