Skip to content

Commit ebdcb2e

Browse files
committed
Added flow control for variables & improved flow control within methods
1 parent 5acfda6 commit ebdcb2e

File tree

12 files changed

+457
-11
lines changed

12 files changed

+457
-11
lines changed

src/main/java/io/github/splotycode/deobfuscator/JavaDeobfuscator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public static void main(String[] args) {
4141
private byte[] buffer = new byte[1024 * 4];
4242

4343
{
44-
modules.add(new PrettyPrintModule());
44+
//modules.add(new PrettyPrintModule());
4545
modules.add(new StaticStringLength());
4646
modules.add(new RemoveUnusedMethods());
4747
modules.add(new RenameModule());

src/main/java/io/github/splotycode/deobfuscator/flow/FlowClass.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package io.github.splotycode.deobfuscator.flow;
22

3-
import jdk.internal.org.objectweb.asm.Opcodes;
43
import jdk.internal.org.objectweb.asm.tree.ClassNode;
54
import lombok.Getter;
65

@@ -10,14 +9,23 @@
109
@Getter
1110
public class FlowClass {
1211

12+
private boolean userCode;
13+
1314
private ClassNode classNode;
1415
private FlowClass superClass;
1516

1617
private HashMap<String, FlowMethod> methods = new HashMap<>();
18+
private HashMap<String, FlowField> fields = new HashMap<>();
19+
1720
private ArrayList<FlowClass> extenders = new ArrayList<>();
1821

19-
public FlowClass(ClassNode classNode) {
22+
public FlowClass(ClassNode classNode, boolean userCode) {
2023
this.classNode = classNode;
24+
this.userCode = userCode;
25+
}
26+
27+
public String getName() {
28+
return classNode.name;
2129
}
2230

2331
public FlowMethod getMethod(String name) {
@@ -41,5 +49,8 @@ public void update(FlowControl flowControl) {
4149
for (FlowMethod method : methods.values()) {
4250
method.update(flowControl);
4351
}
52+
for (FlowField field : fields.values()) {
53+
field.update(flowControl);
54+
}
4455
}
4556
}

src/main/java/io/github/splotycode/deobfuscator/flow/FlowControl.java

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,16 @@
44
import io.github.splotycode.deobfuscator.JavaDeobfuscator;
55
import io.github.splotycode.deobfuscator.search.MethodPattern;
66
import jdk.internal.org.objectweb.asm.tree.ClassNode;
7+
import jdk.internal.org.objectweb.asm.tree.FieldNode;
78
import jdk.internal.org.objectweb.asm.tree.MethodNode;
9+
import lombok.Getter;
810

911
import java.util.ArrayList;
12+
import java.util.Collection;
1013
import java.util.HashMap;
1114
import java.util.HashSet;
12-
import java.util.Set;
13-
1415

16+
@Getter
1517
public class FlowControl {
1618

1719
private HashMap<String, FlowClass> classes = new HashMap<>();
@@ -25,19 +27,28 @@ public void update() {
2527
methodsSignature.clear();
2628
for (ClassNode classNode : JavaDeobfuscator.getInstance().getClasses().values()) {
2729
String name = classNode.name;
28-
FlowClass clazz = new FlowClass(classNode);
30+
FlowClass clazz = new FlowClass(classNode, true);
2931
classes.put(name, clazz);
3032
for (MethodNode methodNode : classNode.methods) {
31-
FlowMethod method = new FlowMethod(methodNode, clazz, true);
33+
FlowMethod method = new FlowMethod(methodNode, clazz);
3234
methods.put(name, method);
35+
clazz.getMethods().put(method.getName(), method);
3336
methodsSignature.put(MethodPattern.generatePattern(classNode, methodNode), method);
3437
}
38+
for (FieldNode fieldNode : classNode.fields) {
39+
FlowField field = new FlowField(fieldNode, clazz);
40+
clazz.getFields().put(field.getName(), field);
41+
}
3542
}
3643
for (FlowClass clazz : classes.values()) {
3744
clazz.update(this);
3845
}
3946
}
4047

48+
public Collection<FlowClass> getAllClasses() {
49+
return classes.values();
50+
}
51+
4152
public FlowClass getClass(String name) {
4253
return classes.get(name);
4354
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
package io.github.splotycode.deobfuscator.flow;
2+
3+
import io.github.splotycode.deobfuscator.flow.stack.StackInstruction;
4+
import io.github.splotycode.deobfuscator.flow.stack.StackValue;
5+
import io.github.splotycode.deobfuscator.flow.stack.ValueStackType;
6+
import io.github.splotycode.deobfuscator.search.InstructionSearch;
7+
import jdk.internal.org.objectweb.asm.Opcodes;
8+
import jdk.internal.org.objectweb.asm.Type;
9+
import jdk.internal.org.objectweb.asm.tree.AbstractInsnNode;
10+
import jdk.internal.org.objectweb.asm.tree.FieldInsnNode;
11+
import jdk.internal.org.objectweb.asm.tree.FieldNode;
12+
import jdk.internal.org.objectweb.asm.tree.MethodNode;
13+
import lombok.Getter;
14+
15+
import java.lang.reflect.Modifier;
16+
import java.util.HashSet;
17+
import java.util.Set;
18+
19+
@Getter
20+
public class FlowField implements FlowVariable, InstructionSearch {
21+
22+
private FieldNode fieldNode;
23+
private FlowClass flowClass;
24+
private HashSet<Type> usedTypes = new HashSet<>();
25+
private HashSet<Object> staticValues = new HashSet<>();
26+
private Type baseType;
27+
28+
public FlowField(FieldNode fieldNode, FlowClass flowClass) {
29+
this.fieldNode = fieldNode;
30+
this.flowClass = flowClass;
31+
}
32+
33+
@Override
34+
public String getName() {
35+
return fieldNode.name;
36+
}
37+
38+
@Override
39+
public Type baseType() {
40+
return baseType;
41+
}
42+
43+
@Override
44+
public Set<Type> usedTypes() {
45+
return usedTypes;
46+
}
47+
48+
@Override
49+
public Set<Object> staticValues() {
50+
return staticValues;
51+
}
52+
53+
@Override
54+
public void update(FlowControl flowControl) {
55+
usedTypes.clear();
56+
staticValues.clear();
57+
58+
baseType = Type.getType(fieldNode.desc);
59+
if (Modifier.isPrivate(fieldNode.access)) {
60+
search(flowClass.getClassNode());
61+
} else {
62+
for (FlowClass clazz : flowControl.getAllClasses()) {
63+
search(clazz.getClassNode());
64+
}
65+
}
66+
}
67+
68+
@Override
69+
public boolean onInstruction(MethodNode caller, AbstractInsnNode instruction) {
70+
if (instruction.getOpcode() == Opcodes.PUTSTATIC) {
71+
FieldInsnNode field = (FieldInsnNode) instruction;
72+
if (field.owner.equals(flowClass.getName()) && field.name.equals(getName()) && field.desc.equals(baseType().getDescriptor())) {
73+
StackValue value = StackInstruction.guesStackValue(field, 1);
74+
System.out.println(getName() + " " + value);
75+
if (value != null && value.getType().hasDeclarationType()) {
76+
if (value.getStaticValue() != null) {
77+
staticValues.add(value.getStaticValue());
78+
}
79+
usedTypes.add(((ValueStackType) value.getType()).getType());
80+
}
81+
}
82+
}
83+
return false;
84+
}
85+
}

src/main/java/io/github/splotycode/deobfuscator/flow/FlowMethod.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,9 @@ public class FlowMethod {
1515
private FlowMethod overrides;
1616
private ArrayList<FlowMethod> overriders = new ArrayList<>();
1717

18-
private boolean userCode;
19-
20-
public FlowMethod(MethodNode method, FlowClass clazz, boolean userCode) {
18+
public FlowMethod(MethodNode method, FlowClass clazz) {
2119
this.method = method;
2220
this.clazz = clazz;
23-
this.userCode = userCode;
2421
}
2522

2623
public void update(FlowControl flowControl) {
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package io.github.splotycode.deobfuscator.flow;
2+
3+
import jdk.internal.org.objectweb.asm.Type;
4+
5+
import java.util.Set;
6+
7+
public interface FlowVariable {
8+
9+
String getName();
10+
11+
Type baseType();
12+
13+
Set<Type> usedTypes();
14+
Set<Object> staticValues();
15+
16+
default boolean hasOnlyType(Type type) {
17+
Set<Type> types = usedTypes();
18+
return types != null && types.size() == 1 && types.contains(type);
19+
}
20+
21+
void update(FlowControl flowControl);
22+
23+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package io.github.splotycode.deobfuscator.flow.stack;
2+
3+
import jdk.internal.org.objectweb.asm.Opcodes;
4+
import jdk.internal.org.objectweb.asm.Type;
5+
import jdk.internal.org.objectweb.asm.tree.AbstractInsnNode;
6+
import jdk.internal.org.objectweb.asm.tree.IntInsnNode;
7+
import jdk.internal.org.objectweb.asm.tree.TypeInsnNode;
8+
import lombok.AllArgsConstructor;
9+
import lombok.ToString;
10+
11+
@ToString
12+
@AllArgsConstructor
13+
public class ArrayReferenceStackType implements StackType {
14+
15+
public static ArrayReferenceStackType INT_ARRAY = new ArrayReferenceStackType(Type.getType("[I"));
16+
public static ArrayReferenceStackType BOOLEAN_ARRAY = new ArrayReferenceStackType(Type.getType("[Z"));
17+
public static ArrayReferenceStackType CHAR_ARRAY = new ArrayReferenceStackType(Type.getType("[C"));
18+
public static ArrayReferenceStackType FLOAT_ARRAY = new ArrayReferenceStackType(Type.getType("[F"));
19+
public static ArrayReferenceStackType DOUBLE_ARRAY = new ArrayReferenceStackType(Type.getType("[D"));
20+
public static ArrayReferenceStackType BYTE_ARRAY = new ArrayReferenceStackType(Type.getType("[B"));
21+
public static ArrayReferenceStackType SHORT_ARRAY = new ArrayReferenceStackType(Type.getType("[S"));
22+
public static ArrayReferenceStackType LONG_ARRAY = new ArrayReferenceStackType(Type.getType("[L"));
23+
24+
public static ArrayReferenceStackType byInstruction(AbstractInsnNode instruction) {
25+
if (instruction instanceof IntInsnNode) {
26+
switch (((IntInsnNode) instruction).operand) {
27+
case Opcodes.T_INT:
28+
return INT_ARRAY;
29+
case Opcodes.T_BOOLEAN:
30+
return BOOLEAN_ARRAY;
31+
case Opcodes.T_CHAR:
32+
return CHAR_ARRAY;
33+
case Opcodes.T_FLOAT:
34+
return FLOAT_ARRAY;
35+
case Opcodes.T_DOUBLE:
36+
return DOUBLE_ARRAY;
37+
case Opcodes.T_BYTE:
38+
return BYTE_ARRAY;
39+
case Opcodes.T_SHORT:
40+
return SHORT_ARRAY;
41+
case Opcodes.T_LONG:
42+
return LONG_ARRAY;
43+
default:
44+
throw new IllegalStateException("Invalid array type on operand stack");
45+
}
46+
}
47+
return new ArrayReferenceStackType(Type.getType(((TypeInsnNode) instruction).desc));
48+
}
49+
50+
private Type type;
51+
52+
public Type arrayType() {
53+
return type;
54+
}
55+
56+
public Type typeInArray() {
57+
return type.getElementType();
58+
}
59+
60+
@Override
61+
public boolean isReference() {
62+
return true;
63+
}
64+
}

0 commit comments

Comments
 (0)