remove stack of ifs in illegal state ex deob, get rid of using pcs in

frame to execute, need to remove more of this later, make jumps jump to
instructions, doesn't yet work
This commit is contained in:
Adam
2015-06-20 17:56:46 -04:00
parent 98d85c646b
commit 713db7777f
17 changed files with 116 additions and 45 deletions

View File

@@ -1,5 +1,6 @@
package info.sigterm.deob;
import info.sigterm.deob.deobfuscators.IllegalStateExceptions;
import info.sigterm.deob.deobfuscators.Jumps;
import info.sigterm.deob.deobfuscators.RuntimeExceptions;
import info.sigterm.deob.deobfuscators.UnusedBlocks;
@@ -35,11 +36,16 @@ public class Deob
{
public static void main(String[] args) throws IOException
{
long start = System.currentTimeMillis();
ClassGroup group = loadJar(args[0]);
// remove except RuntimeException
new RuntimeExceptions().run(group);
// remove illegal state exceptions, frees up some parameters
new IllegalStateExceptions().run(group);
// remove code blocks that used to be the runtime exception handlers
new UnusedBlocks().run(group);
@@ -53,6 +59,9 @@ public class Deob
new Jumps().run(group);
saveJar(group, args[1]);
long end = System.currentTimeMillis();
System.out.println("Done in " + ((end - start) / 1000L) + "s");
}
private static ClassGroup loadJar(String jarfile) throws IOException

View File

@@ -99,12 +99,19 @@ public class Instructions
public void buildBlocks()
{
clearBlockGraph();
buildJumpGraph();
Block current = null;
for (Instruction i : instructions)
{
if (current == null)
if (current == null || !i.from.isEmpty())
{
// this caused exception errors?
if (current != null)
{
current.end = current.instructions.get(current.instructions.size() - 1);
blocks.add(current);
}
current = new Block();
current.begin = i;
findExceptionInfo(current, i);

View File

@@ -50,7 +50,7 @@ public class AThrow extends Instruction
if (this.getPc() >= start.getPc() && this.getPc() < end.getPc())
{
Frame f = frame.dup();
f.jumpAbsolute(e.getHandler().getPc());
f.jump(e.getHandler());
}
}

View File

@@ -63,7 +63,7 @@ public class CheckCast extends Instruction
f.addInstructionContext(ins);
f.jumpAbsolute(e.getHandler().getPc());
f.jump(e.getHandler());
}
}
}

View File

@@ -56,7 +56,7 @@ public class Goto extends Instruction implements JumpingInstruction
@Override
public void execute(Frame e)
{
e.jump(offset);
e.jump(to);
}
@Override

View File

@@ -46,7 +46,7 @@ public class GotoW extends Instruction implements JumpingInstruction
@Override
public void execute(Frame e)
{
e.jump(offset);
e.jump(to);
}
@Override

View File

@@ -57,8 +57,10 @@ public class If extends Instruction implements JumpingInstruction
ins.pop(one, two);
frame.addInstructionContext(ins);
Frame other = frame.dup();
other.jump(offset);
other.jump(to);
}
@Override

View File

@@ -59,7 +59,7 @@ public class If0 extends Instruction implements JumpingInstruction
frame.addInstructionContext(ins);
Frame other = frame.dup();
other.jump(offset);
other.jump(to);
}
@Override

View File

@@ -110,7 +110,7 @@ public class InvokeInterface extends Instruction implements InvokeInstruction
StackContext ctx = new StackContext(ins, new Type("java/lang/Exception"));
stack.push(ctx);
f.jumpAbsolute(e.getHandler().getPc());
f.jump(e.getHandler());
}
}
}

View File

@@ -105,7 +105,7 @@ public class InvokeSpecial extends Instruction implements InvokeInstruction
StackContext ctx = new StackContext(ins, new Type("java/lang/Exception"));
stack.push(ctx);
f.jumpAbsolute(e.getHandler().getPc());
f.jump(e.getHandler());
}
}
}

View File

@@ -102,7 +102,7 @@ public class InvokeStatic extends Instruction implements InvokeInstruction
StackContext ctx = new StackContext(ins, new Type("java/lang/Exception"));
stack.push(ctx);
f.jumpAbsolute(e.getHandler().getPc());
f.jump(e.getHandler());
}
}
}

View File

@@ -106,7 +106,7 @@ public class InvokeVirtual extends Instruction implements InvokeInstruction
StackContext ctx = new StackContext(ins, new Type("java/lang/Exception"));
stack.push(ctx);
f.jumpAbsolute(e.getHandler().getPc());
f.jump(e.getHandler());
}
}
}

View File

@@ -107,13 +107,13 @@ public class LookupSwitch extends Instruction implements JumpingInstruction
frame.addInstructionContext(ins);
for (int i : branch)
for (Instruction i : branchi)
{
Frame other = frame.dup();
other.jump(i);
}
frame.jump(def);
frame.jump(defi);
}
@Override

View File

@@ -104,13 +104,13 @@ public class TableSwitch extends Instruction implements JumpingInstruction
frame.addInstructionContext(ins);
for (int i : jumps)
for (Instruction i : branchi)
{
Frame other = frame.dup();
other.jump(i);
}
frame.jump(def);
frame.jump(defi);
}
@Override

