Skip to content

Commit 8c14ee5

Browse files
committed
fix(obf): fix #47
1 parent 184ed6a commit 8c14ee5

7 files changed

Lines changed: 231 additions & 18 deletions

File tree

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,3 +96,9 @@ dev.skidfuscator.obfuscator/src/test/resources/test.jar.compressed.skid
9696
skidfuscator.log
9797

9898
calculations.txt
99+
100+
dev.skidfuscator.obfuscator/out/test/resources/test.jar.compressed.skid
101+
102+
dev.skidfuscator.obfuscator/out/test/resources/test.jar.compressed.json
103+
104+
dev.skidfuscator.obfuscator/out/test/resources/test.jar.compressed
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
exempt: [
2+
"class{^dev\\/skidfuscator\\/test}"
3+
]
4+
5+
driver: {
6+
enabled: true
7+
}
8+
9+
classRenamer {
10+
enabled: true
11+
}
12+
13+
methodRenamer {
14+
enabled: false
15+
}
16+
17+
flowException {
18+
enabled: true
19+
exempt: []
20+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
exempt: [
2+
"class{^dev\\/skidfuscator\\/test}"
3+
]
4+
5+
driver: {
6+
enabled: true
7+
}
8+
9+
fileCrasher: {
10+
enabled: false
11+
}
12+
13+
stringEncryption {
14+
type: STANDARD
15+
enabled: true
16+
exempt: []
17+
}
18+
19+
exceptionReturn {
20+
enabled: true
21+
exempt: []
22+
}
23+
24+
classRenamer {
25+
enabled: false
26+
type: CUSTOM
27+
prefix: "skido/"
28+
chars: [
29+
"K"
30+
"oO",
31+
"o0"
32+
]
33+
depth: 3
34+
}
35+
36+
methodRenamer {
37+
enabled: false
38+
type: CUSTOM
39+
chars: [
40+
"K"
41+
"oO",
42+
"o0"
43+
]
44+
depth: 3
45+
}
46+
47+
fieldRenamer {
48+
enabled: false
49+
type: ALPHABETICAL
50+
}
51+
52+
flowException {
53+
enabled: true
54+
strength: AGGRESSIVE
55+
exempt: []
56+
}
57+
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
exempt: [
2+
"class{^dev\\/skidfuscator\\/test}"
3+
]
4+
5+
driver: {
6+
enabled: true
7+
}
8+
9+
fileCrasher: {
10+
enabled: false
11+
}
12+
13+
stringEncryption {
14+
type: STANDARD
15+
enabled: true
16+
exempt: []
17+
}
18+
19+
reference {
20+
enabled: true
21+
}
22+
23+
exceptionReturn {
24+
25+
enabled: true
26+
exempt: []
27+
}
28+
29+
classRenamer {
30+
enabled: false
31+
type: CUSTOM
32+
prefix: "skido/"
33+
chars: [
34+
"K"
35+
"oO",
36+
"o0"
37+
]
38+
depth: 3
39+
}
40+
41+
methodRenamer {
42+
enabled: true
43+
type: CUSTOM
44+
chars: [
45+
"K"
46+
"oO",
47+
"o0"
48+
]
49+
depth: 3
50+
}
51+
52+
fieldRenamer {
53+
enabled: false
54+
type: ALPHABETICAL
55+
}
56+
57+
flowException {
58+
enabled: true
59+
exempt: []
60+
}
61+
62+
outliner {
63+
enable: false
64+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
method{main}

org.mapleir.parent/org.mapleir.ir/src/main/java/org/mapleir/ir/algorithms/BoissinotDestructor.java

Lines changed: 81 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ private BoissinotDestructor(ControlFlowGraph cfg) {
9898

9999
coalescePhis();
100100
coalesceCopies();
101-
101+
102102
remapLocals();
103103
applyRemapping();
104104

@@ -353,9 +353,36 @@ private void coalesceCopies() {
353353
if (!copy.isSynthetic() && copy.getExpression() instanceof VarExpr) {
354354
Local lhs = copy.getVariable().getLocal();
355355
Local rhs = ((VarExpr) copy.getExpression()).getLocal();
356-
if (!isReservedRegister((VersionedLocal) rhs)) {
356+
357+
/*
358+
* Fix 4th December 2023
359+
* right and left must be both of same type to coalesce, or else
360+
* variables initialized with null and overriden in one branch
361+
* will have that one branch value propagated to the other branch
362+
*
363+
* eg:
364+
* var = nullconst
365+
* for (i in [0, 10)) {
366+
* if (cond) {
367+
* var = i
368+
* }
369+
* }
370+
* print(var)
371+
*
372+
* would become:
373+
*
374+
* var = nullconst
375+
* for (i in [0, 10)) {
376+
* var = i;
377+
* if (cond) {
378+
* }
379+
* }
380+
* print(var)
381+
*
382+
*/
383+
if (!isReservedRegister((VersionedLocal) rhs) && lhs.isStack() == rhs.isStack()) {
357384
if (tryCoalesceCopyValue(lhs, rhs)) {
358-
// System.out.println("COPYKILL(1) " + lhs + " == " + rhs);
385+
//System.out.println("COPYKILL(1) " + lhs + " == " + rhs);
359386
it.remove();
360387
}
361388

@@ -398,32 +425,32 @@ private boolean isReservedRegister(VersionedLocal l) {
398425

399426
// Process the copy a = b. Returns true if a and b can be coalesced via value.
400427
private boolean tryCoalesceCopyValue(Local a, Local b) {
401-
// System.out.println("Enter COPY");
428+
//System.out.println("Enter COPY");
402429
CongruenceClass conClassA = getCongruenceClass(a);
403430
CongruenceClass conClassB = getCongruenceClass(b);
404431

405-
// System.out.println(" A: " + conClassA);
406-
// System.out.println(" B: " + conClassB);
432+
//System.out.println(" A: " + conClassA);
433+
//System.out.println(" B: " + conClassB);
407434

408-
// System.out.println(" same=" + (conClassA == conClassB));
435+
//System.out.println(" same=" + (conClassA == conClassB));
409436
if (conClassA == conClassB)
410437
return true;
411438

412439
if (conClassA.size() == 1 && conClassB.size() == 1) {
413440
boolean r = checkInterfereSingle(conClassA, conClassB);
414-
// System.out.println(" single=" + r);
441+
//System.out.println(" single=" + r);
415442
return r;
416443
}
417444

418445
boolean r2 = checkInterfere(conClassA, conClassB);
419-
// System.out.println(" both=" + r2);
446+
//System.out.println(" both=" + r2);
420447
if (r2) {
421448
return false;
422449
}
423450

424451
// merge congruence classes
425452
merge(conClassA, conClassB);
426-
// System.out.println("Exit COPY");
453+
//System.out.println("Exit COPY");
427454
return true;
428455
}
429456

@@ -570,21 +597,49 @@ private boolean dominates(Local a, Local b) {
570597
}
571598
}
572599

600+
/**
601+
* Purpose: The checkInterfere method determines if there is any interference
602+
* between two congruence classes, red and blue, in the context of SSA variable
603+
* coalescence.
604+
* <br/>
605+
* Process:
606+
* The method uses dominator tree traversal to compare elements from each class.
607+
* It maintains two stacks: one for the elements (dom) and one for their corresponding class (domClasses).
608+
* The method iterates through each class, comparing elements based on their dominance relationship.
609+
* If any pair of elements from different classes interfere, the method returns true.
610+
* Return Value: Returns true if there is interference between the two classes, otherwise false.
611+
*
612+
* Note: This method assumes that the CongruenceClass type and related methods like dominates, interference, and checkPreDomOrder are correctly implemented and available in the context.
613+
* @param red The first congruence class to check for interference.
614+
* @param blue The second congruence class to check for interference.
615+
* @return Returns true if there is interference between the two classes, otherwise false.
616+
*/
573617
private boolean checkInterfere(CongruenceClass red, CongruenceClass blue) {
574-
// System.out.println("Enter interfere: " + red + " vs " + blue);
575-
Stack<Local> dom = new Stack<>(); // dominator tree traversal stack
576-
Stack<Integer> domClasses = new Stack<>(); // 0=red, 1=blue
577-
int nr = 0, nb = 0; // from the paper
578-
Local ir = red.first(), ib = blue.first(); // iteration pointers
579-
Local lr = red.last(), lb = blue.last(); // end sentinels
618+
// Initialize stacks for dominator tree traversal and class tracking
619+
Stack<Local> dom = new Stack<>();
620+
Stack<Integer> domClasses = new Stack<>();
621+
622+
// Initialize counters for red and blue classes
623+
int nr = 0, nb = 0;
624+
625+
// Initialize iteration pointers and end sentinels for both classes
626+
Local ir = red.first(), ib = blue.first();
627+
Local lr = red.last(), lb = blue.last();
628+
629+
// Flags to track if there are more elements in each class
580630
boolean redHasNext = true, blueHasNext = true;
581-
equalAncOut.put(ir, null); // these have no parents so we have to manually init them
631+
632+
// Manually initialize for elements with no parents
633+
equalAncOut.put(ir, null);
582634
equalAncOut.put(ib, null);
635+
583636
do {
584637
// System.out.println("\n ir, ib, lr, lb: " + ir + " " + ib + " " + lr + " " + lb);
585638
// System.out.println(" dom: " + dom);
586639
Local current;
587640
int currentClass;
641+
642+
// Determine which class to process next based on pre-dominator order
588643
if (!blueHasNext || (redHasNext && checkPreDomOrder(ir, ib))) {
589644
// current = red[ir++] (Red case)
590645
current = ir;
@@ -601,6 +656,7 @@ private boolean checkInterfere(CongruenceClass red, CongruenceClass blue) {
601656
ib = blue.higher(ib);
602657
}
603658

659+
// Pop elements from stack that do not dominate the current element
604660
while (!dom.isEmpty() && !dominates(dom.peek(), current)) {
605661
if (domClasses.peek() == 0)
606662
nr--;
@@ -611,13 +667,20 @@ else if (domClasses.peek() == 1)
611667
dom.pop();
612668
domClasses.pop();
613669
}
670+
671+
// Check for interference
614672
if (!dom.isEmpty() && interference(current, dom.peek(), currentClass == domClasses.peek())) {
615673
return true;
616674
}
675+
676+
// Push current element and its class onto the stacks
617677
dom.push(current);
618678
domClasses.push(currentClass);
619-
} while ((redHasNext && nb > 0) || (blueHasNext && nr > 0) || (redHasNext && blueHasNext));
679+
}
680+
// Continue while there are elements in either class and unprocessed dominators in the stack
681+
while ((redHasNext && nb > 0) || (blueHasNext && nr > 0) || (redHasNext && blueHasNext));
620682

683+
// No interference detected
621684
return false;
622685
}
623686

org.mapleir.parent/org.mapleir.main/src/main/java/org/mapleir/Boot.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,8 @@ public static void main(String[] args) throws Exception {
141141

142142
BoissinotDestructor.leaveSSA(cfg);
143143

144+
145+
144146
// CFGUtils.easyDumpCFG(cfg, "pre-reaalloc");
145147
LocalsReallocator.realloc(cfg);
146148
// CFGUtils.easyDumpCFG(cfg, "post-reaalloc");

0 commit comments

Comments
 (0)