Skip to content

Commit

Permalink
fix(3rd-party Reddit apps): Spoof user agent to work around Reddit AP…
Browse files Browse the repository at this point in the history
…I issues (#3253)

Co-authored-by: oSumAtrIX <[email protected]>
  • Loading branch information
OctoNezd and oSumAtrIX authored May 30, 2024
1 parent d8415c0 commit 495e6d6
Show file tree
Hide file tree
Showing 10 changed files with 93 additions and 35 deletions.
7 changes: 7 additions & 0 deletions api/revanced-patches.api
Original file line number Diff line number Diff line change
Expand Up @@ -555,6 +555,7 @@ public final class app/revanced/patches/reddit/customclients/baconreader/api/Spo
public final class app/revanced/patches/reddit/customclients/boostforreddit/api/SpoofClientPatch : app/revanced/patches/reddit/customclients/BaseSpoofClientPatch {
public static final field INSTANCE Lapp/revanced/patches/reddit/customclients/boostforreddit/api/SpoofClientPatch;
public fun patchClientId (Ljava/util/Set;Lapp/revanced/patcher/data/BytecodeContext;)V
public fun patchUserAgent (Ljava/util/Set;Lapp/revanced/patcher/data/BytecodeContext;)V
}

public final class app/revanced/patches/reddit/customclients/infinityforreddit/api/SpoofClientPatch : app/revanced/patches/reddit/customclients/BaseSpoofClientPatch {
Expand All @@ -577,6 +578,11 @@ public final class app/revanced/patches/reddit/customclients/joeyforreddit/ads/D
public final class app/revanced/patches/reddit/customclients/joeyforreddit/api/SpoofClientPatch : app/revanced/patches/reddit/customclients/BaseSpoofClientPatch {
public static final field INSTANCE Lapp/revanced/patches/reddit/customclients/joeyforreddit/api/SpoofClientPatch;
public fun patchClientId (Ljava/util/Set;Lapp/revanced/patcher/data/BytecodeContext;)V
public fun patchUserAgent (Ljava/util/Set;Lapp/revanced/patcher/data/BytecodeContext;)V
}

public final class app/revanced/patches/reddit/customclients/joeyforreddit/api/fingerprints/AuthUtilityUserAgent : app/revanced/patcher/fingerprint/MethodFingerprint {
public static final field INSTANCE Lapp/revanced/patches/reddit/customclients/joeyforreddit/api/fingerprints/AuthUtilityUserAgent;
}

public final class app/revanced/patches/reddit/customclients/joeyforreddit/detection/piracy/DisablePiracyDetectionPatch : app/revanced/patcher/patch/BytecodePatch {
Expand Down Expand Up @@ -621,6 +627,7 @@ public final class app/revanced/patches/reddit/customclients/syncforreddit/api/S
public static final field INSTANCE Lapp/revanced/patches/reddit/customclients/syncforreddit/api/SpoofClientPatch;
public fun patchClientId (Ljava/util/Set;Lapp/revanced/patcher/data/BytecodeContext;)V
public fun patchMiscellaneous (Ljava/util/Set;Lapp/revanced/patcher/data/BytecodeContext;)V
public fun patchUserAgent (Ljava/util/Set;Lapp/revanced/patcher/data/BytecodeContext;)V
}

public final class app/revanced/patches/reddit/customclients/syncforreddit/detection/piracy/DisablePiracyDetectionPatch : app/revanced/patcher/patch/BytecodePatch {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,32 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.fingerprint.MethodFingerprintResult
import app.revanced.patches.reddit.customclients.BaseSpoofClientPatch
import app.revanced.patches.reddit.customclients.boostforreddit.api.fingerprints.GetClientIdFingerprint
import app.revanced.patches.reddit.customclients.boostforreddit.api.fingerprints.LoginActivityOnCreateFingerprint

import app.revanced.patches.reddit.customclients.boostforreddit.api.fingerprints.JRAWUserAgent

@Suppress("unused")
object SpoofClientPatch : BaseSpoofClientPatch(
redirectUri = "http://rubenmayayo.com",
clientIdFingerprints = setOf(GetClientIdFingerprint),
userAgentFingerprints = setOf(LoginActivityOnCreateFingerprint),
compatiblePackages = setOf(CompatiblePackage("com.rubenmayayo.reddit"))
userAgentFingerprints = setOf(JRAWUserAgent),
compatiblePackages = setOf(CompatiblePackage("com.rubenmayayo.reddit")),
) {
override fun Set<MethodFingerprintResult>.patchClientId(context: BytecodeContext) {
first().mutableMethod.addInstructions(
0,
"""
const-string v0, "$clientId"
return-object v0
"""
""",
)
}

override fun Set<MethodFingerprintResult>.patchUserAgent(context: BytecodeContext) {
// Use a random user agent.
val randomName = (0..100000).random()

first().mutableMethod.addInstructions(
1,
"const-string v3, \"$randomName\"",
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package app.revanced.patches.reddit.customclients.boostforreddit.api.fingerprints

import app.revanced.patcher.fingerprint.MethodFingerprint

internal object JRAWUserAgent : MethodFingerprint(
strings = listOf("platform", "appId", "version", "redditUsername"),
)

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ package app.revanced.patches.reddit.customclients.joeyforreddit.api

import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstructions
import app.revanced.patcher.fingerprint.MethodFingerprintResult
import app.revanced.patches.reddit.customclients.BaseSpoofClientPatch
import app.revanced.patches.reddit.customclients.joeyforreddit.api.fingerprints.AuthUtilityUserAgent
import app.revanced.patches.reddit.customclients.joeyforreddit.api.fingerprints.GetClientIdFingerprint
import app.revanced.patches.reddit.customclients.joeyforreddit.detection.piracy.DisablePiracyDetectionPatch

Expand All @@ -12,6 +14,7 @@ import app.revanced.patches.reddit.customclients.joeyforreddit.detection.piracy.
object SpoofClientPatch : BaseSpoofClientPatch(
redirectUri = "https://127.0.0.1:65023/authorize_callback",
clientIdFingerprints = setOf(GetClientIdFingerprint),
userAgentFingerprints = setOf(AuthUtilityUserAgent),
compatiblePackages = setOf(
CompatiblePackage("o.o.joey"),
CompatiblePackage("o.o.joey.pro"),
Expand All @@ -28,4 +31,18 @@ object SpoofClientPatch : BaseSpoofClientPatch(
"""
)
}

override fun Set<MethodFingerprintResult>.patchUserAgent(context: BytecodeContext) {
// Use a random user agent.
val randomName = (0..100000).random()
val userAgent = "$randomName:app.revanced.$randomName:v1.0.0 (by /u/revanced)"

first().mutableMethod.replaceInstructions(
0,
"""
const-string v0, "$userAgent"
return-object v0
""",
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package app.revanced.patches.reddit.customclients.joeyforreddit.api.fingerprints

import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode

object AuthUtilityUserAgent : MethodFingerprint(
returnType = "Ljava/lang/String;",
accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
opcodes = listOf(Opcode.APUT_OBJECT),
customFingerprint = { _, classDef ->
classDef.sourceFile == "AuthUtility.java"
},
)
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
package app.revanced.patches.reddit.customclients.joeyforreddit.detection.piracy

import app.revanced.util.exception
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patches.reddit.customclients.joeyforreddit.detection.piracy.fingerprints.PiracyDetectionFingerprint
import app.revanced.util.exception

object DisablePiracyDetectionPatch : BytecodePatch(setOf(PiracyDetectionFingerprint)) {
override fun execute(context: BytecodeContext) {
PiracyDetectionFingerprint.result?.mutableMethod?.addInstruction(
0,
"""
return-void
"""
"return-void",
) ?: throw PiracyDetectionFingerprint.exception
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstruction
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.StringReference

@Suppress("unused")
object SpoofClientPatch : BaseSpoofClientPatch(
redirectUri = "redditisfun://auth",
Expand Down Expand Up @@ -54,7 +53,7 @@ object SpoofClientPatch : BaseSpoofClientPatch(
override fun Set<MethodFingerprintResult>.patchUserAgent(context: BytecodeContext) {
// Use a random user agent.
val randomName = (0..100000).random()
val userAgent = "android:app.revanced.$randomName:v1.0.0 (by /u/revanced)"
val userAgent = "$randomName:app.revanced.$randomName:v1.0.0 (by /u/revanced)"

first().mutableMethod.addInstructions(
0,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,30 +6,29 @@ import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.fingerprint.MethodFingerprintResult
import app.revanced.patches.reddit.customclients.BaseSpoofClientPatch
import app.revanced.patches.reddit.customclients.syncforreddit.api.fingerprints.*
import app.revanced.patches.reddit.customclients.syncforreddit.api.fingerprints.GetAuthorizationStringFingerprint
import app.revanced.patches.reddit.customclients.syncforreddit.api.fingerprints.GetBearerTokenFingerprint
import app.revanced.patches.reddit.customclients.syncforreddit.api.fingerprints.ImgurImageAPIFingerprint
import app.revanced.patches.reddit.customclients.syncforreddit.api.fingerprints.LoadBrowserURLFingerprint
import app.revanced.patches.reddit.customclients.syncforreddit.detection.piracy.DisablePiracyDetectionPatch
import app.revanced.util.exception
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.reference.StringReference
import java.util.*


@Suppress("unused")
object SpoofClientPatch : BaseSpoofClientPatch(
redirectUri = "http://redditsync/auth",
miscellaneousFingerprints = setOf(ImgurImageAPIFingerprint),
clientIdFingerprints = setOf(GetAuthorizationStringFingerprint),
userAgentFingerprints = setOf(LoadBrowserURLFingerprint),
userAgentFingerprints = setOf(GetUserAgentFingerprint),
compatiblePackages = setOf(
CompatiblePackage("com.laurencedawson.reddit_sync"),
CompatiblePackage("com.laurencedawson.reddit_sync.pro"),
CompatiblePackage("com.laurencedawson.reddit_sync.dev")
CompatiblePackage("com.laurencedawson.reddit_sync.dev"),
),
dependencies = setOf(DisablePiracyDetectionPatch::class)
dependencies = setOf(DisablePiracyDetectionPatch::class),
) {
override fun Set<MethodFingerprintResult>.patchClientId(context: BytecodeContext) {
forEach { fingerprintResult ->
Expand All @@ -41,7 +40,7 @@ object SpoofClientPatch : BaseSpoofClientPatch(
"""
const-string v0, "Basic $auth"
return-object v0
"""
""",
)
} ?: throw GetBearerTokenFingerprint.exception
}.let {
Expand All @@ -54,12 +53,12 @@ object SpoofClientPatch : BaseSpoofClientPatch(

val newAuthorizationUrl = reference.string.replace(
"client_id=.*?&".toRegex(),
"client_id=$clientId&"
"client_id=$clientId&",
)

replaceInstruction(
occurrenceIndex,
"const-string v$targetRegister, \"$newAuthorizationUrl\""
"const-string v$targetRegister, \"$newAuthorizationUrl\"",
)
}
}
Expand All @@ -72,7 +71,21 @@ object SpoofClientPatch : BaseSpoofClientPatch(

it.mutableMethod.replaceInstruction(
apiUrlIndex,
"const-string v1, \"https://api.imgur.com/3/image\""
"const-string v1, \"https://api.imgur.com/3/image\"",
)
}

override fun Set<MethodFingerprintResult>.patchUserAgent(context: BytecodeContext) {
// Use a random user agent.
val randomName = (0..100000).random()
val userAgent = "$randomName:app.revanced.$randomName:v1.0.0 (by /u/revanced)"

first().mutableMethod.replaceInstruction(
0,
"""
const-string v0, "$userAgent"
return-object v0
""",
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package app.revanced.patches.reddit.customclients.syncforreddit.api.fingerprints

import app.revanced.patcher.fingerprint.MethodFingerprint

internal object GetUserAgentFingerprint : MethodFingerprint(
strings = listOf("android:com.laurencedawson.reddit_sync"),
)

0 comments on commit 495e6d6

Please sign in to comment.