Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(Instagram): Added few patches #3604

Draft
wants to merge 20 commits into
base: dev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
2a4c2dc
feat(Instagram): Added `Enable developer menu` patch
Sep 1, 2024
ab1690f
feat(Instagram): Added `Max media quality` patch
Sep 1, 2024
535a50a
feat(Instagram): Added `Selectable bio` patch
Sep 1, 2024
6a54ffb
feat(Instagram): Added `Sanitize sharing links` patch
Sep 1, 2024
685c7c8
feat(Instagram): Added `Open links in external browser` patch
Sep 1, 2024
71657ac
upd(Instagram): Code correction for `Enable developer menu` patch
Sep 2, 2024
7589cef
upd(Instagram): Code correction for `Selectable bio` patch
Sep 2, 2024
0968783
upd(Instagram): Code correction for `Max media quality` patch
Sep 2, 2024
1eb6017
upd(Instagram): Code correction for `Sanitize sharing links` patch
Sep 2, 2024
bf5762b
upd(Instagram): Code correction for `Open links in external browser` …
Sep 2, 2024
af9fc80
upd(Instagram): Code correction for `Enable developer menu` patch
Sep 2, 2024
4ec9a28
upd(Instagram): Code correction for `Open links in external browser` …
Sep 2, 2024
7ab6003
upd(Instagram): Code correction for `Sanitize sharing links` patch
Sep 2, 2024
c36a50f
upd(Instagram): Code correction for `Selectable bio` patch
Sep 2, 2024
b6e2e8a
upd(Instagram): Code correction for `Max media quality` patch
Sep 2, 2024
ddb9ed8
upd(Instagram): updated descriptions.
Sep 2, 2024
606f571
upd(Instagram): Added profile & highlights link `Sanitize sharing lin…
Sep 2, 2024
8788b4e
upd(Instagram): Better patch description for `Max media quality`
Sep 6, 2024
4603458
upd(Instagram): Better patch description for `Max media quality`
Sep 6, 2024
12ef5c9
refactor
oSumAtrIX Sep 17, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions api/revanced-patches.api
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,10 @@ public final class app/revanced/patches/inshorts/ad/HideAdsPatch : app/revanced/
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}

public final class app/revanced/patches/instagram/misc/integrations/IntegrationsPatch : app/revanced/patches/shared/misc/integrations/BaseIntegrationsPatch {
public static final field INSTANCE Lapp/revanced/patches/instagram/misc/integrations/IntegrationsPatch;
}

public final class app/revanced/patches/instagram/patches/ad/HideAdsPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/instagram/patches/ad/HideAdsPatch;
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
Expand All @@ -361,6 +365,36 @@ public final class app/revanced/patches/instagram/patches/ads/timeline/HideTimel
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}

public final class app/revanced/patches/instagram/patches/interaction/bio/SelectableBioPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/instagram/patches/interaction/bio/SelectableBioPatch;
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/instagram/patches/interaction/links/browser/OpenLinksInExternalBrowser : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/instagram/patches/interaction/links/browser/OpenLinksInExternalBrowser;
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/instagram/patches/interaction/links/tracking/SanitizeSharingLinksPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/instagram/patches/interaction/links/tracking/SanitizeSharingLinksPatch;
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/instagram/patches/layout/menu/developer/EnableDeveloperMenuPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/instagram/patches/layout/menu/developer/EnableDeveloperMenuPatch;
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/instagram/patches/misc/quality/MaxMediaQualityPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/instagram/patches/misc/quality/MaxMediaQualityPatch;
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/irplus/ad/RemoveAdsPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/irplus/ad/RemoveAdsPatch;
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package app.revanced.patches.instagram.misc.integrations

import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.instagram.misc.integrations.fingerprints.MainActivityOnCreateFingerprint
import app.revanced.patches.shared.misc.integrations.BaseIntegrationsPatch

@Patch(requiresIntegrations = true)
object IntegrationsPatch : BaseIntegrationsPatch(
setOf(MainActivityOnCreateFingerprint),
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package app.revanced.patches.instagram.misc.integrations.fingerprints

import app.revanced.patches.instagram.misc.integrations.fingerprints.MainActivityOnCreateFingerprint.getApplicationContextIndex
import app.revanced.patches.shared.misc.integrations.BaseIntegrationsPatch.IntegrationsFingerprint
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstructionOrThrow
import com.android.tools.smali.dexlib2.builder.instruction.BuilderInstruction35c
import com.android.tools.smali.dexlib2.iface.reference.MethodReference

internal object MainActivityOnCreateFingerprint : IntegrationsFingerprint(
customFingerprint = { methodDef, _ ->
methodDef.name == "onCreate" && methodDef.definingClass == "Lcom/instagram/app/InstagramAppShell;"
},
insertIndexResolver = { method ->
getApplicationContextIndex = method.indexOfFirstInstructionOrThrow {
getReference<MethodReference>()?.name == "onCreate"
}

getApplicationContextIndex + 1 // Below the invoke-super instruction.
},
contextRegisterResolver = { method ->
val moveResultInstruction = method.implementation!!.instructions.elementAt(getApplicationContextIndex)
as BuilderInstruction35c
moveResultInstruction.registerC
},
) {
private var getApplicationContextIndex = -1
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package app.revanced.patches.instagram.patches.interaction.bio

import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.getInstructions
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.instagram.patches.interaction.bio.fingerprints.SelectableBioFingerprint
import app.revanced.util.resultOrThrow
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction

@Patch(
name = "Selectable bio",
description = "Make the user's bio selectable.",
compatiblePackages = [CompatiblePackage("com.instagram.android")],
)
@Suppress("unused")
object SelectableBioPatch : BytecodePatch(
setOf(SelectableBioFingerprint),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please name fingerprints to the method they match to. If this one for example matches to the constructor, call it "ConstructBioViewFingerprint"

) {
override fun execute(context: BytecodeContext) {
SelectableBioFingerprint.resultOrThrow().mutableMethod.apply {
val setBioTextIndex = getInstructions().first { it.opcode == Opcode.INVOKE_VIRTUAL }.location.index
val setTextViewInstruction = getInstruction<FiveRegisterInstruction>(setBioTextIndex)
val textViewRegister = setTextViewInstruction.registerC
val textRegister = setTextViewInstruction.registerD

// Make the textview selectable.
addInstructions(
setBioTextIndex + 1,
"""
const/4 v$textRegister, 0x1
invoke-virtual { v$textViewRegister, v$textRegister }, Landroid/widget/TextView;->setTextIsSelectable(Z)V
""",
)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package app.revanced.patches.instagram.patches.interaction.bio.fingerprints

import app.revanced.patcher.fingerprint.MethodFingerprint

internal object SelectableBioFingerprint : MethodFingerprint(
strings = listOf("is_bio_visible"),
returnType = "V",
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package app.revanced.patches.instagram.patches.interaction.links.browser

import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.getInstructions
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.smali.ExternalLabel
import app.revanced.patches.instagram.misc.integrations.IntegrationsPatch
import app.revanced.patches.instagram.patches.interaction.links.browser.fingerprints.OpenLinksInExternalBrowserFingerprint
import app.revanced.util.resultOrThrow

@Patch(
name = "Open links in external browser",
dependencies = [IntegrationsPatch::class],
compatiblePackages = [CompatiblePackage("com.instagram.android")],
)
@Suppress("unused")
object OpenLinksInExternalBrowser : BytecodePatch(
setOf(OpenLinksInExternalBrowserFingerprint),
) {
override fun execute(context: BytecodeContext) {
OpenLinksInExternalBrowserFingerprint.resultOrThrow().let { it ->
// Get the method that returns the url.
val getUrlMethod = it.mutableClass.methods.first {
it.returnType == "Ljava/lang/String;" && it.parameters.size == 0
}.name

// Patch the method that opens the link in the internal browser.
it.mutableClass.methods.last { it.returnType == "V" && it.parameters.size == 0 }.apply {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not a safe approach. Please fingerprint the method and get it through that.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Basically that method originally has 4 lines, 2 const/4, 1 invoke and return-void. Moreover both the "get url" method and the method where the fragment is built is present in the same call. So I thought its easier to find the class and then find the methods accordingly

val continueInstruction = getInstructions().first()

// Call the openInExternalBrowser method.
// If it returns true, return void.
// If it returns false, proceed as usual.
addInstructionsWithLabels(
0,
"""
invoke-virtual { p0 }, ${it.classDef}->$getUrlMethod()Ljava/lang/String;
move-result-object v0

invoke-static { v0 }, Lapp/revanced/integrations/instagram/links/ExternalBrowser;->openInExternalBrowser(Ljava/lang/String;)Z
move-result v0

if-eqz v0, :not_opened
return-void
""",
ExternalLabel("not_opened", continueInstruction),
)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package app.revanced.patches.instagram.patches.interaction.links.browser.fingerprints

import app.revanced.patcher.fingerprint.MethodFingerprint

internal object OpenLinksInExternalBrowserFingerprint : MethodFingerprint(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Name the fingerprint like explained above.

strings = listOf("TrackingInfo.ARG_HIDE_SYSTEM_BAR", "TrackingInfo.ARG_MODULE_NAME"),
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package app.revanced.patches.instagram.patches.interaction.links.tracking

import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.getInstructions
import app.revanced.patcher.fingerprint.MethodFingerprint
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
import app.revanced.patches.instagram.patches.interaction.links.tracking.fingerprints.*
import app.revanced.util.getReference
import app.revanced.util.resultOrThrow
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.TypeReference

@Patch(
name = "Sanitize sharing links",
description = "Removes the tracking query parameters from links before they are shared.",
compatiblePackages = [CompatiblePackage("com.instagram.android")],
requiresIntegrations = true,
)
@Suppress("unused")
object SanitizeSharingLinksPatch : BytecodePatch(
setOf(
StoryShareUrlFingerprint,
LiveShareUrlFingerprint,
PostShareClassFinderFingerprint,
ProfileShareUrlFingerprint,
HighlightsShareUrlFingerprint,
Comment on lines +28 to +32
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These fingerprints need to be named according to the method they match too

),
) {
private const val INVOKE_INTEGRATIONS_METHOD_INSTRUCTION =
"Lapp/revanced/integrations/instagram/links/ShareLink;->sanitizeUrl(Ljava/lang/String;)Ljava/lang/String;"

override fun execute(context: BytecodeContext) {
fun sanitizeUrl(method: MutableMethod) = method.apply {
val index = getInstructions().first { it.opcode == Opcode.IPUT_OBJECT }.location.index - 2
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please comment what this index does in the code

// Register where the link is present.
val register = getInstruction<OneRegisterInstruction>(index).registerA

addInstructions(
index + 1,
"""
invoke-static{ v$register }, $INVOKE_INTEGRATIONS_METHOD_INSTRUCTION
move-result-object v$register
""",
)
}

fun sanitizeUrl(fingerprint: MethodFingerprint) = sanitizeUrl(fingerprint.resultOrThrow().mutableMethod)

// Sanitize share link of stories.
sanitizeUrl(StoryShareUrlFingerprint)
// Sanitize share link of live.
sanitizeUrl(LiveShareUrlFingerprint)
// Sanitize share link of profile.
sanitizeUrl(ProfileShareUrlFingerprint)
// Sanitize share link of highlights.
sanitizeUrl(HighlightsShareUrlFingerprint)
// Sanitize share link of posts & reels.
PostShareClassFinderFingerprint.resultOrThrow().mutableMethod.let { method ->
val classIndex = method.getInstructions().last { it.opcode == Opcode.CONST_CLASS }.location.index
val className = method.getInstruction(classIndex).getReference<TypeReference>()!!.type
val parseJsonMethod = context.findClass(className)!!.mutableClass.methods.first {
it.name == "parseFromJson"
}

sanitizeUrl(parseJsonMethod)
}
Comment on lines +64 to +72
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why aren't you using a fingerprint for this?

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package app.revanced.patches.instagram.patches.interaction.links.tracking.fingerprints

import app.revanced.patcher.fingerprint.MethodFingerprint

internal object HighlightsShareUrlFingerprint : MethodFingerprint(
strings = listOf("story_highlights_to_share_url"),
customFingerprint = { methodDef, _ ->
methodDef.name == "parseFromJson"
},
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package app.revanced.patches.instagram.patches.interaction.links.tracking.fingerprints

import app.revanced.patcher.fingerprint.MethodFingerprint

internal object LiveShareUrlFingerprint : MethodFingerprint(
strings = listOf("live_to_share_url"),
customFingerprint = { methodDef, _ ->
methodDef.name == "parseFromJson"
},
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package app.revanced.patches.instagram.patches.interaction.links.tracking.fingerprints

import app.revanced.patcher.fingerprint.MethodFingerprint

internal object PostShareClassFinderFingerprint : MethodFingerprint(
strings = listOf("media/%s/permalink"),
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package app.revanced.patches.instagram.patches.interaction.links.tracking.fingerprints

import app.revanced.patcher.fingerprint.MethodFingerprint

internal object ProfileShareUrlFingerprint : MethodFingerprint(
strings = listOf("profile_to_share_url"),
customFingerprint = { methodDef, _ ->
methodDef.name == "parseFromJson"
},
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package app.revanced.patches.instagram.patches.interaction.links.tracking.fingerprints

import app.revanced.patcher.fingerprint.MethodFingerprint

internal object StoryShareUrlFingerprint : MethodFingerprint(
strings = listOf("story_item_to_share_url"),
customFingerprint = { methodDef, _ ->
methodDef.name == "parseFromJson"
},
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package app.revanced.patches.instagram.patches.layout.menu.developer

import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstructions
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
import app.revanced.patches.instagram.patches.layout.menu.developer.fingerprints.ShouldAddPrefTTLFingerprint
import app.revanced.util.resultOrThrow
import com.android.tools.smali.dexlib2.Opcode

@Patch(
name = "Enable developer menu",
compatiblePackages = [CompatiblePackage("com.instagram.android")],
)
@Suppress("unused")
object EnableDeveloperMenuPatch : BytecodePatch(
setOf(ShouldAddPrefTTLFingerprint),
) {
override fun execute(context: BytecodeContext) {
ShouldAddPrefTTLFingerprint.resultOrThrow().mutableMethod.let { method ->
val isDeveloperMethodCallIndex = method.getInstructions().first {
it.opcode == Opcode.INVOKE_STATIC
}.location.index

val isDeveloperMethod = context.toMethodWalker(method).nextMethod(isDeveloperMethodCallIndex, true)
.getMethod() as MutableMethod

isDeveloperMethod.addInstructions(
0,
"""
const v0, 0x1
return v0
""",
)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package app.revanced.patches.instagram.patches.layout.menu.developer.fingerprints

import app.revanced.patcher.fingerprint.MethodFingerprint

internal object ShouldAddPrefTTLFingerprint : MethodFingerprint(
customFingerprint = { methodDef, _ ->
methodDef.name == "shouldAddPrefTTL" && methodDef.definingClass == "Lcom/instagram/debug/whoptions/WhitehatOptionsFragment;"
},
)
Loading
Loading