diff --git a/deobfuscator-api/src/main/java/uwu/narumi/deobfuscator/api/asm/matcher/Match.java b/deobfuscator-api/src/main/java/uwu/narumi/deobfuscator/api/asm/matcher/Match.java index 3dd14749..f0ae8413 100644 --- a/deobfuscator-api/src/main/java/uwu/narumi/deobfuscator/api/asm/matcher/Match.java +++ b/deobfuscator-api/src/main/java/uwu/narumi/deobfuscator/api/asm/matcher/Match.java @@ -1,5 +1,6 @@ package uwu.narumi.deobfuscator.api.asm.matcher; +import org.jetbrains.annotations.ApiStatus; import org.objectweb.asm.tree.AbstractInsnNode; import uwu.narumi.deobfuscator.api.asm.InsnContext; import uwu.narumi.deobfuscator.api.asm.MethodContext; @@ -34,12 +35,13 @@ public boolean matches(MethodContext methodContext) { } /** - * Matches the instrustion and merges if successful + * Matches the instruction and merges if successful * * @param insnContext Instruction context * @param currentMatchContext Match context to merge into * @return If matches */ + @ApiStatus.Internal public boolean matchAndMerge(InsnContext insnContext, MatchContext currentMatchContext) { MatchContext result = this.matchResult(insnContext); if (result != null) { diff --git a/deobfuscator-api/src/main/java/uwu/narumi/deobfuscator/api/asm/matcher/MatchContext.java b/deobfuscator-api/src/main/java/uwu/narumi/deobfuscator/api/asm/matcher/MatchContext.java index 56e9117c..b8e79a0b 100644 --- a/deobfuscator-api/src/main/java/uwu/narumi/deobfuscator/api/asm/matcher/MatchContext.java +++ b/deobfuscator-api/src/main/java/uwu/narumi/deobfuscator/api/asm/matcher/MatchContext.java @@ -5,11 +5,11 @@ import org.objectweb.asm.tree.analysis.OriginalSourceValue; import uwu.narumi.deobfuscator.api.asm.InsnContext; -import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; -import java.util.List; +import java.util.HashSet; import java.util.Map; +import java.util.Set; /** * Immutable match context. After matching process, the context is frozen by {@link MatchContext#freeze()} @@ -17,20 +17,20 @@ public class MatchContext { private final InsnContext insnContext; private final Map captures; - private final List collectedInsns; + private final Set collectedInsns; - private MatchContext(InsnContext insnContext, Map captures, List collectedInsns) { + private MatchContext(InsnContext insnContext, Map captures, Set collectedInsns) { this.insnContext = insnContext; this.captures = captures; this.collectedInsns = collectedInsns; } public static MatchContext of(InsnContext insnContext) { - return new MatchContext(insnContext, new HashMap<>(), new ArrayList<>()); + return new MatchContext(insnContext, new HashMap<>(), new HashSet<>()); } public MatchContext freeze() { - return new MatchContext(this.insnContext, Collections.unmodifiableMap(this.captures), Collections.unmodifiableList(this.collectedInsns)); + return new MatchContext(this.insnContext, Collections.unmodifiableMap(this.captures), Collections.unmodifiableSet(this.collectedInsns)); } /** @@ -40,12 +40,7 @@ public MatchContext freeze() { */ void merge(MatchContext other) { this.captures.putAll(other.captures); - for (AbstractInsnNode insn : other.collectedInsns) { - // Don't allow duplicates - if (this.collectedInsns.contains(insn)) continue; - - this.collectedInsns.add(insn); - } + this.collectedInsns.addAll(other.collectedInsns); } /** @@ -81,7 +76,7 @@ public Map captures() { /** * Collected instructions that matches this match and children matches */ - public List collectedInsns() { + public Set collectedInsns() { return collectedInsns; } diff --git a/deobfuscator-api/src/main/java/uwu/narumi/deobfuscator/api/asm/matcher/impl/FrameMatch.java b/deobfuscator-api/src/main/java/uwu/narumi/deobfuscator/api/asm/matcher/impl/FrameMatch.java new file mode 100644 index 00000000..3e072d23 --- /dev/null +++ b/deobfuscator-api/src/main/java/uwu/narumi/deobfuscator/api/asm/matcher/impl/FrameMatch.java @@ -0,0 +1,101 @@ +package uwu.narumi.deobfuscator.api.asm.matcher.impl; + +import org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.analysis.Frame; +import org.objectweb.asm.tree.analysis.OriginalSourceValue; +import uwu.narumi.deobfuscator.api.asm.matcher.Match; +import uwu.narumi.deobfuscator.api.asm.matcher.MatchContext; + +/** + * Match instruction from stack + */ +public class FrameMatch extends Match { + private final Match match; + private final FrameMatchOptions options; + + /** + * @param match A {@link Match} to match against that stack value + * @param options Options for the frame match + */ + private FrameMatch(Match match, FrameMatchOptions options) { + this.match = match; + this.options = options; + } + + public static FrameMatch stack(int stackValueIdx, Match match) { + return new FrameMatch(match, new StackFrameOptions(stackValueIdx, false)); + } + + public static FrameMatch stackOriginal(int stackValueIdx, Match match) { + return new FrameMatch(match, new StackFrameOptions(stackValueIdx, true)); + } + + public static FrameMatch localVariable(int localVariableIdx, Match match) { + return new FrameMatch(match, new LocalVariableFrameOptions(localVariableIdx)); + } + + @Override + protected boolean test(MatchContext context) { + if (context.insnContext().methodContext().frames() == null) { + throw new IllegalStateException("Got frameless method context"); + } + + if (context.frame() == null) { + // If we expect stack values, then frame can't be null + return false; + } + + // Get the source value + OriginalSourceValue sourceValue; + if (this.options instanceof StackFrameOptions stackFrameOptions) { + // Pop values from stack and match them + int index = context.frame().getStackSize() - (stackFrameOptions.stackValueIdx + 1); + if (index < 0) { + // If the stack value should exist but does not, then it does not match + return false; + } + + if (this.match instanceof SkipMatch) { + // Skip match earlier + return true; + } + + Frame frame = context.frame(); + sourceValue = frame.getStack(index); + if (stackFrameOptions.originalValue) { + sourceValue = sourceValue.originalSource; + } + } else if (this.options instanceof LocalVariableFrameOptions lvFrameOptions) { + if (this.match instanceof SkipMatch) { + // Skip match earlier + return true; + } + + Frame frame = context.frame(); + sourceValue = frame.getLocal(lvFrameOptions.localVariableIdx); + } else { + throw new IllegalStateException("Unknown frame match options"); + } + + if (!sourceValue.isOneWayProduced()) { + // We only want stack values that are one way produced + return false; + } + + AbstractInsnNode stackValueInsn = sourceValue.getProducer(); + return this.match.matchAndMerge(context.insnContext().of(stackValueInsn), context); + } + + sealed interface FrameMatchOptions permits StackFrameOptions, LocalVariableFrameOptions { + } + + /** + * @param stackValueIdx Index of the value in the stack, starting from the top of the stack, so '0' is the top value. + * @param originalValue + */ + record StackFrameOptions(int stackValueIdx, boolean originalValue) implements FrameMatchOptions { + } + + record LocalVariableFrameOptions(int localVariableIdx) implements FrameMatchOptions { + } +} diff --git a/deobfuscator-api/src/main/java/uwu/narumi/deobfuscator/api/asm/matcher/impl/StackMatch.java b/deobfuscator-api/src/main/java/uwu/narumi/deobfuscator/api/asm/matcher/impl/StackMatch.java deleted file mode 100644 index 432635d9..00000000 --- a/deobfuscator-api/src/main/java/uwu/narumi/deobfuscator/api/asm/matcher/impl/StackMatch.java +++ /dev/null @@ -1,72 +0,0 @@ -package uwu.narumi.deobfuscator.api.asm.matcher.impl; - -import org.objectweb.asm.tree.AbstractInsnNode; -import org.objectweb.asm.tree.analysis.Frame; -import org.objectweb.asm.tree.analysis.OriginalSourceValue; -import uwu.narumi.deobfuscator.api.asm.matcher.Match; -import uwu.narumi.deobfuscator.api.asm.matcher.MatchContext; - -/** - * Match instruction from stack - */ -public class StackMatch extends Match { - private final int stackValueIdx; - private final Match match; - private final boolean originalValue; - - /** - * @param stackValueIdx Index of the value in the stack, starting from the top of the stack, so '0' is the top value. - * @param match A {@link Match} to match against that stack value - */ - private StackMatch(int stackValueIdx, Match match, boolean originalValue) { - this.stackValueIdx = stackValueIdx; - this.match = match; - this.originalValue = originalValue; - } - - public static StackMatch of(int stackValueIdx, Match match) { - return new StackMatch(stackValueIdx, match, false); - } - - public static StackMatch ofOriginal(int stackValueIdx, Match match) { - return new StackMatch(stackValueIdx, match, true); - } - - @Override - protected boolean test(MatchContext context) { - if (context.insnContext().methodContext().frames() == null) { - throw new IllegalStateException("Got frameless method context"); - } - - if (context.frame() == null) { - // If we expect stack values, then frame can't be null - return false; - } - - // Pop values from stack and match them - int index = context.frame().getStackSize() - (this.stackValueIdx + 1); - if (index < 0) { - // If the stack value should exist but does not, then it does not match - return false; - } - - if (this.match instanceof SkipMatch) { - // Skip match earlier - return true; - } - - Frame frame = context.frame(); - OriginalSourceValue sourceValue = frame.getStack(index); - if (this.originalValue) { - sourceValue = sourceValue.originalSource; - } - - if (!sourceValue.isOneWayProduced()) { - // We only want stack values that are one way produced - return false; - } - - AbstractInsnNode stackValueInsn = sourceValue.getProducer(); - return this.match.matchAndMerge(context.insnContext().of(stackValueInsn), context); - } -} diff --git a/deobfuscator-api/src/main/java/uwu/narumi/deobfuscator/api/asm/matcher/impl/VarLoadMatch.java b/deobfuscator-api/src/main/java/uwu/narumi/deobfuscator/api/asm/matcher/impl/VarLoadMatch.java new file mode 100644 index 00000000..dfaed62e --- /dev/null +++ b/deobfuscator-api/src/main/java/uwu/narumi/deobfuscator/api/asm/matcher/impl/VarLoadMatch.java @@ -0,0 +1,39 @@ +package uwu.narumi.deobfuscator.api.asm.matcher.impl; + +import org.jetbrains.annotations.Nullable; +import org.objectweb.asm.tree.VarInsnNode; +import uwu.narumi.deobfuscator.api.asm.matcher.Match; +import uwu.narumi.deobfuscator.api.asm.matcher.MatchContext; + +public class VarLoadMatch extends Match { + private Match localStoreMatch = null; + + private VarLoadMatch() { + } + + public static VarLoadMatch of() { + return new VarLoadMatch(); + } + + /** + * Match local variable store instruction of this variable + */ + public VarLoadMatch localStoreMatch(@Nullable Match match) { + this.localStoreMatch = match; + return this; + } + + @Override + protected boolean test(MatchContext context) { + boolean matches = context.insnContext().insn().isVarLoad(); + + // Match local variable store instruction + if (matches && localStoreMatch != null) { + VarInsnNode varInsn = (VarInsnNode) context.insnContext().insn(); + + matches = FrameMatch.localVariable(varInsn.var, localStoreMatch).matchAndMerge(context.insnContext(), context); + } + + return matches; + } +} 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 b5891be9..ec8fbc39 100644 --- a/deobfuscator-impl/src/test/java/uwu/narumi/deobfuscator/TestDeobfuscation.java +++ b/deobfuscator-impl/src/test/java/uwu/narumi/deobfuscator/TestDeobfuscation.java @@ -1,6 +1,7 @@ package uwu.narumi.deobfuscator; import uwu.narumi.deobfuscator.core.other.composed.ComposedHP888Transformer; +import uwu.narumi.deobfuscator.core.other.composed.ComposedUnknownObf1Transformer; import uwu.narumi.deobfuscator.core.other.composed.ComposedZelixTransformer; import uwu.narumi.deobfuscator.core.other.composed.general.ComposedGeneralFlowTransformer; import uwu.narumi.deobfuscator.core.other.composed.general.ComposedPeepholeCleanTransformer; @@ -53,10 +54,11 @@ protected void registerAll() { .input(OutputType.SINGLE_CLASS, InputType.CUSTOM_CLASS, "JSR.class") .register(); - // Samples - test("Some flow obf sample") - .transformers(ComposedGeneralFlowTransformer::new) - .input(OutputType.SINGLE_CLASS, InputType.CUSTOM_CLASS, "FlowObfSample.class") + // Unknown obf 1 + // TODO: If you know the obfuscator used to obfuscate this class, you can make a PR which renames this test + test("Unknown obf 1") + .transformers(ComposedUnknownObf1Transformer::new) + .input(OutputType.MULTIPLE_CLASSES, InputType.CUSTOM_CLASS, "unknown/obf1") .register(); // Zelix diff --git a/deobfuscator-transformers/src/main/java/uwu/narumi/deobfuscator/core/other/composed/ComposedUnknownObf1Transformer.java b/deobfuscator-transformers/src/main/java/uwu/narumi/deobfuscator/core/other/composed/ComposedUnknownObf1Transformer.java new file mode 100644 index 00000000..e925e5be --- /dev/null +++ b/deobfuscator-transformers/src/main/java/uwu/narumi/deobfuscator/core/other/composed/ComposedUnknownObf1Transformer.java @@ -0,0 +1,21 @@ +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.impl.clean.LocalVariableNamesCleanTransformer; +import uwu.narumi.deobfuscator.core.other.impl.unknown.obf1.UnknownObf1_StringByteArrayTransformer; + +public class ComposedUnknownObf1Transformer extends ComposedTransformer { + public ComposedUnknownObf1Transformer() { + super( + // Remove local variables names + LocalVariableNamesCleanTransformer::new, + + // Fix flow + ComposedGeneralFlowTransformer::new, + + // Decrypt strings + UnknownObf1_StringByteArrayTransformer::new + ); + } +} diff --git a/deobfuscator-transformers/src/main/java/uwu/narumi/deobfuscator/core/other/composed/general/ComposedPeepholeCleanTransformer.java b/deobfuscator-transformers/src/main/java/uwu/narumi/deobfuscator/core/other/composed/general/ComposedPeepholeCleanTransformer.java index d7505156..58c9ab24 100644 --- a/deobfuscator-transformers/src/main/java/uwu/narumi/deobfuscator/core/other/composed/general/ComposedPeepholeCleanTransformer.java +++ b/deobfuscator-transformers/src/main/java/uwu/narumi/deobfuscator/core/other/composed/general/ComposedPeepholeCleanTransformer.java @@ -22,6 +22,8 @@ public ComposedPeepholeCleanTransformer() { UnUsedLabelCleanTransformer::new, UselessGotosCleanTransformer::new, + // Early pop clean (for correct unused var stores removal) + UselessPopCleanTransformer::new, // Pop unused local variables stores PopUnUsedLocalVariablesTransformer::new, // Remove useless POP instructions. This also cleans up garbage var stores from the PopUnUsedLocalVariablesTransformer diff --git a/deobfuscator-transformers/src/main/java/uwu/narumi/deobfuscator/core/other/impl/unknown/obf1/UnknownObf1_StringByteArrayTransformer.java b/deobfuscator-transformers/src/main/java/uwu/narumi/deobfuscator/core/other/impl/unknown/obf1/UnknownObf1_StringByteArrayTransformer.java new file mode 100644 index 00000000..171b4c8a --- /dev/null +++ b/deobfuscator-transformers/src/main/java/uwu/narumi/deobfuscator/core/other/impl/unknown/obf1/UnknownObf1_StringByteArrayTransformer.java @@ -0,0 +1,124 @@ +package uwu.narumi.deobfuscator.core.other.impl.unknown.obf1; + +import org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.LdcInsnNode; +import org.objectweb.asm.tree.VarInsnNode; +import uwu.narumi.deobfuscator.api.asm.MethodContext; +import uwu.narumi.deobfuscator.api.asm.matcher.Match; +import uwu.narumi.deobfuscator.api.asm.matcher.group.SequenceMatch; +import uwu.narumi.deobfuscator.api.asm.matcher.impl.InsnMatch; +import uwu.narumi.deobfuscator.api.asm.matcher.impl.MethodMatch; +import uwu.narumi.deobfuscator.api.asm.matcher.impl.NumberMatch; +import uwu.narumi.deobfuscator.api.asm.matcher.impl.OpcodeMatch; +import uwu.narumi.deobfuscator.api.asm.matcher.impl.FrameMatch; +import uwu.narumi.deobfuscator.api.asm.matcher.impl.VarLoadMatch; +import uwu.narumi.deobfuscator.api.transformer.Transformer; + +import java.util.HashSet; +import java.util.Set; + +/** + * Decrypts strings from byte arrays. + *

+ * Transforms this: + *

+ * byte[] var6 = new byte[16];
+ * var6[5] = -38;
+ * var6[5] = 115;
+ * var6[8] = 110;
+ * var6[4] = 97;
+ * var6[15] = 110;
+ * var6[10] = 101;
+ * var6[9] = 82;
+ * var6[12] = 112;
+ * var6[11] = 115;
+ * var6[6] = 115;
+ * var6[14] = 119;
+ * var6[0] = 99;
+ * var6[3] = 112;
+ * var6[7] = 79;
+ * var6[1] = 111;
+ * var6[2] = 109;
+ * var6[13] = 97;
+ * String string = new String(var6);
+ * 
+ * + * Into this: + *
+ * String string = "compassOnRespawn";
+ * 
+ */ +public class UnknownObf1_StringByteArrayTransformer extends Transformer { + + private static final Match STRING_BYTE_ARRAY_CONSTRUCTOR = MethodMatch.invokeSpecial() + // INVOKESPECIAL - new String(byte[]) + .owner("java/lang/String").name("").desc("([B)V").capture("string-constructor") + // ALOAD - Load variable + .and(FrameMatch.stack(0, VarLoadMatch.of() + // ASTORE - Store array into variable + .localStoreMatch(OpcodeMatch.of(ASTORE).capture("store-array") + // NEWARRAY + .and(FrameMatch.stack(0, OpcodeMatch.of(NEWARRAY) + // Number - Array length + .and(FrameMatch.stack(0, NumberMatch.numInteger().capture("array-length"))) + )) + ) + .and(FrameMatch.stack(0, OpcodeMatch.of(DUP) + .and(FrameMatch.stack(0, OpcodeMatch.of(NEW))) + )) + )); + + @Override + protected void transform() throws Exception { + scopedClasses().forEach(classWrapper -> classWrapper.methods().forEach(methodNode -> { + MethodContext methodContext = MethodContext.framed(classWrapper, methodNode); + + STRING_BYTE_ARRAY_CONSTRUCTOR.findAllMatches(methodContext).forEach(matchContext -> { + Set collectedInsns = new HashSet<>(matchContext.collectedInsns()); + + AbstractInsnNode stringConstructorInsn = matchContext.captures().get("string-constructor").insn(); + VarInsnNode storeArrayInsn = (VarInsnNode) matchContext.captures().get("store-array").insn(); + int arrayLength = matchContext.captures().get("array-length").insn().asInteger(); + + // Get byte array + byte[] bytes = getByteArray(storeArrayInsn, arrayLength, collectedInsns, methodContext); + + // Pass byte array to build a string + String deobfString = new String(bytes); + + // Place deobfuscated string into LDC instruction + methodNode.instructions.insert(stringConstructorInsn, new LdcInsnNode(deobfString)); + + // Remove all obfuscated instructions + collectedInsns.forEach(methodNode.instructions::remove); + + markChange(); + }); + })); + } + + /** + * Build a byte array from instructions + */ + private byte[] getByteArray(VarInsnNode storeArrayInsn, int arrayLength, Set collectedInsns, MethodContext methodContext) { + // TODO: Maybe convert this to use FrameMatch? + Match storeByteToArray = SequenceMatch.of( + VarLoadMatch.of().localStoreMatch(InsnMatch.of(storeArrayInsn)), + NumberMatch.numInteger().capture("index"), + NumberMatch.of().capture("value"), + OpcodeMatch.of(BASTORE) + ); + + // Build byte array + byte[] bytes = new byte[arrayLength]; + storeByteToArray.findAllMatches(methodContext).forEach(matchContext -> { + int index = matchContext.captures().get("index").insn().asInteger(); + byte value = (byte) matchContext.captures().get("value").insn().asInteger(); + + bytes[index] = value; + collectedInsns.addAll(matchContext.collectedInsns()); + }); + + return bytes; + } +} diff --git a/deobfuscator-transformers/src/main/java/uwu/narumi/deobfuscator/core/other/impl/zkm/ZelixLongEncryptionMPCTransformer.java b/deobfuscator-transformers/src/main/java/uwu/narumi/deobfuscator/core/other/impl/zkm/ZelixLongEncryptionMPCTransformer.java index 62ca0abf..1b49e62e 100644 --- a/deobfuscator-transformers/src/main/java/uwu/narumi/deobfuscator/core/other/impl/zkm/ZelixLongEncryptionMPCTransformer.java +++ b/deobfuscator-transformers/src/main/java/uwu/narumi/deobfuscator/core/other/impl/zkm/ZelixLongEncryptionMPCTransformer.java @@ -12,7 +12,7 @@ import uwu.narumi.deobfuscator.api.asm.matcher.impl.FieldMatch; import uwu.narumi.deobfuscator.api.asm.matcher.impl.MethodMatch; import uwu.narumi.deobfuscator.api.asm.matcher.impl.NumberMatch; -import uwu.narumi.deobfuscator.api.asm.matcher.impl.StackMatch; +import uwu.narumi.deobfuscator.api.asm.matcher.impl.FrameMatch; import uwu.narumi.deobfuscator.api.context.Context; import uwu.narumi.deobfuscator.api.execution.SandBox; import uwu.narumi.deobfuscator.api.helper.AsmHelper; @@ -58,15 +58,15 @@ public class ZelixLongEncryptionMPCTransformer extends Transformer { private static final Match DECRYPT_LONG_MATCHER = FieldMatch.putStatic().desc("J") // Decrypt - .and(StackMatch.of(0, MethodMatch.invokeInterface().desc("(J)J") - .and(StackMatch.of(0, NumberMatch.numLong().capture("decrypt-key"))) // Decrypt key + .and(FrameMatch.stack(0, MethodMatch.invokeInterface().desc("(J)J") + .and(FrameMatch.stack(0, NumberMatch.numLong().capture("decrypt-key"))) // Decrypt key // Create decrypter - .and(StackMatch.of(1, MethodMatch.invokeStatic().and(Match.of(context -> + .and(FrameMatch.stack(1, MethodMatch.invokeStatic().and(Match.of(context -> ((MethodInsnNode) context.insn()).desc.startsWith("(JJLjava/lang/Object;)"))).capture("create-decrypter-method") - .and(StackMatch.of(0, MethodMatch.invokeVirtual().and(StackMatch.of(0, MethodMatch.invokeStatic())))) // Class lookup - .and(StackMatch.of(1, NumberMatch.numLong().capture("key-2"))) // Key 2 - .and(StackMatch.of(2, NumberMatch.numLong().capture("key-1"))) // Key 1 + .and(FrameMatch.stack(0, MethodMatch.invokeVirtual().and(FrameMatch.stack(0, MethodMatch.invokeStatic())))) // Class lookup + .and(FrameMatch.stack(1, NumberMatch.numLong().capture("key-2"))) // Key 2 + .and(FrameMatch.stack(2, NumberMatch.numLong().capture("key-1"))) // Key 1 )) .capture("decrypt-method") )); diff --git a/deobfuscator-transformers/src/main/java/uwu/narumi/deobfuscator/core/other/impl/zkm/ZelixParametersTransformer.java b/deobfuscator-transformers/src/main/java/uwu/narumi/deobfuscator/core/other/impl/zkm/ZelixParametersTransformer.java index 73f1018d..0a9ef9ea 100644 --- a/deobfuscator-transformers/src/main/java/uwu/narumi/deobfuscator/core/other/impl/zkm/ZelixParametersTransformer.java +++ b/deobfuscator-transformers/src/main/java/uwu/narumi/deobfuscator/core/other/impl/zkm/ZelixParametersTransformer.java @@ -13,7 +13,7 @@ import uwu.narumi.deobfuscator.api.asm.matcher.impl.MethodMatch; import uwu.narumi.deobfuscator.api.asm.matcher.impl.NumberMatch; import uwu.narumi.deobfuscator.api.asm.matcher.impl.OpcodeMatch; -import uwu.narumi.deobfuscator.api.asm.matcher.impl.StackMatch; +import uwu.narumi.deobfuscator.api.asm.matcher.impl.FrameMatch; import uwu.narumi.deobfuscator.api.helper.AsmHelper; import uwu.narumi.deobfuscator.api.helper.MethodHelper; import uwu.narumi.deobfuscator.api.transformer.Transformer; @@ -59,11 +59,11 @@ public class ZelixParametersTransformer extends Transformer { return ((VarInsnNode) context.insn()).var == MethodHelper.getFirstParameterIdx(context.insnContext().methodNode()); })); - private static final Match OBJECT_ARRAY_ACCESS = StackMatch.of(0, OpcodeMatch.of(CHECKCAST).capture("cast") - .and(StackMatch.of(0, OpcodeMatch.of(AALOAD) - .and(StackMatch.of(0, NumberMatch.numInteger().capture("index") - .and(StackMatch.of(0, OpcodeMatch.of(DUP) - .and(StackMatch.ofOriginal(0, OBJECT_ARRAY_ALOAD.capture("load-array"))) + private static final Match OBJECT_ARRAY_ACCESS = FrameMatch.stack(0, OpcodeMatch.of(CHECKCAST).capture("cast") + .and(FrameMatch.stack(0, OpcodeMatch.of(AALOAD) + .and(FrameMatch.stack(0, NumberMatch.numInteger().capture("index") + .and(FrameMatch.stack(0, OpcodeMatch.of(DUP) + .and(FrameMatch.stackOriginal(0, OBJECT_ARRAY_ALOAD.capture("load-array"))) )) )) )) @@ -71,14 +71,14 @@ public class ZelixParametersTransformer extends Transformer { private static final Match OBJECT_ARRAY_VAR_USAGE = Match.of(ctx -> ctx.insn().isVarStore()).capture("var-store") .and( - StackMatch.of(0, MethodMatch.invokeVirtual().capture("to-primitive") // Converting to a primitive type + FrameMatch.stack(0, MethodMatch.invokeVirtual().capture("to-primitive") // Converting to a primitive type .and(OBJECT_ARRAY_ACCESS) ).or(OBJECT_ARRAY_ACCESS) ); private static final Match OBJECT_ARRAY_POP = OpcodeMatch.of(POP) .and( - StackMatch.ofOriginal(0, OBJECT_ARRAY_ALOAD.capture("load-array")) + FrameMatch.stackOriginal(0, OBJECT_ARRAY_ALOAD.capture("load-array")) ); @Override diff --git a/testData/compiled/custom-classes/FlowObfSample.class b/testData/compiled/custom-classes/unknown/obf1/IIIIIIIIlIlIIIIlIIlIIIIIIIIlIlIllllIIIlIIIlIIllIllllIIIIllIIIIllIIllllIIIIllllIIIIIIIllIllIIIlllIlIIllIlIIllIlIIIIIlIIIIIllllIlIIllIllllIIlIIIIIIlIllIlIIIIlIlIIlIIlllIIIIlIIlIIllIlIIIlIlIlIIIIllIlllll.class similarity index 100% rename from testData/compiled/custom-classes/FlowObfSample.class rename to testData/compiled/custom-classes/unknown/obf1/IIIIIIIIlIlIIIIlIIlIIIIIIIIlIlIllllIIIlIIIlIIllIllllIIIIllIIIIllIIllllIIIIllllIIIIIIIllIllIIIlllIlIIllIlIIllIlIIIIIlIIIIIllllIlIIllIllllIIlIIIIIIlIllIlIIIIlIlIIlIIlllIIIIlIIlIIllIlIIIlIlIlIIIIllIlllll.class diff --git a/testData/compiled/custom-classes/unknown/obf1/IIIIIllIlIIIlIIIlIIIIIlIIlIlIllIllIlllIlllllllllllIlIIIIIlIIlIllIlllIIllIllIlIIIlIlIIlllllIlIIllIIIllIlllllIIllIlllIIllIIIIlllllIlIlIlllIlIllIllllIIIIIlIlIIlIlIIlIIIIlllllllIllIlIIIlllIllIIlIIllIIIlII.class b/testData/compiled/custom-classes/unknown/obf1/IIIIIllIlIIIlIIIlIIIIIlIIlIlIllIllIlllIlllllllllllIlIIIIIlIIlIllIlllIIllIllIlIIIlIlIIlllllIlIIllIIIllIlllllIIllIlllIIllIIIIlllllIlIlIlllIlIllIllllIIIIIlIlIIlIlIIlIIIIlllllllIllIlIIIlllIllIIlIIllIIIlII.class new file mode 100644 index 00000000..45bd6bed Binary files /dev/null and b/testData/compiled/custom-classes/unknown/obf1/IIIIIllIlIIIlIIIlIIIIIlIIlIlIllIllIlllIlllllllllllIlIIIIIlIIlIllIlllIIllIllIlIIIlIlIIlllllIlIIllIIIllIlllllIIllIlllIIllIIIIlllllIlIlIlllIlIllIllllIIIIIlIlIIlIlIIlIIIIlllllllIllIlIIIlllIllIIlIIllIIIlII.class differ diff --git a/testData/results/custom-classes/unknown/obf1/IIIIIIIIlIlIIIIlIIlIIIIIIIIlIlIllllIIIlIIIlIIllIllllIIIIllIIIIllIIllllIIIIllllIIIIIIIllIllIIIlllIlIIllIlIIllIlIIIIIlIIIIIllllIlIIllIllllIIlIIIIIIlIllIlIIIIlIlIIlIIlllIIIIlIIlIIllIlIIIlIlIlIIIIllIlllll.dec b/testData/results/custom-classes/unknown/obf1/IIIIIIIIlIlIIIIlIIlIIIIIIIIlIlIllllIIIlIIIlIIllIllllIIIIllIIIIllIIllllIIIIllllIIIIIIIllIllIIIlllIlIIllIlIIllIlIIIIIlIIIIIllllIlIIllIllllIIlIIIIIIlIllIlIIIIlIlIIlIIlllIIIIlIIlIIllIlIIIlIlIlIIIIllIlllll.dec new file mode 100644 index 00000000..c4a2eb0d --- /dev/null +++ b/testData/results/custom-classes/unknown/obf1/IIIIIIIIlIlIIIIlIIlIIIIIIIIlIlIllllIIIlIIIlIIllIllllIIIIllIIIIllIIllllIIIIllllIIIIIIIllIllIIIlllIlIIllIlIIllIlIIIIIlIIIIIllllIlIIllIllllIIlIIIIIIlIllIlIIIIlIlIIlIIlllIIIIlIIlIIllIlIIIlIlIlIIIIllIlllll.dec @@ -0,0 +1,18 @@ +import org.bukkit.Bukkit; +import org.bukkit.event.Listener; + +public class IIIIIIIIlIlIIIIlIIlIIIIIIIIlIlIllllIIIlIIIlIIllIllllIIIIllIIIIllIIllllIIIIllllIIIIIIIllIllIIIlllIlIIllIlIIllIlIIIIIlIIIIIllllIlIIllIllllIIlIIIIIIlIllIlIIIIlIlIIlIIlllIIIIlIIlIIllIlIIIlIlIlIIIIllIlllll + implements Listener { + public static int lIIIIlllIlIIllIIIlllllIlllIIllIllIIlIIllIIIllIIlIllllIIIIllIIlIIIIlIllIIlllIllIllllIIIlllIllIllIlllIlllllIIlIIIlllllIIIlIlIllllIllllIllllIIlIIllIlIIllIIllIIlIllIIllllIlllIIIIlIIllIIIIIIIIllllIlIllllIl( + int var0 + ) { + Bukkit.getServer(); + Bukkit.getServer(); + Bukkit.getServer(); + Bukkit.getServer(); + Bukkit.getServer(); + Bukkit.getServer(); + Bukkit.getServer(); + return 0; + } +} diff --git a/testData/results/custom-classes/unknown/obf1/IIIIIllIlIIIlIIIlIIIIIlIIlIlIllIllIlllIlllllllllllIlIIIIIlIIlIllIlllIIllIllIlIIIlIlIIlllllIlIIllIIIllIlllllIIllIlllIIllIIIIlllllIlIlIlllIlIllIllllIIIIIlIlIIlIlIIlIIIIlllllllIllIlIIIlllIllIIlIIllIIIlII.dec b/testData/results/custom-classes/unknown/obf1/IIIIIllIlIIIlIIIlIIIIIlIIlIlIllIllIlllIlllllllllllIlIIIIIlIIlIllIlllIIllIllIlIIIlIlIIlllllIlIIllIIIllIlllllIIllIlllIIllIIIIlllllIlIlIlllIlIllIllllIIIIIlIlIIlIlIIlIIIIlllllllIllIlIIIlllIllIIlIIllIIIlII.dec new file mode 100644 index 00000000..c7cf1c60 --- /dev/null +++ b/testData/results/custom-classes/unknown/obf1/IIIIIllIlIIIlIIIlIIIIIlIIlIlIllIllIlllIlllllllllllIlIIIIIlIIlIllIlllIIllIllIlIIIlIlIIlllllIlIIllIIIllIlllllIIllIlllIIllIIIIlllllIlIlIlllIlIllIllllIIIIIlIlIIlIlIIlIIIIlllllllIllIlIIIlllIllIIlIIllIIIlII.dec @@ -0,0 +1,30 @@ +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerRespawnEvent; +import org.bukkit.inventory.ItemFlag; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +public class IIIIIllIlIIIlIIIlIIIIIlIIlIlIllIllIlllIlllllllllllIlIIIIIlIIlIllIlllIIllIllIlIIIlIlIIlllllIlIIllIIIllIlllllIIllIlllIIllIIIIlllllIlIlIlllIlIllIllllIIIIIlIlIIlIlIIlIIIIlllllllIllIlIIIlllIllIIlIIllIIIlII + implements Listener { + @EventHandler + public void onPlayerRespawn(PlayerRespawnEvent var1) { + Player var2 = var1.getPlayer(); + if (lIIlIIIllIIlIlllIIIIllllIIllllIlIlIIlIlllIIlIlIllIlIIIIlIllllIIIIIlllllIIllIIIllIIlllIIlllllIlIIIIIIlIIIIIllIIlllIlllIllIlIlllllIlIlllIIIlIllIIIlIlllIIIIIlllIIIIllIlllIlIlIllllIlIIIIllllIlIlIIlIIlIllI.IllIllIlIllIIIIlllIllIlIlIllIIllIlllllllllIlIIIIIIlllllllIIlIllllIIIlIllIllIlIIIIlllIlllIIlllIIIIIIIIIlIlllIlllIIlIllIllIIlIIllIIlllIIIlllIllIllIIllIlIllllllIIllllIllIIIlllIllllIIlllIIIlIlIIlllIIIIlIl + .getConfig() + .getBoolean("compassOnRespawn") + && !var2.getInventory().contains(Material.COMPASS)) { + ItemStack var3 = new ItemStack(Material.COMPASS, 1); + var3.addUnsafeEnchantment(Enchantment.VANISHING_CURSE, 1); + ItemMeta var4 = var3.getItemMeta(); + var4.setDisplayName(ChatColor.RED + "[" + ChatColor.AQUA + "" + ChatColor.BOLD + "Compass Tracker" + ChatColor.RESET + "" + ChatColor.RED + "]"); + var4.addItemFlags(new ItemFlag[]{ItemFlag.HIDE_ENCHANTS}); + var3.setItemMeta(var4); + var2.getInventory().addItem(new ItemStack[]{var3}); + } + } +}