Inline static constant string fields
This commit is contained in:
@@ -1,6 +1,8 @@
|
|||||||
package info.sigterm.deob;
|
package info.sigterm.deob;
|
||||||
|
|
||||||
|
import info.sigterm.deob.deobfuscators.FieldInliner;
|
||||||
import info.sigterm.deob.deobfuscators.FieldMover;
|
import info.sigterm.deob.deobfuscators.FieldMover;
|
||||||
|
import info.sigterm.deob.deobfuscators.MethodMover;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
@@ -94,9 +96,11 @@ public class Deob
|
|||||||
|
|
||||||
// new ModularArithmeticDeobfuscation().run(group);
|
// 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]);
|
saveJar(group, args[1]);
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,13 @@ public abstract class Attribute
|
|||||||
this.length = is.readInt();
|
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
|
public final void write(DataOutputStream out) throws IOException
|
||||||
{
|
{
|
||||||
ByteArrayOutputStream bout = new ByteArrayOutputStream();
|
ByteArrayOutputStream bout = new ByteArrayOutputStream();
|
||||||
@@ -28,6 +35,8 @@ public abstract class Attribute
|
|||||||
byte[] b = bout.toByteArray();
|
byte[] b = bout.toByteArray();
|
||||||
out.writeInt(b.length);
|
out.writeInt(b.length);
|
||||||
out.write(b);
|
out.write(b);
|
||||||
|
|
||||||
|
length = b.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void writeAttr(DataOutputStream out) throws IOException;
|
public abstract void writeAttr(DataOutputStream out) throws IOException;
|
||||||
|
|||||||
@@ -117,4 +117,10 @@ public class Attributes
|
|||||||
a.write(out);
|
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();
|
DataInputStream is = attributes.getStream();
|
||||||
value = this.getAttributes().getClassFile().getPool().getEntry(is.readUnsignedShort());
|
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()
|
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();
|
group.buildClassGraph();
|
||||||
this.group = group;
|
this.group = group;
|
||||||
findUses();
|
findUses();
|
||||||
moveFields();
|
int count = moveFields();
|
||||||
|
|
||||||
|
System.out.println("Moved " + count + " fields");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user