mirror of
https://github.com/revanced/revanced-patcher
synced 2024-11-24 05:16:22 +01:00
feat: add fuzzy resolver
fixed docs for MethodSignature & added tests for fuzzy resolver
This commit is contained in:
parent
18853f70a4
commit
7a56dca004
@ -46,20 +46,23 @@ data class MethodMetadata(
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Metadata for the Patcher, this contains things like how the Patcher should interpret this signature.
|
* Metadata for the Patcher, this contains things like how the Patcher should interpret this signature.
|
||||||
* @param method The method the Patcher should use to resolve the signature.
|
* @param method The method the resolver should use to resolve the signature.
|
||||||
*/
|
*/
|
||||||
data class PatcherMetadata(
|
data class PatcherMetadata(
|
||||||
val method: PatcherMethod
|
val method: ResolverMethod
|
||||||
)
|
)
|
||||||
|
|
||||||
interface PatcherMethod {
|
/**
|
||||||
|
* The method the resolver should use to resolve the signature.
|
||||||
|
*/
|
||||||
|
interface ResolverMethod {
|
||||||
/**
|
/**
|
||||||
* When comparing the signature, if one or more of the opcodes do not match, skip.
|
* When comparing the signature, if one or more of the opcodes do not match, skip.
|
||||||
*/
|
*/
|
||||||
class Direct : PatcherMethod
|
class Direct : ResolverMethod
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When comparing the signature, if [threshold] or more of the opcodes do not match, skip.
|
* When comparing the signature, if [threshold] or more of the opcodes do not match, skip.
|
||||||
*/
|
*/
|
||||||
class Fuzzy(val threshold: Int) : PatcherMethod
|
class Fuzzy(val threshold: Int) : ResolverMethod
|
||||||
}
|
}
|
@ -3,9 +3,9 @@ package app.revanced.patcher.signature.resolver
|
|||||||
import app.revanced.patcher.cache.MethodMap
|
import app.revanced.patcher.cache.MethodMap
|
||||||
import app.revanced.patcher.proxy.ClassProxy
|
import app.revanced.patcher.proxy.ClassProxy
|
||||||
import app.revanced.patcher.signature.MethodSignature
|
import app.revanced.patcher.signature.MethodSignature
|
||||||
|
import app.revanced.patcher.signature.ResolverMethod
|
||||||
import app.revanced.patcher.signature.PatternScanResult
|
import app.revanced.patcher.signature.PatternScanResult
|
||||||
import app.revanced.patcher.signature.SignatureResolverResult
|
import app.revanced.patcher.signature.SignatureResolverResult
|
||||||
import org.jf.dexlib2.Opcode
|
|
||||||
import org.jf.dexlib2.iface.ClassDef
|
import org.jf.dexlib2.iface.ClassDef
|
||||||
import org.jf.dexlib2.iface.Method
|
import org.jf.dexlib2.iface.Method
|
||||||
import org.jf.dexlib2.iface.instruction.Instruction
|
import org.jf.dexlib2.iface.instruction.Instruction
|
||||||
@ -75,10 +75,44 @@ internal class SignatureResolver(
|
|||||||
return if (signature.opcodes == null) {
|
return if (signature.opcodes == null) {
|
||||||
PatternScanResult(0, 0)
|
PatternScanResult(0, 0)
|
||||||
} else {
|
} else {
|
||||||
method.implementation?.instructions?.scanFor(signature.opcodes)
|
method.implementation?.instructions?.let {
|
||||||
|
compareOpcodes(signature, it)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun compareOpcodes(
|
||||||
|
signature: MethodSignature,
|
||||||
|
instructions: Iterable<Instruction>
|
||||||
|
): PatternScanResult? {
|
||||||
|
val count = instructions.count()
|
||||||
|
val pattern = signature.opcodes!!
|
||||||
|
val size = pattern.count()
|
||||||
|
var threshold = 0
|
||||||
|
if (signature.metadata.patcher.method is ResolverMethod.Fuzzy) {
|
||||||
|
threshold = signature.metadata.patcher.method.threshold
|
||||||
|
}
|
||||||
|
|
||||||
|
for (instructionIndex in 0 until count) {
|
||||||
|
var patternIndex = 0
|
||||||
|
var currentThreshold = threshold
|
||||||
|
while (instructionIndex + patternIndex < count) {
|
||||||
|
println("currentThreshold = $currentThreshold")
|
||||||
|
if (
|
||||||
|
instructions.elementAt(
|
||||||
|
instructionIndex + patternIndex
|
||||||
|
).opcode != pattern.elementAt(patternIndex)
|
||||||
|
&& currentThreshold-- == 0
|
||||||
|
) break
|
||||||
|
if (++patternIndex < size) continue
|
||||||
|
|
||||||
|
return PatternScanResult(instructionIndex, instructionIndex + patternIndex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
private fun compareParameterTypes(
|
private fun compareParameterTypes(
|
||||||
signature: Iterable<String>,
|
signature: Iterable<String>,
|
||||||
original: MutableList<out CharSequence>
|
original: MutableList<out CharSequence>
|
||||||
@ -89,20 +123,4 @@ internal class SignatureResolver(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private operator fun ClassDef.component1() = this
|
private operator fun ClassDef.component1() = this
|
||||||
private operator fun ClassDef.component2() = this.methods
|
private operator fun ClassDef.component2() = this.methods
|
||||||
|
|
||||||
private fun MutableIterable<Instruction>.scanFor(pattern: Iterable<Opcode>): PatternScanResult? {
|
|
||||||
val count = this.count()
|
|
||||||
val size = pattern.count()
|
|
||||||
for (instructionIndex in 0 until count) {
|
|
||||||
var patternIndex = 0
|
|
||||||
while (instructionIndex + patternIndex < count) {
|
|
||||||
if (this.elementAt(instructionIndex + patternIndex).opcode != pattern.elementAt(patternIndex)) break
|
|
||||||
if (++patternIndex < size) continue
|
|
||||||
|
|
||||||
return PatternScanResult(instructionIndex, instructionIndex + patternIndex)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null
|
|
||||||
}
|
|
@ -38,7 +38,7 @@ internal class PatcherTest {
|
|||||||
comment = "Main method of TestClass. Version 1.0.0"
|
comment = "Main method of TestClass. Version 1.0.0"
|
||||||
),
|
),
|
||||||
patcher = PatcherMetadata(
|
patcher = PatcherMetadata(
|
||||||
method = PatcherMethod.Fuzzy(2)
|
method = ResolverMethod.Fuzzy(2)
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
"V",
|
"V",
|
||||||
@ -46,7 +46,7 @@ internal class PatcherTest {
|
|||||||
listOf("[L"),
|
listOf("[L"),
|
||||||
listOf(
|
listOf(
|
||||||
Opcode.CONST_STRING,
|
Opcode.CONST_STRING,
|
||||||
Opcode.INVOKE_VIRTUAL,
|
Opcode.INVOKE_STATIC, // This is intentionally wrong to test the Fuzzy resolver.
|
||||||
Opcode.RETURN_VOID
|
Opcode.RETURN_VOID
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user