From 60bcf6658a22192473fe54a07d70caf9636e5c48 Mon Sep 17 00:00:00 2001 From: inotia00 Date: Mon, 27 Feb 2023 22:49:47 +0900 Subject: [PATCH] make litho patch to abstract patch --- .../fingerprints/LithoFingerprint.kt | 7 +- .../fingerprints/LithoObjectFingerprint.kt | 16 ++ .../patch/litho/AbstractLithoFilterPatch.kt | 93 ++++++++++ .../ComponentContextParserFingerprint.kt | 20 --- .../EmptyComponentBuilderFingerprint.kt | 10 -- .../bytecode/patch/GeneralAdsBytecodePatch.kt | 170 +++++++++++------- .../patch/GeneralAdsSecondaryBytecodePatch.kt | 139 -------------- .../general/resource/patch/GeneralAdsPatch.kt | 2 - .../misc/litho/patch/LithoFilterPatch.kt | 57 +----- 9 files changed, 229 insertions(+), 285 deletions(-) rename src/main/kotlin/app/revanced/patches/{youtube/misc/litho => shared}/fingerprints/LithoFingerprint.kt (67%) create mode 100644 src/main/kotlin/app/revanced/patches/shared/fingerprints/LithoObjectFingerprint.kt create mode 100644 src/main/kotlin/app/revanced/patches/shared/patch/litho/AbstractLithoFilterPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/ads/general/bytecode/fingerprints/ComponentContextParserFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/ads/general/bytecode/fingerprints/EmptyComponentBuilderFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/ads/general/bytecode/patch/GeneralAdsSecondaryBytecodePatch.kt diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/litho/fingerprints/LithoFingerprint.kt b/src/main/kotlin/app/revanced/patches/shared/fingerprints/LithoFingerprint.kt similarity index 67% rename from src/main/kotlin/app/revanced/patches/youtube/misc/litho/fingerprints/LithoFingerprint.kt rename to src/main/kotlin/app/revanced/patches/shared/fingerprints/LithoFingerprint.kt index 43e16854a..fb05121f6 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/litho/fingerprints/LithoFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/shared/fingerprints/LithoFingerprint.kt @@ -1,11 +1,16 @@ -package app.revanced.patches.youtube.misc.litho.fingerprints +package app.revanced.patches.shared.fingerprints import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import org.jf.dexlib2.AccessFlags +import org.jf.dexlib2.Opcode object LithoFingerprint : MethodFingerprint( returnType = "L", access = AccessFlags.PUBLIC or AccessFlags.FINAL, + opcodes = listOf( + Opcode.INVOKE_VIRTUAL, + Opcode.IF_EQZ + ), strings = listOf("Element missing type extension") ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/shared/fingerprints/LithoObjectFingerprint.kt b/src/main/kotlin/app/revanced/patches/shared/fingerprints/LithoObjectFingerprint.kt new file mode 100644 index 000000000..6202924b1 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/shared/fingerprints/LithoObjectFingerprint.kt @@ -0,0 +1,16 @@ +package app.revanced.patches.shared.fingerprints + +import app.revanced.patcher.extensions.or +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint +import org.jf.dexlib2.AccessFlags +import org.jf.dexlib2.Opcode + +object LithoObjectFingerprint : MethodFingerprint( + returnType = "L", + access = AccessFlags.PUBLIC or AccessFlags.FINAL, + opcodes = listOf( + Opcode.CONST_STRING, + Opcode.INVOKE_VIRTUAL + ), + strings = listOf("Element missing type extension") +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/shared/patch/litho/AbstractLithoFilterPatch.kt b/src/main/kotlin/app/revanced/patches/shared/patch/litho/AbstractLithoFilterPatch.kt new file mode 100644 index 000000000..e159b2703 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/shared/patch/litho/AbstractLithoFilterPatch.kt @@ -0,0 +1,93 @@ +package app.revanced.patches.shared.patch.litho + +import app.revanced.extensions.toErrorResult +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.data.BytecodeContext +import app.revanced.patcher.extensions.addInstructions +import app.revanced.patcher.extensions.instruction +import app.revanced.patcher.patch.BytecodePatch +import app.revanced.patcher.patch.PatchResult +import app.revanced.patcher.patch.PatchResultSuccess +import app.revanced.patcher.util.smali.ExternalLabel +import app.revanced.patches.shared.fingerprints.LithoFingerprint +import app.revanced.patches.shared.fingerprints.LithoObjectFingerprint +import org.jf.dexlib2.Opcode +import org.jf.dexlib2.builder.instruction.BuilderInstruction21c +import org.jf.dexlib2.builder.instruction.BuilderInstruction35c +import org.jf.dexlib2.iface.instruction.OneRegisterInstruction +import org.jf.dexlib2.iface.instruction.ReferenceInstruction +import org.jf.dexlib2.iface.instruction.TwoRegisterInstruction +import org.jf.dexlib2.iface.reference.FieldReference +import org.jf.dexlib2.iface.reference.MethodReference + +@Version("0.0.1") +abstract class AbstractLithoFilterPatch( + private val descriptor: String +) : BytecodePatch( + listOf( + LithoFingerprint, + LithoObjectFingerprint + ) +) { + override fun execute(context: BytecodeContext): PatchResult { + + /* + * Compatible with both YouTube and YouTube Music + * But not yet implemented in Music integrations + */ + LithoObjectFingerprint.result?.let { + val endIndex = it.scanResult.patternScanResult!!.endIndex + objectRegister = (it.mutableMethod.instruction(endIndex) as BuilderInstruction35c).registerC + } ?: return LithoObjectFingerprint.toErrorResult() + + LithoFingerprint.result?.let { result -> + val endIndex = result.scanResult.patternScanResult!!.endIndex + val method = result.mutableMethod + + with (method.implementation!!.instructions) { + val targetIndex = indexOfFirst { + it.opcode == Opcode.CONST_STRING && + (it as BuilderInstruction21c).reference.toString() == "Element missing type extension" + } + 2 + + val builderMethodDescriptor = (elementAt(targetIndex) as ReferenceInstruction).reference as MethodReference + val emptyComponentFieldDescriptor = (elementAt(targetIndex + 2) as ReferenceInstruction).reference as FieldReference + + val identifierRegister = (method.instruction(endIndex) as OneRegisterInstruction).registerA + val bytebufferRegister = method.implementation!!.registerCount - method.parameters.size + 2 + val secondParameter = method.parameters[2] + + filter { instruction -> + val fieldReference = (instruction as? ReferenceInstruction)?.reference as? FieldReference + fieldReference?.let { it.type == "Ljava/lang/StringBuilder;" } == true + }.forEach { instruction -> + val insertIndex = indexOf(instruction) + 1 + + val stringBuilderRegister = (method.instruction(insertIndex) as OneRegisterInstruction).registerA + val clobberedRegister = (method.instruction(insertIndex + 1) as TwoRegisterInstruction).registerA + + method.addInstructions( + insertIndex, // right after setting the component.pathBuilder field, + """ + move-object/from16 v$clobberedRegister, v$bytebufferRegister + iget-object v$clobberedRegister, v$clobberedRegister, $secondParameter->b:Ljava/nio/ByteBuffer; + invoke-static {v$stringBuilderRegister, v$identifierRegister, v$objectRegister, v$clobberedRegister}, $descriptor->filter(Ljava/lang/StringBuilder;Ljava/lang/String;Ljava/lang/Object;Ljava/nio/ByteBuffer;)Z + move-result v$clobberedRegister + if-eqz v$clobberedRegister, :not_an_ad + move-object/from16 v$identifierRegister, p1 + invoke-static {v$identifierRegister}, $builderMethodDescriptor + move-result-object v0 + iget-object v0, v0, $emptyComponentFieldDescriptor + return-object v0 + """,listOf(ExternalLabel("not_an_ad", method.instruction(insertIndex))) + ) + } + } + } ?: return LithoFingerprint.toErrorResult() + + return PatchResultSuccess() + } + private companion object { + private var objectRegister: Int = 3 + } +} diff --git a/src/main/kotlin/app/revanced/patches/youtube/ads/general/bytecode/fingerprints/ComponentContextParserFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/ads/general/bytecode/fingerprints/ComponentContextParserFingerprint.kt deleted file mode 100644 index 13225beb7..000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/ads/general/bytecode/fingerprints/ComponentContextParserFingerprint.kt +++ /dev/null @@ -1,20 +0,0 @@ -package app.revanced.patches.youtube.ads.general.bytecode.fingerprints - -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import org.jf.dexlib2.Opcode - -object ComponentContextParserFingerprint : MethodFingerprint( - opcodes = listOf( - Opcode.INVOKE_INTERFACE, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - Opcode.INVOKE_VIRTUAL, - Opcode.GOTO, - Opcode.INVOKE_VIRTUAL, - Opcode.CONST_16, - Opcode.INVOKE_VIRTUAL, - Opcode.IPUT_OBJECT, - Opcode.NEW_INSTANCE - ), - strings = listOf("LoggingProperties are not in proto format") -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/ads/general/bytecode/fingerprints/EmptyComponentBuilderFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/ads/general/bytecode/fingerprints/EmptyComponentBuilderFingerprint.kt deleted file mode 100644 index 0ac4f30d7..000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/ads/general/bytecode/fingerprints/EmptyComponentBuilderFingerprint.kt +++ /dev/null @@ -1,10 +0,0 @@ -package app.revanced.patches.youtube.ads.general.bytecode.fingerprints - -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import org.jf.dexlib2.Opcode - -object EmptyComponentBuilderFingerprint : MethodFingerprint( - opcodes = listOf( - Opcode.INVOKE_STATIC_RANGE - ), -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/ads/general/bytecode/patch/GeneralAdsBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/ads/general/bytecode/patch/GeneralAdsBytecodePatch.kt index dac9378f0..67976e948 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/ads/general/bytecode/patch/GeneralAdsBytecodePatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/ads/general/bytecode/patch/GeneralAdsBytecodePatch.kt @@ -1,98 +1,142 @@ package app.revanced.patches.youtube.ads.general.bytecode.patch -import app.revanced.extensions.toErrorResult +import app.revanced.extensions.findMutableMethodOf +import app.revanced.extensions.injectHideCall +import app.revanced.extensions.toResult import app.revanced.patcher.annotation.Name import app.revanced.patcher.annotation.Version import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.extensions.addInstructions import app.revanced.patcher.extensions.instruction -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultError -import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.annotations.DependsOn +import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patcher.util.smali.ExternalLabel import app.revanced.patches.shared.annotation.YouTubeCompatibility import app.revanced.patches.shared.patch.mapping.ResourceMappingPatch -import app.revanced.patches.youtube.ads.general.bytecode.fingerprints.ComponentContextParserFingerprint -import app.revanced.patches.youtube.ads.general.bytecode.fingerprints.EmptyComponentBuilderFingerprint import app.revanced.util.bytecode.BytecodeHelper.updatePatchStatus import app.revanced.util.integrations.Constants.ADS_PATH import org.jf.dexlib2.Opcode -import org.jf.dexlib2.builder.instruction.BuilderInstruction21s -import org.jf.dexlib2.iface.instruction.Instruction -import org.jf.dexlib2.iface.instruction.OneRegisterInstruction -import org.jf.dexlib2.iface.instruction.ReferenceInstruction -import org.jf.dexlib2.iface.instruction.formats.Instruction31i -import org.jf.dexlib2.iface.reference.FieldReference -import org.jf.dexlib2.iface.reference.MethodReference +import org.jf.dexlib2.iface.instruction.formats.* -@DependsOn([ResourceMappingPatch::class]) @Name("hide-general-ads-bytecode-patch") +@DependsOn([ResourceMappingPatch::class]) @YouTubeCompatibility @Version("0.0.1") -class GeneralAdsBytecodePatch : BytecodePatch( - listOf(ComponentContextParserFingerprint) -) { +class GeneralAdsBytecodePatch : BytecodePatch() { + private val resourceIds = arrayOf( + "id" to "ad_attribution", + "layout" to "horizontal_card_list", + "layout" to "album_card", + "id" to "reel_player_badge", + "id" to "reel_player_badge2", + "id" to "reel_player_info_panel" + ).map { (type, name) -> + ResourceMappingPatch + .resourceMappings + .single { it.type == type && it.name == name }.id + } + private var patchSuccessArray = Array(resourceIds.size) {false} + override fun execute(context: BytecodeContext): PatchResult { - ComponentContextParserFingerprint.result?.let { result -> - val builderMethodIndex = EmptyComponentBuilderFingerprint - .also { it.resolve(context, result.mutableMethod, result.mutableClass) } - .let { it.result?.scanResult?.patternScanResult?.startIndex?: return EmptyComponentBuilderFingerprint.toErrorResult() } + context.classes.forEach { classDef -> + classDef.methods.forEach { method -> + with(method.implementation) { + this?.instructions?.forEachIndexed { index, instruction -> + when (instruction.opcode) { + Opcode.CONST -> { + when ((instruction as Instruction31i).wideLiteral) { + resourceIds[0] -> { // general ads + val insertIndex = index + 1 + val invokeInstruction = instructions.elementAt(insertIndex) + if (invokeInstruction.opcode != Opcode.INVOKE_VIRTUAL) return@forEachIndexed - val emptyComponentFieldIndex = builderMethodIndex + 2 + val mutableMethod = context.proxy(classDef).mutableClass.findMutableMethodOf(method) - with(result.mutableMethod) { - val insertHookIndex = implementation!!.instructions.indexOfFirst { - it.opcode == Opcode.CONST_16 && - (it as BuilderInstruction21s).narrowLiteral == 124 - } + 3 + val viewRegister = (invokeInstruction as Instruction35c).registerC + mutableMethod.implementation!!.injectHideCall(insertIndex, viewRegister, "ads/GeneralAdsPatch", "hideAdAttributionView") + patchSuccessArray[0] = true; + } - val stringBuilderRegister = (instruction(insertHookIndex) as OneRegisterInstruction).registerA - val clobberedRegister = (instruction(insertHookIndex - 3) as OneRegisterInstruction).registerA + resourceIds[1] -> { // breaking news + val insertIndex = index + 4 + val invokeInstruction = instructions.elementAt(insertIndex) + if (invokeInstruction.opcode != Opcode.CHECK_CAST) return@forEachIndexed - val bufferIndex = implementation!!.instructions.indexOfFirst { - it.opcode == Opcode.CONST && - (it as Instruction31i).narrowLiteral == 183314536 - } - 1 + val mutableMethod = context.proxy(classDef).mutableClass.findMutableMethodOf(method) - val bufferRegister = (instruction(bufferIndex) as OneRegisterInstruction).registerA + val viewRegister = (invokeInstruction as Instruction21c).registerA + mutableMethod.implementation!!.injectHideCall(insertIndex, viewRegister, "ads/GeneralAdsPatch", "hideBreakingNewsShelf") + patchSuccessArray[1] = true; + } - val builderMethodDescriptor = instruction(builderMethodIndex).toDescriptor() - val emptyComponentFieldDescriptor = instruction(emptyComponentFieldIndex).toDescriptor() + resourceIds[2] -> { // album cards + val insertIndex = index + 4 + val invokeInstruction = instructions.elementAt(insertIndex) + if (invokeInstruction.opcode != Opcode.CHECK_CAST) return@forEachIndexed - addInstructions( - insertHookIndex, // right after setting the component.pathBuilder field, - """ - invoke-static {v$stringBuilderRegister, v$bufferRegister}, $ADS_PATH/LithoFilterPatch;->filter(Ljava/lang/StringBuilder;Ljava/lang/String;)Z - move-result v$clobberedRegister - if-eqz v$clobberedRegister, :not_an_ad - move-object/from16 v$bufferRegister, p1 - invoke-static {v$bufferRegister}, $builderMethodDescriptor - move-result-object v0 - iget-object v0, v0, $emptyComponentFieldDescriptor - return-object v0 - """, - listOf(ExternalLabel("not_an_ad", instruction(insertHookIndex))) - ) + val mutableMethod = context.proxy(classDef).mutableClass.findMutableMethodOf(method) + + val viewRegister = (invokeInstruction as Instruction21c).registerA + mutableMethod.implementation!!.injectHideCall(insertIndex, viewRegister, "ads/GeneralAdsPatch", "hideAlbumCards") + patchSuccessArray[2] = true; + } + + resourceIds[3], resourceIds[4] -> { // paid content banner + val insertIndex = index + 3 + val invokeInstruction = instructions.elementAt(insertIndex) + if (invokeInstruction.opcode != Opcode.CHECK_CAST) return@forEachIndexed + + val mutableMethod = context.proxy(classDef).mutableClass.findMutableMethodOf(method) + val dummyRegister = (instructions.elementAt(index) as Instruction31i).registerA + val viewRegister = (invokeInstruction as Instruction21c).registerA + + mutableMethod.addInjectCall(insertIndex, dummyRegister, viewRegister, "hidePaidContentBanner") + + patchSuccessArray[3] = true; + patchSuccessArray[4] = true; + } + + resourceIds[5] -> { // info panel + val insertIndex = index + 3 + val invokeInstruction = instructions.elementAt(insertIndex) + if (invokeInstruction.opcode != Opcode.CHECK_CAST) return@forEachIndexed + + val mutableMethod = context.proxy(classDef).mutableClass.findMutableMethodOf(method) + val dummyRegister = (instructions.elementAt(index) as Instruction31i).registerA + val viewRegister = (invokeInstruction as Instruction21c).registerA + + mutableMethod.addInjectCall(insertIndex + 7, dummyRegister, viewRegister, "hideInfoPanel") + + patchSuccessArray[5] = true; + } + } + } + else -> return@forEachIndexed + } + } + } } - } ?: return ComponentContextParserFingerprint.toErrorResult() - + } context.updatePatchStatus("GeneralAds") - return PatchResultSuccess() + return toResult(patchSuccessArray.indexOf(false)) } - private companion object { - fun Instruction.toDescriptor() = when (val reference = (this as? ReferenceInstruction)?.reference) { - is MethodReference -> "${reference.definingClass}->${reference.name}(${ - reference.parameterTypes.joinToString( - "" - ) { it } - })${reference.returnType}" - is FieldReference -> "${reference.definingClass}->${reference.name}:${reference.type}" - else -> throw PatchResultError("Unsupported reference type") - } + private fun MutableMethod.addInjectCall( + index: Int, + dummyRegister: Int, + viewRegister: Int, + method: String + ) { + addInstructions( + index + 1, """ + invoke-static {}, $ADS_PATH/GeneralAdsPatch;->$method()Z + move-result v$dummyRegister + if-eqz v$dummyRegister, :shown + const v$viewRegister, 0x0 + """, listOf(ExternalLabel("shown", this.instruction(index + 1))) + ) } } diff --git a/src/main/kotlin/app/revanced/patches/youtube/ads/general/bytecode/patch/GeneralAdsSecondaryBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/ads/general/bytecode/patch/GeneralAdsSecondaryBytecodePatch.kt deleted file mode 100644 index 790ba9c59..000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/ads/general/bytecode/patch/GeneralAdsSecondaryBytecodePatch.kt +++ /dev/null @@ -1,139 +0,0 @@ -package app.revanced.patches.youtube.ads.general.bytecode.patch - -import app.revanced.extensions.findMutableMethodOf -import app.revanced.extensions.injectHideCall -import app.revanced.extensions.toResult -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.extensions.instruction -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod -import app.revanced.patcher.util.smali.ExternalLabel -import app.revanced.patches.shared.annotation.YouTubeCompatibility -import app.revanced.patches.shared.patch.mapping.ResourceMappingPatch -import app.revanced.util.integrations.Constants.ADS_PATH -import org.jf.dexlib2.Opcode -import org.jf.dexlib2.iface.instruction.formats.* - -@Name("hide-general-ads-secondary-bytecode-patch") -@DependsOn([ResourceMappingPatch::class]) -@YouTubeCompatibility -@Version("0.0.1") -class GeneralAdsSecondaryBytecodePatch : BytecodePatch() { - private val resourceIds = arrayOf( - "id" to "ad_attribution", - "layout" to "horizontal_card_list", - "layout" to "album_card", - "id" to "reel_player_badge", - "id" to "reel_player_badge2", - "id" to "reel_player_info_panel" - ).map { (type, name) -> - ResourceMappingPatch - .resourceMappings - .single { it.type == type && it.name == name }.id - } - private var patchSuccessArray = Array(resourceIds.size) {false} - - override fun execute(context: BytecodeContext): PatchResult { - context.classes.forEach { classDef -> - classDef.methods.forEach { method -> - with(method.implementation) { - this?.instructions?.forEachIndexed { index, instruction -> - when (instruction.opcode) { - Opcode.CONST -> { - when ((instruction as Instruction31i).wideLiteral) { - resourceIds[0] -> { // general ads - val insertIndex = index + 1 - val invokeInstruction = instructions.elementAt(insertIndex) - if (invokeInstruction.opcode != Opcode.INVOKE_VIRTUAL) return@forEachIndexed - - val mutableMethod = context.proxy(classDef).mutableClass.findMutableMethodOf(method) - - val viewRegister = (invokeInstruction as Instruction35c).registerC - mutableMethod.implementation!!.injectHideCall(insertIndex, viewRegister, "ads/GeneralAdsPatch", "hideAdAttributionView") - patchSuccessArray[0] = true; - } - - resourceIds[1] -> { // breaking news - val insertIndex = index + 4 - val invokeInstruction = instructions.elementAt(insertIndex) - if (invokeInstruction.opcode != Opcode.CHECK_CAST) return@forEachIndexed - - val mutableMethod = context.proxy(classDef).mutableClass.findMutableMethodOf(method) - - val viewRegister = (invokeInstruction as Instruction21c).registerA - mutableMethod.implementation!!.injectHideCall(insertIndex, viewRegister, "ads/GeneralAdsPatch", "hideBreakingNewsShelf") - patchSuccessArray[1] = true; - } - - resourceIds[2] -> { // album cards - val insertIndex = index + 4 - val invokeInstruction = instructions.elementAt(insertIndex) - if (invokeInstruction.opcode != Opcode.CHECK_CAST) return@forEachIndexed - - val mutableMethod = context.proxy(classDef).mutableClass.findMutableMethodOf(method) - - val viewRegister = (invokeInstruction as Instruction21c).registerA - mutableMethod.implementation!!.injectHideCall(insertIndex, viewRegister, "ads/GeneralAdsPatch", "hideAlbumCards") - patchSuccessArray[2] = true; - } - - resourceIds[3], resourceIds[4] -> { // paid content banner - val insertIndex = index + 3 - val invokeInstruction = instructions.elementAt(insertIndex) - if (invokeInstruction.opcode != Opcode.CHECK_CAST) return@forEachIndexed - - val mutableMethod = context.proxy(classDef).mutableClass.findMutableMethodOf(method) - val dummyRegister = (instructions.elementAt(index) as Instruction31i).registerA - val viewRegister = (invokeInstruction as Instruction21c).registerA - - mutableMethod.addInjectCall(insertIndex, dummyRegister, viewRegister, "hidePaidContentBanner") - - patchSuccessArray[3] = true; - patchSuccessArray[4] = true; - } - - resourceIds[5] -> { // info panel - val insertIndex = index + 3 - val invokeInstruction = instructions.elementAt(insertIndex) - if (invokeInstruction.opcode != Opcode.CHECK_CAST) return@forEachIndexed - - val mutableMethod = context.proxy(classDef).mutableClass.findMutableMethodOf(method) - val dummyRegister = (instructions.elementAt(index) as Instruction31i).registerA - val viewRegister = (invokeInstruction as Instruction21c).registerA - - mutableMethod.addInjectCall(insertIndex + 7, dummyRegister, viewRegister, "hideInfoPanel") - - patchSuccessArray[5] = true; - } - } - } - else -> return@forEachIndexed - } - } - } - } - } - return toResult(patchSuccessArray.indexOf(false)) - } - - private fun MutableMethod.addInjectCall( - index: Int, - dummyRegister: Int, - viewRegister: Int, - method: String - ) { - addInstructions( - index + 1, """ - invoke-static {}, $ADS_PATH/GeneralAdsPatch;->$method()Z - move-result v$dummyRegister - if-eqz v$dummyRegister, :shown - const v$viewRegister, 0x0 - """, listOf(ExternalLabel("shown", this.instruction(index + 1))) - ) - } -} diff --git a/src/main/kotlin/app/revanced/patches/youtube/ads/general/resource/patch/GeneralAdsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/ads/general/resource/patch/GeneralAdsPatch.kt index edbb3626c..124f5c956 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/ads/general/resource/patch/GeneralAdsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/ads/general/resource/patch/GeneralAdsPatch.kt @@ -13,7 +13,6 @@ import app.revanced.patcher.patch.annotations.DependsOn import app.revanced.patcher.patch.annotations.Patch import app.revanced.patches.shared.annotation.YouTubeCompatibility import app.revanced.patches.youtube.ads.general.bytecode.patch.GeneralAdsBytecodePatch -import app.revanced.patches.youtube.ads.general.bytecode.patch.GeneralAdsSecondaryBytecodePatch import app.revanced.patches.youtube.misc.litho.patch.LithoFilterPatch import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsPatch import org.w3c.dom.Element @@ -24,7 +23,6 @@ import org.w3c.dom.Element @DependsOn( [ GeneralAdsBytecodePatch::class, - GeneralAdsSecondaryBytecodePatch::class, LithoFilterPatch::class, SettingsPatch::class ] diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/litho/patch/LithoFilterPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/litho/patch/LithoFilterPatch.kt index 2860e0cca..be2c295ee 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/litho/patch/LithoFilterPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/litho/patch/LithoFilterPatch.kt @@ -1,25 +1,16 @@ package app.revanced.patches.youtube.misc.litho.patch -import app.revanced.extensions.toErrorResult import app.revanced.patcher.annotation.Version import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.extensions.instruction -import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.util.smali.ExternalLabel import app.revanced.patches.shared.annotation.YouTubeCompatibility +import app.revanced.patches.shared.patch.litho.AbstractLithoFilterPatch import app.revanced.patches.youtube.ads.doublebacktoclose.patch.DoubleBackToClosePatch -import app.revanced.patches.youtube.misc.litho.fingerprints.LithoFingerprint import app.revanced.patches.youtube.ads.swiperefresh.patch.SwipeRefreshPatch +import app.revanced.util.bytecode.BytecodeHelper.updatePatchStatus import app.revanced.util.integrations.Constants.ADS_PATH -import org.jf.dexlib2.Opcode -import org.jf.dexlib2.builder.instruction.BuilderInstruction21c -import org.jf.dexlib2.iface.instruction.ReferenceInstruction -import org.jf.dexlib2.iface.reference.FieldReference -import org.jf.dexlib2.iface.reference.MethodReference @DependsOn( [ @@ -29,47 +20,13 @@ import org.jf.dexlib2.iface.reference.MethodReference ) @YouTubeCompatibility @Version("0.0.1") -class LithoFilterPatch : BytecodePatch( - listOf( - LithoFingerprint - ) -) -{ +class LithoFilterPatch : AbstractLithoFilterPatch( + "$ADS_PATH/LithoFilterPatch;" +) { override fun execute(context: BytecodeContext): PatchResult { + super.execute(context) - LithoFingerprint.result?.mutableMethod?.let { - val implementations = it.implementation!! - val instructions = implementations.instructions - val parameter = it.parameters[2] - val stringRegister = implementations.registerCount - it.parameters.size + 1 - val dummyRegister = stringRegister + 1 - - val lithoIndex = instructions.indexOfFirst { instruction-> - instruction.opcode == Opcode.CONST_STRING && - (instruction as BuilderInstruction21c).reference.toString() == "Element missing type extension" - } + 2 - - val firstReference = (instructions.elementAt(lithoIndex) as ReferenceInstruction).reference as MethodReference - val secondReference = (instructions.elementAt(lithoIndex + 2) as ReferenceInstruction).reference as FieldReference - - it.addInstructions( - 0, """ - move-object/from16 v1, v$stringRegister - invoke-virtual {v1}, Ljava/lang/Object;->toString()Ljava/lang/String; - move-result-object v1 - move-object/from16 v2, v$dummyRegister - iget-object v2, v2, $parameter->b:Ljava/nio/ByteBuffer; - invoke-static {v1, v2}, $ADS_PATH/ExtendedLithoFilterPatch;->InflatedLithoView(Ljava/lang/String;Ljava/nio/ByteBuffer;)Z - move-result v3 - if-eqz v3, :do_not_block - move-object/from16 v0, p1 - invoke-static {v0}, $firstReference - move-result-object v0 - iget-object v0, v0, ${secondReference.definingClass}->${secondReference.name}:${secondReference.type} - return-object v0 - """, listOf(ExternalLabel("do_not_block", it.instruction(0))) - ) - } ?: return LithoFingerprint.toErrorResult() + context.updatePatchStatus("ByteBuffer") return PatchResultSuccess() }