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.
pull/48/head
Graham 5 years ago
parent c6d184c5c5
commit 1319295d77
  1. 7
      asm/src/main/java/dev/openrs2/asm/classpath/ClassPath.java
  2. 44
      asm/src/main/java/dev/openrs2/asm/classpath/Library.java
  3. 3
      asm/src/main/java/dev/openrs2/asm/transform/ClassForNameTransformer.java
  4. 52
      deob/src/main/java/dev/openrs2/deob/Deobfuscator.java
  5. 23
      deob/src/main/java/dev/openrs2/deob/remap/ClassNamePrefixer.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<MemberRef> createInheritedFieldSets() {
var disjointSet = new ForestDisjointSet<MemberRef>();
var ancestorCache = new HashMap<ClassMetadata, ImmutableSet<MemberDesc>>();

@ -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<ClassNode> {
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<String>();
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));

@ -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;

@ -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"));
}
}

@ -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() {

Loading…
Cancel
Save