forked from openrs2/openrs2
parent
64b8ea5fe7
commit
6425990b23
@ -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…
Reference in new issue