Finish methodmover
This commit is contained in:
@@ -3,6 +3,9 @@ package info.sigterm.deob;
|
|||||||
import info.sigterm.deob.deobfuscators.ConstantParameter;
|
import info.sigterm.deob.deobfuscators.ConstantParameter;
|
||||||
import info.sigterm.deob.deobfuscators.IllegalStateExceptions;
|
import info.sigterm.deob.deobfuscators.IllegalStateExceptions;
|
||||||
import info.sigterm.deob.deobfuscators.MethodInliner;
|
import info.sigterm.deob.deobfuscators.MethodInliner;
|
||||||
|
import info.sigterm.deob.deobfuscators.MethodMover;
|
||||||
|
import info.sigterm.deob.deobfuscators.ModularArithmeticDeobfuscation;
|
||||||
|
import info.sigterm.deob.deobfuscators.RenameUnique;
|
||||||
import info.sigterm.deob.deobfuscators.RuntimeExceptions;
|
import info.sigterm.deob.deobfuscators.RuntimeExceptions;
|
||||||
import info.sigterm.deob.deobfuscators.UnreachedCode;
|
import info.sigterm.deob.deobfuscators.UnreachedCode;
|
||||||
import info.sigterm.deob.deobfuscators.UnusedFields;
|
import info.sigterm.deob.deobfuscators.UnusedFields;
|
||||||
@@ -21,6 +24,13 @@ import java.util.jar.JarFile;
|
|||||||
import java.util.jar.JarOutputStream;
|
import java.util.jar.JarOutputStream;
|
||||||
import java.util.jar.Manifest;
|
import java.util.jar.Manifest;
|
||||||
|
|
||||||
|
//move static methods
|
||||||
|
//move static fields
|
||||||
|
//math deob
|
||||||
|
//remove dead classes
|
||||||
|
//inline constant fields
|
||||||
|
//compare old and new
|
||||||
|
|
||||||
public class Deob
|
public class Deob
|
||||||
{
|
{
|
||||||
public static void main(String[] args) throws IOException
|
public static void main(String[] args) throws IOException
|
||||||
@@ -38,9 +48,6 @@ public class Deob
|
|||||||
// remove except RuntimeException
|
// remove except RuntimeException
|
||||||
bstart = System.currentTimeMillis();
|
bstart = System.currentTimeMillis();
|
||||||
new RuntimeExceptions().run(group);
|
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;
|
bdur = System.currentTimeMillis() - bstart;
|
||||||
System.out.println("runtime exception took " + bdur/1000L + " seconds");
|
System.out.println("runtime exception took " + bdur/1000L + " seconds");
|
||||||
|
|
||||||
@@ -92,10 +99,13 @@ public class Deob
|
|||||||
bdur = System.currentTimeMillis() - bstart;
|
bdur = System.currentTimeMillis() - bstart;
|
||||||
System.out.println("unused methods took " + bdur/1000L + " seconds");
|
System.out.println("unused methods took " + bdur/1000L + " seconds");
|
||||||
|
|
||||||
//new ModularArithmeticDeobfuscation().run(group);
|
|
||||||
|
|
||||||
new MethodInliner().run(group);
|
new MethodInliner().run(group);
|
||||||
|
|
||||||
|
// new ModularArithmeticDeobfuscation().run(group);
|
||||||
|
|
||||||
|
new MethodMover().run(group);
|
||||||
|
|
||||||
saveJar(group, args[1]);
|
saveJar(group, args[1]);
|
||||||
|
|
||||||
long end = System.currentTimeMillis();
|
long end = System.currentTimeMillis();
|
||||||
|
|||||||
@@ -42,6 +42,8 @@ public class Method
|
|||||||
|
|
||||||
public void write(DataOutputStream out) throws IOException
|
public void write(DataOutputStream out) throws IOException
|
||||||
{
|
{
|
||||||
|
assert methods.getMethods().contains(this);
|
||||||
|
|
||||||
ConstantPool pool = methods.getClassFile().getPool();
|
ConstantPool pool = methods.getClassFile().getPool();
|
||||||
|
|
||||||
out.writeShort(accessFlags);
|
out.writeShort(accessFlags);
|
||||||
@@ -55,6 +57,11 @@ public class Method
|
|||||||
return methods;
|
return methods;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setMethods(Methods methods)
|
||||||
|
{
|
||||||
|
this.methods = methods;
|
||||||
|
}
|
||||||
|
|
||||||
public String getName()
|
public String getName()
|
||||||
{
|
{
|
||||||
return name;
|
return name;
|
||||||
|
|||||||
@@ -226,7 +226,7 @@ public abstract class Instruction
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public void renameMethod(Method m, String name)
|
public void renameMethod(Method oldMethod, info.sigterm.deob.pool.Method newMethod)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -238,9 +238,9 @@ public class Instructions
|
|||||||
i.renameField(f, name);
|
i.renameField(f, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void renameMethod(Method m, String name)
|
public void renameMethod(Method oldMethod, info.sigterm.deob.pool.Method newMethod)
|
||||||
{
|
{
|
||||||
for (Instruction i : instructions)
|
for (Instruction i : instructions)
|
||||||
i.renameMethod(m, name);
|
i.renameMethod(oldMethod, newMethod);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import info.sigterm.deob.execution.StackContext;
|
|||||||
import info.sigterm.deob.execution.Type;
|
import info.sigterm.deob.execution.Type;
|
||||||
import info.sigterm.deob.pool.Class;
|
import info.sigterm.deob.pool.Class;
|
||||||
import info.sigterm.deob.pool.InterfaceMethod;
|
import info.sigterm.deob.pool.InterfaceMethod;
|
||||||
|
import info.sigterm.deob.pool.Method;
|
||||||
import info.sigterm.deob.pool.NameAndType;
|
import info.sigterm.deob.pool.NameAndType;
|
||||||
import info.sigterm.deob.pool.PoolEntry;
|
import info.sigterm.deob.pool.PoolEntry;
|
||||||
import info.sigterm.deob.signature.Signature;
|
import info.sigterm.deob.signature.Signature;
|
||||||
@@ -149,10 +150,10 @@ public class InvokeInterface extends Instruction implements InvokeInstruction
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void renameMethod(info.sigterm.deob.Method m, String name)
|
public void renameMethod(info.sigterm.deob.Method m, Method newMethod)
|
||||||
{
|
{
|
||||||
for (info.sigterm.deob.Method m2 : getMethods())
|
for (info.sigterm.deob.Method m2 : getMethods())
|
||||||
if (m2.equals(m))
|
if (m2.equals(m))
|
||||||
method = new InterfaceMethod(method.getClassEntry(), new NameAndType(name, method.getNameAndType().getDescriptor()));
|
method = new InterfaceMethod(newMethod.getClassEntry(), newMethod.getNameAndType());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -142,10 +142,10 @@ public class InvokeSpecial extends Instruction implements InvokeInstruction
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void renameMethod(info.sigterm.deob.Method m, String name)
|
public void renameMethod(info.sigterm.deob.Method m, Method newMethod)
|
||||||
{
|
{
|
||||||
for (info.sigterm.deob.Method m2 : getMethods())
|
for (info.sigterm.deob.Method m2 : getMethods())
|
||||||
if (m2.equals(m))
|
if (m2.equals(m))
|
||||||
method = new Method(method.getClassEntry(), new NameAndType(name, method.getNameAndType().getDescriptor()));
|
method = newMethod;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -139,7 +139,7 @@ public class InvokeStatic extends Instruction implements InvokeInstruction
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void renameMethod(info.sigterm.deob.Method m, String name)
|
public void renameMethod(info.sigterm.deob.Method m, Method newMethod)
|
||||||
{
|
{
|
||||||
ClassGroup group = this.getInstructions().getCode().getAttributes().getClassFile().getGroup();
|
ClassGroup group = this.getInstructions().getCode().getAttributes().getClassFile().getGroup();
|
||||||
ClassFile otherClass = group.findClass(method.getClassEntry().getName());
|
ClassFile otherClass = group.findClass(method.getClassEntry().getName());
|
||||||
@@ -150,6 +150,6 @@ public class InvokeStatic extends Instruction implements InvokeInstruction
|
|||||||
assert other.isStatic();
|
assert other.isStatic();
|
||||||
|
|
||||||
if (other.equals(m))
|
if (other.equals(m))
|
||||||
method = new Method(method.getClassEntry(), new NameAndType(name, method.getNameAndType().getDescriptor()));
|
method = newMethod;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -147,10 +147,10 @@ public class InvokeVirtual extends Instruction implements InvokeInstruction
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void renameMethod(info.sigterm.deob.Method m, String name)
|
public void renameMethod(info.sigterm.deob.Method m, Method newMethod)
|
||||||
{
|
{
|
||||||
for (info.sigterm.deob.Method m2 : getMethods())
|
for (info.sigterm.deob.Method m2 : getMethods())
|
||||||
if (m2.equals(m))
|
if (m2.equals(m))
|
||||||
method = new Method(method.getClassEntry(), new NameAndType(name, method.getNameAndType().getDescriptor()));
|
method = newMethod;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,15 +9,18 @@ import info.sigterm.deob.attributes.code.Instruction;
|
|||||||
import info.sigterm.deob.attributes.code.Instructions;
|
import info.sigterm.deob.attributes.code.Instructions;
|
||||||
import info.sigterm.deob.attributes.code.instructions.InvokeStatic;
|
import info.sigterm.deob.attributes.code.instructions.InvokeStatic;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import org.apache.commons.collections4.map.MultiValueMap;
|
import org.apache.commons.collections4.map.MultiValueMap;
|
||||||
|
|
||||||
// find static methods that are only called from methods of one class
|
// find static methods that are only called from non-static methods of one class
|
||||||
public class MethodMover implements Deobfuscator
|
public class MethodMover implements Deobfuscator
|
||||||
{
|
{
|
||||||
|
private ClassGroup group;
|
||||||
private MultiValueMap<Method, Method> calls = new MultiValueMap<>();
|
private MultiValueMap<Method, Method> calls = new MultiValueMap<>();
|
||||||
|
|
||||||
private void buildCalls(ClassGroup group)
|
private void buildCalls()
|
||||||
{
|
{
|
||||||
calls.clear();
|
calls.clear();
|
||||||
|
|
||||||
@@ -30,6 +33,9 @@ public class MethodMover implements Deobfuscator
|
|||||||
if (code == null)
|
if (code == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (m.isStatic())
|
||||||
|
continue; // only want member methods
|
||||||
|
|
||||||
Instructions ins = code.getInstructions();
|
Instructions ins = code.getInstructions();
|
||||||
for (Instruction i : ins.getInstructions())
|
for (Instruction i : ins.getInstructions())
|
||||||
{
|
{
|
||||||
@@ -50,8 +56,10 @@ public class MethodMover implements Deobfuscator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void look()
|
private int moveMethods()
|
||||||
{
|
{
|
||||||
|
int moved = 0;
|
||||||
|
|
||||||
for (Method m : calls.keySet())
|
for (Method m : calls.keySet())
|
||||||
{
|
{
|
||||||
Collection<Method> values = calls.getCollection(m);
|
Collection<Method> values = calls.getCollection(m);
|
||||||
@@ -76,15 +84,54 @@ public class MethodMover implements Deobfuscator
|
|||||||
if (caller == null)
|
if (caller == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
System.out.println(caller.getName() + " always calls " + m.getName() + " sz " + values.size());
|
if (m.getMethods().getClassFile() == caller)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
++moved;
|
||||||
|
move(m, caller);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return moved;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void move(Method method, ClassFile to)
|
||||||
|
{
|
||||||
|
assert method.getMethods().getClassFile() != to;
|
||||||
|
|
||||||
|
info.sigterm.deob.pool.Method newMethod = new info.sigterm.deob.pool.Method(
|
||||||
|
new info.sigterm.deob.pool.Class(to.getName()),
|
||||||
|
method.getNameAndType()
|
||||||
|
);
|
||||||
|
|
||||||
|
// move on instructions
|
||||||
|
for (ClassFile cf : group.getClasses())
|
||||||
|
{
|
||||||
|
for (Method m : cf.getMethods().getMethods())
|
||||||
|
{
|
||||||
|
Code code = m.getCode();
|
||||||
|
|
||||||
|
if (code == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
code.getInstructions().renameMethod(method, newMethod);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// move the method
|
||||||
|
method.getMethods().removeMethod(method);
|
||||||
|
to.getMethods().getMethods().add(method);
|
||||||
|
method.setMethods(to.getMethods());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run(ClassGroup group)
|
public void run(ClassGroup group)
|
||||||
{
|
{
|
||||||
|
this.group = group;
|
||||||
|
|
||||||
group.buildClassGraph();
|
group.buildClassGraph();
|
||||||
buildCalls(group);
|
buildCalls();
|
||||||
look();
|
int count = moveMethods();
|
||||||
|
|
||||||
|
System.out.println("Moved " + count + " methods");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -174,7 +174,13 @@ public class RenameUnique implements Deobfuscator
|
|||||||
{
|
{
|
||||||
Instructions instructions = method.getCode().getInstructions();
|
Instructions instructions = method.getCode().getInstructions();
|
||||||
for (Method m : methods)
|
for (Method m : methods)
|
||||||
instructions.renameMethod(m, name);
|
{
|
||||||
|
info.sigterm.deob.pool.Method newMethod = new info.sigterm.deob.pool.Method(
|
||||||
|
new info.sigterm.deob.pool.Class(m.getMethods().getClassFile().getName()),
|
||||||
|
new NameAndType(name, m.getNameAndType().getDescriptor())
|
||||||
|
);
|
||||||
|
instructions.renameMethod(m, newMethod);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user