Skip to content

Commit

Permalink
Merge pull request #80 from EpicPlayerA10/fix/method-matcher
Browse files Browse the repository at this point in the history
Fix method matcher wrongly matching method names
  • Loading branch information
narumii authored Aug 26, 2024
2 parents 02210e9 + f054a3d commit 5693cdb
Show file tree
Hide file tree
Showing 9 changed files with 130 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public boolean test(AbstractInsnNode node) {
return node instanceof MethodInsnNode
&& (opcode == -1 || node.getOpcode() == opcode)
&& (owner == null || ((MethodInsnNode) node).owner.equals(owner))
&& (name == null || Arrays.binarySearch(name, ((MethodInsnNode) node).name) != -1)
&& (name == null || Arrays.binarySearch(name, ((MethodInsnNode) node).name) >= 0)
&& (desc == null || ((MethodInsnNode) node).desc.equals(desc));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ protected void registerAll() {
register("Simple flow obfuscation", InputType.JAVA_CODE, List.of(ComposedGeneralFlowTransformer::new), "TestSimpleFlowObfuscation");
register("Universal Number Transformer", InputType.JAVA_CODE, List.of(UniversalNumberTransformer::new), "TestUniversalNumberTransformer");
register("Inline static fields", InputType.JAVA_CODE, List.of(InlineStaticFieldTransformer::new), "TestInlineStaticFields");
// TODO: Account for static field modification
register("Inline static fields with modification", InputType.JAVA_CODE, List.of(InlineStaticFieldTransformer::new), "TestInlineStaticFieldsWithModification");

// Samples
// TODO: Deobfuscate switches
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
package uwu.narumi.deobfuscator.core.other.composed;

import uwu.narumi.deobfuscator.api.transformer.ComposedTransformer;
import uwu.narumi.deobfuscator.core.other.impl.clean.InvalidMethodCleanTransformer;
import uwu.narumi.deobfuscator.core.other.impl.clean.PeepholeCleanTransformer;
import uwu.narumi.deobfuscator.core.other.impl.clean.LineNumberCleanTransformer;
import uwu.narumi.deobfuscator.core.other.impl.clean.peephole.DeadCodeCleanTransformer;
import uwu.narumi.deobfuscator.core.other.impl.clean.peephole.UnUsedLabelCleanTransformer;
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.universal.UniversalNumberTransformer;
Expand All @@ -15,9 +13,7 @@ public class ComposedGeneralFlowTransformer extends ComposedTransformer {
public ComposedGeneralFlowTransformer() {
super(
// Preparation
DeadCodeCleanTransformer::new,
LineNumberCleanTransformer::new,
UnUsedLabelCleanTransformer::new,
InvalidMethodCleanTransformer::new,
() -> new InlineStaticFieldTransformer(true, true),
InlineLocalVariablesTransformer::new,

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package uwu.narumi.deobfuscator.core.other.impl.clean;

import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.analysis.Analyzer;
import org.objectweb.asm.tree.analysis.AnalyzerException;
import org.objectweb.asm.tree.analysis.BasicInterpreter;
import uwu.narumi.deobfuscator.api.asm.ClassWrapper;
import uwu.narumi.deobfuscator.api.context.Context;
import uwu.narumi.deobfuscator.api.transformer.Transformer;

/**
* Remove invalid methods. WARNING: If some transformer will produce invalid bytecode in methods, this transformer will remove them.
*/
public class InvalidMethodCleanTransformer extends Transformer {
private boolean changed = false;

@Override
protected boolean transform(ClassWrapper scope, Context context) throws Exception {
context.classes(scope).forEach(classWrapper -> {
var iterator = classWrapper.methods().iterator();
while (iterator.hasNext()) {
MethodNode methodNode = iterator.next();

Analyzer<?> analyzer = new Analyzer<>(new BasicInterpreter());
try {
analyzer.analyze(classWrapper.name(), methodNode);
} catch (AnalyzerException e) {
// Remove invalid method
LOGGER.warn("Found invalid method: {}#{}{}. Removing...", classWrapper.name(), methodNode.name, methodNode.desc);
iterator.remove();
changed = true;
}
}
});

return changed;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,34 +15,27 @@ public class DeadCodeCleanTransformer extends Transformer {

@Override
protected boolean transform(ClassWrapper scope, Context context) throws Exception {
context.classes(scope).forEach(classWrapper -> {
var iterator = classWrapper.methods().iterator();
while (iterator.hasNext()) {
MethodNode methodNode = iterator.next();

Analyzer<?> analyzer = new Analyzer<>(new BasicInterpreter());
try {
analyzer.analyze(classWrapper.name(), methodNode);
} catch (AnalyzerException e) {
// Remove invalid method
LOGGER.warn("Found invalid method: {}#{}{}. Removing...", classWrapper.name(), methodNode.name, methodNode.desc);
iterator.remove();
return;
}
Frame<?>[] frames = analyzer.getFrames();
AbstractInsnNode[] insns = methodNode.instructions.toArray();
for (int i = 0; i < frames.length; i++) {
AbstractInsnNode insn = insns[i];
context.classes(scope).forEach(classWrapper -> classWrapper.methods().forEach(methodNode -> {
Analyzer<?> analyzer = new Analyzer<>(new BasicInterpreter());
try {
analyzer.analyze(classWrapper.name(), methodNode);
} catch (AnalyzerException e) {
// Skip invalid methods
return;
}
Frame<?>[] frames = analyzer.getFrames();
AbstractInsnNode[] insns = methodNode.instructions.toArray();
for (int i = 0; i < frames.length; i++) {
AbstractInsnNode insn = insns[i];

// If frame is null then it means that the code is unreachable
if (frames[i] == null && insn.getType() != AbstractInsnNode.LABEL) {
methodNode.instructions.remove(insn);
insns[i] = null;
changed = true;
}
// If frame is null then it means that the code is unreachable
if (frames[i] == null && insn.getType() != AbstractInsnNode.LABEL) {
methodNode.instructions.remove(insn);
insns[i] = null;
changed = true;
}
}
});
}));

return changed;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package uwu.narumi.deobfuscator.core.other.impl.clean.peephole;

import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.IincInsnNode;
import org.objectweb.asm.tree.VarInsnNode;
import org.objectweb.asm.tree.analysis.Frame;
import org.objectweb.asm.tree.analysis.OriginalSourceValue;
Expand All @@ -27,11 +28,18 @@ protected boolean transform(ClassWrapper scope, Context context) throws Exceptio

// Find all local variables in use
for (AbstractInsnNode insn : methodNode.instructions.toArray()) {
if (insn instanceof VarInsnNode varInsnNode && insn.isVarLoad()) {
if ((insn instanceof VarInsnNode && !insn.isVarStore()) || insn instanceof IincInsnNode) {
Frame<OriginalSourceValue> frame = frames.get(insn);
if (frame == null) return;

OriginalSourceValue localVariableSourceValue = frame.getLocal(varInsnNode.var);
int varIndex;
if (insn instanceof VarInsnNode varInsnNode) {
varIndex = varInsnNode.var;
} else {
varIndex = ((IincInsnNode) insn).var;
}

OriginalSourceValue localVariableSourceValue = frame.getLocal(varIndex);
for (AbstractInsnNode sourceInsn : localVariableSourceValue.insns) {
// Save var stores in use
if (sourceInsn.isVarStore()) {
Expand Down
6 changes: 3 additions & 3 deletions testData/results/java/TestInlineStaticFields.dec
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ public class TestInlineStaticFields {
public static boolean TEST3 = true;

public static void test() {
byte var10001 = 123;
String var10003 = "placki";
boolean var10005 = true;
System.out.println(123);
System.out.println("placki");
System.out.println(true);
}

public static void modifyStatic() {
Expand Down
28 changes: 28 additions & 0 deletions testData/results/java/TestInlineStaticFieldsWithModification.dec
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import java.io.File;

public class TestInlineStaticFieldsWithModification {
private static final char SYSTEM_SEPARATOR = File.separatorChar;
private static final char OTHER_SEPARATOR;

private static int getAdsCriticalOffset(String fileName) {
int offset1 = fileName.lastIndexOf(SYSTEM_SEPARATOR);
int offset2 = fileName.lastIndexOf(92);
if (offset1 == -1) {
return offset2 == -1 ? 0 : offset2 + 1;
} else {
return offset2 == -1 ? offset1 + 1 : Math.max(offset1, offset2) + 1;
}
}

static boolean isSystemWindows() {
return SYSTEM_SEPARATOR == '\\';
}

static {
if (isSystemWindows()) {
OTHER_SEPARATOR = '/';
} else {
OTHER_SEPARATOR = '\\';
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import java.io.File;

public class TestInlineStaticFieldsWithModification {
private static final char SYSTEM_SEPARATOR = File.separatorChar;
private static final char OTHER_SEPARATOR;

private static int getAdsCriticalOffset(String fileName) {
int offset1 = fileName.lastIndexOf(SYSTEM_SEPARATOR);
int offset2 = fileName.lastIndexOf(OTHER_SEPARATOR);
if (offset1 == -1) {
return offset2 == -1 ? 0 : offset2 + 1;
} else {
return offset2 == -1 ? offset1 + 1 : Math.max(offset1, offset2) + 1;
}
}

static {
if (isSystemWindows()) {
OTHER_SEPARATOR = '/';
} else {
OTHER_SEPARATOR = '\\';
}
}

static boolean isSystemWindows() {
return SYSTEM_SEPARATOR == '\\';
}
}

0 comments on commit 5693cdb

Please sign in to comment.