Skip to content

Commit 8524532

Browse files
committed
Handle special case where we cannot determine if it is INVOKEVIRTUAL or INVOKEINTERFACE
1 parent acb5711 commit 8524532

File tree

2 files changed

+28
-2
lines changed

2 files changed

+28
-2
lines changed

deobfuscator-api/src/main/java/uwu/narumi/deobfuscator/api/context/Context.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
import uwu.narumi.deobfuscator.api.asm.ClassWrapper;
1414
import uwu.narumi.deobfuscator.api.classpath.ClassProvider;
1515
import uwu.narumi.deobfuscator.api.classpath.ClassInfoStorage;
16+
import uwu.narumi.deobfuscator.api.classpath.CombinedClassProvider;
17+
import uwu.narumi.deobfuscator.api.classpath.JvmClassProvider;
1618
import uwu.narumi.deobfuscator.api.execution.SandBox;
1719
import uwu.narumi.deobfuscator.api.helper.ClassHelper;
1820

@@ -136,4 +138,11 @@ public Map<String, ClassWrapper> getClassesMap() {
136138
public Map<String, byte[]> getFilesMap() {
137139
return filesMap;
138140
}
141+
142+
/**
143+
* Gets the class provider that holds all classes in the context, including the jvm runtime.
144+
*/
145+
public ClassProvider getFullClassProvider() {
146+
return new CombinedClassProvider(this, this.getLibraries(), JvmClassProvider.INSTANCE);
147+
}
139148
}

deobfuscator-transformers/src/main/java/uwu/narumi/deobfuscator/core/other/impl/qprotect/qProtectInvokeDynamicTransformer.java

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import org.objectweb.asm.Opcodes;
44
import org.objectweb.asm.tree.AbstractInsnNode;
5+
import org.objectweb.asm.tree.ClassNode;
56
import org.objectweb.asm.tree.InvokeDynamicInsnNode;
67
import org.objectweb.asm.tree.LdcInsnNode;
78
import org.objectweb.asm.tree.LookupSwitchInsnNode;
@@ -42,6 +43,8 @@ protected void transform() throws Exception {
4243
// Decrypt the method invocation
4344
AbstractInsnNode decryptedInsn = decryptMethodInvocation(xorKey, encryptedData, decryptionInfo);
4445
methodNode.instructions.set(invokeDynamicInsn, decryptedInsn);
46+
47+
markChange();
4548
}
4649
}
4750
});
@@ -95,7 +98,7 @@ private DecryptionInfo extractDecryptionInformation(InvokeDynamicInsnNode invoke
9598
* @param decryptionInfo Decryption information
9699
* @return Decrypted method invocation instruction
97100
*/
98-
private static AbstractInsnNode decryptMethodInvocation(String xorKey, String encryptedData, DecryptionInfo decryptionInfo) {
101+
private AbstractInsnNode decryptMethodInvocation(String xorKey, String encryptedData, DecryptionInfo decryptionInfo) {
99102
char[] xorKeyArr = xorKey.toCharArray();
100103

101104
// Decrypt the data using XOR cipher
@@ -133,7 +136,21 @@ private static AbstractInsnNode decryptMethodInvocation(String xorKey, String en
133136
}
134137

135138
int opcode = decryptionInfo.invocationTypes().get(methodType);
136-
return new MethodInsnNode(opcode, opcode == INVOKESPECIAL ? specialClass : ownerClass, methodName, methodDesc, false);
139+
140+
// Handle special case where we cannot determine if it is INVOKEVIRTUAL or INVOKEINTERFACE
141+
if (opcode == INVOKEVIRTUAL) {
142+
ClassNode classInfo = context().getFullClassProvider().getClassInfo(ownerClass);
143+
if (classInfo != null) {
144+
// Check if class is an interface
145+
if (isAccess(classInfo.access, ACC_INTERFACE)) {
146+
opcode = INVOKEINTERFACE;
147+
}
148+
} else {
149+
LOGGER.warn("Could not find class {} for class/interface type detection. If you want a runnable jar then add the required lib.", ownerClass);
150+
}
151+
}
152+
153+
return new MethodInsnNode(opcode, opcode == INVOKESPECIAL ? specialClass : ownerClass, methodName, methodDesc, opcode == INVOKEINTERFACE);
137154
}
138155

139156
/**

0 commit comments

Comments
 (0)