From e81e46c68c5ea389e179ec134bc5252cd73e0797 Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 25 Oct 2015 19:11:25 -0400 Subject: [PATCH] First modarith test --- .../deobfuscators/arithmetic/ModArith.java | 82 ++++++++++--------- .../arithmetic/ModArithTest.java | 61 ++++++++++++++ 2 files changed, 106 insertions(+), 37 deletions(-) create mode 100644 src/test/java/net/runelite/deob/deobfuscators/arithmetic/ModArithTest.java diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java index 5f58bd289c..a3a086e95d 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java @@ -68,7 +68,6 @@ public class ModArith implements Deobfuscator outer: for (InstructionContext ctx : f.getInstructions()) { - // detect field = constant if (ctx.getInstruction() instanceof SetFieldInstruction) { SetFieldInstruction sfi = (SetFieldInstruction) ctx.getInstruction(); @@ -83,6 +82,7 @@ public class ModArith implements Deobfuscator { int it = ldc.getConstantAsInt(); if (DMath.isBig(it)) + // field = constant return true; } } @@ -111,12 +111,14 @@ public class ModArith implements Deobfuscator { int i = pci.getConstantAsInt(); if (DMath.isBig(i)) + // field = constant * not other field return true; } } } } } + // field * imul if (!(ctx.getInstruction() instanceof IMul)) continue; @@ -179,11 +181,12 @@ public class ModArith implements Deobfuscator return false; } - static class numgs { + static class AssociatedConstant + { int value; boolean other; } - private MultiValueMap values2 = new MultiValueMap(); + private MultiValueMap constants = new MultiValueMap(); private void findUses2() { @@ -202,7 +205,7 @@ public class ModArith implements Deobfuscator continue; List l = this.getInsInExpr(ctx, new HashSet()); - boolean other = false; + boolean other = false; // check if this contains another field for (InstructionContext i : l) { if (i.getInstruction() instanceof InvokeInstruction) @@ -225,10 +228,10 @@ public class ModArith implements Deobfuscator LDC_W w = (LDC_W) i.getInstruction(); if (w.getConstant().getObject() instanceof Integer) { - numgs n = new numgs(); + AssociatedConstant n = new AssociatedConstant(); n.value = w.getConstantAsInt(); n.other = other; - values2.put(fi.getMyField(), n); + constants.put(fi.getMyField(), n); } } } @@ -238,7 +241,6 @@ public class ModArith implements Deobfuscator private void findUses() { - // XXX Here needs to be able pick up setters like ield489 -= -2129182073, and also constant setters for (Frame f : execution.processedFrames) for (InstructionContext ctx : f.getInstructions()) { @@ -272,6 +274,7 @@ public class ModArith implements Deobfuscator if (value == 1 || value == 0) continue; + // field * constant constantGetters.put(field, value); } else if (ctx.getInstruction() instanceof SetFieldInstruction) @@ -294,6 +297,7 @@ public class ModArith implements Deobfuscator int i = ldc.getConstantAsInt(); if (DMath.isBig(i)) + // field = constant constantSetters.put(field, i); } } @@ -324,12 +328,13 @@ public class ModArith implements Deobfuscator if (value2 == 1 || value2 == 0) continue; + // field = something * constant constantSetters.put(field, value2); } } } - private Pair guess2(Field field, Collection col, Collection constants) + private Pair guess(Field field, Collection constants) { // multiply each by each, // lowest number wins @@ -411,16 +416,16 @@ public class ModArith implements Deobfuscator } } - Boolean g = isGetterOrSetter(field, true, col, s1), - g2 = isGetterOrSetter(field, true, col, s2); + boolean g = isGetterOrSetter(field, true, s1), + g2 = isGetterOrSetter(field, true, s2); - if (g == null || g2 == null || g == g2) + if (g == g2) { - g = isGetterOrSetter(field, false, col, s1); - g2 = isGetterOrSetter(field, false, col, s2); + g = isGetterOrSetter(field, false, s1); + g2 = isGetterOrSetter(field, false, s2); } - if (g == null || g2 == null || g == g2) + if (g == g2) System.out.println("BAD " + field.getName() + " " + s1 + " * " + s2 + " = " + smallest + " " + g + " " + g2); else { @@ -442,7 +447,8 @@ public class ModArith implements Deobfuscator return null; } - private Boolean isGetterOrSetter(Field field, boolean getter, Collection col, int value) + // figure out if value is a getter or setter + private boolean isGetterOrSetter(Field field, boolean getter, int value) { Collection c; if (getter) @@ -469,6 +475,7 @@ public class ModArith implements Deobfuscator return false; } + // remove duplicates from a collection private void removeDupes(Collection in) { Set set = new HashSet(); @@ -491,31 +498,32 @@ public class ModArith implements Deobfuscator for (ClassFile cf : group.getClasses()) for (Field f : cf.getFields().getFields()) { - Collection col = values2.getCollection(f); + Collection col = constants.getCollection(f); // all constants in instructions associated with the field if (col == null) continue; - { - Collection col2 = col.stream().filter(i -> DMath.isBig(i.value)).collect(Collectors.toList()); - - Collection noOther = col2.stream().filter(i -> !i.other).map(i -> i.value).collect(Collectors.toList()); - Collection other = col2.stream().filter(i -> i.other).map(i -> i.value).collect(Collectors.toList()); - other.addAll(noOther); + // filter out non big ones + Collection col2 = col.stream().filter(i -> DMath.isBig(i.value)).collect(Collectors.toList()); - removeDupes(noOther); - removeDupes(other); - - if (!isFieldObfuscated(execution, f)) - continue; - - Pair p = this.guess2(f, null, noOther); - if (p == null) - p = this.guess2(f, null, other); - - if (p != null) - { - pairs.add(p); - } + // filer out ones that have another field in the expression + Collection noOther = col2.stream().filter(i -> !i.other).map(i -> i.value).collect(Collectors.toList()); + Collection other = col2.stream().filter(i -> i.other).map(i -> i.value).collect(Collectors.toList()); + other.addAll(noOther); + + removeDupes(noOther); + removeDupes(other); + + if (!isFieldObfuscated(execution, f)) + continue; + + // guess with constants not associated with other fields + Pair p = this.guess(f, noOther); + if (p == null) + p = this.guess(f, other); // fall back to all constants + + if (p != null) + { + pairs.add(p); } } } @@ -590,7 +598,7 @@ public class ModArith implements Deobfuscator pairs.clear(); constantGetters.clear();; constantSetters.clear(); - values2.clear(); + constants.clear(); execution = new Execution(group); execution.populateInitialMethods(); diff --git a/src/test/java/net/runelite/deob/deobfuscators/arithmetic/ModArithTest.java b/src/test/java/net/runelite/deob/deobfuscators/arithmetic/ModArithTest.java new file mode 100644 index 0000000000..cda585d0b9 --- /dev/null +++ b/src/test/java/net/runelite/deob/deobfuscators/arithmetic/ModArithTest.java @@ -0,0 +1,61 @@ +package net.runelite.deob.deobfuscators.arithmetic; + +import java.io.DataInputStream; +import java.io.IOException; +import java.io.InputStream; +import net.runelite.deob.ClassFile; +import net.runelite.deob.ClassGroup; +import net.runelite.deob.Deobfuscator; +import net.runelite.deob.attributes.Code; +import net.runelite.deob.attributes.code.Instruction; +import net.runelite.deob.attributes.code.Instructions; +import net.runelite.deob.attributes.code.instructions.LDC_W; +import org.junit.Assert; +import org.junit.Test; + +class TestClass +{ + private static int dummy(Object... args) { return 0; } + + public int field1051 = -1611704481; + + public void test() + { + if(-1 != this.field1051 * 1928543073) + { + dummy(this.field1051 * 1928543073); + this.field1051 = dummy() * 1611704481; + } + } +} + +public class ModArithTest +{ + @Test + public void test() throws IOException + { + InputStream in = this.getClass().getClassLoader().getResourceAsStream("net/runelite/deob/deobfuscators/arithmetic/TestClass.class"); + Assert.assertNotNull(in); + + ClassGroup group = new ClassGroup(); + + ClassFile cf = new ClassFile(group, new DataInputStream(in)); + group.addClass(cf); + + ModArith d1 = new ModArith(); + d1.run(group); + d1.runOnce(); + + Deobfuscator d2 = new MultiplicationDeobfuscator(); + d2.run(group); + + Code code = cf.findMethod("test").getCode(); + Instructions instructions = code.getInstructions(); + for (Instruction i : instructions.getInstructions()) + if (i instanceof LDC_W) + { + LDC_W ldc = (LDC_W) i; + Assert.assertFalse(DMath.isBig(ldc.getConstantAsInt())); + } + } +}