summaryrefslogtreecommitdiff
path: root/src/cuchaz/enigma/bytecode
diff options
context:
space:
mode:
authorGravatar jeff2014-08-18 00:55:30 -0400
committerGravatar jeff2014-08-18 00:55:30 -0400
commit34c1e8e64ec4575527a19fb4cb0640c57da784db (patch)
tree44e3f1d50f8d8b8a9ab7c26dd94b58cba750cc67 /src/cuchaz/enigma/bytecode
parentadded support for automatic reconstruction of inner and anonymous classes (diff)
downloadenigma-fork-34c1e8e64ec4575527a19fb4cb0640c57da784db.tar.gz
enigma-fork-34c1e8e64ec4575527a19fb4cb0640c57da784db.tar.xz
enigma-fork-34c1e8e64ec4575527a19fb4cb0640c57da784db.zip
crap-ton of bug fixes for inner classes
Diffstat (limited to 'src/cuchaz/enigma/bytecode')
-rw-r--r--src/cuchaz/enigma/bytecode/BytecodeTools.java57
-rw-r--r--src/cuchaz/enigma/bytecode/ClassTranslator.java53
-rw-r--r--src/cuchaz/enigma/bytecode/InnerClassWriter.java42
3 files changed, 116 insertions, 36 deletions
diff --git a/src/cuchaz/enigma/bytecode/BytecodeTools.java b/src/cuchaz/enigma/bytecode/BytecodeTools.java
index 664350e..0de9bd6 100644
--- a/src/cuchaz/enigma/bytecode/BytecodeTools.java
+++ b/src/cuchaz/enigma/bytecode/BytecodeTools.java
@@ -15,6 +15,7 @@ import java.io.ByteArrayOutputStream;
15import java.io.DataInputStream; 15import java.io.DataInputStream;
16import java.io.DataOutputStream; 16import java.io.DataOutputStream;
17import java.io.IOException; 17import java.io.IOException;
18import java.util.List;
18import java.util.Map; 19import java.util.Map;
19import java.util.Set; 20import java.util.Set;
20 21
@@ -25,6 +26,7 @@ import javassist.bytecode.CodeAttribute;
25import javassist.bytecode.ConstPool; 26import javassist.bytecode.ConstPool;
26import javassist.bytecode.ExceptionTable; 27import javassist.bytecode.ExceptionTable;
27 28
29import com.beust.jcommander.internal.Lists;
28import com.google.common.collect.Maps; 30import com.google.common.collect.Maps;
29import com.google.common.collect.Sets; 31import com.google.common.collect.Sets;
30 32
@@ -266,4 +268,59 @@ public class BytecodeTools
266 ); 268 );
267 } 269 }
268 } 270 }
271
272 public static List<String> getParameterTypes( String signature )
273 {
274 List<String> types = Lists.newArrayList();
275 for( int i=0; i<signature.length(); )
276 {
277 char c = signature.charAt( i );
278
279 // handle parens
280 if( c == '(' )
281 {
282 i++;
283 c = signature.charAt( i );
284 }
285 if( c == ')' )
286 {
287 break;
288 }
289
290 // find a type
291 String type = null;
292
293 int arrayDim = 0;
294 while( c == '[' )
295 {
296 // advance to array type
297 arrayDim++;
298 i++;
299 c = signature.charAt( i );
300 }
301
302 if( c == 'L' )
303 {
304 // read class type
305 int pos = signature.indexOf( ';', i + 1 );
306 String className = signature.substring( i + 1, pos );
307 type = "L" + className + ";";
308 i = pos + 1;
309 }
310 else
311 {
312 // read primitive type
313 type = signature.substring( i, i + 1 );
314 i++;
315 }
316
317 // was it an array?
318 while( arrayDim-- > 0 )
319 {
320 type = "[" + type;
321 }
322 types.add( type );
323 }
324 return types;
325 }
269} 326}
diff --git a/src/cuchaz/enigma/bytecode/ClassTranslator.java b/src/cuchaz/enigma/bytecode/ClassTranslator.java
index 3b5beeb..9ce06a5 100644
--- a/src/cuchaz/enigma/bytecode/ClassTranslator.java
+++ b/src/cuchaz/enigma/bytecode/ClassTranslator.java
@@ -10,7 +10,6 @@
10 ******************************************************************************/ 10 ******************************************************************************/
11package cuchaz.enigma.bytecode; 11package cuchaz.enigma.bytecode;
12 12
13import java.util.HashSet;
14import java.util.Set; 13import java.util.Set;
15 14
16import javassist.ClassMap; 15import javassist.ClassMap;
@@ -20,6 +19,10 @@ import javassist.CtField;
20import javassist.CtMethod; 19import javassist.CtMethod;
21import javassist.bytecode.ConstPool; 20import javassist.bytecode.ConstPool;
22import javassist.bytecode.Descriptor; 21import javassist.bytecode.Descriptor;
22import javassist.bytecode.InnerClassesAttribute;
23
24import com.beust.jcommander.internal.Sets;
25
23import cuchaz.enigma.mapping.ClassEntry; 26import cuchaz.enigma.mapping.ClassEntry;
24import cuchaz.enigma.mapping.FieldEntry; 27import cuchaz.enigma.mapping.FieldEntry;
25import cuchaz.enigma.mapping.MethodEntry; 28import cuchaz.enigma.mapping.MethodEntry;
@@ -133,25 +136,47 @@ public class ClassTranslator
133 136
134 // translate all the class names referenced in the code 137 // translate all the class names referenced in the code
135 // the above code only changed method/field/reference names and types, but not the class names themselves 138 // the above code only changed method/field/reference names and types, but not the class names themselves
136 Set<String> classNames = getAllClassNames( c ); 139 Set<ClassEntry> classEntries = getAllClassEntries( c );
137 ClassMap map = new ClassMap(); 140 ClassMap map = new ClassMap();
138 for( String className : classNames ) 141 for( ClassEntry obfClassEntry : classEntries )
139 { 142 {
140 String translatedName = m_translator.translateClass( className ); 143 map.put( obfClassEntry.getName(), m_translator.translateEntry( obfClassEntry ).getName() );
141 if( translatedName != null )
142 {
143 map.put( className, translatedName );
144 }
145 } 144 }
146 if( !map.isEmpty() ) 145 c.replaceClassName( map );
146
147 // translate the names in the InnerClasses attribute
148 InnerClassesAttribute attr = (InnerClassesAttribute)c.getClassFile().getAttribute( InnerClassesAttribute.tag );
149 if( attr != null )
147 { 150 {
148 c.replaceClassName( map ); 151 for( int i=0; i<attr.tableLength(); i++ )
152 {
153 ClassEntry obfClassEntry = new ClassEntry( Descriptor.toJvmName( attr.innerClass( i ) ) );
154 ClassEntry deobfClassEntry = m_translator.translateEntry( obfClassEntry );
155 attr.setInnerClassIndex( i, constants.addClassInfo( deobfClassEntry.getName() ) );
156 if( attr.outerClassIndex( i ) != 0 )
157 {
158 attr.setOuterClassIndex( i, constants.addClassInfo( deobfClassEntry.getOuterClassName() ) );
159 }
160 if( attr.innerNameIndex( i ) != 0 )
161 {
162 attr.setInnerNameIndex( i, constants.addUtf8Info( deobfClassEntry.getInnerClassName() ) );
163 }
164
165 /* DEBUG
166 System.out.println( String.format( "\tOBF: %s DEOBF: %s-> ATTR: %s,%s,%s",
167 obfClassEntry, deobfClassEntry,
168 attr.outerClass( i ),
169 attr.innerClass( i ),
170 attr.innerName( i )
171 ) );
172 */
173 }
149 } 174 }
150 } 175 }
151 176
152 private Set<String> getAllClassNames( CtClass c ) 177 private Set<ClassEntry> getAllClassEntries( CtClass c )
153 { 178 {
154 final Set<String> names = new HashSet<String>(); 179 final Set<ClassEntry> entries = Sets.newHashSet();
155 ClassMap map = new ClassMap( ) 180 ClassMap map = new ClassMap( )
156 { 181 {
157 @Override 182 @Override
@@ -159,13 +184,13 @@ public class ClassTranslator
159 { 184 {
160 if( obj instanceof String ) 185 if( obj instanceof String )
161 { 186 {
162 names.add( (String)obj ); 187 entries.add( new ClassEntry( (String)obj ) );
163 } 188 }
164 return null; 189 return null;
165 } 190 }
166 private static final long serialVersionUID = -202160293602070641L; 191 private static final long serialVersionUID = -202160293602070641L;
167 }; 192 };
168 c.replaceClassName( map ); 193 c.replaceClassName( map );
169 return names; 194 return entries;
170 } 195 }
171} 196}
diff --git a/src/cuchaz/enigma/bytecode/InnerClassWriter.java b/src/cuchaz/enigma/bytecode/InnerClassWriter.java
index b0e33ac..c412b1a 100644
--- a/src/cuchaz/enigma/bytecode/InnerClassWriter.java
+++ b/src/cuchaz/enigma/bytecode/InnerClassWriter.java
@@ -18,16 +18,14 @@ import javassist.bytecode.ConstPool;
18import javassist.bytecode.Descriptor; 18import javassist.bytecode.Descriptor;
19import javassist.bytecode.InnerClassesAttribute; 19import javassist.bytecode.InnerClassesAttribute;
20import cuchaz.enigma.analysis.JarIndex; 20import cuchaz.enigma.analysis.JarIndex;
21import cuchaz.enigma.mapping.Translator; 21import cuchaz.enigma.mapping.ClassEntry;
22 22
23public class InnerClassWriter 23public class InnerClassWriter
24{ 24{
25 private Translator m_deobfuscatingTranslator;
26 private JarIndex m_jarIndex; 25 private JarIndex m_jarIndex;
27 26
28 public InnerClassWriter( Translator deobfuscatingTranslator, JarIndex jarIndex ) 27 public InnerClassWriter( JarIndex jarIndex )
29 { 28 {
30 m_deobfuscatingTranslator = deobfuscatingTranslator;
31 m_jarIndex = jarIndex; 29 m_jarIndex = jarIndex;
32 } 30 }
33 31
@@ -44,7 +42,8 @@ public class InnerClassWriter
44 else 42 else
45 { 43 {
46 // this is an inner class, rename it to outer$inner 44 // this is an inner class, rename it to outer$inner
47 c.setName( obfOuterClassName + "$" + obfClassName ); 45 ClassEntry obfClassEntry = new ClassEntry( obfOuterClassName + "$" + obfClassName );
46 c.setName( obfClassEntry.getName() );
48 } 47 }
49 48
50 // write the inner classes if needed 49 // write the inner classes if needed
@@ -62,31 +61,20 @@ public class InnerClassWriter
62 for( String obfInnerClassName : obfInnerClassNames ) 61 for( String obfInnerClassName : obfInnerClassNames )
63 { 62 {
64 // deobfuscate the class names 63 // deobfuscate the class names
65 String deobfOuterClassName = m_deobfuscatingTranslator.translateClass( obfOuterClassName ); 64 ClassEntry obfClassEntry = new ClassEntry( obfOuterClassName + "$" + obfInnerClassName );
66 if( deobfOuterClassName == null ) 65
67 {
68 deobfOuterClassName = obfOuterClassName;
69 }
70 String obfOuterInnerClassName = obfOuterClassName + "$" + obfInnerClassName;
71 String deobfOuterInnerClassName = m_deobfuscatingTranslator.translateClass( obfOuterInnerClassName );
72 if( deobfOuterInnerClassName == null )
73 {
74 deobfOuterInnerClassName = obfOuterInnerClassName;
75 }
76 String deobfInnerClassName = deobfOuterInnerClassName.substring( deobfOuterInnerClassName.lastIndexOf( '$' ) + 1 );
77
78 // here's what the JVM spec says about the InnerClasses attribute 66 // here's what the JVM spec says about the InnerClasses attribute
79 // append( inner, outer of inner if inner is member of outer 0 ow, name after $ if inner not anonymous 0 ow, flags ); 67 // append( inner, outer of inner if inner is member of outer 0 ow, name after $ if inner not anonymous 0 ow, flags );
80 68
81 // update the attribute with this inner class 69 // update the attribute with this inner class
82 ConstPool constPool = c.getClassFile().getConstPool(); 70 ConstPool constPool = c.getClassFile().getConstPool();
83 int innerClassIndex = constPool.addClassInfo( deobfOuterInnerClassName ); 71 int innerClassIndex = constPool.addClassInfo( obfClassEntry.getName() );
84 int outerClassIndex = 0; 72 int outerClassIndex = 0;
85 int innerClassSimpleNameIndex = 0; 73 int innerClassSimpleNameIndex = 0;
86 if( !m_jarIndex.isAnonymousClass( obfInnerClassName ) ) 74 if( !m_jarIndex.isAnonymousClass( obfInnerClassName ) )
87 { 75 {
88 outerClassIndex = constPool.addClassInfo( deobfOuterClassName ); 76 outerClassIndex = constPool.addClassInfo( obfClassEntry.getOuterClassName() );
89 innerClassSimpleNameIndex = constPool.addUtf8Info( deobfInnerClassName ); 77 innerClassSimpleNameIndex = constPool.addUtf8Info( obfClassEntry.getInnerClassName() );
90 } 78 }
91 79
92 attr.append( 80 attr.append(
@@ -96,8 +84,18 @@ public class InnerClassWriter
96 c.getClassFile().getAccessFlags() & ~AccessFlag.SUPER 84 c.getClassFile().getAccessFlags() & ~AccessFlag.SUPER
97 ); 85 );
98 86
87 /* DEBUG
88 System.out.println( String.format( "\tOBF: %s -> ATTR: %s,%s,%s (replace %s with %s)",
89 obfClassEntry,
90 attr.outerClass( attr.tableLength() - 1 ),
91 attr.innerClass( attr.tableLength() - 1 ),
92 attr.innerName( attr.tableLength() - 1 ),
93 obfInnerClassName, obfClassEntry.getName()
94 ) );
95 */
96
99 // make sure the outer class references only the new inner class names 97 // make sure the outer class references only the new inner class names
100 c.replaceClassName( obfInnerClassName, deobfOuterInnerClassName ); 98 c.replaceClassName( obfInnerClassName, obfClassEntry.getName() );
101 } 99 }
102 } 100 }
103} 101}