feat(Spotify): Add Spoof signature patch (#4576)

This commit is contained in:
oSumAtrIX 2025-03-09 13:06:53 +01:00 committed by GitHub
parent aa2b79fe7e
commit 3646c70556
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 75 additions and 40 deletions

View File

@ -816,6 +816,10 @@ public final class app/revanced/patches/spotify/lite/ondemand/OnDemandPatchKt {
public static final fun getOnDemandPatch ()Lapp/revanced/patcher/patch/BytecodePatch; public static final fun getOnDemandPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
} }
public final class app/revanced/patches/spotify/misc/fix/SpoofSignaturePatchKt {
public static final fun getSpoofSignaturePatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/spotify/navbar/PremiumNavbarTabPatchKt { public final class app/revanced/patches/spotify/navbar/PremiumNavbarTabPatchKt {
public static final fun getPremiumNavbarTabPatch ()Lapp/revanced/patcher/patch/BytecodePatch; public static final fun getPremiumNavbarTabPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
} }

View File

@ -0,0 +1,5 @@
package app.revanced.patches.spotify.misc.fix
import app.revanced.patcher.fingerprint
internal val getAppSignatureFingerprint = fingerprint { strings("Failed to get the application signatures") }

View File

@ -0,0 +1,33 @@
package app.revanced.patches.spotify.misc.fix
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.util.indexOfFirstInstructionReversedOrThrow
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
@Suppress("unused")
val spoofSignaturePatch = bytecodePatch(
name = "Spoof signature",
description = "Spoofs the signature of the app to fix various functions of the app.",
) {
compatibleWith("com.spotify.music")
execute {
getAppSignatureFingerprint.method.apply {
val failedToGetSignaturesStringMatch = getAppSignatureFingerprint.stringMatches!!.first()
val concatSignaturesIndex = indexOfFirstInstructionReversedOrThrow(
failedToGetSignaturesStringMatch.index,
Opcode.MOVE_RESULT_OBJECT,
)
val register = getInstruction<OneRegisterInstruction>(concatSignaturesIndex).registerA
val expectedSignature = "d6a6dced4a85f24204bf9505ccc1fce114cadb32"
replaceInstruction(concatSignaturesIndex, "const-string v$register, \"$expectedSignature\"")
}
}
}

View File

@ -178,8 +178,7 @@ fun Method.indexOfFirstLiteralInstructionReversedOrThrow(literal: Long): Int {
* *
* @return if the method contains a literal with the given value. * @return if the method contains a literal with the given value.
*/ */
fun Method.containsLiteralInstruction(literal: Long) = fun Method.containsLiteralInstruction(literal: Long) = indexOfFirstLiteralInstruction(literal) >= 0
indexOfFirstLiteralInstruction(literal) >= 0
/** /**
* Traverse the class hierarchy starting from the given root class. * Traverse the class hierarchy starting from the given root class.
@ -205,23 +204,20 @@ fun BytecodePatchContext.traverseClassHierarchy(targetClass: MutableClass, callb
* if the [Instruction] is not a [ReferenceInstruction] or the [Reference] is not of type [T]. * if the [Instruction] is not a [ReferenceInstruction] or the [Reference] is not of type [T].
* @see ReferenceInstruction * @see ReferenceInstruction
*/ */
inline fun <reified T : Reference> Instruction.getReference() = inline fun <reified T : Reference> Instruction.getReference() = (this as? ReferenceInstruction)?.reference as? T
(this as? ReferenceInstruction)?.reference as? T
/** /**
* @return The index of the first opcode specified, or -1 if not found. * @return The index of the first opcode specified, or -1 if not found.
* @see indexOfFirstInstructionOrThrow * @see indexOfFirstInstructionOrThrow
*/ */
fun Method.indexOfFirstInstruction(targetOpcode: Opcode): Int = fun Method.indexOfFirstInstruction(targetOpcode: Opcode): Int = indexOfFirstInstruction(0, targetOpcode)
indexOfFirstInstruction(0, targetOpcode)
/** /**
* @param startIndex Optional starting index to start searching from. * @param startIndex Optional starting index to start searching from.
* @return The index of the first opcode specified, or -1 if not found. * @return The index of the first opcode specified, or -1 if not found.
* @see indexOfFirstInstructionOrThrow * @see indexOfFirstInstructionOrThrow
*/ */
fun Method.indexOfFirstInstruction(startIndex: Int = 0, targetOpcode: Opcode): Int = fun Method.indexOfFirstInstruction(startIndex: Int = 0, targetOpcode: Opcode): Int = indexOfFirstInstruction(startIndex) {
indexOfFirstInstruction(startIndex) {
opcode == targetOpcode opcode == targetOpcode
} }
@ -251,23 +247,21 @@ fun Method.indexOfFirstInstruction(startIndex: Int = 0, filter: Instruction.() -
* @throws PatchException * @throws PatchException
* @see indexOfFirstInstruction * @see indexOfFirstInstruction
*/ */
fun Method.indexOfFirstInstructionOrThrow(targetOpcode: Opcode): Int = fun Method.indexOfFirstInstructionOrThrow(targetOpcode: Opcode): Int = indexOfFirstInstructionOrThrow(0, targetOpcode)
indexOfFirstInstructionOrThrow(0, targetOpcode)
/** /**
* @return The index of the first opcode specified, starting from the index specified. * @return The index of the first opcode specified, starting from the index specified.
* @throws PatchException * @throws PatchException
* @see indexOfFirstInstruction * @see indexOfFirstInstruction
*/ */
fun Method.indexOfFirstInstructionOrThrow(startIndex: Int = 0, targetOpcode: Opcode): Int = fun Method.indexOfFirstInstructionOrThrow(startIndex: Int = 0, targetOpcode: Opcode): Int = indexOfFirstInstructionOrThrow(startIndex) {
indexOfFirstInstructionOrThrow(startIndex) {
opcode == targetOpcode opcode == targetOpcode
} }
/** /**
* Get the index of the first [Instruction] that matches the predicate, starting from [startIndex]. * Get the index of the first [Instruction] that matches the predicate, starting from [startIndex].
* *
* @return the index of the instruction * @return The index of the instruction.
* @throws PatchException * @throws PatchException
* @see indexOfFirstInstruction * @see indexOfFirstInstruction
*/ */
@ -288,8 +282,7 @@ fun Method.indexOfFirstInstructionOrThrow(startIndex: Int = 0, filter: Instructi
* @return -1 if the instruction is not found. * @return -1 if the instruction is not found.
* @see indexOfFirstInstructionReversedOrThrow * @see indexOfFirstInstructionReversedOrThrow
*/ */
fun Method.indexOfFirstInstructionReversed(startIndex: Int? = null, targetOpcode: Opcode): Int = fun Method.indexOfFirstInstructionReversed(startIndex: Int? = null, targetOpcode: Opcode): Int = indexOfFirstInstructionReversed(startIndex) {
indexOfFirstInstructionReversed(startIndex) {
opcode == targetOpcode opcode == targetOpcode
} }
@ -316,8 +309,7 @@ fun Method.indexOfFirstInstructionReversed(startIndex: Int? = null, filter: Inst
* *
* @return -1 if the instruction is not found. * @return -1 if the instruction is not found.
*/ */
fun Method.indexOfFirstInstructionReversed(targetOpcode: Opcode): Int = fun Method.indexOfFirstInstructionReversed(targetOpcode: Opcode): Int = indexOfFirstInstructionReversed {
indexOfFirstInstructionReversed {
opcode == targetOpcode opcode == targetOpcode
} }
@ -326,11 +318,10 @@ fun Method.indexOfFirstInstructionReversed(targetOpcode: Opcode): Int =
* starting from and [startIndex] and searching down. * starting from and [startIndex] and searching down.
* *
* @param startIndex Optional starting index to search down from. Searching includes the start index. * @param startIndex Optional starting index to search down from. Searching includes the start index.
* @return -1 if the instruction is not found. * @return The index of the instruction.
* @see indexOfFirstInstructionReversed * @see indexOfFirstInstructionReversed
*/ */
fun Method.indexOfFirstInstructionReversedOrThrow(startIndex: Int? = null, targetOpcode: Opcode): Int = fun Method.indexOfFirstInstructionReversedOrThrow(startIndex: Int? = null, targetOpcode: Opcode): Int = indexOfFirstInstructionReversedOrThrow(startIndex) {
indexOfFirstInstructionReversedOrThrow(startIndex) {
opcode == targetOpcode opcode == targetOpcode
} }
@ -340,16 +331,16 @@ fun Method.indexOfFirstInstructionReversedOrThrow(startIndex: Int? = null, targe
* *
* @return -1 if the instruction is not found. * @return -1 if the instruction is not found.
*/ */
fun Method.indexOfFirstInstructionReversedOrThrow(targetOpcode: Opcode): Int = fun Method.indexOfFirstInstructionReversedOrThrow(targetOpcode: Opcode): Int = indexOfFirstInstructionReversedOrThrow {
indexOfFirstInstructionReversedOrThrow {
opcode == targetOpcode opcode == targetOpcode
} }
/** /**
* Get the index of matching instruction, * Get the index of matching instruction,
* starting from and [startIndex] and searching down. * starting from and [startIndex] and searching down.
* *
* @param startIndex Optional starting index to search down from. Searching includes the start index. * @param startIndex Optional starting index to search down from. Searching includes the start index.
* @return -1 if the instruction is not found. * @return The index of the instruction.
* @see indexOfFirstInstructionReversed * @see indexOfFirstInstructionReversed
*/ */
fun Method.indexOfFirstInstructionReversedOrThrow(startIndex: Int? = null, filter: Instruction.() -> Boolean): Int { fun Method.indexOfFirstInstructionReversedOrThrow(startIndex: Int? = null, filter: Instruction.() -> Boolean): Int {
@ -389,8 +380,7 @@ fun Method.findInstructionIndicesReversedOrThrow(filter: Instruction.() -> Boole
* _Returns an empty list if no indices are found_ * _Returns an empty list if no indices are found_
* @see findInstructionIndicesReversedOrThrow * @see findInstructionIndicesReversedOrThrow
*/ */
fun Method.findInstructionIndicesReversed(opcode: Opcode): List<Int> = fun Method.findInstructionIndicesReversed(opcode: Opcode): List<Int> = findInstructionIndicesReversed { this.opcode == opcode }
findInstructionIndicesReversed { this.opcode == opcode }
/** /**
* @return An immutable list of indices of the opcode in reverse order. * @return An immutable list of indices of the opcode in reverse order.
@ -408,15 +398,18 @@ internal fun MutableMethod.insertFeatureFlagBooleanOverride(literal: Long, exten
val index = indexOfFirstInstructionOrThrow(literalIndex, Opcode.MOVE_RESULT) val index = indexOfFirstInstructionOrThrow(literalIndex, Opcode.MOVE_RESULT)
val register = getInstruction<OneRegisterInstruction>(index).registerA val register = getInstruction<OneRegisterInstruction>(index).registerA
val operation = if (register < 16) "invoke-static { v$register }" val operation = if (register < 16) {
else "invoke-static/range { v$register .. v$register }" "invoke-static { v$register }"
} else {
"invoke-static/range { v$register .. v$register }"
}
addInstructions( addInstructions(
index + 1, index + 1,
""" """
$operation, $extensionsMethod $operation, $extensionsMethod
move-result v$register move-result v$register
""" """,
) )
} }