Convert SignedClassUtils to Kotlin

pull/48/head
Graham 4 years ago
parent 64b8ea5fe7
commit 6425990b23
  1. 108
      deob/src/main/java/dev/openrs2/deob/SignedClassUtils.java
  2. 94
      deob/src/main/java/dev/openrs2/deob/SignedClassUtils.kt

@ -1,108 +0,0 @@
package dev.openrs2.deob;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import com.google.common.collect.Sets;
import dev.openrs2.asm.InsnMatcher;
import dev.openrs2.asm.classpath.Library;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.ClassRemapper;
import org.objectweb.asm.commons.SimpleRemapper;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.LdcInsnNode;
import org.objectweb.asm.tree.MethodNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public final class SignedClassUtils {
private static final Logger logger = LoggerFactory.getLogger(SignedClassUtils.class);
private static final InsnMatcher LOAD_SIGNED_CLASS_MATCHER = InsnMatcher.compile("LDC INVOKESTATIC ASTORE ALOAD GETFIELD ALOAD INVOKEVIRTUAL ALOAD INVOKEVIRTUAL POP");
public static void move(Library loader, Library client, Library signLink) {
/* find signed classes */
var signedClasses = findSignedClasses(loader);
logger.info("Identified signed classes {}", signedClasses);
var dependencies = findDependencies(loader, signedClasses);
logger.info("Identified signed class dependencies {}", dependencies);
/* rename dependencies of signed classes so they don't clash with client classes */
var mapping = new HashMap<String, String>();
for (var dependency : dependencies) {
mapping.put(dependency, "loader_" + dependency);
}
var remapper = new SimpleRemapper(mapping);
/* delete original signed classes (these have no dependencies) */
for (var name : signedClasses) {
client.remove(name);
}
/* move loader signed classes to signlink */
for (var name : Sets.union(signedClasses, dependencies)) {
var in = loader.remove(name);
var out = new ClassNode();
in.accept(new ClassRemapper(out, remapper));
signLink.add(out);
}
}
private static Set<String> findSignedClasses(Library loader) {
var clazz = loader.get("loader");
if (clazz == null) {
throw new IllegalArgumentException("Failed to find loader class");
}
for (var method : clazz.methods) {
if (method.name.equals("run") && method.desc.equals("()V")) {
return findSignedClasses(method);
}
}
throw new IllegalArgumentException("Failed to find loader.run() method");
}
private static Set<String> findSignedClasses(MethodNode method) {
var classes = new HashSet<String>();
LOAD_SIGNED_CLASS_MATCHER.match(method).forEach(match -> {
var ldc = (LdcInsnNode) match.get(0);
if (ldc.cst instanceof String && !ldc.cst.equals("unpack")) {
classes.add((String) ldc.cst);
}
});
return classes;
}
private static Set<String> findDependencies(Library loader, Set<String> signedClasses) {
var dependencies = new HashSet<String>();
for (var signedClass : signedClasses) {
var clazz = loader.get(signedClass);
for (var field : clazz.fields) {
var type = Type.getType(field.desc);
if (type.getSort() != Type.OBJECT) {
continue;
}
var name = type.getClassName();
if (loader.contains(name) && !signedClasses.contains(name)) {
dependencies.add(name);
}
}
}
return dependencies;
}
private SignedClassUtils() {
/* empty */
}
}

@ -0,0 +1,94 @@
package dev.openrs2.deob
import com.github.michaelbull.logging.InlineLogger
import dev.openrs2.asm.InsnMatcher
import dev.openrs2.asm.classpath.Library
import org.objectweb.asm.Type
import org.objectweb.asm.commons.ClassRemapper
import org.objectweb.asm.commons.SimpleRemapper
import org.objectweb.asm.tree.ClassNode
import org.objectweb.asm.tree.LdcInsnNode
import org.objectweb.asm.tree.MethodNode
object SignedClassUtils {
private val logger = InlineLogger()
private val LOAD_SIGNED_CLASS_MATCHER =
InsnMatcher.compile("LDC INVOKESTATIC ASTORE ALOAD GETFIELD ALOAD INVOKEVIRTUAL ALOAD INVOKEVIRTUAL POP")
@JvmStatic
fun move(loader: Library, client: Library, signLink: Library) {
// find signed classes
val signedClasses = findSignedClasses(loader)
logger.info { "Identified signed classes $signedClasses" }
val dependencies = findDependencies(loader, signedClasses)
logger.info { "Identified signed class dependencies $dependencies" }
// rename dependencies of signed classes so they don't clash with client classes
val mapping = mutableMapOf<String, String>()
for (dependency in dependencies) {
mapping[dependency] = "loader_$dependency"
}
val remapper = SimpleRemapper(mapping)
// delete original signed classes (these have no dependencies)
for (name in signedClasses) {
client.remove(name)
}
// move loader signed classes to signlink
for (name in signedClasses.union(dependencies)) {
val `in` = loader.remove(name)
val out = ClassNode()
`in`.accept(ClassRemapper(out, remapper))
signLink.add(out)
}
}
private fun findSignedClasses(loader: Library): Set<String> {
val clazz = loader["loader"] ?: throw IllegalArgumentException("Failed to find loader class")
val method = clazz.methods.find { it.name == "run" && it.desc == "()V" }
?: throw IllegalArgumentException("Failed to find loader.run() method")
return findSignedClasses(method)
}
private fun findSignedClasses(method: MethodNode): Set<String> {
val classes = mutableSetOf<String>()
LOAD_SIGNED_CLASS_MATCHER.match(method).forEach {
val ldc = it[0] as LdcInsnNode
val cst = ldc.cst
if (cst is String && cst != "unpack") {
classes.add(cst)
}
}
return classes
}
private fun findDependencies(loader: Library, signedClasses: Set<String>): Set<String> {
val dependencies = mutableSetOf<String>()
for (signedClass in signedClasses) {
val clazz = loader[signedClass]
for (field in clazz.fields) {
val type = Type.getType(field.desc)
if (type.sort != Type.OBJECT) {
continue
}
val name = type.className
if (loader.contains(name) && !signedClasses.contains(name)) {
dependencies.add(name)
}
}
}
return dependencies
}
}
Loading…
Cancel
Save