From 08659a5a3cf13c0dd4bd3b974d1d5d472adc7d90 Mon Sep 17 00:00:00 2001 From: Alex Uskov Date: Mon, 9 Oct 2023 07:06:45 +0400 Subject: [PATCH 01/26] Make FxTwitter patch --- .../twitter/misc/fxtwitter/FxTwitterPatch.kt | 126 ++++++++++++++++++ .../fingerprints/FxTwitterPatchFingerprint.kt | 13 ++ .../FxTwitterPatchFingerprintResource.kt | 19 +++ 3 files changed, 158 insertions(+) create mode 100644 src/main/kotlin/app/revanced/patches/twitter/misc/fxtwitter/FxTwitterPatch.kt create mode 100644 src/main/kotlin/app/revanced/patches/twitter/misc/fxtwitter/fingerprints/FxTwitterPatchFingerprint.kt create mode 100644 src/main/kotlin/app/revanced/patches/twitter/misc/fxtwitter/fingerprints/FxTwitterPatchFingerprintResource.kt diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/fxtwitter/FxTwitterPatch.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/fxtwitter/FxTwitterPatch.kt new file mode 100644 index 0000000000..9f3dfcec89 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/twitter/misc/fxtwitter/FxTwitterPatch.kt @@ -0,0 +1,126 @@ +package app.revanced.patches.twitter.misc.fxtwitter + +import app.revanced.patcher.data.BytecodeContext +import app.revanced.patcher.extensions.InstructionExtensions.addInstruction +import app.revanced.patcher.extensions.InstructionExtensions.getInstructions +import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction +import app.revanced.patcher.patch.BytecodePatch +import app.revanced.patcher.patch.PatchException +import app.revanced.patcher.patch.annotation.CompatiblePackage +import app.revanced.patcher.patch.annotation.Patch +import app.revanced.patcher.patch.options.types.StringPatchOption.Companion.stringPatchOption +import app.revanced.patches.twitter.misc.fxtwitter.fingerprints.FxTwitterPatchFingerprint +import app.revanced.patches.twitter.misc.fxtwitter.fingerprints.FxTwitterPatchFingerprintResource +import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.builder.BuilderInstruction +import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction +import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction +import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c +import com.android.tools.smali.dexlib2.iface.reference.MethodReference +import com.android.tools.smali.dexlib2.iface.reference.StringReference +import java.util.logging.Logger + + +@Patch( + name = "FxTwitter", + description = "Replaces the default Twitter share link with FxTwitter.", + compatiblePackages = [CompatiblePackage("com.twitter.android")] +) +@Suppress("unused") +object FxTwitterPatch : BytecodePatch( + setOf(FxTwitterPatchFingerprint, FxTwitterPatchFingerprintResource) +) { + private var shareLinkBase by stringPatchOption( + key = "twitter_share_link_base", + default = "fxtwitter.com", + title = "Embed builder domain", + description = "The embed builder domain used to share the twitter links. (Default: fxtwitter.com) known alts: vxtwitter.com, fixupx.com.", + ) + + override fun execute(context: BytecodeContext) { + var twitterGetShareLinkMethod = FxTwitterPatchFingerprint.result?.apply { + val instructions = this.mutableMethod.getInstructions() + + for ((index, instruction) in instructions.withIndex()) { + if (instruction.opcode == Opcode.CONST_STRING) { + val string = ((instruction as ReferenceInstruction).reference as StringReference).string + + if (string.contains("https://twitter.com/%1\$s/status/%2\$d") || string.contains("https://x.com/%1\$s/status/%2\$d")) { + val overrideRegister = (instruction as OneRegisterInstruction).registerA + + // Totally efficient + var overrideString = string.replace("twitter.com", shareLinkBase.toString()) + overrideString = overrideString.replace("x.com", shareLinkBase.toString()) + this.mutableMethod.replaceInstruction( + index, + """ + const-string v$overrideRegister, "$overrideString" + """ + ) + } + } + } + } ?: throw PatchException("FxTwitterPatchFingerprint not found") + + + FxTwitterPatchFingerprintResource.result?.apply { + val instructions = this.mutableMethod.getInstructions() + + // Save user nickname to v9 + for ((index, instruction) in instructions.withIndex()) { + if (instruction.opcode == Opcode.INVOKE_VIRTUAL) { + + val methodRef = + (instruction as ReferenceInstruction).reference as MethodReference + if ( + methodRef.returnType != "Ljava/lang/String;") continue; + + this.mutableMethod.addInstruction( + index + 2, + """ + move-object v9, v3 + """ + ) + + break; + } + } + + // Save tweet id to v7, v8 + for ((index, instruction) in instructions.withIndex()) { + if (instruction.opcode == Opcode.INVOKE_VIRTUAL) { + + val methodRef = + (instruction as ReferenceInstruction).reference as MethodReference + if (methodRef.definingClass != "Ljava/lang/Long;") continue; + + this.mutableMethod.addInstruction( + index + 2, + """ + move-wide v7, v5 + """ + ) + break; + } + } + + // Call the method patched by FxTwitterPatchFingerprint + for ((index, instruction) in instructions.withIndex()) { + if (instruction.opcode == Opcode.INVOKE_VIRTUAL) { + + val methodRef = + (instruction as ReferenceInstruction).reference as MethodReference + if (methodRef.definingClass != "Landroid/content/res/Resources;") continue; + + this.mutableMethod.replaceInstruction( + index, + """ + invoke-static { v7, v8, v9 }, ${twitterGetShareLinkMethod.method} + """ + ) + break; + } + } + } + } +} diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/fxtwitter/fingerprints/FxTwitterPatchFingerprint.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/fxtwitter/fingerprints/FxTwitterPatchFingerprint.kt new file mode 100644 index 0000000000..e6af5db9ee --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/twitter/misc/fxtwitter/fingerprints/FxTwitterPatchFingerprint.kt @@ -0,0 +1,13 @@ +package app.revanced.patches.twitter.misc.fxtwitter.fingerprints + +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint +import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.AccessFlags + +object FxTwitterPatchFingerprint: MethodFingerprint( + accessFlags = AccessFlags.PUBLIC.value or AccessFlags.STATIC.value, + opcodes = listOf(Opcode.RETURN_OBJECT), + returnType = "Ljava/lang/String;", + parameters = listOf("J", "Ljava/lang/String;"), + strings = listOf("/%1\$s/status/%2\$d"), +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/fxtwitter/fingerprints/FxTwitterPatchFingerprintResource.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/fxtwitter/fingerprints/FxTwitterPatchFingerprintResource.kt new file mode 100644 index 0000000000..103319ef0f --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/twitter/misc/fxtwitter/fingerprints/FxTwitterPatchFingerprintResource.kt @@ -0,0 +1,19 @@ +package app.revanced.patches.twitter.misc.fxtwitter.fingerprints + +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint +import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.AccessFlags + +object FxTwitterPatchFingerprintResource: MethodFingerprint( + accessFlags = AccessFlags.PUBLIC.value or AccessFlags.FINAL.value, + opcodes = listOf( + Opcode.CONST_STRING, + Opcode.INVOKE_STATIC, + Opcode.CONST_4, + Opcode.NEW_ARRAY, + Opcode.IGET_OBJECT, + Opcode.INVOKE_VIRTUAL, + ), + parameters = listOf("Landroid/content/res/Resources;"), + strings = listOf("res.getString"), +) \ No newline at end of file From 6a666c0cc32acbd6f58d03432adc2cceaaab4f6c Mon Sep 17 00:00:00 2001 From: Alex Uskov Date: Mon, 9 Oct 2023 07:27:01 +0400 Subject: [PATCH 02/26] Fix replacing logic. Add dynamic source registers --- .../twitter/misc/fxtwitter/FxTwitterPatch.kt | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/fxtwitter/FxTwitterPatch.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/fxtwitter/FxTwitterPatch.kt index 9f3dfcec89..36f6df58eb 100644 --- a/src/main/kotlin/app/revanced/patches/twitter/misc/fxtwitter/FxTwitterPatch.kt +++ b/src/main/kotlin/app/revanced/patches/twitter/misc/fxtwitter/FxTwitterPatch.kt @@ -48,9 +48,13 @@ object FxTwitterPatch : BytecodePatch( if (string.contains("https://twitter.com/%1\$s/status/%2\$d") || string.contains("https://x.com/%1\$s/status/%2\$d")) { val overrideRegister = (instruction as OneRegisterInstruction).registerA - // Totally efficient - var overrideString = string.replace("twitter.com", shareLinkBase.toString()) - overrideString = overrideString.replace("x.com", shareLinkBase.toString()) + var overrideString = string + if (string.contains("twitter.com")) { + overrideString = string.replace("twitter.com", shareLinkBase.toString()) + } else if (string.contains("x.com")) { + overrideString = string.replace("x.com", shareLinkBase.toString()) + } + this.mutableMethod.replaceInstruction( index, """ @@ -75,10 +79,12 @@ object FxTwitterPatch : BytecodePatch( if ( methodRef.returnType != "Ljava/lang/String;") continue; + val sourceRegister = (instructions[index + 1] as OneRegisterInstruction).registerA + this.mutableMethod.addInstruction( index + 2, """ - move-object v9, v3 + move-object v9, v$sourceRegister """ ) @@ -94,10 +100,12 @@ object FxTwitterPatch : BytecodePatch( (instruction as ReferenceInstruction).reference as MethodReference if (methodRef.definingClass != "Ljava/lang/Long;") continue; + val sourceRegister = (instructions[index + 1] as OneRegisterInstruction).registerA + this.mutableMethod.addInstruction( index + 2, """ - move-wide v7, v5 + move-wide v7, v$sourceRegister """ ) break; From 8e071a1f4fe1699008f9d352b4f28661e520d01e Mon Sep 17 00:00:00 2001 From: Alex Uskov Date: Mon, 9 Oct 2023 10:18:00 +0400 Subject: [PATCH 03/26] Fixes for the patch. Change the patching algo to make the patch more stable --- .../ChangeLinkSharingDomainPatch.kt} | 93 ++++++++++--------- .../LinkBuilderMethodFingerprint.kt} | 7 +- .../LinkResourceGetterFingerprint.kt} | 5 +- 3 files changed, 58 insertions(+), 47 deletions(-) rename src/main/kotlin/app/revanced/patches/twitter/misc/{fxtwitter/FxTwitterPatch.kt => links/ChangeLinkSharingDomainPatch.kt} (60%) rename src/main/kotlin/app/revanced/patches/twitter/misc/{fxtwitter/fingerprints/FxTwitterPatchFingerprint.kt => links/fingerprints/LinkBuilderMethodFingerprint.kt} (69%) rename src/main/kotlin/app/revanced/patches/twitter/misc/{fxtwitter/fingerprints/FxTwitterPatchFingerprintResource.kt => links/fingerprints/LinkResourceGetterFingerprint.kt} (72%) diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/fxtwitter/FxTwitterPatch.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt similarity index 60% rename from src/main/kotlin/app/revanced/patches/twitter/misc/fxtwitter/FxTwitterPatch.kt rename to src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt index 36f6df58eb..b2312dce53 100644 --- a/src/main/kotlin/app/revanced/patches/twitter/misc/fxtwitter/FxTwitterPatch.kt +++ b/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt @@ -1,44 +1,45 @@ -package app.revanced.patches.twitter.misc.fxtwitter +package app.revanced.patches.twitter.misc.links +import app.revanced.extensions.exception import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.extensions.InstructionExtensions.addInstruction +import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.InstructionExtensions.getInstructions +import app.revanced.patcher.extensions.InstructionExtensions.removeInstructions import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchException import app.revanced.patcher.patch.annotation.CompatiblePackage import app.revanced.patcher.patch.annotation.Patch import app.revanced.patcher.patch.options.types.StringPatchOption.Companion.stringPatchOption -import app.revanced.patches.twitter.misc.fxtwitter.fingerprints.FxTwitterPatchFingerprint -import app.revanced.patches.twitter.misc.fxtwitter.fingerprints.FxTwitterPatchFingerprintResource +import app.revanced.patches.twitter.misc.links.fingerprints.LinkBuilderMethodFingerprint +import app.revanced.patches.twitter.misc.links.fingerprints.LinkResourceGetterFingerprint import com.android.tools.smali.dexlib2.Opcode -import com.android.tools.smali.dexlib2.builder.BuilderInstruction import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction -import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c import com.android.tools.smali.dexlib2.iface.reference.MethodReference import com.android.tools.smali.dexlib2.iface.reference.StringReference -import java.util.logging.Logger @Patch( - name = "FxTwitter", - description = "Replaces the default Twitter share link with FxTwitter.", + name = "Change link sharing domain", + description = "Replaces the default Twitter share domain.", compatiblePackages = [CompatiblePackage("com.twitter.android")] ) @Suppress("unused") -object FxTwitterPatch : BytecodePatch( - setOf(FxTwitterPatchFingerprint, FxTwitterPatchFingerprintResource) +object ChangeLinkSharingDomainPatch : BytecodePatch( + setOf(LinkBuilderMethodFingerprint, LinkResourceGetterFingerprint) ) { - private var shareLinkBase by stringPatchOption( - key = "twitter_share_link_base", + private var domain by stringPatchOption( + key = "domain", default = "fxtwitter.com", - title = "Embed builder domain", - description = "The embed builder domain used to share the twitter links. (Default: fxtwitter.com) known alts: vxtwitter.com, fixupx.com.", + title = "Domain name", + description = "The domain to use when sharing links.", ) override fun execute(context: BytecodeContext) { - var twitterGetShareLinkMethod = FxTwitterPatchFingerprint.result?.apply { + + // Replace the domain in the method that generates the share link + val linkBuilderMethod = LinkBuilderMethodFingerprint.result?.apply { val instructions = this.mutableMethod.getInstructions() for ((index, instruction) in instructions.withIndex()) { @@ -50,9 +51,9 @@ object FxTwitterPatch : BytecodePatch( var overrideString = string if (string.contains("twitter.com")) { - overrideString = string.replace("twitter.com", shareLinkBase.toString()) + overrideString = string.replace("twitter.com", domain.toString()) } else if (string.contains("x.com")) { - overrideString = string.replace("x.com", shareLinkBase.toString()) + overrideString = string.replace("x.com", domain.toString()) } this.mutableMethod.replaceInstruction( @@ -64,71 +65,79 @@ object FxTwitterPatch : BytecodePatch( } } } - } ?: throw PatchException("FxTwitterPatchFingerprint not found") - + } ?: throw LinkBuilderMethodFingerprint.exception - FxTwitterPatchFingerprintResource.result?.apply { + LinkResourceGetterFingerprint.result?.apply { val instructions = this.mutableMethod.getInstructions() - // Save user nickname to v9 + // Result register of the original method call + var resultRegister = 0 + + // Remove instructions at the end and get the register of the last instruction for ((index, instruction) in instructions.withIndex()) { if (instruction.opcode == Opcode.INVOKE_VIRTUAL) { - val methodRef = (instruction as ReferenceInstruction).reference as MethodReference - if ( - methodRef.returnType != "Ljava/lang/String;") continue; + if (methodRef.definingClass != "Landroid/content/res/Resources;") continue; - val sourceRegister = (instructions[index + 1] as OneRegisterInstruction).registerA + // Get the result register of the original method call + resultRegister = (instructions[index + 1] as OneRegisterInstruction).registerA - this.mutableMethod.addInstruction( - index + 2, - """ - move-object v9, v$sourceRegister - """ - ) + // Remove the original method call for getting the link from resources and the move-result-object instruction + this.mutableMethod.removeInstructions(index, 2) + + // Remove the instruction that uses the resultRegister as an array reference to prevent an error + this.mutableMethod.removeInstructions(index - 2, 1) break; } } - // Save tweet id to v7, v8 + // Save user nickname to v7 for ((index, instruction) in instructions.withIndex()) { if (instruction.opcode == Opcode.INVOKE_VIRTUAL) { val methodRef = (instruction as ReferenceInstruction).reference as MethodReference - if (methodRef.definingClass != "Ljava/lang/Long;") continue; + if ( + methodRef.returnType != "Ljava/lang/String;") continue; val sourceRegister = (instructions[index + 1] as OneRegisterInstruction).registerA - this.mutableMethod.addInstruction( index + 2, """ - move-wide v7, v$sourceRegister + move-object v7, v$sourceRegister """ ) break; } } - // Call the method patched by FxTwitterPatchFingerprint + // Call the patched method and save the result to resultRegister for ((index, instruction) in instructions.withIndex()) { if (instruction.opcode == Opcode.INVOKE_VIRTUAL) { val methodRef = (instruction as ReferenceInstruction).reference as MethodReference - if (methodRef.definingClass != "Landroid/content/res/Resources;") continue; + if (methodRef.definingClass != "Ljava/lang/Long;") continue; + + // Get the first part of the tweet ID + val sourceRegister = (instructions[index + 1] as OneRegisterInstruction).registerA + // Get the second part of the tweet ID + val sourcePlusOne = sourceRegister + 1 - this.mutableMethod.replaceInstruction( - index, + // Call the patched method with the tweet ID and username and save the result to resultRegister + this.mutableMethod.addInstructions( + index + 2, """ - invoke-static { v7, v8, v9 }, ${twitterGetShareLinkMethod.method} + invoke-static { v$sourceRegister, v$sourcePlusOne, v7 }, ${linkBuilderMethod.method} + move-result-object v$resultRegister """ ) break; } } - } + + } ?: throw LinkBuilderMethodFingerprint.exception } } diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/fxtwitter/fingerprints/FxTwitterPatchFingerprint.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/LinkBuilderMethodFingerprint.kt similarity index 69% rename from src/main/kotlin/app/revanced/patches/twitter/misc/fxtwitter/fingerprints/FxTwitterPatchFingerprint.kt rename to src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/LinkBuilderMethodFingerprint.kt index e6af5db9ee..b03289c16b 100644 --- a/src/main/kotlin/app/revanced/patches/twitter/misc/fxtwitter/fingerprints/FxTwitterPatchFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/LinkBuilderMethodFingerprint.kt @@ -1,10 +1,11 @@ -package app.revanced.patches.twitter.misc.fxtwitter.fingerprints +package app.revanced.patches.twitter.misc.links.fingerprints import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.Opcode -object FxTwitterPatchFingerprint: MethodFingerprint( +// Returns a shareable link string based on a tweet ID and a username +object LinkBuilderMethodFingerprint : MethodFingerprint( accessFlags = AccessFlags.PUBLIC.value or AccessFlags.STATIC.value, opcodes = listOf(Opcode.RETURN_OBJECT), returnType = "Ljava/lang/String;", diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/fxtwitter/fingerprints/FxTwitterPatchFingerprintResource.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/LinkResourceGetterFingerprint.kt similarity index 72% rename from src/main/kotlin/app/revanced/patches/twitter/misc/fxtwitter/fingerprints/FxTwitterPatchFingerprintResource.kt rename to src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/LinkResourceGetterFingerprint.kt index 103319ef0f..b4a62411b2 100644 --- a/src/main/kotlin/app/revanced/patches/twitter/misc/fxtwitter/fingerprints/FxTwitterPatchFingerprintResource.kt +++ b/src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/LinkResourceGetterFingerprint.kt @@ -1,10 +1,11 @@ -package app.revanced.patches.twitter.misc.fxtwitter.fingerprints +package app.revanced.patches.twitter.misc.links.fingerprints import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.AccessFlags -object FxTwitterPatchFingerprintResource: MethodFingerprint( +// Gets Resource string for share link view available by pressing "Share via" button +object LinkResourceGetterFingerprint : MethodFingerprint( accessFlags = AccessFlags.PUBLIC.value or AccessFlags.FINAL.value, opcodes = listOf( Opcode.CONST_STRING, From 15cc3c09cf2ec119e22d2ac0dd11c5f442da0259 Mon Sep 17 00:00:00 2001 From: Alex Uskov Date: Mon, 9 Oct 2023 15:17:49 +0400 Subject: [PATCH 04/26] Add removal of telemetry from links too (not sure if should be its own patch) --- .../misc/links/ChangeLinkSharingDomainPatch.kt | 14 ++++++++++++-- .../fingerprints/AddTelemetryToLinkFingerprint.kt | 14 ++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/AddTelemetryToLinkFingerprint.kt diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt index b2312dce53..5334ce3d82 100644 --- a/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt +++ b/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt @@ -11,6 +11,7 @@ import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.annotation.CompatiblePackage import app.revanced.patcher.patch.annotation.Patch import app.revanced.patcher.patch.options.types.StringPatchOption.Companion.stringPatchOption +import app.revanced.patches.twitter.misc.links.fingerprints.AddTelemetryToLinkFingerprint import app.revanced.patches.twitter.misc.links.fingerprints.LinkBuilderMethodFingerprint import app.revanced.patches.twitter.misc.links.fingerprints.LinkResourceGetterFingerprint import com.android.tools.smali.dexlib2.Opcode @@ -27,7 +28,7 @@ import com.android.tools.smali.dexlib2.iface.reference.StringReference ) @Suppress("unused") object ChangeLinkSharingDomainPatch : BytecodePatch( - setOf(LinkBuilderMethodFingerprint, LinkResourceGetterFingerprint) + setOf(LinkBuilderMethodFingerprint, LinkResourceGetterFingerprint, AddTelemetryToLinkFingerprint) ) { private var domain by stringPatchOption( key = "domain", @@ -37,6 +38,15 @@ object ChangeLinkSharingDomainPatch : BytecodePatch( ) override fun execute(context: BytecodeContext) { + // Remove telemetry from links + AddTelemetryToLinkFingerprint.result?.apply { + this.mutableMethod.addInstruction( + 0, + """ + return-object p0 + """ + ) + } ?: throw AddTelemetryToLinkFingerprint.exception // Replace the domain in the method that generates the share link val linkBuilderMethod = LinkBuilderMethodFingerprint.result?.apply { @@ -138,6 +148,6 @@ object ChangeLinkSharingDomainPatch : BytecodePatch( } } - } ?: throw LinkBuilderMethodFingerprint.exception + } ?: throw LinkResourceGetterFingerprint.exception } } diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/AddTelemetryToLinkFingerprint.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/AddTelemetryToLinkFingerprint.kt new file mode 100644 index 0000000000..7a91c01269 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/AddTelemetryToLinkFingerprint.kt @@ -0,0 +1,14 @@ +package app.revanced.patches.twitter.misc.links.fingerprints + +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint +import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.Opcode + +// Returns a shareable link string based on a tweet ID and a username +object AddTelemetryToLinkFingerprint : MethodFingerprint( + accessFlags = AccessFlags.PUBLIC.value or AccessFlags.STATIC.value or AccessFlags.FINAL.value, + opcodes = listOf(Opcode.RETURN_OBJECT), + returnType = "Ljava/lang/String;", + parameters = listOf("Ljava/lang/String;", "I", "Ljava/lang/String;"), + strings = listOf("", "shareParam", "sessionToken"), +) \ No newline at end of file From 5b0eec28af514c48a42004f6e4b230ed58e7d792 Mon Sep 17 00:00:00 2001 From: Alex Uskov Date: Mon, 9 Oct 2023 15:24:41 +0400 Subject: [PATCH 05/26] Fix comment --- .../misc/links/fingerprints/AddTelemetryToLinkFingerprint.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/AddTelemetryToLinkFingerprint.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/AddTelemetryToLinkFingerprint.kt index 7a91c01269..3bee1fb2e5 100644 --- a/src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/AddTelemetryToLinkFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/AddTelemetryToLinkFingerprint.kt @@ -4,7 +4,7 @@ import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -// Returns a shareable link string based on a tweet ID and a username +// Adds telemetry to the share links object AddTelemetryToLinkFingerprint : MethodFingerprint( accessFlags = AccessFlags.PUBLIC.value or AccessFlags.STATIC.value or AccessFlags.FINAL.value, opcodes = listOf(Opcode.RETURN_OBJECT), From 243bae34a46aa4eceee54828fd34a59b05740e44 Mon Sep 17 00:00:00 2001 From: Alex Uskov Date: Mon, 9 Oct 2023 15:42:52 +0400 Subject: [PATCH 06/26] Moved telemetry patch to its own file --- .../links/ChangeLinkSharingDomainPatch.kt | 13 +------- .../misc/links/RemoveLinkTelemetryPatch.kt | 31 +++++++++++++++++++ 2 files changed, 32 insertions(+), 12 deletions(-) create mode 100644 src/main/kotlin/app/revanced/patches/twitter/misc/links/RemoveLinkTelemetryPatch.kt diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt index 5334ce3d82..684bdb77d7 100644 --- a/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt +++ b/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt @@ -11,7 +11,6 @@ import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.annotation.CompatiblePackage import app.revanced.patcher.patch.annotation.Patch import app.revanced.patcher.patch.options.types.StringPatchOption.Companion.stringPatchOption -import app.revanced.patches.twitter.misc.links.fingerprints.AddTelemetryToLinkFingerprint import app.revanced.patches.twitter.misc.links.fingerprints.LinkBuilderMethodFingerprint import app.revanced.patches.twitter.misc.links.fingerprints.LinkResourceGetterFingerprint import com.android.tools.smali.dexlib2.Opcode @@ -28,7 +27,7 @@ import com.android.tools.smali.dexlib2.iface.reference.StringReference ) @Suppress("unused") object ChangeLinkSharingDomainPatch : BytecodePatch( - setOf(LinkBuilderMethodFingerprint, LinkResourceGetterFingerprint, AddTelemetryToLinkFingerprint) + setOf(LinkBuilderMethodFingerprint, LinkResourceGetterFingerprint) ) { private var domain by stringPatchOption( key = "domain", @@ -38,16 +37,6 @@ object ChangeLinkSharingDomainPatch : BytecodePatch( ) override fun execute(context: BytecodeContext) { - // Remove telemetry from links - AddTelemetryToLinkFingerprint.result?.apply { - this.mutableMethod.addInstruction( - 0, - """ - return-object p0 - """ - ) - } ?: throw AddTelemetryToLinkFingerprint.exception - // Replace the domain in the method that generates the share link val linkBuilderMethod = LinkBuilderMethodFingerprint.result?.apply { val instructions = this.mutableMethod.getInstructions() diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/links/RemoveLinkTelemetryPatch.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/links/RemoveLinkTelemetryPatch.kt new file mode 100644 index 0000000000..d4dafeb456 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/twitter/misc/links/RemoveLinkTelemetryPatch.kt @@ -0,0 +1,31 @@ +package app.revanced.patches.twitter.misc.links + +import app.revanced.extensions.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.twitter.misc.links.fingerprints.AddTelemetryToLinkFingerprint + +@Patch( + name = "Remove link telemetry", + description = "Removes telemetry at the end of the links", + compatiblePackages = [CompatiblePackage("com.twitter.android")] +) +@Suppress("unused") +object RemoveLinkTelemetryPatch : BytecodePatch( + setOf(AddTelemetryToLinkFingerprint) +) { + override fun execute(context: BytecodeContext) { + // Remove telemetry from links + AddTelemetryToLinkFingerprint.result?.apply { + this.mutableMethod.addInstruction( + 0, + """ + return-object p0 + """ + ) + } ?: throw AddTelemetryToLinkFingerprint.exception + } +} From a34205f8585c99ddc76b8eb293e005171949548e Mon Sep 17 00:00:00 2001 From: Alex Uskov Date: Tue, 10 Oct 2023 15:29:27 +0400 Subject: [PATCH 07/26] Simplify patch --- .../links/ChangeLinkSharingDomainPatch.kt | 58 +++++++++---------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt index 684bdb77d7..1d937f18d3 100644 --- a/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt +++ b/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt @@ -4,6 +4,7 @@ import app.revanced.extensions.exception import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.extensions.InstructionExtensions.addInstruction 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.extensions.InstructionExtensions.removeInstructions import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction @@ -39,31 +40,30 @@ object ChangeLinkSharingDomainPatch : BytecodePatch( override fun execute(context: BytecodeContext) { // Replace the domain in the method that generates the share link val linkBuilderMethod = LinkBuilderMethodFingerprint.result?.apply { - val instructions = this.mutableMethod.getInstructions() - for ((index, instruction) in instructions.withIndex()) { - if (instruction.opcode == Opcode.CONST_STRING) { - val string = ((instruction as ReferenceInstruction).reference as StringReference).string - - if (string.contains("https://twitter.com/%1\$s/status/%2\$d") || string.contains("https://x.com/%1\$s/status/%2\$d")) { - val overrideRegister = (instruction as OneRegisterInstruction).registerA - - var overrideString = string - if (string.contains("twitter.com")) { - overrideString = string.replace("twitter.com", domain.toString()) - } else if (string.contains("x.com")) { - overrideString = string.replace("x.com", domain.toString()) - } - - this.mutableMethod.replaceInstruction( - index, - """ - const-string v$overrideRegister, "$overrideString" - """ - ) - } - } + // Find the index of the string instruction that contains the link + val stringIndex = scanResult.stringsScanResult!!.matches.find { match -> + ( + match.string == "https://twitter.com/%1\$s/status/%2\$d" || match.string == "https://x.com/%1\$s/status/%2\$d") + }!!.index + + val instruction = this.mutableMethod.getInstruction(stringIndex) + val overrideRegister = (instruction as OneRegisterInstruction).registerA + val string = ((instruction as ReferenceInstruction).reference as StringReference).string + + var overrideString = string + if (string.contains("twitter.com")) { + overrideString = string.replace("twitter.com", domain.toString()) + } else if (string.contains("x.com")) { + overrideString = string.replace("x.com", domain.toString()) } + + this.mutableMethod.replaceInstruction( + stringIndex, + """ + const-string v$overrideRegister, "$overrideString" + """ + ) } ?: throw LinkBuilderMethodFingerprint.exception LinkResourceGetterFingerprint.result?.apply { @@ -77,7 +77,7 @@ object ChangeLinkSharingDomainPatch : BytecodePatch( if (instruction.opcode == Opcode.INVOKE_VIRTUAL) { val methodRef = (instruction as ReferenceInstruction).reference as MethodReference - if (methodRef.definingClass != "Landroid/content/res/Resources;") continue; + if (methodRef.definingClass != "Landroid/content/res/Resources;") continue // Get the result register of the original method call resultRegister = (instructions[index + 1] as OneRegisterInstruction).registerA @@ -88,7 +88,7 @@ object ChangeLinkSharingDomainPatch : BytecodePatch( // Remove the instruction that uses the resultRegister as an array reference to prevent an error this.mutableMethod.removeInstructions(index - 2, 1) - break; + break } } @@ -99,7 +99,7 @@ object ChangeLinkSharingDomainPatch : BytecodePatch( val methodRef = (instruction as ReferenceInstruction).reference as MethodReference if ( - methodRef.returnType != "Ljava/lang/String;") continue; + methodRef.returnType != "Ljava/lang/String;") continue val sourceRegister = (instructions[index + 1] as OneRegisterInstruction).registerA this.mutableMethod.addInstruction( @@ -108,7 +108,7 @@ object ChangeLinkSharingDomainPatch : BytecodePatch( move-object v7, v$sourceRegister """ ) - break; + break } } @@ -118,7 +118,7 @@ object ChangeLinkSharingDomainPatch : BytecodePatch( val methodRef = (instruction as ReferenceInstruction).reference as MethodReference - if (methodRef.definingClass != "Ljava/lang/Long;") continue; + if (methodRef.definingClass != "Ljava/lang/Long;") continue // Get the first part of the tweet ID val sourceRegister = (instructions[index + 1] as OneRegisterInstruction).registerA @@ -133,7 +133,7 @@ object ChangeLinkSharingDomainPatch : BytecodePatch( move-result-object v$resultRegister """ ) - break; + break } } From 32394bea93f7e7a5f82dde9ac78eb849a5b6541a Mon Sep 17 00:00:00 2001 From: Alex Uskov Date: Fri, 13 Oct 2023 16:45:19 +0400 Subject: [PATCH 08/26] Update src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt Co-authored-by: oSumAtrIX --- .../patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt index 1d937f18d3..e56bb46ade 100644 --- a/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt +++ b/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt @@ -23,7 +23,7 @@ import com.android.tools.smali.dexlib2.iface.reference.StringReference @Patch( name = "Change link sharing domain", - description = "Replaces the default Twitter share domain.", + description = "Replaces the domain name of Twitter links when sharing them.", compatiblePackages = [CompatiblePackage("com.twitter.android")] ) @Suppress("unused") From 936853875d9d3939515c0f832a6bd97eed48ba4a Mon Sep 17 00:00:00 2001 From: Alex Uskov Date: Fri, 13 Oct 2023 16:45:50 +0400 Subject: [PATCH 09/26] Update src/main/kotlin/app/revanced/patches/twitter/misc/links/RemoveLinkTelemetryPatch.kt Co-authored-by: oSumAtrIX --- .../twitter/misc/links/RemoveLinkTelemetryPatch.kt | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/links/RemoveLinkTelemetryPatch.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/links/RemoveLinkTelemetryPatch.kt index d4dafeb456..154aef4d44 100644 --- a/src/main/kotlin/app/revanced/patches/twitter/misc/links/RemoveLinkTelemetryPatch.kt +++ b/src/main/kotlin/app/revanced/patches/twitter/misc/links/RemoveLinkTelemetryPatch.kt @@ -19,13 +19,7 @@ object RemoveLinkTelemetryPatch : BytecodePatch( ) { override fun execute(context: BytecodeContext) { // Remove telemetry from links - AddTelemetryToLinkFingerprint.result?.apply { - this.mutableMethod.addInstruction( - 0, - """ - return-object p0 - """ - ) - } ?: throw AddTelemetryToLinkFingerprint.exception + AddTelemetryToLinkFingerprint.result?.mutableMethod?.addInstruction(0, "return-object p0") + ?: throw AddTelemetryToLinkFingerprint.exception } } From d67acd4d0ecee28895e1c068abdfd1d7b5ca48d2 Mon Sep 17 00:00:00 2001 From: Alex Uskov Date: Tue, 28 Nov 2023 11:50:06 +0400 Subject: [PATCH 10/26] Simplify stuff --- .../links/ChangeLinkSharingDomainPatch.kt | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt index e56bb46ade..9253804a0d 100644 --- a/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt +++ b/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt @@ -43,19 +43,22 @@ object ChangeLinkSharingDomainPatch : BytecodePatch( // Find the index of the string instruction that contains the link val stringIndex = scanResult.stringsScanResult!!.matches.find { match -> - ( - match.string == "https://twitter.com/%1\$s/status/%2\$d" || match.string == "https://x.com/%1\$s/status/%2\$d") + (match.string == "https://twitter.com/%1\$s/status/%2\$d" || match.string == "https://x.com/%1\$s/status/%2\$d") }!!.index - val instruction = this.mutableMethod.getInstruction(stringIndex) - val overrideRegister = (instruction as OneRegisterInstruction).registerA + val instruction = this.mutableMethod.getInstruction(stringIndex) + val overrideRegister = instruction.registerA val string = ((instruction as ReferenceInstruction).reference as StringReference).string var overrideString = string - if (string.contains("twitter.com")) { - overrideString = string.replace("twitter.com", domain.toString()) - } else if (string.contains("x.com")) { - overrideString = string.replace("x.com", domain.toString()) + when { + string.contains("twitter.com") -> { + overrideString = string.replace("twitter.com", domain.toString()) + } + + string.contains("x.com") -> { + overrideString = string.replace("x.com", domain.toString()) + } } this.mutableMethod.replaceInstruction( @@ -98,8 +101,8 @@ object ChangeLinkSharingDomainPatch : BytecodePatch( val methodRef = (instruction as ReferenceInstruction).reference as MethodReference - if ( - methodRef.returnType != "Ljava/lang/String;") continue + + if (methodRef.returnType != "Ljava/lang/String;") continue val sourceRegister = (instructions[index + 1] as OneRegisterInstruction).registerA this.mutableMethod.addInstruction( From 788ecff43a4c8ff5be3c066b3b32482368c55ffb Mon Sep 17 00:00:00 2001 From: Alex Uskov Date: Tue, 28 Nov 2023 12:02:20 +0400 Subject: [PATCH 11/26] Fixup comments --- .../patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt index 9253804a0d..58b3474438 100644 --- a/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt +++ b/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt @@ -123,9 +123,8 @@ object ChangeLinkSharingDomainPatch : BytecodePatch( (instruction as ReferenceInstruction).reference as MethodReference if (methodRef.definingClass != "Ljava/lang/Long;") continue - // Get the first part of the tweet ID + // Get the registers for tweet ID number (64 bits) val sourceRegister = (instructions[index + 1] as OneRegisterInstruction).registerA - // Get the second part of the tweet ID val sourcePlusOne = sourceRegister + 1 // Call the patched method with the tweet ID and username and save the result to resultRegister From a69d91635b3d5722f85972df6898673656d1fafe Mon Sep 17 00:00:00 2001 From: Alex Uskov Date: Tue, 28 Nov 2023 12:39:32 +0400 Subject: [PATCH 12/26] Reduce size of fingerprints --- .../misc/links/fingerprints/AddTelemetryToLinkFingerprint.kt | 4 ---- .../misc/links/fingerprints/LinkBuilderMethodFingerprint.kt | 4 ---- 2 files changed, 8 deletions(-) diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/AddTelemetryToLinkFingerprint.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/AddTelemetryToLinkFingerprint.kt index 3bee1fb2e5..7c249c0816 100644 --- a/src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/AddTelemetryToLinkFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/AddTelemetryToLinkFingerprint.kt @@ -6,9 +6,5 @@ import com.android.tools.smali.dexlib2.Opcode // Adds telemetry to the share links object AddTelemetryToLinkFingerprint : MethodFingerprint( - accessFlags = AccessFlags.PUBLIC.value or AccessFlags.STATIC.value or AccessFlags.FINAL.value, - opcodes = listOf(Opcode.RETURN_OBJECT), - returnType = "Ljava/lang/String;", - parameters = listOf("Ljava/lang/String;", "I", "Ljava/lang/String;"), strings = listOf("", "shareParam", "sessionToken"), ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/LinkBuilderMethodFingerprint.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/LinkBuilderMethodFingerprint.kt index b03289c16b..4580f78936 100644 --- a/src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/LinkBuilderMethodFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/LinkBuilderMethodFingerprint.kt @@ -6,9 +6,5 @@ import com.android.tools.smali.dexlib2.Opcode // Returns a shareable link string based on a tweet ID and a username object LinkBuilderMethodFingerprint : MethodFingerprint( - accessFlags = AccessFlags.PUBLIC.value or AccessFlags.STATIC.value, - opcodes = listOf(Opcode.RETURN_OBJECT), - returnType = "Ljava/lang/String;", - parameters = listOf("J", "Ljava/lang/String;"), strings = listOf("/%1\$s/status/%2\$d"), ) \ No newline at end of file From 4fc592555485910cba9bd48cdfa3f0ae4df1948c Mon Sep 17 00:00:00 2001 From: Alex Uskov Date: Tue, 28 Nov 2023 13:21:35 +0400 Subject: [PATCH 13/26] Fix semantic stuff --- .../links/ChangeLinkSharingDomainPatch.kt | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt index 58b3474438..3dd0f07552 100644 --- a/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt +++ b/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt @@ -39,14 +39,14 @@ object ChangeLinkSharingDomainPatch : BytecodePatch( override fun execute(context: BytecodeContext) { // Replace the domain in the method that generates the share link - val linkBuilderMethod = LinkBuilderMethodFingerprint.result?.apply { - + // This is used in the copy link button to generate the link that is copied to the clipboard + val linkBuilderMethod = LinkBuilderMethodFingerprint.result?.let { // Find the index of the string instruction that contains the link - val stringIndex = scanResult.stringsScanResult!!.matches.find { match -> + val stringIndex = it.scanResult.stringsScanResult!!.matches.find { match -> (match.string == "https://twitter.com/%1\$s/status/%2\$d" || match.string == "https://x.com/%1\$s/status/%2\$d") }!!.index - val instruction = this.mutableMethod.getInstruction(stringIndex) + val instruction = it.mutableMethod.getInstruction(stringIndex) val overrideRegister = instruction.registerA val string = ((instruction as ReferenceInstruction).reference as StringReference).string @@ -61,14 +61,16 @@ object ChangeLinkSharingDomainPatch : BytecodePatch( } } - this.mutableMethod.replaceInstruction( + it.mutableMethod.replaceInstruction( stringIndex, - """ - const-string v$overrideRegister, "$overrideString" - """ + "const-string v$overrideRegister, \"$overrideString\"" ) + + it.method } ?: throw LinkBuilderMethodFingerprint.exception + // Replace instruction that gets the link template from resources with a call to our patched method. + // It is used in the Share via... dialog to show the link that will be shared. LinkResourceGetterFingerprint.result?.apply { val instructions = this.mutableMethod.getInstructions() @@ -107,9 +109,7 @@ object ChangeLinkSharingDomainPatch : BytecodePatch( val sourceRegister = (instructions[index + 1] as OneRegisterInstruction).registerA this.mutableMethod.addInstruction( index + 2, - """ - move-object v7, v$sourceRegister - """ + "move-object v7, v$sourceRegister" ) break } @@ -131,7 +131,7 @@ object ChangeLinkSharingDomainPatch : BytecodePatch( this.mutableMethod.addInstructions( index + 2, """ - invoke-static { v$sourceRegister, v$sourcePlusOne, v7 }, ${linkBuilderMethod.method} + invoke-static { v$sourceRegister, v$sourcePlusOne, v7 }, $linkBuilderMethod move-result-object v$resultRegister """ ) From 200641ba0810b63af08e2923daa677ac835e6bb9 Mon Sep 17 00:00:00 2001 From: Alex Uskov Date: Tue, 28 Nov 2023 14:51:57 +0400 Subject: [PATCH 14/26] Make the register dynamic --- .../links/ChangeLinkSharingDomainPatch.kt | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt index 3dd0f07552..6885df9f14 100644 --- a/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt +++ b/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt @@ -9,14 +9,17 @@ import app.revanced.patcher.extensions.InstructionExtensions.getInstructions import app.revanced.patcher.extensions.InstructionExtensions.removeInstructions import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction import app.revanced.patcher.patch.BytecodePatch +import app.revanced.patcher.patch.PatchException import app.revanced.patcher.patch.annotation.CompatiblePackage import app.revanced.patcher.patch.annotation.Patch import app.revanced.patcher.patch.options.types.StringPatchOption.Companion.stringPatchOption import app.revanced.patches.twitter.misc.links.fingerprints.LinkBuilderMethodFingerprint import app.revanced.patches.twitter.misc.links.fingerprints.LinkResourceGetterFingerprint import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.builder.BuilderInstruction import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction +import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction import com.android.tools.smali.dexlib2.iface.reference.MethodReference import com.android.tools.smali.dexlib2.iface.reference.StringReference @@ -97,7 +100,10 @@ object ChangeLinkSharingDomainPatch : BytecodePatch( } } - // Save user nickname to v7 + // Instruction that sets free register to "this", needed to restore the original value of the register + var instructionToGetThis: TwoRegisterInstruction? = null + + // Save user nickname to free register for ((index, instruction) in instructions.withIndex()) { if (instruction.opcode == Opcode.INVOKE_VIRTUAL) { @@ -106,15 +112,22 @@ object ChangeLinkSharingDomainPatch : BytecodePatch( if (methodRef.returnType != "Ljava/lang/String;") continue - val sourceRegister = (instructions[index + 1] as OneRegisterInstruction).registerA + // Get instruction that sets free register to "this" + instructionToGetThis = this.mutableMethod.getInstruction(index - 1) + + // Get the register for the username + val sourceRegister = this.mutableMethod.getInstruction(index + 1).registerA + this.mutableMethod.addInstruction( index + 2, - "move-object v7, v$sourceRegister" + "move-object v${instructionToGetThis.registerA}, v$sourceRegister" ) break } } + if (instructionToGetThis == null) throw PatchException("Instruction to get \"this\" not found") + // Call the patched method and save the result to resultRegister for ((index, instruction) in instructions.withIndex()) { if (instruction.opcode == Opcode.INVOKE_VIRTUAL) { @@ -131,10 +144,13 @@ object ChangeLinkSharingDomainPatch : BytecodePatch( this.mutableMethod.addInstructions( index + 2, """ - invoke-static { v$sourceRegister, v$sourcePlusOne, v7 }, $linkBuilderMethod + invoke-static { v$sourceRegister, v$sourcePlusOne, v${instructionToGetThis.registerA} }, $linkBuilderMethod move-result-object v$resultRegister """ ) + + // Restore the register that was used to store our string by duplicating the instruction that got "this" + this.mutableMethod.addInstruction(index+4, instructionToGetThis as BuilderInstruction) break } } From 97dfa846c28909c18cb92be6d5537a5e2538bf16 Mon Sep 17 00:00:00 2001 From: Alex Uskov Date: Tue, 28 Nov 2023 19:49:21 +0400 Subject: [PATCH 15/26] Fix building revanced --- .../twitter/misc/links/ChangeLinkSharingDomainPatch.kt | 2 +- .../misc/links/fingerprints/AddTelemetryToLinkFingerprint.kt | 4 +--- .../misc/links/fingerprints/LinkBuilderMethodFingerprint.kt | 4 +--- .../misc/links/fingerprints/LinkResourceGetterFingerprint.kt | 2 +- 4 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt index 6885df9f14..2c55d3f962 100644 --- a/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt +++ b/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt @@ -12,7 +12,7 @@ import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.PatchException import app.revanced.patcher.patch.annotation.CompatiblePackage import app.revanced.patcher.patch.annotation.Patch -import app.revanced.patcher.patch.options.types.StringPatchOption.Companion.stringPatchOption +import app.revanced.patcher.patch.options.PatchOption.PatchExtensions.stringPatchOption import app.revanced.patches.twitter.misc.links.fingerprints.LinkBuilderMethodFingerprint import app.revanced.patches.twitter.misc.links.fingerprints.LinkResourceGetterFingerprint import com.android.tools.smali.dexlib2.Opcode diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/AddTelemetryToLinkFingerprint.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/AddTelemetryToLinkFingerprint.kt index 7c249c0816..c4efd42f79 100644 --- a/src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/AddTelemetryToLinkFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/AddTelemetryToLinkFingerprint.kt @@ -1,8 +1,6 @@ package app.revanced.patches.twitter.misc.links.fingerprints -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import com.android.tools.smali.dexlib2.AccessFlags -import com.android.tools.smali.dexlib2.Opcode +import app.revanced.patcher.fingerprint.MethodFingerprint // Adds telemetry to the share links object AddTelemetryToLinkFingerprint : MethodFingerprint( diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/LinkBuilderMethodFingerprint.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/LinkBuilderMethodFingerprint.kt index 4580f78936..083d252ee8 100644 --- a/src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/LinkBuilderMethodFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/LinkBuilderMethodFingerprint.kt @@ -1,8 +1,6 @@ package app.revanced.patches.twitter.misc.links.fingerprints -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import com.android.tools.smali.dexlib2.AccessFlags -import com.android.tools.smali.dexlib2.Opcode +import app.revanced.patcher.fingerprint.MethodFingerprint // Returns a shareable link string based on a tweet ID and a username object LinkBuilderMethodFingerprint : MethodFingerprint( diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/LinkResourceGetterFingerprint.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/LinkResourceGetterFingerprint.kt index b4a62411b2..8610daf89f 100644 --- a/src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/LinkResourceGetterFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/LinkResourceGetterFingerprint.kt @@ -1,6 +1,6 @@ package app.revanced.patches.twitter.misc.links.fingerprints -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint +import app.revanced.patcher.fingerprint.MethodFingerprint import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.AccessFlags From 3ca6466afc5359cb92498b28dffe8375cd8e7fe9 Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Sat, 2 Dec 2023 00:38:05 +0100 Subject: [PATCH 16/26] refactor: Use better names --- .../misc/links/ChangeLinkSharingDomainPatch.kt | 2 +- ...tch.kt => RemoveTrackingQueryParameterPatch.kt} | 14 +++++++------- ...int.kt => AddTrackingQueryToLinkFingerprint.kt} | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) rename src/main/kotlin/app/revanced/patches/twitter/misc/links/{RemoveLinkTelemetryPatch.kt => RemoveTrackingQueryParameterPatch.kt} (60%) rename src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/{AddTelemetryToLinkFingerprint.kt => AddTrackingQueryToLinkFingerprint.kt} (78%) diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt index 2c55d3f962..b76d089b14 100644 --- a/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt +++ b/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt @@ -34,7 +34,7 @@ object ChangeLinkSharingDomainPatch : BytecodePatch( setOf(LinkBuilderMethodFingerprint, LinkResourceGetterFingerprint) ) { private var domain by stringPatchOption( - key = "domain", + key = "domainName", default = "fxtwitter.com", title = "Domain name", description = "The domain to use when sharing links.", diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/links/RemoveLinkTelemetryPatch.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/links/RemoveTrackingQueryParameterPatch.kt similarity index 60% rename from src/main/kotlin/app/revanced/patches/twitter/misc/links/RemoveLinkTelemetryPatch.kt rename to src/main/kotlin/app/revanced/patches/twitter/misc/links/RemoveTrackingQueryParameterPatch.kt index 154aef4d44..3747d0ec13 100644 --- a/src/main/kotlin/app/revanced/patches/twitter/misc/links/RemoveLinkTelemetryPatch.kt +++ b/src/main/kotlin/app/revanced/patches/twitter/misc/links/RemoveTrackingQueryParameterPatch.kt @@ -6,20 +6,20 @@ 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.twitter.misc.links.fingerprints.AddTelemetryToLinkFingerprint +import app.revanced.patches.twitter.misc.links.fingerprints.AddTrackingQueryToLinkFingerprint @Patch( - name = "Remove link telemetry", - description = "Removes telemetry at the end of the links", + name = "Remove tracking query parameter", + description = "Remove the tracking query parameter from links.", compatiblePackages = [CompatiblePackage("com.twitter.android")] ) @Suppress("unused") -object RemoveLinkTelemetryPatch : BytecodePatch( - setOf(AddTelemetryToLinkFingerprint) +object RemoveTrackingQueryParameterPatch : BytecodePatch( + setOf(AddTrackingQueryToLinkFingerprint) ) { override fun execute(context: BytecodeContext) { // Remove telemetry from links - AddTelemetryToLinkFingerprint.result?.mutableMethod?.addInstruction(0, "return-object p0") - ?: throw AddTelemetryToLinkFingerprint.exception + AddTrackingQueryToLinkFingerprint.result?.mutableMethod?.addInstruction(0, "return-object p0") + ?: throw AddTrackingQueryToLinkFingerprint.exception } } diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/AddTelemetryToLinkFingerprint.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/AddTrackingQueryToLinkFingerprint.kt similarity index 78% rename from src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/AddTelemetryToLinkFingerprint.kt rename to src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/AddTrackingQueryToLinkFingerprint.kt index c4efd42f79..a98a4448ac 100644 --- a/src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/AddTelemetryToLinkFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/AddTrackingQueryToLinkFingerprint.kt @@ -3,6 +3,6 @@ package app.revanced.patches.twitter.misc.links.fingerprints import app.revanced.patcher.fingerprint.MethodFingerprint // Adds telemetry to the share links -object AddTelemetryToLinkFingerprint : MethodFingerprint( +object AddTrackingQueryToLinkFingerprint : MethodFingerprint( strings = listOf("", "shareParam", "sessionToken"), ) \ No newline at end of file From 45f84dee82e0f91866b1af3ac7f094a819adf122 Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Sat, 2 Dec 2023 00:38:31 +0100 Subject: [PATCH 17/26] fix: Make option required --- .../patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt index b76d089b14..65c146f6d5 100644 --- a/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt +++ b/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt @@ -38,6 +38,7 @@ object ChangeLinkSharingDomainPatch : BytecodePatch( default = "fxtwitter.com", title = "Domain name", description = "The domain to use when sharing links.", + required = true ) override fun execute(context: BytecodeContext) { From d884f91d1bb1f1ca3f3901556e402961327179e9 Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Sat, 2 Dec 2023 00:40:00 +0100 Subject: [PATCH 18/26] style: Punctuate comments --- .../links/ChangeLinkSharingDomainPatch.kt | 32 +++++++++---------- .../RemoveTrackingQueryParameterPatch.kt | 1 - .../AddTrackingQueryToLinkFingerprint.kt | 1 - .../LinkBuilderMethodFingerprint.kt | 2 +- .../LinkResourceGetterFingerprint.kt | 2 +- 5 files changed, 18 insertions(+), 20 deletions(-) diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt index 65c146f6d5..f4cbec1c7b 100644 --- a/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt +++ b/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt @@ -42,10 +42,10 @@ object ChangeLinkSharingDomainPatch : BytecodePatch( ) override fun execute(context: BytecodeContext) { - // Replace the domain in the method that generates the share link - // This is used in the copy link button to generate the link that is copied to the clipboard + // Replace the domain in the method that generates the share link. + // This is used in the copy link button to generate the link that is copied to the clipboard. val linkBuilderMethod = LinkBuilderMethodFingerprint.result?.let { - // Find the index of the string instruction that contains the link + // Find the index of the string instruction that contains the link. val stringIndex = it.scanResult.stringsScanResult!!.matches.find { match -> (match.string == "https://twitter.com/%1\$s/status/%2\$d" || match.string == "https://x.com/%1\$s/status/%2\$d") }!!.index @@ -78,33 +78,33 @@ object ChangeLinkSharingDomainPatch : BytecodePatch( LinkResourceGetterFingerprint.result?.apply { val instructions = this.mutableMethod.getInstructions() - // Result register of the original method call + // Result register of the original method call. var resultRegister = 0 - // Remove instructions at the end and get the register of the last instruction + // Remove instructions at the end and get the register of the last instruction. for ((index, instruction) in instructions.withIndex()) { if (instruction.opcode == Opcode.INVOKE_VIRTUAL) { val methodRef = (instruction as ReferenceInstruction).reference as MethodReference if (methodRef.definingClass != "Landroid/content/res/Resources;") continue - // Get the result register of the original method call + // Get the result register of the original method call. resultRegister = (instructions[index + 1] as OneRegisterInstruction).registerA - // Remove the original method call for getting the link from resources and the move-result-object instruction + // Remove the original method call for getting the link from resources and the move-result-object instruction. this.mutableMethod.removeInstructions(index, 2) - // Remove the instruction that uses the resultRegister as an array reference to prevent an error + // Remove the instruction that uses the resultRegister as an array reference to prevent an error. this.mutableMethod.removeInstructions(index - 2, 1) break } } - // Instruction that sets free register to "this", needed to restore the original value of the register + // Instruction that sets free register to "this", needed to restore the original value of the register. var instructionToGetThis: TwoRegisterInstruction? = null - // Save user nickname to free register + // Save user nickname to free register. for ((index, instruction) in instructions.withIndex()) { if (instruction.opcode == Opcode.INVOKE_VIRTUAL) { @@ -113,10 +113,10 @@ object ChangeLinkSharingDomainPatch : BytecodePatch( if (methodRef.returnType != "Ljava/lang/String;") continue - // Get instruction that sets free register to "this" + // Get instruction that sets free register to "this". instructionToGetThis = this.mutableMethod.getInstruction(index - 1) - // Get the register for the username + // Get the register for the username. val sourceRegister = this.mutableMethod.getInstruction(index + 1).registerA this.mutableMethod.addInstruction( @@ -129,7 +129,7 @@ object ChangeLinkSharingDomainPatch : BytecodePatch( if (instructionToGetThis == null) throw PatchException("Instruction to get \"this\" not found") - // Call the patched method and save the result to resultRegister + // Call the patched method and save the result to resultRegister. for ((index, instruction) in instructions.withIndex()) { if (instruction.opcode == Opcode.INVOKE_VIRTUAL) { @@ -137,11 +137,11 @@ object ChangeLinkSharingDomainPatch : BytecodePatch( (instruction as ReferenceInstruction).reference as MethodReference if (methodRef.definingClass != "Ljava/lang/Long;") continue - // Get the registers for tweet ID number (64 bits) + // Get the registers for tweet ID number (64 bits). val sourceRegister = (instructions[index + 1] as OneRegisterInstruction).registerA val sourcePlusOne = sourceRegister + 1 - // Call the patched method with the tweet ID and username and save the result to resultRegister + // Call the patched method with the tweet ID and username and save the result to resultRegister. this.mutableMethod.addInstructions( index + 2, """ @@ -150,7 +150,7 @@ object ChangeLinkSharingDomainPatch : BytecodePatch( """ ) - // Restore the register that was used to store our string by duplicating the instruction that got "this" + // Restore the register that was used to store our string by duplicating the instruction that got "this". this.mutableMethod.addInstruction(index+4, instructionToGetThis as BuilderInstruction) break } diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/links/RemoveTrackingQueryParameterPatch.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/links/RemoveTrackingQueryParameterPatch.kt index 3747d0ec13..91af66a899 100644 --- a/src/main/kotlin/app/revanced/patches/twitter/misc/links/RemoveTrackingQueryParameterPatch.kt +++ b/src/main/kotlin/app/revanced/patches/twitter/misc/links/RemoveTrackingQueryParameterPatch.kt @@ -18,7 +18,6 @@ object RemoveTrackingQueryParameterPatch : BytecodePatch( setOf(AddTrackingQueryToLinkFingerprint) ) { override fun execute(context: BytecodeContext) { - // Remove telemetry from links AddTrackingQueryToLinkFingerprint.result?.mutableMethod?.addInstruction(0, "return-object p0") ?: throw AddTrackingQueryToLinkFingerprint.exception } diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/AddTrackingQueryToLinkFingerprint.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/AddTrackingQueryToLinkFingerprint.kt index a98a4448ac..b1704e1243 100644 --- a/src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/AddTrackingQueryToLinkFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/AddTrackingQueryToLinkFingerprint.kt @@ -2,7 +2,6 @@ package app.revanced.patches.twitter.misc.links.fingerprints import app.revanced.patcher.fingerprint.MethodFingerprint -// Adds telemetry to the share links object AddTrackingQueryToLinkFingerprint : MethodFingerprint( strings = listOf("", "shareParam", "sessionToken"), ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/LinkBuilderMethodFingerprint.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/LinkBuilderMethodFingerprint.kt index 083d252ee8..4572804b73 100644 --- a/src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/LinkBuilderMethodFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/LinkBuilderMethodFingerprint.kt @@ -2,7 +2,7 @@ package app.revanced.patches.twitter.misc.links.fingerprints import app.revanced.patcher.fingerprint.MethodFingerprint -// Returns a shareable link string based on a tweet ID and a username +// Returns a shareable link string based on a tweet ID and a username. object LinkBuilderMethodFingerprint : MethodFingerprint( strings = listOf("/%1\$s/status/%2\$d"), ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/LinkResourceGetterFingerprint.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/LinkResourceGetterFingerprint.kt index 8610daf89f..77c0e066d5 100644 --- a/src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/LinkResourceGetterFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/LinkResourceGetterFingerprint.kt @@ -4,7 +4,7 @@ import app.revanced.patcher.fingerprint.MethodFingerprint import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.AccessFlags -// Gets Resource string for share link view available by pressing "Share via" button +// Gets Resource string for share link view available by pressing "Share via" button. object LinkResourceGetterFingerprint : MethodFingerprint( accessFlags = AccessFlags.PUBLIC.value or AccessFlags.FINAL.value, opcodes = listOf( From c48b22d91e30d8f1e69ceec7107c78e700f9d3b2 Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Sat, 2 Dec 2023 00:55:33 +0100 Subject: [PATCH 19/26] refactor: Simplify code --- .../links/ChangeLinkSharingDomainPatch.kt | 77 +++++++------------ ...ngerprint.kt => LinkBuilderFingerprint.kt} | 2 +- .../LinkResourceGetterFingerprint.kt | 5 +- 3 files changed, 32 insertions(+), 52 deletions(-) rename src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/{LinkBuilderMethodFingerprint.kt => LinkBuilderFingerprint.kt} (80%) diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt index f4cbec1c7b..250db0d54b 100644 --- a/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt +++ b/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt @@ -13,7 +13,7 @@ import app.revanced.patcher.patch.PatchException import app.revanced.patcher.patch.annotation.CompatiblePackage import app.revanced.patcher.patch.annotation.Patch import app.revanced.patcher.patch.options.PatchOption.PatchExtensions.stringPatchOption -import app.revanced.patches.twitter.misc.links.fingerprints.LinkBuilderMethodFingerprint +import app.revanced.patches.twitter.misc.links.fingerprints.LinkBuilderFingerprint import app.revanced.patches.twitter.misc.links.fingerprints.LinkResourceGetterFingerprint import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.builder.BuilderInstruction @@ -21,7 +21,6 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction import com.android.tools.smali.dexlib2.iface.reference.MethodReference -import com.android.tools.smali.dexlib2.iface.reference.StringReference @Patch( @@ -31,9 +30,9 @@ import com.android.tools.smali.dexlib2.iface.reference.StringReference ) @Suppress("unused") object ChangeLinkSharingDomainPatch : BytecodePatch( - setOf(LinkBuilderMethodFingerprint, LinkResourceGetterFingerprint) + setOf(LinkBuilderFingerprint, LinkResourceGetterFingerprint) ) { - private var domain by stringPatchOption( + private var domainName by stringPatchOption( key = "domainName", default = "fxtwitter.com", title = "Domain name", @@ -42,41 +41,26 @@ object ChangeLinkSharingDomainPatch : BytecodePatch( ) override fun execute(context: BytecodeContext) { - // Replace the domain in the method that generates the share link. - // This is used in the copy link button to generate the link that is copied to the clipboard. - val linkBuilderMethod = LinkBuilderMethodFingerprint.result?.let { - // Find the index of the string instruction that contains the link. - val stringIndex = it.scanResult.stringsScanResult!!.matches.find { match -> - (match.string == "https://twitter.com/%1\$s/status/%2\$d" || match.string == "https://x.com/%1\$s/status/%2\$d") - }!!.index - - val instruction = it.mutableMethod.getInstruction(stringIndex) - val overrideRegister = instruction.registerA - val string = ((instruction as ReferenceInstruction).reference as StringReference).string - - var overrideString = string - when { - string.contains("twitter.com") -> { - overrideString = string.replace("twitter.com", domain.toString()) - } + val linkBuilderResult = LinkBuilderFingerprint.result ?: throw LinkBuilderFingerprint.exception - string.contains("x.com") -> { - overrideString = string.replace("x.com", domain.toString()) - } - } + // region Copy link button. + linkBuilderResult.mutableMethod.apply { + val stringIndex = linkBuilderResult.scanResult.stringsScanResult!!.matches + .first().index - it.mutableMethod.replaceInstruction( + val targetRegister = getInstruction(stringIndex).registerA + replaceInstruction( stringIndex, - "const-string v$overrideRegister, \"$overrideString\"" + "const-string v$targetRegister, \"https://$domainName/%1\$s/status/%2\$d\"" ) + } - it.method - } ?: throw LinkBuilderMethodFingerprint.exception - // Replace instruction that gets the link template from resources with a call to our patched method. - // It is used in the Share via... dialog to show the link that will be shared. + // endregion + + // Used in the Share via... dialog. LinkResourceGetterFingerprint.result?.apply { - val instructions = this.mutableMethod.getInstructions() + val instructions = mutableMethod.getInstructions() // Result register of the original method call. var resultRegister = 0 @@ -91,11 +75,13 @@ object ChangeLinkSharingDomainPatch : BytecodePatch( // Get the result register of the original method call. resultRegister = (instructions[index + 1] as OneRegisterInstruction).registerA - // Remove the original method call for getting the link from resources and the move-result-object instruction. - this.mutableMethod.removeInstructions(index, 2) + mutableMethod.apply { + // Remove the original method call for getting the link from resources and the move-result-object instruction. + removeInstructions(index, 2) - // Remove the instruction that uses the resultRegister as an array reference to prevent an error. - this.mutableMethod.removeInstructions(index - 2, 1) + // Remove the instruction that uses the resultRegister as an array reference to prevent an error. + removeInstructions(index - 2, 1) + } break } @@ -107,21 +93,14 @@ object ChangeLinkSharingDomainPatch : BytecodePatch( // Save user nickname to free register. for ((index, instruction) in instructions.withIndex()) { if (instruction.opcode == Opcode.INVOKE_VIRTUAL) { - - val methodRef = - (instruction as ReferenceInstruction).reference as MethodReference - - if (methodRef.returnType != "Ljava/lang/String;") continue + val methodReference = (instruction as ReferenceInstruction).reference.toString() + if (!methodReference.endsWith("Ljava/lang/String;")) continue // Get instruction that sets free register to "this". - instructionToGetThis = this.mutableMethod.getInstruction(index - 1) - - // Get the register for the username. - val sourceRegister = this.mutableMethod.getInstruction(index + 1).registerA - - this.mutableMethod.addInstruction( + instructionToGetThis = mutableMethod.getInstruction(index - 1) + mutableMethod.addInstruction( index + 2, - "move-object v${instructionToGetThis.registerA}, v$sourceRegister" + "move-object v${instructionToGetThis.registerA}, v${instructionToGetThis.registerA}" ) break } @@ -145,7 +124,7 @@ object ChangeLinkSharingDomainPatch : BytecodePatch( this.mutableMethod.addInstructions( index + 2, """ - invoke-static { v$sourceRegister, v$sourcePlusOne, v${instructionToGetThis.registerA} }, $linkBuilderMethod + invoke-static { v$sourceRegister, v$sourcePlusOne, v${instructionToGetThis.registerA} }, ${linkBuilderResult.method} move-result-object v$resultRegister """ ) diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/LinkBuilderMethodFingerprint.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/LinkBuilderFingerprint.kt similarity index 80% rename from src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/LinkBuilderMethodFingerprint.kt rename to src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/LinkBuilderFingerprint.kt index 4572804b73..5c9d2581c1 100644 --- a/src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/LinkBuilderMethodFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/LinkBuilderFingerprint.kt @@ -3,6 +3,6 @@ package app.revanced.patches.twitter.misc.links.fingerprints import app.revanced.patcher.fingerprint.MethodFingerprint // Returns a shareable link string based on a tweet ID and a username. -object LinkBuilderMethodFingerprint : MethodFingerprint( +object LinkBuilderFingerprint : MethodFingerprint( strings = listOf("/%1\$s/status/%2\$d"), ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/LinkResourceGetterFingerprint.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/LinkResourceGetterFingerprint.kt index 77c0e066d5..67bccf0bd5 100644 --- a/src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/LinkResourceGetterFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/twitter/misc/links/fingerprints/LinkResourceGetterFingerprint.kt @@ -1,12 +1,13 @@ package app.revanced.patches.twitter.misc.links.fingerprints +import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint -import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.Opcode // Gets Resource string for share link view available by pressing "Share via" button. object LinkResourceGetterFingerprint : MethodFingerprint( - accessFlags = AccessFlags.PUBLIC.value or AccessFlags.FINAL.value, + accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, opcodes = listOf( Opcode.CONST_STRING, Opcode.INVOKE_STATIC, From 6f313c131db0e2a1430b65f40912324a7461366b Mon Sep 17 00:00:00 2001 From: Alex Uskov Date: Sat, 2 Dec 2023 21:00:51 +0400 Subject: [PATCH 20/26] Fix the typo, improve code readability attempt #1 --- .../links/ChangeLinkSharingDomainPatch.kt | 111 +++++++++--------- 1 file changed, 56 insertions(+), 55 deletions(-) diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt index 250db0d54b..5f9c9351ac 100644 --- a/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt +++ b/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt @@ -44,7 +44,7 @@ object ChangeLinkSharingDomainPatch : BytecodePatch( val linkBuilderResult = LinkBuilderFingerprint.result ?: throw LinkBuilderFingerprint.exception // region Copy link button. - linkBuilderResult.mutableMethod.apply { + val buildShareLinkMethod = linkBuilderResult.mutableMethod.apply { val stringIndex = linkBuilderResult.scanResult.stringsScanResult!!.matches .first().index @@ -63,76 +63,77 @@ object ChangeLinkSharingDomainPatch : BytecodePatch( val instructions = mutableMethod.getInstructions() // Result register of the original method call. - var resultRegister = 0 + var shareLinkRegister = 0 - // Remove instructions at the end and get the register of the last instruction. + // Remove the original call to the method that uses the resources template to build the link. for ((index, instruction) in instructions.withIndex()) { - if (instruction.opcode == Opcode.INVOKE_VIRTUAL) { - val methodRef = - (instruction as ReferenceInstruction).reference as MethodReference - if (methodRef.definingClass != "Landroid/content/res/Resources;") continue + if (instruction.opcode != Opcode.INVOKE_VIRTUAL) continue - // Get the result register of the original method call. - resultRegister = (instructions[index + 1] as OneRegisterInstruction).registerA + val methodRef = + (instruction as ReferenceInstruction).reference as MethodReference + if (methodRef.definingClass != "Landroid/content/res/Resources;") continue - mutableMethod.apply { - // Remove the original method call for getting the link from resources and the move-result-object instruction. - removeInstructions(index, 2) + shareLinkRegister = (instructions[index + 1] as OneRegisterInstruction).registerA - // Remove the instruction that uses the resultRegister as an array reference to prevent an error. - removeInstructions(index - 2, 1) - } + mutableMethod.apply { + removeInstructions(index, 2) - break + // Remove the instruction that uses the resultRegister as an array reference to prevent an error. + removeInstructions(index - 2, 1) } + break } - // Instruction that sets free register to "this", needed to restore the original value of the register. - var instructionToGetThis: TwoRegisterInstruction? = null - // Save user nickname to free register. + var tempInstruction: TwoRegisterInstruction? = null + var nicknameRegister = -1 + + // Get the nickname of the user that posted the tweet. This is used to build the link. for ((index, instruction) in instructions.withIndex()) { - if (instruction.opcode == Opcode.INVOKE_VIRTUAL) { - val methodReference = (instruction as ReferenceInstruction).reference.toString() - if (!methodReference.endsWith("Ljava/lang/String;")) continue - - // Get instruction that sets free register to "this". - instructionToGetThis = mutableMethod.getInstruction(index - 1) - mutableMethod.addInstruction( - index + 2, - "move-object v${instructionToGetThis.registerA}, v${instructionToGetThis.registerA}" - ) - break - } + if (instruction.opcode != Opcode.INVOKE_VIRTUAL) continue + val methodReference = (instruction as ReferenceInstruction).reference.toString() + if (!methodReference.endsWith("Ljava/lang/String;")) continue + + val sourceNicknameRegister = + this.mutableMethod.getInstruction(index + 1).registerA + + tempInstruction = mutableMethod.getInstruction(index - 1) + nicknameRegister = tempInstruction.registerA + + // Save the user nickname to the register that was used to store "this". + mutableMethod.addInstruction( + index + 2, + "move-object v${nicknameRegister}, v$sourceNicknameRegister" + ) + break + } + if (tempInstruction == null) throw PatchException("Save user nickname to free register failed.") - if (instructionToGetThis == null) throw PatchException("Instruction to get \"this\" not found") // Call the patched method and save the result to resultRegister. for ((index, instruction) in instructions.withIndex()) { - if (instruction.opcode == Opcode.INVOKE_VIRTUAL) { - - val methodRef = - (instruction as ReferenceInstruction).reference as MethodReference - if (methodRef.definingClass != "Ljava/lang/Long;") continue - - // Get the registers for tweet ID number (64 bits). - val sourceRegister = (instructions[index + 1] as OneRegisterInstruction).registerA - val sourcePlusOne = sourceRegister + 1 - - // Call the patched method with the tweet ID and username and save the result to resultRegister. - this.mutableMethod.addInstructions( - index + 2, - """ - invoke-static { v$sourceRegister, v$sourcePlusOne, v${instructionToGetThis.registerA} }, ${linkBuilderResult.method} - move-result-object v$resultRegister - """ - ) - - // Restore the register that was used to store our string by duplicating the instruction that got "this". - this.mutableMethod.addInstruction(index+4, instructionToGetThis as BuilderInstruction) - break - } + if (instruction.opcode != Opcode.INVOKE_VIRTUAL) continue + val methodRef = + (instruction as ReferenceInstruction).reference as MethodReference + if (methodRef.definingClass != "Ljava/lang/Long;") continue + + // Get tweet id (long) + val tweetIdP1 = (instructions[index + 1] as OneRegisterInstruction).registerA + val tweetIdP2 = tweetIdP1 + 1 + + // Call the patched method with the tweet ID and username and save the result to resultRegister. + this.mutableMethod.addInstructions( + index + 2, + """ + invoke-static { v$tweetIdP1, v$tweetIdP2, v$nicknameRegister }, $buildShareLinkMethod + move-result-object v$shareLinkRegister + """ + ) + + // Restore the register that was used to store our string by duplicating the instruction that got "this". + this.mutableMethod.addInstruction(index + 4, tempInstruction as BuilderInstruction) + break } } ?: throw LinkResourceGetterFingerprint.exception From 6d3409a50e1dd6598076ab80f8e409bfc614deb2 Mon Sep 17 00:00:00 2001 From: Alex Uskov Date: Sat, 2 Dec 2023 21:46:56 +0400 Subject: [PATCH 21/26] Remove for loops, remove useless variables --- .../links/ChangeLinkSharingDomainPatch.kt | 109 ++++++++---------- 1 file changed, 47 insertions(+), 62 deletions(-) diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt index 5f9c9351ac..6b91198923 100644 --- a/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt +++ b/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt @@ -1,11 +1,12 @@ package app.revanced.patches.twitter.misc.links import app.revanced.extensions.exception +import app.revanced.extensions.getReference +import app.revanced.extensions.indexOfFirstInstruction import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.extensions.InstructionExtensions.addInstruction 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.extensions.InstructionExtensions.removeInstructions import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction import app.revanced.patcher.patch.BytecodePatch @@ -18,7 +19,6 @@ import app.revanced.patches.twitter.misc.links.fingerprints.LinkResourceGetterFi import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.builder.BuilderInstruction import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction -import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction import com.android.tools.smali.dexlib2.iface.reference.MethodReference @@ -60,82 +60,67 @@ object ChangeLinkSharingDomainPatch : BytecodePatch( // Used in the Share via... dialog. LinkResourceGetterFingerprint.result?.apply { - val instructions = mutableMethod.getInstructions() - - // Result register of the original method call. - var shareLinkRegister = 0 - // Remove the original call to the method that uses the resources template to build the link. - for ((index, instruction) in instructions.withIndex()) { - if (instruction.opcode != Opcode.INVOKE_VIRTUAL) continue - - val methodRef = - (instruction as ReferenceInstruction).reference as MethodReference - if (methodRef.definingClass != "Landroid/content/res/Resources;") continue + val originalMethodIndex = mutableMethod.indexOfFirstInstruction { + opcode == Opcode.INVOKE_VIRTUAL && + getReference()?.definingClass == "Landroid/content/res/Resources;" + } + if (originalMethodIndex == -1) throw PatchException("Could not find originalMethodIndex") - shareLinkRegister = (instructions[index + 1] as OneRegisterInstruction).registerA + val shareLinkRegister = + mutableMethod.getInstruction(originalMethodIndex + 1).registerA - mutableMethod.apply { - removeInstructions(index, 2) + mutableMethod.apply { + removeInstructions(originalMethodIndex, 2) - // Remove the instruction that uses the resultRegister as an array reference to prevent an error. - removeInstructions(index - 2, 1) - } - break + // Remove the instruction that uses the resultRegister as an array reference to prevent an error. + removeInstructions(originalMethodIndex - 2, 1) } - var tempInstruction: TwoRegisterInstruction? = null - var nicknameRegister = -1 - // Get the nickname of the user that posted the tweet. This is used to build the link. - for ((index, instruction) in instructions.withIndex()) { - if (instruction.opcode != Opcode.INVOKE_VIRTUAL) continue - val methodReference = (instruction as ReferenceInstruction).reference.toString() - if (!methodReference.endsWith("Ljava/lang/String;")) continue - - val sourceNicknameRegister = - this.mutableMethod.getInstruction(index + 1).registerA + val getNicknameIndex = mutableMethod.indexOfFirstInstruction { + opcode == Opcode.INVOKE_VIRTUAL && + getReference().toString().endsWith("Ljava/lang/String;") + } + if (getNicknameIndex == -1) throw PatchException("Could not find getNicknameIndex") - tempInstruction = mutableMethod.getInstruction(index - 1) - nicknameRegister = tempInstruction.registerA + val sourceNicknameRegister = + this.mutableMethod.getInstruction(getNicknameIndex + 1).registerA - // Save the user nickname to the register that was used to store "this". - mutableMethod.addInstruction( - index + 2, - "move-object v${nicknameRegister}, v$sourceNicknameRegister" - ) - break + val tempInstruction = mutableMethod.getInstruction(getNicknameIndex - 1) + val nicknameRegister = tempInstruction.registerA - } - if (tempInstruction == null) throw PatchException("Save user nickname to free register failed.") + // Save the user nickname to the register that was used to store "this". + mutableMethod.addInstruction( + getNicknameIndex + 2, + "move-object v${nicknameRegister}, v$sourceNicknameRegister" + ) // Call the patched method and save the result to resultRegister. - for ((index, instruction) in instructions.withIndex()) { - if (instruction.opcode != Opcode.INVOKE_VIRTUAL) continue - val methodRef = - (instruction as ReferenceInstruction).reference as MethodReference - if (methodRef.definingClass != "Ljava/lang/Long;") continue - - // Get tweet id (long) - val tweetIdP1 = (instructions[index + 1] as OneRegisterInstruction).registerA - val tweetIdP2 = tweetIdP1 + 1 - - // Call the patched method with the tweet ID and username and save the result to resultRegister. - this.mutableMethod.addInstructions( - index + 2, - """ - invoke-static { v$tweetIdP1, v$tweetIdP2, v$nicknameRegister }, $buildShareLinkMethod - move-result-object v$shareLinkRegister - """ - ) - - // Restore the register that was used to store our string by duplicating the instruction that got "this". - this.mutableMethod.addInstruction(index + 4, tempInstruction as BuilderInstruction) - break + val convertTweetIdToLongIndex = mutableMethod.indexOfFirstInstruction { + opcode == Opcode.INVOKE_VIRTUAL && + getReference()?.definingClass == "Ljava/lang/Long;" } + if (convertTweetIdToLongIndex == -1) throw PatchException("Could not find convertTweetIdToLongIndex") + + // Get tweet id (long) + val tweetIdP1 = + mutableMethod.getInstruction(convertTweetIdToLongIndex + 1).registerA + val tweetIdP2 = tweetIdP1 + 1 + + // Call the patched method with the tweet ID and username and save the result to shareLinkRegister. + this.mutableMethod.addInstructions( + convertTweetIdToLongIndex + 2, + """ + invoke-static { v$tweetIdP1, v$tweetIdP2, v$nicknameRegister }, $buildShareLinkMethod + move-result-object v$shareLinkRegister + """ + ) + // Restore the register that was used to store our string by duplicating the instruction that got "this". + this.mutableMethod.addInstruction(convertTweetIdToLongIndex + 4, tempInstruction as BuilderInstruction) } ?: throw LinkResourceGetterFingerprint.exception } } From 6e084b394240120b8f6d833adaa9858e9e929137 Mon Sep 17 00:00:00 2001 From: Alex Uskov Date: Sat, 2 Dec 2023 22:02:39 +0400 Subject: [PATCH 22/26] Remove useless comments, mark regions --- .../twitter/misc/links/ChangeLinkSharingDomainPatch.kt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt index 6b91198923..bce871897f 100644 --- a/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt +++ b/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt @@ -78,7 +78,7 @@ object ChangeLinkSharingDomainPatch : BytecodePatch( } - // Get the nickname of the user that posted the tweet. This is used to build the link. + // region Get the nickname of the user that posted the tweet. This is used to build the link. val getNicknameIndex = mutableMethod.indexOfFirstInstruction { opcode == Opcode.INVOKE_VIRTUAL && getReference().toString().endsWith("Ljava/lang/String;") @@ -96,21 +96,20 @@ object ChangeLinkSharingDomainPatch : BytecodePatch( getNicknameIndex + 2, "move-object v${nicknameRegister}, v$sourceNicknameRegister" ) + // endregion - // Call the patched method and save the result to resultRegister. + // region Call the patched method and save the result to resultRegister. val convertTweetIdToLongIndex = mutableMethod.indexOfFirstInstruction { opcode == Opcode.INVOKE_VIRTUAL && getReference()?.definingClass == "Ljava/lang/Long;" } if (convertTweetIdToLongIndex == -1) throw PatchException("Could not find convertTweetIdToLongIndex") - // Get tweet id (long) val tweetIdP1 = mutableMethod.getInstruction(convertTweetIdToLongIndex + 1).registerA val tweetIdP2 = tweetIdP1 + 1 - // Call the patched method with the tweet ID and username and save the result to shareLinkRegister. this.mutableMethod.addInstructions( convertTweetIdToLongIndex + 2, """ @@ -119,8 +118,9 @@ object ChangeLinkSharingDomainPatch : BytecodePatch( """ ) - // Restore the register that was used to store our string by duplicating the instruction that got "this". + // Restore the borrowed nicknameRegister. this.mutableMethod.addInstruction(convertTweetIdToLongIndex + 4, tempInstruction as BuilderInstruction) + // endregion } ?: throw LinkResourceGetterFingerprint.exception } } From c1ffa29dd2e4b4e1d2f7dfada270213885565166 Mon Sep 17 00:00:00 2001 From: Alex Uskov Date: Sat, 2 Dec 2023 22:04:54 +0400 Subject: [PATCH 23/26] Rename stuff --- .../twitter/misc/links/ChangeLinkSharingDomainPatch.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt index bce871897f..47acfc9dd5 100644 --- a/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt +++ b/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt @@ -73,7 +73,7 @@ object ChangeLinkSharingDomainPatch : BytecodePatch( mutableMethod.apply { removeInstructions(originalMethodIndex, 2) - // Remove the instruction that uses the resultRegister as an array reference to prevent an error. + // Remove the instruction that uses the shareLinkRegister as an array reference to prevent an error. removeInstructions(originalMethodIndex - 2, 1) } @@ -99,7 +99,7 @@ object ChangeLinkSharingDomainPatch : BytecodePatch( // endregion - // region Call the patched method and save the result to resultRegister. + // region Call the patched method and save the result to shareLinkRegister. val convertTweetIdToLongIndex = mutableMethod.indexOfFirstInstruction { opcode == Opcode.INVOKE_VIRTUAL && getReference()?.definingClass == "Ljava/lang/Long;" From 3084500d93f440becd89373704f6d5d24723ee61 Mon Sep 17 00:00:00 2001 From: Alex Uskov Date: Wed, 6 Dec 2023 12:56:26 +0400 Subject: [PATCH 24/26] Make code even more readable --- .../links/ChangeLinkSharingDomainPatch.kt | 40 +++++++++++++++---- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt index 47acfc9dd5..ef74c19e21 100644 --- a/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt +++ b/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt @@ -62,37 +62,56 @@ object ChangeLinkSharingDomainPatch : BytecodePatch( LinkResourceGetterFingerprint.result?.apply { // Remove the original call to the method that uses the resources template to build the link. val originalMethodIndex = mutableMethod.indexOfFirstInstruction { - opcode == Opcode.INVOKE_VIRTUAL && - getReference()?.definingClass == "Landroid/content/res/Resources;" + getReference()?.definingClass == "Landroid/content/res/Resources;" } if (originalMethodIndex == -1) throw PatchException("Could not find originalMethodIndex") val shareLinkRegister = - mutableMethod.getInstruction(originalMethodIndex + 1).registerA + mutableMethod.getInstruction( + // Offset to instruction that saves the result of the method call to the register. + originalMethodIndex + 1 + ).registerA mutableMethod.apply { + // Remove original method call and instruction to move the result to the shareLinkRegister. removeInstructions(originalMethodIndex, 2) // Remove the instruction that uses the shareLinkRegister as an array reference to prevent an error. + // Original smali aput-object v3, v1, v5 (v1 is the shareLinkRegister) removeInstructions(originalMethodIndex - 2, 1) } // region Get the nickname of the user that posted the tweet. This is used to build the link. val getNicknameIndex = mutableMethod.indexOfFirstInstruction { - opcode == Opcode.INVOKE_VIRTUAL && - getReference().toString().endsWith("Ljava/lang/String;") + getReference().toString().endsWith("Ljava/lang/String;") } if (getNicknameIndex == -1) throw PatchException("Could not find getNicknameIndex") val sourceNicknameRegister = - this.mutableMethod.getInstruction(getNicknameIndex + 1).registerA + this.mutableMethod.getInstruction( + // Offset to instruction that saves the result of the method call to the register. + getNicknameIndex + 1 + ).registerA + + // Instruction with a spare register that can be used to store the user nickname. + val tempInstructionIndex = mutableMethod.indexOfFirstInstruction { + opcode == Opcode.IGET_OBJECT + } + if (tempInstructionIndex == -1) throw PatchException("Could not find tempInstructionIndex") + if (tempInstructionIndex > getNicknameIndex) throw PatchException( + "tempInstructionIndex > getNicknameIndex, this indicates that the instruction was moved." + ) - val tempInstruction = mutableMethod.getInstruction(getNicknameIndex - 1) + val tempInstruction = mutableMethod.getInstruction( + // Smali: move-result-object v3 (v3 is the shareLinkRegister) + tempInstructionIndex + ) val nicknameRegister = tempInstruction.registerA // Save the user nickname to the register that was used to store "this". mutableMethod.addInstruction( + // This offset is used to place the instruction after sourceNicknameRegister is filled with data. getNicknameIndex + 2, "move-object v${nicknameRegister}, v$sourceNicknameRegister" ) @@ -111,6 +130,7 @@ object ChangeLinkSharingDomainPatch : BytecodePatch( val tweetIdP2 = tweetIdP1 + 1 this.mutableMethod.addInstructions( + // This offset is used to place the instruction after the save of the method result. convertTweetIdToLongIndex + 2, """ invoke-static { v$tweetIdP1, v$tweetIdP2, v$nicknameRegister }, $buildShareLinkMethod @@ -119,7 +139,11 @@ object ChangeLinkSharingDomainPatch : BytecodePatch( ) // Restore the borrowed nicknameRegister. - this.mutableMethod.addInstruction(convertTweetIdToLongIndex + 4, tempInstruction as BuilderInstruction) + this.mutableMethod.addInstruction( + // This offset places after the instructions that were in the previous addInstructions call. + convertTweetIdToLongIndex + 4, + tempInstruction as BuilderInstruction + ) // endregion } ?: throw LinkResourceGetterFingerprint.exception } From 457733c559d1a6548f0ae351d1dd5b2192d5d60f Mon Sep 17 00:00:00 2001 From: Alex Uskov Date: Wed, 6 Dec 2023 13:01:37 +0400 Subject: [PATCH 25/26] Remove invalid comment --- .../patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt index ef74c19e21..c4ce7dbc7f 100644 --- a/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt +++ b/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt @@ -104,7 +104,6 @@ object ChangeLinkSharingDomainPatch : BytecodePatch( ) val tempInstruction = mutableMethod.getInstruction( - // Smali: move-result-object v3 (v3 is the shareLinkRegister) tempInstructionIndex ) val nicknameRegister = tempInstruction.registerA From c8c976cde793af7d8ff9efaea95cda09f59813ea Mon Sep 17 00:00:00 2001 From: Alex Uskov Date: Wed, 6 Dec 2023 13:03:52 +0400 Subject: [PATCH 26/26] Remove comment --- .../patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt index c4ce7dbc7f..e86d2d04bd 100644 --- a/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt +++ b/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt @@ -139,7 +139,6 @@ object ChangeLinkSharingDomainPatch : BytecodePatch( // Restore the borrowed nicknameRegister. this.mutableMethod.addInstruction( - // This offset places after the instructions that were in the previous addInstructions call. convertTweetIdToLongIndex + 4, tempInstruction as BuilderInstruction )