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 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 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.
*/
fun Method.containsLiteralInstruction(literal: Long) =
indexOfFirstLiteralInstruction(literal) >= 0
fun Method.containsLiteralInstruction(literal: Long) = indexOfFirstLiteralInstruction(literal) >= 0
/**
* Traverse the class hierarchy starting from the given root class.
@ -205,25 +204,22 @@ fun BytecodePatchContext.traverseClassHierarchy(targetClass: MutableClass, callb
* if the [Instruction] is not a [ReferenceInstruction] or the [Reference] is not of type [T].
* @see ReferenceInstruction
*/
inline fun <reified T : Reference> Instruction.getReference() =
(this as? ReferenceInstruction)?.reference as? T
inline fun <reified T : Reference> Instruction.getReference() = (this as? ReferenceInstruction)?.reference as? T
/**
* @return The index of the first opcode specified, or -1 if not found.
* @see indexOfFirstInstructionOrThrow
*/
fun Method.indexOfFirstInstruction(targetOpcode: Opcode): Int =
indexOfFirstInstruction(0, targetOpcode)
fun Method.indexOfFirstInstruction(targetOpcode: Opcode): Int = indexOfFirstInstruction(0, targetOpcode)
/**
* @param startIndex Optional starting index to start searching from.
* @return The index of the first opcode specified, or -1 if not found.
* @see indexOfFirstInstructionOrThrow
*/
fun Method.indexOfFirstInstruction(startIndex: Int = 0, targetOpcode: Opcode): Int =
indexOfFirstInstruction(startIndex) {
opcode == targetOpcode
}
fun Method.indexOfFirstInstruction(startIndex: Int = 0, targetOpcode: Opcode): Int = indexOfFirstInstruction(startIndex) {
opcode == targetOpcode
}
/**
* Get the index of the first [Instruction] that matches the predicate, starting from [startIndex].
@ -251,23 +247,21 @@ fun Method.indexOfFirstInstruction(startIndex: Int = 0, filter: Instruction.() -
* @throws PatchException
* @see indexOfFirstInstruction
*/
fun Method.indexOfFirstInstructionOrThrow(targetOpcode: Opcode): Int =
indexOfFirstInstructionOrThrow(0, targetOpcode)
fun Method.indexOfFirstInstructionOrThrow(targetOpcode: Opcode): Int = indexOfFirstInstructionOrThrow(0, targetOpcode)
/**
* @return The index of the first opcode specified, starting from the index specified.
* @throws PatchException
* @see indexOfFirstInstruction
*/
fun Method.indexOfFirstInstructionOrThrow(startIndex: Int = 0, targetOpcode: Opcode): Int =
indexOfFirstInstructionOrThrow(startIndex) {
opcode == targetOpcode
}
fun Method.indexOfFirstInstructionOrThrow(startIndex: Int = 0, targetOpcode: Opcode): Int = indexOfFirstInstructionOrThrow(startIndex) {
opcode == targetOpcode
}
/**
* 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
* @see indexOfFirstInstruction
*/
@ -288,10 +282,9 @@ fun Method.indexOfFirstInstructionOrThrow(startIndex: Int = 0, filter: Instructi
* @return -1 if the instruction is not found.
* @see indexOfFirstInstructionReversedOrThrow
*/
fun Method.indexOfFirstInstructionReversed(startIndex: Int? = null, targetOpcode: Opcode): Int =
indexOfFirstInstructionReversed(startIndex) {
opcode == targetOpcode
}
fun Method.indexOfFirstInstructionReversed(startIndex: Int? = null, targetOpcode: Opcode): Int = indexOfFirstInstructionReversed(startIndex) {
opcode == targetOpcode
}
/**
* Get the index of matching instruction,
@ -316,23 +309,21 @@ fun Method.indexOfFirstInstructionReversed(startIndex: Int? = null, filter: Inst
*
* @return -1 if the instruction is not found.
*/
fun Method.indexOfFirstInstructionReversed(targetOpcode: Opcode): Int =
indexOfFirstInstructionReversed {
opcode == targetOpcode
}
fun Method.indexOfFirstInstructionReversed(targetOpcode: Opcode): Int = indexOfFirstInstructionReversed {
opcode == targetOpcode
}
/**
* Get the index of matching instruction,
* starting from and [startIndex] and searching down.
*
* @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
*/
fun Method.indexOfFirstInstructionReversedOrThrow(startIndex: Int? = null, targetOpcode: Opcode): Int =
indexOfFirstInstructionReversedOrThrow(startIndex) {
opcode == targetOpcode
}
fun Method.indexOfFirstInstructionReversedOrThrow(startIndex: Int? = null, targetOpcode: Opcode): Int = indexOfFirstInstructionReversedOrThrow(startIndex) {
opcode == targetOpcode
}
/**
* Get the index of matching instruction,
@ -340,16 +331,16 @@ fun Method.indexOfFirstInstructionReversedOrThrow(startIndex: Int? = null, targe
*
* @return -1 if the instruction is not found.
*/
fun Method.indexOfFirstInstructionReversedOrThrow(targetOpcode: Opcode): Int =
indexOfFirstInstructionReversedOrThrow {
opcode == targetOpcode
}
fun Method.indexOfFirstInstructionReversedOrThrow(targetOpcode: Opcode): Int = indexOfFirstInstructionReversedOrThrow {
opcode == targetOpcode
}
/**
* Get the index of matching instruction,
* starting from and [startIndex] and searching down.
*
* @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
*/
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_
* @see findInstructionIndicesReversedOrThrow
*/
fun Method.findInstructionIndicesReversed(opcode: Opcode): List<Int> =
findInstructionIndicesReversed { this.opcode == opcode }
fun Method.findInstructionIndicesReversed(opcode: Opcode): List<Int> = findInstructionIndicesReversed { this.opcode == opcode }
/**
* @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 register = getInstruction<OneRegisterInstruction>(index).registerA
val operation = if (register < 16) "invoke-static { v$register }"
else "invoke-static/range { v$register .. v$register }"
val operation = if (register < 16) {
"invoke-static { v$register }"
} else {
"invoke-static/range { v$register .. v$register }"
}
addInstructions(
index + 1,
"""
$operation, $extensionsMethod
move-result v$register
"""
""",
)
}