From 99985d7d6f6223a7ad38a9c9995dfd1bdd822813 Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 11 Oct 2015 19:38:36 -0400 Subject: [PATCH] class172/field2976 passed to invoke is not simplified --- src/main/java/net/runelite/deob/Field.java | 23 +++++ src/main/java/net/runelite/deob/Fields.java | 5 ++ src/main/java/net/runelite/deob/Method.java | 10 ++- .../runelite/deob/attributes/Attributes.java | 5 ++ .../code/instructions/GetStatic.java | 7 ++ .../code/instructions/InvokeStatic.java | 7 ++ .../deob/deobfuscators/arithmetic/DMath.java | 5 +- .../deobfuscators/arithmetic/ModArith.java | 83 ++++++++++++++++-- .../net/runelite/deob/ClassGroupFactory.java | 20 +++++ .../MultiplicationDeobfuscatorTest.java | 87 +++++++++++++++++-- 10 files changed, 237 insertions(+), 15 deletions(-) diff --git a/src/main/java/net/runelite/deob/Field.java b/src/main/java/net/runelite/deob/Field.java index c9f2bfd3a1..05bb4aeff5 100644 --- a/src/main/java/net/runelite/deob/Field.java +++ b/src/main/java/net/runelite/deob/Field.java @@ -9,6 +9,7 @@ import java.io.DataOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Objects; +import net.runelite.deob.pool.NameAndType; public class Field { @@ -41,6 +42,15 @@ public class Field attributes = new Attributes(this, is); } + public Field(Fields fields, String name, Type type) + { + this.fields = fields; + this.name = name; + this.type = type; + + attributes = new Attributes(this); + } + public void write(DataOutputStream out) throws IOException { ConstantPool pool = fields.getClassFile().getPool(); @@ -70,6 +80,11 @@ public class Field { return (accessFlags & ACC_STATIC) != 0; } + + public void setStatic() + { + accessFlags |= ACC_STATIC; + } public String getName() { @@ -95,6 +110,14 @@ public class Field { return attributes; } + + public net.runelite.deob.pool.Field getPoolField() + { + return new net.runelite.deob.pool.Field( + new net.runelite.deob.pool.Class(this.getFields().getClassFile().getName()), + new NameAndType(this.getName(), this.getType()) + ); + } @Override public int hashCode() diff --git a/src/main/java/net/runelite/deob/Fields.java b/src/main/java/net/runelite/deob/Fields.java index 471eaaf9a7..d363dabfc9 100644 --- a/src/main/java/net/runelite/deob/Fields.java +++ b/src/main/java/net/runelite/deob/Fields.java @@ -40,6 +40,11 @@ public class Fields { return classFile; } + + public void addField(Field field) + { + fields.add(field); + } public List getFields() { diff --git a/src/main/java/net/runelite/deob/Method.java b/src/main/java/net/runelite/deob/Method.java index e32c63d51b..77a2833c83 100644 --- a/src/main/java/net/runelite/deob/Method.java +++ b/src/main/java/net/runelite/deob/Method.java @@ -145,5 +145,13 @@ public class Method } return list; - } + } + + public net.runelite.deob.pool.Method getPoolMethod() + { + return new net.runelite.deob.pool.Method( + new net.runelite.deob.pool.Class(this.getMethods().getClassFile().getName()), + new NameAndType(this.getName(), this.getDescriptor()) + ); + } } diff --git a/src/main/java/net/runelite/deob/attributes/Attributes.java b/src/main/java/net/runelite/deob/attributes/Attributes.java index be8c8a816c..b76cf0d24c 100644 --- a/src/main/java/net/runelite/deob/attributes/Attributes.java +++ b/src/main/java/net/runelite/deob/attributes/Attributes.java @@ -37,6 +37,11 @@ public class Attributes load(is); } + + public Attributes(Field f) + { + field = f; + } public Attributes(Method m) { diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/GetStatic.java b/src/main/java/net/runelite/deob/attributes/code/instructions/GetStatic.java index 3cd81d4496..7299357251 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/GetStatic.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/GetStatic.java @@ -29,6 +29,13 @@ public class GetStatic extends Instruction implements GetFieldInstruction super(instructions, type, pc); } + public GetStatic(Instructions instructions, Field field) + { + super(instructions, InstructionType.GETSTATIC, -1); + + this.field = field; + } + @Override public void load(DataInputStream is) throws IOException { diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/InvokeStatic.java b/src/main/java/net/runelite/deob/attributes/code/instructions/InvokeStatic.java index 5d434e9793..d3bc166584 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/InvokeStatic.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/InvokeStatic.java @@ -33,6 +33,13 @@ public class InvokeStatic extends Instruction implements InvokeInstruction super(instructions, type, pc); } + public InvokeStatic(Instructions instructions, Method method) + { + super(instructions, InstructionType.INVOKESTATIC, -1); + + this.method = method; + } + @Override public void load(DataInputStream is) throws IOException { diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/DMath.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/DMath.java index 84496a5c93..3fe017b9c2 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/DMath.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/DMath.java @@ -35,6 +35,9 @@ public class DMath public static boolean isBig(int val) { - return (val & 0xFFF00000) != 0; + if ((val & 0x80000000) != 0) + val = ~val + 1; + + return (val & 0x7FF00000) != 0; } } 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 82140b32ff..7be0b2f06a 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java @@ -37,6 +37,76 @@ public class ModArith implements Deobfuscator private List pairs = new ArrayList<>(); private Set deobfuscatedFields = new HashSet<>(); + private List getInsInExpr(InstructionContext ctx, Set set) + { + List l = new ArrayList<>(); + + if (ctx == null || set.contains(ctx.getInstruction())) + return l; + + set.add(ctx.getInstruction()); + + l.add(ctx); + + for (StackContext s : ctx.getPops()) + l.addAll(getInsInExpr(s.getPushed(), set)); + for (StackContext s : ctx.getPushes()) + for (InstructionContext i : s.getPopped()) + l.addAll(getInsInExpr(i, set)); + + return l; + } + + private boolean isFieldObfuscated(Execution e, Field field) + { + // field isn't obfuscated if there are no usages with big constants and no other fields + + for (Frame f : execution.processedFrames) + outer: + for (InstructionContext ctx : f.getInstructions()) + { + if (!(ctx.getInstruction() instanceof FieldInstruction)) + continue; + + FieldInstruction fi = (FieldInstruction) ctx.getInstruction(); + + if (fi.getMyField() != field) + continue; + + List ins = getInsInExpr(ctx, new HashSet()); + + // continue if expr contains another ins + for (InstructionContext i : ins) + { + if (i.getInstruction() instanceof FieldInstruction) + { + FieldInstruction ifi = (FieldInstruction) i.getInstruction(); + + if (ifi.getMyField() != field) + continue outer; + } + } + + // find big constant + for (InstructionContext i : ins) + { + if (i.getInstruction() instanceof LDC_W) + { + LDC_W ldc = (LDC_W) i.getInstruction(); + if (ldc.getConstant().getObject() instanceof Integer) + { + int value = ldc.getConstantAsInt(); + + if (DMath.isBig(value)) + return true; + } + } + } + } + + return false; + } + private List findAssocConstants(Field field, InstructionContext ctx) throws OtherFieldException { // starts with ctx = setfield @@ -97,11 +167,6 @@ public class ModArith implements Deobfuscator if (field == null) continue; - if (field.getName().equals("field2201")) - { - int k=7; - } - int value = (int) pc.getConstant().getObject(); if (value == 1 || value == 0) @@ -302,7 +367,7 @@ public class ModArith implements Deobfuscator Collection getters = constantGetters.getCollection(f), setters = constantSetters.getCollection(f); - if (f.getName().equals("field551")) + if (f.getName().equals("field2976")) { int k=5; } @@ -322,6 +387,12 @@ public class ModArith implements Deobfuscator if (answer == null) continue; + if (!this.isFieldObfuscated(execution, f)) + { + System.out.println("Skipping field " + f.getName() + " which isnt obfuscated"); + continue; + } + answer.field = f; pairs.add(answer); } diff --git a/src/test/java/net/runelite/deob/ClassGroupFactory.java b/src/test/java/net/runelite/deob/ClassGroupFactory.java index 16fd6195ed..f9553259e6 100644 --- a/src/test/java/net/runelite/deob/ClassGroupFactory.java +++ b/src/test/java/net/runelite/deob/ClassGroupFactory.java @@ -2,7 +2,10 @@ package net.runelite.deob; import net.runelite.deob.attributes.Attributes; import net.runelite.deob.attributes.Code; +import net.runelite.deob.attributes.code.Instructions; +import net.runelite.deob.attributes.code.instructions.VReturn; import net.runelite.deob.signature.Signature; +import net.runelite.deob.signature.Type; public class ClassGroupFactory { @@ -15,6 +18,11 @@ public class ClassGroupFactory cf.setSuperName("java/lang/Object"); group.addClass(cf); + Fields fields = cf.getFields(); + Field field = new Field(fields, "field", new Type("I")); + field.setStatic(); + fields.addField(field); + Methods methods = cf.getMethods(); Method method = new Method(methods, "func", new Signature("()V")); method.setStatic(); @@ -25,6 +33,18 @@ public class ClassGroupFactory Code code = new Code(methodAttributes); methodAttributes.addAttribute(code); + method = new Method(methods, "func2", new Signature("(III)V")); + method.setStatic(); + methods.addMethod(method); + + methodAttributes = method.getAttributes(); + + code = new Code(methodAttributes); + methodAttributes.addAttribute(code); + + Instructions ins = code.getInstructions(); + ins.addInstruction(new VReturn(ins)); + return group; } } diff --git a/src/test/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscatorTest.java b/src/test/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscatorTest.java index b803bc3d12..d1fc2b2952 100644 --- a/src/test/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscatorTest.java +++ b/src/test/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscatorTest.java @@ -4,10 +4,13 @@ import java.util.Collection; import net.runelite.deob.ClassGroup; import net.runelite.deob.ClassGroupFactory; import net.runelite.deob.Deobfuscator; +import net.runelite.deob.Field; 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.Dup_X1; +import net.runelite.deob.attributes.code.instructions.GetStatic; +import net.runelite.deob.attributes.code.instructions.Goto; import net.runelite.deob.attributes.code.instructions.IAdd; import net.runelite.deob.attributes.code.instructions.IConst_0; import net.runelite.deob.attributes.code.instructions.IConst_1; @@ -20,6 +23,7 @@ import net.runelite.deob.attributes.code.instructions.IMul; import net.runelite.deob.attributes.code.instructions.IStore; import net.runelite.deob.attributes.code.instructions.IStore_0; import net.runelite.deob.attributes.code.instructions.If0; +import net.runelite.deob.attributes.code.instructions.InvokeStatic; import net.runelite.deob.attributes.code.instructions.LDC_W; import net.runelite.deob.attributes.code.instructions.NOP; import net.runelite.deob.attributes.code.instructions.Pop; @@ -43,7 +47,7 @@ public class MultiplicationDeobfuscatorTest // imul // putstatic class29/field949 I @Test - public void testDupX1_1() + public void test1() { ClassGroup group = ClassGroupFactory.generateGroup(); Code code = group.findClass("test").findMethod("func").getCode(); @@ -113,7 +117,7 @@ public class MultiplicationDeobfuscatorTest // ldc 561453169 // imul @Test - public void testDupX1_2() + public void test2() { ClassGroup group = ClassGroupFactory.generateGroup(); Code code = group.findClass("test").findMethod("func").getCode(); @@ -172,7 +176,7 @@ public class MultiplicationDeobfuscatorTest } @Test - public void testDupX1_3() + public void test3() { ClassGroup group = ClassGroupFactory.generateGroup(); Code code = group.findClass("test").findMethod("func").getCode(); @@ -244,7 +248,7 @@ public class MultiplicationDeobfuscatorTest } @Test - public void testDupX1_4() + public void test4() { ClassGroup group = ClassGroupFactory.generateGroup(); Code code = group.findClass("test").findMethod("func").getCode(); @@ -301,7 +305,7 @@ public class MultiplicationDeobfuscatorTest } @Test - public void testDupX1_5() + public void test5() { ClassGroup group = ClassGroupFactory.generateGroup(); Code code = group.findClass("test").findMethod("func").getCode(); @@ -361,7 +365,7 @@ public class MultiplicationDeobfuscatorTest } @Test - public void testDupX1_6() + public void test6() { ClassGroup group = ClassGroupFactory.generateGroup(); Code code = group.findClass("test").findMethod("func").getCode(); @@ -413,7 +417,7 @@ public class MultiplicationDeobfuscatorTest } @Test - public void testDupX1_7() + public void test7() { ClassGroup group = ClassGroupFactory.generateGroup(); Code code = group.findClass("test").findMethod("func").getCode(); @@ -461,4 +465,73 @@ public class MultiplicationDeobfuscatorTest Assert.assertEquals(-1, constant2.getConstantAsInt()); Assert.assertEquals(1, constant3.getConstantAsInt()); } + + @Test + public void test8() + { + ClassGroup group = ClassGroupFactory.generateGroup(); + Code code = group.findClass("test").findMethod("func").getCode(); + Code code2 = group.findClass("test").findMethod("func2").getCode(); + Field field = group.findClass("test").findField("field"); + Instructions ins = code.getInstructions(); + + code.setMaxStack(2); + + Instruction[] prepareVariables = { + new IConst_3(ins), + new IStore_0(ins) + }; + + for (Instruction i : prepareVariables) + ins.addInstruction(i); + + LDC_W constant1 = new LDC_W(ins, -1616202347), + constant2 = new LDC_W(ins, 2747837); + + NOP label1 = new NOP(ins), + label2 = new NOP(ins), + label3 = new NOP(ins); + + Instruction body[] = { + new GetStatic(ins, field.getPoolField()), + constant1, + new IMul(ins), + constant2, + new IMul(ins), + + new ILoad(ins, 0), + + new LDC_W(ins, 42), + new If0(ins, label1), + new Goto(ins, label2), + + label1, + new IConst_M1(ins), + new Goto(ins, label3), + + label2, + new IConst_0(ins), + new Goto(ins, label3), + + label3, + new InvokeStatic(ins, group.findClass("test").findMethod("func2").getPoolMethod()), + + new VReturn(ins) + }; + + for (Instruction i : body) + ins.addInstruction(i); + + Execution e = new Execution(group); + e.populateInitialMethods(); + e.run(); + + assert constant1.getConstantAsInt() * constant2.getConstantAsInt() == 1; + + Deobfuscator d = new MultiplicationDeobfuscator(); + d.run(group); + + Assert.assertEquals(1, constant1.getConstantAsInt()); + Assert.assertEquals(1, constant2.getConstantAsInt()); + } }