Skip to content

Commit

Permalink
Added Stream API for loading, now all timings are in milliseconds (#4)
Browse files Browse the repository at this point in the history
 - Added Stream API for loading
 - Now all timings are in milliseconds
  • Loading branch information
Nikita authored Sep 10, 2017
1 parent 929031c commit 7518e7c
Show file tree
Hide file tree
Showing 12 changed files with 112 additions and 135 deletions.
28 changes: 14 additions & 14 deletions com/neonObf/CustomClassWriter.java
Original file line number Diff line number Diff line change
Expand Up @@ -100,19 +100,19 @@ private String getCommonSuperClass0(String type1, String type2) {
if (isAssignableFrom(type1, type2))
return type1;
else
if (isAssignableFrom(type2, type1))
return type2;
else
if (Modifier.isInterface(first.access)
|| Modifier.isInterface(second.access))
return "java/lang/Object";
else {
do {
type1 = first.superName;
first = assureLoaded(type1);
} while (!isAssignableFrom(type1, type2));
return type1;
}
if (isAssignableFrom(type2, type1))
return type2;
else
if (Modifier.isInterface(first.access)
|| Modifier.isInterface(second.access))
return "java/lang/Object";
else {
do {
type1 = first.superName;
first = assureLoaded(type1);
} while (!isAssignableFrom(type1, type2));
return type1;
}
}

private String getCommonSuperClass1(String type1, String type2) {
Expand Down Expand Up @@ -200,4 +200,4 @@ public static InputStream getClass(File f, String className) {
} catch(Throwable t) { }
return null;
}
}
}
54 changes: 36 additions & 18 deletions com/neonObf/DirWalker.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,44 @@

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.zip.ZipFile;

import org.objectweb.asm.ClassReader;

