fix(GmsCore support): Spoof package name (#57)

* fix(YouTube - GMSCore Support): Spoof `requestChecksum` package name

* Apply code review suggestions

* fix(YouTube - GmsCore Support): Add `YouTube` package visibility

* feat(GmsCore support): Add the `android.permission.QUERY_ALL_PACKAGES` permission instead of adding the package name to the <queries> element

* feat(YouTube/Spoof signature): implemented with settings

* Update description

Co-authored-by: KobeW50 <84587632+KobeW50@users.noreply.github.com>

* Update strings.xml

Co-authored-by: KobeW50 <84587632+KobeW50@users.noreply.github.com>

* Update strings.xml

Co-authored-by: KobeW50 <84587632+KobeW50@users.noreply.github.com>

* Update strings.xml

Co-authored-by: KobeW50 <84587632+KobeW50@users.noreply.github.com>

* fix(YouTube/Spoof signature): Instead of using hardcoded package names, use the Manifest's MetaData

* chore: remove unused variable

* fix(YouTube/Spoof signature): Removed from settings, integrated into `GmsCore support` patch

---------

Co-authored-by: inotia00 <108592928+inotia00@users.noreply.github.com>
Co-authored-by: KobeW50 <84587632+KobeW50@users.noreply.github.com>
This commit is contained in:
Hoàng Gia Bảo
2024-06-22 13:56:05 +07:00
committed by GitHub
parent 5911a62d3f
commit 27c40de516
5 changed files with 79 additions and 19 deletions

View File

@ -3,6 +3,7 @@ package app.revanced.patches.shared.gms
import app.revanced.patcher.PatchClass
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.getInstructions
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.fingerprint.MethodFingerprint
@ -13,18 +14,21 @@ import app.revanced.patches.shared.gms.BaseGmsCoreSupportPatch.Constants.PERMISS
import app.revanced.patches.shared.gms.fingerprints.CastContextFetchFingerprint
import app.revanced.patches.shared.gms.fingerprints.CastDynamiteModuleFingerprint
import app.revanced.patches.shared.gms.fingerprints.CastDynamiteModuleV2Fingerprint
import app.revanced.patches.shared.gms.fingerprints.CertificateFingerprint
import app.revanced.patches.shared.gms.fingerprints.CertificateFingerprint.GET_PACKAGE_NAME_METHOD_REFERENCE
import app.revanced.patches.shared.gms.fingerprints.GmsCoreSupportFingerprint
import app.revanced.patches.shared.gms.fingerprints.GmsCoreSupportFingerprint.GET_GMS_CORE_VENDOR_GROUP_ID_METHOD_NAME
import app.revanced.patches.shared.gms.fingerprints.GooglePlayUtilityFingerprint
import app.revanced.patches.shared.gms.fingerprints.PrimeMethodFingerprint
import app.revanced.patches.shared.gms.fingerprints.ServiceCheckFingerprint
import app.revanced.patches.shared.integrations.Constants.PATCHES_PATH
import app.revanced.patches.shared.packagename.PackageNamePatch
import app.revanced.util.getReference
import app.revanced.util.getTargetIndexWithReference
import app.revanced.util.resultOrThrow
import app.revanced.util.returnEarly
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.builder.instruction.BuilderInstruction21c
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction21c
import com.android.tools.smali.dexlib2.iface.reference.StringReference
@ -60,6 +64,7 @@ abstract class BaseGmsCoreSupportPatch(
) + dependencies,
compatiblePackages = compatiblePackages,
fingerprints = setOf(
// Google Play Services.
CastContextFetchFingerprint,
CastDynamiteModuleFingerprint,
CastDynamiteModuleV2Fingerprint,
@ -67,11 +72,21 @@ abstract class BaseGmsCoreSupportPatch(
GooglePlayUtilityFingerprint,
PrimeMethodFingerprint,
ServiceCheckFingerprint,
mainActivityOnCreateFingerprint
// Signature verification.
CertificateFingerprint,
// MainActivity.
mainActivityOnCreateFingerprint,
),
requiresIntegrations = true,
) {
private val gmsCoreVendorGroupId = "app.revanced"
private companion object {
const val GMS_CORE_VENDOR_GROUP_ID = "app.revanced"
const val INTEGRATIONS_CLASS_DESCRIPTOR =
"$PATCHES_PATH/GmsCoreSupport;"
}
override fun execute(context: BytecodeContext) {
val packageName = PackageNamePatch.getPackageName(fromPackageName)
@ -106,14 +121,32 @@ abstract class BaseGmsCoreSupportPatch(
// Verify GmsCore is installed and whitelisted for power optimizations and background usage.
mainActivityOnCreateFingerprint.resultOrThrow().mutableMethod.addInstructions(
1, // Hack to not disturb other patches (such as the YTMusic integrations patch).
"invoke-static/range { p0 .. p0 }, $PATCHES_PATH/GmsCoreSupport;->" +
"invoke-static/range { p0 .. p0 }, $INTEGRATIONS_CLASS_DESCRIPTOR->" +
"checkGmsCore(Landroid/app/Activity;)V",
)
// Change the vendor of GmsCore in ReVanced Integrations.
GmsCoreSupportFingerprint.resultOrThrow().mutableClass.methods
.single { it.name == GET_GMS_CORE_VENDOR_GROUP_ID_METHOD_NAME }
.replaceInstruction(0, "const-string v0, \"$gmsCoreVendorGroupId\"")
GmsCoreSupportFingerprint
.resultOrThrow()
.mutableMethod
.replaceInstruction(0, "const-string v0, \"$GMS_CORE_VENDOR_GROUP_ID\"")
// Spoof signature.
CertificateFingerprint.result?.mutableClass?.methods?.forEach { mutableMethod ->
mutableMethod.apply {
val getPackageNameIndex =
getTargetIndexWithReference(GET_PACKAGE_NAME_METHOD_REFERENCE)
if (getPackageNameIndex > -1) {
val targetRegister = (getInstruction(getPackageNameIndex) as FiveRegisterInstruction).registerC
replaceInstruction(
getPackageNameIndex,
"invoke-static {v$targetRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->spoofPackageName(Landroid/content/Context;)Ljava/lang/String;",
)
}
}
} // Since it has only been confirmed to work on YouTube and YouTube Music, does not raise an exception even if the fingerprint cannot be solved.
}
private fun BytecodeContext.transformStringReferences(transform: (str: String) -> String?) =
@ -163,10 +196,10 @@ abstract class BaseGmsCoreSupportPatch(
in PERMISSIONS,
in ACTIONS,
in AUTHORITIES,
-> referencedString.replace("com.google", gmsCoreVendorGroupId)
-> referencedString.replace("com.google", GMS_CORE_VENDOR_GROUP_ID)
// No vendor prefix for whatever reason...
"subscribedfeeds" -> "$gmsCoreVendorGroupId.subscribedfeeds"
"subscribedfeeds" -> "$GMS_CORE_VENDOR_GROUP_ID.subscribedfeeds"
else -> null
}
@ -179,7 +212,7 @@ abstract class BaseGmsCoreSupportPatch(
if (str.startsWith(uriPrefix)) {
return str.replace(
uriPrefix,
"content://${authority.replace("com.google", gmsCoreVendorGroupId)}",
"content://${authority.replace("com.google", GMS_CORE_VENDOR_GROUP_ID)}",
)
}
}
@ -189,7 +222,7 @@ abstract class BaseGmsCoreSupportPatch(
if (str.startsWith(subFeedsUriPrefix)) {
return str.replace(
subFeedsUriPrefix,
"content://$gmsCoreVendorGroupId.subscribedfeeds"
"content://$GMS_CORE_VENDOR_GROUP_ID.subscribedfeeds"
)
}
}

View File

@ -100,10 +100,17 @@ abstract class BaseGmsCoreSupportResourcePatch(
).replace(
"com.google.android.c2dm",
"$gmsCoreVendorGroupId.android.c2dm",
).replace(
"</queries>",
"<package android:name=\"$gmsCoreVendorGroupId.android.gms\"/></queries>",
),
)
// 'QUERY_ALL_PACKAGES' permission is required,
// To check whether apps such as GmsCore, YouTube or YouTube Music are installed on the device.
xmlEditor["AndroidManifest.xml"].use { editor ->
editor.file.getElementsByTagName("manifest").item(0).also {
it.appendChild(it.ownerDocument.createElement("uses-permission").also { element ->
element.setAttribute("android:name", "android.permission.QUERY_ALL_PACKAGES")
})
}
}
}
}

