Start of constant parameter stuff

This commit is contained in:
Adam
2015-07-30 16:39:48 -04:00
parent f27e410f5b
commit 5478fc7385
14 changed files with 227 additions and 23 deletions

View File

@@ -20,6 +20,7 @@ import info.sigterm.deob.attributes.code.instructions.Goto;
import info.sigterm.deob.attributes.code.instructions.GotoW;
import info.sigterm.deob.attributes.code.instructions.Return;
import info.sigterm.deob.block.Block;
import info.sigterm.deob.deobfuscators.ConstantParameter;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
@@ -43,31 +44,54 @@ public class Deob
ClassGroup group = loadJar(args[0]);
new RenameUnique().run(group);
// remove except RuntimeException
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);
new ConstantParameter().run(group);
// remove unused methods
new UnusedMethods().run(group);
// remove illegal state exceptions, frees up some parameters
new IllegalStateExceptions().run(group);
// remove unhit blocks
new UnusedBlocks().run(group);
// remove unused parameters
new UnusedParameters().run(group);
// long bstart = System.currentTimeMillis();
// new RenameUnique().run(group);
// long bdur = System.currentTimeMillis() - bstart;
// System.out.println("rename unique took " + bdur/1000L + " seconds");
//
// // remove except RuntimeException
// bstart = System.currentTimeMillis();
// 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);
// bdur = System.currentTimeMillis() - bstart;
// System.out.println("runtime exception took " + bdur/1000L + " seconds");
//
// // remove unused methods
// bstart = System.currentTimeMillis();
// new UnusedMethods().run(group);
// bdur = System.currentTimeMillis() - bstart;
// System.out.println("unused methods took " + bdur/1000L + " seconds");
//
// // remove illegal state exceptions, frees up some parameters
// bstart = System.currentTimeMillis();
// new IllegalStateExceptions().run(group);
// bdur = System.currentTimeMillis() - bstart;
// System.out.println("illegal state exception took " + bdur/1000L + " seconds");
//
// // remove unhit blocks
// bstart = System.currentTimeMillis();
// new UnusedBlocks().run(group);
// bdur = System.currentTimeMillis() - bstart;
// System.out.println("unused blocks took " + bdur/1000L + " seconds");
//
// // remove unused parameters
// bstart = System.currentTimeMillis();
// new UnusedParameters().run(group);
// bdur = System.currentTimeMillis() - bstart;
// System.out.println("unused blocks took " + bdur/1000L + " seconds");
// remove jump obfuscation
//new Jumps().run(group);
// remove unused fields
new UnusedFields().run(group);
// bstart = System.currentTimeMillis();
// new UnusedFields().run(group);
// bdur = System.currentTimeMillis() - bstart;
// System.out.println("unused fields took " + bdur/1000L + " seconds");
//new ModularArithmeticDeobfuscation().run(group);

View File

@@ -10,4 +10,6 @@ public interface InvokeInstruction
public void removeParameter(int idx);
public PoolEntry getMethod();
public List<Method> getMethods();
}

View File