public class DirWalker {
public DirWalker(File file, boolean isLibrary) throws Throwable {
public DirWalker(File file, boolean isLibrary) {
String name = file.getName();
String path = file.getAbsolutePath();
if (file.isDirectory()) {
if (file.listFiles() != null && !path.endsWith(".donot"))
for(File f : file.listFiles())
if (!(f.getName().charAt(0) == '.' || f.getName().charAt(0) == '$'))
new DirWalker(f, isLibrary);
} else
Arrays.stream(file.listFiles())
.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")))
.forEach(f -> {
try {
new DirWalker(f, isLibrary);
} catch (Throwable t) {
t.printStackTrace();
}
});
} else {
if (file.isFile() && name.lastIndexOf('.') > -1) {
if (name.endsWith("jar"))
loadZIP(new File(path), isLibrary);
if (name.endsWith("class"))
if(!name.equals("module-info.class"))
loadClass(new File(path), isLibrary);
name = name.toLowerCase();
if(name.endsWith(".jar") || name.endsWith(".zip"))
try {
loadZIP(file, isLibrary);
} catch(Throwable t) {
new Throwable("Failed to load JAR @ " + path, t).printStackTrace();
}
if(name.endsWith(".class"))
try {
loadClass(file, isLibrary);
} catch(Throwable t) {
new Throwable("Failed to load class @ " + path, t).printStackTrace();
}
}
}
}

public void loadClass(File f, boolean isLibrary) throws Throwable {
Expand All @@ -41,17 +57,19 @@ public void loadZIP(File f, boolean isLibrary) throws Throwable {
Main inst = Main.getInstance();
final ZipFile zipIn = new ZipFile(f);
ArrayList<String> classList = new ArrayList<>();
Collections.list(zipIn.entries()).forEach((next) -> {
try {
if (next.getName().endsWith(".class") && !next.getName().equals("module-info.class"))
Collections.list(zipIn.entries())
.stream()
.filter(next -> (next.getName().endsWith(".class") && !next.getName().equals("module-info.class")))
.forEach(next -> {
if (isLibrary)
classList.add(next.getName().replaceAll("(.*)\\.class", "$1"));
else
inst.classes.add(CustomClassWriter.loadClass(zipIn.getInputStream(next), ClassReader.SKIP_FRAMES));
} catch(Throwable t) {
t.printStackTrace();
}
});
try {
inst.classes.add(CustomClassWriter.loadClass(zipIn.getInputStream(next), ClassReader.SKIP_FRAMES));
} catch(Throwable t) {
t.printStackTrace();
}
});
zipIn.close();
inst.loadedAPI.add(new ZIPLibrary(f, classList, isLibrary));
}
Expand Down
101 changes: 40 additions & 61 deletions com/neonObf/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,18 @@ public class Main extends Thread {
public static final HashMap<String, Transformer> transformers = new HashMap<>();

public File inF, outF;
public ArrayList<ClassNode> classes = new ArrayList<ClassNode>();
public ArrayList<ClassFile> files = new ArrayList<ClassFile>();
public HashMap<String, ClassNode> nameToNode = new HashMap<String, ClassNode>();
public HashMap<ClassNode, String> nodeToName = new HashMap<ClassNode, String>();
public ArrayList<ClassNode> classes = new ArrayList<>();
public ArrayList<ClassFile> files = new ArrayList<>();
public HashMap<String, ClassNode> nameToNode = new HashMap<>();
public HashMap<ClassNode, String> nodeToName = new HashMap<>();
public String[] libraries;
public ArrayList<Library> loadedAPI = new ArrayList<Library>();
public ArrayList<Library> loadedAPI = new ArrayList<>();
public String[] usedTransformers;
public HashMap<String, Integer> pkgLens = new HashMap<String, Integer>();
public HashMap<String, Integer> pkgLens = new HashMap<>();
public SmartNameGen nameGen;
public String[] args;
public CommandLine cmd;
public final long startTime = System.currentTimeMillis();

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

Option testArg = new Option( null, "test", false, "Means that no output are written to file");

testArg.setRequired(false);
options.addOption(testArg);

CommandLineParser parser = new DefaultParser();
HelpFormatter formatter = new HelpFormatter();

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

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

ArrayList<String> librariesList = new ArrayList<>();
if(cmd.hasOption("libraries"))
if(cmd.hasOption("libraries")) {
ArrayList<String> librariesList = new ArrayList<>();
for (String libraryName1 : cmd.getOptionValues("libraries"))
for (String libraryName2 : libraryName1.split(";"))
librariesList.add(libraryName2);
libraries = librariesList.toArray(new String[librariesList.size()]);

libraries = librariesList.toArray(new String[librariesList.size()]);
}

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

public static boolean isEmpty(MethodNode mn) {
return mn.instructions.getFirst() != null;
}

public static void printLogo() {
System.out.println("|---------------------------------------------------------------------------|");
System.out.println("| __ __ ______ ______ __ __ ______ ______ ______ |");
Expand All @@ -171,21 +175,23 @@ public void run() {
return;
}

System.out.println("Loading java APIs...");
System.out.println("Loading java APIs... " + getDateTag());
new DirWalker(new File(System.getProperty("java.home") + File.separatorChar + "lib"), true);
System.out.println("Loading user APIs...");
for(String lib : libraries)
new DirWalker(new File(lib), true);
System.out.println("All APIs loaded!");
if(libraries != null) {
System.out.println("Loading user APIs... " + getDateTag());
for (String lib : libraries)
new DirWalker(new File(lib), true);
}
System.out.println("All APIs loaded! " + getDateTag());

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

System.out.println("Loading input file...");
System.out.println("Loading input file... " + getDateTag());
new DirWalker(inF, false);

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

System.out.println("Making class tree...");
System.out.println("Making class tree... " + getDateTag());
CustomClassWriter.loadHierachy();

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

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

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

System.out.println("--------------------------------------------------");
Expand All @@ -212,11 +218,16 @@ public void run() {
dump(cn, true);
System.out.println("--------------------------------------------------");
System.out.println("All classes dumped! " + getDateTag());
System.out.println("Saving all classes...");
saveAll();
System.out.println("All classes saved!");
if(cmd.hasOption("test"))
System.out.println("All transformations and dumps went successfully!");
else {
System.out.println("Saving all classes... " + getDateTag());
saveAll();
System.out.println("All classes saved! " + getDateTag());
}
} catch(Throwable t) {
System.out.println(t.getMessage());
t.printStackTrace();
}
}

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

public static SimpleDateFormat sdf = new SimpleDateFormat("hh:mm:ss");

public static String getDateTag() {
return "[" + sdf.format(new Date()) + "]";
public String getDateTag() {
return "[" + (System.currentTimeMillis() - startTime) + "ms]";
}

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

return classBytes;
} catch(Throwable t) {
System.out.println("Error occurred while writing " + node.name + ". This class will be original. Exception: " + t.getMessage());
System.out.println("Error occurred while writing " + node.name + ". This class will not be written. Exception: " + t.getMessage());
}
return null;
}

public void saveAll() throws Throwable {
outF.createNewFile();
ZipOutputStream out = new ZipOutputStream(new FileOutputStream(outF));
/* Start of combination of jar's */
ZipFile zf = new ZipFile(inF);
Enumeration<? extends ZipEntry> in = zf.entries();

byte[] data;

while (in.hasMoreElements()) {
ZipEntry ze = in.nextElement();
boolean finded = false;

for(ClassFile mc : files)
if (mc != null && ze != null && mc.name != null && ze.getName() != null
&& mc.name.equals(ze.getName())) {
finded = true;
break;
}

if (zf != null && ze != null && !finded) {
DataInputStream dis = new DataInputStream(zf.getInputStream(ze));
data = new byte[(int) ze.getSize()];
dis.readFully(data);
dis.close();

ze = modifyEntry(new ZipEntry(ze.getName()));

out.putNextEntry(ze);
out.write(data, 0, data.length);
out.closeEntry();
}
}
zf.close();
/* End of combination of jar's */
for(ClassFile mc : files)
try {
data = mc.bytecode;
Expand Down
17 changes: 8 additions & 9 deletions com/neonObf/transformers/AntiMemoryDump.java
Original file line number Diff line number Diff line change
Expand Up @@ -59,18 +59,17 @@ public void run() {
@Deprecated
@Override
public ArrayList<ClassNode> obfuscate(ArrayList<ClassNode> classes) throws Throwable {
for(int i = 0; i < classes.size(); i++) {
ClassNode cn = classes.get(i);

classes.parallelStream().forEach((cn) -> {
ExecutorService service = Executors.newCachedThreadPool();
for(MethodNode mn : (List<MethodNode>) cn.methods)
service.execute(new AntiMemoryDump(mn));
((List<MethodNode>) cn.methods).parallelStream().forEach(mn -> service.execute(new AntiMemoryDump(mn)));

service.shutdown();
service.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);

classes.set(i, cn);
}
try {
service.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch(Throwable t) {
t.printStackTrace();
}
});

return classes;
}
Expand Down
7 changes: 2 additions & 5 deletions com/neonObf/transformers/BasicTypesEncryption.java
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,6 @@ public static String encrypt(String str, long rnd, String fileName, int line) {
public ArrayList<ClassNode> obfuscate(ArrayList<ClassNode> classes) throws Throwable {
SmartNameGen nameGen = Main.getInstance().nameGen;


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

Expand All @@ -283,9 +282,7 @@ public ArrayList<ClassNode> obfuscate(ArrayList<ClassNode> classes) throws Throw
cn.name
)
);
((List<MethodNode>)cn.methods).parallelStream().forEach((mn) -> {
service.execute(new BasicTypesEncryption(mn, cn, rand.nextLong()));
});
((List<MethodNode>)cn.methods).parallelStream().forEach(mn -> service.execute(new BasicTypesEncryption(mn, cn, rand.nextLong())));

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

if (
(next.getOpcode() >= LDC && next.getOpcode() <= LDC+2) ||
(next.getOpcode() >= LDC && next.getOpcode() <= LDC + 2 /* LDC2_W */) ||
next.getOpcode() == BIPUSH ||
next.getOpcode() == SIPUSH
)
Expand Down
8 changes: 2 additions & 6 deletions com/neonObf/transformers/CodeHider.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,8 @@ public void run() {
public ArrayList<ClassNode> obfuscate(ArrayList<ClassNode> classes) throws Throwable {
classes.parallelStream().forEach((cn) -> {
ExecutorService service = Executors.newCachedThreadPool();
((List<MethodNode>) cn.methods).parallelStream().forEach((mn) -> {
service.submit(new CodeHider(mn));
});
((List<FieldNode>) cn.fields).parallelStream().forEach((fn) -> {
service.submit(new CodeHider(fn));
});
((List<MethodNode>) cn.methods).parallelStream().forEach(mn -> service.submit(new CodeHider(mn)));
((List<FieldNode>) cn.fields).parallelStream().forEach(fn -> service.submit(new CodeHider(fn)));

service.shutdown();
try {
Expand Down
Loading

0 comments on commit 7518e7c

Please sign in to comment.