translating one field works

This commit is contained in:
Adam
2015-09-06 23:39:47 -04:00
parent 88bd6490de
commit f46e4dfdce
4 changed files with 129 additions and 75 deletions

View File

@@ -18,6 +18,7 @@ import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
import net.runelite.deob.attributes.code.instruction.types.PushConstantInstruction; import net.runelite.deob.attributes.code.instruction.types.PushConstantInstruction;
import static net.runelite.deob.attributes.code.instructions.PutStatic.translate;
import net.runelite.deob.deobfuscators.arithmetic.Encryption; import net.runelite.deob.deobfuscators.arithmetic.Encryption;
import net.runelite.deob.deobfuscators.arithmetic.Pair; import net.runelite.deob.deobfuscators.arithmetic.Pair;
@@ -56,78 +57,81 @@ public class PutField extends Instruction implements SetFieldInstruction
if (encryption != null && myField != null) if (encryption != null && myField != null)
{ {
Pair pair = encryption.getField(myField); Pair pair = encryption.getField(myField);
InstructionContext ctx = value.getPushed(); if (pair != null)
if (ctx.getInstruction() instanceof IAdd && pair != null) translate(encryption, pair, ins);
{ // XXX move translate() here
// field += constant * crap; // InstructionContext ctx = value.getPushed();
// in bytecode is really // if (ctx.getInstruction() instanceof IAdd && pair != null)
// field = field + constant * crap // {
// // field += constant * crap;
List<StackContext> pops = ctx.getPops(); // // in bytecode is really
// // field = field + constant * crap
if (pops.get(0).getPushed().getInstruction() instanceof IMul) //
{ // List<StackContext> pops = ctx.getPops();
ctx = pops.get(0).getPushed(); //
} // if (pops.get(0).getPushed().getInstruction() instanceof IMul)
else if (pops.get(1).getPushed().getInstruction() instanceof IMul) // {
{ // ctx = pops.get(0).getPushed();
ctx = pops.get(1).getPushed(); // }
} // else if (pops.get(1).getPushed().getInstruction() instanceof IMul)
} // {
if (ctx.getInstruction() instanceof PushConstantInstruction && pair != null) // ctx = pops.get(1).getPushed();
{ // }
// field = encryptedvalue // }
// decrypt value by * getter // if (ctx.getInstruction() instanceof PushConstantInstruction && pair != null)
// {
PushConstantInstruction pci = (PushConstantInstruction) ctx.getInstruction(); // // field = encryptedvalue
int v = (int) pci.getConstant().getObject(); // // decrypt value by * getter
//
if (v != 0 && v != 1) // PushConstantInstruction pci = (PushConstantInstruction) ctx.getInstruction();
{ // int v = (int) pci.getConstant().getObject();
v = v * pair.getter; //
// if (v != 0 && v != 1)
encryption.change(pci, v); // {
} // v = v * pair.getter;
} //
if (ctx.getInstruction() instanceof ISub) // encryption.change(pci, v);
{ // }
List<StackContext> stackCtx = ctx.getPops(); // }
// if (ctx.getInstruction() instanceof ISub)
StackContext one = stackCtx.get(0), two = stackCtx.get(1); // {
// List<StackContext> stackCtx = ctx.getPops();
if (one.getPushed().getInstruction() instanceof IMul) //
{ // StackContext one = stackCtx.get(0), two = stackCtx.get(1);
ctx = one.getPushed(); //
} // if (one.getPushed().getInstruction() instanceof IMul)
else if (two.getPushed().getInstruction() instanceof IMul) // {
{ // ctx = one.getPushed();
ctx = two.getPushed(); // }
} // else if (two.getPushed().getInstruction() instanceof IMul)
} // {
if (ctx.getInstruction() instanceof IMul && pair != null) // ctx = two.getPushed();
{ // }
List<StackContext> stackCtx = ctx.getPops(); // }
// if (ctx.getInstruction() instanceof IMul && pair != null)
StackContext one = stackCtx.get(0), two = stackCtx.get(1); // {
// List<StackContext> stackCtx = ctx.getPops();
StackContext magicStack = PutStatic.findMagic(one, two); //
// StackContext one = stackCtx.get(0), two = stackCtx.get(1);
if (magicStack != null) //
{ // StackContext magicStack = PutStatic.findMagic(one, two);
PushConstantInstruction pci = (PushConstantInstruction) magicStack.getPushed().getInstruction(); //
int v = (int) pci.getConstant().getObject(); // if (magicStack != null)
// {
// field is encrypted with pair // PushConstantInstruction pci = (PushConstantInstruction) magicStack.getPushed().getInstruction();
// divide value by setter // int v = (int) pci.getConstant().getObject();
//
if (v != 0 && v != 1) // // field is encrypted with pair
{ // // divide value by setter
v = v * pair.getter; //
// if (v != 0 && v != 1)
encryption.change(pci, v); // {
} // v = v * pair.getter;
} //
} // encryption.change(pci, v);
// }
// }
// }
} }
frame.addInstructionContext(ins); frame.addInstructionContext(ins);