View File

@ -0,0 +1,20 @@
package app.revanced.patches.shared.gms.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patches.shared.gms.fingerprints.CertificateFingerprint.GET_PACKAGE_NAME_METHOD_REFERENCE
import app.revanced.util.fingerprint.ReferenceFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
/**
* Method which the package name is used to check the app signature.
*/
internal object CertificateFingerprint : ReferenceFingerprint(
returnType = "Ljava/lang/String;",
accessFlags = AccessFlags.PROTECTED or AccessFlags.FINAL,
parameters = emptyList(),
strings = listOf("X.509", "user", "S"),
reference = { GET_PACKAGE_NAME_METHOD_REFERENCE }
) {
const val GET_PACKAGE_NAME_METHOD_REFERENCE =
"Landroid/content/Context;->getPackageName()Ljava/lang/String;"
}

View File

@ -3,9 +3,8 @@ package app.revanced.patches.shared.gms.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
internal object GmsCoreSupportFingerprint : MethodFingerprint(
customFingerprint = { _, classDef ->
classDef.type.endsWith("GmsCoreSupport;")
customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("/GmsCoreSupport;")
&& methodDef.name == "getGmsCoreVendorGroupId"
},
) {
const val GET_GMS_CORE_VENDOR_GROUP_ID_METHOD_NAME = "getGmsCoreVendorGroupId"
}
)