Skip to content

Commit 4c8ee44

Browse files
author
Nikita
authored
Added .class support, fixed checking. (#2)
* Removed class checking as now it also checks names * Checkout commit description Added support for obfuscating .class files, fixed checking.
1 parent 6f6a651 commit 4c8ee44

8 files changed

+178
-114
lines changed

README.md

-1
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,3 @@ ObjectWeb ASM v6.0 (BETA):
2727
- asm-analysis
2828
- asm-commons
2929
- asm-tree
30-
- asm-util

com/neonObf/ClassLibrary.java

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package com.neonObf;
2+
3+
import org.objectweb.asm.ClassReader;
4+
import org.objectweb.asm.tree.ClassNode;
5+
6+
import java.io.File;
7+
import java.io.FileInputStream;
8+
9+
import static com.neonObf.CustomClassWriter.loadClass;
10+
11+
public class ClassLibrary implements Library {
12+
public final File file;
13+
public final ClassNode classNode;
14+
public final boolean isLibrary;
15+
16+
public ClassLibrary(File file, boolean isLibrary) throws Throwable {
17+
this.file = file;
18+
this.isLibrary = isLibrary;
19+
this.classNode = loadClass (
20+
new FileInputStream(file),
21+
isLibrary
22+
? ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES
23+
: ClassReader.SKIP_FRAMES
24+
); // There's no other way to detect class name :(
25+
}
26+
27+
@Override
28+
public boolean isLibrary() {
29+
return isLibrary;
30+
}
31+
32+
@Override
33+
public ClassNode getClassNode(String name) {
34+
if(!classNode.name.equals(name))
35+
return null;
36+
return classNode;
37+
}
38+
}

com/neonObf/CustomClassWriter.java

+53-58
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,15 @@ public static void loadHierachy() {
2525
while (!toLoad.isEmpty()) {
2626
ClassNode poll = toLoad.poll();
2727

28-
for(ClassNode toProcess : loadHierachy(poll)) {
29-
if (processed.add(toProcess.name)) {
28+
for(ClassNode toProcess : loadHierachy(poll))
29+
if (processed.add(toProcess.name))
3030
toLoad.add(toProcess);
31-
}
32-
}
3331
}
3432
}
3533

3634
public static List<ClassNode> loadHierachy(ClassNode specificNode) {
3735
try {
38-
if (specificNode.name.equals("java/lang/Object")) {
36+
if ("java/lang/Object".equals(specificNode.name)) {
3937
return Collections.emptyList();
4038
}
4139
if ((specificNode.access & Opcodes.ACC_INTERFACE) != 0) {
@@ -58,8 +56,7 @@ public static List<ClassNode> loadHierachy(ClassNode specificNode) {
5856
for(String interfaceReference : (List<String>) specificNode.interfaces) {
5957
ClassNode interfaceNode = assureLoaded(interfaceReference);
6058
if (interfaceNode == null) {
61-
throw new IllegalArgumentException("Could not load "
62-
+ interfaceReference);
59+
throw new IllegalArgumentException("Could not load " + interfaceReference);
6360
}
6461
ClassTree interfaceTree = getClassTree(interfaceReference);
6562
interfaceTree.subClasses.add(specificNode.name);
@@ -80,59 +77,19 @@ public CustomClassWriter(int flags) {
8077
public static ClassNode assureLoaded(String ref) {
8178
ClassNode clazz = Main.getInstance().nameToNode.get(ref);
8279
if (clazz == null) {
83-
for(Library lib : Main.getInstance().loadedAPI)
84-
if(lib.classNames.contains(ref)) {
85-
clazz = loadClass(getClass(lib.file, ref), lib.isLibrary ? ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES : ClassReader.SKIP_FRAMES);
86-
if(clazz != null) {
87-
if(!lib.isLibrary)
88-
Main.getInstance().classes.add(clazz);
89-
return clazz;
90-
}
80+
for(Library lib : Main.getInstance().loadedAPI) {
81+
clazz = lib.getClassNode(ref);
82+
if(clazz != null) {
83+
if(!lib.isLibrary())
84+
Main.getInstance().classes.add(clazz);
85+
return clazz;
9186
}
87+
}
9288
throw new NoClassInPathException(ref);
9389
}
9490
return clazz;
9591
}
9692

97-
public static InputStream getClass(File f, String className) {
98-
try {
99-
final ZipFile zipIn = new ZipFile(f);
100-
final Enumeration<? extends ZipEntry> e = zipIn.entries();
101-
ArrayList<String> classList = new ArrayList<>();
102-
while (e.hasMoreElements()) {
103-
final ZipEntry next = e.nextElement();
104-
String nextClassName = next.getName().replaceAll("(.*)\\.class", "$1");
105-
if (nextClassName.equals(className))
106-
return zipIn.getInputStream(next);
107-
}
108-
zipIn.close();
109-
} catch(Throwable t) { }
110-
return null;
111-
}
112-
113-
public static ClassNode loadClass(InputStream is, int mode) {
114-
try {
115-
final ClassReader reader = new ClassReader(is);
116-
final ClassNode node = new ClassNode();
117-
118-
reader.accept(node, mode);
119-
for(int i = 0; i < node.methods.size(); ++i) {
120-
final MethodNode methodNode2 = (MethodNode) node.methods.get(i);
121-
final JSRInlinerAdapter adapter = new JSRInlinerAdapter(methodNode2, methodNode2.access, methodNode2.name, methodNode2.desc, methodNode2.signature, (String[]) methodNode2.exceptions.toArray(new String[0]));
122-
methodNode2.accept(adapter);
123-
node.methods.set(i, adapter);
124-
}
125-
126-
Main.getInstance().nameToNode.put(node.name, node);
127-
Main.getInstance().nodeToName.put(node, node.name);
128-
129-
return node;
130-
} catch(Throwable t) {
131-
t.printStackTrace();
132-
return null;
133-
}
134-
}
135-
13693
@Override
13794
protected String getCommonSuperClass(String type1, String type2) {
13895
String a = getCommonSuperClass1(type1, type2);
@@ -161,21 +118,21 @@ private String getCommonSuperClass0(String type1, String type2) {
161118
}
162119

163120
private String getCommonSuperClass1(String type1, String type2) {
164-
if (type1.equals("java/lang/Object") || type2.equals("java/lang/Object"))
121+
if ("java/lang/Object".equals(type1) || "java/lang/Object".equals(type2))
165122
return "java/lang/Object";
166123
String a = getCommonSuperClass0(type1, type2);
167124
String b = getCommonSuperClass0(type2, type1);
168-
if (!a.equals("java/lang/Object"))
125+
if (!"java/lang/Object".equals(a))
169126
return a;
170-
if (!b.equals("java/lang/Object"))
127+
if (!"java/lang/Object".equals(b))
171128
return b;
172129
ClassNode first = assureLoaded(type1);
173130
ClassNode second = assureLoaded(type2);
174131
return getCommonSuperClass(first.superName, second.superName);
175132
}
176133

177134
private boolean isAssignableFrom(String type1, String type2) {
178-
if (type1.equals("java/lang/Object"))
135+
if ("java/lang/Object".equals(type1))
179136
return true;
180137
if (type1.equals(type2))
181138
return true;
@@ -207,4 +164,42 @@ public static ClassTree getClassTree(String classNode) {
207164
}
208165
return tree;
209166
}
167+
168+
public static ClassNode loadClass(InputStream is, int mode) {
169+
try {
170+
final ClassReader reader = new ClassReader(is);
171+
final ClassNode node = new ClassNode();
172+
173+
reader.accept(node, mode);
174+
for(int i = 0; i < node.methods.size(); ++i) {
175+
final MethodNode methodNode2 = (MethodNode) node.methods.get(i);
176+
final JSRInlinerAdapter adapter = new JSRInlinerAdapter(methodNode2, methodNode2.access, methodNode2.name, methodNode2.desc, methodNode2.signature, (String[]) methodNode2.exceptions.toArray(new String[0]));
177+
methodNode2.accept(adapter);
178+
node.methods.set(i, adapter);
179+
}
180+
181+
Main.getInstance().nameToNode.put(node.name, node);
182+
Main.getInstance().nodeToName.put(node, node.name);
183+
184+
return node;
185+
} catch(Throwable t) {
186+
t.printStackTrace();
187+
return null;
188+
}
189+
}
190+
191+
public static InputStream getClass(File f, String className) {
192+
try {
193+
final ZipFile zipIn = new ZipFile(f);
194+
final Enumeration<? extends ZipEntry> e = zipIn.entries();
195+
className += ".class";
196+
while (e.hasMoreElements()) {
197+
final ZipEntry next = e.nextElement();
198+
if (next.getName().equals(className))
199+
return zipIn.getInputStream(next);
200+
}
201+
zipIn.close();
202+
} catch(Throwable t) { }
203+
return null;
204+
}
210205
}

com/neonObf/DirWalker.java

+34-28
Original file line numberDiff line numberDiff line change
@@ -3,53 +3,59 @@
33

44
import java.io.File;
55
import java.io.FileInputStream;
6-
import java.io.InputStream;
76
import java.util.ArrayList;
87
import java.util.Enumeration;
98
import java.util.zip.ZipEntry;
109
import java.util.zip.ZipFile;
1110

1211
import org.objectweb.asm.ClassReader;
13-
import org.objectweb.asm.commons.JSRInlinerAdapter;
14-
import org.objectweb.asm.tree.ClassNode;
15-
import org.objectweb.asm.tree.MethodNode;
1612

1713
public class DirWalker {
18-
public DirWalker(File file, int mode, boolean isLibrary) throws Throwable {
14+
public DirWalker(File file, boolean isLibrary) throws Throwable {
15+
Main inst = Main.getInstance();
1916
String name = file.getName();
2017
String path = file.getAbsolutePath();
2118
if (file.isDirectory()) {
2219
if (file.listFiles() != null && !path.endsWith(".donot"))
2320
for(File f : file.listFiles())
2421
if (!(f.getName().charAt(0) == '.' || f.getName().charAt(0) == '$'))
25-
new DirWalker(f, mode, isLibrary);
22+
new DirWalker(f, isLibrary);
2623
} else
27-
if (file.isFile() && name.lastIndexOf('.') > -1
28-
&& (name.endsWith("jar") || name.endsWith("class"))) {
24+
if (file.isFile() && name.lastIndexOf('.') > -1) {
2925
if (name.endsWith("jar"))
30-
loadFile(new File(path), mode, isLibrary);
26+
loadZIP(new File(path), isLibrary);
27+
if (name.endsWith("class"))
28+
loadClass(new File(path), isLibrary);
3129
}
3230
}
3331

34-
public void loadFile(File f, int mode, boolean isLibrary) throws Throwable {
35-
try {
36-
final ZipFile zipIn = new ZipFile(f);
37-
final Enumeration<? extends ZipEntry> e = zipIn.entries();
38-
ArrayList<String> classList = new ArrayList<>();
39-
while (e.hasMoreElements()) {
40-
final ZipEntry next = e.nextElement();
41-
if (next.getName().endsWith(".class")) {
42-
if(isLibrary)
43-
classList.add(next.getName().replaceAll("(.*)\\.class", "$1"));
44-
else
45-
Main.getInstance().classes.add(CustomClassWriter.loadClass(zipIn.getInputStream(next), ClassReader.SKIP_FRAMES));
46-
} else
47-
if (next.isDirectory())
48-
continue;
49-
}
50-
zipIn.close();
51-
Main.getInstance().loadedAPI.add(new Library(f, classList, isLibrary));
52-
} catch(Throwable t) {
32+
public void loadClass(File f, boolean isLibrary) throws Throwable {
33+
Main inst = Main.getInstance();
34+
ClassLibrary lib = new ClassLibrary(f, isLibrary);
35+
if(isLibrary)
36+
; // classList.add(next.getName().replaceAll("(.*)\\.class", "$1")); # Now we can't use .class as library ._.
37+
else
38+
inst.classes.add(lib.classNode);
39+
inst.loadedAPI.add(lib);
40+
}
41+
42+
public void loadZIP(File f, boolean isLibrary) throws Throwable {
43+
Main inst = Main.getInstance();
44+
final ZipFile zipIn = new ZipFile(f);
45+
final Enumeration<? extends ZipEntry> e = zipIn.entries();
46+
ArrayList<String> classList = new ArrayList<>();
47+
while (e.hasMoreElements()) {
48+
final ZipEntry next = e.nextElement();
49+
if (next.getName().endsWith(".class")) {
50+
if(isLibrary)
51+
classList.add(next.getName().replaceAll("(.*)\\.class", "$1"));
52+
else
53+
inst.classes.add(CustomClassWriter.loadClass(zipIn.getInputStream(next), ClassReader.SKIP_FRAMES));
54+
} else
55+
if (next.isDirectory())
56+
continue;
5357
}
58+
zipIn.close();
59+
inst.loadedAPI.add(new ZIPLibrary(f, classList, isLibrary));
5460
}
5561
}

com/neonObf/Library.java

+4-11
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,9 @@
11
package com.neonObf;
22

3-
import java.io.File;
4-
import java.util.ArrayList;
3+
import org.objectweb.asm.tree.ClassNode;
54

6-
public class Library {
7-
public File file;
8-
public ArrayList<String> classNames;
9-
public boolean isLibrary;
5+
public interface Library {
6+
ClassNode getClassNode(String name);
107

11-
public Library(File file, ArrayList<String> classNames, boolean isLibrary) {
12-
this.file = file;
13-
this.classNames = classNames;
14-
this.isLibrary = isLibrary;
15-
}
8+
boolean isLibrary();
169
}

com/neonObf/Main.java

+11-15
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,20 @@
66
import java.io.FileOutputStream;
77
import java.nio.file.attribute.FileTime;
88
import java.text.SimpleDateFormat;
9-
import java.util.*;
9+
import java.util.ArrayList;
10+
import java.util.Date;
11+
import java.util.Enumeration;
12+
import java.util.HashMap;
13+
import java.util.List;
14+
import java.util.Random;
1015
import java.util.zip.ZipEntry;
1116
import java.util.zip.ZipFile;
1217
import java.util.zip.ZipOutputStream;
1318

14-
import org.objectweb.asm.ClassReader;
1519
import org.objectweb.asm.ClassWriter;
1620
import org.objectweb.asm.tree.ClassNode;
1721
import org.objectweb.asm.tree.InnerClassNode;
1822
import org.objectweb.asm.tree.MethodNode;
19-
import org.objectweb.asm.util.CheckClassAdapter;
2023

2124
import com.neonObf.transformers.*;
2225

@@ -157,24 +160,24 @@ public void run() {
157160
}
158161

159162
System.out.println("Loading java APIs...");
160-
new DirWalker(new File(System.getProperty("java.home") + File.separatorChar + "lib"), ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES, true);
163+
new DirWalker(new File(System.getProperty("java.home") + File.separatorChar + "lib"), true);
161164
if (!args[2].equalsIgnoreCase("null")) {
162165
System.out.println("Loading user APIs...");
163-
new DirWalker(new File(args[2]), ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES, true);
166+
new DirWalker(new File(args[2]), true);
164167
}
165168
System.out.println("All APIs loaded!");
166169

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

169172
System.out.println("Loading input file...");
170-
new DirWalker(inF, ClassReader.SKIP_FRAMES, false);
173+
new DirWalker(inF, false);
171174

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

174177
System.out.println("Making class tree...");
175178
CustomClassWriter.loadHierachy();
176179

177-
ArrayList<ClassNode> modClasses = classes;
180+
ArrayList<ClassNode> modClasses = new ArrayList<>(classes);
178181

179182
System.out.println("Starting transforming.... " + getDateTag());
180183

@@ -277,19 +280,12 @@ public byte[] dump(ClassNode node, boolean autoAdd) {
277280
}
278281
byte[] classBytes = writer.toByteArray();
279282

280-
ClassReader cr = new ClassReader(classBytes);
281-
try {
282-
cr.accept(new CheckClassAdapter(new ClassWriter(0)), 0);
283-
} catch(Throwable t) {
284-
System.out.println("Error: " + node.name + " failed verification. Exception: " + t.getMessage());
285-
}
286-
287283
if (autoAdd)
288284
files.add(new ClassFile(node.name.replaceAll("\\.", "/") + ".class", classBytes));
289285

290286
return classBytes;
291287
} catch(Throwable t) {
292-
System.out.println("Error while writing " + node.name + ". This class will be original. Exception: " + t.getMessage());
288+
System.out.println("Error occurred while writing " + node.name + ". This class will be original. Exception: " + t.getMessage());
293289
}
294290
return null;
295291
}

0 commit comments

Comments
 (0)