Skip to content

Commit 39a1227

Browse files
committed
chore(all): more improvements
1 parent a1f3420 commit 39a1227

13 files changed

Lines changed: 360 additions & 39 deletions

File tree

dev.skidfuscator.obfuscator/src/main/java/dev/skidfuscator/obfuscator/exempt/SimpleExemptAnalysis.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ public boolean isExempt(MethodNode methodNode) {
5151
}
5252
} catch (AssertionError e) {
5353
// Do nothing
54+
e.printStackTrace();
5455
}
5556
}
5657

dev.skidfuscator.obfuscator/src/main/java/dev/skidfuscator/obfuscator/transform/impl/number/NumberTransformer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ void handle(final RunMethodTransformEvent event) {
7070

7171
for (Stmt stmt : new HashSet<>(vertex)) {
7272
for (Expr expr : stmt.enumerateOnlyChildren()) {
73-
if (!(expr instanceof ConstantExpr))
73+
if (!(expr instanceof ConstantExpr) || expr instanceof SkidConstantExpr)
7474
continue;
7575

7676
final ConstantExpr constantExpr = (ConstantExpr) expr;

dev.skidfuscator.obfuscator/src/main/java/dev/skidfuscator/obfuscator/transform/impl/string/StringTransformer.java

Lines changed: 50 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,40 @@
11
package dev.skidfuscator.obfuscator.transform.impl.string;
22

3+
import dev.skidfuscator.builder.FieldNodeBuilder;
4+
import dev.skidfuscator.builder.MethodNodeBuilder;
35
import dev.skidfuscator.obfuscator.Skidfuscator;
46
import dev.skidfuscator.obfuscator.event.annotation.Listen;
57
import dev.skidfuscator.obfuscator.event.impl.transform.method.RunMethodTransformEvent;
68
import dev.skidfuscator.obfuscator.skidasm.SkidClassNode;
79
import dev.skidfuscator.obfuscator.skidasm.SkidMethodNode;
10+
import dev.skidfuscator.obfuscator.skidasm.builder.SkidFieldNodeBuilder;
11+
import dev.skidfuscator.obfuscator.skidasm.builder.SkidMethodNodeBuilder;
812
import dev.skidfuscator.obfuscator.skidasm.cfg.SkidBlock;
913
import dev.skidfuscator.obfuscator.skidasm.expr.SkidConstantExpr;
1014
import dev.skidfuscator.obfuscator.transform.AbstractTransformer;
1115
import dev.skidfuscator.obfuscator.transform.Transformer;
1216
import dev.skidfuscator.obfuscator.transform.impl.string.generator.BasicEncryptionGenerator;
17+
import dev.skidfuscator.obfuscator.transform.impl.string.generator.BytesEncryptionGenerator;
1318
import dev.skidfuscator.obfuscator.util.RandomUtil;
1419
import org.mapleir.asm.ClassNode;
20+
import org.mapleir.asm.FieldNode;
21+
import org.mapleir.asm.MethodNode;
1522
import org.mapleir.ir.cfg.ControlFlowGraph;
1623
import org.mapleir.ir.code.CodeUnit;
1724
import org.mapleir.ir.code.Expr;
1825
import org.mapleir.ir.code.expr.ConstantExpr;
26+
import org.mapleir.ir.code.expr.NewArrayExpr;
1927
import org.mapleir.ir.code.expr.invoke.StaticInvocationExpr;
28+
import org.mapleir.ir.code.stmt.ReturnStmt;
29+
import org.objectweb.asm.Opcodes;
30+
import org.objectweb.asm.Type;
2031

2132
import java.util.*;
2233
import java.util.stream.Collectors;
2334

2435
public class StringTransformer extends AbstractTransformer {
25-
private final Map<ClassNode, BasicEncryptionGenerator> keyMap = new HashMap<>();
36+
private final Map<ClassNode, BytesEncryptionGenerator> keyMap = new HashMap<>();
37+
2638
private final Set<String> INJECTED = new HashSet<>();
2739

2840
public StringTransformer(Skidfuscator skidfuscator) {
@@ -48,9 +60,9 @@ void handle(final RunMethodTransformEvent event) {
4860
if (cfg == null)
4961
return;
5062

51-
final ClassNode parentNode = methodNode.getParent();
63+
final SkidClassNode parentNode = methodNode.getParent();
5264

53-
BasicEncryptionGenerator generator = keyMap.get(parentNode);
65+
BytesEncryptionGenerator generator = keyMap.get(parentNode);
5466

5567
if (generator == null) {
5668
final int size = RandomUtil.nextInt(127) + 1;
@@ -60,15 +72,15 @@ void handle(final RunMethodTransformEvent event) {
6072
keys[i] = RandomUtil.nextInt(127) + 1;
6173
}
6274

63-
keyMap.put(parentNode, (generator = new BasicEncryptionGenerator(keys)));
75+
keyMap.put(parentNode, (generator = new BytesEncryptionGenerator(keys)));
6476
}
6577

6678
if (!INJECTED.contains(parentNode.getName())) {
6779
generator.visit((SkidClassNode) methodNode.owner, BasicEncryptionGenerator.METHOD_NAME);
6880
INJECTED.add(parentNode.getName());
6981
}
7082

71-
BasicEncryptionGenerator finalGenerator = generator;
83+
BytesEncryptionGenerator finalGenerator = generator;
7284
cfg.allExprStream()
7385
/*
7486
*
@@ -87,15 +99,43 @@ void handle(final RunMethodTransformEvent event) {
8799
final CodeUnit parent = unit.getParent();
88100

89101
final String constant = (String) unit.getConstant();
102+
103+
90104
final int value = methodNode.getBlockPredicate((SkidBlock) unit.getBlock());
91-
final String encrypted = finalGenerator.encrypt(constant, value);
105+
final byte[] encrypted = finalGenerator.encrypt(constant, value);
106+
107+
final SkidMethodNode injector = new SkidMethodNodeBuilder(skidfuscator, parentNode)
108+
.access(Opcodes.ACC_STATIC | Opcodes.ACC_TRANSIENT | Opcodes.ACC_PRIVATE)
109+
.name(RandomUtil.randomAlphabeticalString(15))
110+
.desc("()[B")
111+
.phantom(true)
112+
.build();
92113

93-
final ConstantExpr encryptedExpr = new ConstantExpr(encrypted);
94-
final Expr loadExpr = methodNode.getFlowPredicate().getGetter().get(unit.getBlock());
95114

96-
final Expr modified = new StaticInvocationExpr(new Expr[]{encryptedExpr, loadExpr},
115+
final Expr[] csts = new Expr[encrypted.length];
116+
for (int i = 0; i < encrypted.length; i++) {
117+
csts[i] = new SkidConstantExpr(encrypted[i], Type.BYTE_TYPE);
118+
}
119+
120+
final NewArrayExpr encryptedExpr = new NewArrayExpr(
121+
new Expr[]{new ConstantExpr(encrypted.length, Type.INT_TYPE)},
122+
Type.getType(byte[].class),
123+
csts
124+
);
125+
126+
injector.getCfg()
127+
.getEntry()
128+
.add(new ReturnStmt(Type.getType(byte[].class), encryptedExpr));
129+
130+
final Expr loadExpr = methodNode.getFlowPredicate().getGetter().get(unit.getBlock());
131+
final Expr modified = new StaticInvocationExpr(new Expr[]{new StaticInvocationExpr(
132+
new Expr[0],
133+
parentNode.getName(),
134+
injector.getName(),
135+
injector.getDesc()
136+
), loadExpr},
97137
methodNode.getOwner(), BasicEncryptionGenerator.METHOD_NAME,
98-
"(Ljava/lang/String;I)Ljava/lang/String;");
138+
"([BI)Ljava/lang/String;");
99139

100140
try {
101141
parent.overwrite(unit, modified);

dev.skidfuscator.obfuscator/src/main/java/dev/skidfuscator/obfuscator/transform/impl/string/generator/BasicEncryptionGenerator.java

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import org.objectweb.asm.MethodVisitor;
99
import org.objectweb.asm.Opcodes;
1010

11+
import java.nio.charset.StandardCharsets;
1112
import java.util.Base64;
1213

1314
import static org.objectweb.asm.Opcodes.*;
@@ -21,7 +22,7 @@ public BasicEncryptionGenerator(Integer[] keys) {
2122
}
2223

2324
@Override
24-
public String encrypt(String input, int key) {
25+
public byte[] encrypt(String input, int key) {
2526
final byte[] encrypted = input.getBytes();
2627

2728
// Super simple converting our integer to string, and getting bytes.
@@ -34,24 +35,22 @@ public String encrypt(String input, int key) {
3435
}
3536

3637
// Base64 encode it for testing
37-
return Base64.getEncoder().encodeToString(encrypted);
38+
return encrypted;
3839
}
3940

4041
@Override
41-
public String decrypt(String input, int key) {
42-
final byte[] decrypted = Base64.getDecoder().decode(input.getBytes());
43-
42+
public String decrypt(byte[] input, int key) {
4443
// Super simple converting our integer to string, and getting bytes.
4544
final byte[] keyBytes = Integer.toString(key).getBytes();
4645

4746
// Super simple XOR
48-
for (int i = 0; i < decrypted.length; i++) {
49-
decrypted[i] ^= keyBytes[i % keyBytes.length];
50-
decrypted[i] ^= keys[i % keys.length];
47+
for (int i = 0; i < input.length; i++) {
48+
input[i] ^= keyBytes[i % keyBytes.length];
49+
input[i] ^= keys[i % keys.length];
5150
}
5251

5352
// Base64 encode it for testing
54-
return new String(decrypted);
53+
return new String(input, StandardCharsets.UTF_16);
5554
}
5655

5756
@Override
@@ -69,11 +68,9 @@ public void visit(final SkidClassNode node, String name) {
6968
methodVisitor.visitCode();
7069
Label label0 = new Label();
7170
methodVisitor.visitLabel(label0);
72-
methodVisitor.visitLineNumber(33, label0);
73-
methodVisitor.visitMethodInsn(INVOKESTATIC, "java/util/Base64", "getDecoder", "()Ljava/util/Base64$Decoder;", false);
71+
methodVisitor.visitLineNumber(43, label0);
7472
methodVisitor.visitVarInsn(ALOAD, 0);
7573
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "getBytes", "()[B", false);
76-
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "java/util/Base64$Decoder", "decode", "([B)[B", false);
7774
methodVisitor.visitVarInsn(ASTORE, 2);
7875
Label label1 = new Label();
7976
methodVisitor.visitLabel(label1);
@@ -152,7 +149,8 @@ public void visit(final SkidClassNode node, String name) {
152149
methodVisitor.visitTypeInsn(NEW, "java/lang/String");
153150
methodVisitor.visitInsn(DUP);
154151
methodVisitor.visitVarInsn(ALOAD, 2);
155-
methodVisitor.visitMethodInsn(INVOKESPECIAL, "java/lang/String", "<init>", "([B)V", false);
152+
methodVisitor.visitFieldInsn(GETSTATIC, "java/nio/charset/StandardCharsets", "UTF_8", "Ljava/nio/charset/Charset;");
153+
methodVisitor.visitMethodInsn(INVOKESPECIAL, "java/lang/String", "<init>", "([BLjava/nio/charset/Charset;)V", false);
156154
methodVisitor.visitInsn(ARETURN);
157155
Label label9 = new Label();
158156
methodVisitor.visitLabel(label9);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
package dev.skidfuscator.obfuscator.transform.impl.string.generator;
2+
3+
import dev.skidfuscator.obfuscator.event.EventBus;
4+
import dev.skidfuscator.obfuscator.event.impl.transform.method.InitMethodTransformEvent;
5+
import dev.skidfuscator.obfuscator.skidasm.SkidClassNode;
6+
import dev.skidfuscator.obfuscator.skidasm.SkidMethodNode;
7+
import org.mapleir.asm.FieldNode;
8+
import org.objectweb.asm.Label;
9+
import org.objectweb.asm.MethodVisitor;
10+
import org.objectweb.asm.Opcodes;
11+
12+
import java.nio.charset.StandardCharsets;
13+
import java.util.HashMap;
14+
import java.util.HashSet;
15+
import java.util.Map;
16+
import java.util.Set;
17+
18+
import static org.objectweb.asm.Opcodes.*;
19+
20+
public class BytesEncryptionGenerator implements EncryptionGenerator {
21+
public static final String METHOD_NAME = "thisIsAInsaneEncryptionMethod";
22+
private final Integer[] keys;
23+
24+
public BytesEncryptionGenerator(Integer[] keys) {
25+
this.keys = keys;
26+
}
27+
28+
@Override
29+
public byte[] encrypt(String input, int key) {
30+
final byte[] encrypted = input.getBytes(StandardCharsets.UTF_16);
31+
32+
// Super simple converting our integer to string, and getting bytes.
33+
final byte[] keyBytes = Integer.toString(key).getBytes();
34+
35+
// Super simple XOR
36+
for (int i = 0; i < encrypted.length; i++) {
37+
encrypted[i] ^= keyBytes[i % keyBytes.length];
38+
encrypted[i] ^= keys[i % keys.length];
39+
}
40+
41+
// Base64 encode it for testing
42+
return encrypted;
43+
}
44+
45+
@Override
46+
public String decrypt(byte[] input, int key) {
47+
// Super simple converting our integer to string, and getting bytes.
48+
final byte[] keyBytes = Integer.toString(key).getBytes();
49+
50+
// Super simple XOR
51+
for (int i = 0; i < input.length; i++) {
52+
input[i] ^= keyBytes[i % keyBytes.length];
53+
input[i] ^= keys[i % keys.length];
54+
}
55+
56+
// Base64 encode it for testing
57+
return new String(input, StandardCharsets.UTF_16);
58+
}
59+
60+
@Override
61+
public void visit(final SkidClassNode node, String name) {
62+
// TODO: Fix the retardness and make it so that all
63+
// generated methods can be properly genned
64+
final SkidMethodNode skidMethodNode = node.createMethod()
65+
.access(ACC_PRIVATE | ACC_STATIC)
66+
.name(name)
67+
.desc("([BI)Ljava/lang/String;")
68+
.phantom(true)
69+
.build();
70+
final MethodVisitor methodVisitor = skidMethodNode.node;
71+
72+
methodVisitor.visitCode();
73+
Label label0 = new Label();
74+
methodVisitor.visitLabel(label0);
75+
methodVisitor.visitLineNumber(16, label0);
76+
methodVisitor.visitVarInsn(ILOAD, 1);
77+
methodVisitor.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "toString", "(I)Ljava/lang/String;", false);
78+
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "getBytes", "()[B", false);
79+
methodVisitor.visitVarInsn(ASTORE, 2);
80+
81+
// Keys
82+
methodVisitor.visitIntInsn(BIPUSH, keys.length);
83+
methodVisitor.visitIntInsn(NEWARRAY, T_BYTE);
84+
85+
for (int i = 0; i < keys.length; i++) {
86+
methodVisitor.visitInsn(DUP);
87+
methodVisitor.visitIntInsn(BIPUSH, i);
88+
methodVisitor.visitIntInsn(BIPUSH, keys[i]);
89+
methodVisitor.visitInsn(BASTORE);
90+
}
91+
92+
methodVisitor.visitVarInsn(ASTORE, 4);
93+
94+
Label label1 = new Label();
95+
methodVisitor.visitLabel(label1);
96+
methodVisitor.visitLineNumber(19, label1);
97+
methodVisitor.visitInsn(ICONST_0);
98+
methodVisitor.visitVarInsn(ISTORE, 3);
99+
Label label2 = new Label();
100+
methodVisitor.visitLabel(label2);
101+
methodVisitor.visitFrame(Opcodes.F_APPEND, 2, new Object[]{"[B", Opcodes.INTEGER}, 0, null);
102+
methodVisitor.visitVarInsn(ILOAD, 3);
103+
methodVisitor.visitVarInsn(ALOAD, 0);
104+
methodVisitor.visitInsn(ARRAYLENGTH);
105+
Label label3 = new Label();
106+
methodVisitor.visitJumpInsn(IF_ICMPGE, label3);
107+
Label label4 = new Label();
108+
methodVisitor.visitLabel(label4);
109+
methodVisitor.visitLineNumber(20, label4);
110+
methodVisitor.visitVarInsn(ALOAD, 0);
111+
methodVisitor.visitVarInsn(ILOAD, 3);
112+
methodVisitor.visitInsn(DUP2);
113+
methodVisitor.visitInsn(BALOAD);
114+
methodVisitor.visitVarInsn(ALOAD, 2);
115+
methodVisitor.visitVarInsn(ILOAD, 3);
116+
methodVisitor.visitVarInsn(ALOAD, 2);
117+
methodVisitor.visitInsn(ARRAYLENGTH);
118+
methodVisitor.visitInsn(IREM);
119+
methodVisitor.visitInsn(BALOAD);
120+
methodVisitor.visitInsn(IXOR);
121+
methodVisitor.visitInsn(I2B);
122+
methodVisitor.visitInsn(BASTORE);
123+
Label label5 = new Label();
124+
methodVisitor.visitLabel(label5);
125+
methodVisitor.visitLineNumber(21, label5);
126+
methodVisitor.visitVarInsn(ALOAD, 0);
127+
methodVisitor.visitVarInsn(ILOAD, 3);
128+
methodVisitor.visitInsn(DUP2);
129+
methodVisitor.visitInsn(BALOAD);
130+
methodVisitor.visitVarInsn(ALOAD, 4);
131+
methodVisitor.visitVarInsn(ILOAD, 3);
132+
methodVisitor.visitVarInsn(ALOAD, 4);
133+
methodVisitor.visitInsn(ARRAYLENGTH);
134+
methodVisitor.visitInsn(IREM);
135+
methodVisitor.visitInsn(BALOAD);
136+
methodVisitor.visitInsn(IXOR);
137+
methodVisitor.visitInsn(I2B);
138+
methodVisitor.visitInsn(BASTORE);
139+
Label label6 = new Label();
140+
methodVisitor.visitLabel(label6);
141+
methodVisitor.visitLineNumber(19, label6);
142+
methodVisitor.visitIincInsn(3, 1);
143+
methodVisitor.visitJumpInsn(GOTO, label2);
144+
methodVisitor.visitLabel(label3);
145+
methodVisitor.visitLineNumber(25, label3);
146+
methodVisitor.visitFrame(Opcodes.F_CHOP, 1, null, 0, null);
147+
methodVisitor.visitTypeInsn(NEW, "java/lang/String");
148+
methodVisitor.visitInsn(DUP);
149+
methodVisitor.visitVarInsn(ALOAD, 0);
150+
methodVisitor.visitFieldInsn(GETSTATIC, "java/nio/charset/StandardCharsets", "UTF_16", "Ljava/nio/charset/Charset;");
151+
methodVisitor.visitMethodInsn(INVOKESPECIAL, "java/lang/String", "<init>", "([BLjava/nio/charset/Charset;)V", false);
152+
methodVisitor.visitInsn(ARETURN);
153+
Label label7 = new Label();
154+
methodVisitor.visitLabel(label7);
155+
methodVisitor.visitLocalVariable("i", "I", null, label2, label3, 3);
156+
methodVisitor.visitLocalVariable("input", "[B", null, label0, label7, 0);
157+
methodVisitor.visitLocalVariable("key", "I", null, label0, label7, 1);
158+
methodVisitor.visitLocalVariable("keyBytes", "[B", null, label1, label7, 2);
159+
methodVisitor.visitLocalVariable("keys", "[B", null, label0, label7, 3);
160+
methodVisitor.visitMaxs(6, 5);
161+
methodVisitor.visitEnd();
162+
163+
// /!\ Absolutely critical line
164+
skidMethodNode.recomputeCfg();
165+
EventBus.call(
166+
new InitMethodTransformEvent(skidMethodNode.getSkidfuscator(), skidMethodNode)
167+
);
168+
}
169+
}

dev.skidfuscator.obfuscator/src/main/java/dev/skidfuscator/obfuscator/transform/impl/string/generator/EncryptionGenerator.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
import dev.skidfuscator.obfuscator.skidasm.SkidClassNode;
44

55
public interface EncryptionGenerator {
6-
String encrypt(String input, int key);
6+
byte[] encrypt(String input, int key);
77

8-
String decrypt(String input, int key);
8+
String decrypt(byte[] input, int key);
99

1010
void visit(final SkidClassNode node, String name);
1111
}

0 commit comments

Comments
 (0)