@@ -48,7 +48,8 @@ public class InvokeInterface extends Instruction implements InvokeInstruction
out.writeByte(0);
}
private List<info.sigterm.deob.Method> getMethods()
@Override
public List<info.sigterm.deob.Method> getMethods()
{
ClassGroup group = this.getInstructions().getCode().getAttributes().getClassFile().getGroup();

View File

@@ -43,7 +43,8 @@ public class InvokeSpecial extends Instruction implements InvokeInstruction
out.writeShort(this.getPool().make(method));
}
private List<info.sigterm.deob.Method> getMethods()
@Override
public List<info.sigterm.deob.Method> getMethods()
{
ClassGroup group = this.getInstructions().getCode().getAttributes().getClassFile().getGroup();

View File

@@ -43,7 +43,8 @@ public class InvokeStatic extends Instruction implements InvokeInstruction
out.writeShort(this.getPool().make(method));
}
private List<info.sigterm.deob.Method> getMethods()
@Override
public List<info.sigterm.deob.Method> getMethods()
{
ClassGroup group = this.getInstructions().getCode().getAttributes().getClassFile().getGroup();

View File

@@ -83,7 +83,8 @@ public class InvokeVirtual extends Instruction implements InvokeInstruction
// find the possible methods this instruction might be invoking. we can't know for sure
// which method is being invoked without tracking the types of objects in fields and when
// passed in parameters/return values.
private List<info.sigterm.deob.Method> getMethods()
@Override
public List<info.sigterm.deob.Method> getMethods()
{
ClassGroup group = this.getInstructions().getCode().getAttributes().getClassFile().getGroup();

View File

@@ -0,0 +1,133 @@
package info.sigterm.deob.deobfuscators;
import info.sigterm.deob.ClassGroup;
import info.sigterm.deob.Deobfuscator;
import info.sigterm.deob.Method;
import info.sigterm.deob.attributes.code.instruction.types.InvokeInstruction;
import info.sigterm.deob.attributes.code.instruction.types.PushConstantInstruction;
import info.sigterm.deob.execution.Execution;
import info.sigterm.deob.execution.Frame;
import info.sigterm.deob.execution.InstructionContext;
import info.sigterm.deob.execution.StackContext;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.map.MultiValueMap;
class ConstantMethodParameter
{
public Method method;
public int paramNum;
public Object value;
}
class MethodGroup
{
public List<Method> methods; // methods that can be invoked
public Collection<Integer> constantParameters; // parameters which are always constant for all invocations
public List<ConstantMethodParameter> cmps = new ArrayList<>(); // cmps for all methods in the group, which hold the values.
}
public class ConstantParameter implements Deobfuscator
{
private MultiValueMap<Method, ConstantMethodParameter> parameters = new MultiValueMap<>();
// methods can be in more than one group because of multiple inheritance with interfaces
private MultiValueMap<Method, MethodGroup> methodGroups = new MultiValueMap<>();
private void findConstantParameter(Execution execution, Method method, InstructionContext invokeCtx)
{
List<StackContext> pops = invokeCtx.getPops();
for (int i = 0; i < method.getDescriptor().size(); ++i)
{
// object is poped first
int offset = method.isStatic() ? 0 : 1;
StackContext ctx = pops.get(offset + i);
if (ctx.getPushed().getInstruction() instanceof PushConstantInstruction)
{
PushConstantInstruction pc = (PushConstantInstruction) ctx.getPushed().getInstruction();
if (!(pc.getConstant().getObject() instanceof Integer))
continue;
ConstantMethodParameter cmp = new ConstantMethodParameter();
cmp.method = method;
cmp.paramNum = i;
cmp.value = pc.getConstant().getObject();
parameters.put(method, cmp);
}
}
}
private Collection<Integer> getParametersFor(Method method)
{
Collection<ConstantMethodParameter> params = parameters.getCollection(method);
Collection<Integer> out = new ArrayList<>();
if (params != null)
for (ConstantMethodParameter p : params)
out.add(p.paramNum);
return out;
}
private void findParameters(Execution execution)
{
for (Frame frame : execution.processedFrames)
for (InstructionContext ins : frame.getInstructions())
{
if (!(ins.getInstruction() instanceof InvokeInstruction))
continue;
List<Method> methods = ((InvokeInstruction) ins.getInstruction()).getMethods();
for (Method m : methods)
findConstantParameter(execution, m, ins);
// get common constant indexes from all methods that can possibly be called
Collection<Integer> parameterIndexes = null;
for (Method m : methods)
{
Collection<Integer> idxs = getParametersFor(m);
if (parameterIndexes == null)
parameterIndexes = idxs;
else
parameterIndexes = CollectionUtils.intersection(parameterIndexes, idxs);
}
MethodGroup group = new MethodGroup();
group.methods = methods;
group.constantParameters = parameterIndexes;
// build constant method parameters
for (Method m : methods)
{
Collection<ConstantMethodParameter> params = parameters.getCollection(m);
if (params != null)
group.cmps.addAll(params);
}
// insert
for (Method m : methods)
methodGroups.put(m, group);
}
}
@Override
public void run(ClassGroup group)
{
group.buildClassGraph(); // required for getMethods in the invoke stuff
Execution execution = new Execution(group);
execution.populateInitialMethods();
execution.run();
findParameters(execution);
System.out.println("finished with " + methodGroups.size() + " groups");
}
}

View File

@@ -54,4 +54,10 @@ public class Double extends PoolEntry
{
out.writeDouble(value);
}
@Override
public Object getObject()
{
return value;
}
}

View File

@@ -48,4 +48,10 @@ public class Float extends PoolEntry
{
out.writeFloat(value);
}
@Override
public Object getObject()
{
return value;
}
}

View File

@@ -54,4 +54,10 @@ public class Integer extends PoolEntry
{
out.writeInt(value);
}
@Override
public Object getObject()
{
return value;
}
}

View File

@@ -54,4 +54,10 @@ public class Long extends PoolEntry
{
out.writeLong(value);
}
@Override
public Object getObject()
{
return value;
}
}

View File

@@ -45,4 +45,9 @@ public abstract class PoolEntry
{
return 1;
}
public Object getObject()
{
return this;
}
}

View File

@@ -61,4 +61,10 @@ public class String extends PoolEntry
{
out.writeShort(stringIndex);
}
@Override
public Object getObject()
{
return string;
}
}

View File

@@ -46,4 +46,10 @@ public class UTF8 extends PoolEntry
java.lang.String s = getValue();
out.writeUTF(s);
}
@Override
public Object getObject()
{
return string;
}
}