Inline static constant string fields
This commit is contained in:
@@ -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]);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -117,4 +117,10 @@ public class Attributes
|
||||
a.write(out);
|
||||
}
|
||||
}
|
||||
|
||||
public void addAttribute(Attribute a)
|
||||
{
|
||||
assert a.getAttributes() == this;
|
||||
attributes.add(a);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
187
src/main/java/info/sigterm/deob/deobfuscators/FieldInliner.java
Normal file
187
src/main/java/info/sigterm/deob/deobfuscators/FieldInliner.java
Normal 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");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user