From fff85d46868437afc637aa81d595d8b08843e044 Mon Sep 17 00:00:00 2001 From: PantlessCoding Date: Sat, 7 Sep 2024 11:51:05 -0400 Subject: [PATCH 01/11] WIP --- api/revanced-patches.api | 6 +++ .../ads/mainfeed/HideSponsoredStoriesPatch.kt | 44 +++++++++++++++++++ .../GetStoryVisibilityFingerprint.kt | 26 +++++++++++ 3 files changed, 76 insertions(+) create mode 100644 src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/HideSponsoredStoriesPatch.kt create mode 100644 src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/fingerprints/GetStoryVisibilityFingerprint.kt diff --git a/api/revanced-patches.api b/api/revanced-patches.api index 769746f26e..edbabda53f 100644 --- a/api/revanced-patches.api +++ b/api/revanced-patches.api @@ -263,6 +263,12 @@ public final class app/revanced/patches/duolingo/debug/EnableDebugMenuPatch : ap public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V } +public final class app/revanced/patches/facebook/ads/mainfeed/HideSponsoredStoriesPatch : app/revanced/patcher/patch/BytecodePatch { + public static final field INSTANCE Lapp/revanced/patches/facebook/ads/mainfeed/HideSponsoredStoriesPatch; + public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V + public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V +} + public final class app/revanced/patches/facebook/ads/story/HideStoryAdsPatch : app/revanced/patcher/patch/BytecodePatch { public static final field INSTANCE Lapp/revanced/patches/facebook/ads/story/HideStoryAdsPatch; public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V diff --git a/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/HideSponsoredStoriesPatch.kt b/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/HideSponsoredStoriesPatch.kt new file mode 100644 index 0000000000..c700445a68 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/HideSponsoredStoriesPatch.kt @@ -0,0 +1,44 @@ +package app.revanced.patches.facebook.ads.mainfeed + +import app.revanced.util.exception +import app.revanced.patcher.data.BytecodeContext +import app.revanced.patcher.extensions.InstructionExtensions.addInstruction +import app.revanced.patcher.patch.BytecodePatch +import app.revanced.patcher.patch.annotation.CompatiblePackage +import app.revanced.patcher.patch.annotation.Patch +import app.revanced.patches.facebook.ads.mainfeed.fingerprints.GetStoryVisibilityFingerprint +import app.revanced.patches.spotify.lite.ondemand.fingerprints.OnDemandFingerprint + +@Patch( + name = "Hide Sponsored stories", + description = "Hide Sponsored stories in main feed.", + compatiblePackages = [CompatiblePackage("com.facebook.katana")] +) +@Suppress("unused") +object HideSponsoredStoriesPatch : BytecodePatch(setOf(GetStoryVisibilityFingerprint)) { + override fun execute(context: BytecodeContext) { + OnDemandFingerprint.result?.apply { + val insertIndex = scanResult.patternScanResult!!.startIndex + mutableMethod?.addInstruction(insertIndex,"") + + + // Hide stories with sponsored data defined + mutableMethod.addInstruction(insertIndex, """ + # Test cast p0 into Lcom/facebook/graphql/model/GraphQLStory + instance-of v0, p0, Lcom/facebook/graphql/model/GraphQLStory; + # if 0 return to normal logic + if-eqz v0, :resume_normal + # We have a graphQLStory, check if a call on A1G() returns null (return type : LX/3ba) + invoke-virtual {p0}, Lcom/facebook/graphql/model/GraphQLStory;->A1G()LX/3ba; + move-result-object v0 + # if non-null, hide ad + if-eqz v0, :resume_normal + # Return Ljava/lang/Integer; 3 (StoryVisibility.GONE) + const/4 v0, 0x3 + invoke-static {v0}, Ljava/lang/Integer;->valueOf(I)Ljava/lang/Integer; + move-result-object p0 + return-object p0 + """.trimIndent()) + } ?: throw GetStoryVisibilityFingerprint.exception + } +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/fingerprints/GetStoryVisibilityFingerprint.kt b/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/fingerprints/GetStoryVisibilityFingerprint.kt new file mode 100644 index 0000000000..d9266210c7 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/fingerprints/GetStoryVisibilityFingerprint.kt @@ -0,0 +1,26 @@ +package app.revanced.patches.facebook.ads.mainfeed.fingerprints + +import app.revanced.patcher.extensions.or +import app.revanced.patcher.fingerprint.MethodFingerprint +import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.Annotation +import com.android.tools.smali.dexlib2.iface.value.StringEncodedValue + +internal object GetStoryVisibilityFingerprint : MethodFingerprint( + returnType = "Ljava/lang/Integer;", + accessFlags = (AccessFlags.PUBLIC or AccessFlags.STATIC), + parameters = listOf(), // Means at least one ? + opcodes = listOf( + Opcode.INVOKE_STATIC, + Opcode.MOVE_RESULT_OBJECT, + Opcode.IF_NEZ, + Opcode.SGET_OBJECT, + ), + customFingerprint = { methodDef, classDef -> + // Method has a deprecated annotation + methodDef.annotations.any any@{annotation -> + return@any annotation.type == "Ljava/lang/Deprecated;" + } + }, +) \ No newline at end of file From 2b6a2d28578102e4f2738bc41ea6d4843366067e Mon Sep 17 00:00:00 2001 From: PantlessCoding Date: Thu, 5 Sep 2024 19:26:58 -0400 Subject: [PATCH 02/11] First working patch (apk to be tested) --- .../ads/mainfeed/HideSponsoredStoriesPatch.kt | 25 ++++++++++--------- .../GetStoryVisibilityFingerprint.kt | 3 ++- ...phQLStorySponsoredDataGetterFingerprint.kt | 18 +++++++++++++ 3 files changed, 33 insertions(+), 13 deletions(-) create mode 100644 src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/fingerprints/GraphQLStorySponsoredDataGetterFingerprint.kt diff --git a/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/HideSponsoredStoriesPatch.kt b/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/HideSponsoredStoriesPatch.kt index c700445a68..0bc66a932d 100644 --- a/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/HideSponsoredStoriesPatch.kt +++ b/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/HideSponsoredStoriesPatch.kt @@ -7,6 +7,7 @@ import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.annotation.CompatiblePackage import app.revanced.patcher.patch.annotation.Patch import app.revanced.patches.facebook.ads.mainfeed.fingerprints.GetStoryVisibilityFingerprint +import app.revanced.patches.facebook.ads.mainfeed.fingerprints.GraphQLStorySponsoredDataGetterFingerprint import app.revanced.patches.spotify.lite.ondemand.fingerprints.OnDemandFingerprint @Patch( @@ -15,30 +16,30 @@ import app.revanced.patches.spotify.lite.ondemand.fingerprints.OnDemandFingerpri compatiblePackages = [CompatiblePackage("com.facebook.katana")] ) @Suppress("unused") -object HideSponsoredStoriesPatch : BytecodePatch(setOf(GetStoryVisibilityFingerprint)) { +object HideSponsoredStoriesPatch : BytecodePatch(setOf(GetStoryVisibilityFingerprint, GraphQLStorySponsoredDataGetterFingerprint)) { override fun execute(context: BytecodeContext) { - OnDemandFingerprint.result?.apply { - val insertIndex = scanResult.patternScanResult!!.startIndex - mutableMethod?.addInstruction(insertIndex,"") + GetStoryVisibilityFingerprint.result?.apply { + // TODO: Resolve class and method by fingerprint + // Get the class name + val sponsoredDataModelGetter = GraphQLStorySponsoredDataGetterFingerprint.result ?: throw GraphQLStorySponsoredDataGetterFingerprint.exception; // Hide stories with sponsored data defined - mutableMethod.addInstruction(insertIndex, """ - # Test cast p0 into Lcom/facebook/graphql/model/GraphQLStory + // Check if param type is GraphQLStory + // If so calling the sponsoredDataModelGetter, only sponsored content has non null data + // Sponsored Stories gets their visibility forced to StoryVisibility.GONE (== 3) + mutableMethod.addInstruction(0, """ instance-of v0, p0, Lcom/facebook/graphql/model/GraphQLStory; - # if 0 return to normal logic if-eqz v0, :resume_normal - # We have a graphQLStory, check if a call on A1G() returns null (return type : LX/3ba) - invoke-virtual {p0}, Lcom/facebook/graphql/model/GraphQLStory;->A1G()LX/3ba; - move-result-object v0 - # if non-null, hide ad + invoke-virtual {p0}, Lcom/facebook/graphql/model/GraphQLStory;->${sponsoredDataModelGetter.method.name}()${sponsoredDataModelGetter.method.returnType} + move-result-object v0 if-eqz v0, :resume_normal - # Return Ljava/lang/Integer; 3 (StoryVisibility.GONE) const/4 v0, 0x3 invoke-static {v0}, Ljava/lang/Integer;->valueOf(I)Ljava/lang/Integer; move-result-object p0 return-object p0 """.trimIndent()) + } ?: throw GetStoryVisibilityFingerprint.exception } } \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/fingerprints/GetStoryVisibilityFingerprint.kt b/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/fingerprints/GetStoryVisibilityFingerprint.kt index d9266210c7..e590e22e9b 100644 --- a/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/fingerprints/GetStoryVisibilityFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/fingerprints/GetStoryVisibilityFingerprint.kt @@ -10,12 +10,13 @@ import com.android.tools.smali.dexlib2.iface.value.StringEncodedValue internal object GetStoryVisibilityFingerprint : MethodFingerprint( returnType = "Ljava/lang/Integer;", accessFlags = (AccessFlags.PUBLIC or AccessFlags.STATIC), - parameters = listOf(), // Means at least one ? opcodes = listOf( Opcode.INVOKE_STATIC, Opcode.MOVE_RESULT_OBJECT, Opcode.IF_NEZ, Opcode.SGET_OBJECT, + Opcode.RETURN_OBJECT, + Opcode.INVOKE_STATIC, ), customFingerprint = { methodDef, classDef -> // Method has a deprecated annotation diff --git a/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/fingerprints/GraphQLStorySponsoredDataGetterFingerprint.kt b/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/fingerprints/GraphQLStorySponsoredDataGetterFingerprint.kt new file mode 100644 index 0000000000..48bff925c9 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/fingerprints/GraphQLStorySponsoredDataGetterFingerprint.kt @@ -0,0 +1,18 @@ +package app.revanced.patches.facebook.ads.mainfeed.fingerprints + +import app.revanced.patcher.extensions.or +import app.revanced.patcher.fingerprint.MethodFingerprint +import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.Annotation +import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction31i +import com.android.tools.smali.dexlib2.iface.value.StringEncodedValue + +internal object GraphQLStorySponsoredDataGetterFingerprint : MethodFingerprint( + customFingerprint = { methodDef, classDef -> + // Method has a deprecated annotation + classDef.type == "Lcom/facebook/graphql/model/GraphQLStory;" && + (methodDef.implementation?.instructions?.elementAt(1) as? Instruction31i)?.narrowLiteral == 343709267 && + (methodDef.implementation?.instructions?.elementAt(2) as? Instruction31i)?.narrowLiteral == -671355649 + }, +) \ No newline at end of file From 90b004483971af8b671431e2ed84c0896def1857 Mon Sep 17 00:00:00 2001 From: PantlessCoding Date: Fri, 6 Sep 2024 14:35:33 -0400 Subject: [PATCH 03/11] Better implementation --- .../ads/mainfeed/HideSponsoredStoriesPatch.kt | 21 +++++++++---------- .../GetStoryVisibilityFingerprint.kt | 20 +++++++----------- ...phQLStorySponsoredDataGetterFingerprint.kt | 6 +++--- 3 files changed, 21 insertions(+), 26 deletions(-) diff --git a/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/HideSponsoredStoriesPatch.kt b/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/HideSponsoredStoriesPatch.kt index 0bc66a932d..900d5697c2 100644 --- a/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/HideSponsoredStoriesPatch.kt +++ b/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/HideSponsoredStoriesPatch.kt @@ -3,6 +3,7 @@ package app.revanced.patches.facebook.ads.mainfeed import app.revanced.util.exception import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.extensions.InstructionExtensions.addInstruction +import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.annotation.CompatiblePackage import app.revanced.patcher.patch.annotation.Patch @@ -20,26 +21,24 @@ object HideSponsoredStoriesPatch : BytecodePatch(setOf(GetStoryVisibilityFingerp override fun execute(context: BytecodeContext) { GetStoryVisibilityFingerprint.result?.apply { - // TODO: Resolve class and method by fingerprint - // Get the class name + // Get the sponsored data model getter val sponsoredDataModelGetter = GraphQLStorySponsoredDataGetterFingerprint.result ?: throw GraphQLStorySponsoredDataGetterFingerprint.exception; // Hide stories with sponsored data defined // Check if param type is GraphQLStory - // If so calling the sponsoredDataModelGetter, only sponsored content has non null data - // Sponsored Stories gets their visibility forced to StoryVisibility.GONE (== 3) - mutableMethod.addInstruction(0, """ + // If so calling the sponsoredDataModelGetter, only sponsored content has non-null data + // Sponsored Stories gets their visibility forced to StoryVisibility.GONE + mutableMethod.addInstructionsWithLabels(scanResult.patternScanResult!!.startIndex, """ instance-of v0, p0, Lcom/facebook/graphql/model/GraphQLStory; if-eqz v0, :resume_normal invoke-virtual {p0}, Lcom/facebook/graphql/model/GraphQLStory;->${sponsoredDataModelGetter.method.name}()${sponsoredDataModelGetter.method.returnType} move-result-object v0 if-eqz v0, :resume_normal - const/4 v0, 0x3 - invoke-static {v0}, Ljava/lang/Integer;->valueOf(I)Ljava/lang/Integer; - move-result-object p0 - return-object p0 - """.trimIndent()) - + const-string v0, "GONE" + return-object v0 + :resume_normal + nop + """) } ?: throw GetStoryVisibilityFingerprint.exception } } \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/fingerprints/GetStoryVisibilityFingerprint.kt b/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/fingerprints/GetStoryVisibilityFingerprint.kt index e590e22e9b..cf296c92e7 100644 --- a/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/fingerprints/GetStoryVisibilityFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/fingerprints/GetStoryVisibilityFingerprint.kt @@ -8,20 +8,16 @@ import com.android.tools.smali.dexlib2.iface.Annotation import com.android.tools.smali.dexlib2.iface.value.StringEncodedValue internal object GetStoryVisibilityFingerprint : MethodFingerprint( - returnType = "Ljava/lang/Integer;", + returnType = "Ljava/lang/String;", accessFlags = (AccessFlags.PUBLIC or AccessFlags.STATIC), opcodes = listOf( - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, + Opcode.INSTANCE_OF, Opcode.IF_NEZ, - Opcode.SGET_OBJECT, - Opcode.RETURN_OBJECT, - Opcode.INVOKE_STATIC, + Opcode.INSTANCE_OF, + Opcode.IF_NEZ, + Opcode.INSTANCE_OF, + Opcode.IF_NEZ, + Opcode.CONST ), - customFingerprint = { methodDef, classDef -> - // Method has a deprecated annotation - methodDef.annotations.any any@{annotation -> - return@any annotation.type == "Ljava/lang/Deprecated;" - } - }, + strings = listOf("This should not be called for base class object"), ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/fingerprints/GraphQLStorySponsoredDataGetterFingerprint.kt b/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/fingerprints/GraphQLStorySponsoredDataGetterFingerprint.kt index 48bff925c9..4b4cfd231c 100644 --- a/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/fingerprints/GraphQLStorySponsoredDataGetterFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/fingerprints/GraphQLStorySponsoredDataGetterFingerprint.kt @@ -10,9 +10,9 @@ import com.android.tools.smali.dexlib2.iface.value.StringEncodedValue internal object GraphQLStorySponsoredDataGetterFingerprint : MethodFingerprint( customFingerprint = { methodDef, classDef -> - // Method has a deprecated annotation + // All methods within initialise a generic model with the same instructions apart from the value of those two constants classDef.type == "Lcom/facebook/graphql/model/GraphQLStory;" && - (methodDef.implementation?.instructions?.elementAt(1) as? Instruction31i)?.narrowLiteral == 343709267 && - (methodDef.implementation?.instructions?.elementAt(2) as? Instruction31i)?.narrowLiteral == -671355649 + (methodDef.implementation?.instructions?.elementAt(1) as? Instruction31i)?.narrowLiteral == -132939024 && + (methodDef.implementation?.instructions?.elementAt(2) as? Instruction31i)?.narrowLiteral == 341202575 }, ) \ No newline at end of file From 8b4f5a233220ed8d6537d79e651a1fa4d977d7c7 Mon Sep 17 00:00:00 2001 From: PantlessCoding Date: Sat, 7 Sep 2024 11:52:50 -0400 Subject: [PATCH 04/11] Cleanup --- .../facebook/ads/mainfeed/HideSponsoredStoriesPatch.kt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/HideSponsoredStoriesPatch.kt b/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/HideSponsoredStoriesPatch.kt index 900d5697c2..ade2b66680 100644 --- a/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/HideSponsoredStoriesPatch.kt +++ b/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/HideSponsoredStoriesPatch.kt @@ -2,14 +2,12 @@ package app.revanced.patches.facebook.ads.mainfeed import app.revanced.util.exception import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.InstructionExtensions.addInstruction import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.annotation.CompatiblePackage import app.revanced.patcher.patch.annotation.Patch import app.revanced.patches.facebook.ads.mainfeed.fingerprints.GetStoryVisibilityFingerprint import app.revanced.patches.facebook.ads.mainfeed.fingerprints.GraphQLStorySponsoredDataGetterFingerprint -import app.revanced.patches.spotify.lite.ondemand.fingerprints.OnDemandFingerprint @Patch( name = "Hide Sponsored stories", @@ -26,7 +24,7 @@ object HideSponsoredStoriesPatch : BytecodePatch(setOf(GetStoryVisibilityFingerp // Hide stories with sponsored data defined // Check if param type is GraphQLStory - // If so calling the sponsoredDataModelGetter, only sponsored content has non-null data + // If so, calling the sponsoredDataModelGetter, only sponsored content has non-null data // Sponsored Stories gets their visibility forced to StoryVisibility.GONE mutableMethod.addInstructionsWithLabels(scanResult.patternScanResult!!.startIndex, """ instance-of v0, p0, Lcom/facebook/graphql/model/GraphQLStory; From 934ba42579491155fadc0bd958dfcc5c7ad4dc80 Mon Sep 17 00:00:00 2001 From: PantlessCoding Date: Fri, 4 Oct 2024 15:07:44 -0400 Subject: [PATCH 05/11] PR adjustments --- .../ads/mainfeed/HideSponsoredStoriesPatch.kt | 37 ++++++++++--------- ...phQLStorySponsoredDataGetterFingerprint.kt | 26 ++++++++----- 2 files changed, 36 insertions(+), 27 deletions(-) diff --git a/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/HideSponsoredStoriesPatch.kt b/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/HideSponsoredStoriesPatch.kt index ade2b66680..1950bc3e39 100644 --- a/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/HideSponsoredStoriesPatch.kt +++ b/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/HideSponsoredStoriesPatch.kt @@ -8,10 +8,10 @@ import app.revanced.patcher.patch.annotation.CompatiblePackage import app.revanced.patcher.patch.annotation.Patch import app.revanced.patches.facebook.ads.mainfeed.fingerprints.GetStoryVisibilityFingerprint import app.revanced.patches.facebook.ads.mainfeed.fingerprints.GraphQLStorySponsoredDataGetterFingerprint +import app.revanced.util.resultOrThrow @Patch( name = "Hide Sponsored stories", - description = "Hide Sponsored stories in main feed.", compatiblePackages = [CompatiblePackage("com.facebook.katana")] ) @Suppress("unused") @@ -19,24 +19,25 @@ object HideSponsoredStoriesPatch : BytecodePatch(setOf(GetStoryVisibilityFingerp override fun execute(context: BytecodeContext) { GetStoryVisibilityFingerprint.result?.apply { - // Get the sponsored data model getter - val sponsoredDataModelGetter = GraphQLStorySponsoredDataGetterFingerprint.result ?: throw GraphQLStorySponsoredDataGetterFingerprint.exception; + // Get the sponsored data model getter. + val sponsoredDataModelGetter = GraphQLStorySponsoredDataGetterFingerprint.resultOrThrow() - // Hide stories with sponsored data defined - // Check if param type is GraphQLStory - // If so, calling the sponsoredDataModelGetter, only sponsored content has non-null data - // Sponsored Stories gets their visibility forced to StoryVisibility.GONE - mutableMethod.addInstructionsWithLabels(scanResult.patternScanResult!!.startIndex, """ - instance-of v0, p0, Lcom/facebook/graphql/model/GraphQLStory; - if-eqz v0, :resume_normal - invoke-virtual {p0}, Lcom/facebook/graphql/model/GraphQLStory;->${sponsoredDataModelGetter.method.name}()${sponsoredDataModelGetter.method.returnType} - move-result-object v0 - if-eqz v0, :resume_normal - const-string v0, "GONE" - return-object v0 - :resume_normal - nop - """) + // Check if the parameter type is GraphQLStory and if sponsoredDataModelGetter returns a non-null value. + // If so, hide the story by setting the visibility to StoryVisibility.GONE. + mutableMethod.addInstructionsWithLabels( + scanResult.patternScanResult!!.startIndex, + """ + instance-of v0, p0, Lcom/facebook/graphql/model/GraphQLStory; + if-eqz v0, :resume_normal + invoke-virtual {p0}, Lcom/facebook/graphql/model/GraphQLStory;->${sponsoredDataModelGetter.method.name}()${sponsoredDataModelGetter.method.returnType} + move-result-object v0 + if-eqz v0, :resume_normal + const-string v0, "GONE" + return-object v0 + :resume_normal + nop + """ + ) } ?: throw GetStoryVisibilityFingerprint.exception } } \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/fingerprints/GraphQLStorySponsoredDataGetterFingerprint.kt b/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/fingerprints/GraphQLStorySponsoredDataGetterFingerprint.kt index 4b4cfd231c..d15ac14dd2 100644 --- a/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/fingerprints/GraphQLStorySponsoredDataGetterFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/fingerprints/GraphQLStorySponsoredDataGetterFingerprint.kt @@ -1,18 +1,26 @@ package app.revanced.patches.facebook.ads.mainfeed.fingerprints -import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint -import com.android.tools.smali.dexlib2.AccessFlags -import com.android.tools.smali.dexlib2.Opcode -import com.android.tools.smali.dexlib2.iface.Annotation +import com.android.tools.smali.dexlib2.iface.MethodImplementation import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction31i -import com.android.tools.smali.dexlib2.iface.value.StringEncodedValue + +// These constants trace back to some GraphQL node type descriptor. +private const val STORY_TYPE_ID = -132939024 +private const val SPONSORED_DATA_TYPE_ID = 341202575 internal object GraphQLStorySponsoredDataGetterFingerprint : MethodFingerprint( + customFingerprint = { methodDef, classDef -> - // All methods within initialise a generic model with the same instructions apart from the value of those two constants + + fun isMatchingLiteralValue(implementation: MethodImplementation?, index: Int, literal: Int): Boolean { + return (implementation?.instructions?.elementAtOrNull(index) as? Instruction31i)?.narrowLiteral == literal + } + + // All methods within the target class are virtually identical apart from two magic constants on each of them. + // They all return an instance of the same model but filled with different GraphQL child node data. + // Likely, the constants are the parent and child node ids. classDef.type == "Lcom/facebook/graphql/model/GraphQLStory;" && - (methodDef.implementation?.instructions?.elementAt(1) as? Instruction31i)?.narrowLiteral == -132939024 && - (methodDef.implementation?.instructions?.elementAt(2) as? Instruction31i)?.narrowLiteral == 341202575 - }, + isMatchingLiteralValue(methodDef.implementation, 1, STORY_TYPE_ID) && + isMatchingLiteralValue(methodDef.implementation, 2, SPONSORED_DATA_TYPE_ID) + } ) \ No newline at end of file From b3ea7225b9872a31cb494b5cecc0566d94d410ef Mon Sep 17 00:00:00 2001 From: PantlessCoding Date: Sat, 5 Oct 2024 20:29:58 -0400 Subject: [PATCH 06/11] Syntax + spacing uniformity --- .../ads/mainfeed/HideSponsoredStoriesPatch.kt | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/HideSponsoredStoriesPatch.kt b/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/HideSponsoredStoriesPatch.kt index 1950bc3e39..463bc57faf 100644 --- a/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/HideSponsoredStoriesPatch.kt +++ b/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/HideSponsoredStoriesPatch.kt @@ -11,7 +11,7 @@ import app.revanced.patches.facebook.ads.mainfeed.fingerprints.GraphQLStorySpons import app.revanced.util.resultOrThrow @Patch( - name = "Hide Sponsored stories", + name = "Hide Sponsored Stories", compatiblePackages = [CompatiblePackage("com.facebook.katana")] ) @Suppress("unused") @@ -25,19 +25,19 @@ object HideSponsoredStoriesPatch : BytecodePatch(setOf(GetStoryVisibilityFingerp // Check if the parameter type is GraphQLStory and if sponsoredDataModelGetter returns a non-null value. // If so, hide the story by setting the visibility to StoryVisibility.GONE. mutableMethod.addInstructionsWithLabels( - scanResult.patternScanResult!!.startIndex, - """ - instance-of v0, p0, Lcom/facebook/graphql/model/GraphQLStory; - if-eqz v0, :resume_normal - invoke-virtual {p0}, Lcom/facebook/graphql/model/GraphQLStory;->${sponsoredDataModelGetter.method.name}()${sponsoredDataModelGetter.method.returnType} - move-result-object v0 - if-eqz v0, :resume_normal - const-string v0, "GONE" - return-object v0 - :resume_normal - nop - """ - ) + scanResult.patternScanResult!!.startIndex, + """ + instance-of v0, p0, Lcom/facebook/graphql/model/GraphQLStory; + if-eqz v0, :resume_normal + invoke-virtual {p0}, Lcom/facebook/graphql/model/GraphQLStory;->${sponsoredDataModelGetter.method.name}()${sponsoredDataModelGetter.method.returnType} + move-result-object v0 + if-eqz v0, :resume_normal + const-string v0, "GONE" + return-object v0 + :resume_normal + nop + """ + ) } ?: throw GetStoryVisibilityFingerprint.exception } } \ No newline at end of file From 8ec9547aa90faef73cc03cd36783defb73f68c05 Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Mon, 7 Oct 2024 22:48:51 +0200 Subject: [PATCH 07/11] refactor --- .../ads/mainfeed/HideSponsoredStoriesPatch.kt | 14 ++++++------- ...phQLStorySponsoredDataGetterFingerprint.kt | 21 +++++++++++-------- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/HideSponsoredStoriesPatch.kt b/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/HideSponsoredStoriesPatch.kt index 463bc57faf..7e872f8258 100644 --- a/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/HideSponsoredStoriesPatch.kt +++ b/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/HideSponsoredStoriesPatch.kt @@ -11,16 +11,16 @@ import app.revanced.patches.facebook.ads.mainfeed.fingerprints.GraphQLStorySpons import app.revanced.util.resultOrThrow @Patch( - name = "Hide Sponsored Stories", + name = "Hide 'Sponsored Stories'", compatiblePackages = [CompatiblePackage("com.facebook.katana")] ) @Suppress("unused") -object HideSponsoredStoriesPatch : BytecodePatch(setOf(GetStoryVisibilityFingerprint, GraphQLStorySponsoredDataGetterFingerprint)) { +object HideSponsoredStoriesPatch : BytecodePatch( + setOf(GetStoryVisibilityFingerprint, GraphQLStorySponsoredDataGetterFingerprint) +) { override fun execute(context: BytecodeContext) { GetStoryVisibilityFingerprint.result?.apply { - - // Get the sponsored data model getter. - val sponsoredDataModelGetter = GraphQLStorySponsoredDataGetterFingerprint.resultOrThrow() + val sponsoredDataModelGetterMethod = GraphQLStorySponsoredDataGetterFingerprint.resultOrThrow().method // Check if the parameter type is GraphQLStory and if sponsoredDataModelGetter returns a non-null value. // If so, hide the story by setting the visibility to StoryVisibility.GONE. @@ -29,7 +29,7 @@ object HideSponsoredStoriesPatch : BytecodePatch(setOf(GetStoryVisibilityFingerp """ instance-of v0, p0, Lcom/facebook/graphql/model/GraphQLStory; if-eqz v0, :resume_normal - invoke-virtual {p0}, Lcom/facebook/graphql/model/GraphQLStory;->${sponsoredDataModelGetter.method.name}()${sponsoredDataModelGetter.method.returnType} + invoke-virtual {p0}, $sponsoredDataModelGetterMethod move-result-object v0 if-eqz v0, :resume_normal const-string v0, "GONE" @@ -40,4 +40,4 @@ object HideSponsoredStoriesPatch : BytecodePatch(setOf(GetStoryVisibilityFingerp ) } ?: throw GetStoryVisibilityFingerprint.exception } -} \ No newline at end of file +} diff --git a/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/fingerprints/GraphQLStorySponsoredDataGetterFingerprint.kt b/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/fingerprints/GraphQLStorySponsoredDataGetterFingerprint.kt index d15ac14dd2..1d5eb0cc0f 100644 --- a/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/fingerprints/GraphQLStorySponsoredDataGetterFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/fingerprints/GraphQLStorySponsoredDataGetterFingerprint.kt @@ -1,26 +1,29 @@ package app.revanced.patches.facebook.ads.mainfeed.fingerprints import app.revanced.patcher.fingerprint.MethodFingerprint +import app.revanced.patches.facebook.ads.mainfeed.fingerprints.GraphQLStorySponsoredDataGetterFingerprint.SPONSORED_DATA_TYPE_ID +import app.revanced.patches.facebook.ads.mainfeed.fingerprints.GraphQLStorySponsoredDataGetterFingerprint.STORY_TYPE_ID import com.android.tools.smali.dexlib2.iface.MethodImplementation import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction31i -// These constants trace back to some GraphQL node type descriptor. -private const val STORY_TYPE_ID = -132939024 -private const val SPONSORED_DATA_TYPE_ID = 341202575 internal object GraphQLStorySponsoredDataGetterFingerprint : MethodFingerprint( - customFingerprint = { methodDef, classDef -> + fun isMatchingLiteralValue(index: Int, literal: Int): Boolean { + val instruction = methodDef.implementation?.instructions?.elementAtOrNull(index) as? Instruction31i - fun isMatchingLiteralValue(implementation: MethodImplementation?, index: Int, literal: Int): Boolean { - return (implementation?.instructions?.elementAtOrNull(index) as? Instruction31i)?.narrowLiteral == literal + return instruction?.narrowLiteral == literal } // All methods within the target class are virtually identical apart from two magic constants on each of them. // They all return an instance of the same model but filled with different GraphQL child node data. // Likely, the constants are the parent and child node ids. classDef.type == "Lcom/facebook/graphql/model/GraphQLStory;" && - isMatchingLiteralValue(methodDef.implementation, 1, STORY_TYPE_ID) && - isMatchingLiteralValue(methodDef.implementation, 2, SPONSORED_DATA_TYPE_ID) + isMatchingLiteralValue(1, STORY_TYPE_ID) && + isMatchingLiteralValue(2, SPONSORED_DATA_TYPE_ID) } -) \ No newline at end of file +) { + // These constants trace back to some GraphQL node type descriptor. + private const val STORY_TYPE_ID = -132939024 + private const val SPONSORED_DATA_TYPE_ID = 341202575 +} From 868bab0690c862e0b381c821d9913abeb3ea5974 Mon Sep 17 00:00:00 2001 From: PantlessCoding Date: Thu, 17 Oct 2024 10:04:14 -0400 Subject: [PATCH 08/11] Dynamic resolve of obfuscated ids --- .../ads/mainfeed/HideSponsoredStoriesPatch.kt | 60 +++++++++++++++++-- .../BaseModelMapperFingerprint.kt | 21 +++++++ ...etSponsoredDataModelTemplateFingerprint.kt | 23 +++++++ ...phQLStorySponsoredDataGetterFingerprint.kt | 29 --------- 4 files changed, 99 insertions(+), 34 deletions(-) create mode 100644 src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/fingerprints/BaseModelMapperFingerprint.kt create mode 100644 src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/fingerprints/GetSponsoredDataModelTemplateFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/fingerprints/GraphQLStorySponsoredDataGetterFingerprint.kt diff --git a/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/HideSponsoredStoriesPatch.kt b/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/HideSponsoredStoriesPatch.kt index 7e872f8258..3f79daf8ae 100644 --- a/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/HideSponsoredStoriesPatch.kt +++ b/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/HideSponsoredStoriesPatch.kt @@ -2,13 +2,22 @@ package app.revanced.patches.facebook.ads.mainfeed import app.revanced.util.exception import app.revanced.patcher.data.BytecodeContext +import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.annotation.CompatiblePackage import app.revanced.patcher.patch.annotation.Patch +import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable +import app.revanced.patches.facebook.ads.mainfeed.fingerprints.BaseModelMapperFingerprint +import app.revanced.patches.facebook.ads.mainfeed.fingerprints.GetSponsoredDataModelTemplateFingerprint import app.revanced.patches.facebook.ads.mainfeed.fingerprints.GetStoryVisibilityFingerprint -import app.revanced.patches.facebook.ads.mainfeed.fingerprints.GraphQLStorySponsoredDataGetterFingerprint import app.revanced.util.resultOrThrow +import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation +import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction31i +import com.android.tools.smali.dexlib2.immutable.ImmutableMethod +import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter +import kotlin.math.abs @Patch( name = "Hide 'Sponsored Stories'", @@ -16,20 +25,61 @@ import app.revanced.util.resultOrThrow ) @Suppress("unused") object HideSponsoredStoriesPatch : BytecodePatch( - setOf(GetStoryVisibilityFingerprint, GraphQLStorySponsoredDataGetterFingerprint) + setOf(GetStoryVisibilityFingerprint, GetSponsoredDataModelTemplateFingerprint, BaseModelMapperFingerprint) ) { + private const val GRAPHQL_STORY_TYPE = "Lcom/facebook/graphql/model/GraphQLStory;" + override fun execute(context: BytecodeContext) { GetStoryVisibilityFingerprint.result?.apply { - val sponsoredDataModelGetterMethod = GraphQLStorySponsoredDataGetterFingerprint.resultOrThrow().method + val sponsoredDataModelTemplateMethod = GetSponsoredDataModelTemplateFingerprint.resultOrThrow().method + val baseModelMapperMethod = BaseModelMapperFingerprint.resultOrThrow().method + val baseModelWithTreeType = baseModelMapperMethod.returnType + + // The "SponsoredDataModelTemplate" methods has the ids in its body to extract sponsored data + // from GraphQL models, but targets the wrong derived type of "BaseModelWithTree". Since those ids + // could change in future version, We need to extract them and call the base implementation directly. + val getSponsoredDataHelperMethod = ImmutableMethod( + classDef.type, + "getSponsoredData", + listOf(ImmutableMethodParameter(GRAPHQL_STORY_TYPE, null, null)), + baseModelWithTreeType, + AccessFlags.PRIVATE.value or AccessFlags.STATIC.value, + null, + null, + MutableMethodImplementation(4) + ).toMutable().apply { + // Extract the ids of the original method. These ids seem to correspond to model types for + // GraphQL data structure. They are then fed to a method of BaseModelWithTree that populate + // and cast the requested GraphQL subtype. The Ids are found in the two first "CONST" instructions. + val constInstructions = sponsoredDataModelTemplateMethod.implementation!!.instructions + .filterIsInstance() + .toList() + val storyTypeId = constInstructions.elementAt(0).narrowLiteral + val sponsoredDataTypeId = constInstructions.elementAt(1).narrowLiteral + + addInstructions( + """ + const-class v2, $baseModelWithTreeType + const v1, ${(if (storyTypeId < 0) "-" else "")}0x${abs(storyTypeId).toString(16)} + const v0, ${(if (sponsoredDataTypeId < 0) "-" else "")}0x${(sponsoredDataTypeId).toString(16)} + invoke-virtual {p0, v2, v1, v0}, $baseModelMapperMethod + move-result-object v0 + check-cast v0, $baseModelWithTreeType + return-object v0 + """ + ) + } + + mutableClass.methods.add(getSponsoredDataHelperMethod) // Check if the parameter type is GraphQLStory and if sponsoredDataModelGetter returns a non-null value. // If so, hide the story by setting the visibility to StoryVisibility.GONE. mutableMethod.addInstructionsWithLabels( scanResult.patternScanResult!!.startIndex, """ - instance-of v0, p0, Lcom/facebook/graphql/model/GraphQLStory; + instance-of v0, p0, $GRAPHQL_STORY_TYPE if-eqz v0, :resume_normal - invoke-virtual {p0}, $sponsoredDataModelGetterMethod + invoke-static {p0}, $getSponsoredDataHelperMethod move-result-object v0 if-eqz v0, :resume_normal const-string v0, "GONE" diff --git a/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/fingerprints/BaseModelMapperFingerprint.kt b/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/fingerprints/BaseModelMapperFingerprint.kt new file mode 100644 index 0000000000..2d6d18a9e5 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/fingerprints/BaseModelMapperFingerprint.kt @@ -0,0 +1,21 @@ +package app.revanced.patches.facebook.ads.mainfeed.fingerprints + +import app.revanced.patcher.extensions.or +import app.revanced.patcher.fingerprint.MethodFingerprint +import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.Opcode + +internal object BaseModelMapperFingerprint : MethodFingerprint( + + accessFlags = (AccessFlags.PUBLIC or AccessFlags.FINAL), + parameters = listOf("Ljava/lang/Class","I","I"), + returnType = "Lcom/facebook/graphql/modelutil/BaseModelWithTree;", + opcodes = listOf( + Opcode.SGET_OBJECT, + Opcode.INVOKE_STATIC, + Opcode.MOVE_RESULT_OBJECT, + Opcode.CONST_4, + Opcode.IF_EQ + ) + +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/fingerprints/GetSponsoredDataModelTemplateFingerprint.kt b/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/fingerprints/GetSponsoredDataModelTemplateFingerprint.kt new file mode 100644 index 0000000000..9a7384be20 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/fingerprints/GetSponsoredDataModelTemplateFingerprint.kt @@ -0,0 +1,23 @@ +package app.revanced.patches.facebook.ads.mainfeed.fingerprints + +import app.revanced.patcher.extensions.or +import app.revanced.patcher.fingerprint.MethodFingerprint +import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.Opcode + +internal object GetSponsoredDataModelTemplateFingerprint : MethodFingerprint( + + accessFlags = (AccessFlags.PUBLIC or AccessFlags.FINAL), + parameters = listOf(), + returnType = "L", + opcodes = listOf( + Opcode.CONST, + Opcode.CONST, + Opcode.INVOKE_STATIC, + Opcode.MOVE_RESULT_OBJECT, + Opcode.RETURN_OBJECT + ), + customFingerprint = { methodDef, classDef -> + classDef.type == "Lcom/facebook/graphql/model/GraphQLFBMultiAdsFeedUnit;" + } +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/fingerprints/GraphQLStorySponsoredDataGetterFingerprint.kt b/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/fingerprints/GraphQLStorySponsoredDataGetterFingerprint.kt deleted file mode 100644 index 1d5eb0cc0f..0000000000 --- a/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/fingerprints/GraphQLStorySponsoredDataGetterFingerprint.kt +++ /dev/null @@ -1,29 +0,0 @@ -package app.revanced.patches.facebook.ads.mainfeed.fingerprints - -import app.revanced.patcher.fingerprint.MethodFingerprint -import app.revanced.patches.facebook.ads.mainfeed.fingerprints.GraphQLStorySponsoredDataGetterFingerprint.SPONSORED_DATA_TYPE_ID -import app.revanced.patches.facebook.ads.mainfeed.fingerprints.GraphQLStorySponsoredDataGetterFingerprint.STORY_TYPE_ID -import com.android.tools.smali.dexlib2.iface.MethodImplementation -import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction31i - - -internal object GraphQLStorySponsoredDataGetterFingerprint : MethodFingerprint( - customFingerprint = { methodDef, classDef -> - fun isMatchingLiteralValue(index: Int, literal: Int): Boolean { - val instruction = methodDef.implementation?.instructions?.elementAtOrNull(index) as? Instruction31i - - return instruction?.narrowLiteral == literal - } - - // All methods within the target class are virtually identical apart from two magic constants on each of them. - // They all return an instance of the same model but filled with different GraphQL child node data. - // Likely, the constants are the parent and child node ids. - classDef.type == "Lcom/facebook/graphql/model/GraphQLStory;" && - isMatchingLiteralValue(1, STORY_TYPE_ID) && - isMatchingLiteralValue(2, SPONSORED_DATA_TYPE_ID) - } -) { - // These constants trace back to some GraphQL node type descriptor. - private const val STORY_TYPE_ID = -132939024 - private const val SPONSORED_DATA_TYPE_ID = 341202575 -} From 7f4beefa84142c1cf07a9c35f7092291fb7c3548 Mon Sep 17 00:00:00 2001 From: PantlessCoding Date: Thu, 17 Oct 2024 10:31:27 -0400 Subject: [PATCH 09/11] Use base10 in smali code --- .../facebook/ads/mainfeed/HideSponsoredStoriesPatch.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/HideSponsoredStoriesPatch.kt b/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/HideSponsoredStoriesPatch.kt index 3f79daf8ae..9a04ea2837 100644 --- a/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/HideSponsoredStoriesPatch.kt +++ b/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/HideSponsoredStoriesPatch.kt @@ -60,8 +60,8 @@ object HideSponsoredStoriesPatch : BytecodePatch( addInstructions( """ const-class v2, $baseModelWithTreeType - const v1, ${(if (storyTypeId < 0) "-" else "")}0x${abs(storyTypeId).toString(16)} - const v0, ${(if (sponsoredDataTypeId < 0) "-" else "")}0x${(sponsoredDataTypeId).toString(16)} + const v1, $storyTypeId + const v0, $sponsoredDataTypeId invoke-virtual {p0, v2, v1, v0}, $baseModelMapperMethod move-result-object v0 check-cast v0, $baseModelWithTreeType From ef17de47c90b45f7539061fe89305971d4e6e6e7 Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Thu, 17 Oct 2024 17:30:01 +0200 Subject: [PATCH 10/11] slight refactor --- .../ads/mainfeed/HideSponsoredStoriesPatch.kt | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/HideSponsoredStoriesPatch.kt b/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/HideSponsoredStoriesPatch.kt index 9a04ea2837..6f55db0a1a 100644 --- a/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/HideSponsoredStoriesPatch.kt +++ b/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/HideSponsoredStoriesPatch.kt @@ -1,9 +1,9 @@ package app.revanced.patches.facebook.ads.mainfeed -import app.revanced.util.exception import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels +import app.revanced.patcher.extensions.or import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.annotation.CompatiblePackage import app.revanced.patcher.patch.annotation.Patch @@ -11,21 +11,21 @@ import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMu import app.revanced.patches.facebook.ads.mainfeed.fingerprints.BaseModelMapperFingerprint import app.revanced.patches.facebook.ads.mainfeed.fingerprints.GetSponsoredDataModelTemplateFingerprint import app.revanced.patches.facebook.ads.mainfeed.fingerprints.GetStoryVisibilityFingerprint +import app.revanced.util.exception import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction31i import com.android.tools.smali.dexlib2.immutable.ImmutableMethod import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter -import kotlin.math.abs @Patch( name = "Hide 'Sponsored Stories'", - compatiblePackages = [CompatiblePackage("com.facebook.katana")] + compatiblePackages = [CompatiblePackage("com.facebook.katana")], ) @Suppress("unused") object HideSponsoredStoriesPatch : BytecodePatch( - setOf(GetStoryVisibilityFingerprint, GetSponsoredDataModelTemplateFingerprint, BaseModelMapperFingerprint) + setOf(GetStoryVisibilityFingerprint, GetSponsoredDataModelTemplateFingerprint, BaseModelMapperFingerprint), ) { private const val GRAPHQL_STORY_TYPE = "Lcom/facebook/graphql/model/GraphQLStory;" @@ -37,23 +37,23 @@ object HideSponsoredStoriesPatch : BytecodePatch( // The "SponsoredDataModelTemplate" methods has the ids in its body to extract sponsored data // from GraphQL models, but targets the wrong derived type of "BaseModelWithTree". Since those ids - // could change in future version, We need to extract them and call the base implementation directly. + // could change in future version, we need to extract them and call the base implementation directly. val getSponsoredDataHelperMethod = ImmutableMethod( classDef.type, "getSponsoredData", listOf(ImmutableMethodParameter(GRAPHQL_STORY_TYPE, null, null)), baseModelWithTreeType, - AccessFlags.PRIVATE.value or AccessFlags.STATIC.value, + AccessFlags.PRIVATE or AccessFlags.STATIC, null, null, - MutableMethodImplementation(4) + MutableMethodImplementation(4), ).toMutable().apply { // Extract the ids of the original method. These ids seem to correspond to model types for // GraphQL data structure. They are then fed to a method of BaseModelWithTree that populate // and cast the requested GraphQL subtype. The Ids are found in the two first "CONST" instructions. val constInstructions = sponsoredDataModelTemplateMethod.implementation!!.instructions - .filterIsInstance() - .toList() + .filterIsInstance() + .toList() val storyTypeId = constInstructions.elementAt(0).narrowLiteral val sponsoredDataTypeId = constInstructions.elementAt(1).narrowLiteral @@ -66,7 +66,7 @@ object HideSponsoredStoriesPatch : BytecodePatch( move-result-object v0 check-cast v0, $baseModelWithTreeType return-object v0 - """ + """, ) } @@ -86,7 +86,7 @@ object HideSponsoredStoriesPatch : BytecodePatch( return-object v0 :resume_normal nop - """ + """, ) } ?: throw GetStoryVisibilityFingerprint.exception } From 8e610f9c72bb3c7c54254e8ce1d1f668d38ebd40 Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Thu, 17 Oct 2024 17:33:45 +0200 Subject: [PATCH 11/11] slight refactor --- .../facebook/ads/mainfeed/HideSponsoredStoriesPatch.kt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/HideSponsoredStoriesPatch.kt b/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/HideSponsoredStoriesPatch.kt index 6f55db0a1a..82b0bcd0a5 100644 --- a/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/HideSponsoredStoriesPatch.kt +++ b/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/HideSponsoredStoriesPatch.kt @@ -52,10 +52,13 @@ object HideSponsoredStoriesPatch : BytecodePatch( // GraphQL data structure. They are then fed to a method of BaseModelWithTree that populate // and cast the requested GraphQL subtype. The Ids are found in the two first "CONST" instructions. val constInstructions = sponsoredDataModelTemplateMethod.implementation!!.instructions + .asSequence() .filterIsInstance() + .take(2) .toList() - val storyTypeId = constInstructions.elementAt(0).narrowLiteral - val sponsoredDataTypeId = constInstructions.elementAt(1).narrowLiteral + + val storyTypeId = constInstructions[0].narrowLiteral + val sponsoredDataTypeId = constInstructions[1].narrowLiteral addInstructions( """