Skip to content

Commit 9cd8a40

Browse files
committed
Added string encryption merry christmas
1 parent 545ef17 commit 9cd8a40

File tree

15 files changed

+475
-5
lines changed

15 files changed

+475
-5
lines changed

dev.skidfuscator.obfuscator/src/main/java/dev/skidfuscator/obf/SkidMethodRenderer.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import dev.skidfuscator.obf.transform.impl.flow.*;
1212
import dev.skidfuscator.obf.transform.impl.kappa.AhegaoPass;
1313
import dev.skidfuscator.obf.transform.impl.kappa.SuperDuperAgentPass;
14+
import dev.skidfuscator.obf.transform.impl.string.SimpleXorCipher;
1415
import dev.skidfuscator.obf.utils.ProgressUtil;
1516
import dev.skidfuscator.obf.utils.TimedLogger;
1617
import dev.skidfuscator.obf.yggdrasil.caller.CallerType;
@@ -184,6 +185,7 @@ public void render(final SkidSession skidSession) {
184185
new FakeExceptionJumpFlowPass(),
185186
new FakeJumpFlowPass(),
186187
new SeedFlowPass(),
188+
new SimpleXorCipher()
187189
};
188190

189191
final FlowPass[] fixers = new FlowPass[]{
@@ -245,7 +247,7 @@ public void render(final SkidSession skidSession) {
245247

246248
logger.log("[*] Linearizing GEN3...");
247249

248-
skidMethods.parallelStream().forEach(e -> e.renderPublic(skidSession));
250+
skidMethods.forEach(e -> e.renderPublic(skidSession));
249251
logger.log("[*] Finished Gen3 flow obfuscation");
250252

251253
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package dev.skidfuscator.obf.attribute;
2+
3+
public interface Attributable {
4+
<T> Attribute<T> getAttribute(final AttributeKey attributeKey);
5+
<T> void addAttribute(final AttributeKey key, final Attribute<T> attribute);
6+
<T> void removeAttribute(final AttributeKey attributeKey);
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package dev.skidfuscator.obf.attribute;
2+
3+
public interface Attribute<T> {
4+
T getBase();
5+
6+
void set(final T t);
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package dev.skidfuscator.obf.attribute;
2+
3+
import lombok.Data;
4+
5+
import java.util.UUID;
6+
7+
/**
8+
* @author Ghast
9+
* @since 12/02/2021
10+
* Skidfuscator © 2021
11+
*/
12+
13+
@Data
14+
public class AttributeKey {
15+
private final String name;
16+
private final UUID uuid;
17+
18+
public AttributeKey(final String name) {
19+
this(name, UUID.randomUUID());
20+
}
21+
22+
public AttributeKey(final String name, final UUID uuid) {
23+
this.name = name;
24+
this.uuid = uuid;
25+
}
26+
27+
@Override
28+
public boolean equals(final Object o) {
29+
if (this == o) return true;
30+
if (o == null || getClass() != o.getClass()) return false;
31+
32+
final AttributeKey that = (AttributeKey) o;
33+
34+
if (!name.equals(that.name)) return false;
35+
return uuid.equals(that.uuid);
36+
}
37+
38+
@Override
39+
public int hashCode() {
40+
int result = name.hashCode();
41+
result = 31 * result + uuid.hashCode();
42+
return result;
43+
}
44+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package dev.skidfuscator.obf.attribute;
2+
3+
import java.util.HashMap;
4+
import java.util.Map;
5+
6+
public class AttributeMap extends HashMap<AttributeKey, Attribute<Object>> {
7+
public AttributeMap(final Map<? extends AttributeKey, ? extends Attribute<Object>> m) {
8+
super(m);
9+
}
10+
11+
public AttributeMap() {
12+
}
13+
14+
public <T> T poll(final Object key) {
15+
final Object o = super.get(key);
16+
return o == null ? null : (T) ((StandardAttribute) o).getBase();
17+
}
18+
19+
public AttributeMap copy() {
20+
final AttributeMap map = new AttributeMap();
21+
22+
this.forEach((key, value) -> map.put(key, new StandardAttribute<>(value.getBase())));
23+
24+
return map;
25+
}
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package dev.skidfuscator.obf.attribute;
2+
3+
/**
4+
* @author Ghast
5+
* @since 12/02/2021
6+
* Artemis © 2021
7+
*/
8+
public class StandardAttribute<T> implements Attribute<T> {
9+
private T t;
10+
11+
public StandardAttribute(final T t) {
12+
this.t = t;
13+
}
14+
15+
@Override
16+
public T getBase() {
17+
return t;
18+
}
19+
20+
@Override
21+
public void set(final T t) {
22+
this.t = t;
23+
}
24+
}

dev.skidfuscator.obfuscator/src/main/java/dev/skidfuscator/obf/skidasm/SkidGraph.java

+21-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
package dev.skidfuscator.obf.skidasm;
22

3+
import dev.skidfuscator.obf.attribute.Attributable;
4+
import dev.skidfuscator.obf.attribute.Attribute;
5+
import dev.skidfuscator.obf.attribute.AttributeKey;
6+
import dev.skidfuscator.obf.attribute.AttributeMap;
37
import dev.skidfuscator.obf.maple.FakeBlock;
48
import dev.skidfuscator.obf.maple.FakeConditionalJumpEdge;
59
import dev.skidfuscator.obf.maple.FakeConditionalJumpStmt;
@@ -31,7 +35,7 @@
3135
import java.util.*;
3236
import java.util.stream.Collectors;
3337

34-
public class SkidGraph {
38+
public class SkidGraph implements Attributable {
3539
@Getter
3640
private final MethodNode node;
3741
private final SkidMethod method;
@@ -40,6 +44,7 @@ public class SkidGraph {
4044
@Getter
4145
private Local local;
4246
private final Map<BasicBlock, SkidBlock> cache = new HashMap<>();
47+
private final AttributeMap attributeMap = new AttributeMap();
4348

4449
public static final boolean DEBUG = false;
4550

@@ -462,4 +467,19 @@ public void cache(final BasicBlock basicBlock) {
462467
public boolean isInit() {
463468
return node.node.name.equals("<init>");
464469
}
470+
471+
@Override
472+
public <T> Attribute<T> getAttribute(AttributeKey attributeKey) {
473+
return (Attribute<T>) attributeMap.get(attributeKey);
474+
}
475+
476+
@Override
477+
public <T> void addAttribute(AttributeKey key, Attribute<T> attribute) {
478+
attributeMap.put(key, (Attribute<Object>) attribute);
479+
}
480+
481+
@Override
482+
public <T> void removeAttribute(AttributeKey attributeKey) {
483+
attributeMap.remove(attributeKey);
484+
}
465485
}
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
package dev.skidfuscator.obf.transform;
22

33
public @interface Transformer {
4-
String name();
4+
String value();
55
}

dev.skidfuscator.obfuscator/src/main/java/dev/skidfuscator/obf/transform/impl/flow/gen3/FakeExceptionFlowPass.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import dev.skidfuscator.obf.maple.FakeConditionalJumpStmt;
55
import dev.skidfuscator.obf.skidasm.SkidGraph;
66
import dev.skidfuscator.obf.skidasm.SkidMethod;
7+
import dev.skidfuscator.obf.transform.Transformer;
78
import dev.skidfuscator.obf.transform.impl.flow.FlowPass;
89
import dev.skidfuscator.obf.transform.type.SkidGraphTransformer;
910
import dev.skidfuscator.obf.utils.Blocks;
@@ -34,6 +35,8 @@
3435
* >> Space complexity (n = number of blocks)
3536
* C = O(1)
3637
*/
38+
39+
@Transformer("Fake Exception [Simple]")
3740
public class FakeExceptionFlowPass implements SkidGraphTransformer {
3841

3942
@Override
@@ -53,7 +56,7 @@ public void run(SkidSession skidSession, SkidGraph graph) {
5356
final ConstantExpr var_const = new ConstantExpr(graph.getBlock(entry).getSeed());
5457

5558
// Todo add more boilerplates + add exception rotation
56-
final BasicBlock fuckup = Blocks.exception(cfg);
59+
final BasicBlock fuckup = Blocks.exception(cfg, "ay");
5760

5861
// Todo change blocks to be skiddedblocks to add method to directly add these
5962
final FakeConditionalJumpStmt jump_stmt = new FakeConditionalJumpStmt(var_load, var_const, fuckup, ConditionalJumpStmt.ComparisonType.NE);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
package dev.skidfuscator.obf.transform.impl.string;
2+
3+
import dev.skidfuscator.obf.attribute.AttributeKey;
4+
import dev.skidfuscator.obf.init.SkidSession;
5+
import dev.skidfuscator.obf.skidasm.SkidBlock;
6+
import dev.skidfuscator.obf.skidasm.SkidGraph;
7+
import dev.skidfuscator.obf.skidasm.SkidMethod;
8+
import dev.skidfuscator.obf.transform.impl.flow.FlowPass;
9+
import dev.skidfuscator.obf.utils.MiscUtils;
10+
import dev.skidfuscator.obf.utils.generate.XorEncryption;
11+
import org.mapleir.asm.ClassNode;
12+
import org.mapleir.ir.cfg.BasicBlock;
13+
import org.mapleir.ir.cfg.ControlFlowGraph;
14+
import org.mapleir.ir.code.CodeUnit;
15+
import org.mapleir.ir.code.Expr;
16+
import org.mapleir.ir.code.expr.ConstantExpr;
17+
import org.mapleir.ir.code.expr.VarExpr;
18+
import org.mapleir.ir.code.expr.invoke.DynamicInvocationExpr;
19+
import org.mapleir.ir.code.expr.invoke.InitialisedObjectExpr;
20+
import org.mapleir.ir.code.expr.invoke.InvocationExpr;
21+
import org.mapleir.ir.code.expr.invoke.StaticInvocationExpr;
22+
import org.mapleir.ir.locals.Local;
23+
import org.objectweb.asm.Type;
24+
25+
import java.util.HashSet;
26+
import java.util.List;
27+
import java.util.Set;
28+
import java.util.stream.Collectors;
29+
30+
/**
31+
* Xor cipher, a cipher so bad it hurts my eyes out because a simple bruteforce attack could
32+
* reverse engineer this...
33+
*
34+
* Buuuuuuut....
35+
*
36+
* Yes
37+
*
38+
* Kappa
39+
*
40+
* The basic concept of the cipher is we take the digit value of a character, xor it, and tada.
41+
* Yep. Tada.
42+
*
43+
* Yes.
44+
*/
45+
public class SimpleXorCipher implements FlowPass {
46+
private static final Type STRING_TYPE = Type.getType(String.class);
47+
48+
private static final Set<ClassNode> INJECTED = new HashSet<>();
49+
50+
@Override
51+
public void pass(SkidSession session, SkidMethod method) {
52+
for (SkidGraph methodNode : method.getMethodNodes()) {
53+
if (methodNode.getNode().isAbstract() || methodNode.isInit())
54+
continue;
55+
56+
final ControlFlowGraph cfg = session.getCxt().getIRCache().get(methodNode.getNode());
57+
58+
if (cfg == null)
59+
continue;
60+
61+
final List<ConstantExpr> stringList = cfg.allExprStream()
62+
.filter(e -> e instanceof ConstantExpr)
63+
.map(e -> (ConstantExpr) e)
64+
.filter(e -> e.getConstant() instanceof String)
65+
.collect(Collectors.toList());
66+
67+
if (stringList.isEmpty())
68+
continue;
69+
70+
final ClassNode parent = methodNode.getNode().owner;
71+
72+
if (!INJECTED.contains(parent)) {
73+
XorEncryption.visit(parent.node);
74+
INJECTED.add(parent);
75+
}
76+
77+
for (ConstantExpr constantExpr : stringList) {
78+
final CodeUnit parentExpr = constantExpr.getParent();
79+
80+
if (parentExpr instanceof DynamicInvocationExpr || parentExpr instanceof InitialisedObjectExpr)
81+
continue;
82+
83+
final BasicBlock block = constantExpr.getBlock();
84+
final SkidBlock skidBlock = methodNode.getBlock(block);
85+
final Local local = methodNode.getLocal();
86+
87+
final String encrypted = XorEncryption.factor((String) constantExpr.getConstant(), skidBlock.getSeed());
88+
final Expr constant_load = new ConstantExpr(encrypted, STRING_TYPE);
89+
final Expr local_load = new VarExpr(local, Type.INT_TYPE);
90+
91+
final Expr invocation = new StaticInvocationExpr(
92+
new Expr[]{constant_load, local_load},
93+
parent.node.name,
94+
XorEncryption.NAME,
95+
"(Ljava/lang/String;I)Ljava/lang/String;"
96+
);
97+
98+
session.count();
99+
100+
if (parentExpr instanceof InvocationExpr) {
101+
final InvocationExpr invocationExpr = ((InvocationExpr) parentExpr);
102+
final int index = MiscUtils.indexOf(invocationExpr.getArgumentExprs(), constantExpr);
103+
//constantExpr.unlink();
104+
invocationExpr.getArgumentExprs()[index] = invocation;
105+
} else {
106+
final int index = parentExpr.indexOf(constantExpr);
107+
parentExpr.writeAt(invocation, index);
108+
}
109+
110+
111+
}
112+
113+
114+
}
115+
}
116+
117+
@Override
118+
public String getName() {
119+
return "Xor String Encryption";
120+
}
121+
}

0 commit comments

Comments
 (0)