diff --git a/bundler/src/main/java/dev/openrs2/bundler/transform/HostCheckTransformer.java b/bundler/src/main/java/dev/openrs2/bundler/transform/HostCheckTransformer.java new file mode 100644 index 0000000000..fb413dd0b1 --- /dev/null +++ b/bundler/src/main/java/dev/openrs2/bundler/transform/HostCheckTransformer.java @@ -0,0 +1,90 @@ +package dev.openrs2.bundler.transform; + +import dev.openrs2.asm.InsnMatcher; +import dev.openrs2.asm.classpath.ClassPath; +import dev.openrs2.asm.transform.Transformer; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; +import org.objectweb.asm.tree.ClassNode; +import org.objectweb.asm.tree.InsnNode; +import org.objectweb.asm.tree.MethodInsnNode; +import org.objectweb.asm.tree.MethodNode; +import org.objectweb.asm.tree.analysis.AnalyzerException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public final class HostCheckTransformer extends Transformer { + private static final Logger logger = LoggerFactory.getLogger(HostCheckTransformer.class); + + private static final InsnMatcher GET_HOST_MATCHER = InsnMatcher.compile("INVOKEVIRTUAL INVOKEVIRTUAL INVOKEVIRTUAL"); + + private int hostChecks; + + @Override + protected void preTransform(ClassPath classPath) throws AnalyzerException { + hostChecks = 0; + } + + @Override + protected boolean transformCode(ClassNode clazz, MethodNode method) throws AnalyzerException { + if (Type.getReturnType(method.desc).getSort() != Type.BOOLEAN) { + return false; + } + + GET_HOST_MATCHER.match(method).forEach(match -> { + var insn1 = (MethodInsnNode) match.get(0); + if (!insn1.owner.equals(clazz.name)) { + return; + } + + if (!insn1.name.equals("getDocumentBase")) { + return; + } + + if (!insn1.desc.equals("()Ljava/net/URL;")) { + return; + } + + var insn2 = (MethodInsnNode) match.get(1); + if (!insn2.owner.equals("java/net/URL")) { + return; + } + + if (!insn2.name.equals("getHost")) { + return; + } + + if (!insn2.desc.equals("()Ljava/lang/String;")) { + return; + } + + var insn3 = (MethodInsnNode) match.get(2); + if (!insn3.owner.equals("java/lang/String")) { + return; + } + + if (!insn3.name.equals("toLowerCase")) { + return; + } + + if (!insn3.desc.equals("()Ljava/lang/String;")) { + return; + } + + method.instructions.clear(); + method.tryCatchBlocks.clear(); + + method.instructions.add(new InsnNode(Opcodes.ICONST_1)); + method.instructions.add(new InsnNode(Opcodes.IRETURN)); + + hostChecks++; + }); + + return false; + } + + @Override + protected void postTransform(ClassPath classPath) throws AnalyzerException { + logger.info("Removed {} host checks", hostChecks); + } +} diff --git a/deob/src/main/java/dev/openrs2/deob/Deobfuscator.java b/deob/src/main/java/dev/openrs2/deob/Deobfuscator.java index 09c5bf1364..437f4d9b28 100644 --- a/deob/src/main/java/dev/openrs2/deob/Deobfuscator.java +++ b/deob/src/main/java/dev/openrs2/deob/Deobfuscator.java @@ -10,6 +10,7 @@ import com.google.common.collect.ImmutableList; import dev.openrs2.asm.classpath.ClassPath; import dev.openrs2.asm.classpath.Library; import dev.openrs2.asm.transform.Transformer; +import dev.openrs2.bundler.transform.HostCheckTransformer; import dev.openrs2.bundler.transform.RightClickTransformer; import dev.openrs2.deob.remap.ClassNamePrefixer; import dev.openrs2.deob.remap.TypedRemapper; @@ -31,6 +32,7 @@ public final class Deobfuscator { private static final Logger logger = LoggerFactory.getLogger(Deobfuscator.class); private static final List TRANSFORMERS = List.of( + new HostCheckTransformer(), new RightClickTransformer(), new OpaquePredicateTransformer(), new ExceptionTracingTransformer(),