Skip to content

Commit a4df544

Browse files
committed
September Update
-Radon v2 antitamper transformer (credit to @Mysels) -Improved ZKM 8 transformers
1 parent d31a135 commit a4df544

16 files changed

+2937
-500
lines changed

src/main/java/com/javadeobfuscator/deobfuscator/executor/MethodExecutor.java

+4
Original file line numberDiff line numberDiff line change
@@ -1017,6 +1017,8 @@ private static <T> T execute(ClassNode classNode, MethodNode method, AbstractIns
10171017
break;
10181018
}
10191019
provided = fieldClass.fields.stream().filter(f -> f.name.equals(cast.name) && f.desc.equals(cast.desc)).findFirst().orElse(null).value;
1020+
if(type.getSort() == Type.BOOLEAN)
1021+
provided = (Integer)provided == 0 ? false : true;
10201022
context.provider.setField(cast.owner, cast.name, cast.desc, null, provided, context);
10211023
}
10221024

@@ -1097,6 +1099,8 @@ else if(obj instanceof JavaObject)
10971099
break;
10981100
}
10991101
provided = fieldClass.fields.stream().filter(f -> f.name.equals(cast.name) && f.desc.equals(cast.desc)).findFirst().orElse(null).value;
1102+
if(type.getSort() == Type.BOOLEAN)
1103+
provided = (Integer)provided == 0 ? false : true;
11001104
context.provider.setField(cast.owner, cast.name, cast.desc, obj, provided, context);
11011105
}
11021106

src/main/java/com/javadeobfuscator/deobfuscator/executor/defined/JVMMethodProvider.java

+29-9
Original file line numberDiff line numberDiff line change
@@ -146,17 +146,37 @@ public class JVMMethodProvider extends MethodProvider {
146146
}
147147
return null;
148148
});
149-
}});
150-
put("java/io/PushbackInputStream", new HashMap<String, Function3<JavaValue, List<JavaValue>, Context, Object>>() {{
151-
put("<init>(Ljava/io/InputStream;I)V", (targetObject, args, context) -> {
152-
targetObject.initialize(new PushbackInputStream(args.get(0).as(InputStream.class), args.get(1).intValue()));
149+
put("write([BII)V", (targetObject, args, context) -> {
150+
try {
151+
targetObject.as(ByteArrayOutputStream.class).write(args.get(0).as(byte[].class), args.get(1).intValue(), args.get(2).intValue());
152+
} catch (Exception e) {
153+
e.printStackTrace();
154+
}
153155
return null;
154156
});
155-
put("unread([BII)V", (targetObject, args, context) -> {
156-
targetObject.as(PushbackInputStream.class).unread(args.get(0).as(byte[].class), args.get(1).intValue(), args.get(2).intValue());
157-
return null;
158-
});
159-
put("read([BII)I", (targetObject, args, context) -> targetObject.as(PushbackInputStream.class).read(args.get(0).as(byte[].class), args.get(1).intValue(), args.get(2).intValue()));
157+
}});
158+
put("java/io/ByteArrayInputStream", new HashMap<String, Function3<JavaValue, List<JavaValue>, Context, Object>>() {{
159+
put("available()I", (targetObject, args, context) -> targetObject.as(ByteArrayInputStream.class).available());
160+
put("close()V", (targetObject, args, context) -> {
161+
try {
162+
targetObject.as(ByteArrayInputStream.class).close();
163+
} catch (IOException e) {
164+
e.printStackTrace();
165+
}
166+
return null;
167+
});
168+
put("read([B)I", (targetObject, args, context) -> targetObject.as(ByteArrayInputStream.class).read(args.get(0).as(byte[].class)));
169+
}});
170+
put("java/io/PushbackInputStream", new HashMap<String, Function3<JavaValue, List<JavaValue>, Context, Object>>() {{
171+
put("<init>(Ljava/io/InputStream;I)V", (targetObject, args, context) -> {
172+
targetObject.initialize(new PushbackInputStream(args.get(0).as(InputStream.class), args.get(1).intValue()));
173+
return null;
174+
});
175+
put("unread([BII)V", (targetObject, args, context) -> {
176+
targetObject.as(PushbackInputStream.class).unread(args.get(0).as(byte[].class), args.get(1).intValue(), args.get(2).intValue());
177+
return null;
178+
});
179+
put("read([BII)I", (targetObject, args, context) -> targetObject.as(PushbackInputStream.class).read(args.get(0).as(byte[].class), args.get(1).intValue(), args.get(2).intValue()));
160180
}});
161181
put("java/io/FilterInputStream", new HashMap<String, Function3<JavaValue, List<JavaValue>, Context, Object>>() {{
162182
put("<init>(Ljava/io/InputStream;)V", (targetObject, args, context) -> {

src/main/java/com/javadeobfuscator/deobfuscator/transformers/allatori/FlowObfuscationTransformer.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -1111,7 +1111,7 @@ else if(next instanceof LabelNode && hasJump(next, method))
11111111
}
11121112
System.out.println("[Allatori] [FlowObfuscationTransformer] Fixed " + fixed + " instructions");
11131113
System.out.println("[Allatori] [FlowObfuscationTransformer] Done");
1114-
return true;
1114+
return fixed.get() > 0;
11151115
}
11161116

11171117
private boolean hasJump(AbstractInsnNode ain, MethodNode method)

src/main/java/com/javadeobfuscator/deobfuscator/transformers/allatori/LightFlowObfuscationTransformer.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public boolean transform() throws Throwable {
5252
}
5353
System.out.println("[Allatori] [LightFlowObfuscationTransformer] Removed " + fixed + " dead instructions");
5454
System.out.println("[Allatori] [LightFlowObfuscationTransformer] Done");
55-
return true;
55+
return fixed.get() > 0;
5656
}
5757

5858
private boolean willPush(AbstractInsnNode ain)

src/main/java/com/javadeobfuscator/deobfuscator/transformers/skidsuite2/FakeExceptionTransformer.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,6 @@ else if(tc.handler.getNext().getOpcode() == Opcodes.ACONST_NULL
5050
System.out.println("[SkidSuite] [FakeExceptionTransformer] Removed "
5151
+ counter.get() + " fake try-catch blocks");
5252
System.out.println("[SkidSuite] [FakeExceptionTransformer] Done");
53-
return true;
53+
return counter.get() > 0;
5454
}
5555
}

src/main/java/com/javadeobfuscator/deobfuscator/transformers/skidsuite2/StringEncryptionTransformer.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,6 @@ public boolean transform() throws Throwable {
143143
});
144144

145145
System.out.println("[SkidSuite2] [StringEncryptionTransformer] Decrypted " + counter + " strings");
146-
return true;
146+
return counter.get() > 0;
147147
}
148148
}

