Skip to content

Commit 7518e7c

Browse files
author
Nikita
authored
Added Stream API for loading, now all timings are in milliseconds (#4)
- Added Stream API for loading - Now all timings are in milliseconds
1 parent 929031c commit 7518e7c

12 files changed

+112
-135
lines changed

com/neonObf/CustomClassWriter.java

+14-14
Original file line numberDiff line numberDiff line change
@@ -100,19 +100,19 @@ private String getCommonSuperClass0(String type1, String type2) {
100100
if (isAssignableFrom(type1, type2))
101101
return type1;
102102
else
103-
if (isAssignableFrom(type2, type1))
104-
return type2;
105-
else
106-
if (Modifier.isInterface(first.access)
107-
|| Modifier.isInterface(second.access))
108-
return "java/lang/Object";
109-
else {
110-
do {
111-
type1 = first.superName;
112-
first = assureLoaded(type1);
113-
} while (!isAssignableFrom(type1, type2));
114-
return type1;
115-
}
103+
if (isAssignableFrom(type2, type1))
104+
return type2;
105+
else
106+
if (Modifier.isInterface(first.access)
107+
|| Modifier.isInterface(second.access))
108+
return "java/lang/Object";
109+
else {
110+
do {
111+
type1 = first.superName;
112+
first = assureLoaded(type1);
113+
} while (!isAssignableFrom(type1, type2));
114+
return type1;
115+
}
116116
}
117117

118118
private String getCommonSuperClass1(String type1, String type2) {
@@ -200,4 +200,4 @@ public static InputStream getClass(File f, String className) {
200200
} catch(Throwable t) { }
201201
return null;
202202
}
203-
}
203+
}

com/neonObf/DirWalker.java

+36-18
Original file line numberDiff line numberDiff line change
@@ -3,28 +3,44 @@
33

44
import java.io.File;
55
import java.util.ArrayList;
6+
import java.util.Arrays;
67
import java.util.Collections;
78
import java.util.zip.ZipFile;
89

910
import org.objectweb.asm.ClassReader;
1011

