From 1319295d7785ce688cb2d75666552ded7696cfe6 Mon Sep 17 00:00:00 2001 From: Graham Date: Tue, 27 Aug 2019 20:40:49 +0100 Subject: [PATCH] Separate remapping from the write{Pack,Jar} methods This is a prerequisite for removing dummy arguments - before the methods are remapped, removing an argument might cause the method to conflict with another method with the same name and descriptor as the replacement descriptor. --- .../dev/openrs2/asm/classpath/ClassPath.java | 7 +++ .../dev/openrs2/asm/classpath/Library.java | 44 +++++++++++----- .../transform/ClassForNameTransformer.java | 3 +- .../java/dev/openrs2/deob/Deobfuscator.java | 52 +++++++------------ .../openrs2/deob/remap/ClassNamePrefixer.java | 23 +------- 5 files changed, 61 insertions(+), 68 deletions(-) rename {deob/src/main/java/dev/openrs2/deob => asm/src/main/java/dev/openrs2/asm}/transform/ClassForNameTransformer.java (94%) diff --git a/asm/src/main/java/dev/openrs2/asm/classpath/ClassPath.java b/asm/src/main/java/dev/openrs2/asm/classpath/ClassPath.java index bbe767e5..0b613d75 100644 --- a/asm/src/main/java/dev/openrs2/asm/classpath/ClassPath.java +++ b/asm/src/main/java/dev/openrs2/asm/classpath/ClassPath.java @@ -9,6 +9,7 @@ import dev.openrs2.asm.MemberDesc; import dev.openrs2.asm.MemberRef; import dev.openrs2.util.collect.DisjointSet; import dev.openrs2.util.collect.ForestDisjointSet; +import org.objectweb.asm.commons.Remapper; import org.objectweb.asm.tree.ClassNode; public final class ClassPath { @@ -86,6 +87,12 @@ public final class ClassPath { return null; } + public void remap(Remapper remapper) { + for (var library : libraries) { + library.remap(remapper); + } + } + public DisjointSet createInheritedFieldSets() { var disjointSet = new ForestDisjointSet(); var ancestorCache = new HashMap>(); diff --git a/asm/src/main/java/dev/openrs2/asm/classpath/Library.java b/asm/src/main/java/dev/openrs2/asm/classpath/Library.java index e97aec24..90157443 100644 --- a/asm/src/main/java/dev/openrs2/asm/classpath/Library.java +++ b/asm/src/main/java/dev/openrs2/asm/classpath/Library.java @@ -5,6 +5,7 @@ import java.io.IOException; import java.io.SequenceInputStream; import java.nio.file.Files; import java.nio.file.Path; +import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.TreeMap; @@ -14,12 +15,13 @@ import java.util.jar.JarOutputStream; import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; +import dev.openrs2.asm.transform.ClassForNameTransformer; import dev.openrs2.util.io.DeterministicJarOutputStream; import dev.openrs2.util.io.SkipOutputStream; import org.apache.harmony.pack200.Pack200; import org.objectweb.asm.ClassReader; -import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.Opcodes; import org.objectweb.asm.commons.ClassRemapper; import org.objectweb.asm.commons.Remapper; import org.objectweb.asm.tree.ClassNode; @@ -112,33 +114,51 @@ public final class Library implements Iterable { return classes.values().iterator(); } - public void writeJar(Path path, Remapper remapper) throws IOException { + public void remap(Remapper remapper) { + var transformer = new ClassForNameTransformer(remapper); + var classNames = new HashSet(); + + for (var clazz : classes.values()) { + for (var method : clazz.methods) { + if ((method.access & (Opcodes.ACC_NATIVE | Opcodes.ACC_ABSTRACT)) == 0) { + transformer.transformCode(clazz, method); + } + } + + classNames.add(clazz.name); + } + + for (var name : classNames) { + var in = classes.remove(name); + + var out = new ClassNode(); + in.accept(new ClassRemapper(out, remapper)); + + classes.put(out.name, out); + } + } + + public void writeJar(Path path) throws IOException { logger.info("Writing jar {}", path); try (var out = new DeterministicJarOutputStream(Files.newOutputStream(path))) { for (var clazz : classes.values()) { - var name = clazz.name; var writer = new ClassWriter(0); - ClassVisitor visitor = new CheckClassAdapter(writer, true); - if (remapper != null) { - visitor = new ClassRemapper(visitor, remapper); - name = remapper.map(name); - } - clazz.accept(visitor); + clazz.accept(new CheckClassAdapter(writer, true)); - out.putNextEntry(new JarEntry(name + CLASS_SUFFIX)); + out.putNextEntry(new JarEntry(clazz.name + CLASS_SUFFIX)); out.write(writer.toByteArray()); } } } - public void writePack(Path path, Remapper remapper) throws IOException { + public void writePack(Path path) throws IOException { logger.info("Writing pack {}", path); var temp = Files.createTempFile(TEMP_PREFIX, JAR_SUFFIX); try { - writeJar(temp, remapper); + writeJar(temp); try ( var in = new JarInputStream(Files.newInputStream(temp)); diff --git a/deob/src/main/java/dev/openrs2/deob/transform/ClassForNameTransformer.java b/asm/src/main/java/dev/openrs2/asm/transform/ClassForNameTransformer.java similarity index 94% rename from deob/src/main/java/dev/openrs2/deob/transform/ClassForNameTransformer.java rename to asm/src/main/java/dev/openrs2/asm/transform/ClassForNameTransformer.java index b8208d46..3741d202 100644 --- a/deob/src/main/java/dev/openrs2/deob/transform/ClassForNameTransformer.java +++ b/asm/src/main/java/dev/openrs2/asm/transform/ClassForNameTransformer.java @@ -1,9 +1,8 @@ -package dev.openrs2.deob.transform; +package dev.openrs2.asm.transform; import java.util.List; import dev.openrs2.asm.InsnMatcher; -import dev.openrs2.asm.transform.Transformer; import org.objectweb.asm.commons.Remapper; import org.objectweb.asm.tree.AbstractInsnNode; import org.objectweb.asm.tree.ClassNode; diff --git a/deob/src/main/java/dev/openrs2/deob/Deobfuscator.java b/deob/src/main/java/dev/openrs2/deob/Deobfuscator.java index 6a51070f..7c188144 100644 --- a/deob/src/main/java/dev/openrs2/deob/Deobfuscator.java +++ b/deob/src/main/java/dev/openrs2/deob/Deobfuscator.java @@ -16,10 +16,9 @@ import dev.openrs2.deob.remap.TypedRemapper; import dev.openrs2.deob.transform.BitShiftTransformer; import dev.openrs2.deob.transform.BitwiseOpTransformer; import dev.openrs2.deob.transform.CanvasTransformer; -import dev.openrs2.deob.transform.ClassForNameTransformer; import dev.openrs2.deob.transform.CounterTransformer; -import dev.openrs2.deob.transform.DummyLocalTransformer; import dev.openrs2.deob.transform.DummyArgTransformer; +import dev.openrs2.deob.transform.DummyLocalTransformer; import dev.openrs2.deob.transform.ExceptionTracingTransformer; import dev.openrs2.deob.transform.FieldOrderTransformer; import dev.openrs2.deob.transform.OpaquePredicateTransformer; @@ -133,41 +132,30 @@ public final class Deobfuscator { } /* remap all class, method and field names */ - logger.info("Creating remappers"); - var remapper = TypedRemapper.create(classPath); - var glRemapper = TypedRemapper.create(glClassPath); - var unsignedRemapper = TypedRemapper.create(unsignedClassPath); - - /* transform Class.forName() calls */ - logger.info("Transforming Class.forName() calls"); - Transformer transformer = new ClassForNameTransformer(remapper); - transformer.transform(classPath); - - transformer = new ClassForNameTransformer(glRemapper); - transformer.transform(glClassPath); - - transformer = new ClassForNameTransformer(unsignedRemapper); - transformer.transform(unsignedClassPath); + logger.info("Remapping"); + classPath.remap(TypedRemapper.create(classPath)); + glClassPath.remap(TypedRemapper.create(glClassPath)); + unsignedClassPath.remap(TypedRemapper.create(unsignedClassPath)); /* write output jars */ logger.info("Writing output jars"); Files.createDirectories(output); - client.writeJar(output.resolve("runescape.jar"), remapper); - loader.writeJar(output.resolve("loader.jar"), remapper); - signLink.writeJar(output.resolve("signlink.jar"), remapper); - unpack.writeJar(output.resolve("unpack.jar"), remapper); - unpacker.writeJar(output.resolve("unpacker.jar"), remapper); - - gl.writeJar(output.resolve("jaggl.jar"), glRemapper); - glDri.writeJar(output.resolve("jaggl_dri.jar"), glRemapper); - glClient.writeJar(output.resolve("runescape_gl.jar"), glRemapper); - glLoader.writeJar(output.resolve("loader_gl.jar"), glRemapper); - glSignLink.writeJar(output.resolve("signlink_gl.jar"), glRemapper); - glUnpack.writeJar(output.resolve("unpack_gl.jar"), glRemapper); - glUnpacker.writeJar(output.resolve("unpacker_gl.jar"), glRemapper); - - unsignedClient.writeJar(output.resolve("runescape_unsigned.jar"), unsignedRemapper); + client.writeJar(output.resolve("runescape.jar")); + loader.writeJar(output.resolve("loader.jar")); + signLink.writeJar(output.resolve("signlink.jar")); + unpack.writeJar(output.resolve("unpack.jar")); + unpacker.writeJar(output.resolve("unpacker.jar")); + + gl.writeJar(output.resolve("jaggl.jar")); + glDri.writeJar(output.resolve("jaggl_dri.jar")); + glClient.writeJar(output.resolve("runescape_gl.jar")); + glLoader.writeJar(output.resolve("loader_gl.jar")); + glSignLink.writeJar(output.resolve("signlink_gl.jar")); + glUnpack.writeJar(output.resolve("unpack_gl.jar")); + glUnpacker.writeJar(output.resolve("unpacker_gl.jar")); + + unsignedClient.writeJar(output.resolve("runescape_unsigned.jar")); } } diff --git a/deob/src/main/java/dev/openrs2/deob/remap/ClassNamePrefixer.java b/deob/src/main/java/dev/openrs2/deob/remap/ClassNamePrefixer.java index 2de09493..dee2e5e9 100644 --- a/deob/src/main/java/dev/openrs2/deob/remap/ClassNamePrefixer.java +++ b/deob/src/main/java/dev/openrs2/deob/remap/ClassNamePrefixer.java @@ -3,11 +3,7 @@ package dev.openrs2.deob.remap; import java.util.HashMap; import dev.openrs2.asm.classpath.Library; -import dev.openrs2.deob.transform.ClassForNameTransformer; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.commons.ClassRemapper; import org.objectweb.asm.commons.SimpleRemapper; -import org.objectweb.asm.tree.ClassNode; public final class ClassNamePrefixer { public static void addPrefix(Library library, String prefix) { @@ -19,25 +15,8 @@ public final class ClassNamePrefixer { mapping.put(clazz.name, prefix + clazz.name); } } - var remapper = new SimpleRemapper(mapping); - var transformer = new ClassForNameTransformer(remapper); - for (var clazz : library) { - for (var method : clazz.methods) { - if ((method.access & (Opcodes.ACC_NATIVE | Opcodes.ACC_ABSTRACT)) == 0) { - transformer.transformCode(clazz, method); - } - } - } - - for (var name : mapping.keySet()) { - var in = library.remove(name); - - var out = new ClassNode(); - in.accept(new ClassRemapper(out, remapper)); - - library.add(out); - } + library.remap(new SimpleRemapper(mapping)); } private ClassNamePrefixer() {