Maintain static member grouping during deobfuscation

Some static members are not scrambled in the client. Maintaining a
one-to-one mapping between instanced and static classes makes
refactoring easier in these cases.

The browser control filter is removed as we now get the same
functionality for free.

Signed-off-by: Graham <gpe@openrs2.org>
Graham 4 years ago
parent e08f355e6f
commit ac9b132937
  1. 61
      deob/src/main/kotlin/org/openrs2/deob/filter/BrowserControlFilter.kt
  2. 20
      deob/src/main/kotlin/org/openrs2/deob/remap/StaticClassGenerator.kt
  3. 10
      deob/src/main/kotlin/org/openrs2/deob/remap/StaticClassMapping.kt
  4. 6
      deob/src/main/kotlin/org/openrs2/deob/remap/StaticFieldUnscrambler.kt
  5. 6
      deob/src/main/kotlin/org/openrs2/deob/remap/StaticMethodUnscrambler.kt
  6. 14
      deob/src/main/kotlin/org/openrs2/deob/remap/TypedRemapper.kt

@ -1,61 +0,0 @@
package org.openrs2.deob.filter
import com.github.michaelbull.logging.InlineLogger
import org.objectweb.asm.tree.ClassNode
import org.objectweb.asm.tree.MethodInsnNode
import org.openrs2.asm.classpath.ClassPath
import org.openrs2.asm.filter.AnyMemberFilter
import org.openrs2.asm.filter.MemberFilter
import org.openrs2.asm.hasCode
public class BrowserControlFilter private constructor(private val clazz: String) : MemberFilter {
override fun matches(owner: String, name: String, desc: String): Boolean {
return clazz == owner
}
public companion object {
private val logger = InlineLogger()
public fun create(classPath: ClassPath): MemberFilter {
val browserControlClass = findBrowserControlClass(classPath)
return if (browserControlClass != null) {
logger.info { "Identified browser control class $browserControlClass" }
BrowserControlFilter(browserControlClass)
} else {
logger.warn { "Failed to identify browser control class" }
AnyMemberFilter
}
}
private fun findBrowserControlClass(classPath: ClassPath): String? {
for (library in classPath.libraries) {
for (clazz in library) {
if (isBrowserControlClass(clazz)) {
return clazz.name
}
}
}
return null
}
private fun isBrowserControlClass(clazz: ClassNode): Boolean {
for (method in clazz.methods) {
if (!method.hasCode) {
continue
}
for (insn in method.instructions) {
if (insn !is MethodInsnNode) {
continue
} else if (insn.owner == "netscape/javascript/JSObject") {
return true
}
}
}
return false
}
}
}

@ -1,20 +0,0 @@
package org.openrs2.deob.remap
public class StaticClassGenerator(private val generator: NameGenerator, private val maxMembers: Int) {
private var lastClass: String? = null
private var members = 0
public fun generate(): String {
var clazz = lastClass
if (clazz == null || members >= maxMembers) {
clazz = generator.generate("Static")
lastClass = clazz
members = 1
} else {
members++
}
return clazz
}
}

@ -0,0 +1,10 @@
package org.openrs2.deob.remap
public class StaticClassMapping {
private val nameGenerator = NameGenerator()
private val mapping = mutableMapOf<String, String>()
public operator fun get(name: String): String {
return mapping.computeIfAbsent(name) { nameGenerator.generate("Static") }
}
}

@ -19,10 +19,8 @@ public class StaticFieldUnscrambler(
private val scrambledLibraries: Set<String>, private val scrambledLibraries: Set<String>,
private val nameMap: NameMap, private val nameMap: NameMap,
private val inheritedFieldSets: DisjointSet<MemberRef>, private val inheritedFieldSets: DisjointSet<MemberRef>,
staticClassNameGenerator: NameGenerator private val staticClassMapping: StaticClassMapping
) { ) {
private val generator = StaticClassGenerator(staticClassNameGenerator, MAX_FIELDS_PER_CLASS)
public fun unscramble(): Map<DisjointSet.Partition<MemberRef>, StaticField> { public fun unscramble(): Map<DisjointSet.Partition<MemberRef>, StaticField> {
val fields = mutableMapOf<DisjointSet.Partition<MemberRef>, StaticField>() val fields = mutableMapOf<DisjointSet.Partition<MemberRef>, StaticField>()
@ -50,7 +48,7 @@ public class StaticFieldUnscrambler(
val member = MemberRef(clazz, field) val member = MemberRef(clazz, field)
val partition = inheritedFieldSets[member]!! val partition = inheritedFieldSets[member]!!
val owner = nameMap.mapFieldOwner(partition, generator.generate()) val owner = nameMap.mapFieldOwner(partition, staticClassMapping[clazz.name])
fields[partition] = StaticField("${library.name}!$owner", simpleInitializers[desc]) fields[partition] = StaticField("${library.name}!$owner", simpleInitializers[desc])
} }
} }

