Fix up jump inlining, this causes linear scans of the instructions for a

lot of exceptions and is slow. Need to allow inlining in try blocks?
This commit is contained in:
Adam
2015-07-12 00:15:45 -04:00
parent 3fbb69e102
commit ec50303962
10 changed files with 109 additions and 54 deletions

View File

@@ -45,28 +45,31 @@ public class Deob
// remove except RuntimeException // remove except RuntimeException
new RuntimeExceptions().run(group); new RuntimeExceptions().run(group);
// the blocks of runtime exceptions may contain interesting things like other obfuscations we identify later, but now that
// it can't be reached by the execution phase, those things become confused. so remove blocks here.
//new UnusedBlocks().run(group);
// remove unused methods // remove unused methods
new UnusedMethods().run(group); //new UnusedMethods().run(group);
// remove illegal state exceptions, frees up some parameters // remove illegal state exceptions, frees up some parameters
new IllegalStateExceptions().run(group); //new IllegalStateExceptions().run(group);
// remove code blocks that used to be the runtime exception handlers // remove unhit blocks
new UnusedBlocks().run(group); //new UnusedBlocks().run(group);
// remove unused parameters // remove unused parameters
new UnusedParameters().run(group); //new UnusedParameters().run(group);
// remove jump obfuscation // remove jump obfuscation
new Jumps().run(group); new Jumps().run(group);
// remove unused fields // remove unused fields
new UnusedFields().run(group); //new UnusedFields().run(group);
//new ModularArithmeticDeobfuscation().run(group); //new ModularArithmeticDeobfuscation().run(group);
new RenameUnique().run(group); //new RenameUnique().run(group);
saveJar(group, args[1]); saveJar(group, args[1]);

View File

