Start of constant parameter stuff
This commit is contained in:
@@ -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.GotoW;
|
||||||
import info.sigterm.deob.attributes.code.instructions.Return;
|
import info.sigterm.deob.attributes.code.instructions.Return;
|
||||||
import info.sigterm.deob.block.Block;
|
import info.sigterm.deob.block.Block;
|
||||||
|
import info.sigterm.deob.deobfuscators.ConstantParameter;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
@@ -43,31 +44,54 @@ public class Deob
|
|||||||
|
|
||||||
ClassGroup group = loadJar(args[0]);
|
ClassGroup group = loadJar(args[0]);
|
||||||
|
|
||||||
new RenameUnique().run(group);
|
new ConstantParameter().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);
|
|
||||||
|
|
||||||
// remove unused methods
|
// long bstart = System.currentTimeMillis();
|
||||||
new UnusedMethods().run(group);
|
// new RenameUnique().run(group);
|
||||||
|
// long bdur = System.currentTimeMillis() - bstart;
|
||||||
// remove illegal state exceptions, frees up some parameters
|
// System.out.println("rename unique took " + bdur/1000L + " seconds");
|
||||||
new IllegalStateExceptions().run(group);
|
//
|
||||||
|
// // remove except RuntimeException
|
||||||
// remove unhit blocks
|
// bstart = System.currentTimeMillis();
|
||||||
new UnusedBlocks().run(group);
|
// new RuntimeExceptions().run(group);
|
||||||
|
// // the blocks of runtime exceptions may contain interesting things like other obfuscations we identify later, but now that
|
||||||
// remove unused parameters
|
// // it can't be reached by the execution phase, those things become confused. so remove blocks here.
|
||||||
new UnusedParameters().run(group);
|
// 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
|
// remove jump obfuscation
|
||||||
//new Jumps().run(group);
|
//new Jumps().run(group);
|
||||||
|
|
||||||
// remove unused fields
|
// 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);
|
//new ModularArithmeticDeobfuscation().run(group);
|
||||||
|
|
||||||
|
|||||||
@@ -10,4 +10,6 @@ public interface InvokeInstruction
|
|||||||
public void removeParameter(int idx);
|
public void removeParameter(int idx);
|
||||||
|
|
||||||
public PoolEntry getMethod();
|
public PoolEntry getMethod();
|
||||||
|
|
||||||
|
public List<Method> getMethods();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,7 +48,8 @@ public class InvokeInterface extends Instruction implements InvokeInstruction
|
|||||||
out.writeByte(0);
|
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();
|
ClassGroup group = this.getInstructions().getCode().getAttributes().getClassFile().getGroup();
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,8 @@ public class InvokeSpecial extends Instruction implements InvokeInstruction
|
|||||||
out.writeShort(this.getPool().make(method));
|
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();
|
ClassGroup group = this.getInstructions().getCode().getAttributes().getClassFile().getGroup();
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,8 @@ public class InvokeStatic extends Instruction implements InvokeInstruction
|
|||||||
out.writeShort(this.getPool().make(method));
|
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();
|
ClassGroup group = this.getInstructions().getCode().getAttributes().getClassFile().getGroup();
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
// 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
|
// which method is being invoked without tracking the types of objects in fields and when
|
||||||
// passed in parameters/return values.
|
// 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();
|
ClassGroup group = this.getInstructions().getCode().getAttributes().getClassFile().getGroup();
|
||||||
|
|
||||||
|
|||||||
@@ -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");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -54,4 +54,10 @@ public class Double extends PoolEntry
|
|||||||
{
|
{
|
||||||
out.writeDouble(value);
|
out.writeDouble(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getObject()
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,4 +48,10 @@ public class Float extends PoolEntry
|
|||||||
{
|
{
|
||||||
out.writeFloat(value);
|
out.writeFloat(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getObject()
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,4 +54,10 @@ public class Integer extends PoolEntry
|
|||||||
{
|
{
|
||||||
out.writeInt(value);
|
out.writeInt(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getObject()
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,4 +54,10 @@ public class Long extends PoolEntry
|
|||||||
{
|
{
|
||||||
out.writeLong(value);
|
out.writeLong(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getObject()
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,4 +45,9 @@ public abstract class PoolEntry
|
|||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Object getObject()
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,4 +61,10 @@ public class String extends PoolEntry
|
|||||||
{
|
{
|
||||||
out.writeShort(stringIndex);
|
out.writeShort(stringIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getObject()
|
||||||
|
{
|
||||||
|
return string;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,4 +46,10 @@ public class UTF8 extends PoolEntry
|
|||||||
java.lang.String s = getValue();
|
java.lang.String s = getValue();
|
||||||
out.writeUTF(s);
|
out.writeUTF(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getObject()
|
||||||
|
{
|
||||||
|
return string;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user