Skip to content

Commit 78b9716

Browse files
OctoNezdoSumAtrIX
andauthored
fix(3rd-party Reddit apps): Spoof user agent to work around Reddit API issues (#3253)
Co-authored-by: oSumAtrIX <[email protected]>
1 parent 33ea424 commit 78b9716

File tree

10 files changed

+93
-35
lines changed

10 files changed

+93
-35
lines changed

api/revanced-patches.api

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,7 @@ public final class app/revanced/patches/reddit/customclients/baconreader/api/Spo
555555
public final class app/revanced/patches/reddit/customclients/boostforreddit/api/SpoofClientPatch : app/revanced/patches/reddit/customclients/BaseSpoofClientPatch {
556556
public static final field INSTANCE Lapp/revanced/patches/reddit/customclients/boostforreddit/api/SpoofClientPatch;
557557
public fun patchClientId (Ljava/util/Set;Lapp/revanced/patcher/data/BytecodeContext;)V
558+
public fun patchUserAgent (Ljava/util/Set;Lapp/revanced/patcher/data/BytecodeContext;)V
558559
}
559560

560561
public final class app/revanced/patches/reddit/customclients/infinityforreddit/api/SpoofClientPatch : app/revanced/patches/reddit/customclients/BaseSpoofClientPatch {
@@ -577,6 +578,11 @@ public final class app/revanced/patches/reddit/customclients/joeyforreddit/ads/D
577578
public final class app/revanced/patches/reddit/customclients/joeyforreddit/api/SpoofClientPatch : app/revanced/patches/reddit/customclients/BaseSpoofClientPatch {
578579
public static final field INSTANCE Lapp/revanced/patches/reddit/customclients/joeyforreddit/api/SpoofClientPatch;
579580
public fun patchClientId (Ljava/util/Set;Lapp/revanced/patcher/data/BytecodeContext;)V
581+
public fun patchUserAgent (Ljava/util/Set;Lapp/revanced/patcher/data/BytecodeContext;)V
582+
}
583+
584+
public final class app/revanced/patches/reddit/customclients/joeyforreddit/api/fingerprints/AuthUtilityUserAgent : app/revanced/patcher/fingerprint/MethodFingerprint {
585+
public static final field INSTANCE Lapp/revanced/patches/reddit/customclients/joeyforreddit/api/fingerprints/AuthUtilityUserAgent;
580586
}
581587

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

626633
public final class app/revanced/patches/reddit/customclients/syncforreddit/detection/piracy/DisablePiracyDetectionPatch : app/revanced/patcher/patch/BytecodePatch {

src/main/kotlin/app/revanced/patches/reddit/customclients/boostforreddit/api/SpoofClientPatch.kt

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,32 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
55
import app.revanced.patcher.fingerprint.MethodFingerprintResult
66
import app.revanced.patches.reddit.customclients.BaseSpoofClientPatch
77
import app.revanced.patches.reddit.customclients.boostforreddit.api.fingerprints.GetClientIdFingerprint
8-
import app.revanced.patches.reddit.customclients.boostforreddit.api.fingerprints.LoginActivityOnCreateFingerprint
9-
8+
import app.revanced.patches.reddit.customclients.boostforreddit.api.fingerprints.JRAWUserAgent
109

1110
@Suppress("unused")
1211
object SpoofClientPatch : BaseSpoofClientPatch(
1312
redirectUri = "http://rubenmayayo.com",
1413
clientIdFingerprints = setOf(GetClientIdFingerprint),
15-
userAgentFingerprints = setOf(LoginActivityOnCreateFingerprint),
16-
compatiblePackages = setOf(CompatiblePackage("com.rubenmayayo.reddit"))
14+
userAgentFingerprints = setOf(JRAWUserAgent),
15+
compatiblePackages = setOf(CompatiblePackage("com.rubenmayayo.reddit")),
1716
) {
1817
override fun Set<MethodFingerprintResult>.patchClientId(context: BytecodeContext) {
1918
first().mutableMethod.addInstructions(
2019
0,
2120
"""
2221
const-string v0, "$clientId"
2322
return-object v0
24-
"""
23+
""",
24+
)
25+
}
26+
27+
override fun Set<MethodFingerprintResult>.patchUserAgent(context: BytecodeContext) {
28+
// Use a random user agent.
29+
val randomName = (0..100000).random()
30+
31+
first().mutableMethod.addInstructions(
32+
1,
33+
"const-string v3, \"$randomName\"",
2534
)
2635
}
2736
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package app.revanced.patches.reddit.customclients.boostforreddit.api.fingerprints
2+
3+
import app.revanced.patcher.fingerprint.MethodFingerprint
4+
5+
internal object JRAWUserAgent : MethodFingerprint(
6+
strings = listOf("platform", "appId", "version", "redditUsername"),
7+
)

src/main/kotlin/app/revanced/patches/reddit/customclients/boostforreddit/api/fingerprints/LoginActivityOnCreateFingerprint.kt

Lines changed: 0 additions & 14 deletions
This file was deleted.

src/main/kotlin/app/revanced/patches/reddit/customclients/joeyforreddit/api/SpoofClientPatch.kt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@ package app.revanced.patches.reddit.customclients.joeyforreddit.api
22

33
import app.revanced.patcher.data.BytecodeContext
44
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
5+
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstructions
56
import app.revanced.patcher.fingerprint.MethodFingerprintResult
67
import app.revanced.patches.reddit.customclients.BaseSpoofClientPatch
8+
import app.revanced.patches.reddit.customclients.joeyforreddit.api.fingerprints.AuthUtilityUserAgent
79
import app.revanced.patches.reddit.customclients.joeyforreddit.api.fingerprints.GetClientIdFingerprint
810
import app.revanced.patches.reddit.customclients.joeyforreddit.detection.piracy.DisablePiracyDetectionPatch
911

@@ -12,6 +14,7 @@ import app.revanced.patches.reddit.customclients.joeyforreddit.detection.piracy.
1214
object SpoofClientPatch : BaseSpoofClientPatch(
1315
redirectUri = "https://127.0.0.1:65023/authorize_callback",
1416
clientIdFingerprints = setOf(GetClientIdFingerprint),
17+
userAgentFingerprints = setOf(AuthUtilityUserAgent),
1518
compatiblePackages = setOf(
1619
CompatiblePackage("o.o.joey"),
1720
CompatiblePackage("o.o.joey.pro"),
@@ -28,4 +31,18 @@ object SpoofClientPatch : BaseSpoofClientPatch(
2831
"""
2932
)
3033
}
34+
35+
override fun Set<MethodFingerprintResult>.patchUserAgent(context: BytecodeContext) {
36+
// Use a random user agent.
37+
val randomName = (0..100000).random()
38+
val userAgent = "$randomName:app.revanced.$randomName:v1.0.0 (by /u/revanced)"
39+
40+
first().mutableMethod.replaceInstructions(
41+
0,
42+
"""
43+
const-string v0, "$userAgent"
44+
return-object v0
45+
""",
46+
)
47+
}
3148
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package app.revanced.patches.reddit.customclients.joeyforreddit.api.fingerprints
2+
3+
import app.revanced.patcher.extensions.or
4+
import app.revanced.patcher.fingerprint.MethodFingerprint
5+
import com.android.tools.smali.dexlib2.AccessFlags
6+
import com.android.tools.smali.dexlib2.Opcode
7+
8+
object AuthUtilityUserAgent : MethodFingerprint(
9+
returnType = "Ljava/lang/String;",
10+
accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
11+
opcodes = listOf(Opcode.APUT_OBJECT),
12+
customFingerprint = { _, classDef ->
13+
classDef.sourceFile == "AuthUtility.java"
14+
},
15+
)
Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,16 @@
11
package app.revanced.patches.reddit.customclients.joeyforreddit.detection.piracy
22

3-
import app.revanced.util.exception
43
import app.revanced.patcher.data.BytecodeContext
54
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
65
import app.revanced.patcher.patch.BytecodePatch
76
import app.revanced.patches.reddit.customclients.joeyforreddit.detection.piracy.fingerprints.PiracyDetectionFingerprint
7+
import app.revanced.util.exception
88

99
object DisablePiracyDetectionPatch : BytecodePatch(setOf(PiracyDetectionFingerprint)) {
1010
override fun execute(context: BytecodeContext) {
1111
PiracyDetectionFingerprint.result?.mutableMethod?.addInstruction(
1212
0,
13-
"""
14-
return-void
15-
"""
13+
"return-void",
1614
) ?: throw PiracyDetectionFingerprint.exception
1715
}
18-
}
16+
}

src/main/kotlin/app/revanced/patches/reddit/customclients/redditisfun/api/SpoofClientPatch.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import app.revanced.util.getReference
1414
import app.revanced.util.indexOfFirstInstruction
1515
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
1616
import com.android.tools.smali.dexlib2.iface.reference.StringReference
17-
1817
@Suppress("unused")
1918
object SpoofClientPatch : BaseSpoofClientPatch(
2019
redirectUri = "redditisfun://auth",
@@ -54,7 +53,7 @@ object SpoofClientPatch : BaseSpoofClientPatch(
5453
override fun Set<MethodFingerprintResult>.patchUserAgent(context: BytecodeContext) {
5554
// Use a random user agent.
5655
val randomName = (0..100000).random()
57-
val userAgent = "android:app.revanced.$randomName:v1.0.0 (by /u/revanced)"
56+
val userAgent = "$randomName:app.revanced.$randomName:v1.0.0 (by /u/revanced)"
5857

5958
first().mutableMethod.addInstructions(
6059
0,

src/main/kotlin/app/revanced/patches/reddit/customclients/syncforreddit/api/SpoofClientPatch.kt

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,30 +6,29 @@ import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
66
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
77
import app.revanced.patcher.fingerprint.MethodFingerprintResult
88
import app.revanced.patches.reddit.customclients.BaseSpoofClientPatch
9+
import app.revanced.patches.reddit.customclients.syncforreddit.api.fingerprints.*
910
import app.revanced.patches.reddit.customclients.syncforreddit.api.fingerprints.GetAuthorizationStringFingerprint
1011
import app.revanced.patches.reddit.customclients.syncforreddit.api.fingerprints.GetBearerTokenFingerprint
1112
import app.revanced.patches.reddit.customclients.syncforreddit.api.fingerprints.ImgurImageAPIFingerprint
12-
import app.revanced.patches.reddit.customclients.syncforreddit.api.fingerprints.LoadBrowserURLFingerprint
1313
import app.revanced.patches.reddit.customclients.syncforreddit.detection.piracy.DisablePiracyDetectionPatch
1414
import app.revanced.util.exception
1515
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
1616
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
1717
import com.android.tools.smali.dexlib2.iface.reference.StringReference
1818
import java.util.*
1919

20-
2120
@Suppress("unused")
2221
object SpoofClientPatch : BaseSpoofClientPatch(
2322
redirectUri = "http://redditsync/auth",
2423
miscellaneousFingerprints = setOf(ImgurImageAPIFingerprint),
2524
clientIdFingerprints = setOf(GetAuthorizationStringFingerprint),
26-
userAgentFingerprints = setOf(LoadBrowserURLFingerprint),
25+
userAgentFingerprints = setOf(GetUserAgentFingerprint),
2726
compatiblePackages = setOf(
2827
CompatiblePackage("com.laurencedawson.reddit_sync"),
2928
CompatiblePackage("com.laurencedawson.reddit_sync.pro"),
30-
CompatiblePackage("com.laurencedawson.reddit_sync.dev")
29+
CompatiblePackage("com.laurencedawson.reddit_sync.dev"),
3130
),
32-
dependencies = setOf(DisablePiracyDetectionPatch::class)
31+
dependencies = setOf(DisablePiracyDetectionPatch::class),
3332
) {
3433
override fun Set<MethodFingerprintResult>.patchClientId(context: BytecodeContext) {
3534
forEach { fingerprintResult ->
@@ -41,7 +40,7 @@ object SpoofClientPatch : BaseSpoofClientPatch(
4140
"""
4241
const-string v0, "Basic $auth"
4342
return-object v0
44-
"""
43+
""",
4544
)
4645
} ?: throw GetBearerTokenFingerprint.exception
4746
}.let {
@@ -54,12 +53,12 @@ object SpoofClientPatch : BaseSpoofClientPatch(
5453

5554
val newAuthorizationUrl = reference.string.replace(
5655
"client_id=.*?&".toRegex(),
57-
"client_id=$clientId&"
56+
"client_id=$clientId&",
5857
)
5958

6059
replaceInstruction(
6160
occurrenceIndex,
62-
"const-string v$targetRegister, \"$newAuthorizationUrl\""
61+
"const-string v$targetRegister, \"$newAuthorizationUrl\"",
6362
)
6463
}
6564
}
@@ -72,7 +71,21 @@ object SpoofClientPatch : BaseSpoofClientPatch(
7271

7372
it.mutableMethod.replaceInstruction(
7473
apiUrlIndex,
75-
"const-string v1, \"https://api.imgur.com/3/image\""
74+
"const-string v1, \"https://api.imgur.com/3/image\"",
75+
)
76+
}
77+
78+
override fun Set<MethodFingerprintResult>.patchUserAgent(context: BytecodeContext) {
79+
// Use a random user agent.
80+
val randomName = (0..100000).random()
81+
val userAgent = "$randomName:app.revanced.$randomName:v1.0.0 (by /u/revanced)"
82+
83+
first().mutableMethod.replaceInstruction(
84+
0,
85+
"""
86+
const-string v0, "$userAgent"
87+
return-object v0
88+
""",
7689
)
7790
}
7891
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package app.revanced.patches.reddit.customclients.syncforreddit.api.fingerprints
2+
3+
import app.revanced.patcher.fingerprint.MethodFingerprint
4+
5+
internal object GetUserAgentFingerprint : MethodFingerprint(
6+
strings = listOf("android:com.laurencedawson.reddit_sync"),
7+
)

0 commit comments

Comments
 (0)