@@ -87,9 +87,20 @@ public class Instructions
{ {
for (Exception e : code.getExceptions().getExceptions()) for (Exception e : code.getExceptions().getExceptions())
{ {
if (i.getPc() >= e.getStart().getPc() && i.getPc() < e.getEnd().getPc()) int startIdx = instructions.indexOf(e.getStart()),
endIdx = instructions.indexOf(e.getEnd()),
thisIdx = instructions.indexOf(i);
assert startIdx != -1;
assert endIdx != -1;
assert thisIdx != -1;
assert endIdx > startIdx;
if (thisIdx >= startIdx && thisIdx < endIdx)
{ {
block.exceptions.add(e); if (!block.exceptions.contains(e))
block.exceptions.add(e);
} }
if (e.getHandler() == i) if (e.getHandler() == i)
{ {
@@ -98,28 +109,43 @@ public class Instructions
} }
} }
private boolean isException(Instruction i)
{
for (Exception e : code.getExceptions().getExceptions())
if (e.getHandler() == i || e.getStart() == i)
return true;
return false;
}
private boolean isExceptionEnd(Instruction i)
{
for (Exception e : code.getExceptions().getExceptions())
if (e.getEnd() == i)
return true;
return false;
}
public void buildBlocks() public void buildBlocks()
{ {
clearBlockGraph(); clearBlockGraph();
buildJumpGraph(); buildJumpGraph();
Block current = null; Block current = null;
for (Instruction i : instructions) for (int j = 0; j < instructions.size(); ++j)
{ {
if (current == null || !i.from.isEmpty()) Instruction i = instructions.get(j),
next = j + 1 < instructions.size() ? instructions.get(j + 1) : null;
if (current == null)
{ {
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);
} }
i.block = current;
current.instructions.add(i); current.instructions.add(i);
if (i.isTerminal()) findExceptionInfo(current, i);
if (i.isTerminal() || next == null || isException(next) || isExceptionEnd(i) || !next.from.isEmpty())
{ {
current.end = i; current.end = i;
blocks.add(current); blocks.add(current);

View File

@@ -43,11 +43,16 @@ public class AThrow extends Instruction
// jump to instruction handlers that can catch exceptions here // jump to instruction handlers that can catch exceptions here
for (info.sigterm.deob.attributes.code.Exception e : this.getInstructions().getCode().getExceptions().getExceptions()) for (info.sigterm.deob.attributes.code.Exception e : this.getInstructions().getCode().getExceptions().getExceptions())
{ {
Instruction start = e.getStart(), int startIdx = this.getInstructions().getInstructions().indexOf(e.getStart()),
end = e.getEnd(); endIdx = this.getInstructions().getInstructions().indexOf(e.getEnd()),
thisIdx = this.getInstructions().getInstructions().indexOf(this);
assert startIdx != -1;
assert endIdx != -1;
assert thisIdx != -1;
// [start, end) // [start, end)
if (this.getPc() >= start.getPc() && this.getPc() < end.getPc()) if (thisIdx >= startIdx && thisIdx < endIdx)
{ {
Frame f = frame.dup(); Frame f = frame.dup();
f.jump(e.getHandler()); f.jump(e.getHandler());

View File

@@ -41,11 +41,16 @@ public class CheckCast extends Instruction
// jump to instruction handlers that can catch exceptions here // jump to instruction handlers that can catch exceptions here
for (info.sigterm.deob.attributes.code.Exception e : this.getInstructions().getCode().getExceptions().getExceptions()) for (info.sigterm.deob.attributes.code.Exception e : this.getInstructions().getCode().getExceptions().getExceptions())
{ {
Instruction start = e.getStart(), int startIdx = this.getInstructions().getInstructions().indexOf(e.getStart()),
end = e.getEnd(); endIdx = this.getInstructions().getInstructions().indexOf(e.getEnd()),
thisIdx = this.getInstructions().getInstructions().indexOf(this);
assert startIdx != -1;
assert endIdx != -1;
assert thisIdx != -1;
// [start, end) // [start, end)
if (this.getPc() >= start.getPc() && this.getPc() < end.getPc()) if (thisIdx >= startIdx && thisIdx < endIdx)
{ {
Frame f = frame.dup(); Frame f = frame.dup();
Stack stack = f.getStack(); Stack stack = f.getStack();

View File

@@ -114,11 +114,16 @@ public class InvokeInterface extends Instruction implements InvokeInstruction
// jump to instruction handlers that can catch exceptions here // jump to instruction handlers that can catch exceptions here
for (info.sigterm.deob.attributes.code.Exception e : this.getInstructions().getCode().getExceptions().getExceptions()) for (info.sigterm.deob.attributes.code.Exception e : this.getInstructions().getCode().getExceptions().getExceptions())
{ {
Instruction start = e.getStart(), int startIdx = this.getInstructions().getInstructions().indexOf(e.getStart()),
end = e.getEnd(); endIdx = this.getInstructions().getInstructions().indexOf(e.getEnd()),
thisIdx = this.getInstructions().getInstructions().indexOf(this);
assert startIdx != -1;
assert endIdx != -1;
assert thisIdx != -1;
// [start, end) // [start, end)
if (this.getPc() >= start.getPc() && this.getPc() < end.getPc()) if (thisIdx >= startIdx && thisIdx < endIdx)
{ {
Frame f = frame.dup(); Frame f = frame.dup();
Stack stack = f.getStack(); Stack stack = f.getStack();

View File

@@ -101,11 +101,16 @@ public class InvokeSpecial extends Instruction implements InvokeInstruction
// jump to instruction handlers that can catch exceptions here // jump to instruction handlers that can catch exceptions here
for (info.sigterm.deob.attributes.code.Exception e : this.getInstructions().getCode().getExceptions().getExceptions()) for (info.sigterm.deob.attributes.code.Exception e : this.getInstructions().getCode().getExceptions().getExceptions())
{ {
Instruction start = e.getStart(), int startIdx = this.getInstructions().getInstructions().indexOf(e.getStart()),
end = e.getEnd(); endIdx = this.getInstructions().getInstructions().indexOf(e.getEnd()),
thisIdx = this.getInstructions().getInstructions().indexOf(this);
assert startIdx != -1;
assert endIdx != -1;
assert thisIdx != -1;
// [start, end) // [start, end)
if (this.getPc() >= start.getPc() && this.getPc() < end.getPc()) if (thisIdx >= startIdx && thisIdx < endIdx)
{ {
Frame f = frame.dup(); Frame f = frame.dup();
Stack stack = f.getStack(); Stack stack = f.getStack();

View File

@@ -98,11 +98,16 @@ public class InvokeStatic extends Instruction implements InvokeInstruction
// jump to instruction handlers that can catch exceptions here // jump to instruction handlers that can catch exceptions here
for (info.sigterm.deob.attributes.code.Exception e : this.getInstructions().getCode().getExceptions().getExceptions()) for (info.sigterm.deob.attributes.code.Exception e : this.getInstructions().getCode().getExceptions().getExceptions())
{ {
Instruction start = e.getStart(), int startIdx = this.getInstructions().getInstructions().indexOf(e.getStart()),
end = e.getEnd(); endIdx = this.getInstructions().getInstructions().indexOf(e.getEnd()),
thisIdx = this.getInstructions().getInstructions().indexOf(this);
assert startIdx != -1;
assert endIdx != -1;
assert thisIdx != -1;
// [start, end) // [start, end)
if (this.getPc() >= start.getPc() && this.getPc() < end.getPc()) if (thisIdx >= startIdx && thisIdx < endIdx)
{ {
Frame f = frame.dup(); Frame f = frame.dup();
Stack stack = f.getStack(); Stack stack = f.getStack();

View File

@@ -112,12 +112,16 @@ public class InvokeVirtual extends Instruction implements InvokeInstruction
// jump to instruction handlers that can catch exceptions here // jump to instruction handlers that can catch exceptions here
for (info.sigterm.deob.attributes.code.Exception e : this.getInstructions().getCode().getExceptions().getExceptions()) for (info.sigterm.deob.attributes.code.Exception e : this.getInstructions().getCode().getExceptions().getExceptions())
{ {
Instruction start = e.getStart(), int startIdx = this.getInstructions().getInstructions().indexOf(e.getStart()),
end = e.getEnd(); endIdx = this.getInstructions().getInstructions().indexOf(e.getEnd()),
thisIdx = this.getInstructions().getInstructions().indexOf(this);
assert startIdx != -1;
assert endIdx != -1;
assert thisIdx != -1;
// XXX this relies on pc?
// [start, end) // [start, end)
if (this.getPc() >= start.getPc() && this.getPc() < end.getPc()) if (thisIdx >= startIdx && thisIdx < endIdx)
{ {
Frame f = frame.dup(); Frame f = frame.dup();
Stack stack = f.getStack(); Stack stack = f.getStack();

View File

@@ -56,10 +56,6 @@ public class Jumps implements Deobfuscator
//ins.clearBlocks(); //ins.clearBlocks();
ins.clearJumpGraph(); ins.clearJumpGraph();
// 'from' goes away and is replaced with block.begin
for (Instruction in : ilist)
in.replace(from, block.begin);
// remove instructions // remove instructions
for (Instruction in : block.instructions) for (Instruction in : block.instructions)
{ {
@@ -67,13 +63,19 @@ public class Jumps implements Deobfuscator
assert b; assert b;
} }
// store pos of from int idx = ilist.indexOf(from);
int index = ilist.indexOf(from); boolean b = ilist.remove(from);
ilist.remove(from); assert b;
// insert instructions where 'from' was b = ilist.addAll(idx, block.instructions);
for (Instruction in : block.instructions) assert b;
ilist.add(index++, in);
// replace from with block.begin
for (Instruction ins2 : ilist)
ins2.replace(from, block.begin);
for (info.sigterm.deob.attributes.code.Exception e : m.getCode().getExceptions().getExceptions())
e.replace(from, block.begin);
continue methods; continue methods;
} }
@@ -93,6 +95,7 @@ public class Jumps implements Deobfuscator
do do
{ {
i = checkBlockGraphOnce(g); i = checkBlockGraphOnce(g);
System.out.println("pass " + i);
count += i; count += i;
++passes; ++passes;
} }

View File

@@ -53,12 +53,6 @@ public class UnusedFields implements Deobfuscator
if (get == 0 && set == 0) if (get == 0 && set == 0)
return true; return true;
if (get == 0)
{
System.out.println("Field " + field.getFields().getClassFile().getName() + "." + field.getName() + " is set but not get");
return false;
}
return false; return false;
} }