From 337e98fb9527ff2c31e4064d2355ee4793278349 Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 14 Nov 2015 20:33:38 -0500 Subject: [PATCH] Include prev invokes for deciding if weve jumped before, fixes the graph jump test --- src/main/java/net/runelite/deob/Deob.java | 73 ++----------------- .../net/runelite/deob/execution/Frame.java | 10 ++- .../deob/execution/MethodContext.java | 59 ++++++++++++++- .../java/net/runelite/deob/util/JarUtil.java | 58 +++++++++++++++ .../deob/execution/ExecutionTest.java | 19 +++++ 5 files changed, 147 insertions(+), 72 deletions(-) create mode 100644 src/main/java/net/runelite/deob/util/JarUtil.java create mode 100644 src/test/java/net/runelite/deob/execution/ExecutionTest.java diff --git a/src/main/java/net/runelite/deob/Deob.java b/src/main/java/net/runelite/deob/Deob.java index 8f1745b9c6..09d4e778ab 100644 --- a/src/main/java/net/runelite/deob/Deob.java +++ b/src/main/java/net/runelite/deob/Deob.java @@ -1,34 +1,12 @@ package net.runelite.deob; -import net.runelite.deob.deobfuscators.FieldInliner; - -import java.io.ByteArrayOutputStream; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.FileOutputStream; +import java.io.File; import java.io.IOException; -import java.io.InputStream; -import java.util.Enumeration; -import java.util.jar.JarEntry; -import java.util.jar.JarFile; -import java.util.jar.JarOutputStream; -import java.util.jar.Manifest; -import net.runelite.deob.deobfuscators.ConstantParameter; -import net.runelite.deob.deobfuscators.IllegalStateExceptions; import net.runelite.deob.deobfuscators.MethodInliner; import net.runelite.deob.deobfuscators.rename.Rename; -import net.runelite.deob.deobfuscators.RenameUnique; -import net.runelite.deob.deobfuscators.RuntimeExceptions; -import net.runelite.deob.deobfuscators.UnreachedCode; -import net.runelite.deob.deobfuscators.UnusedClass; -import net.runelite.deob.deobfuscators.UnusedFields; import net.runelite.deob.deobfuscators.UnusedMethods; -import net.runelite.deob.deobfuscators.UnusedParameters; -import net.runelite.deob.deobfuscators.arithmetic.ModArith; -import net.runelite.deob.deobfuscators.arithmetic.MultiplicationDeobfuscator; -import net.runelite.deob.deobfuscators.arithmetic.MultiplyOneDeobfuscator; -import net.runelite.deob.deobfuscators.arithmetic.MultiplyZeroDeobfuscator; import net.runelite.deob.execution.Execution; +import net.runelite.deob.util.JarUtil; // XXX something to detect final fields and evaluate them // XXX ORDER IN WHICH FIELDS ARE ACCESSED @@ -41,7 +19,7 @@ public class Deob long start = System.currentTimeMillis(); - ClassGroup group = loadJar(args[0]); + ClassGroup group = JarUtil.loadJar(new File(args[0])); // run(group, new RenameUnique()); // @@ -115,7 +93,7 @@ public class Deob // make fields private - saveJar(group, args[1]); + JarUtil.saveJar(group, new File(args[1])); long end = System.currentTimeMillis(); System.out.println("Done in " + ((end - start) / 1000L) + "s"); @@ -123,8 +101,8 @@ public class Deob private static void merge() throws IOException { - ClassGroup group1 = loadJar("d:/rs/07/adamin1.jar"), - group2 = loadJar("d:/rs/07/adamin2.jar"); + ClassGroup group1 = JarUtil.loadJar(new File("d:/rs/07/adamin1.jar")), + group2 = JarUtil.loadJar(new File("d:/rs/07/adamin2.jar")); Rename rename = new Rename(); rename.run(group1, group2); @@ -135,45 +113,6 @@ public class Deob return name.length() <= 2 || name.startsWith("method") || name.startsWith("vmethod") || name.startsWith("field") || name.startsWith("class"); } - private static ClassGroup loadJar(String jarfile) throws IOException - { - ClassGroup group = new ClassGroup(); - - JarFile jar = new JarFile(jarfile); - for (Enumeration it = jar.entries(); it.hasMoreElements();) - { - JarEntry entry = it.nextElement(); - - if (!entry.getName().endsWith(".class")) - continue; - - InputStream is = jar.getInputStream(entry); - group.addClass(entry.getName(), new DataInputStream(is)); - } - jar.close(); - - return group; - } - - private static void saveJar(ClassGroup group, String jarfile) throws IOException - { - JarOutputStream jout = new JarOutputStream(new FileOutputStream(jarfile), new Manifest()); - - for (ClassFile cf : group.getClasses()) - { - JarEntry entry = new JarEntry(cf.getName() + ".class"); - jout.putNextEntry(entry); - - ByteArrayOutputStream bout = new ByteArrayOutputStream(); - cf.write(new DataOutputStream(bout)); - jout.write(bout.toByteArray()); - - jout.closeEntry(); - } - - jout.close(); - } - private static void run(ClassGroup group, Deobfuscator deob) { long bstart, bdur; diff --git a/src/main/java/net/runelite/deob/execution/Frame.java b/src/main/java/net/runelite/deob/execution/Frame.java index 4e17d7b382..21b231d3fa 100644 --- a/src/main/java/net/runelite/deob/execution/Frame.java +++ b/src/main/java/net/runelite/deob/execution/Frame.java @@ -31,6 +31,7 @@ public class Frame private List instructions = new ArrayList<>(); // instructions executed in this frame private MethodContext ctx; protected int prevVertex = -1; + private List prevInvokes; public Frame(Execution execution, Method method) { @@ -101,6 +102,7 @@ public class Frame this.variables = new Variables(other.variables); this.ctx = other.ctx; this.prevVertex = other.prevVertex; + this.prevInvokes = other.prevInvokes; } public Frame dup() @@ -193,6 +195,12 @@ public class Frame processExceptions(oldCur); + if (oldCur instanceof InvokeInstruction) + { + InvokeInstruction ii = (InvokeInstruction) oldCur; + this.prevInvokes = ii.getMethods(); + } + if (!executing) break; @@ -245,7 +253,7 @@ public class Frame assert to.getInstructions() == method.getCode().getInstructions(); assert method.getCode().getInstructions().getInstructions().contains(to); - if (ctx.hasJumped(from, to)) + if (ctx.hasJumped(this.prevInvokes, from, to)) { executing = false; return; diff --git a/src/main/java/net/runelite/deob/execution/MethodContext.java b/src/main/java/net/runelite/deob/execution/MethodContext.java index f6e20e7e2b..d9f4957bd6 100644 --- a/src/main/java/net/runelite/deob/execution/MethodContext.java +++ b/src/main/java/net/runelite/deob/execution/MethodContext.java @@ -8,15 +8,66 @@ import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import net.runelite.deob.Method; import net.runelite.deob.attributes.code.Instruction; import net.runelite.deob.attributes.code.instruction.types.InvokeInstruction; import net.runelite.deob.util.IdGen; import org.apache.commons.collections4.map.MultiValueMap; +class MIKey +{ + private List method; + private InstructionContext ictx; + + public MIKey(List method, InstructionContext ictx) + { + this.method = method; + this.ictx = ictx; + } + + @Override + public int hashCode() + { + int hash = 5; + hash = 61 * hash + Objects.hashCode(this.method); + hash = 61 * hash + Objects.hashCode(this.ictx); + return hash; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + if (obj == null) + { + return false; + } + if (getClass() != obj.getClass()) + { + return false; + } + final MIKey other = (MIKey) obj; + if (!Objects.equals(this.method, other.method)) + { + return false; + } + if (!Objects.equals(this.ictx, other.ictx)) + { + return false; + } + return true; + } + + +} + public class MethodContext { - private MultiValueMap visited = new MultiValueMap<>(); + private MultiValueMap visited = new MultiValueMap<>(); private IdGen ids = new IdGen(); private Map idMap = new HashMap<>(); private Map insMap = new HashMap<>(); @@ -32,13 +83,13 @@ public class MethodContext return graph; } - protected boolean hasJumped(InstructionContext from, Instruction to) + protected boolean hasJumped(List fromm, InstructionContext from, Instruction to) { - Collection i = visited.getCollection(from); + Collection i = visited.getCollection(new MIKey(fromm, from)); if (i != null && i.contains(to)) return true; - visited.put(from, to); + visited.put(new MIKey(fromm, from), to); return false; } diff --git a/src/main/java/net/runelite/deob/util/JarUtil.java b/src/main/java/net/runelite/deob/util/JarUtil.java new file mode 100644 index 0000000000..ecdfeab8a9 --- /dev/null +++ b/src/main/java/net/runelite/deob/util/JarUtil.java @@ -0,0 +1,58 @@ +package net.runelite.deob.util; + +import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Enumeration; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; +import java.util.jar.JarOutputStream; +import java.util.jar.Manifest; +import net.runelite.deob.ClassFile; +import net.runelite.deob.ClassGroup; + +public class JarUtil +{ + public static ClassGroup loadJar(File jarfile) throws IOException + { + ClassGroup group = new ClassGroup(); + + try (JarFile jar = new JarFile(jarfile)) + { + for (Enumeration it = jar.entries(); it.hasMoreElements();) + { + JarEntry entry = it.nextElement(); + + if (!entry.getName().endsWith(".class")) + continue; + + InputStream is = jar.getInputStream(entry); + group.addClass(entry.getName(), new DataInputStream(is)); + } + } + + return group; + } + + public static void saveJar(ClassGroup group, File jarfile) throws IOException + { + try (JarOutputStream jout = new JarOutputStream(new FileOutputStream(jarfile), new Manifest())) + { + for (ClassFile cf : group.getClasses()) + { + JarEntry entry = new JarEntry(cf.getName() + ".class"); + jout.putNextEntry(entry); + + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + cf.write(new DataOutputStream(bout)); + jout.write(bout.toByteArray()); + + jout.closeEntry(); + } + } + } +} diff --git a/src/test/java/net/runelite/deob/execution/ExecutionTest.java b/src/test/java/net/runelite/deob/execution/ExecutionTest.java new file mode 100644 index 0000000000..ae2bd8a67f --- /dev/null +++ b/src/test/java/net/runelite/deob/execution/ExecutionTest.java @@ -0,0 +1,19 @@ +package net.runelite.deob.execution; + +import java.io.File; +import net.runelite.deob.ClassGroup; +import net.runelite.deob.util.JarUtil; +import org.junit.Test; + +public class ExecutionTest +{ + @Test + public void test() throws Exception + { + ClassGroup group = JarUtil.loadJar(new File("d:/rs/07/adamin1.jar")); + + Execution e = new Execution(group); + e.populateInitialMethods(); + e.run(); + } +}