Skip to content

Commit 352c7f8

Browse files
committed
Fixed mapping + Abstracted transformers
1 parent e8864d4 commit 352c7f8

12 files changed

+565
-188
lines changed

src/main/java/net/cvs0/Obfuscator.java

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import net.cvs0.transformers.LocalVariableRenameTransformer;
1010
import net.cvs0.transformers.ConditionObfuscationTransformer;
1111
import net.cvs0.transformers.StringCompressionTransformer;
12+
1213
import net.cvs0.utils.AntiDebugger;
1314

1415
import java.io.File;
@@ -35,22 +36,6 @@ private void registerDefaultTransformers()
3536
engine.registerTransformer(new StringCompressionTransformer());
3637
}
3738

38-
public void obfuscate(File inputJar, File outputJar, ObfuscationConfig config, File mappingsFile) throws IOException
39-
{
40-
if (inputJar == null) {
41-
throw new IllegalArgumentException("Input JAR file cannot be null");
42-
}
43-
if (outputJar == null) {
44-
throw new IllegalArgumentException("Output JAR file cannot be null");
45-
}
46-
if (config == null) {
47-
throw new IllegalArgumentException("Obfuscation config cannot be null");
48-
}
49-
50-
setupConditionalTransformers(config);
51-
engine.obfuscate(inputJar, outputJar, config, mappingsFile);
52-
}
53-
5439
public void obfuscate(File inputJar, File outputJar, ObfuscationConfig config, File mappingsFile, MappingExporter.MappingFormat format) throws IOException
5540
{
5641
if (inputJar == null) {
Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
package net.cvs0.config;
2+
3+
import java.util.Set;
4+
import java.util.HashSet;
5+
import java.util.Map;
6+
import java.util.HashMap;
7+
8+
public class KeepRulesManager
9+
{
10+
private static final Map<String, KeepRuleSet> PREDEFINED_RULES = new HashMap<>();
11+
12+
static {
13+
initializePredefinedRules();
14+
}
15+
16+
private static void initializePredefinedRules()
17+
{
18+
KeepRuleSet standardEntryPoints = new KeepRuleSet("Standard Entry Points");
19+
standardEntryPoints.addMethodKeepRule("*", "main\\(\\[Ljava/lang/String;\\)V");
20+
standardEntryPoints.addMethodKeepRule("*", "<init>");
21+
standardEntryPoints.addMethodKeepRule("*", "<clinit>");
22+
23+
PREDEFINED_RULES.put("STANDARD_ENTRY_POINTS", standardEntryPoints);
24+
25+
KeepRuleSet serializationRules = new KeepRuleSet("Serialization Rules");
26+
serializationRules.addFieldKeepRule("*", "serialVersionUID");
27+
serializationRules.addMethodKeepRule("*", "writeObject\\(Ljava/io/ObjectOutputStream;\\)V");
28+
serializationRules.addMethodKeepRule("*", "readObject\\(Ljava/io/ObjectInputStream;\\)V");
29+
serializationRules.addMethodKeepRule("*", "readObjectNoData\\(\\)V");
30+
31+
PREDEFINED_RULES.put("SERIALIZATION", serializationRules);
32+
}
33+
34+
public static KeepRuleSet getPredefinedRules(String ruleName)
35+
{
36+
return PREDEFINED_RULES.get(ruleName);
37+
}
38+
39+
public static void applyRulesToBuilder(ObfuscationConfig.Builder builder, String... ruleNames)
40+
{
41+
for (String ruleName : ruleNames) {
42+
KeepRuleSet rules = getPredefinedRules(ruleName);
43+
if (rules != null) {
44+
rules.applyToBuilder(builder);
45+
}
46+
}
47+
}
48+
49+
public static class KeepRuleSet
50+
{
51+
private final String name;
52+
private final Set<FieldKeepRule> fieldRules = new HashSet<>();
53+
private final Set<MethodKeepRule> methodRules = new HashSet<>();
54+
private final Set<ClassKeepRule> classRules = new HashSet<>();
55+
56+
public KeepRuleSet(String name)
57+
{
58+
this.name = name;
59+
}
60+
61+
public void addFieldKeepRule(String classPattern, String fieldPattern)
62+
{
63+
fieldRules.add(new FieldKeepRule(classPattern, fieldPattern));
64+
}
65+
66+
public void addMethodKeepRule(String classPattern, String methodPattern)
67+
{
68+
methodRules.add(new MethodKeepRule(classPattern, methodPattern));
69+
}
70+
71+
public void addClassKeepRule(String classPattern)
72+
{
73+
classRules.add(new ClassKeepRule(classPattern));
74+
}
75+
76+
public void applyToBuilder(ObfuscationConfig.Builder builder)
77+
{
78+
for (FieldKeepRule rule : fieldRules) {
79+
if (rule.getFieldPattern().equals("*")) {
80+
builder.keepAllFieldsForClass(rule.getClassPattern());
81+
} else {
82+
builder.keepClassFieldPattern(rule.getClassPattern(), rule.getFieldPattern());
83+
}
84+
}
85+
86+
for (MethodKeepRule rule : methodRules) {
87+
if (rule.getMethodPattern().equals("*")) {
88+
builder.keepAllMethodsForClass(rule.getClassPattern());
89+
} else {
90+
builder.keepClassMethodPattern(rule.getClassPattern(), rule.getMethodPattern());
91+
}
92+
}
93+
94+
for (ClassKeepRule rule : classRules) {
95+
builder.keepClassPattern(rule.getClassPattern());
96+
}
97+
}
98+
99+
private static class FieldKeepRule
100+
{
101+
final String classPattern;
102+
final String fieldPattern;
103+
104+
FieldKeepRule(String classPattern, String fieldPattern)
105+
{
106+
this.classPattern = classPattern;
107+
this.fieldPattern = fieldPattern;
108+
}
109+
110+
public String getClassPattern()
111+
{
112+
return classPattern;
113+
}
114+
115+
public String getFieldPattern()
116+
{
117+
return fieldPattern;
118+
}
119+
120+
@Override
121+
public boolean equals(Object o)
122+
{
123+
if (this == o) return true;
124+
if (!(o instanceof FieldKeepRule)) return false;
125+
FieldKeepRule that = (FieldKeepRule) o;
126+
return getClassPattern().equals(that.getClassPattern()) && getFieldPattern().equals(that.getFieldPattern());
127+
}
128+
129+
@Override
130+
public int hashCode()
131+
{
132+
return getClassPattern().hashCode() * 31 + getFieldPattern().hashCode();
133+
}
134+
}
135+
136+
private static class MethodKeepRule
137+
{
138+
final String classPattern;
139+
final String methodPattern;
140+
141+
MethodKeepRule(String classPattern, String methodPattern)
142+
{
143+
this.classPattern = classPattern;
144+
this.methodPattern = methodPattern;
145+
}
146+
147+
public String getClassPattern()
148+
{
149+
return classPattern;
150+
}
151+
152+
public String getMethodPattern()
153+
{
154+
return methodPattern;
155+
}
156+
157+
@Override
158+
public boolean equals(Object o)
159+
{
160+
if (this == o) return true;
161+
if (!(o instanceof MethodKeepRule)) return false;
162+
MethodKeepRule that = (MethodKeepRule) o;
163+
return getClassPattern().equals(that.getClassPattern()) && getMethodPattern().equals(that.getMethodPattern());
164+
}
165+
166+
@Override
167+
public int hashCode()
168+
{
169+
return getClassPattern().hashCode() * 31 + getMethodPattern().hashCode();
170+
}
171+
}
172+
173+
private static class ClassKeepRule
174+
{
175+
final String classPattern;
176+
177+
ClassKeepRule(String classPattern)
178+
{
179+
this.classPattern = classPattern;
180+
}
181+
182+
public String getClassPattern()
183+
{
184+
return classPattern;
185+
}
186+
187+
@Override
188+
public boolean equals(Object o)
189+
{
190+
if (this == o) return true;
191+
if (!(o instanceof ClassKeepRule)) return false;
192+
ClassKeepRule that = (ClassKeepRule) o;
193+
return getClassPattern().equals(that.getClassPattern());
194+
}
195+
196+
@Override
197+
public int hashCode()
198+
{
199+
return getClassPattern().hashCode();
200+
}
201+
}
202+
}
203+
}

src/main/java/net/cvs0/config/ObfuscationConfig.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -732,9 +732,7 @@ public Builder keepMainClass()
732732

733733
public Builder keepStandardEntryPoints()
734734
{
735-
keepClassMethodPattern(".*", "main\\(\\[Ljava/lang/String;\\)V");
736-
keepClassMethodPattern(".*", "<init>");
737-
keepClassMethodPattern(".*", "<clinit>");
735+
KeepRulesManager.applyRulesToBuilder(this, "STANDARD_ENTRY_POINTS");
738736
return this;
739737
}
740738

src/main/java/net/cvs0/context/TransformationContext.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ public TransformationContext(ObfuscationConfig config)
3838
private void initializeDefaults()
3939
{
4040
setGlobalProperty("verbose", config.isVerbose());
41-
setGlobalProperty("config.packageScope", config.getPackageScope());
41+
String packageScope = config.getPackageScope();
42+
setGlobalProperty("config.packageScope", packageScope != null ? packageScope : "");
4243
setGlobalProperty("transformation.startTime", startTime);
4344
setGlobalProperty("transformation.thread", Thread.currentThread().getName());
4445
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package net.cvs0.core;
2+
3+
import net.cvs0.context.ObfuscationContext;
4+
5+
public interface ContextProvider
6+
{
7+
ObfuscationContext getContext();
8+
String getCurrentClassName();
9+
}

src/main/java/net/cvs0/core/ObfuscationEngine.java

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ private Map<String, byte[]> obfuscateParallel(Map<String, byte[]> inputClasses,
227227

228228
private byte[] transformClass(ClassReader reader, ObfuscationContext context, String className) throws Exception
229229
{
230-
ClassWriter writer = new ClassWriter(reader, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
230+
ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
231231

232232
ClassReader currentReader = reader;
233233
ClassWriter currentWriter = writer;
@@ -236,10 +236,14 @@ private byte[] transformClass(ClassReader reader, ObfuscationContext context, St
236236
for (Transformer transformer : transformers) {
237237
if (transformer.isEnabled(context)) {
238238
try {
239-
ClassWriter nextWriter = new ClassWriter(currentReader, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
239+
ClassWriter nextWriter = new ClassWriter(ClassWriter.COMPUTE_MAXS);
240240
transformer.transform(currentReader, nextWriter, context);
241241

242242
byte[] transformedBytes = nextWriter.toByteArray();
243+
if (transformedBytes == null || transformedBytes.length == 0) {
244+
Logger.error("Transformer " + transformer.getName() + " produced empty bytecode for class " + className + " - skipping further transformations");
245+
break;
246+
}
243247

244248
ClassReader testReader = new ClassReader(transformedBytes);
245249
String testClassName = testReader.getClassName();
@@ -260,7 +264,13 @@ private byte[] transformClass(ClassReader reader, ObfuscationContext context, St
260264
}
261265
}
262266

263-
return currentWriter.toByteArray();
267+
byte[] result = currentWriter.toByteArray();
268+
if (result == null || result.length == 0) {
269+
Logger.warning("Final transformation produced empty bytecode for class " + className + " - using original");
270+
return reader.b;
271+
}
272+
273+
return result;
264274
}
265275

266276
private Map<String, byte[]> obfuscateSequentially(Map<String, byte[]> inputClasses, ObfuscationConfig config, ObfuscationContext context) throws IOException

0 commit comments

Comments
 (0)