1112
public class DirWalker {
12-
public DirWalker(File file, boolean isLibrary) throws Throwable {
13+
public DirWalker(File file, boolean isLibrary) {
1314
String name = file.getName();
1415
String path = file.getAbsolutePath();
1516
if (file.isDirectory()) {
1617
if (file.listFiles() != null && !path.endsWith(".donot"))
17-
for(File f : file.listFiles())
18-
if (!(f.getName().charAt(0) == '.' || f.getName().charAt(0) == '$'))
19-
new DirWalker(f, isLibrary);
20-
} else
18+
Arrays.stream(file.listFiles())
19+
.filter(f -> f.isDirectory() || !(!(f.getName().endsWith(".class") || f.getName().endsWith(".jar") || f.getName().endsWith(".zip")) || f.getName().charAt(0) == '.' || f.getName().charAt(0) == '$' || f.getName().equals("module-info.class")))
20+
.forEach(f -> {
21+
try {
22+
new DirWalker(f, isLibrary);
23+
} catch (Throwable t) {
24+
t.printStackTrace();
25+
}
26+
});
27+
} else {
2128
if (file.isFile() && name.lastIndexOf('.') > -1) {
22-
if (name.endsWith("jar"))
23-
loadZIP(new File(path), isLibrary);
24-
if (name.endsWith("class"))
25-
if(!name.equals("module-info.class"))
26-
loadClass(new File(path), isLibrary);
29+
name = name.toLowerCase();
30+
if(name.endsWith(".jar") || name.endsWith(".zip"))
31+
try {
32+
loadZIP(file, isLibrary);
33+
} catch(Throwable t) {
34+
new Throwable("Failed to load JAR @ " + path, t).printStackTrace();
35+
}
36+
if(name.endsWith(".class"))
37+
try {
38+
loadClass(file, isLibrary);
39+
} catch(Throwable t) {
40+
new Throwable("Failed to load class @ " + path, t).printStackTrace();
41+
}
2742
}
43+
}
2844
}
2945

3046
public void loadClass(File f, boolean isLibrary) throws Throwable {
@@ -41,17 +57,19 @@ public void loadZIP(File f, boolean isLibrary) throws Throwable {
4157
Main inst = Main.getInstance();
4258
final ZipFile zipIn = new ZipFile(f);
4359
ArrayList<String> classList = new ArrayList<>();
44-
Collections.list(zipIn.entries()).forEach((next) -> {
45-
try {
46-
if (next.getName().endsWith(".class") && !next.getName().equals("module-info.class"))
60+
Collections.list(zipIn.entries())
61+
.stream()
62+
.filter(next -> (next.getName().endsWith(".class") && !next.getName().equals("module-info.class")))
63+
.forEach(next -> {
4764
if (isLibrary)
4865
classList.add(next.getName().replaceAll("(.*)\\.class", "$1"));
4966
else
50-
inst.classes.add(CustomClassWriter.loadClass(zipIn.getInputStream(next), ClassReader.SKIP_FRAMES));
51-
} catch(Throwable t) {
52-
t.printStackTrace();
53-
}
54-
});
67+
try {
68+
inst.classes.add(CustomClassWriter.loadClass(zipIn.getInputStream(next), ClassReader.SKIP_FRAMES));
69+
} catch(Throwable t) {
70+
t.printStackTrace();
71+
}
72+
});
5573
zipIn.close();
5674
inst.loadedAPI.add(new ZIPLibrary(f, classList, isLibrary));
5775
}

com/neonObf/Main.java

+40-61
Original file line numberDiff line numberDiff line change
@@ -29,17 +29,18 @@ public class Main extends Thread {
2929
public static final HashMap<String, Transformer> transformers = new HashMap<>();
3030

3131
public File inF, outF;
32-
public ArrayList<ClassNode> classes = new ArrayList<ClassNode>();
33-
public ArrayList<ClassFile> files = new ArrayList<ClassFile>();
34-
public HashMap<String, ClassNode> nameToNode = new HashMap<String, ClassNode>();
35-
public HashMap<ClassNode, String> nodeToName = new HashMap<ClassNode, String>();
32+
public ArrayList<ClassNode> classes = new ArrayList<>();
33+
public ArrayList<ClassFile> files = new ArrayList<>();
34+
public HashMap<String, ClassNode> nameToNode = new HashMap<>();
35+
public HashMap<ClassNode, String> nodeToName = new HashMap<>();
3636
public String[] libraries;
37-
public ArrayList<Library> loadedAPI = new ArrayList<Library>();
37+
public ArrayList<Library> loadedAPI = new ArrayList<>();
3838
public String[] usedTransformers;
39-
public HashMap<String, Integer> pkgLens = new HashMap<String, Integer>();
39+
public HashMap<String, Integer> pkgLens = new HashMap<>();
4040
public SmartNameGen nameGen;
4141
public String[] args;
4242
public CommandLine cmd;
43+
public final long startTime = System.currentTimeMillis();
4344

4445
public static Main getInstance() {
4546
return instance;
@@ -78,6 +79,11 @@ public void parseArgs() throws Throwable {
7879
dictionaryArg.setArgName("1/2/3");
7980
options.addOption(dictionaryArg);
8081

82+
Option testArg = new Option( null, "test", false, "Means that no output are written to file");
83+
84+
testArg.setRequired(false);
85+
options.addOption(testArg);
86+
8187
CommandLineParser parser = new DefaultParser();
8288
HelpFormatter formatter = new HelpFormatter();
8389

@@ -95,15 +101,17 @@ public void parseArgs() throws Throwable {
95101
if (!(inF = new File(cmd.getOptionValue("input"))).exists())
96102
throw new Throwable("Error: Input file does not exist.");
97103

98-
if ((outF = new File(cmd.getOptionValue("output"))).exists())
104+
if (!cmd.hasOption("test") && (outF = new File(cmd.getOptionValue("output"))).exists())
99105
throw new Throwable("Error: Output file already exists.");
100106

101-
ArrayList<String> librariesList = new ArrayList<>();
102-
if(cmd.hasOption("libraries"))
107+
if(cmd.hasOption("libraries")) {
108+
ArrayList<String> librariesList = new ArrayList<>();
103109
for (String libraryName1 : cmd.getOptionValues("libraries"))
104110
for (String libraryName2 : libraryName1.split(";"))
105111
librariesList.add(libraryName2);
106-
libraries = librariesList.toArray(new String[librariesList.size()]);
112+
113+
libraries = librariesList.toArray(new String[librariesList.size()]);
114+
}
107115

108116
ArrayList<String> usedTransformersList = new ArrayList<>();
109117
for(String transformerName1 : cmd.getOptionValues("transformers"))
@@ -142,10 +150,6 @@ public void parseArgs() throws Throwable {
142150
transformers.put("TryCatch", new TryCatch());
143151
}
144152

145-
public static boolean isEmpty(MethodNode mn) {
146-
return mn.instructions.getFirst() != null;
147-
}
148-
149153
public static void printLogo() {
150154
System.out.println("|---------------------------------------------------------------------------|");
151155
System.out.println("| __ __ ______ ______ __ __ ______ ______ ______ |");
@@ -171,21 +175,23 @@ public void run() {
171175
return;
172176
}
173177

174-
System.out.println("Loading java APIs...");
178+
System.out.println("Loading java APIs... " + getDateTag());
175179
new DirWalker(new File(System.getProperty("java.home") + File.separatorChar + "lib"), true);
176-
System.out.println("Loading user APIs...");
177-
for(String lib : libraries)
178-
new DirWalker(new File(lib), true);
179-
System.out.println("All APIs loaded!");
180+
if(libraries != null) {
181+
System.out.println("Loading user APIs... " + getDateTag());
182+
for (String lib : libraries)
183+
new DirWalker(new File(lib), true);
184+
}
185+
System.out.println("All APIs loaded! " + getDateTag());
180186

181187
System.out.println("--------------------------------------------------");
182188

183-
System.out.println("Loading input file...");
189+
System.out.println("Loading input file... " + getDateTag());
184190
new DirWalker(inF, false);
185191

186192
System.out.println("--------------------------------------------------");
187193

188-
System.out.println("Making class tree...");
194+
System.out.println("Making class tree... " + getDateTag());
189195
CustomClassWriter.loadHierachy();
190196

191197
ArrayList<ClassNode> modClasses = new ArrayList<>(classes);
@@ -195,14 +201,14 @@ public void run() {
195201
System.out.println("--------------------------------------------------");
196202

197203
for(String transformerName : usedTransformers) {
198-
System.out.println("Started transformation with " + transformerName + " transformer");
204+
System.out.println("Started transformation with " + transformerName + " transformer " + getDateTag());
199205

200206
try {
201207
modClasses = transformers.get(transformerName).obfuscate(modClasses);
202208
} catch(NullPointerException npe) {
203209
throw new Throwable("Transformer name \"" + transformerName + "\" aren't defined in Main#transformers.", npe);
204210
}
205-
System.out.println("Transformation completed with " + transformerName + " transformer");
211+
System.out.println("Transformation completed with " + transformerName + " transformer " + getDateTag());
206212
}
207213

208214
System.out.println("--------------------------------------------------");
@@ -212,11 +218,16 @@ public void run() {
212218
dump(cn, true);
213219
System.out.println("--------------------------------------------------");
214220
System.out.println("All classes dumped! " + getDateTag());
215-
System.out.println("Saving all classes...");
216-
saveAll();
217-
System.out.println("All classes saved!");
221+
if(cmd.hasOption("test"))
222+
System.out.println("All transformations and dumps went successfully!");
223+
else {
224+
System.out.println("Saving all classes... " + getDateTag());
225+
saveAll();
226+
System.out.println("All classes saved! " + getDateTag());
227+
}
218228
} catch(Throwable t) {
219229
System.out.println(t.getMessage());
230+
t.printStackTrace();
220231
}
221232
}
222233

@@ -257,10 +268,8 @@ public static String getPackageByClass(String className) {
257268
return className.substring(0, className.lastIndexOf('.'));
258269
}
259270

260-
public static SimpleDateFormat sdf = new SimpleDateFormat("hh:mm:ss");
261-
262-
public static String getDateTag() {
263-
return "[" + sdf.format(new Date()) + "]";
271+
public String getDateTag() {
272+
return "[" + (System.currentTimeMillis() - startTime) + "ms]";
264273
}
265274

266275
public byte[] dump(ClassNode node, boolean autoAdd) {
@@ -299,46 +308,16 @@ public byte[] dump(ClassNode node, boolean autoAdd) {
299308

300309
return classBytes;
301310
} catch(Throwable t) {
302-
System.out.println("Error occurred while writing " + node.name + ". This class will be original. Exception: " + t.getMessage());
311+
System.out.println("Error occurred while writing " + node.name + ". This class will not be written. Exception: " + t.getMessage());
303312
}
304313
return null;
305314
}
306315

307316
public void saveAll() throws Throwable {
308317
outF.createNewFile();
309318
ZipOutputStream out = new ZipOutputStream(new FileOutputStream(outF));
310-
/* Start of combination of jar's */
311-
ZipFile zf = new ZipFile(inF);
312-
Enumeration<? extends ZipEntry> in = zf.entries();
313-
314319
byte[] data;
315320

316-
while (in.hasMoreElements()) {
317-
ZipEntry ze = in.nextElement();
318-
boolean finded = false;
319-
320-
for(ClassFile mc : files)
321-
if (mc != null && ze != null && mc.name != null && ze.getName() != null
322-
&& mc.name.equals(ze.getName())) {
323-
finded = true;
324-
break;
325-
}
326-
327-
if (zf != null && ze != null && !finded) {
328-
DataInputStream dis = new DataInputStream(zf.getInputStream(ze));
329-
data = new byte[(int) ze.getSize()];
330-
dis.readFully(data);
331-
dis.close();
332-
333-
ze = modifyEntry(new ZipEntry(ze.getName()));
334-
335-
out.putNextEntry(ze);
336-
out.write(data, 0, data.length);
337-
out.closeEntry();
338-
}
339-
}
340-
zf.close();
341-
/* End of combination of jar's */
342321
for(ClassFile mc : files)
343322
try {
344323
data = mc.bytecode;

com/neonObf/transformers/AntiMemoryDump.java

+8-9
Original file line numberDiff line numberDiff line change
@@ -59,18 +59,17 @@ public void run() {
5959
@Deprecated
6060
@Override
6161
public ArrayList<ClassNode> obfuscate(ArrayList<ClassNode> classes) throws Throwable {
62-
for(int i = 0; i < classes.size(); i++) {
63-
ClassNode cn = classes.get(i);
64-
62+
classes.parallelStream().forEach((cn) -> {
6563
ExecutorService service = Executors.newCachedThreadPool();
66-
for(MethodNode mn : (List<MethodNode>) cn.methods)
67-
service.execute(new AntiMemoryDump(mn));
64+
((List<MethodNode>) cn.methods).parallelStream().forEach(mn -> service.execute(new AntiMemoryDump(mn)));
6865

6966
service.shutdown();
70-
service.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
71-
72-
classes.set(i, cn);
73-
}
67+
try {
68+
service.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
69+
} catch(Throwable t) {
70+
t.printStackTrace();
71+
}
72+
});
7473

7574
return classes;
7675
}

com/neonObf/transformers/BasicTypesEncryption.java

+2-5
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,6 @@ public static String encrypt(String str, long rnd, String fileName, int line) {
269269
public ArrayList<ClassNode> obfuscate(ArrayList<ClassNode> classes) throws Throwable {
270270
SmartNameGen nameGen = Main.getInstance().nameGen;
271271

272-
273272
classes.parallelStream().forEach((cn) -> {
274273
ExecutorService service = Executors.newCachedThreadPool();
275274

@@ -283,9 +282,7 @@ public ArrayList<ClassNode> obfuscate(ArrayList<ClassNode> classes) throws Throw
283282
cn.name
284283
)
285284
);
286-
((List<MethodNode>)cn.methods).parallelStream().forEach((mn) -> {
287-
service.execute(new BasicTypesEncryption(mn, cn, rand.nextLong()));
288-
});
285+
((List<MethodNode>)cn.methods).parallelStream().forEach(mn -> service.execute(new BasicTypesEncryption(mn, cn, rand.nextLong())));
289286

290287
service.shutdown();
291288
try {
@@ -305,7 +302,7 @@ private static boolean hasInsnsToObf(ClassNode cn) {
305302
AbstractInsnNode next = iterator.next();
306303

307304
if (
308-
(next.getOpcode() >= LDC && next.getOpcode() <= LDC+2) ||
305+
(next.getOpcode() >= LDC && next.getOpcode() <= LDC + 2 /* LDC2_W */) ||
309306
next.getOpcode() == BIPUSH ||
310307
next.getOpcode() == SIPUSH
311308
)

com/neonObf/transformers/CodeHider.java

+2-6
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,8 @@ public void run() {
4646
public ArrayList<ClassNode> obfuscate(ArrayList<ClassNode> classes) throws Throwable {
4747
classes.parallelStream().forEach((cn) -> {
4848
ExecutorService service = Executors.newCachedThreadPool();
49-
((List<MethodNode>) cn.methods).parallelStream().forEach((mn) -> {
50-
service.submit(new CodeHider(mn));
51-
});
52-
((List<FieldNode>) cn.fields).parallelStream().forEach((fn) -> {
53-
service.submit(new CodeHider(fn));
54-
});
49+
((List<MethodNode>) cn.methods).parallelStream().forEach(mn -> service.submit(new CodeHider(mn)));
50+
((List<FieldNode>) cn.fields).parallelStream().forEach(fn -> service.submit(new CodeHider(fn)));
5551

5652
service.shutdown();
5753
try {

0 commit comments

Comments
 (0)