16
16
import java .util .zip .ZipFile ;
17
17
import java .util .zip .ZipOutputStream ;
18
18
19
+ import org .apache .commons .cli .*;
19
20
import org .objectweb .asm .ClassWriter ;
20
21
import org .objectweb .asm .tree .ClassNode ;
21
22
import org .objectweb .asm .tree .InnerClassNode ;
@@ -32,102 +33,113 @@ public class Main extends Thread {
32
33
public ArrayList <ClassFile > files = new ArrayList <ClassFile >();
33
34
public HashMap <String , ClassNode > nameToNode = new HashMap <String , ClassNode >();
34
35
public HashMap <ClassNode , String > nodeToName = new HashMap <ClassNode , String >();
36
+ public String [] libraries ;
35
37
public ArrayList <Library > loadedAPI = new ArrayList <Library >();
36
- public ArrayList <File > paths = new ArrayList <File >();
37
38
public String [] usedTransformers ;
38
39
public HashMap <String , Integer > pkgLens = new HashMap <String , Integer >();
39
40
public SmartNameGen nameGen ;
40
41
public String [] args ;
42
+ public CommandLine cmd ;
41
43
42
44
public static Main getInstance () {
43
45
return instance ;
44
46
}
45
47
46
- private void checkArgs () throws Throwable {
47
- if (args .length < 5 ) {
48
- System .out
49
- .println ("Usage: java -jar NeonObf.jar <jar_to_obfuscate> <jar_to_obfuscate_out> </path/to/libs/> <transformers> <min/norm/max>" );
50
- throw new Throwable ();
51
- }
52
-
53
- for (int i = 0 ; i < args .length ; i ++)
54
- if (parseArg (args [i ], i , args )) {
55
- checkArgs ();
56
- break ;
57
- }
58
- }
59
-
60
48
/***
61
49
* Parses argument
62
- *
63
- * @param arg
64
- * Argument from massive
65
- * @param index
66
- * Index of argument in massive
67
- * @param args
68
- * All arguments
69
- * @return Needed in restart argument checking?
50
+ *
70
51
* @throws Throwable
71
52
*/
72
- public boolean parseArg (String arg , int index , String [] args ) throws Throwable {
73
- File f ;
74
- switch (index ) {
75
- case 0 :
76
- if (!(f = new File (arg )).exists ())
77
- throw new Throwable ("Jar to obfuscate not found :L" );
78
- inF = f ;
53
+ public void parseArgs () throws Throwable {
54
+ Options options = new Options ();
79
55
80
- break ;
81
- case 1 :
82
- if ((f = new File (arg )).exists ()) {
83
- String postfix = "." + new Random ().nextInt (100 );
84
- args [1 ] += postfix ;
85
- System .out .println ("Out file already exists. Using " + postfix );
86
- return true ;
87
- }
88
- outF = f ;
56
+ Option inputArg = new Option ("i" , "input" , true , "Input .jar/.class file/folder path" );
57
+ inputArg .setRequired (true );
58
+ inputArg .setArgName ("path" );
59
+ options .addOption (inputArg );
60
+
61
+ Option outputArg = new Option ("o" , "output" , true , "Output .jar path" );
62
+ outputArg .setRequired (true );
63
+ outputArg .setArgName ("path" );
64
+ options .addOption (outputArg );
65
+
66
+ Option librariesArg = new Option ("l" , "libraries" , true , "Libraries path (separated by semicolons/multiple arguments)" );
67
+ librariesArg .setRequired (false );
68
+ librariesArg .setArgName ("path" );
69
+ options .addOption (librariesArg );
70
+
71
+ Option transformersArg = new Option ("t" , "transformers" , true , "Transformers (separated by semicolons/multiple arguments)" );
72
+ transformersArg .setRequired (true );
73
+ transformersArg .setArgName ("transformers" );
74
+ options .addOption (transformersArg );
75
+
76
+ Option dictionaryArg = new Option ("d" , "dictionary" , true , "Dictionary type" );
77
+ dictionaryArg .setRequired (true );
78
+ dictionaryArg .setArgName ("1/2/3" );
79
+ options .addOption (dictionaryArg );
80
+
81
+ CommandLineParser parser = new DefaultParser ();
82
+ HelpFormatter formatter = new HelpFormatter ();
83
+
84
+ try {
85
+ cmd = parser .parse (options , args );
86
+ } catch (ParseException e ) {
87
+ System .out .println (e .getMessage ());
88
+ formatter .printHelp ("java -jar NeonObf.jar" , options , true );
89
+ System .out .println ("Example: java -jar NeonObf.jar --input IN.jar --output OUT.jar --transformers SourceFileRemover;LineNumberObfuscation;FinalRemover;LocalVariableNameObfuscator;BasicTypesEncryption;GotoFloodObfuscation;CodeHider --dictionary 3" );
90
+
91
+ System .exit (1 );
92
+ return ;
93
+ }
94
+
95
+ if (!(inF = new File (cmd .getOptionValue ("input" ))).exists ())
96
+ throw new Throwable ("Error: Input file does not exist." );
97
+
98
+ if ((outF = new File (cmd .getOptionValue ("output" ))).exists ())
99
+ throw new Throwable ("Error: Output file already exists." );
100
+
101
+ ArrayList <String > librariesList = new ArrayList <>();
102
+ if (cmd .hasOption ("libraries" ))
103
+ for (String libraryName1 : cmd .getOptionValues ("libraries" ))
104
+ for (String libraryName2 : libraryName1 .split (";" ))
105
+ librariesList .add (libraryName2 );
106
+ libraries = librariesList .toArray (new String [librariesList .size ()]);
89
107
108
+ ArrayList <String > usedTransformersList = new ArrayList <>();
109
+ for (String transformerName1 : cmd .getOptionValues ("transformers" ))
110
+ for (String transformerName2 : transformerName1 .split (";" ))
111
+ usedTransformersList .add (transformerName2 );
112
+ usedTransformers = usedTransformersList .toArray (new String [usedTransformersList .size ()]);
113
+
114
+ int dictiounary ;
115
+ try {
116
+ dictiounary = Integer .parseInt (cmd .getOptionValue ("dictionary" ));
117
+ } catch (NumberFormatException t ) {
118
+ throw new Throwable ("Dictionary must be a number (1-3)" );
119
+ }
120
+ switch (dictiounary ) {
121
+ case 1 :
122
+ nameGen = new SmartNameGen ("abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789" + "_" );
90
123
break ;
91
124
case 2 :
92
- if (!(f = new File (arg )).exists () && !arg .equalsIgnoreCase ("null" ))
93
- throw new Throwable (".JAR/.class/folder with libraries must exist! (it can be empty folder or \' null\' )" );
94
-
125
+ nameGen = new SmartNameGen ("abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789" + "_.#{}" );
95
126
break ;
96
127
case 3 :
97
- usedTransformers = arg .split (";" );
98
-
99
- break ;
100
- case 4 :
101
- if (arg .equalsIgnoreCase ("min" ))
102
- nameGen = new SmartNameGen ("abcdefghijklmnopqrstuvwxyz"
103
- + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789" + "_" );
104
- else
105
- if (arg .equalsIgnoreCase ("norm" ))
106
- nameGen = new SmartNameGen ("abcdefghijklmnopqrstuvwxyz"
107
- + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789" + "_.#{}" );
108
- else
109
- if (arg .equalsIgnoreCase ("max" ))
110
- nameGen = new SmartNameGen ("\r " + "\t " );
111
- else
112
- throw new Throwable ("Arg " + index + " is not valid. Arg is " + arg );
113
-
114
- //existTransformers.put("AntiMemoryDump", new AntiMemoryDump());
115
- transformers .put ("BasicTypesEncryption" , new BasicTypesEncryption ());
116
- transformers .put ("CodeHider" , new CodeHider ());
117
- transformers .put ("FinalRemover" , new FinalRemover ());
118
- transformers .put ("GotoFloodObfuscation" , new GotoFloodObfuscation ());
119
- transformers .put ("LineNumberObfuscation" , new LineNumberObfuscation ());
120
- transformers .put ("LocalVariableNameObfuscator" , new LocalVariableNameObfuscator ());
121
- transformers .put ("SourceFileRemover" , new SourceFileRemover ());
122
- transformers .put ("TryCatch" , new TryCatch ());
123
-
128
+ nameGen = new SmartNameGen ("\r " + "\t " );
124
129
break ;
125
130
default :
126
- System .out .println ("Arg " + index + " is excess." );
127
- break ;
131
+ throw new Throwable ("Dictionary number must be in range of 1 to 3" );
128
132
}
129
133
130
- return false ;
134
+ //existTransformers.put("AntiMemoryDump", new AntiMemoryDump());
135
+ transformers .put ("BasicTypesEncryption" , new BasicTypesEncryption ());
136
+ transformers .put ("CodeHider" , new CodeHider ());
137
+ transformers .put ("FinalRemover" , new FinalRemover ());
138
+ transformers .put ("GotoFloodObfuscation" , new GotoFloodObfuscation ());
139
+ transformers .put ("LineNumberObfuscation" , new LineNumberObfuscation ());
140
+ transformers .put ("LocalVariableNameObfuscator" , new LocalVariableNameObfuscator ());
141
+ transformers .put ("SourceFileRemover" , new SourceFileRemover ());
142
+ transformers .put ("TryCatch" , new TryCatch ());
131
143
}
132
144
133
145
public static boolean isEmpty (MethodNode mn ) {
@@ -150,7 +162,7 @@ public void run() {
150
162
try {
151
163
printLogo ();
152
164
try {
153
- checkArgs ();
165
+ parseArgs ();
154
166
} catch (Throwable t ) {
155
167
String msg = t .getMessage ();
156
168
if (msg != null )
@@ -161,10 +173,9 @@ public void run() {
161
173
162
174
System .out .println ("Loading java APIs..." );
163
175
new DirWalker (new File (System .getProperty ("java.home" ) + File .separatorChar + "lib" ), true );
164
- if (!args [2 ].equalsIgnoreCase ("null" )) {
165
- System .out .println ("Loading user APIs..." );
166
- new DirWalker (new File (args [2 ]), true );
167
- }
176
+ System .out .println ("Loading user APIs..." );
177
+ for (String lib : libraries )
178
+ new DirWalker (new File (lib ), true );
168
179
System .out .println ("All APIs loaded!" );
169
180
170
181
System .out .println ("--------------------------------------------------" );
@@ -186,8 +197,11 @@ public void run() {
186
197
for (String transformerName : usedTransformers ) {
187
198
System .out .println ("Started transformation with " + transformerName + " transformer" );
188
199
189
- modClasses = transformers .get (transformerName ).obfuscate (modClasses );
190
-
200
+ try {
201
+ modClasses = transformers .get (transformerName ).obfuscate (modClasses );
202
+ } catch (NullPointerException npe ) {
203
+ throw new Throwable ("Transformer name \" " + transformerName + "\" aren't defined in Main#transformers." , npe );
204
+ }
191
205
System .out .println ("Transformation completed with " + transformerName + " transformer" );
192
206
}
193
207
@@ -202,7 +216,7 @@ public void run() {
202
216
saveAll ();
203
217
System .out .println ("All classes saved!" );
204
218
} catch (Throwable t ) {
205
- t . printStackTrace ( );
219
+ System . out . println ( t . getMessage () );
206
220
}
207
221
}
208
222
@@ -251,7 +265,7 @@ public static String getDateTag() {
251
265
252
266
public byte [] dump (ClassNode node , boolean autoAdd ) {
253
267
if (node .innerClasses != null )
254
- ((List <InnerClassNode >) node .innerClasses ).stream ().filter (in -> in .innerName != null ).forEach (in -> {
268
+ ((List <InnerClassNode >) node .innerClasses ).parallelStream ().filter (in -> in .innerName != null ).forEach (in -> {
255
269
if (in .innerName .indexOf ('/' ) != -1 )
256
270
in .innerName = in .innerName .substring (in .innerName .lastIndexOf ('/' ) + 1 ); // Stringer
257
271
});
0 commit comments