Skip to content

Commit

Permalink
use findAllMatches wherever was possible
Browse files Browse the repository at this point in the history
  • Loading branch information
EpicPlayerA10 committed Sep 25, 2024
1 parent 92777a8 commit 5bf228d
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 76 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -147,68 +147,63 @@ private void decryptEncryptedLongs(Context context, ClassWrapper classWrapper) {

MethodContext methodContext = MethodContext.framed(classWrapper, clinit);

for (AbstractInsnNode insn : clinit.instructions) {
InsnContext insnContext = methodContext.newInsnContext(insn);
if (insnContext.frame() == null) return;

MatchContext result = DECRYPT_LONG_MATCHER.matchResult(insnContext);
if (result != null) {
// Get instructions from storage
MethodInsnNode createDecrypterInsn = (MethodInsnNode) result.captures().get("create-decrypter-method").insn();
MatchContext decryptContext = result.captures().get("decrypt-method");
MethodInsnNode decryptInsn = (MethodInsnNode) decryptContext.insn();

// Some keys
long key1 = result.captures().get("key-1").insn().asLong();
long key2 = result.captures().get("key-2").insn().asLong();
long decryptKey = result.captures().get("decrypt-key").insn().asLong();
// Find all encrypted longs
DECRYPT_LONG_MATCHER.findAllMatches(methodContext).forEach(matchContext -> {
// Get instructions from storage
MethodInsnNode createDecrypterInsn = (MethodInsnNode) matchContext.captures().get("create-decrypter-method").insn();
MatchContext decryptContext = matchContext.captures().get("decrypt-method");
MethodInsnNode decryptInsn = (MethodInsnNode) decryptContext.insn();

// Some keys
long key1 = matchContext.captures().get("key-1").insn().asLong();
long key2 = matchContext.captures().get("key-2").insn().asLong();
long decryptKey = matchContext.captures().get("decrypt-key").insn().asLong();

ClassWrapper longDecrypterCreatorClass = context.getClasses().get(createDecrypterInsn.owner);

try {
// Create decrypter
InstanceClass clazz = sandBox.getHelper().loadClass(longDecrypterCreatorClass.canonicalName());
ObjectValue longDecrypterInstance = sandBox.getInvocationUtil().invokeReference(
clazz.getMethod(createDecrypterInsn.name, createDecrypterInsn.desc),
Argument.int64(key1), // Key 1
Argument.int64(key2), // Key 2
Argument.reference(sandBox.getMemoryManager().nullValue()) // Lookup class
);
InstanceClass longDecrypterClass = (InstanceClass) sandBox.getMemoryManager().readClass(longDecrypterInstance);

ClassWrapper longDecrypterCreatorClass = context.getClasses().get(createDecrypterInsn.owner);
//String instanceStringified = sandBox.vm().getOperations().toString(longDecrypterInstance);
//System.out.println(classWrapper.name() + " -> " + instanceStringified);

try {
// Create decrypter
InstanceClass clazz = sandBox.getHelper().loadClass(longDecrypterCreatorClass.canonicalName());
ObjectValue longDecrypterInstance = sandBox.getInvocationUtil().invokeReference(
clazz.getMethod(createDecrypterInsn.name, createDecrypterInsn.desc),
Argument.int64(key1), // Key 1
Argument.int64(key2), // Key 2
Argument.reference(sandBox.getMemoryManager().nullValue()) // Lookup class
);
InstanceClass longDecrypterClass = (InstanceClass) sandBox.getMemoryManager().readClass(longDecrypterInstance);

//String instanceStringified = sandBox.vm().getOperations().toString(longDecrypterInstance);
//System.out.println(classWrapper.name() + " -> " + instanceStringified);

if (isFallbackDecrypter(longDecrypterClass)) {
LOGGER.error("Detected that '{}' class is decrypted out of order. Decrypted number will have wrong value.", classWrapper.name());
LOGGER.error("The author used 'classInitializationOrderStatement' (https://www.zelix.com/klassmaster/docs/classInitializationOrderStatement.html) " +
"during jar obfuscation to specify class initialization order manually. " +
"You need to pass to ZelixLongEncryptionMPCTransformer a class initialization order. The easiest way wille be doing a static analysis " +
"and find where the mentioned class is used."
);
}

// Decrypt long value
long value = sandBox.getInvocationUtil().invokeLong(
longDecrypterClass.getMethod(decryptInsn.name, decryptInsn.desc),
Argument.reference(longDecrypterInstance),
Argument.int64(decryptKey)
if (isFallbackDecrypter(longDecrypterClass)) {
LOGGER.error("Detected that '{}' class is decrypted out of order. Decrypted number will have wrong value.", classWrapper.name());
LOGGER.error("The author used 'classInitializationOrderStatement' (https://www.zelix.com/klassmaster/docs/classInitializationOrderStatement.html) " +
"during jar obfuscation to specify class initialization order manually. " +
"You need to pass to ZelixLongEncryptionMPCTransformer a class initialization order. The easiest way wille be doing a static analysis " +
"and find where the mentioned class is used."
);

// Remove all instructions that creates decrypter
decryptContext.removeAll();

// Set field to decrypted long value!
insnContext.methodNode().instructions.insertBefore(insnContext.insn(), AsmHelper.numberInsn(value));
markChange();
} catch (VMException ex) {
sandBox.logVMException(ex);
throw new RuntimeException(ex);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}

// Decrypt long value
long value = sandBox.getInvocationUtil().invokeLong(
longDecrypterClass.getMethod(decryptInsn.name, decryptInsn.desc),
Argument.reference(longDecrypterInstance),
Argument.int64(decryptKey)
);

// Remove all instructions that create decrypter
decryptContext.removeAll();

// Set field to decrypted long value!
matchContext.insnContext().methodNode().instructions.insertBefore(matchContext.insn(), AsmHelper.numberInsn(value));
markChange();
} catch (VMException ex) {
sandBox.logVMException(ex);
throw new RuntimeException(ex);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
});

processedClasses.add(classWrapper.name());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
* Decomposes object array param ({@code foo(Object[] args)}) into a readable params like: {@code foo(String arg1, int arg2)}.
Expand Down Expand Up @@ -122,12 +123,7 @@ private List<Type> decomposeObjectArrayToTypes(MethodContext methodContext, Map<
int nextVarIndex = MethodHelper.getFirstParameterIdx(methodContext.methodNode());

// Find all casts from that Object array
for (AbstractInsnNode insn : methodContext.methodNode().instructions.toArray()) {
InsnContext insnContext = methodContext.newInsnContext(insn);

MatchContext matchContext = OBJECT_ARRAY_VAR_USAGE.matchResult(insnContext);
if (matchContext == null) continue;

for (MatchContext matchContext : OBJECT_ARRAY_VAR_USAGE.findAllMatches(methodContext)) {
// Found argument!
VarInsnNode varStore = (VarInsnNode) matchContext.captures().get("var-store").insn();
TypeInsnNode typeInsn = (TypeInsnNode) matchContext.captures().get("cast").insn();
Expand Down Expand Up @@ -169,22 +165,17 @@ private List<Type> decomposeObjectArrayToTypes(MethodContext methodContext, Map<
*/
private boolean removeObjectArrayAccess(MethodContext methodContext) {
// Remove all object array accesses
for (AbstractInsnNode insn : methodContext.methodNode().instructions.toArray()) {
InsnContext insnContext = methodContext.newInsnContext(insn);

MatchContext matchContext = OBJECT_ARRAY_POP.matchResult(insnContext);
if (matchContext == null) continue;
Optional<MatchContext> optMatch = OBJECT_ARRAY_POP.findAllMatches(methodContext).stream().findFirst();
if (optMatch.isEmpty()) return false;
MatchContext matchContext = optMatch.get();

AbstractInsnNode loadArrayInsn = matchContext.captures().get("load-array").insn();
AbstractInsnNode loadArrayInsn = matchContext.captures().get("load-array").insn();

// Remove those instructions
methodContext.methodNode().instructions.remove(loadArrayInsn); // ALOAD
methodContext.methodNode().instructions.remove(insn); // POP

return true;
}
// Remove those instructions
methodContext.methodNode().instructions.remove(loadArrayInsn); // ALOAD
methodContext.methodNode().instructions.remove(matchContext.insn()); // POP

return false;
return true;
}

/**
Expand Down

0 comments on commit 5bf228d

Please sign in to comment.