Inline static constant string fields

This commit is contained in:
Adam
2015-08-15 17:05:54 -04:00
parent 8a7e1d1f97
commit 1c8f2dbc27
6 changed files with 218 additions and 3 deletions

View File

@@ -1,6 +1,8 @@
package info.sigterm.deob;
import info.sigterm.deob.deobfuscators.FieldInliner;
import info.sigterm.deob.deobfuscators.FieldMover;
import info.sigterm.deob.deobfuscators.MethodMover;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
@@ -94,9 +96,11 @@ public class Deob
// new ModularArithmeticDeobfuscation().run(group);
//new MethodMover().run(group);
// new MethodMover().run(group);
//
// new FieldMover().run(group);
new FieldMover().run(group);
new FieldInliner().run(group);
saveJar(group, args[1]);

View File

@@ -20,6 +20,13 @@ public abstract class Attribute
this.length = is.readInt();
}
Attribute(Attributes attr, AttributeType type, int length)
{
this.attributes = attr;
this.type = type;
this.length = length;
}
public final void write(DataOutputStream out) throws IOException
{
ByteArrayOutputStream bout = new ByteArrayOutputStream();
@@ -28,6 +35,8 @@ public abstract class Attribute
byte[] b = bout.toByteArray();
out.writeInt(b.length);
out.write(b);
length = b.length;
}
public abstract void writeAttr(DataOutputStream out) throws IOException;

View File

@@ -117,4 +117,10 @@ public class Attributes
a.write(out);
}
}
public void addAttribute(Attribute a)
{
assert a.getAttributes() == this;
attributes.add(a);
}
}

View File

@@ -17,6 +17,13 @@ public class ConstantValue extends Attribute
DataInputStream is = attributes.getStream();
value = this.getAttributes().getClassFile().getPool().getEntry(is.readUnsignedShort());
}
public ConstantValue(Attributes attributes, PoolEntry value)
{
super(attributes, AttributeType.CONSTANT_VALUE, -1);
this.value = value;
}
public PoolEntry getValue()
{

View File

@@ -0,0 +1,187 @@
package info.sigterm.deob.deobfuscators;
import info.sigterm.deob.ClassFile;
import info.sigterm.deob.ClassGroup;
import info.sigterm.deob.Deobfuscator;
import info.sigterm.deob.Field;
import info.sigterm.deob.Method;
import info.sigterm.deob.attributes.AttributeType;
import info.sigterm.deob.attributes.Attributes;
import info.sigterm.deob.attributes.Code;
import info.sigterm.deob.attributes.ConstantValue;
import info.sigterm.deob.attributes.code.Instruction;
import info.sigterm.deob.attributes.code.Instructions;
import info.sigterm.deob.attributes.code.instruction.types.FieldInstruction;
import info.sigterm.deob.attributes.code.instruction.types.PushConstantInstruction;
import info.sigterm.deob.attributes.code.instruction.types.SetFieldInstruction;
import info.sigterm.deob.attributes.code.instructions.LDC_W;
import info.sigterm.deob.attributes.code.instructions.NOP;
import java.util.ArrayList;
import java.util.List;
public class FieldInliner implements Deobfuscator
{
private ClassGroup group;
private List<Field> fields = new ArrayList<>();
private List<FieldInstruction> findFieldIns(Field field, boolean set)
{
List<FieldInstruction> ins = new ArrayList<>();
for (ClassFile cf : group.getClasses())
{
for (Method m : cf.getMethods().getMethods())
{
Code code = m.getCode();
if (code == null)
continue;
for (Instruction i : code.getInstructions().getInstructions())
{
if (!(i instanceof FieldInstruction))
continue;
FieldInstruction sf = (FieldInstruction) i;
if (sf.getMyField() != field)
continue;
if (sf instanceof SetFieldInstruction != set)
continue;
ins.add(sf);
}
}
}
return ins;
}
private void makeConstantValues()
{
for (ClassFile cf : group.getClasses())
{
for (Field f : cf.getFields().getFields())
{
if (!f.isStatic() || !f.getType().getFullType().equals("Ljava/lang/String;"))
continue;
Attributes attributes = f.getAttributes();
ConstantValue constantValue = (ConstantValue) attributes.findType(AttributeType.CONSTANT_VALUE);
if (constantValue != null)
continue;
List<FieldInstruction> sfis = findFieldIns(f, true);
if (sfis.size() != 1)
continue;
SetFieldInstruction sfi = (SetFieldInstruction) sfis.get(0);
Instruction ins = (Instruction) sfi;
Method mOfSet = ins.getInstructions().getCode().getAttributes().getMethod();
if (!mOfSet.getName().equals("<clinit>"))
continue;
// get prev instruction and change to a constant value
Instructions instructions = mOfSet.getCode().getInstructions();
int idx = instructions.getInstructions().indexOf(ins);
assert idx != -1;
Instruction prev = instructions.getInstructions().get(idx - 1);
if (!(prev instanceof PushConstantInstruction))
continue;
PushConstantInstruction pci = (PushConstantInstruction) prev;
constantValue = new ConstantValue(attributes, pci.getConstant());
attributes.addAttribute(constantValue);
fields.add(f);
// nop
NOP nop1 = new NOP(instructions), nop2 = new NOP(instructions);
for (Instruction i : prev.from)
{
i.jump.remove(prev);
i.jump.add(nop1);
i.replace(prev, nop1);
}
prev.from.clear();
for (Instruction i : ins.from)
{
i.jump.remove(ins);
i.jump.add(nop1);
i.replace(ins, nop1);
}
ins.from.clear();
boolean b = instructions.getInstructions().remove(prev);
assert b;
b = instructions.getInstructions().remove(ins);
assert b;
instructions.getInstructions().add(idx - 1, nop1);
instructions.getInstructions().add(idx, nop2);
}
}
}
public int inlineUse()
{
int count = 0;
for (Field f : fields)
{
// replace getfield with constant push
List<FieldInstruction> fins = findFieldIns(f, false);
ConstantValue value = (ConstantValue) f.getAttributes().findType(AttributeType.CONSTANT_VALUE);
for (FieldInstruction fin : fins)
{
// remove fin, add push constant
Instruction i = (Instruction) fin;
i.getInstructions().buildJumpGraph();
Instruction pushIns = new LDC_W(i.getInstructions(), value.getValue());
List<Instruction> instructions = i.getInstructions().getInstructions();
int idx = instructions.indexOf(i);
assert idx != -1;
// move jumps to i to pushIns
for (Instruction i2 : i.from)
{
i2.jump.remove(i);
i2.jump.add(pushIns);
i2.replace(i, pushIns);
}
i.from.clear();
i.getInstructions().remove(i);
instructions.add(idx, pushIns);
++count;
}
f.getFields().getFields().remove(f);
}
return count;
}
@Override
public void run(ClassGroup group)
{
this.group = group;
makeConstantValues();
int count = inlineUse();
System.out.println("Inlined " + count + " fields");
}
}

View File

@@ -118,7 +118,9 @@ public class FieldMover implements Deobfuscator
group.buildClassGraph();
this.group = group;
findUses();
moveFields();
int count = moveFields();
System.out.println("Moved " + count + " fields");
}
}