refactor(redditisfun): SpoofClientPatch

This commit is contained in:
Pun Butrach
2026-01-12 16:27:33 +07:00
parent 94cc175b55
commit 8dfcbd09cc
2 changed files with 50 additions and 32 deletions

View File

@@ -1,31 +1,35 @@
package app.revanced.patches.reddit.customclients.redditisfun.api
import app.revanced.patcher.fingerprint
import app.revanced.patcher.BytecodePatchContextMethodMatching.gettingFirstMutableMethodDeclaratively
import app.revanced.patcher.accessFlags
import app.revanced.patcher.instructions
import app.revanced.patcher.invoke
import app.revanced.patcher.parameterTypes
import app.revanced.patcher.patch.BytecodePatchContext
import app.revanced.patcher.returnType
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
internal fun baseClientIdFingerprint(string: String) = fingerprint {
strings("yyOCBp.RHJhDKd", string)
}
internal val basicAuthorizationFingerprint = baseClientIdFingerprint(
string = "fJOxVwBUyo*=f:<OoejWs:AqmIJ", // Encrypted basic authorization string.
internal val BytecodePatchContext.basicAuthorizationMethod by gettingFirstMutableMethodDeclaratively(
"yyOCBp.RHJhDKd",
"fJOxVwBUyo*=f:<OoejWs:AqmIJ" // Encrypted basic authorization string.
)
internal val buildAuthorizationStringFingerprint = baseClientIdFingerprint(
string = "client_id",
internal val BytecodePatchContext.buildAuthorizationStringMethod by gettingFirstMutableMethodDeclaratively(
"yyOCBp.RHJhDKd",
"client_id"
)
internal val getUserAgentFingerprint = fingerprint {
internal val BytecodePatchContext.getUserAgentMethod by gettingFirstMutableMethodDeclaratively {
accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC)
returns("Ljava/lang/String;")
parameters()
opcodes(
Opcode.NEW_ARRAY,
Opcode.CONST_4,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.APUT_OBJECT,
Opcode.CONST,
returnType("Ljava/lang/String;")
parameterTypes()
instructions(
Opcode.NEW_ARRAY(),
Opcode.CONST_4(),
Opcode.INVOKE_STATIC(),
Opcode.MOVE_RESULT_OBJECT(),
Opcode.APUT_OBJECT(),
Opcode.CONST(),
)
}

View File

@@ -1,16 +1,17 @@
package app.revanced.patches.reddit.customclients.redditisfun.api
import app.revanced.patcher.Fingerprint
import app.revanced.patcher.Match
import app.revanced.patcher.extensions.getInstruction
import app.revanced.patcher.extensions.replaceInstruction
import app.revanced.patches.reddit.customclients.spoofClientPatch
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstructionOrThrow
import app.revanced.util.returnEarly
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.StringReference
import com.android.tools.smali.dexlib2.mutable.MutableMethod
@Suppress("unused")
val spoofClientPatch = spoofClientPatch(redirectUri = "redditisfun://auth") { clientIdOption ->
compatibleWith(
"com.andrewshu.android.reddit",
@@ -30,21 +31,34 @@ val spoofClientPatch = spoofClientPatch(redirectUri = "redditisfun://auth") { cl
* @param getReplacementIndex A function that returns the index of the instruction to replace
* using the [Match.StringMatch] list from the [Match].
*/
fun Fingerprint.replaceWith(
fun MutableMethod.replaceWith(
string: String,
getReplacementIndex: List<Match.StringMatch>.() -> Int,
) = method.apply {
val replacementIndex = stringMatches.getReplacementIndex()
val clientIdRegister = getInstruction<OneRegisterInstruction>(replacementIndex).registerA
offset: Int,
getReplacementIndex: String
) {
val anchorIndex = indexOfFirstInstructionOrThrow {
opcode == Opcode.CONST_STRING && getReference<StringReference>()?.string == string
}
replaceInstruction(replacementIndex, "const-string v$clientIdRegister, \"$string\"")
val targetIndex = anchorIndex + offset
val clientIdRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA
replaceInstruction(targetIndex, "const-string v$clientIdRegister, \"$getReplacementIndex\"")
}
// Patch OAuth authorization.
buildAuthorizationStringFingerprint.replaceWith(clientId!!) { first().index + 4 }
buildAuthorizationStringMethod.replaceWith(
string = "yyOCBp.RHJhDKd",
offset = 4,
getReplacementIndex = clientId!!
)
// Path basic authorization.
basicAuthorizationFingerprint.replaceWith("$clientId:") { last().index + 7 }
basicAuthorizationMethod.replaceWith(
string = "fJOxVwBUyo*=f:<OoejWs:AqmIJ",
offset = 7,
getReplacementIndex = "$clientId:"
)
// endregion
@@ -54,7 +68,7 @@ val spoofClientPatch = spoofClientPatch(redirectUri = "redditisfun://auth") { cl
val randomName = (0..100000).random()
val userAgent = "$randomName:app.revanced.$randomName:v1.0.0 (by /u/revanced)"
getUserAgentFingerprint.method.returnEarly(userAgent)
getUserAgentMethod.returnEarly(userAgent)
// endregion
@@ -62,9 +76,9 @@ val spoofClientPatch = spoofClientPatch(redirectUri = "redditisfun://auth") { cl
// Reddit messed up and does not append a redirect uri to the authorization url to old.reddit.com/login.
// Replace old.reddit.com with www.reddit.com to fix this.
buildAuthorizationStringFingerprint.method.apply {
buildAuthorizationStringMethod.apply {
val index = indexOfFirstInstructionOrThrow {
getReference<StringReference>()?.contains("old.reddit.com") == true
getReference<StringReference>()?.string?.contains("old.reddit.com") == true
}
val targetRegister = getInstruction<OneRegisterInstruction>(index).registerA