diff options
Diffstat (limited to 'src/cuchaz')
| -rw-r--r-- | src/cuchaz/enigma/Deobfuscator.java | 16 | ||||
| -rw-r--r-- | src/cuchaz/enigma/analysis/JarIndex.java | 31 | ||||
| -rw-r--r-- | src/cuchaz/enigma/analysis/SourceIndexBehaviorVisitor.java | 17 | ||||
| -rw-r--r-- | src/cuchaz/enigma/bytecode/InnerClassWriter.java | 14 | ||||
| -rw-r--r-- | src/cuchaz/enigma/mapping/SignatureUpdater.java | 2 |
5 files changed, 46 insertions, 34 deletions
diff --git a/src/cuchaz/enigma/Deobfuscator.java b/src/cuchaz/enigma/Deobfuscator.java index 1d6f02c9..9c845325 100644 --- a/src/cuchaz/enigma/Deobfuscator.java +++ b/src/cuchaz/enigma/Deobfuscator.java | |||
| @@ -232,7 +232,7 @@ public class Deobfuscator | |||
| 232 | sourceTree.acceptVisitor( new SourceIndexVisitor(), index ); | 232 | sourceTree.acceptVisitor( new SourceIndexVisitor(), index ); |
| 233 | 233 | ||
| 234 | // DEBUG | 234 | // DEBUG |
| 235 | //root.acceptVisitor( new TreeDumpVisitor( new File( "tree.txt" ) ), null ); | 235 | //sourceTree.acceptVisitor( new TreeDumpVisitor( new File( "tree.txt" ) ), null ); |
| 236 | 236 | ||
| 237 | /* DEBUG | 237 | /* DEBUG |
| 238 | for( Token token : index.referenceTokens() ) | 238 | for( Token token : index.referenceTokens() ) |
| @@ -420,19 +420,7 @@ public class Deobfuscator | |||
| 420 | { | 420 | { |
| 421 | if( obfEntry instanceof ClassEntry ) | 421 | if( obfEntry instanceof ClassEntry ) |
| 422 | { | 422 | { |
| 423 | ClassEntry obfClassEntry = (ClassEntry)obfEntry; | 423 | return m_jarIndex.getObfClassEntries().contains( obfEntry ); |
| 424 | if( obfClassEntry.isInnerClass() ) | ||
| 425 | { | ||
| 426 | // both classes must be in the list | ||
| 427 | return m_jarIndex.getObfClassEntries().contains( obfClassEntry.getOuterClassEntry() ) | ||
| 428 | && m_jarIndex.getObfClassEntries().contains( obfClassEntry.getInnerClassName() ); | ||
| 429 | // TODO: make sure this works for the inner class!! | ||
| 430 | } | ||
| 431 | else | ||
| 432 | { | ||
| 433 | // class must be in the list | ||
| 434 | return m_jarIndex.getObfClassEntries().contains( obfEntry ); | ||
| 435 | } | ||
| 436 | } | 424 | } |
| 437 | else | 425 | else |
| 438 | { | 426 | { |
diff --git a/src/cuchaz/enigma/analysis/JarIndex.java b/src/cuchaz/enigma/analysis/JarIndex.java index c36e9cb0..8ebce35e 100644 --- a/src/cuchaz/enigma/analysis/JarIndex.java +++ b/src/cuchaz/enigma/analysis/JarIndex.java | |||
| @@ -63,7 +63,7 @@ public class JarIndex | |||
| 63 | private Multimap<FieldEntry,EntryReference<FieldEntry,BehaviorEntry>> m_fieldReferences; | 63 | private Multimap<FieldEntry,EntryReference<FieldEntry,BehaviorEntry>> m_fieldReferences; |
| 64 | private Multimap<String,String> m_innerClasses; | 64 | private Multimap<String,String> m_innerClasses; |
| 65 | private Map<String,String> m_outerClasses; | 65 | private Map<String,String> m_outerClasses; |
| 66 | private Set<String> m_anonymousClasses; | 66 | private Map<String,BehaviorEntry> m_anonymousClasses; |
| 67 | private Map<MethodEntry,MethodEntry> m_bridgeMethods; | 67 | private Map<MethodEntry,MethodEntry> m_bridgeMethods; |
| 68 | 68 | ||
| 69 | public JarIndex( ) | 69 | public JarIndex( ) |
| @@ -78,7 +78,7 @@ public class JarIndex | |||
| 78 | m_fieldReferences = HashMultimap.create(); | 78 | m_fieldReferences = HashMultimap.create(); |
| 79 | m_innerClasses = HashMultimap.create(); | 79 | m_innerClasses = HashMultimap.create(); |
| 80 | m_outerClasses = Maps.newHashMap(); | 80 | m_outerClasses = Maps.newHashMap(); |
| 81 | m_anonymousClasses = Sets.newHashSet(); | 81 | m_anonymousClasses = Maps.newHashMap(); |
| 82 | m_bridgeMethods = Maps.newHashMap(); | 82 | m_bridgeMethods = Maps.newHashMap(); |
| 83 | } | 83 | } |
| 84 | 84 | ||
| @@ -161,9 +161,10 @@ public class JarIndex | |||
| 161 | m_innerClasses.put( outerClassName, innerClassName ); | 161 | m_innerClasses.put( outerClassName, innerClassName ); |
| 162 | m_outerClasses.put( innerClassName, outerClassName ); | 162 | m_outerClasses.put( innerClassName, outerClassName ); |
| 163 | 163 | ||
| 164 | if( isAnonymousClass( c, outerClassName ) ) | 164 | BehaviorEntry enclosingBehavior = isAnonymousClass( c, outerClassName ); |
| 165 | if( enclosingBehavior != null ) | ||
| 165 | { | 166 | { |
| 166 | m_anonymousClasses.add( innerClassName ); | 167 | m_anonymousClasses.put( innerClassName, enclosingBehavior ); |
| 167 | 168 | ||
| 168 | // DEBUG | 169 | // DEBUG |
| 169 | //System.out.println( "ANONYMOUS: " + outerClassName + "$" + innerClassName ); | 170 | //System.out.println( "ANONYMOUS: " + outerClassName + "$" + innerClassName ); |
| @@ -188,6 +189,7 @@ public class JarIndex | |||
| 188 | EntryRenamer.renameClassesInMultimap( renames, m_methodImplementations ); | 189 | EntryRenamer.renameClassesInMultimap( renames, m_methodImplementations ); |
| 189 | EntryRenamer.renameClassesInMultimap( renames, m_behaviorReferences ); | 190 | EntryRenamer.renameClassesInMultimap( renames, m_behaviorReferences ); |
| 190 | EntryRenamer.renameClassesInMultimap( renames, m_fieldReferences ); | 191 | EntryRenamer.renameClassesInMultimap( renames, m_fieldReferences ); |
| 192 | EntryRenamer.renameClassesInMap( renames, m_bridgeMethods ); | ||
| 191 | } | 193 | } |
| 192 | 194 | ||
| 193 | // step 6: update other indices with bridge method info | 195 | // step 6: update other indices with bridge method info |
| @@ -618,7 +620,7 @@ public class JarIndex | |||
| 618 | return true; | 620 | return true; |
| 619 | } | 621 | } |
| 620 | 622 | ||
| 621 | private boolean isAnonymousClass( CtClass c, String outerClassName ) | 623 | private BehaviorEntry isAnonymousClass( CtClass c, String outerClassName ) |
| 622 | { | 624 | { |
| 623 | ClassEntry innerClassEntry = new ClassEntry( Descriptor.toJvmName( c.getName() ) ); | 625 | ClassEntry innerClassEntry = new ClassEntry( Descriptor.toJvmName( c.getName() ) ); |
| 624 | 626 | ||
| @@ -631,13 +633,13 @@ public class JarIndex | |||
| 631 | // is abstract? | 633 | // is abstract? |
| 632 | if( Modifier.isAbstract( c.getModifiers() ) ) | 634 | if( Modifier.isAbstract( c.getModifiers() ) ) |
| 633 | { | 635 | { |
| 634 | return false; | 636 | return null; |
| 635 | } | 637 | } |
| 636 | 638 | ||
| 637 | // is there exactly one constructor? | 639 | // is there exactly one constructor? |
| 638 | if( c.getDeclaredConstructors().length != 1 ) | 640 | if( c.getDeclaredConstructors().length != 1 ) |
| 639 | { | 641 | { |
| 640 | return false; | 642 | return null; |
| 641 | } | 643 | } |
| 642 | CtConstructor constructor = c.getDeclaredConstructors()[0]; | 644 | CtConstructor constructor = c.getDeclaredConstructors()[0]; |
| 643 | 645 | ||
| @@ -646,7 +648,7 @@ public class JarIndex | |||
| 646 | Collection<EntryReference<BehaviorEntry,BehaviorEntry>> references = getBehaviorReferences( constructorEntry ); | 648 | Collection<EntryReference<BehaviorEntry,BehaviorEntry>> references = getBehaviorReferences( constructorEntry ); |
| 647 | if( references.size() != 1 ) | 649 | if( references.size() != 1 ) |
| 648 | { | 650 | { |
| 649 | return false; | 651 | return null; |
| 650 | } | 652 | } |
| 651 | 653 | ||
| 652 | // does the caller use this type? | 654 | // does the caller use this type? |
| @@ -657,7 +659,7 @@ public class JarIndex | |||
| 657 | if( fieldClass != null && fieldClass.equals( innerClassEntry ) ) | 659 | if( fieldClass != null && fieldClass.equals( innerClassEntry ) ) |
| 658 | { | 660 | { |
| 659 | // caller references this type, so it can't be anonymous | 661 | // caller references this type, so it can't be anonymous |
| 660 | return false; | 662 | return null; |
| 661 | } | 663 | } |
| 662 | } | 664 | } |
| 663 | for( BehaviorEntry behaviorEntry : getReferencedBehaviors( caller ) ) | 665 | for( BehaviorEntry behaviorEntry : getReferencedBehaviors( caller ) ) |
| @@ -668,12 +670,12 @@ public class JarIndex | |||
| 668 | if( className.equals( innerClassEntry.getName() ) ) | 670 | if( className.equals( innerClassEntry.getName() ) ) |
| 669 | { | 671 | { |
| 670 | // caller references this type, so it can't be anonymous | 672 | // caller references this type, so it can't be anonymous |
| 671 | return false; | 673 | return null; |
| 672 | } | 674 | } |
| 673 | } | 675 | } |
| 674 | } | 676 | } |
| 675 | 677 | ||
| 676 | return true; | 678 | return caller; |
| 677 | } | 679 | } |
| 678 | 680 | ||
| 679 | public Set<ClassEntry> getObfClassEntries( ) | 681 | public Set<ClassEntry> getObfClassEntries( ) |
| @@ -905,7 +907,12 @@ public class JarIndex | |||
| 905 | 907 | ||
| 906 | public boolean isAnonymousClass( String obfInnerClassName ) | 908 | public boolean isAnonymousClass( String obfInnerClassName ) |
| 907 | { | 909 | { |
| 908 | return m_anonymousClasses.contains( obfInnerClassName ); | 910 | return m_anonymousClasses.containsKey( obfInnerClassName ); |
| 911 | } | ||
| 912 | |||
| 913 | public BehaviorEntry getAnonymousClassCaller( String obfInnerClassName ) | ||
| 914 | { | ||
| 915 | return m_anonymousClasses.get( obfInnerClassName ); | ||
| 909 | } | 916 | } |
| 910 | 917 | ||
| 911 | public Set<String> getInterfaces( String className ) | 918 | public Set<String> getInterfaces( String className ) |
diff --git a/src/cuchaz/enigma/analysis/SourceIndexBehaviorVisitor.java b/src/cuchaz/enigma/analysis/SourceIndexBehaviorVisitor.java index a1dac4b5..6238b1e7 100644 --- a/src/cuchaz/enigma/analysis/SourceIndexBehaviorVisitor.java +++ b/src/cuchaz/enigma/analysis/SourceIndexBehaviorVisitor.java | |||
| @@ -177,14 +177,17 @@ public class SourceIndexBehaviorVisitor extends SourceIndexVisitor | |||
| 177 | public Void visitObjectCreationExpression( ObjectCreationExpression node, SourceIndex index ) | 177 | public Void visitObjectCreationExpression( ObjectCreationExpression node, SourceIndex index ) |
| 178 | { | 178 | { |
| 179 | MemberReference ref = node.getUserData( Keys.MEMBER_REFERENCE ); | 179 | MemberReference ref = node.getUserData( Keys.MEMBER_REFERENCE ); |
| 180 | ClassEntry classEntry = new ClassEntry( ref.getDeclaringType().getInternalName() ); | 180 | if( ref != null ) |
| 181 | ConstructorEntry constructorEntry = new ConstructorEntry( classEntry, ref.getSignature() ); | ||
| 182 | if( node.getType() instanceof SimpleType ) | ||
| 183 | { | 181 | { |
| 184 | index.addReference( | 182 | ClassEntry classEntry = new ClassEntry( ref.getDeclaringType().getInternalName() ); |
| 185 | ((SimpleType)node.getType()).getIdentifierToken(), | 183 | ConstructorEntry constructorEntry = new ConstructorEntry( classEntry, ref.getSignature() ); |
| 186 | new EntryReference<Entry,Entry>( constructorEntry, m_behaviorEntry ) | 184 | if( node.getType() instanceof SimpleType ) |
| 187 | ); | 185 | { |
| 186 | index.addReference( | ||
| 187 | ((SimpleType)node.getType()).getIdentifierToken(), | ||
| 188 | new EntryReference<Entry,Entry>( constructorEntry, m_behaviorEntry ) | ||
| 189 | ); | ||
| 190 | } | ||
| 188 | } | 191 | } |
| 189 | 192 | ||
| 190 | return recurse( node, index ); | 193 | return recurse( node, index ); |
diff --git a/src/cuchaz/enigma/bytecode/InnerClassWriter.java b/src/cuchaz/enigma/bytecode/InnerClassWriter.java index 5044e065..f94a85d7 100644 --- a/src/cuchaz/enigma/bytecode/InnerClassWriter.java +++ b/src/cuchaz/enigma/bytecode/InnerClassWriter.java | |||
| @@ -16,8 +16,10 @@ import javassist.CtClass; | |||
| 16 | import javassist.bytecode.AccessFlag; | 16 | import javassist.bytecode.AccessFlag; |
| 17 | import javassist.bytecode.ConstPool; | 17 | import javassist.bytecode.ConstPool; |
| 18 | import javassist.bytecode.Descriptor; | 18 | import javassist.bytecode.Descriptor; |
| 19 | import javassist.bytecode.EnclosingMethodAttribute; | ||
| 19 | import javassist.bytecode.InnerClassesAttribute; | 20 | import javassist.bytecode.InnerClassesAttribute; |
| 20 | import cuchaz.enigma.analysis.JarIndex; | 21 | import cuchaz.enigma.analysis.JarIndex; |
| 22 | import cuchaz.enigma.mapping.BehaviorEntry; | ||
| 21 | import cuchaz.enigma.mapping.ClassEntry; | 23 | import cuchaz.enigma.mapping.ClassEntry; |
| 22 | 24 | ||
| 23 | public class InnerClassWriter | 25 | public class InnerClassWriter |
| @@ -44,6 +46,18 @@ public class InnerClassWriter | |||
| 44 | // this is an inner class, rename it to outer$inner | 46 | // this is an inner class, rename it to outer$inner |
| 45 | ClassEntry obfClassEntry = new ClassEntry( obfOuterClassName + "$" + new ClassEntry( obfClassName ).getSimpleName() ); | 47 | ClassEntry obfClassEntry = new ClassEntry( obfOuterClassName + "$" + new ClassEntry( obfClassName ).getSimpleName() ); |
| 46 | c.setName( obfClassEntry.getName() ); | 48 | c.setName( obfClassEntry.getName() ); |
| 49 | |||
| 50 | BehaviorEntry caller = m_jarIndex.getAnonymousClassCaller( obfClassName ); | ||
| 51 | if( caller != null ) | ||
| 52 | { | ||
| 53 | // write the enclosing method attribute | ||
| 54 | c.getClassFile().addAttribute( new EnclosingMethodAttribute( | ||
| 55 | c.getClassFile().getConstPool(), | ||
| 56 | caller.getClassName(), | ||
| 57 | caller.getName(), | ||
| 58 | caller.getSignature() | ||
| 59 | ) ); | ||
| 60 | } | ||
| 47 | } | 61 | } |
| 48 | 62 | ||
| 49 | // write the inner classes if needed | 63 | // write the inner classes if needed |
diff --git a/src/cuchaz/enigma/mapping/SignatureUpdater.java b/src/cuchaz/enigma/mapping/SignatureUpdater.java index 528a7437..d1216bde 100644 --- a/src/cuchaz/enigma/mapping/SignatureUpdater.java +++ b/src/cuchaz/enigma/mapping/SignatureUpdater.java | |||
| @@ -14,7 +14,7 @@ import java.io.IOException; | |||
| 14 | import java.io.StringReader; | 14 | import java.io.StringReader; |
| 15 | import java.util.List; | 15 | import java.util.List; |
| 16 | 16 | ||
| 17 | import com.beust.jcommander.internal.Lists; | 17 | import com.google.common.collect.Lists; |
| 18 | 18 | ||
| 19 | public class SignatureUpdater | 19 | public class SignatureUpdater |
| 20 | { | 20 | { |