Random thinking

This commit is contained in:
Adam
2015-10-20 16:50:12 -04:00
parent c2e1da7125
commit 6b41999fb5

View File

@@ -4,6 +4,7 @@ import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@@ -18,7 +19,6 @@ import net.runelite.deob.attributes.code.Instruction;
import net.runelite.deob.attributes.code.Instructions; import net.runelite.deob.attributes.code.Instructions;
import net.runelite.deob.attributes.code.instruction.types.FieldInstruction; import net.runelite.deob.attributes.code.instruction.types.FieldInstruction;
import net.runelite.deob.attributes.code.instruction.types.GetFieldInstruction; import net.runelite.deob.attributes.code.instruction.types.GetFieldInstruction;
import net.runelite.deob.attributes.code.instruction.types.InvokeInstruction;
import net.runelite.deob.attributes.code.instruction.types.PushConstantInstruction; import net.runelite.deob.attributes.code.instruction.types.PushConstantInstruction;
import net.runelite.deob.attributes.code.instruction.types.SetFieldInstruction; import net.runelite.deob.attributes.code.instruction.types.SetFieldInstruction;
import net.runelite.deob.attributes.code.instructions.IMul; import net.runelite.deob.attributes.code.instructions.IMul;
@@ -72,8 +72,8 @@ public class ModArith implements Deobfuscator
FieldInstruction fi = (FieldInstruction) ctx.getInstruction(); FieldInstruction fi = (FieldInstruction) ctx.getInstruction();
if (fi.getMyField() != field) //if (fi.getMyField() != field)
continue; // continue;
List<InstructionContext> ins = getInsInExpr(ctx, new HashSet()); List<InstructionContext> ins = getInsInExpr(ctx, new HashSet());
@@ -84,8 +84,8 @@ public class ModArith implements Deobfuscator
{ {
FieldInstruction ifi = (FieldInstruction) i.getInstruction(); FieldInstruction ifi = (FieldInstruction) i.getInstruction();
if (ifi.getMyField() != field) //if (ifi.getMyField() != field)
continue outer; // continue outer;
} }
} }
@@ -154,6 +154,40 @@ public class ModArith implements Deobfuscator
return list; return list;
} }
private MultiValueMap<Field, Integer> values2 = new MultiValueMap();
private void findUses2()
{
for (Frame f : execution.processedFrames)
for (InstructionContext ctx : f.getInstructions())
{
if (ctx.getInstruction() instanceof FieldInstruction)
{
FieldInstruction fi = (FieldInstruction) ctx.getInstruction();
if (fi.getMyField() == null)
continue;
if (!fi.getField().getNameAndType().getDescriptorType().getType().equals("I")
|| fi.getField().getNameAndType().getDescriptorType().getArrayDims() != 0)
continue;
List<InstructionContext> l = this.getInsInExpr(ctx, new HashSet());
for (InstructionContext i : l)
{
if (i.getInstruction() instanceof LDC_W)
{
LDC_W w = (LDC_W) i.getInstruction();
if (w.getConstant().getObject() instanceof Integer)
{
values2.put(fi.getMyField(), (int) w.getConstant().getObject());
}
}
}
}
}
}
private void findUses() private void findUses()
{ {
@@ -307,6 +341,101 @@ public class ModArith implements Deobfuscator
return p; return p;
} }
private Pair guess2(Field field, Collection<Integer> constants)
{
// multiply each by each,
// lowest number wins
int s1 = 0, s2 = 0;
int smallest = 0;
for (Integer i : constants)
{
for (Integer i2 : constants)
{
if (i == 0 || i2 == 0)
continue;
int result = i * i2;
if (result == 0)
continue;
if (smallest == 0 || result == 1 || Math.abs(result) < Math.abs(smallest))
{
s1 = i;
s2 = i2;
smallest = result;
}
}
}
if (smallest != 1)
{
if (DMath.isInversable(smallest))
{
// x*y=z*1
// divide x or y by z
if (DMath.isInversable(s1))
{
s2 = s2 * DMath.modInverse(smallest);
smallest = 1;
assert s1 * s2 == 1;
}
else if (DMath.isInversable(s2))
{
s1 = s1 * DMath.modInverse(smallest);
smallest = 1;
assert s1 * s2 == 1;
}
else
{
System.out.println("cant guess " + field.getName());
return null;
// I dont know what one to pick, maybe it doesnt matter
//assert false;
}
}
else
{
if (DMath.isInversable(s1))
{
int newTwo = DMath.modInverse(s1);
if (newTwo * smallest == s2)
{
s2 = newTwo;
smallest = 1;
assert s1 * s2 == 1;
}
}
else if (DMath.isInversable(s2))
{
int newTwo = DMath.modInverse(s2);
if (newTwo * smallest == s1)
{
s1 = newTwo;
smallest = 1;
assert s1 * s2 == 1;
}
}
else
{
System.out.println("cant guess " + field.getName());
return null;
//assert false;
}
}
// // pick the one that isn't inversible
//
// // set it to inverse(other)
//
// // check that inverse(other) * result == s2
}
//System.out.println(field.getName() + " " + s1 + " * " + s2 + " = " + smallest);
return null;
}
private Pair guess(Field field, Collection<Integer> values, boolean getter) private Pair guess(Field field, Collection<Integer> values, boolean getter)
{ {
Map<Integer, Integer> map = CollectionUtils.getCardinalityMap(values); // value -> how many times it occurs Map<Integer, Integer> map = CollectionUtils.getCardinalityMap(values); // value -> how many times it occurs
@@ -377,6 +506,27 @@ public class ModArith implements Deobfuscator
return null; return null;
} }
private void reduce2()
{
for (ClassFile cf : group.getClasses())
for (Field f : cf.getFields().getFields())
{
Collection<Integer> col = values2.getCollection(f);
if (col == null)
continue;
col = col.stream().filter(i -> DMath.isBig(i)).collect(Collectors.toList());
Set<Integer> set = new HashSet<>();
set.addAll(col);
//if (f.getName().equals("field297"))
{
this.guess2(f, set);
}
}
}
private void reduce() private void reduce()
{ {
for (ClassFile cf : group.getClasses()) for (ClassFile cf : group.getClasses())
@@ -385,47 +535,52 @@ public class ModArith implements Deobfuscator
Collection<Integer> getters = constantGetters.getCollection(f), Collection<Integer> getters = constantGetters.getCollection(f),
setters = constantSetters.getCollection(f); setters = constantSetters.getCollection(f);
List<Integer> all = new LinkedList();
if (getters != null) if (getters != null)
{ {
all.addAll(getters);
getters = getters.stream().filter(c -> DMath.isBig(c)).collect(Collectors.toList()); getters = getters.stream().filter(c -> DMath.isBig(c)).collect(Collectors.toList());
if (getters.isEmpty()) if (getters.isEmpty())
getters = null; getters = null;
} }
if (setters != null) if (setters != null)
{ {
all.addAll(setters);
setters = setters.stream().filter(c -> DMath.isBig(c)).collect(Collectors.toList()); setters = setters.stream().filter(c -> DMath.isBig(c)).collect(Collectors.toList());
if (setters.isEmpty()) if (setters.isEmpty())
setters = null; setters = null;
} }
if (f.getName().equals("field347")) this.guess2(f, all);
if (f.getName().equals("field33"))
{ {
int k=5; this.guess2(f, all);
} }
Pair answer = null; // Pair answer = null;
//
if (getters != null && setters != null) // if (getters != null && setters != null)
answer = reduce(getters, setters); // answer = reduce(getters, setters);
//
if (answer == null && getters != null) // if (answer == null && getters != null)
answer = guess(f, getters, true); // answer = guess(f, getters, true);
//
if (answer == null && setters != null) // if (answer == null && setters != null)
answer = guess(f, setters, false); // answer = guess(f, setters, false);
//
if (answer == null) // if (answer == null)
continue; // continue;
//
if (!this.isFieldObfuscated(execution, f)) // if (!this.isFieldObfuscated(execution, f))
{ // {
System.out.println("Skipping field " + f.getName() + " which isnt obfuscated"); // System.out.println("Skipping field " + f.getName() + " which isnt obfuscated");
continue; // continue;
} // }
//
answer.field = f; // answer.field = f;
pairs.add(answer); // pairs.add(answer);
} }
} }
@@ -525,13 +680,14 @@ public class ModArith implements Deobfuscator
pairs.clear(); pairs.clear();
constantGetters.clear();; constantGetters.clear();;
constantSetters.clear(); constantSetters.clear();
values2.clear();
execution = new Execution(group); execution = new Execution(group);
execution.populateInitialMethods(); execution.populateInitialMethods();
execution.run(); execution.run();
findUses(); findUses2();
reduce(); reduce2();
// Encryption encr = new Encryption(); // Encryption encr = new Encryption();
// for (Pair pair : pairs) // for (Pair pair : pairs)