View File

@@ -17,6 +17,7 @@ import java.io.DataInputStream;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
import net.runelite.deob.attributes.code.instruction.types.InvokeInstruction;
import net.runelite.deob.attributes.code.instruction.types.PushConstantInstruction; import net.runelite.deob.attributes.code.instruction.types.PushConstantInstruction;
import net.runelite.deob.deobfuscators.arithmetic.DMath; import net.runelite.deob.deobfuscators.arithmetic.DMath;
import net.runelite.deob.deobfuscators.arithmetic.Encryption; import net.runelite.deob.deobfuscators.arithmetic.Encryption;
@@ -69,7 +70,7 @@ public class PutStatic extends Instruction implements SetFieldInstruction
return null; return null;
} }
private static boolean translate(Encryption encryption, Pair pair, InstructionContext ctx) protected static boolean translate(Encryption encryption, Pair pair, InstructionContext ctx)
{ {
if (ctx.getInstruction() instanceof LDC_W) if (ctx.getInstruction() instanceof LDC_W)
{ {
@@ -89,9 +90,14 @@ public class PutStatic extends Instruction implements SetFieldInstruction
return true; return true;
} }
if (ctx.getInstruction() instanceof InvokeInstruction)
return false;
boolean multipleBranches = ctx.getInstruction() instanceof IAdd || ctx.getInstruction() instanceof ISub; boolean multipleBranches = ctx.getInstruction() instanceof IAdd || ctx.getInstruction() instanceof ISub;
boolean retVal = false; boolean retVal = false;
encryption.begin();
for (StackContext sctx : ctx.getPops()) for (StackContext sctx : ctx.getPops())
{ {
InstructionContext i = sctx.getPushed(); InstructionContext i = sctx.getPushed();
@@ -99,11 +105,25 @@ public class PutStatic extends Instruction implements SetFieldInstruction
if (translate(encryption, pair, i)) if (translate(encryption, pair, i))
{ {
retVal = true; retVal = true;
if (!multipleBranches)
if (!multipleBranches) // only need to translate the one branch, which we have, return.
break; break;
} }
else
{
if (multipleBranches)
{
// we can't translate both branches so rollback
encryption.rollback();
retVal = false;
break;
}
// else this is okay, we can try another
}
} }
encryption.end();
return retVal; return retVal;
} }

View File

@@ -1,15 +1,24 @@
package net.runelite.deob.deobfuscators.arithmetic; package net.runelite.deob.deobfuscators.arithmetic;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Set;
import java.util.Stack;
import net.runelite.deob.Field; import net.runelite.deob.Field;
import net.runelite.deob.attributes.code.instruction.types.PushConstantInstruction; import net.runelite.deob.attributes.code.instruction.types.PushConstantInstruction;
public class Encryption public class Encryption
{ {
private static class PendingStack
{
private Set<PushConstantInstruction> pending = new HashSet<>();
}
private Map<Field, Pair> fields = new HashMap<>(); private Map<Field, Pair> fields = new HashMap<>();
private Map<PushConstantInstruction, Integer> changes = new HashMap<>(); private Map<PushConstantInstruction, Integer> changes = new HashMap<>();
private Stack<PendingStack> stack = new Stack<>();
public void addPair(Pair pair) public void addPair(Pair pair)
{ {
@@ -30,6 +39,10 @@ public class Encryption
{ {
assert !changes.containsKey(pci) || changes.get(pci) == value; assert !changes.containsKey(pci) || changes.get(pci) == value;
changes.put(pci, value); changes.put(pci, value);
if (stack.isEmpty())
return;
PendingStack ps = stack.peek();
ps.pending.add(pci);
} }
public void doChange() public void doChange()
@@ -42,4 +55,21 @@ public class Encryption
pci.setConstant(new net.runelite.deob.pool.Integer(value)); pci.setConstant(new net.runelite.deob.pool.Integer(value));
} }
} }
public void begin()
{
stack.push(new PendingStack());
}
public void end()
{
stack.pop();
}
public void rollback()
{
PendingStack ps = stack.peek();
for (PushConstantInstruction pci : ps.pending)
changes.remove(pci);
}
} }

View File

@@ -278,7 +278,7 @@ public class ModArith implements Deobfuscator
Field field = pair.field; Field field = pair.field;
System.out.println("Processing " + field.getName() + " getter " + pair.getter + " setter " + pair.setter); System.out.println("Processing " + field.getName() + " getter " + pair.getter + " setter " + pair.setter);
if (i > 10) // 25 if (i > 0) // 2
break; break;
Encryption encr = new Encryption(); Encryption encr = new Encryption();