1616
1717package com .javadeobfuscator .deobfuscator ;
1818
19- import com .javadeobfuscator .deobfuscator .asm .ConstantPool ;
20- import com .javadeobfuscator .deobfuscator .config .Configuration ;
21- import com .javadeobfuscator .deobfuscator .config .TransformerConfig ;
22- import com .javadeobfuscator .deobfuscator .exceptions .NoClassInPathException ;
23- import com .javadeobfuscator .deobfuscator .rules .Rule ;
24- import com .javadeobfuscator .deobfuscator .rules .Rules ;
25- import com .javadeobfuscator .deobfuscator .transformers .Transformer ;
26- import com .javadeobfuscator .deobfuscator .utils .ClassTree ;
27- import com .javadeobfuscator .deobfuscator .utils .Utils ;
28- import org .apache .commons .io .IOUtils ;
29- import org .objectweb .asm .ClassReader ;
30- import org .objectweb .asm .ClassWriter ;
31- import org .objectweb .asm .Opcodes ;
32- import org .objectweb .asm .commons .JSRInlinerAdapter ;
33- import org .objectweb .asm .tree .AbstractInsnNode ;
34- import org .objectweb .asm .tree .ClassNode ;
35- import org .objectweb .asm .tree .MethodInsnNode ;
36- import org .objectweb .asm .tree .MethodNode ;
37- import org .objectweb .asm .util .CheckClassAdapter ;
38- import org .slf4j .Logger ;
39- import org .slf4j .LoggerFactory ;
40-
41- import java .io .File ;
42- import java .io .FileOutputStream ;
43- import java .io .IOException ;
44- import java .lang .reflect .Modifier ;
45- import java .util .AbstractMap .SimpleEntry ;
19+ import com .javadeobfuscator .deobfuscator .asm .*;
20+ import com .javadeobfuscator .deobfuscator .config .*;
21+ import com .javadeobfuscator .deobfuscator .exceptions .*;
22+ import com .javadeobfuscator .deobfuscator .rules .*;
23+ import com .javadeobfuscator .deobfuscator .transformers .*;
24+ import com .javadeobfuscator .deobfuscator .utils .*;
25+ import org .apache .commons .io .*;
26+ import org .objectweb .asm .*;
27+ import org .objectweb .asm .commons .*;
28+ import org .objectweb .asm .tree .*;
29+ import org .objectweb .asm .util .*;
30+ import org .slf4j .*;
31+
32+ import java .io .*;
33+ import java .lang .reflect .*;
34+ import java .util .AbstractMap .*;
4635import java .util .*;
47- import java .util .Map .Entry ;
48- import java .util .regex .Matcher ;
49- import java .util .regex .Pattern ;
50- import java .util .regex .PatternSyntaxException ;
51- import java .util .zip .ZipEntry ;
52- import java .util .zip .ZipFile ;
53- import java .util .zip .ZipOutputStream ;
36+ import java .util .Map .*;
37+ import java .util .regex .*;
38+ import java .util .zip .*;
5439
5540public class Deobfuscator {
5641 private Map <String , ClassNode > classpath = new HashMap <>();
@@ -83,6 +68,13 @@ public Deobfuscator(Configuration configuration) {
8368 * enable this to dump troublesome classes. Note that this will not get rid of all junk classes.
8469 */
8570 private static final boolean DELETE_USELESS_CLASSES = false ;
71+
72+ public Map <String , byte []> invaildClasses = new HashMap <>();
73+
74+ /**
75+ * Must enable for paramorphism obfuscated files.
76+ */
77+ private static final boolean PARAMORPHISM = false ;
8678
8779 public ConstantPool getConstantPool (ClassNode classNode ) {
8880 return this .constantPools .get (classNode );
@@ -176,26 +168,69 @@ private boolean isClassIgnored(ClassNode classNode) {
176168 }
177169
178170 private void loadInput () throws IOException {
171+ if (PARAMORPHISM )
172+ {
173+ Map <String , String > classNameToName = new HashMap <>();
174+ Map <String , byte []> entries = new HashMap <>();
175+ //Check all duplicate files
176+ try (ZipFile zipIn = new ZipFile (configuration .getInput ())) {
177+ Enumeration <? extends ZipEntry > e = zipIn .entries ();
178+ while (e .hasMoreElements ()) {
179+ ZipEntry next = e .nextElement ();
180+ if (next .isDirectory () || !next .getName ().endsWith (".class" )) {
181+ continue ;
182+ }
183+
184+ try {
185+ byte [] data = IOUtils .toByteArray (zipIn .getInputStream (next ));
186+ ClassReader reader = new ClassReader (data );
187+ ClassNode node = new ClassNode ();
188+ reader .accept (node , ClassReader .SKIP_FRAMES );
189+ if (entries .containsKey (node .name ))
190+ {
191+ invaildClasses .put (next .getName (), data );
192+ invaildClasses .put (classNameToName .get (node .name ), entries .get (node .name ));
193+ }else
194+ {
195+ classNameToName .put (node .name , next .getName ());
196+ entries .put (node .name , data );
197+ }
198+ }catch (Exception ex )
199+ {
200+ continue ;
201+ }
202+ }
203+ }
204+ //Filter out real classes
205+ List <String > real = new ArrayList <>();
206+ for (Entry <String , byte []> entry : invaildClasses .entrySet ())
207+ {
208+ ClassReader reader = new ClassReader (entry .getValue ());
209+ ClassNode node = new ClassNode ();
210+ reader .accept (node , ClassReader .SKIP_FRAMES );
211+ if ((node .name + ".class" ).equals (entry .getKey ()))
212+ real .add (entry .getKey ());
213+ }
214+ real .forEach (s -> invaildClasses .remove (s ));
215+ }
179216 try (ZipFile zipIn = new ZipFile (configuration .getInput ())) {
180217 Enumeration <? extends ZipEntry > e = zipIn .entries ();
181218 while (e .hasMoreElements ()) {
182219 ZipEntry next = e .nextElement ();
183- if (next .isDirectory () && ! next . getName (). endsWith ( ".class/" ) ) {
220+ if (next .isDirectory ()) {
184221 continue ;
185222 }
186223
187224 byte [] data = IOUtils .toByteArray (zipIn .getInputStream (next ));
188225 loadInput (next .getName (), data );
189226 }
190-
191- classpath .putAll (classes );
192227 }
193228 }
194229
195230 public void loadInput (String name , byte [] data ) {
196231 boolean passthrough = true ;
197232
198- if (name .endsWith (".class" ) || name . endsWith ( ".class/" ) ) {
233+ if (name .endsWith (".class" )) {
199234 try {
200235 ClassReader reader = new ClassReader (data );
201236 ClassNode node = new ClassNode ();
@@ -212,13 +247,17 @@ public void loadInput(String name, byte[] data) {
212247 node .methods .set (i , adapter );
213248 }
214249
215- classes .put (node .name , node );
250+ if (!invaildClasses .containsKey (name ))
251+ classes .put (node .name , node );
252+ classpath .put (node .name , node );
216253 passthrough = false ;
217254 } else {
218255 classpath .put (node .name , node );
219256 }
220- } catch (Exception x ) {
221- logger .error ("Could not parse {} (is it a class file?)" , name , x );
257+ } catch (IllegalArgumentException x ) {
258+ logger .error ("Could not parse {} (is it a class file?)" , name , x );
259+ } catch (ArrayIndexOutOfBoundsException x ) {
260+ logger .error ("Could not parse {} (is it a class file?)" , name , x );
222261 }
223262 }
224263
@@ -402,10 +441,6 @@ public List<ClassNode> loadHierachy(ClassNode specificNode) {
402441 if (specificNode .name .equals ("java/lang/Object" )) {
403442 return Collections .emptyList ();
404443 }
405- if ((specificNode .access & Opcodes .ACC_INTERFACE ) != 0 ) {
406- getOrCreateClassTree (specificNode .name ).parentClasses .add ("java/lang/Object" );
407- return Collections .emptyList ();
408- }
409444 List <ClassNode > toProcess = new ArrayList <>();
410445
411446 ClassTree thisTree = getOrCreateClassTree (specificNode .name );
0 commit comments