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:
@@ -1,5 +1,6 @@
|
|||||||
package info.sigterm.deob;
|
package info.sigterm.deob;
|
||||||
|
|
||||||
|
import info.sigterm.deob.deobfuscators.IllegalStateExceptions;
|
||||||
import info.sigterm.deob.deobfuscators.Jumps;
|
import info.sigterm.deob.deobfuscators.Jumps;
|
||||||
import info.sigterm.deob.deobfuscators.RuntimeExceptions;
|
import info.sigterm.deob.deobfuscators.RuntimeExceptions;
|
||||||
import info.sigterm.deob.deobfuscators.UnusedBlocks;
|
import info.sigterm.deob.deobfuscators.UnusedBlocks;
|
||||||
@@ -35,11 +36,16 @@ public class Deob
|
|||||||
{
|
{
|
||||||
public static void main(String[] args) throws IOException
|
public static void main(String[] args) throws IOException
|
||||||
{
|
{
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
|
||||||
ClassGroup group = loadJar(args[0]);
|
ClassGroup group = loadJar(args[0]);
|
||||||
|
|
||||||
// remove except RuntimeException
|
// remove except RuntimeException
|
||||||
new RuntimeExceptions().run(group);
|
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
|
// remove code blocks that used to be the runtime exception handlers
|
||||||
new UnusedBlocks().run(group);
|
new UnusedBlocks().run(group);
|
||||||
|
|
||||||
@@ -53,6 +59,9 @@ public class Deob
|
|||||||
new Jumps().run(group);
|
new Jumps().run(group);
|
||||||
|
|
||||||
saveJar(group, args[1]);
|
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
|
private static ClassGroup loadJar(String jarfile) throws IOException
|
||||||
|
|||||||
@@ -99,12 +99,19 @@ public class Instructions
|
|||||||
public void buildBlocks()
|
public void buildBlocks()
|
||||||
{
|
{
|
||||||
clearBlockGraph();
|
clearBlockGraph();
|
||||||
|
buildJumpGraph();
|
||||||
|
|
||||||
Block current = null;
|
Block current = null;
|
||||||
for (Instruction i : instructions)
|
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 = new Block();
|
||||||
current.begin = i;
|
current.begin = i;
|
||||||
findExceptionInfo(current, i);
|
findExceptionInfo(current, i);
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ public class AThrow extends Instruction
|
|||||||
if (this.getPc() >= start.getPc() && this.getPc() < end.getPc())
|
if (this.getPc() >= start.getPc() && this.getPc() < end.getPc())
|
||||||
{
|
{
|
||||||
Frame f = frame.dup();
|
Frame f = frame.dup();
|
||||||
f.jumpAbsolute(e.getHandler().getPc());
|
f.jump(e.getHandler());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ public class CheckCast extends Instruction
|
|||||||
|
|
||||||
f.addInstructionContext(ins);
|
f.addInstructionContext(ins);
|
||||||
|
|
||||||
f.jumpAbsolute(e.getHandler().getPc());
|
f.jump(e.getHandler());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ public class Goto extends Instruction implements JumpingInstruction
|
|||||||
@Override
|
@Override
|
||||||
public void execute(Frame e)
|
public void execute(Frame e)
|
||||||
{
|
{
|
||||||
e.jump(offset);
|
e.jump(to);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ public class GotoW extends Instruction implements JumpingInstruction
|
|||||||
@Override
|
@Override
|
||||||
public void execute(Frame e)
|
public void execute(Frame e)
|
||||||
{
|
{
|
||||||
e.jump(offset);
|
e.jump(to);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -57,8 +57,10 @@ public class If extends Instruction implements JumpingInstruction
|
|||||||
|
|
||||||
ins.pop(one, two);
|
ins.pop(one, two);
|
||||||
|
|
||||||
|
frame.addInstructionContext(ins);
|
||||||
|
|
||||||
Frame other = frame.dup();
|
Frame other = frame.dup();
|
||||||
other.jump(offset);
|
other.jump(to);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ public class If0 extends Instruction implements JumpingInstruction
|
|||||||
frame.addInstructionContext(ins);
|
frame.addInstructionContext(ins);
|
||||||
|
|
||||||
Frame other = frame.dup();
|
Frame other = frame.dup();
|
||||||
other.jump(offset);
|
other.jump(to);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ public class InvokeInterface extends Instruction implements InvokeInstruction
|
|||||||
StackContext ctx = new StackContext(ins, new Type("java/lang/Exception"));
|
StackContext ctx = new StackContext(ins, new Type("java/lang/Exception"));
|
||||||
stack.push(ctx);
|
stack.push(ctx);
|
||||||
|
|
||||||
f.jumpAbsolute(e.getHandler().getPc());
|
f.jump(e.getHandler());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ public class InvokeSpecial extends Instruction implements InvokeInstruction
|
|||||||
StackContext ctx = new StackContext(ins, new Type("java/lang/Exception"));
|
StackContext ctx = new StackContext(ins, new Type("java/lang/Exception"));
|
||||||
stack.push(ctx);
|
stack.push(ctx);
|
||||||
|
|
||||||
f.jumpAbsolute(e.getHandler().getPc());
|
f.jump(e.getHandler());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ public class InvokeStatic extends Instruction implements InvokeInstruction
|
|||||||
StackContext ctx = new StackContext(ins, new Type("java/lang/Exception"));
|
StackContext ctx = new StackContext(ins, new Type("java/lang/Exception"));
|
||||||
stack.push(ctx);
|
stack.push(ctx);
|
||||||
|
|
||||||
f.jumpAbsolute(e.getHandler().getPc());
|
f.jump(e.getHandler());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ public class InvokeVirtual extends Instruction implements InvokeInstruction
|
|||||||
StackContext ctx = new StackContext(ins, new Type("java/lang/Exception"));
|
StackContext ctx = new StackContext(ins, new Type("java/lang/Exception"));
|
||||||
stack.push(ctx);
|
stack.push(ctx);
|
||||||
|
|
||||||
f.jumpAbsolute(e.getHandler().getPc());
|
f.jump(e.getHandler());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -107,13 +107,13 @@ public class LookupSwitch extends Instruction implements JumpingInstruction
|
|||||||
|
|
||||||
frame.addInstructionContext(ins);
|
frame.addInstructionContext(ins);
|
||||||
|
|
||||||
for (int i : branch)
|
for (Instruction i : branchi)
|
||||||
{
|
{
|
||||||
Frame other = frame.dup();
|
Frame other = frame.dup();
|
||||||
other.jump(i);
|
other.jump(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
frame.jump(def);
|
frame.jump(defi);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -104,13 +104,13 @@ public class TableSwitch extends Instruction implements JumpingInstruction
|
|||||||
|
|
||||||
frame.addInstructionContext(ins);
|
frame.addInstructionContext(ins);
|
||||||
|
|
||||||
for (int i : jumps)
|
for (Instruction i : branchi)
|
||||||
{
|
{
|
||||||
Frame other = frame.dup();
|
Frame other = frame.dup();
|
||||||
other.jump(i);
|
other.jump(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
frame.jump(def);
|
frame.jump(defi);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -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.If;
|
||||||
import info.sigterm.deob.attributes.code.instructions.If0;
|
import info.sigterm.deob.attributes.code.instructions.If0;
|
||||||
import info.sigterm.deob.attributes.code.instructions.New;
|
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.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
public class IllegalStateExceptions
|
public class IllegalStateExceptions
|
||||||
{
|
{
|
||||||
/* find if, new, ..., athrow, replace with goto */
|
/* find if, new, ..., athrow, replace with goto */
|
||||||
public void run(ClassGroup group)
|
private int checkOnce(Execution execution, ClassGroup group)
|
||||||
{
|
{
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
for (ClassFile cf : group.getClasses())
|
for (ClassFile cf : group.getClasses())
|
||||||
{
|
{
|
||||||
for (Method m : new ArrayList<>(cf.getMethods().getMethods()))
|
for (Method m : new ArrayList<>(cf.getMethods().getMethods()))
|
||||||
@@ -55,13 +61,43 @@ public class IllegalStateExceptions
|
|||||||
else if (ins instanceof If0)
|
else if (ins instanceof If0)
|
||||||
to = ((If0) ins).getTo();
|
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
|
// 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);
|
instructions.remove(ins);
|
||||||
ins = ilist.get(i); // don't need to ++i because
|
ins = ilist.get(i); // don't need to ++i because
|
||||||
}
|
}
|
||||||
while (!(ins instanceof AThrow));
|
|
||||||
|
|
||||||
// remove athrow
|
// remove athrow
|
||||||
instructions.remove(ins);
|
instructions.remove(ins);
|
||||||
@@ -70,9 +106,30 @@ public class IllegalStateExceptions
|
|||||||
ilist.add(i, new Goto(instructions, to));
|
ilist.add(i, new Goto(instructions, to));
|
||||||
|
|
||||||
++count;
|
++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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ public class Execution
|
|||||||
|
|
||||||
public void run()
|
public void run()
|
||||||
{
|
{
|
||||||
|
// XXX update pc? some instructiosn rely on it still.
|
||||||
|
|
||||||
int count = 0, fcount = 0;
|
int count = 0, fcount = 0;
|
||||||
for (ClassFile cf : group.getClasses())
|
for (ClassFile cf : group.getClasses())
|
||||||
for (Method method : cf.getMethods().getMethods())
|
for (Method method : cf.getMethods().getMethods())
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ public class Frame
|
|||||||
private Method method;
|
private Method method;
|
||||||
private boolean executing = true;
|
private boolean executing = true;
|
||||||
private int pc;
|
private int pc;
|
||||||
|
private Instruction cur; // current instruction
|
||||||
private Stack stack;
|
private Stack stack;
|
||||||
private Variables variables;
|
private Variables variables;
|
||||||
private List<InstructionContext> instructions = new ArrayList<>(); // instructions executed in this frame
|
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()));
|
variables.set(pos, new VariableContext(null, new Type(nat.getDescriptor().getTypeOfArg(i)).toStackType()));
|
||||||
pos += nat.getDescriptor().getTypeOfArg(i).getSlots();
|
pos += nat.getDescriptor().getTypeOfArg(i).getSlots();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cur = code.getInstructions().getInstructions().get(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Frame(Frame other)
|
protected Frame(Frame other)
|
||||||
@@ -56,6 +59,7 @@ public class Frame
|
|||||||
this.method = other.method;
|
this.method = other.method;
|
||||||
this.executing = other.executing;
|
this.executing = other.executing;
|
||||||
this.pc = other.pc;
|
this.pc = other.pc;
|
||||||
|
this.cur = other.cur;
|
||||||
this.stack = new Stack(other.stack);
|
this.stack = new Stack(other.stack);
|
||||||
this.variables = new Variables(other.variables);
|
this.variables = new Variables(other.variables);
|
||||||
this.visited = other.visited;
|
this.visited = other.visited;
|
||||||
@@ -106,25 +110,19 @@ public class Frame
|
|||||||
public void execute()
|
public void execute()
|
||||||
{
|
{
|
||||||
Instructions ins = method.getCode().getInstructions();
|
Instructions ins = method.getCode().getInstructions();
|
||||||
|
List<Instruction> instructions = ins.getInstructions();
|
||||||
|
|
||||||
while (executing)
|
while (executing)
|
||||||
{
|
{
|
||||||
int oldPc = pc;
|
Instruction oldCur = cur;
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
i.execute(this);
|
cur.execute(this);
|
||||||
}
|
}
|
||||||
catch (Throwable ex)
|
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):");
|
System.err.println("Frame stack (grows downward):");
|
||||||
while (stack.getSize() > 0)
|
while (stack.getSize() > 0)
|
||||||
{
|
{
|
||||||
@@ -136,9 +134,14 @@ public class Frame
|
|||||||
throw ex;
|
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
|
else
|
||||||
{
|
{
|
||||||
@@ -178,26 +181,17 @@ public class Frame
|
|||||||
return false;
|
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;
|
assert to != null;
|
||||||
|
|
||||||
if (hasJumped(from, to))
|
if (hasJumped(cur, to))
|
||||||
{
|
{
|
||||||
executing = false;
|
executing = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
doJump(from, to);
|
doJump(cur, to);
|
||||||
this.pc = pc;
|
cur = to;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user