feat: add capability to filter from protobuf buffer
This commit is contained in:
parent
67d237c23f
commit
b738b6bf35
|
@ -0,0 +1,25 @@
|
|||
package app.revanced.patches.youtube.misc.litho.filter.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import org.jf.dexlib2.Opcode
|
||||
|
||||
object ProtobufBufferFingerprint : MethodFingerprint(
|
||||
opcodes = listOf(
|
||||
Opcode.IGET_OBJECT, // References the field required below.
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
Opcode.IF_NEZ,
|
||||
Opcode.CONST_4,
|
||||
Opcode.GOTO,
|
||||
Opcode.CHECK_CAST, // Casts the referenced field to a specific type that stores the protobuf buffer.
|
||||
Opcode.INVOKE_VIRTUAL
|
||||
)
|
||||
)
|
|
@ -17,6 +17,7 @@ import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
|||
import app.revanced.patches.youtube.misc.litho.filter.annotation.LithoFilterCompatibility
|
||||
import app.revanced.patches.youtube.misc.litho.filter.fingerprints.ComponentContextParserFingerprint
|
||||
import app.revanced.patches.youtube.misc.litho.filter.fingerprints.EmptyComponentBuilderFingerprint
|
||||
import app.revanced.patches.youtube.misc.litho.filter.fingerprints.ProtobufBufferFingerprint
|
||||
import app.revanced.patches.youtube.misc.litho.filter.fingerprints.ReadComponentIdentifierFingerprint
|
||||
import org.jf.dexlib2.iface.instruction.Instruction
|
||||
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
|
@ -32,7 +33,9 @@ class LithoFilterPatch : BytecodePatch(
|
|||
) {
|
||||
override fun execute(context: BytecodeContext): PatchResult {
|
||||
ComponentContextParserFingerprint.result?.also {
|
||||
arrayOf(EmptyComponentBuilderFingerprint, ReadComponentIdentifierFingerprint).forEach { fingerprint ->
|
||||
arrayOf(
|
||||
EmptyComponentBuilderFingerprint, ReadComponentIdentifierFingerprint, ProtobufBufferFingerprint
|
||||
).forEach { fingerprint ->
|
||||
if (!fingerprint.resolve(context, it.mutableMethod, it.mutableClass))
|
||||
return fingerprint.toErrorResult()
|
||||
}
|
||||
|
@ -45,26 +48,54 @@ class LithoFilterPatch : BytecodePatch(
|
|||
val builderMethodDescriptor = instruction(builderMethodIndex).descriptor
|
||||
val emptyComponentFieldDescriptor = instruction(emptyComponentFieldIndex).descriptor
|
||||
// Register is overwritten right after it is used in this patch, therefore free to clobber.
|
||||
val clobberedRegister = instruction(insertHookIndex - 1).twoRegisterA
|
||||
val free = instruction<TwoRegisterInstruction>(insertHookIndex - 1).registerA
|
||||
val free2 = instruction<OneRegisterInstruction>(insertHookIndex).registerA
|
||||
|
||||
@Suppress("UnnecessaryVariable")
|
||||
// The register, this patch clobbers, is previously used for the StringBuilder,
|
||||
// later on a new StringBuilder is instantiated on it.
|
||||
val stringBuilderRegister = clobberedRegister
|
||||
val stringBuilderRegister = free
|
||||
|
||||
val identifierRegister = instruction(ReadComponentIdentifierFingerprint.patternScanEndIndex).oneRegisterA
|
||||
val identifierRegister =
|
||||
instruction<OneRegisterInstruction>(ReadComponentIdentifierFingerprint.patternScanEndIndex).registerA
|
||||
|
||||
// Parameter that holds a ref to a type with a field that ref the protobuf buffer object.
|
||||
val protobufParameterNumber = 3
|
||||
|
||||
// Get the field that stores an protobuf buffer required below.
|
||||
val protobufBufferRefTypeRefFieldDescriptor =
|
||||
instruction(ProtobufBufferFingerprint.patternScanStartIndex).descriptor
|
||||
val protobufBufferRefTypeDescriptor =
|
||||
instruction(ProtobufBufferFingerprint.patternScanEndIndex - 1).descriptor
|
||||
val protobufBufferFieldDescriptor = "$protobufBufferRefTypeDescriptor->b:Ljava/nio/ByteBuffer;"
|
||||
|
||||
addInstructions(
|
||||
insertHookIndex, // right after setting the component.pathBuilder field,
|
||||
insertHookIndex, // right after setting the component.pathBuilder field.
|
||||
"""
|
||||
invoke-static {v$stringBuilderRegister, v$identifierRegister}, Lapp/revanced/integrations/patches/LithoFilterPatch;->filter(Ljava/lang/StringBuilder;Ljava/lang/String;)Z
|
||||
move-result v$clobberedRegister
|
||||
if-eqz v$clobberedRegister, :not_an_ad
|
||||
move-object/from16 v$clobberedRegister, p1
|
||||
invoke-static {v$clobberedRegister}, $builderMethodDescriptor
|
||||
move-result-object v$clobberedRegister
|
||||
iget-object v$clobberedRegister, v$clobberedRegister, $emptyComponentFieldDescriptor
|
||||
return-object v$clobberedRegister
|
||||
# Get the protobuf buffer object.
|
||||
|
||||
move-object/from16 v$free2, p$protobufParameterNumber
|
||||
iget-object v$free2, v$free2, $protobufBufferRefTypeRefFieldDescriptor
|
||||
check-cast v$free2, $protobufBufferRefTypeDescriptor
|
||||
|
||||
# Register "free" now holds the protobuf buffer object
|
||||
|
||||
iget-object v$free2, v$free2, $protobufBufferFieldDescriptor
|
||||
|
||||
# Invoke the filter method.
|
||||
|
||||
invoke-static { v$stringBuilderRegister, v$identifierRegister, v$free2 }, $FILTER_METHOD_DESCRIPTOR
|
||||
move-result v$free
|
||||
|
||||
if-eqz v$free, :not_an_ad
|
||||
|
||||
# If the filter method returned true, then return a replacement empty component.
|
||||
|
||||
move-object/from16 v$free, p1
|
||||
invoke-static {v$free}, $builderMethodDescriptor
|
||||
move-result-object v$free
|
||||
iget-object v$free, v$free, $emptyComponentFieldDescriptor
|
||||
return-object v$free
|
||||
""",
|
||||
listOf(ExternalLabel("not_an_ad", instruction(insertHookIndex)))
|
||||
)
|
||||
|
@ -75,16 +106,20 @@ class LithoFilterPatch : BytecodePatch(
|
|||
}
|
||||
|
||||
private companion object {
|
||||
private val MethodFingerprint.patternScanResult
|
||||
get() = result!!.scanResult.patternScanResult!!
|
||||
|
||||
val MethodFingerprint.patternScanEndIndex
|
||||
get() = result!!.scanResult.patternScanResult!!.endIndex
|
||||
get() = patternScanResult.endIndex
|
||||
|
||||
val MethodFingerprint.patternScanStartIndex
|
||||
get() = patternScanResult.startIndex
|
||||
|
||||
val Instruction.descriptor
|
||||
get() = (this as ReferenceInstruction).reference.toString()
|
||||
|
||||
val Instruction.oneRegisterA
|
||||
get() = (this as OneRegisterInstruction).registerA
|
||||
|
||||
val Instruction.twoRegisterA
|
||||
get() = (this as TwoRegisterInstruction).registerA
|
||||
const val FILTER_METHOD_DESCRIPTOR =
|
||||
"Lapp/revanced/integrations/patches/litho/LithoFilterPatch;" +
|
||||
"->filter(Ljava/lang/StringBuilder;Ljava/lang/String;Ljava/nio/ByteBuffer;)Z"
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue