I think my invokevirtual execution is wrong because it doesn't actually
look for virtual methods on the type, which is why my unused method deob does weird things. I am seeing methods that still exist after running it that appear to be using non-inversible constants.
This commit is contained in:
@@ -0,0 +1,8 @@
|
|||||||
|
package info.sigterm.deob.attributes.code.instruction.types;
|
||||||
|
|
||||||
|
import info.sigterm.deob.pool.Field;
|
||||||
|
|
||||||
|
public interface SetFieldInstruction
|
||||||
|
{
|
||||||
|
public Field getField();
|
||||||
|
}
|
||||||
@@ -3,16 +3,18 @@ package info.sigterm.deob.attributes.code.instructions;
|
|||||||
import info.sigterm.deob.attributes.code.Instruction;
|
import info.sigterm.deob.attributes.code.Instruction;
|
||||||
import info.sigterm.deob.attributes.code.InstructionType;
|
import info.sigterm.deob.attributes.code.InstructionType;
|
||||||
import info.sigterm.deob.attributes.code.Instructions;
|
import info.sigterm.deob.attributes.code.Instructions;
|
||||||
|
import info.sigterm.deob.attributes.code.instruction.types.SetFieldInstruction;
|
||||||
import info.sigterm.deob.execution.Frame;
|
import info.sigterm.deob.execution.Frame;
|
||||||
import info.sigterm.deob.execution.InstructionContext;
|
import info.sigterm.deob.execution.InstructionContext;
|
||||||
import info.sigterm.deob.execution.Stack;
|
import info.sigterm.deob.execution.Stack;
|
||||||
import info.sigterm.deob.execution.StackContext;
|
import info.sigterm.deob.execution.StackContext;
|
||||||
import info.sigterm.deob.pool.Field;
|
import info.sigterm.deob.pool.Field;
|
||||||
|
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
public class PutField extends Instruction
|
public class PutField extends Instruction implements SetFieldInstruction
|
||||||
{
|
{
|
||||||
private Field field;
|
private Field field;
|
||||||
|
|
||||||
@@ -45,4 +47,10 @@ public class PutField extends Instruction
|
|||||||
frame.addInstructionContext(ins);
|
frame.addInstructionContext(ins);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Field getField()
|
||||||
|
{
|
||||||
|
return field;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,16 +3,18 @@ package info.sigterm.deob.attributes.code.instructions;
|
|||||||
import info.sigterm.deob.attributes.code.Instruction;
|
import info.sigterm.deob.attributes.code.Instruction;
|
||||||
import info.sigterm.deob.attributes.code.InstructionType;
|
import info.sigterm.deob.attributes.code.InstructionType;
|
||||||
import info.sigterm.deob.attributes.code.Instructions;
|
import info.sigterm.deob.attributes.code.Instructions;
|
||||||
|
import info.sigterm.deob.attributes.code.instruction.types.SetFieldInstruction;
|
||||||
import info.sigterm.deob.execution.Frame;
|
import info.sigterm.deob.execution.Frame;
|
||||||
import info.sigterm.deob.execution.InstructionContext;
|
import info.sigterm.deob.execution.InstructionContext;
|
||||||
import info.sigterm.deob.execution.Stack;
|
import info.sigterm.deob.execution.Stack;
|
||||||
import info.sigterm.deob.execution.StackContext;
|
import info.sigterm.deob.execution.StackContext;
|
||||||
import info.sigterm.deob.pool.Field;
|
import info.sigterm.deob.pool.Field;
|
||||||
|
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
public class PutStatic extends Instruction
|
public class PutStatic extends Instruction implements SetFieldInstruction
|
||||||
{
|
{
|
||||||
private Field field;
|
private Field field;
|
||||||
|
|
||||||
@@ -44,4 +46,9 @@ public class PutStatic extends Instruction
|
|||||||
frame.addInstructionContext(ins);
|
frame.addInstructionContext(ins);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Field getField()
|
||||||
|
{
|
||||||
|
return field;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,9 @@ import info.sigterm.deob.attributes.Code;
|
|||||||
import info.sigterm.deob.attributes.code.Instruction;
|
import info.sigterm.deob.attributes.code.Instruction;
|
||||||
import info.sigterm.deob.attributes.code.Instructions;
|
import info.sigterm.deob.attributes.code.Instructions;
|
||||||
import info.sigterm.deob.attributes.code.instruction.types.GetFieldInstruction;
|
import info.sigterm.deob.attributes.code.instruction.types.GetFieldInstruction;
|
||||||
|
import info.sigterm.deob.attributes.code.instruction.types.LVTInstruction;
|
||||||
import info.sigterm.deob.attributes.code.instruction.types.PushConstantInstruction;
|
import info.sigterm.deob.attributes.code.instruction.types.PushConstantInstruction;
|
||||||
|
import info.sigterm.deob.attributes.code.instruction.types.SetFieldInstruction;
|
||||||
import info.sigterm.deob.attributes.code.instructions.IMul;
|
import info.sigterm.deob.attributes.code.instructions.IMul;
|
||||||
import info.sigterm.deob.execution.Execution;
|
import info.sigterm.deob.execution.Execution;
|
||||||
import info.sigterm.deob.execution.Frame;
|
import info.sigterm.deob.execution.Frame;
|
||||||
@@ -67,8 +69,8 @@ public class ModularArithmeticDeobfuscation
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
// check for push constant and for get field instruction
|
// check for push constant and for get field instruction
|
||||||
Instruction one = ctx.getPops().get(0).getIns().getInstruction();
|
Instruction one = ctx.getPops().get(0).getPushed().getInstruction();
|
||||||
Instruction two = ctx.getPops().get(1).getIns().getInstruction();
|
Instruction two = ctx.getPops().get(1).getPushed().getInstruction();
|
||||||
|
|
||||||
PushConstantInstruction pc = null;
|
PushConstantInstruction pc = null;
|
||||||
GetFieldInstruction gf = null;
|
GetFieldInstruction gf = null;
|
||||||
@@ -86,14 +88,35 @@ public class ModularArithmeticDeobfuscation
|
|||||||
if (pc == null)
|
if (pc == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
int constant = Integer.parseInt(pc.getConstant().toString());
|
||||||
|
|
||||||
|
StackContext push = ctx.getPushes().get(0); // result of imul operation
|
||||||
|
InstructionContext popCtx = push.getPopped(); // instruction which popped the result
|
||||||
|
|
||||||
|
if (popCtx == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
//System.err.println("Stack ctx never popped! Pushed by " + push.getPushed().getInstruction());
|
||||||
|
//int i = frame.getInstructions().indexOf(push.getPushed().getInstruction());
|
||||||
|
//System.err.println("next ins is " + frame.getInstructions().get(i + 1).getInstruction());
|
||||||
|
}
|
||||||
|
|
||||||
|
// XXX look only for setting to lvt.
|
||||||
|
if (!(popCtx.getInstruction() instanceof LVTInstruction))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
LVTInstruction lvti = (LVTInstruction) popCtx.getInstruction();
|
||||||
|
if (!lvti.store())
|
||||||
|
continue;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
int constant = Integer.parseInt(pc.getConstant().toString());
|
|
||||||
modInverse(constant);
|
modInverse(constant);
|
||||||
}
|
}
|
||||||
catch (ArithmeticException ex)
|
catch (ArithmeticException ex)
|
||||||
{
|
{
|
||||||
continue;
|
System.err.println("Constant " + constant + " passed getter logic tests but is not inversable");
|
||||||
|
continue; // if the constant isn't inversable then it can't be the right one
|
||||||
}
|
}
|
||||||
|
|
||||||
Integer old = constants.get(gf.getField());
|
Integer old = constants.get(gf.getField());
|
||||||
@@ -103,10 +126,9 @@ public class ModularArithmeticDeobfuscation
|
|||||||
System.out.println("For " + gf.getField().getNameAndType().getName() + " in " + gf.getField().getClassEntry().getName() + " constant " + pc.getConstant().toString() + " mismatch on " + old);
|
System.out.println("For " + gf.getField().getNameAndType().getName() + " in " + gf.getField().getClassEntry().getName() + " constant " + pc.getConstant().toString() + " mismatch on " + old);
|
||||||
|
|
||||||
constants.put(gf.getField(), newi);
|
constants.put(gf.getField(), newi);
|
||||||
|
|
||||||
// see what the result is used for?
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
System.out.println("Found " + constants.size() + " constants");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static BigInteger modInverse(BigInteger val, int bits)
|
private static BigInteger modInverse(BigInteger val, int bits)
|
||||||
|
|||||||
@@ -22,7 +22,10 @@ public class InstructionContext
|
|||||||
public void pop(StackContext... ctx)
|
public void pop(StackContext... ctx)
|
||||||
{
|
{
|
||||||
for (StackContext c : ctx)
|
for (StackContext c : ctx)
|
||||||
|
{
|
||||||
|
c.setPopped(this); // now we know which instruction popped this, record it
|
||||||
pops.add(c);
|
pops.add(c);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void push(StackContext... ctx)
|
public void push(StackContext... ctx)
|
||||||
@@ -47,6 +50,11 @@ public class InstructionContext
|
|||||||
return pops;
|
return pops;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<StackContext> getPushes()
|
||||||
|
{
|
||||||
|
return pushes;
|
||||||
|
}
|
||||||
|
|
||||||
public void removeStack(int idx)
|
public void removeStack(int idx)
|
||||||
{
|
{
|
||||||
// idx 0 is top of the stack, 1 is one under
|
// idx 0 is top of the stack, 1 is one under
|
||||||
|
|||||||
@@ -22,8 +22,8 @@ public class Stack
|
|||||||
{
|
{
|
||||||
for (int i = 0; i < level; ++i)
|
for (int i = 0; i < level; ++i)
|
||||||
System.err.print(" ");
|
System.err.print(" ");
|
||||||
System.err.println(ctx.getType().type + " pushed by " + ctx.getIns().getInstruction().getType().getName() + " at " + ctx.getIns().getInstruction().getPc());
|
System.err.println(ctx.getType().type + " pushed by " + ctx.getPushed().getInstruction().getType().getName() + " at " + ctx.getPushed().getInstruction().getPc());
|
||||||
for (StackContext c : ctx.getIns().getPops())
|
for (StackContext c : ctx.getPushed().getPops())
|
||||||
printStack(c, level + 2);
|
printStack(c, level + 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,7 +31,7 @@ public class Stack
|
|||||||
{
|
{
|
||||||
if (size == stack.length)
|
if (size == stack.length)
|
||||||
{
|
{
|
||||||
info.sigterm.deob.Method m = i.getIns().getInstruction().getInstructions().getCode().getAttributes().getMethod();
|
info.sigterm.deob.Method m = i.getPushed().getInstruction().getInstructions().getCode().getAttributes().getMethod();
|
||||||
System.err.println("in " + m.getMethods().getClassFile().getName() + " method " + m.getNameAndType().getName());
|
System.err.println("in " + m.getMethods().getClassFile().getName() + " method " + m.getNameAndType().getName());
|
||||||
for (int c = 0; c < stack.length; ++c)
|
for (int c = 0; c < stack.length; ++c)
|
||||||
printStack(stack[c], 0);
|
printStack(stack[c], 0);
|
||||||
|
|||||||
@@ -2,30 +2,41 @@ package info.sigterm.deob.execution;
|
|||||||
|
|
||||||
public class StackContext
|
public class StackContext
|
||||||
{
|
{
|
||||||
private InstructionContext ic; // instruction which pushed this
|
private InstructionContext pushed; // instruction which pushed this
|
||||||
|
private InstructionContext popped; // instruction which popped this
|
||||||
private Type type; // type of this
|
private Type type; // type of this
|
||||||
|
|
||||||
public StackContext(InstructionContext i, Type t)
|
public StackContext(InstructionContext pushed, Type type)
|
||||||
{
|
{
|
||||||
ic = i;
|
this.pushed = pushed;
|
||||||
type = t;
|
this.type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
public StackContext(InstructionContext i, Class<?> c)
|
public StackContext(InstructionContext pushed, Class<?> clazz)
|
||||||
{
|
{
|
||||||
ic = i;
|
this.pushed = pushed;
|
||||||
type = new Type(c.getCanonicalName());
|
type = new Type(clazz.getCanonicalName());
|
||||||
}
|
}
|
||||||
|
|
||||||
public StackContext(InstructionContext i, info.sigterm.deob.pool.Class c)
|
public StackContext(InstructionContext pushed, info.sigterm.deob.pool.Class c)
|
||||||
{
|
{
|
||||||
ic = i;
|
this.pushed = pushed;
|
||||||
type = new Type(c.getName());
|
type = new Type(c.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
public InstructionContext getIns()
|
public InstructionContext getPushed()
|
||||||
{
|
{
|
||||||
return ic;
|
return pushed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InstructionContext getPopped()
|
||||||
|
{
|
||||||
|
return popped;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPopped(InstructionContext popped)
|
||||||
|
{
|
||||||
|
this.popped = popped;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Type getType()
|
public Type getType()
|
||||||
@@ -37,13 +48,13 @@ public class StackContext
|
|||||||
public void removeStack()
|
public void removeStack()
|
||||||
{
|
{
|
||||||
// remove the instruction which pushed this
|
// remove the instruction which pushed this
|
||||||
if (!ic.getInstruction().removeStack())
|
if (!pushed.getInstruction().removeStack())
|
||||||
// dup will return false as the other objects on the stack below this are necessary
|
// dup will return false as the other objects on the stack below this are necessary
|
||||||
// for the other branch.
|
// for the other branch.
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// remove from the stack things this instruction read
|
// remove from the stack things this instruction read
|
||||||
for (StackContext ctx : ic.getPops())
|
for (StackContext ctx : pushed.getPops())
|
||||||
ctx.removeStack();
|
ctx.removeStack();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user