View File

@@ -11,16 +11,22 @@ import info.sigterm.deob.attributes.code.instructions.Goto;
import info.sigterm.deob.attributes.code.instructions.If;
import info.sigterm.deob.attributes.code.instructions.If0;
import info.sigterm.deob.attributes.code.instructions.New;
import info.sigterm.deob.execution.Execution;
import info.sigterm.deob.execution.Frame;
import info.sigterm.deob.execution.InstructionContext;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class IllegalStateExceptions
{
/* find if, new, ..., athrow, replace with goto */
public void run(ClassGroup group)
private int checkOnce(Execution execution, ClassGroup group)
{
int count = 0;
for (ClassFile cf : group.getClasses())
{
for (Method m : new ArrayList<>(cf.getMethods().getMethods()))
@@ -55,13 +61,43 @@ public class IllegalStateExceptions
else if (ins instanceof If0)
to = ((If0) ins).getTo();
// remove stack of if.
boolean found = false;
for (Frame f : execution.processedFrames)
if (f.getMethod() == m)
for (InstructionContext ic : f.getInstructions())
if (ic.getInstruction() == ins) // this is the if
{
found = true;
if (ins instanceof If)
ic.removeStack(1);
ic.removeStack(0);
}
assert found;
// instruction is no longer at 'i' because we've just removed stuff...
i = ilist.indexOf(ins);
// remove up to athrow
do
while (!(ins instanceof AThrow))
{
// modify instructions which jump to here to instead jump to 'to'
for (Instruction from : ins.from)
{
from.jump.remove(ins);
//ins.from.remove(from);
from.replace(ins, to);
from.jump.add(to);
}
ins.from.clear();
instructions.remove(ins);
ins = ilist.get(i); // don't need to ++i because
}
while (!(ins instanceof AThrow));
// remove athrow
instructions.remove(ins);
@@ -70,9 +106,30 @@ public class IllegalStateExceptions
ilist.add(i, new Goto(instructions, to));
++count;
break;
}
}
}
System.out.println("Removed " + count + " illegal state exceptions");
return count;
}
public void run(ClassGroup group)
{
Execution execution = new Execution(group);
execution.run();
int count = 0;
int passes = 0;
int i;
do
{
i = checkOnce(execution, group);
count += i;
++passes;
}
while (i > 0);
System.out.println("Removed " + count + " illegal state exceptions in " + passes + " passes");
}
}

View File

@@ -21,6 +21,8 @@ public class Execution
public void run()
{
// XXX update pc? some instructiosn rely on it still.
int count = 0, fcount = 0;
for (ClassFile cf : group.getClasses())
for (Method method : cf.getMethods().getMethods())

View File

@@ -20,6 +20,7 @@ public class Frame
private Method method;
private boolean executing = true;
private int pc;
private Instruction cur; // current instruction
private Stack stack;
private Variables variables;
private List<InstructionContext> instructions = new ArrayList<>(); // instructions executed in this frame
@@ -48,6 +49,8 @@ public class Frame
variables.set(pos, new VariableContext(null, new Type(nat.getDescriptor().getTypeOfArg(i)).toStackType()));
pos += nat.getDescriptor().getTypeOfArg(i).getSlots();
}
cur = code.getInstructions().getInstructions().get(0);
}
protected Frame(Frame other)
@@ -56,6 +59,7 @@ public class Frame
this.method = other.method;
this.executing = other.executing;
this.pc = other.pc;
this.cur = other.cur;
this.stack = new Stack(other.stack);
this.variables = new Variables(other.variables);
this.visited = other.visited;
@@ -106,25 +110,19 @@ public class Frame
public void execute()
{
Instructions ins = method.getCode().getInstructions();
List<Instruction> instructions = ins.getInstructions();
while (executing)
{
int oldPc = pc;
Instruction i = ins.findInstruction(pc);
if (i == null)
{
System.err.println("Cant find ins at pc " + pc + " in method " + method.getName() + " in " + method.getCode().getAttributes().getClassFile().getName());
System.exit(-1);
}
Instruction oldCur = cur;
try
{
i.execute(this);
cur.execute(this);
}
catch (Throwable ex)
{
System.err.println("Error executing instruction " + i.getDesc(this));
System.err.println("Error executing instruction " + cur.getDesc(this));
System.err.println("Frame stack (grows downward):");
while (stack.getSize() > 0)
{
@@ -136,9 +134,14 @@ public class Frame
throw ex;
}
if (oldPc == pc)
if (!executing)
break;
if (oldCur == cur)
{
pc += i.getLength();
int idx = instructions.indexOf(cur);
assert idx != -1;
cur = instructions.get(idx + 1);
}
else
{
@@ -178,26 +181,17 @@ public class Frame
return false;
}
public void jump(int offset)
public void jump(Instruction to)
{
jumpAbsolute(pc + offset);
}
public void jumpAbsolute(int pc)
{
Instruction from = method.getCode().getInstructions().findInstruction(this.pc);
Instruction to = method.getCode().getInstructions().findInstruction(pc);
assert from != null;
assert to != null;
if (hasJumped(from, to))
if (hasJumped(cur, to))
{
executing = false;
return;
}
doJump(from, to);
this.pc = pc;
doJump(cur, to);
cur = to;
}
}