From 04a9b4f0ff3699d1ec12f55d5267adb24d6ef40a Mon Sep 17 00:00:00 2001 From: Dawid Date: Fri, 13 Mar 2026 14:02:40 +0100 Subject: [PATCH 1/7] qProtect Strong String Transformer --- .../Composed_qProtectTransformer.java | 48 +++-- .../qProtectStrongStringTransformer.java | 181 ++++++++++++++++++ .../pool/UniversalNumberPoolTransformer.java | 34 ++-- 3 files changed, 233 insertions(+), 30 deletions(-) create mode 100644 deobfuscator-transformers/src/main/java/uwu/narumi/deobfuscator/core/other/impl/qprotect/qProtectStrongStringTransformer.java diff --git a/deobfuscator-transformers/src/main/java/uwu/narumi/deobfuscator/core/other/composed/Composed_qProtectTransformer.java b/deobfuscator-transformers/src/main/java/uwu/narumi/deobfuscator/core/other/composed/Composed_qProtectTransformer.java index e21783fe..96256df4 100644 --- a/deobfuscator-transformers/src/main/java/uwu/narumi/deobfuscator/core/other/composed/Composed_qProtectTransformer.java +++ b/deobfuscator-transformers/src/main/java/uwu/narumi/deobfuscator/core/other/composed/Composed_qProtectTransformer.java @@ -1,22 +1,15 @@ package uwu.narumi.deobfuscator.core.other.composed; import uwu.narumi.deobfuscator.api.transformer.ComposedTransformer; +import uwu.narumi.deobfuscator.core.other.composed.general.ComposedGeneralFlowTransformer; import uwu.narumi.deobfuscator.core.other.composed.general.ComposedPeepholeCleanTransformer; import uwu.narumi.deobfuscator.core.other.impl.clean.LocalVariableNamesCleanTransformer; import uwu.narumi.deobfuscator.core.other.impl.pool.InlineLocalVariablesTransformer; import uwu.narumi.deobfuscator.core.other.impl.pool.InlineStaticFieldTransformer; -import uwu.narumi.deobfuscator.core.other.impl.qprotect.qProtectAESStringEncryptionTransformer; -import uwu.narumi.deobfuscator.core.other.impl.qprotect.qProtectFieldFlowTransformer; -import uwu.narumi.deobfuscator.core.other.impl.qprotect.qProtectInvokeDynamicStrongTransformer; -import uwu.narumi.deobfuscator.core.other.impl.universal.SourceFileNameRecoverTransformer; +import uwu.narumi.deobfuscator.core.other.impl.qprotect.*; +import uwu.narumi.deobfuscator.core.other.impl.universal.*; import uwu.narumi.deobfuscator.core.other.impl.universal.pool.UniversalStringPoolTransformer; -import uwu.narumi.deobfuscator.core.other.impl.qprotect.qProtectStringTransformer; -import uwu.narumi.deobfuscator.core.other.impl.qprotect.qProtectTryCatchTransformer; -import uwu.narumi.deobfuscator.core.other.impl.qprotect.qProtectInvokeDynamicTransformer; import uwu.narumi.deobfuscator.core.other.impl.universal.pool.UniversalNumberPoolTransformer; -import uwu.narumi.deobfuscator.core.other.impl.universal.TryCatchRepairTransformer; -import uwu.narumi.deobfuscator.core.other.impl.universal.UniversalFlowTransformer; -import uwu.narumi.deobfuscator.core.other.impl.universal.UniversalNumberTransformer; /** * https://qtechnologies.dev/ @@ -24,6 +17,10 @@ // TODO: Deobfuscate strong string encryption. Sample: qprotect.StringStrongEncryption public class Composed_qProtectTransformer extends ComposedTransformer { public Composed_qProtectTransformer() { + super(false); + } + + public Composed_qProtectTransformer(boolean strongStrings) { super( // This fixes some weird issues where "this" is used as a local variable name. LocalVariableNamesCleanTransformer::new, @@ -33,7 +30,7 @@ public Composed_qProtectTransformer() { InlineStaticFieldTransformer::new, InlineLocalVariablesTransformer::new, - // Inline number pools + // Inline number pools, but keep byte arrays for StrongStringEncryption UniversalNumberPoolTransformer::new, // Decrypt method invocation qProtectInvokeDynamicTransformer::new, @@ -42,11 +39,16 @@ public Composed_qProtectTransformer() { // Fix flow UniversalFlowTransformer::new, - // Decrypt strings - qProtectStringTransformer::new, - qProtectAESStringEncryptionTransformer::new, - // Inline string pools - UniversalStringPoolTransformer::new, + !strongStrings ? () -> new ComposedTransformer(false, + // Strings + qProtectStringTransformer::new, + qProtectAESStringEncryptionTransformer::new, + StringBuilderTransformer::new, + + // Inline string pools + UniversalStringPoolTransformer::new, + StringBuilderTransformer::new + ) : ComposedTransformer::new, // Inline fields again InlineStaticFieldTransformer::new, @@ -60,7 +62,19 @@ public Composed_qProtectTransformer() { TryCatchRepairTransformer::new, // Remove field flow after cleaning code from garbage, so we can do pattern matching - qProtectFieldFlowTransformer::new + qProtectFieldFlowTransformer::new, + + strongStrings ? () -> new ComposedTransformer(false, + // Strings + qProtectStrongStringTransformer::new, + qProtectAESStringEncryptionTransformer::new, + StringBuilderTransformer::new, + + // Inline string pools + UniversalStringPoolTransformer::new, + StringBuilderTransformer::new + ) : ComposedTransformer::new + ); } } diff --git a/deobfuscator-transformers/src/main/java/uwu/narumi/deobfuscator/core/other/impl/qprotect/qProtectStrongStringTransformer.java b/deobfuscator-transformers/src/main/java/uwu/narumi/deobfuscator/core/other/impl/qprotect/qProtectStrongStringTransformer.java new file mode 100644 index 00000000..0af3da03 --- /dev/null +++ b/deobfuscator-transformers/src/main/java/uwu/narumi/deobfuscator/core/other/impl/qprotect/qProtectStrongStringTransformer.java @@ -0,0 +1,181 @@ +package uwu.narumi.deobfuscator.core.other.impl.qprotect; + +import org.objectweb.asm.tree.LdcInsnNode; +import org.objectweb.asm.tree.MethodInsnNode; +import org.objectweb.asm.tree.MethodNode; +import org.objectweb.asm.tree.TableSwitchInsnNode; +import uwu.narumi.deobfuscator.api.asm.MethodContext; +import uwu.narumi.deobfuscator.api.asm.MethodRef; +import uwu.narumi.deobfuscator.api.asm.matcher.Match; +import uwu.narumi.deobfuscator.api.asm.matcher.MatchContext; +import uwu.narumi.deobfuscator.api.asm.matcher.group.SequenceMatch; +import uwu.narumi.deobfuscator.api.asm.matcher.impl.*; +import uwu.narumi.deobfuscator.api.transformer.Transformer; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicReference; + +/** + * Transforms encrypted strings in qProtect obfuscated code. Example here: {@link qprotect.StringStrongEncryption} + */ +public class qProtectStrongStringTransformer extends Transformer { + + private static final Match DECRYPT_STRING_MATCH = MethodMatch.invokeStatic().desc("(II)Ljava/lang/String;") + .and(FrameMatch.stack(0, NumberMatch.numInteger().capture("salt2"))) + .and(FrameMatch.stack(1, NumberMatch.numInteger().capture("salt1"))); + + @Override + protected void transform() throws Exception { + scopedClasses().forEach(classWrapper -> { + AtomicReference decryptionMethodRef = new AtomicReference<>(); + + Map encryptedArray = new HashMap<>(); + + classWrapper.findClInit().ifPresent(clinit -> { + if (clinit.instructions.size() > 3 && clinit.instructions.get(0).isNumber()) { + MethodContext clinitContext = MethodContext.of(classWrapper, clinit); + SequenceMatch.of(OpcodeMatch.of(DUP), NumberMatch.of().capture("array-index"), StringMatch.of().capture("encrypted-value"), OpcodeMatch.of(AASTORE)).findAllMatches(clinitContext).forEach(matchContext -> { + encryptedArray.put(matchContext.captures().get("array-index").insn().asInteger(), matchContext.captures().get("encrypted-value").insn().asString()); + matchContext.removeAll(); + }); + } + }); + if (encryptedArray.isEmpty()) return; + + String[] decryptedArray = new String[encryptedArray.size()]; + + classWrapper.methods().forEach(methodNode -> { + DECRYPT_STRING_MATCH.findAllMatches(MethodContext.of(classWrapper, methodNode)).forEach(matchContext -> { + int salt1 = matchContext.captures().get("salt1").insn().asInteger(); + int salt2 = matchContext.captures().get("salt2").insn().asInteger(); + + MethodInsnNode decryptMethodInsn = (MethodInsnNode) matchContext.insn(); + decryptionMethodRef.set(MethodRef.of(decryptMethodInsn)); + + MethodNode decryptionMethod = findMethod(classWrapper.classNode(), MethodRef.of(decryptMethodInsn)).orElseThrow(); + + MethodContext decryptedMethodContext = MethodContext.of(classWrapper, decryptionMethod); + List numbers = NumberMatch.of().findAllMatches(decryptedMethodContext); + + int swappedKey = -1; + + int[] numbersArray = new int[2]; + for (int i = 0, hit = 0; i < numbers.size() && hit < 2; i++) { + if (numbers.get(i).insn().asInteger() != -1) { + numbersArray[hit] = numbers.get(i).insn().asInteger(); + hit++; + } + } + int number1 = numbersArray[0]; + int number2 = numbersArray[1]; + + if (!encryptedArray.containsKey(swappedKey)) { + int key = salt1; + swappedKey = (~(key = (key | number1) & (~key | number2)) | 0xFFFF) - ~key; + } + if (!encryptedArray.containsKey(swappedKey)) { + int key = salt1; + swappedKey = (~(key = key & number1 | ~key & number2) | 0xFFFF) - ~key; + } + if (!encryptedArray.containsKey(swappedKey)) { + int key = salt1; + swappedKey = (~(key = (key | number1) & ~(key & number2)) | 0xFFFF) - ~key; + } + + if (!encryptedArray.containsKey(swappedKey)) { + int key = salt1; + swappedKey = (~(key = (key | number1) - (key & number1)) | 0xFFFF) - ~key; + } + + + if (!encryptedArray.containsKey(swappedKey)) { + System.out.println(swappedKey); + return; + } + + + int n3 = encryptedArray.get(swappedKey).toCharArray()[0]; + int switchCaseKey = (~n3 | 0xFF) - ~n3; + int switchReturnKey; + TableSwitchInsnNode table = (TableSwitchInsnNode) Match.of(ctx -> ctx.insn() instanceof TableSwitchInsnNode).findFirstMatch(decryptedMethodContext).insn(); + if (switchCaseKey >= table.min && switchCaseKey <= table.max) { + switchReturnKey = table.labels.get(switchCaseKey).getNext().asNumber().intValue(); + } else { + switchReturnKey = table.dflt.getNext().asNumber().intValue(); + } + + String decryptedString = decrypt(encryptedArray.get(swappedKey), decryptedArray, salt1, salt2, swappedKey, switchReturnKey); + methodNode.instructions.insert(matchContext.insn(), new LdcInsnNode(decryptedString)); + matchContext.removeAll(); + + markChange(); + }); + }); + + // Remove decryption method + if (decryptionMethodRef.get() != null) { + classWrapper.methods().removeIf(methodNode -> methodNode.name.equals(decryptionMethodRef.get().name()) && methodNode.desc.equals(decryptionMethodRef.get().desc())); + } + }); + } + /* + * n pierwszy klucz + * n2 drugi klucz + * n4 klucz rozszyfrowany po pierwszej matematyce losowej + * n5 zwrocony przez switch klucz + * */ + private static String decrypt(String encryptedString, String[] decryptedArray, int n, int n2, int n4, int n5) { + int n3 = n; + if (decryptedArray[n4] == null) { + char[] cArray = encryptedString.toCharArray(); + + n3 = (short)n2; + int n6 = (~n3 | 0xFF) - ~n3 + ~n5 + 1; + if (n6 < 0) { + n6 += 256; + } + n3 = (short)n2; + int n7 = n5; + int n8 = ((n3 = (~n3 | 0xFFFF) - ~n3 >>> 8) & ~n7) - (~n3 & n7); + if (n8 < 0) { + n8 += 256; + } + int n9 = 0; + while (n9 < cArray.length) { + int n10 = n9 % 2; + int n11 = n9; + char[] cArray2 = cArray; + int n12 = cArray[n11]; + if (n10 == 0) { + n7 = n6; + n3 = n12; + cArray2[n11] = (char)(n3 & ~n7 | ~n3 & n7); + n7 = n6 << 5; + n3 = n6 >>> 3; + int n13 = (n3 & ~n7) + n7; + n7 = cArray[n9]; + n3 = n13; + n3 = (n3 | n7) & (~n3 | ~n7); + n6 = (~n3 | 0xFF) - ~n3; + } else { + n7 = n8; + n3 = n12; + cArray2[n11] = (char)(n3 & ~n7 | ~n3 & n7); + n7 = n8 << 5; + n3 = n8 >>> 3; + int n14 = (n3 & ~n7) + n7; + n7 = cArray[n9]; + n3 = n14; + n3 = (n3 | n7) - (n3 & n7); + n8 = (~n3 | 0xFF) - ~n3; + } + ++n9; + } + decryptedArray[n4] = new String(cArray).intern(); + } + return decryptedArray[n4]; + } +} diff --git a/deobfuscator-transformers/src/main/java/uwu/narumi/deobfuscator/core/other/impl/universal/pool/UniversalNumberPoolTransformer.java b/deobfuscator-transformers/src/main/java/uwu/narumi/deobfuscator/core/other/impl/universal/pool/UniversalNumberPoolTransformer.java index dca07ae7..cd22b054 100644 --- a/deobfuscator-transformers/src/main/java/uwu/narumi/deobfuscator/core/other/impl/universal/pool/UniversalNumberPoolTransformer.java +++ b/deobfuscator-transformers/src/main/java/uwu/narumi/deobfuscator/core/other/impl/universal/pool/UniversalNumberPoolTransformer.java @@ -11,6 +11,7 @@ import uwu.narumi.deobfuscator.api.asm.matcher.Match; import uwu.narumi.deobfuscator.api.asm.matcher.MatchContext; import uwu.narumi.deobfuscator.api.asm.matcher.group.AnyMatch; +import uwu.narumi.deobfuscator.api.asm.matcher.group.SequenceMatch; import uwu.narumi.deobfuscator.api.asm.matcher.impl.FieldMatch; import uwu.narumi.deobfuscator.api.asm.matcher.impl.FrameMatch; import uwu.narumi.deobfuscator.api.asm.matcher.impl.InsnMatch; @@ -24,6 +25,7 @@ import java.util.Objects; import java.util.Set; +import java.util.concurrent.atomic.AtomicBoolean; /** * Transforms number pool references to actual values. @@ -96,6 +98,8 @@ protected void transform() throws Exception { .and(FrameMatch.stack(1, FieldMatch.getStatic().fieldRef(fieldRefPool))))); } + AtomicBoolean markAsEntireArrayUse = new AtomicBoolean(false); + // Replace number pool references with actual values classWrapper.methods().forEach(methodNode -> { MethodContext methodContext = MethodContext.of(classWrapper, methodNode); @@ -109,23 +113,27 @@ protected void transform() throws Exception { numberPoolReferenceCtx.removeAll(); markChange(); }); + if (!markAsEntireArrayUse.get()) + markAsEntireArrayUse.set(SequenceMatch.of(Match.of(ctx -> !ctx.insn().isNumber()), FieldMatch.getStatic().fieldRef(fieldRefPool)).findAny(methodContext).isPresent()); }); // Cleanup - classWrapper.methods().remove(numberPoolMatchCtx.insnContext().methodNode()); - classWrapper.fields().removeIf(fieldNode -> fieldNode.name.equals(numberPoolFieldInsn.name) && fieldNode.desc.equals(numberPoolFieldInsn.desc)); - // Remove number pool initialization from clinit - classWrapper.findClInit().ifPresent(clinit -> { - for (AbstractInsnNode insn : clinit.instructions.toArray()) { - if (insn.getOpcode() == INVOKESTATIC && insn instanceof MethodInsnNode methodInsn && - methodInsn.name.equals(numberPoolMatchCtx.insnContext().methodNode().name) && methodInsn.desc.equals(numberPoolMatchCtx.insnContext().methodNode().desc) && - methodInsn.owner.equals(classWrapper.name()) - ) { - // Remove invocation - clinit.instructions.remove(insn); + if (!markAsEntireArrayUse.get() || isChanged()) { + classWrapper.methods().remove(numberPoolMatchCtx.insnContext().methodNode()); + classWrapper.fields().removeIf(fieldNode -> fieldNode.name.equals(numberPoolFieldInsn.name) && fieldNode.desc.equals(numberPoolFieldInsn.desc)); + // Remove number pool initialization from clinit + classWrapper.findClInit().ifPresent(clinit -> { + for (AbstractInsnNode insn : clinit.instructions.toArray()) { + if (insn.getOpcode() == INVOKESTATIC && insn instanceof MethodInsnNode methodInsn && + methodInsn.name.equals(numberPoolMatchCtx.insnContext().methodNode().name) && methodInsn.desc.equals(numberPoolMatchCtx.insnContext().methodNode().desc) && + methodInsn.owner.equals(classWrapper.name()) + ) { + // Remove invocation + clinit.instructions.remove(insn); + } } - } - }); + }); + } }); } From 8e80b1c463cf7ec5e2698a07c987c25a2c48ad8c Mon Sep 17 00:00:00 2001 From: Dawid Date: Fri, 13 Mar 2026 14:03:11 +0100 Subject: [PATCH 2/7] qProtect Indy fix --- .../qprotect/qProtectInvokeDynamicStrongTransformer.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/deobfuscator-transformers/src/main/java/uwu/narumi/deobfuscator/core/other/impl/qprotect/qProtectInvokeDynamicStrongTransformer.java b/deobfuscator-transformers/src/main/java/uwu/narumi/deobfuscator/core/other/impl/qprotect/qProtectInvokeDynamicStrongTransformer.java index 54894798..2ecc15f4 100644 --- a/deobfuscator-transformers/src/main/java/uwu/narumi/deobfuscator/core/other/impl/qprotect/qProtectInvokeDynamicStrongTransformer.java +++ b/deobfuscator-transformers/src/main/java/uwu/narumi/deobfuscator/core/other/impl/qprotect/qProtectInvokeDynamicStrongTransformer.java @@ -32,10 +32,7 @@ public class qProtectInvokeDynamicStrongTransformer extends Transformer { private static final int XOR_KEY_ARRAY_SIZE = 16; - private static final Match RESOLVE_HANDLE_MATCH = MethodMatch.invokeSpecial().owner("java/lang/invoke/ConstantCallSite").name("").desc("(Ljava/lang/invoke/MethodHandle;)V") - .and(FrameMatch.stack(0, OpcodeMatch.of(CHECKCAST) - .and(FrameMatch.stack(0, MethodMatch.invokeStatic().desc("([Ljava/lang/Object;)Ljava/lang/Object;").capture("resolveHandleMethod"))))); - + private static final Match RESOLVE_HANDLE_MATCH = MethodMatch.invokeStatic().desc("([Ljava/lang/Object;)Ljava/lang/Object;").capture("resolveHandleMethod"); private static final Match FIND_METHOD_HANDLE_MATCH = MethodMatch.invokeStatic().desc("(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); private static final Match XOR_KEY_ARRAY_MATCH = OpcodeMatch.of(ASTORE).capture("varStore") From f71cf2361b506d9e24f72e1e07014e66a68252dc Mon Sep 17 00:00:00 2001 From: Dawid Date: Fri, 13 Mar 2026 14:03:22 +0100 Subject: [PATCH 3/7] qProtect Tests --- .../deobfuscator/TestDeobfuscation.java | 5 + .../sample4/fastcode/IIlIllllIIIlIlllIl.class | Bin 0 -> 91307 bytes .../sample4/fastcode/IIlIllllIIIlIlllIl.dec | 201 ++++++++++++++++++ 3 files changed, 206 insertions(+) create mode 100644 testData/compiled/custom-classes/qprotect/sample4/fastcode/IIlIllllIIIlIlllIl.class create mode 100644 testData/results/custom-classes/qprotect/sample4/fastcode/IIlIllllIIIlIlllIl.dec diff --git a/deobfuscator-impl/src/test/java/uwu/narumi/deobfuscator/TestDeobfuscation.java b/deobfuscator-impl/src/test/java/uwu/narumi/deobfuscator/TestDeobfuscation.java index a0a3b090..55927b10 100644 --- a/deobfuscator-impl/src/test/java/uwu/narumi/deobfuscator/TestDeobfuscation.java +++ b/deobfuscator-impl/src/test/java/uwu/narumi/deobfuscator/TestDeobfuscation.java @@ -177,6 +177,11 @@ protected void registerAll() { .inputClassesDir(InputType.CUSTOM_CLASS, "qprotect/sample3") .register(); + test("qProtect Strong String Sample 4") + .transformers(() -> new Composed_qProtectTransformer(true)) + .inputClassesDir(InputType.CUSTOM_CLASS, "qprotect/sample4") + .register(); + test("qProtect-Lite Jar Sample") .transformers(Composed_qProtectTransformer::new) .inputJar("qprotect-obf.jar") diff --git a/testData/compiled/custom-classes/qprotect/sample4/fastcode/IIlIllllIIIlIlllIl.class b/testData/compiled/custom-classes/qprotect/sample4/fastcode/IIlIllllIIIlIlllIl.class new file mode 100644 index 0000000000000000000000000000000000000000..5c6e5c10ddfb96d0e7bf27b6ad2e80ee7ac13925 GIT binary patch literal 91307 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 literal 0 HcmV?d00001 diff --git a/testData/results/custom-classes/qprotect/sample4/fastcode/IIlIllllIIIlIlllIl.dec b/testData/results/custom-classes/qprotect/sample4/fastcode/IIlIllllIIIlIlllIl.dec new file mode 100644 index 00000000..33a9e4ad --- /dev/null +++ b/testData/results/custom-classes/qprotect/sample4/fastcode/IIlIllllIIIlIlllIl.dec @@ -0,0 +1,201 @@ +package fastcode; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.GregorianCalendar; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import net.md_5.bungee.api.ChatColor; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +public class IIlIllllIIIlIlllIl { + private static final String[] IlIIIIIIlII = new String[228]; + public static final String WITH_DELIMITER = "((?<=%1$s)|(?=%1$s))"; + private static final String[] IlIIIIIIlIl = new String[228]; + + public static long parseDateDiff(String var0, boolean var1) { + try { + Pattern var2 = Pattern.compile( + "(?:([0-9]+)\\s*y[a-z]*[,\\s]*)?(?:([0-9]+)\\s*mo[a-z]*[,\\s]*)?(?:([0-9]+)\\s*w[a-z]*[,\\s]*)?(?:([0-9]+)\\s*d[a-z]*[,\\s]*)?(?:([0-9]+)\\s*h[a-z]*[,\\s]*)?(?:([0-9]+)\\s*m[a-z]*[,\\s]*)?(?:([0-9]+)\\s*(?:s[a-z]*)?)?", + 2 + ); + Matcher var3 = var2.matcher(var0); + int var4 = 0; + int var5 = 0; + int var6 = 0; + int var7 = 0; + int var8 = 0; + int var9 = 0; + int var10 = 0; + boolean var11 = false; + + while (var3.find()) { + if (var3.group() != null && !var3.group().isEmpty()) { + for (int var12 = 0; var12 < var3.groupCount(); var12++) { + if (var3.group(var12) != null && !var3.group(var12).isEmpty()) { + var11 = true; + break; + } + } + + if (var11) { + if (var3.group(1) != null && !var3.group(1).isEmpty()) { + var4 = Integer.parseInt(var3.group(1)); + } + + if (var3.group(2) != null && !var3.group(2).isEmpty()) { + var5 = Integer.parseInt(var3.group(2)); + } + + if (var3.group(3) != null && !var3.group(3).isEmpty()) { + var6 = Integer.parseInt(var3.group(3)); + } + + if (var3.group(4) != null && !var3.group(4).isEmpty()) { + var7 = Integer.parseInt(var3.group(4)); + } + + if (var3.group(5) != null && !var3.group(5).isEmpty()) { + var8 = Integer.parseInt(var3.group(5)); + } + + if (var3.group(6) != null && !var3.group(6).isEmpty()) { + var9 = Integer.parseInt(var3.group(6)); + } + + if (var3.group(7) != null && !var3.group(7).isEmpty()) { + var10 = Integer.parseInt(var3.group(7)); + } + break; + } + } + } + + if (!var11) { + return -1L; + } else { + GregorianCalendar var15 = new GregorianCalendar(); + if (var4 > 0) { + var15.add(1, var4 * (var1 ? 1 : -1)); + } + + if (var5 > 0) { + var15.add(2, var5 * (var1 ? 1 : -1)); + } + + if (var6 > 0) { + var15.add(3, var6 * (var1 ? 1 : -1)); + } + + if (var7 > 0) { + var15.add(5, var7 * (var1 ? 1 : -1)); + } + + if (var8 > 0) { + var15.add(11, var8 * (var1 ? 1 : -1)); + } + + if (var9 > 0) { + var15.add(12, var9 * (var1 ? 1 : -1)); + } + + if (var10 > 0) { + var15.add(13, var10 * (var1 ? 1 : -1)); + } + + GregorianCalendar var13 = new GregorianCalendar(); + var13.add(1, 10); + return var15.after(var13) ? var13.getTimeInMillis() : var15.getTimeInMillis(); + } + } catch (Exception var14) { + return -1L; + } + } + + public static List fixLore(List var0) { + ArrayList var1 = new ArrayList(); + if (var0 == null) { + return var1; + } else { + var0.forEach(var1x -> var1.add(fixColor(var1x))); + return var1; + } + } + + public static List lores(ItemStack var0, Player var1) { + ItemMeta var2 = var0.getItemMeta(); + List var3 = var2.getLore(); + return (List)(var3 == null ? new ArrayList<>() : var3.stream().map(IIlIllllIIIlIlllIl::fixColor).collect(Collectors.toList())); + } + + public static void sendTitle(Player var0, String var1, String var2) { + var0.sendTitle(fixColor(var1), fixColor(var2)); + } + + private IIlIllllIIIlIlllIl() { + throw new UnsupportedOperationException("This is a utility class and cannot be instantiated"); + } + + public static void sendActionbar(Player var0, String var1) { + if (var0 != null && var1 != null) { + String var2 = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3]; + + try { + Class var3 = Class.forName("org.bukkit.craftbukkit." + var2 + ".entity.CraftPlayer"); + Object var4 = var3.cast(var0); + Class var5 = Class.forName("net.minecraft.server." + var2 + ".PacketPlayOutChat"); + Class var6 = Class.forName("net.minecraft.server." + var2 + ".Packet"); + Class var7; + if (var2.startsWith("v1_8_")) { + var7 = Class.forName("net.minecraft.server." + var2 + ".ChatSerializer"); + } else { + var7 = Class.forName("net.minecraft.server." + var2 + ".ChatComponentText"); + } + + Class var8 = Class.forName("net.minecraft.server." + var2 + ".IChatBaseComponent"); + Method var9 = null; + if (var2.startsWith("v1_8_")) { + var9 = var7.getDeclaredMethod("a", String.class); + } + + Object var10 = var2.startsWith("v1_8_") + ? var8.cast(var9.invoke(var7, "{'text': '" + var1 + "'}")) + : var7.getConstructor(String.class).newInstance(var1); + Object var11 = var5.getConstructor(var8, byte.class).newInstance(var10, (byte)2); + Method var12 = var3.getDeclaredMethod("getHandle"); + Object var13 = var12.invoke(var4); + Field var14 = var13.getClass().getDeclaredField("playerConnection"); + Object var15 = var14.get(var13); + Method var16 = var15.getClass().getDeclaredMethod("sendPacket", var6); + var16.invoke(var15, var11); + } catch (Exception var17) { + var17.printStackTrace(); + } + } + } + + public static String fixColor(String var0) { + String[] var1 = var0.split(String.format("((?<=%1$s)|(?=%1$s))", "&")); + StringBuilder var2 = new StringBuilder(); + + for (int var3 = 0; var3 < var1.length; var3++) { + if (var1[var3].equalsIgnoreCase("&")) { + if (var1[++var3].charAt(0) == '#') { + var2.append(ChatColor.of(var1[var3].substring(0, 7)) + var1[var3].substring(7)); + } else { + var2.append(org.bukkit.ChatColor.translateAlternateColorCodes('&', "&" + var1[var3]).replace(">>", "»")); + } + } else { + var2.append(var1[var3]); + } + } + + return var2.toString(); + } +} From e224899b09d84cb164164092b990c9c50b98e032 Mon Sep 17 00:00:00 2001 From: Dawid Date: Fri, 13 Mar 2026 15:49:10 +0100 Subject: [PATCH 4/7] qProtect Indy's --- .../qprotect/qProtectInvokeDynamicStrongTransformer.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/deobfuscator-transformers/src/main/java/uwu/narumi/deobfuscator/core/other/impl/qprotect/qProtectInvokeDynamicStrongTransformer.java b/deobfuscator-transformers/src/main/java/uwu/narumi/deobfuscator/core/other/impl/qprotect/qProtectInvokeDynamicStrongTransformer.java index 2ecc15f4..4ff1ae90 100644 --- a/deobfuscator-transformers/src/main/java/uwu/narumi/deobfuscator/core/other/impl/qprotect/qProtectInvokeDynamicStrongTransformer.java +++ b/deobfuscator-transformers/src/main/java/uwu/narumi/deobfuscator/core/other/impl/qprotect/qProtectInvokeDynamicStrongTransformer.java @@ -11,6 +11,7 @@ import uwu.narumi.deobfuscator.api.asm.MethodContext; import uwu.narumi.deobfuscator.api.asm.MethodRef; import uwu.narumi.deobfuscator.api.asm.matcher.Match; +import uwu.narumi.deobfuscator.api.asm.matcher.group.AnyMatch; import uwu.narumi.deobfuscator.api.asm.matcher.impl.FrameMatch; import uwu.narumi.deobfuscator.api.asm.matcher.impl.MethodMatch; import uwu.narumi.deobfuscator.api.asm.matcher.impl.NewArrayMatch; @@ -32,7 +33,10 @@ public class qProtectInvokeDynamicStrongTransformer extends Transformer { private static final int XOR_KEY_ARRAY_SIZE = 16; - private static final Match RESOLVE_HANDLE_MATCH = MethodMatch.invokeStatic().desc("([Ljava/lang/Object;)Ljava/lang/Object;").capture("resolveHandleMethod"); + private static final Match RESOLVE_HANDLE_MATCH = AnyMatch.of(MethodMatch.invokeSpecial().owner("java/lang/invoke/ConstantCallSite").name("").desc("(Ljava/lang/invoke/MethodHandle;)V") + .and(FrameMatch.stack(0, OpcodeMatch.of(CHECKCAST) + .and(FrameMatch.stack(0, MethodMatch.invokeStatic().desc("([Ljava/lang/Object;)Ljava/lang/Object;").capture("resolveHandleMethod"))))), + MethodMatch.invokeStatic().desc("([Ljava/lang/Object;)Ljava/lang/Object;").capture("resolveHandleMethod")); private static final Match FIND_METHOD_HANDLE_MATCH = MethodMatch.invokeStatic().desc("(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); private static final Match XOR_KEY_ARRAY_MATCH = OpcodeMatch.of(ASTORE).capture("varStore") From 25492123f4d57f6065928e5d6008ea356f96e726 Mon Sep 17 00:00:00 2001 From: Animowany Date: Sun, 15 Mar 2026 14:29:38 +0100 Subject: [PATCH 5/7] I did many things wrong, fixes --- .../Composed_qProtectTransformer.java | 70 +++++++++++++------ ...ProtectInvokeDynamicStrongTransformer.java | 5 +- .../pool/UniversalNumberPoolTransformer.java | 32 ++++----- 3 files changed, 63 insertions(+), 44 deletions(-) diff --git a/deobfuscator-transformers/src/main/java/uwu/narumi/deobfuscator/core/other/composed/Composed_qProtectTransformer.java b/deobfuscator-transformers/src/main/java/uwu/narumi/deobfuscator/core/other/composed/Composed_qProtectTransformer.java index 96256df4..891b3f73 100644 --- a/deobfuscator-transformers/src/main/java/uwu/narumi/deobfuscator/core/other/composed/Composed_qProtectTransformer.java +++ b/deobfuscator-transformers/src/main/java/uwu/narumi/deobfuscator/core/other/composed/Composed_qProtectTransformer.java @@ -17,10 +17,6 @@ // TODO: Deobfuscate strong string encryption. Sample: qprotect.StringStrongEncryption public class Composed_qProtectTransformer extends ComposedTransformer { public Composed_qProtectTransformer() { - super(false); - } - - public Composed_qProtectTransformer(boolean strongStrings) { super( // This fixes some weird issues where "this" is used as a local variable name. LocalVariableNamesCleanTransformer::new, @@ -39,16 +35,12 @@ public Composed_qProtectTransformer(boolean strongStrings) { // Fix flow UniversalFlowTransformer::new, - !strongStrings ? () -> new ComposedTransformer(false, - // Strings - qProtectStringTransformer::new, - qProtectAESStringEncryptionTransformer::new, - StringBuilderTransformer::new, + // Strings + qProtectStringTransformer::new, + qProtectAESStringEncryptionTransformer::new, - // Inline string pools - UniversalStringPoolTransformer::new, - StringBuilderTransformer::new - ) : ComposedTransformer::new, + // Inline string pools + UniversalStringPoolTransformer::new, // Inline fields again InlineStaticFieldTransformer::new, @@ -62,19 +54,51 @@ public Composed_qProtectTransformer(boolean strongStrings) { TryCatchRepairTransformer::new, // Remove field flow after cleaning code from garbage, so we can do pattern matching - qProtectFieldFlowTransformer::new, + qProtectFieldFlowTransformer::new + ); + } + + public Composed_qProtectTransformer(boolean strongStrings) { + super( + // This fixes some weird issues where "this" is used as a local variable name. + LocalVariableNamesCleanTransformer::new, + + // Initial cleaning code from garbage + UniversalNumberTransformer::new, + InlineStaticFieldTransformer::new, + InlineLocalVariablesTransformer::new, + + // Inline number pools, but keep byte arrays for StrongStringEncryption + UniversalNumberPoolTransformer::new, + // Decrypt method invocation + qProtectInvokeDynamicTransformer::new, + qProtectInvokeDynamicStrongTransformer::new, + + // Fix flow + UniversalFlowTransformer::new, + + // Inline fields again + InlineStaticFieldTransformer::new, + InlineLocalVariablesTransformer::new, - strongStrings ? () -> new ComposedTransformer(false, - // Strings - qProtectStrongStringTransformer::new, - qProtectAESStringEncryptionTransformer::new, - StringBuilderTransformer::new, + // Cleanup + ComposedPeepholeCleanTransformer::new, - // Inline string pools - UniversalStringPoolTransformer::new, - StringBuilderTransformer::new - ) : ComposedTransformer::new + // Resolve qProtect flow that uses try-catches + qProtectTryCatchTransformer::new, + TryCatchRepairTransformer::new, + + // String Strings + qProtectStrongStringTransformer::new, + qProtectAESStringEncryptionTransformer::new, + StringBuilderTransformer::new, + // Inline string pools + UniversalStringPoolTransformer::new, + StringBuilderTransformer::new, + + // Remove field flow after cleaning code from garbage, so we can do pattern matching + qProtectFieldFlowTransformer::new ); } } diff --git a/deobfuscator-transformers/src/main/java/uwu/narumi/deobfuscator/core/other/impl/qprotect/qProtectInvokeDynamicStrongTransformer.java b/deobfuscator-transformers/src/main/java/uwu/narumi/deobfuscator/core/other/impl/qprotect/qProtectInvokeDynamicStrongTransformer.java index 4ff1ae90..8bb7d223 100644 --- a/deobfuscator-transformers/src/main/java/uwu/narumi/deobfuscator/core/other/impl/qprotect/qProtectInvokeDynamicStrongTransformer.java +++ b/deobfuscator-transformers/src/main/java/uwu/narumi/deobfuscator/core/other/impl/qprotect/qProtectInvokeDynamicStrongTransformer.java @@ -34,9 +34,10 @@ public class qProtectInvokeDynamicStrongTransformer extends Transformer { private static final int XOR_KEY_ARRAY_SIZE = 16; private static final Match RESOLVE_HANDLE_MATCH = AnyMatch.of(MethodMatch.invokeSpecial().owner("java/lang/invoke/ConstantCallSite").name("").desc("(Ljava/lang/invoke/MethodHandle;)V") - .and(FrameMatch.stack(0, OpcodeMatch.of(CHECKCAST) - .and(FrameMatch.stack(0, MethodMatch.invokeStatic().desc("([Ljava/lang/Object;)Ljava/lang/Object;").capture("resolveHandleMethod"))))), + .and(FrameMatch.stack(0, OpcodeMatch.of(CHECKCAST) + .and(FrameMatch.stack(0, MethodMatch.invokeStatic().desc("([Ljava/lang/Object;)Ljava/lang/Object;").capture("resolveHandleMethod"))))), MethodMatch.invokeStatic().desc("([Ljava/lang/Object;)Ljava/lang/Object;").capture("resolveHandleMethod")); + private static final Match FIND_METHOD_HANDLE_MATCH = MethodMatch.invokeStatic().desc("(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); private static final Match XOR_KEY_ARRAY_MATCH = OpcodeMatch.of(ASTORE).capture("varStore") diff --git a/deobfuscator-transformers/src/main/java/uwu/narumi/deobfuscator/core/other/impl/universal/pool/UniversalNumberPoolTransformer.java b/deobfuscator-transformers/src/main/java/uwu/narumi/deobfuscator/core/other/impl/universal/pool/UniversalNumberPoolTransformer.java index cd22b054..8706323b 100644 --- a/deobfuscator-transformers/src/main/java/uwu/narumi/deobfuscator/core/other/impl/universal/pool/UniversalNumberPoolTransformer.java +++ b/deobfuscator-transformers/src/main/java/uwu/narumi/deobfuscator/core/other/impl/universal/pool/UniversalNumberPoolTransformer.java @@ -98,8 +98,6 @@ protected void transform() throws Exception { .and(FrameMatch.stack(1, FieldMatch.getStatic().fieldRef(fieldRefPool))))); } - AtomicBoolean markAsEntireArrayUse = new AtomicBoolean(false); - // Replace number pool references with actual values classWrapper.methods().forEach(methodNode -> { MethodContext methodContext = MethodContext.of(classWrapper, methodNode); @@ -113,27 +111,23 @@ protected void transform() throws Exception { numberPoolReferenceCtx.removeAll(); markChange(); }); - if (!markAsEntireArrayUse.get()) - markAsEntireArrayUse.set(SequenceMatch.of(Match.of(ctx -> !ctx.insn().isNumber()), FieldMatch.getStatic().fieldRef(fieldRefPool)).findAny(methodContext).isPresent()); }); // Cleanup - if (!markAsEntireArrayUse.get() || isChanged()) { - classWrapper.methods().remove(numberPoolMatchCtx.insnContext().methodNode()); - classWrapper.fields().removeIf(fieldNode -> fieldNode.name.equals(numberPoolFieldInsn.name) && fieldNode.desc.equals(numberPoolFieldInsn.desc)); - // Remove number pool initialization from clinit - classWrapper.findClInit().ifPresent(clinit -> { - for (AbstractInsnNode insn : clinit.instructions.toArray()) { - if (insn.getOpcode() == INVOKESTATIC && insn instanceof MethodInsnNode methodInsn && - methodInsn.name.equals(numberPoolMatchCtx.insnContext().methodNode().name) && methodInsn.desc.equals(numberPoolMatchCtx.insnContext().methodNode().desc) && - methodInsn.owner.equals(classWrapper.name()) - ) { - // Remove invocation - clinit.instructions.remove(insn); - } + classWrapper.methods().remove(numberPoolMatchCtx.insnContext().methodNode()); + classWrapper.fields().removeIf(fieldNode -> fieldNode.name.equals(numberPoolFieldInsn.name) && fieldNode.desc.equals(numberPoolFieldInsn.desc)); + // Remove number pool initialization from clinit + classWrapper.findClInit().ifPresent(clinit -> { + for (AbstractInsnNode insn : clinit.instructions.toArray()) { + if (insn.getOpcode() == INVOKESTATIC && insn instanceof MethodInsnNode methodInsn && + methodInsn.name.equals(numberPoolMatchCtx.insnContext().methodNode().name) && methodInsn.desc.equals(numberPoolMatchCtx.insnContext().methodNode().desc) && + methodInsn.owner.equals(classWrapper.name()) + ) { + // Remove invocation + clinit.instructions.remove(insn); } - }); - } + } + }); }); } From 80d7cf99f0fa65debafb56494ddf7712b2da48c6 Mon Sep 17 00:00:00 2001 From: Animowany Date: Sun, 15 Mar 2026 14:30:04 +0100 Subject: [PATCH 6/7] Tests --- .../java/uwu/narumi/deobfuscator/TestDeobfuscation.java | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/deobfuscator-impl/src/test/java/uwu/narumi/deobfuscator/TestDeobfuscation.java b/deobfuscator-impl/src/test/java/uwu/narumi/deobfuscator/TestDeobfuscation.java index 55927b10..b6c466a6 100644 --- a/deobfuscator-impl/src/test/java/uwu/narumi/deobfuscator/TestDeobfuscation.java +++ b/deobfuscator-impl/src/test/java/uwu/narumi/deobfuscator/TestDeobfuscation.java @@ -172,14 +172,9 @@ protected void registerAll() { .inputClassesDir(InputType.CUSTOM_CLASS, "qprotect/sample2") .register(); - test("qProtect Sample 3") - .transformers(Composed_qProtectTransformer::new) - .inputClassesDir(InputType.CUSTOM_CLASS, "qprotect/sample3") - .register(); - - test("qProtect Strong String Sample 4") + test("qProtect Strong String Sample 3") .transformers(() -> new Composed_qProtectTransformer(true)) - .inputClassesDir(InputType.CUSTOM_CLASS, "qprotect/sample4") + .inputClassesDir(InputType.CUSTOM_CLASS, "qprotect/sample3") .register(); test("qProtect-Lite Jar Sample") From 2aa531b4ba44a432951af50846037a5ffc92cc15 Mon Sep 17 00:00:00 2001 From: Animowany Date: Sun, 15 Mar 2026 14:32:18 +0100 Subject: [PATCH 7/7] Valid tests --- .../sample3/fastcode/IlllIIlIIlllIIIl.dec | 360 +----------------- .../sample4/fastcode/IIlIllllIIIlIlllIl.dec | 201 ---------- 2 files changed, 17 insertions(+), 544 deletions(-) delete mode 100644 testData/results/custom-classes/qprotect/sample4/fastcode/IIlIllllIIIlIlllIl.dec diff --git a/testData/results/custom-classes/qprotect/sample3/fastcode/IlllIIlIIlllIIIl.dec b/testData/results/custom-classes/qprotect/sample3/fastcode/IlllIIlIIlllIIIl.dec index f5b6116d..090e0adc 100644 --- a/testData/results/custom-classes/qprotect/sample3/fastcode/IlllIIlIIlllIIIl.dec +++ b/testData/results/custom-classes/qprotect/sample3/fastcode/IlllIIlIIlllIIIl.dec @@ -10,9 +10,7 @@ import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.inventory.ItemStack; public class IlllIIlIIlllIIIl { - private static final String[] IlIIlIlIIIIIlll = new String[]{ - "EáÞ\u0018¸", "ßÖA", "Õ", "%Qj\u0002", "\u009fS\u0085NÓúØ", "÷Ö\u0006\u0095ù", "ÚÈb\u001cÛ9", "$wòÊ=j", "ý»\u0001\u0018\u009a", "\u0090¦]í®*" - }; + private static final String[] IlIIlIlIIIIIlll = new String[10]; public IIIlllIIIIllIl userManager; public IIIIlIIIIIIl plugin = IIIIlIIIIIIl.getPlugin(); private static final String[] IIllIIIlIlIIlII = new String[10]; @@ -24,24 +22,19 @@ public class IlllIIlIIlllIIIl { public IlllIIlIIlllIIIl() { this.userManager = this.plugin.getUserManager(); - this.database = new File(this.plugin.getDataFolder(), IIIllIIIlIIIIIl(-2044252752, 906984765)); + this.database = new File(this.plugin.getDataFolder(), "users"); } public void loadUser(IllIlIIIllIIll var1, File var2) { try { YamlConfiguration var3 = YamlConfiguration.loadConfiguration(var2); ArrayList var4 = new ArrayList(); - if (var3.contains(IIIllIIIlIIIIIl(498347452, -1569708320) + IIIllIIIlIIIIIl(-472699458, -412626163))) { - Objects.requireNonNull( - var3.getList( - IIIllIIIlIIIIIl(-260821569, 1878136150) + IIIllIIIlIIIIIl(525217201, -1963008494) + IIIllIIIlIIIIIl(-924701254, -1452694356) - ) - ) - .forEach(var1x -> { - if (var1x instanceof ItemStack) { - var4.add((ItemStack)var1x); - } - }); + if (var3.contains("sakiewkaItems")) { + Objects.requireNonNull(var3.getList("sakiewkaItems")).forEach(var1x -> { + if (var1x instanceof ItemStack) { + var4.add((ItemStack)var1x); + } + }); } var1.setSakiewkaItems(var4); @@ -58,21 +51,14 @@ public class IlllIIlIIlllIIIl { } else { try { YamlConfiguration var3 = YamlConfiguration.loadConfiguration(var2); - IllIlIIIllIIll var4 = new IllIlIIIllIIll(var3.getString(IIIllIIIlIIIIIl(-466014789, -1870939692))); + IllIlIIIllIIll var4 = new IllIlIIIllIIll(var3.getString("name")); ArrayList var5 = new ArrayList(); - if (var3.contains(IIIllIIIlIIIIIl(-616747585, 821106006) + IIIllIIIlIIIIIl(-681955919, -1796547054) + IIIllIIIlIIIIIl(1487220154, -1766480724)) - ) - { - Objects.requireNonNull( - var3.getList( - IIIllIIIlIIIIIl(-1446695489, -1084877482) + IIIllIIIlIIIIIl(493628849, -115483118) + IIIllIIIlIIIIIl(135540154, -998923092) - ) - ) - .forEach(var1x -> { - if (var1x instanceof ItemStack) { - var5.add((ItemStack)var1x); - } - }); + if (var3.contains("sakiewkaItems")) { + Objects.requireNonNull(var3.getList("sakiewkaItems")).forEach(var1x -> { + if (var1x instanceof ItemStack) { + var5.add((ItemStack)var1x); + } + }); } var4.setSakiewkaItems(var5); @@ -90,9 +76,9 @@ public class IlllIIlIIlllIIIl { YamlConfiguration var3 = new YamlConfiguration(); try { - var3.set(IIIllIIIlIIIIIl(224341435, 1776794068), var1.getName()); + var3.set("name", var1.getName()); List var4 = var1.getSakiewkaItems(); - var3.set(IIIllIIIlIIIIIl(1792421304, 826715748) + IIIllIIIlIIIIIl(-24891971, 315653954) + IIIllIIIlIIIIIl(378023353, 747270512), var4); + var3.set("sakiewkaItems", var4); var3.save(var2); } catch (IOException var5) { Bukkit.getLogger().severe("Failed to save user data to file: " + var2.getName()); @@ -100,318 +86,6 @@ public class IlllIIlIIlllIIIl { } } - private static String IIIllIIIlIIIIIl(int var0, int var1) { - int var12 = (var0 | 11704) & ~(var0 & 11704); - int var2 = (~var12 | 65535) - ~var12; - if (IIllIIIlIlIIlII[var2] == null) { - char[] var3 = IlIIlIlIIIIIlll[var2].toCharArray(); - int var14 = var3[0]; - - short var4 = switch ((~var14 | 0xFF) - ~var14) { - case 0 -> 55; - case 1 -> 95; - case 2 -> 0; - case 3 -> 21; - case 4 -> 105; - case 5 -> 38; - case 6 -> 116; - case 7 -> 80; - case 8 -> 19; - case 9 -> 65; - case 10 -> 2; - case 11 -> 123; - case 12 -> 161; - case 13 -> 163; - case 14 -> 233; - case 15 -> 50; - case 16 -> 10; - case 17 -> 243; - case 18 -> 177; - case 19 -> 127; - case 20 -> 199; - case 21 -> 62; - case 22 -> 81; - case 23 -> 58; - case 24 -> 162; - case 25 -> 120; - case 26 -> 229; - case 27 -> 74; - case 28 -> 11; - case 29 -> 159; - case 30 -> 119; - case 31 -> 66; - case 32 -> 225; - case 33 -> 190; - case 34 -> 167; - case 35 -> 18; - case 36 -> 255; - case 37 -> 137; - case 38 -> 215; - case 39 -> 201; - case 40 -> 131; - case 41 -> 37; - case 42 -> 22; - case 43 -> 91; - case 44 -> 178; - case 45 -> 113; - case 46 -> 157; - case 47 -> 246; - case 48 -> 25; - case 49 -> 180; - case 50 -> 170; - case 51 -> 14; - case 52 -> 138; - case 53 -> 17; - case 54 -> 212; - case 55 -> 72; - case 56 -> 9; - case 57 -> 88; - case 58 -> 149; - case 59 -> 124; - case 60 -> 168; - case 61 -> 226; - case 62 -> 107; - case 63 -> 64; - case 64 -> 188; - case 65 -> 184; - case 66 -> 34; - case 67 -> 213; - case 68 -> 63; - case 69 -> 46; - case 70 -> 223; - case 71 -> 92; - case 72 -> 133; - case 73 -> 164; - case 74 -> 98; - case 75 -> 208; - case 76 -> 197; - case 77 -> 28; - case 78 -> 7; - case 79 -> 13; - case 80 -> 155; - case 81 -> 148; - case 82 -> 117; - case 83 -> 15; - case 84 -> 114; - case 85 -> 247; - case 86 -> 236; - case 87 -> 205; - case 88 -> 32; - case 89 -> 41; - case 90 -> 76; - case 91 -> 189; - case 92 -> 141; - case 93 -> 69; - case 94 -> 192; - case 95 -> 135; - case 96 -> 89; - case 97 -> 40; - case 98 -> 51; - case 99 -> 47; - case 100 -> 110; - case 101 -> 118; - case 102 -> 57; - case 103 -> 239; - case 104 -> 253; - case 105 -> 54; - case 106 -> 206; - case 107 -> 60; - case 108 -> 165; - case 109 -> 102; - case 110 -> 125; - case 111 -> 130; - case 112 -> 166; - case 113 -> 12; - case 114 -> 36; - case 115 -> 222; - case 116 -> 26; - case 117 -> 142; - case 118 -> 45; - case 119 -> 129; - case 120 -> 78; - case 121 -> 156; - case 122 -> 132; - case 123 -> 195; - case 124 -> 220; - case 125 -> 71; - case 126 -> 238; - case 127 -> 49; - case 128 -> 202; - case 129 -> 151; - case 130 -> 126; - case 131 -> 230; - case 132 -> 173; - case 133 -> 53; - case 134 -> 245; - case 135 -> 5; - case 136 -> 150; - case 137 -> 187; - case 138 -> 8; - case 139 -> 61; - case 140 -> 193; - case 141 -> 68; - case 142 -> 99; - case 143 -> 175; - case 144 -> 23; - case 145 -> 196; - case 146 -> 30; - case 147 -> 85; - case 148 -> 4; - case 149 -> 101; - case 150 -> 44; - case 151 -> 139; - case 152 -> 70; - case 153 -> 83; - case 154 -> 209; - case 155 -> 174; - case 156 -> 87; - case 157 -> 75; - case 158 -> 29; - case 159 -> 244; - case 160 -> 154; - case 161 -> 94; - case 162 -> 147; - case 163 -> 171; - case 164 -> 112; - case 165 -> 59; - case 166 -> 35; - case 167 -> 79; - case 168 -> 204; - case 169 -> 97; - case 170 -> 146; - case 171 -> 108; - case 172 -> 1; - case 173 -> 104; - case 174 -> 176; - case 175 -> 73; - case 176 -> 198; - case 177 -> 90; - case 178 -> 158; - case 179 -> 221; - case 180 -> 152; - case 181 -> 103; - case 182 -> 100; - case 183 -> 248; - case 184 -> 143; - case 185 -> 240; - case 186 -> 31; - case 187 -> 43; - case 188 -> 252; - case 189 -> 234; - case 190 -> 235; - case 191 -> 249; - case 192 -> 144; - case 193 -> 254; - case 194 -> 153; - case 195 -> 140; - case 196 -> 207; - case 197 -> 217; - case 198 -> 3; - case 199 -> 160; - case 200 -> 224; - case 201 -> 109; - case 202 -> 121; - case 203 -> 203; - case 204 -> 172; - case 205 -> 93; - case 206 -> 186; - case 207 -> 231; - case 208 -> 218; - case 209 -> 52; - case 210 -> 77; - case 211 -> 219; - case 212 -> 48; - case 213 -> 6; - case 214 -> 122; - case 215 -> 20; - case 216 -> 191; - case 217 -> 16; - case 218 -> 82; - case 219 -> 136; - case 220 -> 242; - case 221 -> 39; - case 222 -> 96; - case 223 -> 182; - case 224 -> 169; - case 225 -> 67; - case 226 -> 33; - case 227 -> 145; - case 228 -> 241; - case 229 -> 250; - case 230 -> 24; - case 231 -> 183; - case 232 -> 115; - case 233 -> 128; - case 234 -> 27; - case 235 -> 251; - case 236 -> 228; - case 237 -> 84; - case 238 -> 179; - case 239 -> 237; - case 240 -> 214; - case 241 -> 56; - case 242 -> 86; - case 243 -> 42; - case 244 -> 227; - case 245 -> 185; - case 246 -> 106; - case 247 -> 194; - case 248 -> 200; - case 249 -> 210; - case 250 -> 216; - case 251 -> 111; - case 252 -> 232; - case 253 -> 181; - case 254 -> 134; - default -> 211; - }; - int var15 = (short)var1; - int var5 = (~var15 | 0xFF) - ~var15 + ~var4 + 1; - if (var5 < 0) { - var5 += 256; - } - - var15 = (short)var1; - var14 = (~var15 | 65535) - ~var15 >>> 8; - int var6 = (var14 ^ var4) - 2 * (~var14 & var4); - if (var6 < 0) { - var6 += 256; - } - - for (int var7 = 0; var7 < var3.length; var7++) { - int var8 = var7 % 2; - char var10002 = var3[var7]; - if (var8 == 0) { - char var18 = var10002; - var3[var7] = (char)((var18 | var5) & ~(var18 & var5)); - int var29 = var5 >>> 3; - int var13 = var5 << 5; - var15 = var29; - var29 = (var15 & ~var13) + var13; - char var26 = var3[var7]; - var15 = var29; - var15 = var15 & ~var26 | ~var15 & var26; - var5 = (~var15 | 0xFF) - ~var15; - } else { - int var22 = var10002; - var3[var7] = (char)((var22 | var6) - (var22 & var6)); - int var31 = var6 >>> 3; - int var27 = var6 << 5; - var22 = var31; - var31 = (var22 & ~var27) + var27; - char var28 = var3[var7]; - var22 = var31; - var22 = (var22 | var28) - (var22 & var28); - var6 = (~var22 | 0xFF) - ~var22; - } - } - - IIllIIIlIlIIlII[var2] = new String(var3).intern(); - } - - return IIllIIIlIlIIlII[var2]; - } - private File getFile(String var1) { return new File(this.database, var1 + ".yml"); } diff --git a/testData/results/custom-classes/qprotect/sample4/fastcode/IIlIllllIIIlIlllIl.dec b/testData/results/custom-classes/qprotect/sample4/fastcode/IIlIllllIIIlIlllIl.dec deleted file mode 100644 index 33a9e4ad..00000000 --- a/testData/results/custom-classes/qprotect/sample4/fastcode/IIlIllllIIIlIlllIl.dec +++ /dev/null @@ -1,201 +0,0 @@ -package fastcode; - -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.GregorianCalendar; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Collectors; -import net.md_5.bungee.api.ChatColor; -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; - -public class IIlIllllIIIlIlllIl { - private static final String[] IlIIIIIIlII = new String[228]; - public static final String WITH_DELIMITER = "((?<=%1$s)|(?=%1$s))"; - private static final String[] IlIIIIIIlIl = new String[228]; - - public static long parseDateDiff(String var0, boolean var1) { - try { - Pattern var2 = Pattern.compile( - "(?:([0-9]+)\\s*y[a-z]*[,\\s]*)?(?:([0-9]+)\\s*mo[a-z]*[,\\s]*)?(?:([0-9]+)\\s*w[a-z]*[,\\s]*)?(?:([0-9]+)\\s*d[a-z]*[,\\s]*)?(?:([0-9]+)\\s*h[a-z]*[,\\s]*)?(?:([0-9]+)\\s*m[a-z]*[,\\s]*)?(?:([0-9]+)\\s*(?:s[a-z]*)?)?", - 2 - ); - Matcher var3 = var2.matcher(var0); - int var4 = 0; - int var5 = 0; - int var6 = 0; - int var7 = 0; - int var8 = 0; - int var9 = 0; - int var10 = 0; - boolean var11 = false; - - while (var3.find()) { - if (var3.group() != null && !var3.group().isEmpty()) { - for (int var12 = 0; var12 < var3.groupCount(); var12++) { - if (var3.group(var12) != null && !var3.group(var12).isEmpty()) { - var11 = true; - break; - } - } - - if (var11) { - if (var3.group(1) != null && !var3.group(1).isEmpty()) { - var4 = Integer.parseInt(var3.group(1)); - } - - if (var3.group(2) != null && !var3.group(2).isEmpty()) { - var5 = Integer.parseInt(var3.group(2)); - } - - if (var3.group(3) != null && !var3.group(3).isEmpty()) { - var6 = Integer.parseInt(var3.group(3)); - } - - if (var3.group(4) != null && !var3.group(4).isEmpty()) { - var7 = Integer.parseInt(var3.group(4)); - } - - if (var3.group(5) != null && !var3.group(5).isEmpty()) { - var8 = Integer.parseInt(var3.group(5)); - } - - if (var3.group(6) != null && !var3.group(6).isEmpty()) { - var9 = Integer.parseInt(var3.group(6)); - } - - if (var3.group(7) != null && !var3.group(7).isEmpty()) { - var10 = Integer.parseInt(var3.group(7)); - } - break; - } - } - } - - if (!var11) { - return -1L; - } else { - GregorianCalendar var15 = new GregorianCalendar(); - if (var4 > 0) { - var15.add(1, var4 * (var1 ? 1 : -1)); - } - - if (var5 > 0) { - var15.add(2, var5 * (var1 ? 1 : -1)); - } - - if (var6 > 0) { - var15.add(3, var6 * (var1 ? 1 : -1)); - } - - if (var7 > 0) { - var15.add(5, var7 * (var1 ? 1 : -1)); - } - - if (var8 > 0) { - var15.add(11, var8 * (var1 ? 1 : -1)); - } - - if (var9 > 0) { - var15.add(12, var9 * (var1 ? 1 : -1)); - } - - if (var10 > 0) { - var15.add(13, var10 * (var1 ? 1 : -1)); - } - - GregorianCalendar var13 = new GregorianCalendar(); - var13.add(1, 10); - return var15.after(var13) ? var13.getTimeInMillis() : var15.getTimeInMillis(); - } - } catch (Exception var14) { - return -1L; - } - } - - public static List fixLore(List var0) { - ArrayList var1 = new ArrayList(); - if (var0 == null) { - return var1; - } else { - var0.forEach(var1x -> var1.add(fixColor(var1x))); - return var1; - } - } - - public static List lores(ItemStack var0, Player var1) { - ItemMeta var2 = var0.getItemMeta(); - List var3 = var2.getLore(); - return (List)(var3 == null ? new ArrayList<>() : var3.stream().map(IIlIllllIIIlIlllIl::fixColor).collect(Collectors.toList())); - } - - public static void sendTitle(Player var0, String var1, String var2) { - var0.sendTitle(fixColor(var1), fixColor(var2)); - } - - private IIlIllllIIIlIlllIl() { - throw new UnsupportedOperationException("This is a utility class and cannot be instantiated"); - } - - public static void sendActionbar(Player var0, String var1) { - if (var0 != null && var1 != null) { - String var2 = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3]; - - try { - Class var3 = Class.forName("org.bukkit.craftbukkit." + var2 + ".entity.CraftPlayer"); - Object var4 = var3.cast(var0); - Class var5 = Class.forName("net.minecraft.server." + var2 + ".PacketPlayOutChat"); - Class var6 = Class.forName("net.minecraft.server." + var2 + ".Packet"); - Class var7; - if (var2.startsWith("v1_8_")) { - var7 = Class.forName("net.minecraft.server." + var2 + ".ChatSerializer"); - } else { - var7 = Class.forName("net.minecraft.server." + var2 + ".ChatComponentText"); - } - - Class var8 = Class.forName("net.minecraft.server." + var2 + ".IChatBaseComponent"); - Method var9 = null; - if (var2.startsWith("v1_8_")) { - var9 = var7.getDeclaredMethod("a", String.class); - } - - Object var10 = var2.startsWith("v1_8_") - ? var8.cast(var9.invoke(var7, "{'text': '" + var1 + "'}")) - : var7.getConstructor(String.class).newInstance(var1); - Object var11 = var5.getConstructor(var8, byte.class).newInstance(var10, (byte)2); - Method var12 = var3.getDeclaredMethod("getHandle"); - Object var13 = var12.invoke(var4); - Field var14 = var13.getClass().getDeclaredField("playerConnection"); - Object var15 = var14.get(var13); - Method var16 = var15.getClass().getDeclaredMethod("sendPacket", var6); - var16.invoke(var15, var11); - } catch (Exception var17) { - var17.printStackTrace(); - } - } - } - - public static String fixColor(String var0) { - String[] var1 = var0.split(String.format("((?<=%1$s)|(?=%1$s))", "&")); - StringBuilder var2 = new StringBuilder(); - - for (int var3 = 0; var3 < var1.length; var3++) { - if (var1[var3].equalsIgnoreCase("&")) { - if (var1[++var3].charAt(0) == '#') { - var2.append(ChatColor.of(var1[var3].substring(0, 7)) + var1[var3].substring(7)); - } else { - var2.append(org.bukkit.ChatColor.translateAlternateColorCodes('&', "&" + var1[var3]).replace(">>", "»")); - } - } else { - var2.append(var1[var3]); - } - } - - return var2.toString(); - } -}