feat(fingerprint)!: StringsScanResult for MethodFingerprint

BREAKING CHANGE: `MethodFingerprint` now has a field for `MethodFingerprintScanResult`. `MethodFingerprintScanResult` now holds the previous field `MethodFingerprint.patternScanResult`.

Signed-off-by: oSumAtrIX <johan.melkonyan1@web.de>
This commit is contained in:
oSumAtrIX 2022-09-21 01:09:53 +02:00
parent a2bb4004c7
commit 3813e28ac2
No known key found for this signature in database
GPG key ID: A9B3094ACDB604B4
2 changed files with 98 additions and 46 deletions

View file

@ -37,15 +37,65 @@ abstract class MethodFingerprint(
* Represents the result of a [MethodFingerprintUtils].
* @param method The matching method.
* @param classDef The [ClassDef] that contains the matching [method].
* @param patternScanResult Opcodes pattern scan result.
* @param scanResult The result of scanning for the [MethodFingerprint].
* @param data The [BytecodeData] this [MethodFingerprintResult] is attached to, to create proxies.
*/
data class MethodFingerprintResult(
val method: Method,
val classDef: ClassDef,
val patternScanResult: PatternScanResult?,
val scanResult: MethodFingerprintScanResult,
internal val data: BytecodeData
) {
/**
* The result of scanning on the [MethodFingerprint].
* @param patternScanResult The result of the pattern scan.
* @param stringsScanResult The result of the string scan.
*/
data class MethodFingerprintScanResult(
val patternScanResult: PatternScanResult?,
val stringsScanResult: StringsScanResult?
) {
/**
* The result of scanning strings on the [MethodFingerprint].
* @param matches The list of strings that were matched.
*/
data class StringsScanResult(val matches: List<StringMatch>){
/**
* Represents a match for a string at an index.
* @param string The string that was matched.
* @param index The index of the string.
*/
data class StringMatch(val string: String, val index: Int)
}
/**
* The result of a pattern scan.
* @param startIndex The start index of the instructions where to which this pattern matches.
* @param endIndex The end index of the instructions where to which this pattern matches.
* @param warnings A list of warnings considering this [PatternScanResult].
*/
data class PatternScanResult(
val startIndex: Int,
val endIndex: Int,
var warnings: List<Warning>? = null
) {
/**
* Represents warnings of the pattern scan.
* @param correctOpcode The opcode the instruction list has.
* @param wrongOpcode The opcode the pattern list of the signature currently has.
* @param instructionIndex The index of the opcode relative to the instruction list.
* @param patternIndex The index of the opcode relative to the pattern list from the signature.
*/
data class Warning(
val correctOpcode: Opcode,
val wrongOpcode: Opcode,
val instructionIndex: Int,
val patternIndex: Int,
)
}
}
/**
* Returns a mutable clone of [classDef]
*
@ -65,30 +115,4 @@ data class MethodFingerprintResult(
it.softCompareTo(this.method)
}
}
}
/**
* The result of a pattern scan.
* @param startIndex The start index of the instructions where to which this pattern matches.
* @param endIndex The end index of the instructions where to which this pattern matches.
* @param warnings A list of warnings considering this [PatternScanResult].
*/
data class PatternScanResult(
val startIndex: Int,
val endIndex: Int,
var warnings: List<Warning>? = null
) {
/**
* Represents warnings of the pattern scan.
* @param correctOpcode The opcode the instruction list has.
* @param wrongOpcode The opcode the pattern list of the signature currently has.
* @param instructionIndex The index of the opcode relative to the instruction list.
* @param patternIndex The index of the opcode relative to the pattern list from the signature.
*/
data class Warning(
val correctOpcode: Opcode,
val wrongOpcode: Opcode,
val instructionIndex: Int,
val patternIndex: Int,
)
}

View file

@ -7,14 +7,12 @@ import app.revanced.patcher.extensions.parametersEqual
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult
import app.revanced.patcher.fingerprint.method.impl.PatternScanResult
import org.jf.dexlib2.Opcode
import org.jf.dexlib2.iface.ClassDef
import org.jf.dexlib2.iface.Method
import org.jf.dexlib2.iface.instruction.Instruction
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
import org.jf.dexlib2.iface.reference.StringReference
/**
* Utility class for [MethodFingerprint]
*/
@ -73,21 +71,32 @@ object MethodFingerprintUtils {
if (methodFingerprint.customFingerprint != null && !methodFingerprint.customFingerprint!!(context))
return false
if (methodFingerprint.strings != null) {
val implementation = context.implementation ?: return false
val stringsScanResult: StringsScanResult? =
if (methodFingerprint.strings != null) {
StringsScanResult(buildList {
val implementation = context.implementation ?: return false
val stringsList = methodFingerprint.strings.toMutableList()
val stringsList = methodFingerprint.strings.toMutableList()
implementation.instructions.forEach { instruction ->
if (instruction.opcode.ordinal != Opcode.CONST_STRING.ordinal) return@forEach
implementation.instructions.forEach { instruction ->
if (instruction.opcode.ordinal != Opcode.CONST_STRING.ordinal) return@forEach
val string = ((instruction as ReferenceInstruction).reference as StringReference).string
val index = stringsList.indexOfFirst { it == string }
if (index != -1) stringsList.removeAt(index)
}
val string = ((instruction as ReferenceInstruction).reference as StringReference).string
val index = stringsList.indexOfFirst { it == string }
if (index == -1) return@forEach
if (stringsList.isNotEmpty()) return false
}
add(
StringMatch(
string,
index
)
)
stringsList.removeAt(index)
}
if (stringsList.isNotEmpty()) return false
})
} else null
val patternScanResult = if (methodFingerprint.opcodes != null) {
context.implementation?.instructions ?: return false
@ -95,14 +104,22 @@ object MethodFingerprintUtils {
context.patternScan(methodFingerprint) ?: return false
} else null
methodFingerprint.result = MethodFingerprintResult(context, classDef, patternScanResult, forData)
methodFingerprint.result = MethodFingerprintResult(
context,
classDef,
MethodFingerprintResult.MethodFingerprintScanResult(
patternScanResult,
stringsScanResult
),
forData
)
return true
}
private fun Method.patternScan(
fingerprint: MethodFingerprint
): PatternScanResult? {
): MethodFingerprintResult.MethodFingerprintScanResult.PatternScanResult? {
val instructions = this.implementation!!.instructions
val fingerprintFuzzyPatternScanThreshold = fingerprint.fuzzyScanThreshold
@ -131,7 +148,8 @@ object MethodFingerprintUtils {
continue
}
// the pattern is valid, generate warnings if fuzzyPatternScanMethod is FuzzyPatternScanMethod
val result = PatternScanResult(index, index + patternIndex)
val result =
MethodFingerprintResult.MethodFingerprintScanResult.PatternScanResult(index, index + patternIndex)
if (fingerprint.fuzzyPatternScanMethod !is FuzzyPatternScanMethod) return result
result.warnings = result.createWarnings(pattern, instructions)
@ -143,7 +161,10 @@ object MethodFingerprintUtils {
}
}
private fun PatternScanResult.createWarnings(
private typealias StringsScanResult = MethodFingerprintResult.MethodFingerprintScanResult.StringsScanResult
private typealias StringMatch = MethodFingerprintResult.MethodFingerprintScanResult.StringsScanResult.StringMatch
private fun MethodFingerprintResult.MethodFingerprintScanResult.PatternScanResult.createWarnings(
pattern: Iterable<Opcode?>, instructions: Iterable<Instruction>
) = buildList {
for ((patternIndex, instructionIndex) in (this@createWarnings.startIndex until this@createWarnings.endIndex).withIndex()) {
@ -152,7 +173,14 @@ private fun PatternScanResult.createWarnings(
if (patternOpcode == null || patternOpcode.ordinal == originalOpcode.ordinal) continue
this.add(PatternScanResult.Warning(originalOpcode, patternOpcode, instructionIndex, patternIndex))
this.add(
MethodFingerprintResult.MethodFingerprintScanResult.PatternScanResult.Warning(
originalOpcode,
patternOpcode,
instructionIndex,
patternIndex
)
)
}
}