diff --git a/patches/api/patches.api b/patches/api/patches.api index 71401bc89..92106329f 100644 --- a/patches/api/patches.api +++ b/patches/api/patches.api @@ -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; } diff --git a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/fix/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/fix/Fingerprints.kt new file mode 100644 index 000000000..c6e476c56 --- /dev/null +++ b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/fix/Fingerprints.kt @@ -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") } diff --git a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/fix/SpoofSignaturePatch.kt b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/fix/SpoofSignaturePatch.kt new file mode 100644 index 000000000..6dfd31e45 --- /dev/null +++ b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/fix/SpoofSignaturePatch.kt @@ -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(concatSignaturesIndex).registerA + + val expectedSignature = "d6a6dced4a85f24204bf9505ccc1fce114cadb32" + + replaceInstruction(concatSignaturesIndex, "const-string v$register, \"$expectedSignature\"") + } + } +} diff --git a/patches/src/main/kotlin/app/revanced/util/BytecodeUtils.kt b/patches/src/main/kotlin/app/revanced/util/BytecodeUtils.kt index 58cdd9098..16e4a298d 100644 --- a/patches/src/main/kotlin/app/revanced/util/BytecodeUtils.kt +++ b/patches/src/main/kotlin/app/revanced/util/BytecodeUtils.kt @@ -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 Instruction.getReference() = - (this as? ReferenceInstruction)?.reference as? T +inline fun 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 = - findInstructionIndicesReversed { this.opcode == opcode } +fun Method.findInstructionIndicesReversed(opcode: Opcode): List = 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(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 - """ + """, ) }