src/main/java/com/javadeobfuscator/deobfuscator/transformers/smoke/NumberObfuscationTransformer.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ else if(entry.getKey() == a2)
124124
classNode.methods = classNode.methods.stream().filter(methodNode -> !numberMethods.containsKey(classNode.name + methodNode.name + methodNode.desc)).collect(Collectors.toList()));
125125

126126
System.out.println("[Smoke] [NumberObfuscationTransformer] Removed " + count.get() + " instructions");
127-
return true;
127+
return count.get() > 0;
128128
}
129129

130130
private Integer doMath(int value1, int value2, int opcode) {

src/main/java/com/javadeobfuscator/deobfuscator/transformers/smoke/StringEncryptionTransformer.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ public boolean transform() throws Throwable {
101101
System.out.println("[Smoke] [StringEncryptionTransformer] Decrypted " + count + " encrypted strings");
102102
System.out.println("[Smoke] [StringEncryptionTransformer] Removed " + cleanup(decryptor) + " decryption methods");
103103
System.out.println("[Smoke] [StringEncryptionTransformer] Done");
104-
return true;
104+
return count.get() > 0;
105105
}
106106

107107
private int cleanup(Set<MethodNode> methods)

src/main/java/com/javadeobfuscator/deobfuscator/transformers/special/RadonTransformerV2.java

+108-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
package com.javadeobfuscator.deobfuscator.transformers.special;
22

3+
import java.io.ByteArrayInputStream;
4+
import java.io.ByteArrayOutputStream;
5+
import java.io.IOException;
6+
import java.io.InputStream;
37
import java.lang.reflect.Modifier;
48
import java.util.*;
59
import java.util.Map.Entry;
610
import java.util.concurrent.atomic.AtomicInteger;
11+
import java.util.zip.ZipFile;
712

813
import org.assertj.core.internal.asm.Opcodes;
914
import org.objectweb.asm.Handle;
@@ -28,6 +33,7 @@
2833
import com.javadeobfuscator.deobfuscator.executor.defined.MappedFieldProvider;
2934
import com.javadeobfuscator.deobfuscator.executor.defined.MappedMethodProvider;
3035
import com.javadeobfuscator.deobfuscator.executor.defined.PrimitiveFieldProvider;
36+
import com.javadeobfuscator.deobfuscator.executor.defined.types.JavaClass;
3137
import com.javadeobfuscator.deobfuscator.executor.defined.types.JavaMethodHandle;
3238
import com.javadeobfuscator.deobfuscator.executor.providers.ComparisonProvider;
3339
import com.javadeobfuscator.deobfuscator.executor.providers.DelegatingProvider;
@@ -41,6 +47,7 @@
4147

4248
public class RadonTransformerV2 extends Transformer<TransformerConfig>
4349
{
50+
public static boolean ANTITAMPER = true;
4451
public static boolean EJECTOR = true;
4552
public static boolean ANTI_DEBUG = true;
4653
public static boolean FLOW_OBF = true;
@@ -110,6 +117,87 @@ public boolean canCheckEquality(JavaValue first, JavaValue second, Context conte
110117
AtomicInteger number = new AtomicInteger();
111118
AtomicInteger indy = new AtomicInteger();
112119
AtomicInteger str = new AtomicInteger();
120+
AtomicInteger antiTamper = new AtomicInteger();
121+
if(ANTITAMPER)
122+
{
123+
MethodNode atDecr = null;
124+
ClassNode atOwner = null;
125+
finder:
126+
for(ClassNode classNode : classNodes())
127+
if(classNode.methods.size() == 1)
128+
{
129+
MethodNode method = classNode.methods.get(0);
130+
if(!method.desc.equals("(Ljava/lang/String;)Ljava/lang/String;"))
131+
continue;
132+
Map<Integer, AtomicInteger> insnCount = new HashMap<>();
133+
Map<String, AtomicInteger> invokeCount = new HashMap<>();
134+
for(AbstractInsnNode i = method.instructions.getFirst(); i != null; i = i.getNext()) {
135+
int opcode = i.getOpcode();
136+
insnCount.putIfAbsent(opcode, new AtomicInteger(0));
137+
insnCount.get(opcode).getAndIncrement();
138+
if(i instanceof MethodInsnNode) {
139+
invokeCount.putIfAbsent(((MethodInsnNode) i).name, new AtomicInteger(0));
140+
invokeCount.get(((MethodInsnNode) i).name).getAndIncrement();
141+
}
142+
}
143+
if(insnCount.get(Opcodes.NEWARRAY) == null || insnCount.get(Opcodes.ISTORE) == null
144+
|| insnCount.get(Opcodes.BALOAD) == null || insnCount.get(Opcodes.IOR) == null
145+
|| invokeCount.get("toCharArray") == null || invokeCount.get("getResourceAsStream") == null
146+
|| invokeCount.get("getMethodName") == null)
147+
continue;
148+
atDecr = method;
149+
atOwner = classNode;
150+
break finder;
151+
}
152+
if(atDecr != null)
153+
{
154+
ZipFile zipIn = new ZipFile(getDeobfuscator().getConfig().getInput());
155+
for(AbstractInsnNode ain : atDecr.instructions.toArray())
156+
if (ain.getOpcode() == Opcodes.INVOKEVIRTUAL
157+
&& ((MethodInsnNode)ain).owner.equals("java/lang/Class")
158+
&& ((MethodInsnNode)ain).name.equals("getResourceAsStream")
159+
&& ((MethodInsnNode)ain).desc.equals("(Ljava/lang/String;)Ljava/io/InputStream;"))
160+
MethodExecutor.customMethodFunc.put(ain, (list, ctx) -> {
161+
try {
162+
String clazzName = list.remove(0).as(String.class);
163+
list.remove(0).as(JavaClass.class);
164+
clazzName = clazzName.substring(1);
165+
InputStream in = zipIn.getInputStream(zipIn.getEntry(clazzName));
166+
ByteArrayOutputStream baos = cloneInputStream(in);
167+
InputStream input = new ByteArrayInputStream(baos.toByteArray());
168+
return JavaValue.valueOf(input);
169+
} catch (IOException e) {
170+
e.printStackTrace();
171+
}
172+
return null;
173+
});
174+
for(ClassNode classNode : classNodes())
175+
for(MethodNode m : classNode.methods) {
176+
InstructionModifier modifier = new InstructionModifier();
177+
for(AbstractInsnNode ain : TransformerHelper.instructionIterator(m))
178+
if (ain instanceof MethodInsnNode) {
179+
MethodInsnNode insn = (MethodInsnNode)ain;
180+
if (insn.owner.equals(atOwner.name) && insn.name.equals(atDecr.name)
181+
&& insn.desc.equals(atDecr.desc)) {
182+
AbstractInsnNode ldc = ain.getPrevious();
183+
if (!(ldc instanceof LdcInsnNode) || !(((LdcInsnNode)ldc).cst instanceof String))
184+
continue;
185+
Context context = new Context(provider);
186+
context.push(classNode.name, m.name,
187+
getDeobfuscator().getConstantPool(classNode).getSize());
188+
context.dictionary = classpath;
189+
((LdcInsnNode)ldc).cst = MethodExecutor.execute(atOwner, atDecr,
190+
Arrays.asList(JavaValue.valueOf(((LdcInsnNode) ldc).cst)), null, context);
191+
modifier.remove(ain);
192+
antiTamper.getAndIncrement();
193+
}
194+
}
195+
modifier.apply(m);
196+
}
197+
}
198+
classes.remove(atOwner.name);
199+
classpath.remove(atOwner.name);
200+
}
113201
//Bad Annotations
114202
for(ClassNode classNode : classNodes())
115203
for(MethodNode method : classNode.methods)
@@ -187,7 +275,7 @@ public boolean canCheckEquality(JavaValue first, JavaValue second, Context conte
187275
}else if(last.getOpcode() == Opcodes.PUTFIELD)
188276
{
189277
if(list.size() != 3)
190-
throw new RuntimeException("Unexpected Ejector pattern (PS)");
278+
throw new RuntimeException("Unexpected Ejector pattern (PF)");
191279
AbstractInsnNode prev = list.get(1);
192280
method.instructions.remove(ain.getPrevious());//number
193281
method.instructions.insertBefore(ain, prev.clone(null));
@@ -1050,6 +1138,7 @@ && getNextFollowGoto(ain, 2) != null && getNextFollowGoto(ain, 2).getOpcode() ==
10501138
classes.remove(e.name);
10511139
classpath.remove(e.name);
10521140
});
1141+
System.out.println("[Special] [RadonTransformerV2] Decrypted " + antiTamper + " strings with anti-tamper");
10531142
System.out.println("[Special] [RadonTransformerV2] Unejected " + eject + " methods");
10541143
System.out.println("[Special] [RadonTransformerV2] Removed " + antiDebug + " anti-debug injections");
10551144
System.out.println("[Special] [RadonTransformerV2] Removed " + tryCatch + " try-catch blocks");
@@ -1460,4 +1549,22 @@ private AbstractInsnNode doMath(AbstractInsnNode value1, AbstractInsnNode value2
14601549
}
14611550
throw new RuntimeException();
14621551
}
1552+
1553+
private static ByteArrayOutputStream cloneInputStream(InputStream input)
1554+
{
1555+
try
1556+
{
1557+
ByteArrayOutputStream baos = new ByteArrayOutputStream();
1558+
byte[] buffer = new byte[1024];
1559+
int len;
1560+
while((len = input.read(buffer)) > -1)
1561+
baos.write(buffer, 0, len);
1562+
baos.flush();
1563+
return baos;
1564+
}catch(Exception e)
1565+
{
1566+
e.printStackTrace();
1567+
return null;
1568+
}
1569+
}
14631570
}