@ -13,10 +13,8 @@ public class StaticMethodUnscrambler(
private val scrambledLibraries: Set<String>, private val scrambledLibraries: Set<String>,
private val nameMap: NameMap, private val nameMap: NameMap,
private val inheritedMethodSets: DisjointSet<MemberRef>, private val inheritedMethodSets: DisjointSet<MemberRef>,
staticClassNameGenerator: NameGenerator private val staticClassMapping: StaticClassMapping
) { ) {
private val generator = StaticClassGenerator(staticClassNameGenerator, MAX_METHODS_PER_CLASS)
public fun unscramble(): Map<DisjointSet.Partition<MemberRef>, String> { public fun unscramble(): Map<DisjointSet.Partition<MemberRef>, String> {
val owners = mutableMapOf<DisjointSet.Partition<MemberRef>, String>() val owners = mutableMapOf<DisjointSet.Partition<MemberRef>, String>()
@ -37,7 +35,7 @@ public class StaticMethodUnscrambler(
val member = MemberRef(clazz, method) val member = MemberRef(clazz, method)
val partition = inheritedMethodSets[member]!! val partition = inheritedMethodSets[member]!!
val owner = nameMap.mapMethodOwner(partition, generator.generate()) val owner = nameMap.mapMethodOwner(partition, staticClassMapping[clazz.name])
owners[partition] = "${library.name}!$owner" owners[partition] = "${library.name}!$owner"
} }
} }

@ -5,10 +5,8 @@ import org.objectweb.asm.tree.AbstractInsnNode
import org.openrs2.asm.MemberRef import org.openrs2.asm.MemberRef
import org.openrs2.asm.classpath.ClassPath import org.openrs2.asm.classpath.ClassPath
import org.openrs2.asm.classpath.ExtendedRemapper import org.openrs2.asm.classpath.ExtendedRemapper
import org.openrs2.asm.filter.UnionMemberFilter
import org.openrs2.deob.ArgRef import org.openrs2.deob.ArgRef
import org.openrs2.deob.Profile import org.openrs2.deob.Profile
import org.openrs2.deob.filter.BrowserControlFilter
import org.openrs2.deob.util.map.NameMap import org.openrs2.deob.util.map.NameMap
import org.openrs2.util.collect.DisjointSet import org.openrs2.util.collect.DisjointSet
@ -98,24 +96,22 @@ public class TypedRemapper private constructor(
verifyMemberMapping(fields, profile.maxObfuscatedNameLen) verifyMemberMapping(fields, profile.maxObfuscatedNameLen)
verifyMemberMapping(methods, profile.maxObfuscatedNameLen) verifyMemberMapping(methods, profile.maxObfuscatedNameLen)
val browserControlFilter = BrowserControlFilter.create(classPath) val staticClassMapping = StaticClassMapping()
val staticClassNameGenerator = NameGenerator()
val staticFields = StaticFieldUnscrambler( val staticFields = StaticFieldUnscrambler(
classPath, classPath,
UnionMemberFilter(profile.excludedFields, browserControlFilter), profile.excludedFields,
profile.scrambledLibraries, profile.scrambledLibraries,
nameMap, nameMap,
inheritedFieldSets, inheritedFieldSets,
staticClassNameGenerator staticClassMapping
).unscramble() ).unscramble()
val staticMethods = StaticMethodUnscrambler( val staticMethods = StaticMethodUnscrambler(
classPath, classPath,
UnionMemberFilter(profile.excludedMethods, browserControlFilter), profile.excludedMethods,
profile.scrambledLibraries, profile.scrambledLibraries,
nameMap, nameMap,
inheritedMethodSets, inheritedMethodSets,
staticClassNameGenerator staticClassMapping
).unscramble() ).unscramble()
return TypedRemapper( return TypedRemapper(

Loading…
Cancel
Save