Skip to content

Commit 2ed36d4

Browse files
committed
Condition obfuscation
1 parent 1c4d025 commit 2ed36d4

File tree

8 files changed

+335
-10
lines changed

8 files changed

+335
-10
lines changed

README.md

Lines changed: 116 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ A powerful and flexible Java bytecode obfuscator built with ASM that provides co
99
- **Method Renaming** - Obfuscate method names with intelligent handling of constructors, synthetic methods, and inheritance
1010
- **Field Renaming** - Rename fields while maintaining proper access relationships
1111
- **Local Variable Renaming** - Obfuscate local variable names for additional protection
12+
- **Condition Obfuscation** - Transform simple boolean constants (true/false) into complex arithmetic expressions
1213
- **Reference Updating** - Automatically updates all references to renamed elements throughout the codebase
1314
- **Inheritance-Aware Renaming** - Properly handles interface implementations and method overrides
1415
- **Multiple Naming Modes** - Choose from sequential, alphabetic, random short/long, or single character naming schemes
@@ -58,25 +59,25 @@ cd java-bytecode-obfuscator
5859
```bash
5960
# Simple obfuscation with all features enabled
6061
java -jar java-bytecode-obfuscator-1.0-SNAPSHOT.jar input.jar output.jar \
61-
--rename-classes --rename-methods --rename-fields --rename-local-variables
62+
--rename-classes --rename-methods --rename-fields --rename-local-variables --obfuscate-conditions
6263

6364
# With main class protection
6465
java -jar java-bytecode-obfuscator-1.0-SNAPSHOT.jar input.jar output.jar \
6566
-m com.example.Main --keep-main-class --keep-entry-points \
66-
--rename-classes --rename-methods --rename-fields --rename-local-variables
67+
--rename-classes --rename-methods --rename-fields --rename-local-variables --obfuscate-conditions
6768

6869
# Generate mappings for debugging
6970
java -jar java-bytecode-obfuscator-1.0-SNAPSHOT.jar input.jar output.jar \
7071
--mappings mappings.txt --verbose \
71-
--rename-classes --rename-methods --rename-fields --rename-local-variables
72+
--rename-classes --rename-methods --rename-fields --rename-local-variables --obfuscate-conditions
7273

7374
# Use different naming modes
7475
java -jar java-bytecode-obfuscator-1.0-SNAPSHOT.jar input.jar output.jar \
75-
--naming-mode RANDOM_SHORT --rename-classes --rename-methods --rename-fields
76+
--naming-mode RANDOM_SHORT --rename-classes --rename-methods --rename-fields --obfuscate-conditions
7677

7778
java -jar java-bytecode-obfuscator-1.0-SNAPSHOT.jar input.jar output.jar \
7879
--naming-mode SEQUENTIAL_ALPHA --verbose \
79-
--rename-classes --rename-methods --rename-fields --rename-local-variables
80+
--rename-classes --rename-methods --rename-fields --rename-local-variables --obfuscate-conditions
8081
```
8182

8283
### Configuration File
@@ -89,6 +90,8 @@ Create a JSON configuration file for complex scenarios:
8990
"renameClasses": true,
9091
"renameFields": true,
9192
"renameMethods": true,
93+
"renameLocalVariables": true,
94+
"obfuscateConditions": true,
9295
"namingMode": "RANDOM_SHORT",
9396
"verbose": true,
9497
"keepRules": {
@@ -117,6 +120,8 @@ ObfuscationConfig config = new ObfuscationConfig.Builder()
117120
.renameClasses(true)
118121
.renameFields(true)
119122
.renameMethods(true)
123+
.renameLocalVariables(true)
124+
.obfuscateConditions(true)
120125
.namingMode(NamingMode.RANDOM_SHORT)
121126
.verbose(true)
122127

@@ -194,6 +199,101 @@ ObfuscationConfig config = new ObfuscationConfig.Builder()
194199
.build();
195200
```
196201

202+
## Condition Obfuscation
203+
204+
Condition obfuscation transforms simple boolean constants (`true` and `false`) into mathematically equivalent complex expressions that make the code harder to understand and analyze.
205+
206+
### How It Works
207+
208+
The transformer replaces simple boolean constants with arithmetic expressions that evaluate to the same value:
209+
210+
**Original Code:**
211+
```java
212+
if (someFlag == true) {
213+
doSomething();
214+
}
215+
boolean result = false;
216+
```
217+
218+
**Obfuscated Code:**
219+
```java
220+
// true becomes: 2 - 1
221+
if (someFlag == (2 - 1)) {
222+
doSomething();
223+
}
224+
// false becomes: 1 - 1
225+
boolean result = (1 - 1);
226+
```
227+
228+
### Features
229+
230+
- **Safe Transformation** - Only transforms constants that are likely to be boolean conditions (10% probability to avoid breaking non-boolean integer usage)
231+
- **Multiple Strategies** - Uses various mathematical expressions to avoid patterns
232+
- **Stackmap-Safe** - Generates bytecode that passes JVM verification
233+
- **Conservative Approach** - Only targets simple constant loading to maintain program correctness
234+
235+
### Usage
236+
237+
```bash
238+
# Enable condition obfuscation via CLI
239+
java -jar obfuscator.jar input.jar output.jar --obfuscate-conditions
240+
241+
# Combined with other obfuscation techniques
242+
java -jar obfuscator.jar input.jar output.jar \
243+
--rename-classes --rename-methods --rename-fields \
244+
--obfuscate-conditions --verbose
245+
```
246+
247+
### Configuration
248+
249+
```json
250+
{
251+
"renameClasses": true,
252+
"renameFields": true,
253+
"renameMethods": true,
254+
"obfuscateConditions": true,
255+
"verbose": true
256+
}
257+
```
258+
259+
### Programmatic Usage
260+
261+
```java
262+
ObfuscationConfig config = new ObfuscationConfig.Builder()
263+
.renameClasses(true)
264+
.renameFields(true)
265+
.renameMethods(true)
266+
.obfuscateConditions(true)
267+
.build();
268+
```
269+
270+
### Examples
271+
272+
**Before Obfuscation:**
273+
```java
274+
public boolean isEnabled() {
275+
return true;
276+
}
277+
278+
public void process() {
279+
if (false) {
280+
handleError();
281+
}
282+
}
283+
```
284+
285+
**After Obfuscation:**
286+
```java
287+
public boolean a() {
288+
return 3 - 2; // Evaluates to 1 (true)
289+
}
290+
291+
public void b() {
292+
if (5 - 5) { // Evaluates to 0 (false)
293+
c();
294+
}
295+
}
296+
197297
## CLI Reference
198298

199299
### Command Line Options
@@ -212,6 +312,7 @@ Options:
212312
--rename-fields Enable field renaming
213313
--rename-methods Enable method renaming
214314
--rename-local-variables Enable local variable renaming
315+
--obfuscate-conditions Enable condition obfuscation (transforms boolean constants)
215316
-n, --naming-mode <mode> Name generation mode (SEQUENTIAL_PREFIX, SEQUENTIAL_ALPHA,
216317
RANDOM_SHORT, RANDOM_LONG, SINGLE_CHAR)
217318
--mappings <file> Output mappings file
@@ -238,6 +339,7 @@ java -jar obfuscator.jar input.jar output.jar \
238339
--main-class com/example/Main \
239340
--keep-main-class \
240341
--keep-entry-points \
342+
--obfuscate-conditions \
241343
--verbose
242344
243345
# Keep specific classes
@@ -252,16 +354,18 @@ java -jar obfuscator.jar input.jar output.jar --mappings mappings.txt
252354
# Use different naming modes
253355
java -jar obfuscator.jar input.jar output.jar \
254356
--naming-mode RANDOM_LONG \
255-
--rename-classes --rename-methods --rename-fields
357+
--rename-classes --rename-methods --rename-fields --obfuscate-conditions
256358
257359
java -jar obfuscator.jar input.jar output.jar \
258360
--naming-mode SINGLE_CHAR \
361+
--obfuscate-conditions \
259362
--verbose
260363
261364
# Override config file settings
262365
java -jar obfuscator.jar -c config.json input.jar output.jar \
263366
--rename-classes false \
264367
--naming-mode SEQUENTIAL_ALPHA \
368+
--obfuscate-conditions \
265369
--verbose
266370
```
267371

@@ -274,6 +378,8 @@ java -jar obfuscator.jar -c config.json input.jar output.jar \
274378
"renameClasses": true,
275379
"renameFields": true,
276380
"renameMethods": true,
381+
"renameLocalVariables": true,
382+
"obfuscateConditions": true,
277383
"namingMode": "SEQUENTIAL_PREFIX",
278384
"verbose": true,
279385
"keepRules": {
@@ -290,6 +396,8 @@ java -jar obfuscator.jar -c config.json input.jar output.jar \
290396
"renameClasses": true,
291397
"renameFields": true,
292398
"renameMethods": true,
399+
"renameLocalVariables": true,
400+
"obfuscateConditions": true,
293401
"namingMode": "RANDOM_SHORT",
294402
"verbose": false,
295403
"keepRules": {
@@ -342,6 +450,8 @@ java -jar obfuscator.jar -c config.json input.jar output.jar \
342450
"renameClasses": true,
343451
"renameFields": true,
344452
"renameMethods": true,
453+
"renameLocalVariables": true,
454+
"obfuscateConditions": true,
345455
"namingMode": "RANDOM_LONG",
346456
"verbose": true,
347457
"keepRules": {
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"mainClass": "com/example/Application",
3+
"renameClasses": true,
4+
"renameFields": true,
5+
"renameMethods": true,
6+
"renameLocalVariables": true,
7+
"obfuscateConditions": true,
8+
"namingMode": "RANDOM_SHORT",
9+
"verbose": true,
10+
"keepRules": {
11+
"keepMainClass": true,
12+
"keepStandardEntryPoints": true,
13+
"keepClassPatterns": [
14+
".*Configuration",
15+
".*Controller",
16+
".*Entity"
17+
],
18+
"keepMethodPatterns": {
19+
".*Controller": ["handle.*", "process.*"],
20+
".*Service": ["get.*", "set.*", "find.*"]
21+
},
22+
"keepFieldPatterns": {
23+
".*Entity": ["id", ".*Date", ".*Time"],
24+
".*Configuration": [".*"]
25+
}
26+
}
27+
}

src/main/java/net/cvs0/Main.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ public class Main implements Callable<Integer>
4141
@Option(names = {"--rename-local-variables"}, description = "Enable local variable renaming")
4242
private Boolean renameLocalVariables;
4343

44+
@Option(names = {"--obfuscate-conditions"}, description = "Enable condition obfuscation (transforms true/false into complex expressions)")
45+
private Boolean obfuscateConditions;
46+
4447
@Option(names = {"--mappings", "--output-mappings"}, description = "Output mappings file")
4548
private File mappingsFile;
4649

@@ -155,6 +158,10 @@ private ObfuscationConfig buildConfiguration() throws Exception
155158
builder.renameLocalVariables(renameLocalVariables);
156159
}
157160

161+
if (obfuscateConditions != null) {
162+
builder.obfuscateConditions(obfuscateConditions);
163+
}
164+
158165
if (verbose) {
159166
builder.verbose(true);
160167
}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import net.cvs0.transformers.FieldRenameTransformer;
77
import net.cvs0.transformers.MethodRenameTransformer;
88
import net.cvs0.transformers.LocalVariableRenameTransformer;
9+
import net.cvs0.transformers.ConditionObfuscationTransformer;
910

1011
import java.io.File;
1112
import java.io.IOException;
@@ -25,6 +26,7 @@ private void registerDefaultTransformers()
2526
engine.registerTransformer(new ClassRenameTransformer());
2627
engine.registerTransformer(new FieldRenameTransformer());
2728
engine.registerTransformer(new MethodRenameTransformer());
29+
engine.registerTransformer(new ConditionObfuscationTransformer());
2830
engine.registerTransformer(new LocalVariableRenameTransformer());
2931
}
3032

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,24 @@ private void parseBasicSettings(JsonNode root, ObfuscationConfig.Builder builder
4343
builder.renameMethods(root.get("renameMethods").asBoolean());
4444
}
4545

46+
if (root.has("renameLocalVariables")) {
47+
builder.renameLocalVariables(root.get("renameLocalVariables").asBoolean());
48+
}
49+
50+
if (root.has("obfuscateConditions")) {
51+
builder.obfuscateConditions(root.get("obfuscateConditions").asBoolean());
52+
}
53+
54+
if (root.has("namingMode")) {
55+
String namingModeStr = root.get("namingMode").asText();
56+
try {
57+
NamingMode namingMode = NamingMode.valueOf(namingModeStr);
58+
builder.namingMode(namingMode);
59+
} catch (IllegalArgumentException e) {
60+
System.err.println("Warning: Invalid naming mode '" + namingModeStr + "', using default");
61+
}
62+
}
63+
4664
if (root.has("verbose")) {
4765
builder.verbose(root.get("verbose").asBoolean());
4866
}

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

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ public class ObfuscationConfig
1010
private final boolean renameFields;
1111
private final boolean renameMethods;
1212
private final boolean renameLocalVariables;
13+
private final boolean obfuscateConditions;
1314
private final boolean verbose;
1415
private final KeepRules keepRules;
1516
private final String packageScope;
@@ -21,6 +22,7 @@ public ObfuscationConfig(
2122
boolean renameFields,
2223
boolean renameMethods,
2324
boolean renameLocalVariables,
25+
boolean obfuscateConditions,
2426
boolean verbose,
2527
KeepRules keepRules,
2628
String packageScope,
@@ -31,6 +33,7 @@ public ObfuscationConfig(
3133
this.renameFields = renameFields;
3234
this.renameMethods = renameMethods;
3335
this.renameLocalVariables = renameLocalVariables;
36+
this.obfuscateConditions = obfuscateConditions;
3437
this.verbose = verbose;
3538
this.keepRules = keepRules != null ? keepRules : new KeepRules();
3639
this.packageScope = packageScope;
@@ -62,6 +65,11 @@ public boolean isRenameLocalVariables()
6265
return renameLocalVariables;
6366
}
6467

68+
public boolean isObfuscateConditions()
69+
{
70+
return obfuscateConditions;
71+
}
72+
6573
public boolean isVerbose()
6674
{
6775
return verbose;
@@ -226,6 +234,7 @@ public static class Builder
226234
private boolean renameFields = true;
227235
private boolean renameMethods = true;
228236
private boolean renameLocalVariables = true;
237+
private boolean obfuscateConditions = false;
229238
private boolean verbose = false;
230239
private final KeepRules keepRules = new KeepRules();
231240
private String packageScope;
@@ -234,11 +243,11 @@ public static class Builder
234243
public Builder mainClass(String mainClass)
235244
{
236245
this.mainClass = mainClass;
237-
if (mainClass != null) {
246+
if (mainClass != null && !mainClass.isEmpty()) {
238247
String[] parts = mainClass.split("/");
239-
if (parts.length >= 2) {
248+
if (parts.length >= 2 && parts[0] != null && parts[1] != null) {
240249
this.packageScope = parts[0] + "/" + parts[1];
241-
} else if (parts.length == 1) {
250+
} else if (parts.length == 1 && parts[0] != null) {
242251
this.packageScope = parts[0];
243252
} else {
244253
this.packageScope = "";
@@ -271,6 +280,12 @@ public Builder renameLocalVariables(boolean renameLocalVariables)
271280
return this;
272281
}
273282

283+
public Builder obfuscateConditions(boolean obfuscateConditions)
284+
{
285+
this.obfuscateConditions = obfuscateConditions;
286+
return this;
287+
}
288+
274289
public Builder verbose(boolean verbose)
275290
{
276291
this.verbose = verbose;
@@ -355,7 +370,7 @@ public Builder keepStandardEntryPoints()
355370

356371
public ObfuscationConfig build()
357372
{
358-
return new ObfuscationConfig(mainClass, renameClasses, renameFields, renameMethods, renameLocalVariables, verbose, keepRules, packageScope, namingMode);
373+
return new ObfuscationConfig(mainClass, renameClasses, renameFields, renameMethods, renameLocalVariables, obfuscateConditions, verbose, keepRules, packageScope, namingMode);
359374
}
360375
}
361376
}

0 commit comments

Comments
 (0)