src/main/java/com/javadeobfuscator/deobfuscator/transformers/stringer/HideAccessObfuscationTransformer.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,7 @@ public boolean canCheckEquality(JavaValue first, JavaValue second, Context conte
436436
System.out.println("[Stringer] [HideAccessTransformer] Removed " + (int) cleanedup + " invokedynamic bootstrap methods");
437437

438438
System.out.println("[Stringer] [HideAccessTransformer] Done");
439-
return true;
439+
return count.get() > 0;
440440
}
441441

442442
private void castFix(Context context) {

src/main/java/com/javadeobfuscator/deobfuscator/transformers/stringer/InvokedynamicTransformer.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -51,18 +51,19 @@ public boolean transform() {
5151
System.out.println("[Stringer] [InvokedynamicTransformer] Finding invokedynamic instructions");
5252
int amount = findInvokeDynamic();
5353
System.out.println("[Stringer] [InvokedynamicTransformer] Found " + amount + " invokedynamic instructions");
54+
int inlined = 0;
5455
if (amount > 0) {
5556
System.out.println("[Stringer] [InvokedynamicTransformer] Inlining invokedynamic");
5657
long start = System.currentTimeMillis();
57-
int inlined = inlineInvokeDynamic(amount);
58+
inlined = inlineInvokeDynamic(amount);
5859
long end = System.currentTimeMillis();
5960
System.out.println("[Stringer] [InvokedynamicTransformer] Removed " + inlined + " invokedynamic instructions, took " + TimeUnit.MILLISECONDS.toSeconds(end - start) + "s");
6061
System.out.println("[Stringer] [InvokedynamicTransformer] Cleaning up bootstrap methods");
6162
int cleanedup = cleanup();
6263
System.out.println("[Stringer] [InvokedynamicTransformer] Removed " + cleanedup + " bootstrap methods");
6364
}
6465
System.out.println("[Stringer] [InvokedynamicTransformer] Done");
65-
return true;
66+
return inlined > 0;
6667
}
6768

6869
private int findInvokeDynamic() {

src/main/java/com/javadeobfuscator/deobfuscator/transformers/stringer/ReflectionObfuscationTransformer.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -53,14 +53,15 @@ public boolean transform() {
5353
System.out.println("[Stringer] [ReflectionObfuscationTransformer] Starting");
5454
int count = count();
5555
System.out.println("[Stringer] [ReflectionObfuscationTransformer] Found " + count + " reflection obfuscation calls");
56+
int decrypted = 0;
5657
if (count > 0) {
57-
int decrypted = decrypt(count);
58+
decrypted = decrypt(count);
5859
System.out.println("[Stringer] [ReflectionObfuscationTransformer] Deobfuscated " + decrypted + " reflection obfuscation calls");
5960
int cleanedup = cleanup();
6061
System.out.println("[Stringer] [ReflectionObfuscationTransformer] Removed " + cleanedup + " reflection obfuscation classes");
6162
}
6263
System.out.println("[Stringer] [ReflectionObfuscationTransformer] Done");
63-
return true;
64+
return decrypted > 0;
6465
}
6566

6667
private int count() {

src/main/java/com/javadeobfuscator/deobfuscator/transformers/stringer/ResourceEncryptionTransformer.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ public boolean transform() {
5959
int processed = process();
6060
System.out.println("[Stringer] [ResourceEncryptionTransformer] Processed " + processed + " resources");
6161
System.out.println("[Stringer] [ResourceEncryptionTransformer] Done");
62-
return true;
62+
return processed > 0;
6363
}
6464

6565
private int process() {

src/main/java/com/javadeobfuscator/deobfuscator/transformers/stringer/StringEncryptionTransformer.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -100,14 +100,15 @@ public boolean transform() {
100100
System.out.println("[Stringer] [StringEncryptionTransformer] Concatted " + concat + " strings");
101101
int count = count();
102102
System.out.println("[Stringer] [StringEncryptionTransformer] Found " + count + " encrypted strings");
103+
int decrypted = 0;
103104
if (count > 0) {
104-
int decrypted = decrypt(count);
105+
decrypted = decrypt(count);
105106
System.out.println("[Stringer] [StringEncryptionTransformer] Decrypted " + decrypted + " encrypted strings");
106107
int cleanedup = cleanup();
107108
System.out.println("[Stringer] [StringEncryptionTransformer] Removed " + cleanedup + " decryption classes");
108109
}
109110
System.out.println("[Stringer] [StringEncryptionTransformer] Done");
110-
return true;
111+
return decrypted > 0;
111112
}
112113

113114
private int concatStrings()

0 commit comments

Comments
 (0)