diff --git a/src/main/kotlin/app/revanced/patches/misc/MicroGPatch.kt b/src/main/kotlin/app/revanced/patches/misc/MicroGPatch.kt deleted file mode 100644 index c5e3baac..00000000 --- a/src/main/kotlin/app/revanced/patches/misc/MicroGPatch.kt +++ /dev/null @@ -1,598 +0,0 @@ -package app.revanced.patches.misc - -import app.revanced.extensions.startsWithAny -import app.revanced.patcher.PatcherData -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.extensions.or -import app.revanced.patcher.patch.* -import app.revanced.patcher.proxy -import app.revanced.patcher.proxy.mutableTypes.MutableClass -import app.revanced.patcher.signature.MethodMetadata -import app.revanced.patcher.signature.MethodSignature -import app.revanced.patcher.signature.MethodSignatureMetadata -import app.revanced.patcher.signature.PatternScanMethod -import app.revanced.patcher.smali.toInstruction -import app.revanced.patcher.smali.toInstructions -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode -import org.jf.dexlib2.builder.MutableMethodImplementation -import org.jf.dexlib2.builder.instruction.BuilderInstruction21c -import org.jf.dexlib2.iface.instruction.formats.Instruction21c -import org.jf.dexlib2.iface.reference.StringReference -import org.jf.dexlib2.immutable.reference.ImmutableStringReference - -private const val BASE_MICROG_PACKAGE_NAME = "com.mgoogle" -private const val BASE_REVANCED_PACKAGE_NAME = "app.revanced.android.youtube" - -private val compatiblePackages = listOf( - PackageMetadata( - "com.google.android.youtube", listOf("17.14.35") - ) -) - -private val metadata = PatchMetadata( - "microg", - "MicroG Patch", - "Patch to allow YouTube ReVanced to run without root and under a different package name.", - compatiblePackages, - "0.0.1" -) - -private val description = "Signature required for ${metadata.name}." - -enum class StringReplaceMode { - REPLACE_WITH_MICROG, REPLACE_WITH_REVANCED, DO_NOT_REPLACE -} - -class MicroGPatch : Patch( - metadata, listOf( - MethodSignature( - MethodSignatureMetadata( - "google-play-sig-check-method", - MethodMetadata("Ldsf;", "d"), - PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value. - compatiblePackages, - description, - "0.0.1" - ), "L", AccessFlags.PUBLIC or AccessFlags.STATIC, listOf("L", "L"), listOf( - Opcode.MOVE_OBJECT_FROM16, - Opcode.CONST_STRING, - Opcode.CONST_STRING, - Opcode.NEW_INSTANCE, - Opcode.MOVE_OBJECT_FROM16, - Opcode.INVOKE_DIRECT, - Opcode.CONST_4, - Opcode.CONST_STRING, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IF_EQ, - Opcode.IGET_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.SGET, - Opcode.IGET_OBJECT, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_WIDE, - Opcode.CONST_WIDE, - Opcode.CONST_STRING, - Opcode.CONST_4, - Opcode.CONST_STRING, - Opcode.CONST_4, - Opcode.CMP_LONG, - Opcode.IF_GEZ, - Opcode.CONST_16, - Opcode.GOTO_16, - Opcode.CONST_STRING, - Opcode.IGET_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CONST_16, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.GOTO, - Opcode.MOVE_EXCEPTION, - Opcode.CONST_STRING, - Opcode.INVOKE_STATIC, - Opcode.CONST_4, - Opcode.IGET_OBJECT, - Opcode.IF_EQZ, - Opcode.CONST_STRING, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT, - Opcode.CONST, - Opcode.IF_NE, - Opcode.CONST_16, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.SGET_OBJECT, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IF_NEZ, - Opcode.CONST_STRING, - Opcode.GOTO, - Opcode.NEW_ARRAY - ), listOf("This should never happen.", "GooglePlayServicesUtil", "Google Play Store signature invalid.") - ), MethodSignature( - MethodSignatureMetadata( - "google-play-service-checker-method", - MethodMetadata("Llpe;", "d"), - PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value. - compatiblePackages, - description, - "0.0.1" - ), "V", AccessFlags.PUBLIC or AccessFlags.STATIC, listOf("L", "I"), listOf( - Opcode.SGET_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT, - Opcode.IF_EQZ, - Opcode.SGET_OBJECT, - Opcode.CONST_STRING, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.NEW_INSTANCE, - Opcode.INVOKE_DIRECT, - Opcode.CONST_STRING, - Opcode.INVOKE_VIRTUAL, - Opcode.INVOKE_VIRTUAL, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CONST_STRING, - Opcode.INVOKE_STATIC, - Opcode.IF_NEZ, - Opcode.NEW_INSTANCE, - Opcode.INVOKE_DIRECT, - Opcode.THROW, - Opcode.NEW_INSTANCE, - Opcode.CONST_STRING, - Opcode.INVOKE_DIRECT, - Opcode.THROW, - Opcode.RETURN_VOID - ), listOf("Google Play Services not available") - ), MethodSignature( - MethodSignatureMetadata( - "google-play-utility-method", - MethodMetadata("Llpe;", "b"), - PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value. - compatiblePackages, - description, - "0.0.1" - ), "I", AccessFlags.PUBLIC or AccessFlags.STATIC, listOf("L", "L"), listOf( - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.GOTO, - Opcode.CONST_STRING, - Opcode.CONST_STRING, - Opcode.INVOKE_STATIC, - Opcode.CONST_STRING, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT, - Opcode.CONST_4, - Opcode.IF_NEZ, - Opcode.SGET_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT, - Opcode.IF_EQZ, - Opcode.GOTO, - Opcode.SGET_OBJECT, - Opcode.MONITOR_ENTER, - Opcode.SGET_BOOLEAN, - Opcode.IF_EQZ, - Opcode.MONITOR_EXIT, - Opcode.GOTO, - Opcode.SPUT_BOOLEAN, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CONST_16, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IGET_OBJECT, - Opcode.IF_NEZ, - Opcode.MONITOR_EXIT, - Opcode.GOTO, - Opcode.CONST_STRING, - Opcode.INVOKE_VIRTUAL, - Opcode.CONST_STRING, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT, - Opcode.SPUT, - Opcode.GOTO, - Opcode.MOVE_EXCEPTION, - Opcode.CONST_STRING, - Opcode.CONST_STRING, - Opcode.INVOKE_STATIC, - Opcode.MONITOR_EXIT, - Opcode.SGET, - Opcode.IF_EQZ, - Opcode.CONST, - Opcode.IF_NE, - Opcode.GOTO, - Opcode.NEW_INSTANCE, - Opcode.INVOKE_DIRECT, - Opcode.THROW, - Opcode.NEW_INSTANCE, - Opcode.INVOKE_DIRECT, - Opcode.THROW, - Opcode.MOVE_EXCEPTION, - Opcode.MONITOR_EXIT, - Opcode.THROW, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT, - Opcode.CONST_4, - Opcode.IF_NEZ, - Opcode.SGET_OBJECT, - Opcode.IF_NEZ, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CONST_STRING, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT, - Opcode.IF_NEZ, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CONST_STRING, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT, - Opcode.IF_EQZ, - Opcode.GOTO, - Opcode.CONST_4, - Opcode.GOTO, - Opcode.CONST_4, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.SPUT_OBJECT, - Opcode.SGET_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT, - Opcode.IF_NEZ, - Opcode.CONST_4, - Opcode.GOTO, - Opcode.CONST_4, - Opcode.INVOKE_STATIC, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CONST_16, - Opcode.IF_EQZ, - Opcode.CONST_STRING, - Opcode.CONST_16, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.GOTO, - Opcode.CONST_STRING, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CONST_STRING, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_STATIC, - Opcode.CONST_16, - Opcode.GOTO_16, - Opcode.CONST_4, - Opcode.CONST_STRING, - Opcode.CONST_16, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_STATIC, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT, - Opcode.IF_NEZ, - Opcode.CONST_STRING, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CONST_STRING, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_STATIC, - Opcode.GOTO, - Opcode.IF_EQZ, - Opcode.INVOKE_STATIC, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT, - Opcode.IF_NEZ, - Opcode.CONST_STRING, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CONST_STRING, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_STATIC, - Opcode.GOTO, - Opcode.IF_EQZ, - Opcode.IF_EQZ, - Opcode.IGET_OBJECT, - Opcode.AGET_OBJECT, - Opcode.IGET_OBJECT, - Opcode.AGET_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT, - Opcode.IF_NEZ, - Opcode.CONST_STRING, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CONST_STRING, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_STATIC, - Opcode.GOTO, - Opcode.IGET, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT, - Opcode.IF_GE, - Opcode.IGET, - Opcode.NEW_INSTANCE, - Opcode.INVOKE_DIRECT, - Opcode.CONST_STRING, - Opcode.INVOKE_VIRTUAL, - Opcode.INVOKE_VIRTUAL, - Opcode.CONST_STRING, - Opcode.INVOKE_VIRTUAL, - Opcode.INVOKE_VIRTUAL, - Opcode.CONST_STRING, - Opcode.INVOKE_VIRTUAL, - Opcode.INVOKE_VIRTUAL, - Opcode.CONST_STRING, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_STATIC, - Opcode.CONST_4, - Opcode.GOTO, - Opcode.IGET_OBJECT, - Opcode.IF_NEZ, - Opcode.CONST_STRING, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.GOTO, - Opcode.MOVE_EXCEPTION, - Opcode.CONST_STRING, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CONST_STRING, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_STATIC, - Opcode.GOTO, - Opcode.IGET_BOOLEAN, - Opcode.IF_NEZ, - Opcode.CONST_4, - Opcode.GOTO, - Opcode.RETURN, - Opcode.CONST_STRING, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CONST_STRING, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_STATIC, - Opcode.RETURN - ), listOf("This should never happen.", "MetadataValueReader", "com.google.android.gms") - ), MethodSignature( - MethodSignatureMetadata( - "google-play-prime-method", - MethodMetadata("Louy;", "e"), - PatternScanMethod.Direct(), - compatiblePackages, - description, - "0.0.1" - ), null, null, null, null, listOf("com.google.android.GoogleCamera", "com.android.vending") - ) - ) -) { - override fun execute(patcherData: PatcherData): PatchResult { - // smali patches - disablePlayServiceChecks() - patcherData.classes.forEach { classDef -> - var proxiedClass: MutableClass? = null - - classDef.methods.forEach methodLoop@{ method -> - val implementation = method.implementation ?: return@methodLoop - - var proxiedImplementation: MutableMethodImplementation? = null - - implementation.instructions.forEachIndexed { i, instruction -> - if (instruction.opcode == Opcode.CONST_STRING) { - val stringValue = ((instruction as Instruction21c).reference as StringReference).string - - val replaceMode = - if (stringValue.startsWith("com.google.android.gms.chimera.container")) // https://github.com/TeamVanced/VancedMicroG/pull/139/file - StringReplaceMode.DO_NOT_REPLACE - else if (stringValue == "com.google" || stringValue.startsWithAny( - "com.google.android.gms.auth.accounts", - "com.google.android.gms.chimera", - "com.google.android.c2dm", - "com.google.android.c2dm", - "com.google.android.gsf", - "com.google.android.c2dm", - "com.google.iid", - "content://com.google.settings" - ) - ) { - StringReplaceMode.REPLACE_WITH_MICROG - } else if (stringValue.startsWithAny( - "com.google.android.youtube.SuggestionsProvider", - "com.google.android.youtube.fileprovider" - ) - ) { - StringReplaceMode.REPLACE_WITH_REVANCED - } else { - StringReplaceMode.DO_NOT_REPLACE - } - - - if (replaceMode != StringReplaceMode.DO_NOT_REPLACE) { - if (proxiedClass == null) { - proxiedClass = patcherData.proxy(classDef).resolve() - } - - if (proxiedImplementation == null) { - proxiedImplementation = - proxiedClass!!.methods.first { - it.name == method.name && it.parameterTypes.containsAll(method.parameterTypes) - }.implementation!! - } - - val newString = - if (replaceMode == StringReplaceMode.REPLACE_WITH_REVANCED) stringValue.replace( - "com.google.android.youtube", BASE_REVANCED_PACKAGE_NAME - ) - else stringValue.replace("com.google", BASE_MICROG_PACKAGE_NAME) - - proxiedImplementation!!.replaceInstruction( - i, BuilderInstruction21c( - Opcode.CONST_STRING, instruction.registerA, ImmutableStringReference(newString) - ) - ) - } - - // TODO: phenotype reference -> microg reference - //if (instruction is ReferenceInstruction) { - // val proxy = patcherData.proxy(classDef).resolve() - // val implementation = proxy.methods.first { it.name == method.name }.implementation!! - // when (instruction.referenceType) { - // ReferenceType.METHOD -> { - // val reference = instruction.reference as MethodReference - // if (!reference.name.startsWith("com.google.android.gms.phenotype")) return@forEachIndexed - - // val modifiedReference = ImmutableMethodReference( - // reference.definingClass.replace("com.google", BASE_MICROG_PACKAGE_NAME), - // reference.name, - // reference.parameterTypes.map { - // it.toString().replace("com.google", BASE_MICROG_PACKAGE_NAME) - // }, - // reference.returnType.replace("com.google", BASE_MICROG_PACKAGE_NAME), - // ); - - // val newInstruction = when (instruction.opcode.format) { - // Format.Format35c -> { - // val instruction35c = instruction as Instruction35c - // BuilderInstruction35c( - // instruction.opcode, - // instruction35c.registerCount, - // instruction35c.registerC, - // instruction35c.registerD, - // instruction35c.registerE, - // instruction35c.registerF, - // instruction35c.registerG, - // modifiedReference - // ) - // } - // Format.Format3rc -> - // BuilderInstruction3rc( - // instruction.opcode, - // ) - // Format.Format45cc -> - // BuilderInstruction45cc( - // instruction.opcode, - // ) - // Format.Format4rcc -> - // BuilderInstruction4rcc( - // instruction.opcode, - // ) - // } - // implementation.replaceInstruction( - // i, - - // ) - // } - // ReferenceType.METHOD_PROTO -> { - - // } - // ReferenceType.TYPE -> { - - // } - // ReferenceType.CALL_SITE -> { - - // } - // ReferenceType.METHOD_HANDLE -> { - - // } - // ReferenceType.FIELD -> { - - // } - // ReferenceType.NONE -> { - - // } - // } - //} - - } - } - } - } - - // replace string back - val implementation = signatures.elementAt(2).result!!.findParentMethod( - MethodSignature( - MethodSignatureMetadata( - "do-not-replace-method", - MethodMetadata("Llpe;", "c"), - PatternScanMethod.Direct(), - compatiblePackages, - description, - "0.0.1" - ), "L", AccessFlags.PUBLIC or AccessFlags.STATIC, listOf("L"), null, listOf("com.google.android.gms") - ) - )!!.method.implementation!! - - implementation.replaceInstruction( - implementation.instructions.indexOfFirst { it.opcode == Opcode.CONST_STRING }, - "const-string v0, \"com.google.android.gms\"".toInstruction() - ) - - // allow GC to clean unused/ replaced immutable class definitions after this call - patcherData.classes.applyProxies() - - // TODO: resource patches - return PatchResultSuccess() - - } - - private fun disablePlayServiceChecks() { - for (i in 0 until signatures.count() - 1) { - val result = signatures.elementAt(i).result!! - val stringInstructions = when (result.immutableMethod.returnType.first()) { - 'L' -> """ - const/4 v0, 0x0 - return-object v0 - """ - 'V' -> "return-void" - 'I' -> """ - const/4 v0, 0x0 - return v0 - """ - else -> throw Exception("This case should never happen.") - } - result.method.implementation!!.addInstructions( - 0, stringInstructions.trimIndent().toInstructions() - ) - } - - val implementation = signatures.last().result!!.method.implementation!! - - var register = 2 - val index = implementation.instructions.indexOfFirst { - if (it.opcode != Opcode.CONST_STRING) return@indexOfFirst false - - val instructionString = ((it as Instruction21c).reference as StringReference).string - if (instructionString != "com.google.android.youtube") return@indexOfFirst false - - register = it.registerA - return@indexOfFirst true - } - - implementation.replaceInstruction( - index, "const-string v$register, \"$BASE_REVANCED_PACKAGE_NAME\"".toInstruction() - ) - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/MicroGPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/MicroGPatch.kt deleted file mode 100644 index cfe93b4a..00000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/MicroGPatch.kt +++ /dev/null @@ -1,602 +0,0 @@ -package app.revanced.patches.youtube.misc - -import app.revanced.extensions.startsWithAny -import app.revanced.patcher.data.implementation.BytecodeData -import app.revanced.patcher.data.implementation.proxy -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.extensions.or -import app.revanced.patcher.patch.implementation.BytecodePatch -import app.revanced.patcher.patch.implementation.metadata.PackageMetadata -import app.revanced.patcher.patch.implementation.metadata.PatchMetadata -import app.revanced.patcher.patch.implementation.misc.PatchResult -import app.revanced.patcher.patch.implementation.misc.PatchResultSuccess -import app.revanced.patcher.proxy.mutableTypes.MutableClass -import app.revanced.patcher.signature.MethodMetadata -import app.revanced.patcher.signature.MethodSignature -import app.revanced.patcher.signature.MethodSignatureMetadata -import app.revanced.patcher.signature.PatternScanMethod -import app.revanced.patcher.smali.toInstruction -import app.revanced.patcher.smali.toInstructions -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode -import org.jf.dexlib2.builder.MutableMethodImplementation -import org.jf.dexlib2.builder.instruction.BuilderInstruction21c -import org.jf.dexlib2.iface.instruction.formats.Instruction21c -import org.jf.dexlib2.iface.reference.StringReference -import org.jf.dexlib2.immutable.reference.ImmutableStringReference - -private const val BASE_MICROG_PACKAGE_NAME = "com.mgoogle" -private const val BASE_REVANCED_PACKAGE_NAME = "app.revanced.android.youtube" - -private val compatiblePackages = listOf( - PackageMetadata( - "com.google.android.youtube", listOf("17.14.35") - ) -) - -private val metadata = PatchMetadata( - "microg", - "MicroG Patch", - "Patch to allow YouTube ReVanced to run without root and under a different package name.", - compatiblePackages, - "0.0.1" -) - -private val description = "Signature required for ${metadata.name}." - -enum class StringReplaceMode { - REPLACE_WITH_MICROG, REPLACE_WITH_REVANCED, DO_NOT_REPLACE -} - -class MicroGPatch : BytecodePatch( - metadata, listOf( - MethodSignature( - MethodSignatureMetadata( - "google-play-sig-check-method", - MethodMetadata("Ldsf;", "d"), - PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value. - compatiblePackages, - description, - "0.0.1" - ), "L", AccessFlags.PUBLIC or AccessFlags.STATIC, listOf("L", "L"), listOf( - Opcode.MOVE_OBJECT_FROM16, - Opcode.CONST_STRING, - Opcode.CONST_STRING, - Opcode.NEW_INSTANCE, - Opcode.MOVE_OBJECT_FROM16, - Opcode.INVOKE_DIRECT, - Opcode.CONST_4, - Opcode.CONST_STRING, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IF_EQ, - Opcode.IGET_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.SGET, - Opcode.IGET_OBJECT, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_WIDE, - Opcode.CONST_WIDE, - Opcode.CONST_STRING, - Opcode.CONST_4, - Opcode.CONST_STRING, - Opcode.CONST_4, - Opcode.CMP_LONG, - Opcode.IF_GEZ, - Opcode.CONST_16, - Opcode.GOTO_16, - Opcode.CONST_STRING, - Opcode.IGET_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CONST_16, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.GOTO, - Opcode.MOVE_EXCEPTION, - Opcode.CONST_STRING, - Opcode.INVOKE_STATIC, - Opcode.CONST_4, - Opcode.IGET_OBJECT, - Opcode.IF_EQZ, - Opcode.CONST_STRING, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT, - Opcode.CONST, - Opcode.IF_NE, - Opcode.CONST_16, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.SGET_OBJECT, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IF_NEZ, - Opcode.CONST_STRING, - Opcode.GOTO, - Opcode.NEW_ARRAY - ), listOf("This should never happen.", "GooglePlayServicesUtil", "Google Play Store signature invalid.") - ), MethodSignature( - MethodSignatureMetadata( - "google-play-service-checker-method", - MethodMetadata("Llpe;", "d"), - PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value. - compatiblePackages, - description, - "0.0.1" - ), "V", AccessFlags.PUBLIC or AccessFlags.STATIC, listOf("L", "I"), listOf( - Opcode.SGET_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT, - Opcode.IF_EQZ, - Opcode.SGET_OBJECT, - Opcode.CONST_STRING, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.NEW_INSTANCE, - Opcode.INVOKE_DIRECT, - Opcode.CONST_STRING, - Opcode.INVOKE_VIRTUAL, - Opcode.INVOKE_VIRTUAL, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CONST_STRING, - Opcode.INVOKE_STATIC, - Opcode.IF_NEZ, - Opcode.NEW_INSTANCE, - Opcode.INVOKE_DIRECT, - Opcode.THROW, - Opcode.NEW_INSTANCE, - Opcode.CONST_STRING, - Opcode.INVOKE_DIRECT, - Opcode.THROW, - Opcode.RETURN_VOID - ), listOf("Google Play Services not available") - ), MethodSignature( - MethodSignatureMetadata( - "google-play-utility-method", - MethodMetadata("Llpe;", "b"), - PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value. - compatiblePackages, - description, - "0.0.1" - ), "I", AccessFlags.PUBLIC or AccessFlags.STATIC, listOf("L", "L"), listOf( - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.GOTO, - Opcode.CONST_STRING, - Opcode.CONST_STRING, - Opcode.INVOKE_STATIC, - Opcode.CONST_STRING, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT, - Opcode.CONST_4, - Opcode.IF_NEZ, - Opcode.SGET_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT, - Opcode.IF_EQZ, - Opcode.GOTO, - Opcode.SGET_OBJECT, - Opcode.MONITOR_ENTER, - Opcode.SGET_BOOLEAN, - Opcode.IF_EQZ, - Opcode.MONITOR_EXIT, - Opcode.GOTO, - Opcode.SPUT_BOOLEAN, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CONST_16, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IGET_OBJECT, - Opcode.IF_NEZ, - Opcode.MONITOR_EXIT, - Opcode.GOTO, - Opcode.CONST_STRING, - Opcode.INVOKE_VIRTUAL, - Opcode.CONST_STRING, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT, - Opcode.SPUT, - Opcode.GOTO, - Opcode.MOVE_EXCEPTION, - Opcode.CONST_STRING, - Opcode.CONST_STRING, - Opcode.INVOKE_STATIC, - Opcode.MONITOR_EXIT, - Opcode.SGET, - Opcode.IF_EQZ, - Opcode.CONST, - Opcode.IF_NE, - Opcode.GOTO, - Opcode.NEW_INSTANCE, - Opcode.INVOKE_DIRECT, - Opcode.THROW, - Opcode.NEW_INSTANCE, - Opcode.INVOKE_DIRECT, - Opcode.THROW, - Opcode.MOVE_EXCEPTION, - Opcode.MONITOR_EXIT, - Opcode.THROW, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT, - Opcode.CONST_4, - Opcode.IF_NEZ, - Opcode.SGET_OBJECT, - Opcode.IF_NEZ, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CONST_STRING, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT, - Opcode.IF_NEZ, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CONST_STRING, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT, - Opcode.IF_EQZ, - Opcode.GOTO, - Opcode.CONST_4, - Opcode.GOTO, - Opcode.CONST_4, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.SPUT_OBJECT, - Opcode.SGET_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT, - Opcode.IF_NEZ, - Opcode.CONST_4, - Opcode.GOTO, - Opcode.CONST_4, - Opcode.INVOKE_STATIC, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CONST_16, - Opcode.IF_EQZ, - Opcode.CONST_STRING, - Opcode.CONST_16, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.GOTO, - Opcode.CONST_STRING, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CONST_STRING, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_STATIC, - Opcode.CONST_16, - Opcode.GOTO_16, - Opcode.CONST_4, - Opcode.CONST_STRING, - Opcode.CONST_16, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_STATIC, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT, - Opcode.IF_NEZ, - Opcode.CONST_STRING, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CONST_STRING, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_STATIC, - Opcode.GOTO, - Opcode.IF_EQZ, - Opcode.INVOKE_STATIC, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT, - Opcode.IF_NEZ, - Opcode.CONST_STRING, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CONST_STRING, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_STATIC, - Opcode.GOTO, - Opcode.IF_EQZ, - Opcode.IF_EQZ, - Opcode.IGET_OBJECT, - Opcode.AGET_OBJECT, - Opcode.IGET_OBJECT, - Opcode.AGET_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT, - Opcode.IF_NEZ, - Opcode.CONST_STRING, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CONST_STRING, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_STATIC, - Opcode.GOTO, - Opcode.IGET, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT, - Opcode.IF_GE, - Opcode.IGET, - Opcode.NEW_INSTANCE, - Opcode.INVOKE_DIRECT, - Opcode.CONST_STRING, - Opcode.INVOKE_VIRTUAL, - Opcode.INVOKE_VIRTUAL, - Opcode.CONST_STRING, - Opcode.INVOKE_VIRTUAL, - Opcode.INVOKE_VIRTUAL, - Opcode.CONST_STRING, - Opcode.INVOKE_VIRTUAL, - Opcode.INVOKE_VIRTUAL, - Opcode.CONST_STRING, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_STATIC, - Opcode.CONST_4, - Opcode.GOTO, - Opcode.IGET_OBJECT, - Opcode.IF_NEZ, - Opcode.CONST_STRING, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.GOTO, - Opcode.MOVE_EXCEPTION, - Opcode.CONST_STRING, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CONST_STRING, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_STATIC, - Opcode.GOTO, - Opcode.IGET_BOOLEAN, - Opcode.IF_NEZ, - Opcode.CONST_4, - Opcode.GOTO, - Opcode.RETURN, - Opcode.CONST_STRING, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CONST_STRING, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_STATIC, - Opcode.RETURN - ), listOf("This should never happen.", "MetadataValueReader", "com.google.android.gms") - ), MethodSignature( - MethodSignatureMetadata( - "google-play-prime-method", - MethodMetadata("Louy;", "e"), - PatternScanMethod.Direct(), - compatiblePackages, - description, - "0.0.1" - ), null, null, null, null, listOf("com.google.android.GoogleCamera", "com.android.vending") - ) - ) -) { - override fun execute(data: BytecodeData): PatchResult { - // smali patches - disablePlayServiceChecks() - data.classes.forEach { classDef -> - var proxiedClass: MutableClass? = null - - classDef.methods.forEach methodLoop@{ method -> - val implementation = method.implementation ?: return@methodLoop - - var proxiedImplementation: MutableMethodImplementation? = null - - implementation.instructions.forEachIndexed { i, instruction -> - if (instruction.opcode == Opcode.CONST_STRING) { - val stringValue = ((instruction as Instruction21c).reference as StringReference).string - - val replaceMode = - if (stringValue.startsWith("com.google.android.gms.chimera.container")) // https://github.com/TeamVanced/VancedMicroG/pull/139/file - StringReplaceMode.DO_NOT_REPLACE - else if (stringValue == "com.google" || stringValue.startsWithAny( - "com.google.android.gms.auth.accounts", - "com.google.android.gms.chimera", - "com.google.android.c2dm", - "com.google.android.c2dm", - "com.google.android.gsf", - "com.google.android.c2dm", - "com.google.iid", - "content://com.google.settings" - ) - ) { - StringReplaceMode.REPLACE_WITH_MICROG - } else if (stringValue.startsWithAny( - "com.google.android.youtube.SuggestionsProvider", - "com.google.android.youtube.fileprovider" - ) - ) { - StringReplaceMode.REPLACE_WITH_REVANCED - } else { - StringReplaceMode.DO_NOT_REPLACE - } - - - if (replaceMode != StringReplaceMode.DO_NOT_REPLACE) { - if (proxiedClass == null) { - proxiedClass = data.proxy(classDef).resolve() - } - - if (proxiedImplementation == null) { - proxiedImplementation = - proxiedClass!!.methods.first { - it.name == method.name && it.parameterTypes.containsAll(method.parameterTypes) - }.implementation!! - } - - val newString = - if (replaceMode == StringReplaceMode.REPLACE_WITH_REVANCED) stringValue.replace( - "com.google.android.youtube", BASE_REVANCED_PACKAGE_NAME - ) - else stringValue.replace("com.google", BASE_MICROG_PACKAGE_NAME) - - proxiedImplementation!!.replaceInstruction( - i, BuilderInstruction21c( - Opcode.CONST_STRING, instruction.registerA, ImmutableStringReference(newString) - ) - ) - } - - // TODO: phenotype reference -> microg reference - //if (instruction is ReferenceInstruction) { - // val proxy = patcherData.proxy(classDef).resolve() - // val implementation = proxy.methods.first { it.name == method.name }.implementation!! - // when (instruction.referenceType) { - // ReferenceType.METHOD -> { - // val reference = instruction.reference as MethodReference - // if (!reference.name.startsWith("com.google.android.gms.phenotype")) return@forEachIndexed - - // val modifiedReference = ImmutableMethodReference( - // reference.definingClass.replace("com.google", BASE_MICROG_PACKAGE_NAME), - // reference.name, - // reference.parameterTypes.map { - // it.toString().replace("com.google", BASE_MICROG_PACKAGE_NAME) - // }, - // reference.returnType.replace("com.google", BASE_MICROG_PACKAGE_NAME), - // ); - - // val newInstruction = when (instruction.opcode.format) { - // Format.Format35c -> { - // val instruction35c = instruction as Instruction35c - // BuilderInstruction35c( - // instruction.opcode, - // instruction35c.registerCount, - // instruction35c.registerC, - // instruction35c.registerD, - // instruction35c.registerE, - // instruction35c.registerF, - // instruction35c.registerG, - // modifiedReference - // ) - // } - // Format.Format3rc -> - // BuilderInstruction3rc( - // instruction.opcode, - // ) - // Format.Format45cc -> - // BuilderInstruction45cc( - // instruction.opcode, - // ) - // Format.Format4rcc -> - // BuilderInstruction4rcc( - // instruction.opcode, - // ) - // } - // implementation.replaceInstruction( - // i, - - // ) - // } - // ReferenceType.METHOD_PROTO -> { - - // } - // ReferenceType.TYPE -> { - - // } - // ReferenceType.CALL_SITE -> { - - // } - // ReferenceType.METHOD_HANDLE -> { - - // } - // ReferenceType.FIELD -> { - - // } - // ReferenceType.NONE -> { - - // } - // } - //} - - } - } - } - } - - // replace string back - val implementation = signatures.elementAt(2).result!!.findParentMethod( - MethodSignature( - MethodSignatureMetadata( - "do-not-replace-method", - MethodMetadata("Llpe;", "c"), - PatternScanMethod.Direct(), - compatiblePackages, - description, - "0.0.1" - ), "L", AccessFlags.PUBLIC or AccessFlags.STATIC, listOf("L"), null, listOf("com.google.android.gms") - ) - )!!.method.implementation!! - - implementation.replaceInstruction( - implementation.instructions.indexOfFirst { it.opcode == Opcode.CONST_STRING }, - "const-string v0, \"com.google.android.gms\"".toInstruction() - ) - - // allow GC to clean unused/ replaced immutable class definitions after this call - data.classes.applyProxies() - - // TODO: resource patches - return PatchResultSuccess() - - } - - private fun disablePlayServiceChecks() { - for (i in 0 until signatures.count() - 1) { - val result = signatures.elementAt(i).result!! - val stringInstructions = when (result.immutableMethod.returnType.first()) { - 'L' -> """ - const/4 v0, 0x0 - return-object v0 - """ - 'V' -> "return-void" - 'I' -> """ - const/4 v0, 0x0 - return v0 - """ - else -> throw Exception("This case should never happen.") - } - result.method.implementation!!.addInstructions( - 0, stringInstructions.trimIndent().toInstructions() - ) - } - - val implementation = signatures.last().result!!.method.implementation!! - - var register = 2 - val index = implementation.instructions.indexOfFirst { - if (it.opcode != Opcode.CONST_STRING) return@indexOfFirst false - - val instructionString = ((it as Instruction21c).reference as StringReference).string - if (instructionString != "com.google.android.youtube") return@indexOfFirst false - - register = it.registerA - return@indexOfFirst true - } - - implementation.replaceInstruction( - index, "const-string v$register, \"$BASE_REVANCED_PACKAGE_NAME\"".toInstruction() - ) - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/patch/IntegrationsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/patch/IntegrationsPatch.kt index 25bfe66e..a396e0d1 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/patch/IntegrationsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/patch/IntegrationsPatch.kt @@ -13,7 +13,7 @@ import app.revanced.patcher.patch.implementation.misc.PatchResultSuccess import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable import app.revanced.patcher.util.smali.toInstructions import app.revanced.patches.youtube.misc.integrations.annotations.IntegrationsCompatibility -import app.revanced.patches.youtube.misc.integrations.signatures.InitSignature +import app.revanced.patches.youtube.misc.microg.signatures.IntegrityCheckSignature import org.jf.dexlib2.AccessFlags import org.jf.dexlib2.immutable.ImmutableMethod import org.jf.dexlib2.immutable.ImmutableMethodImplementation @@ -25,7 +25,7 @@ import org.jf.dexlib2.immutable.ImmutableMethodImplementation @Version("0.0.1") class IntegrationsPatch : BytecodePatch( listOf( - InitSignature + IntegrityCheckSignature ) ) { override fun execute(data: BytecodeData): PatchResult { diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/manifest/patch/FixLocaleConfigErrorPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/manifest/patch/FixLocaleConfigErrorPatch.kt index df1233d9..e7491ca1 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/manifest/patch/FixLocaleConfigErrorPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/manifest/patch/FixLocaleConfigErrorPatch.kt @@ -8,32 +8,31 @@ import app.revanced.patcher.patch.annotations.Patch import app.revanced.patcher.patch.implementation.ResourcePatch import app.revanced.patcher.patch.implementation.misc.PatchResult import app.revanced.patcher.patch.implementation.misc.PatchResultSuccess -import app.revanced.patches.youtube.misc.manifest.annotations.FixLocaleConfigErrorCompatibility +import app.revanced.patches.youtube.misc.microg.annotations.MicroGPatchCompatibility import org.w3c.dom.Element @Patch @Name("locale-config-fix") @Description("Fix an error when building the resources by patching the manifest file.") -@FixLocaleConfigErrorCompatibility +@MicroGPatchCompatibility @Version("0.0.1") class FixLocaleConfigErrorPatch : ResourcePatch() { override fun execute(data: ResourceData): PatchResult { // create an xml editor instance - val editor = data.getXmlEditor("AndroidManifest.xml") + data.getXmlEditor("AndroidManifest.xml").use { + // edit the application nodes attribute... + val applicationNode = it + .file + .getElementsByTagName("application") + .item(0) as Element - // edit the application nodes attribute... - val applicationNode = editor - .file - .getElementsByTagName("application") - .item(0) as Element - // by replacing the attributes name - val attribute = "android:localeConfig" - applicationNode.setAttribute("localeConfig", applicationNode.getAttribute(attribute)) - applicationNode.removeAttribute("android:localeConfig") + // by replacing the attributes name + val attribute = "android:localeConfig" + applicationNode.setAttribute("localeConfig", applicationNode.getAttribute(attribute)) + applicationNode.removeAttribute("android:localeConfig") - // close & save the modified file - editor.close() + } return PatchResultSuccess() } diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/annotations/MicroGPatchCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/microg/annotations/MicroGPatchCompatibility.kt new file mode 100644 index 00000000..b5f9ef99 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/microg/annotations/MicroGPatchCompatibility.kt @@ -0,0 +1,13 @@ +package app.revanced.patches.youtube.misc.microg.annotations + +import app.revanced.patcher.annotation.Compatibility +import app.revanced.patcher.annotation.Package + +@Compatibility( + [Package( + "com.google.android.youtube", arrayOf("17.14.35", "17.19.36") + )] +) +@Target(AnnotationTarget.CLASS) +@Retention(AnnotationRetention.RUNTIME) +internal annotation class MicroGPatchCompatibility \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/patch/bytecode/MicroGBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/microg/patch/bytecode/MicroGBytecodePatch.kt new file mode 100644 index 00000000..2a990c86 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/microg/patch/bytecode/MicroGBytecodePatch.kt @@ -0,0 +1,173 @@ +package app.revanced.patches.youtube.misc.microg.patch.bytecode + +import app.revanced.extensions.startsWithAny +import app.revanced.patcher.annotation.Description +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.data.implementation.BytecodeData +import app.revanced.patcher.data.implementation.proxy +import app.revanced.patcher.extensions.addInstructions +import app.revanced.patcher.extensions.or +import app.revanced.patcher.patch.annotations.Patch +import app.revanced.patcher.patch.implementation.BytecodePatch +import app.revanced.patcher.patch.implementation.misc.PatchResult +import app.revanced.patcher.patch.implementation.misc.PatchResultSuccess +import app.revanced.patcher.signature.implementation.method.MethodSignature +import app.revanced.patcher.signature.implementation.method.annotation.DirectPatternScanMethod +import app.revanced.patcher.signature.implementation.method.annotation.MatchingMethod +import app.revanced.patcher.util.proxy.mutableTypes.MutableClass +import app.revanced.patcher.util.smali.toInstruction +import app.revanced.patcher.util.smali.toInstructions +import app.revanced.patches.youtube.misc.microg.annotations.MicroGPatchCompatibility +import app.revanced.patches.youtube.misc.microg.patch.resource.enum.StringReplaceMode +import app.revanced.patches.youtube.misc.microg.shared.Constants.BASE_MICROG_PACKAGE_NAME +import app.revanced.patches.youtube.misc.microg.shared.Constants.BASE_REVANCED_PACKAGE_NAME +import app.revanced.patches.youtube.misc.microg.signatures.GooglePlayUtilitySignature +import app.revanced.patches.youtube.misc.microg.signatures.IntegrityCheckSignature +import app.revanced.patches.youtube.misc.microg.signatures.PrimeSignature +import app.revanced.patches.youtube.misc.microg.signatures.ServiceCheckSignature +import org.jf.dexlib2.AccessFlags +import org.jf.dexlib2.Opcode +import org.jf.dexlib2.builder.MutableMethodImplementation +import org.jf.dexlib2.builder.instruction.BuilderInstruction21c +import org.jf.dexlib2.iface.instruction.formats.Instruction21c +import org.jf.dexlib2.iface.reference.StringReference +import org.jf.dexlib2.immutable.reference.ImmutableStringReference + +@Patch +@Name("microg-bytecode-patch") +@Description("Patch to allow YouTube ReVanced to run without root and under a different package name.") +@MicroGPatchCompatibility +@Version("0.0.1") +class MicroGBytecodePatch : BytecodePatch( + listOf( + IntegrityCheckSignature, ServiceCheckSignature, GooglePlayUtilitySignature, PrimeSignature + ) +) { + override fun execute(data: BytecodeData): PatchResult { + // smali patches + disablePlayServiceChecks() + data.classes.forEach { classDef -> + var proxiedClass: MutableClass? = null + + classDef.methods.forEach methodLoop@{ method -> + val implementation = method.implementation ?: return@methodLoop + + var proxiedImplementation: MutableMethodImplementation? = null + + implementation.instructions.forEachIndexed { i, instruction -> + if (instruction.opcode == Opcode.CONST_STRING) { + val stringValue = ((instruction as Instruction21c).reference as StringReference).string + + val replaceMode = + if (stringValue.startsWith("com.google.android.gms.chimera.container")) // https://github.com/TeamVanced/VancedMicroG/pull/139/file + StringReplaceMode.DO_NOT_REPLACE + else if (stringValue == "com.google" || stringValue.startsWithAny( + "com.google.android.gms.auth.accounts", + "com.google.android.gms.chimera", + "com.google.android.c2dm", + "com.google.android.c2dm", + "com.google.android.gsf", + "com.google.android.c2dm", + "com.google.iid", + "content://com.google.settings" + ) + ) { + StringReplaceMode.REPLACE_WITH_MICROG + } else if (stringValue.startsWithAny( + "com.google.android.youtube.SuggestionsProvider", + "com.google.android.youtube.fileprovider" + ) + ) { + StringReplaceMode.REPLACE_WITH_REVANCED + } else { + StringReplaceMode.DO_NOT_REPLACE + } + + + if (replaceMode != StringReplaceMode.DO_NOT_REPLACE) { + if (proxiedClass == null) { + proxiedClass = data.proxy(classDef).resolve() + } + + if (proxiedImplementation == null) { + proxiedImplementation = proxiedClass!!.methods.first { + it.name == method.name && it.parameterTypes.containsAll(method.parameterTypes) + }.implementation!! + } + + val newString = + if (replaceMode == StringReplaceMode.REPLACE_WITH_REVANCED) stringValue.replace( + "com.google.android.youtube", BASE_REVANCED_PACKAGE_NAME + ) + else stringValue.replace("com.google", BASE_MICROG_PACKAGE_NAME) + + proxiedImplementation!!.replaceInstruction( + i, BuilderInstruction21c( + Opcode.CONST_STRING, instruction.registerA, ImmutableStringReference(newString) + ) + ) + } + } + } + } + } + + + // replace string back + val implementation = + signatures.elementAt(2).result!!.findParentMethod(@Name("do-not-replace-method") @MatchingMethod( + "Llpe;", "c" + ) @DirectPatternScanMethod @MicroGPatchCompatibility @Version("0.0.1") object : MethodSignature( + "L", AccessFlags.PUBLIC or AccessFlags.STATIC, listOf("L"), null, listOf("com.google.android.gms") + ) {})!!.method.implementation!! + + implementation.replaceInstruction( + implementation.instructions.indexOfFirst { it.opcode == Opcode.CONST_STRING }, + "const-string v0, \"com.google.android.gms\"".toInstruction() + ) + + // allow GC to clean unused/ replaced immutable class definitions after this call + data.classes.applyProxies() + + return PatchResultSuccess() + } + + private fun disablePlayServiceChecks() { + for (i in 0 until signatures.count() - 1) { + val result = signatures.elementAt(i).result!! + val stringInstructions = when (result.immutableMethod.returnType.first()) { + 'L' -> """ + const/4 v0, 0x0 + return-object v0 + """ + 'V' -> "return-void" + 'I' -> """ + const/4 v0, 0x0 + return v0 + """ + else -> throw Exception("This case should never happen.") + } + result.method.implementation!!.addInstructions( + 0, stringInstructions.trimIndent().toInstructions() + ) + } + + val implementation = signatures.last().result!!.method.implementation!! + + var register = 2 + val index = implementation.instructions.indexOfFirst { + if (it.opcode != Opcode.CONST_STRING) return@indexOfFirst false + + val instructionString = ((it as Instruction21c).reference as StringReference).string + if (instructionString != "com.google.android.youtube") return@indexOfFirst false + + register = it.registerA + return@indexOfFirst true + } + + implementation.replaceInstruction( + index, "const-string v$register, \"$BASE_REVANCED_PACKAGE_NAME\"".toInstruction() + ) + } +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/patch/resource/MicroGResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/microg/patch/resource/MicroGResourcePatch.kt new file mode 100644 index 00000000..a816afa1 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/microg/patch/resource/MicroGResourcePatch.kt @@ -0,0 +1,68 @@ +package app.revanced.patches.youtube.misc.microg.patch.resource + +import app.revanced.patcher.annotation.Description +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.data.implementation.ResourceData +import app.revanced.patcher.patch.annotations.Patch +import app.revanced.patcher.patch.implementation.ResourcePatch +import app.revanced.patcher.patch.implementation.misc.PatchResult +import app.revanced.patcher.patch.implementation.misc.PatchResultSuccess +import app.revanced.patches.youtube.misc.microg.annotations.MicroGPatchCompatibility +import app.revanced.patches.youtube.misc.microg.shared.Constants.BASE_MICROG_PACKAGE_NAME +import app.revanced.patches.youtube.misc.microg.shared.Constants.BASE_REVANCED_PACKAGE_NAME + +@Patch +@Name("microg-bytecode-patch") +@Description("Bytecode patch to allow YouTube ReVanced to run without root and under a different package name.") +@MicroGPatchCompatibility +@Version("0.0.1") +class MicroGResourcePatch : ResourcePatch() { + override fun execute(data: ResourceData): PatchResult { + data.writer("AndroidManifest.xml").write( + data.reader("AndroidManifest.xml").readText().replace( + "package=\"com.google.android.youtube\"", "package=\"$BASE_REVANCED_PACKAGE_NAME\"" + ).replace( + " android:label=\"@string/application_name\" ", " android:label=\"{APP_NAME}\" " + ).replace( + "", + " \n " + ) + ) + + val replacement = arrayOf( + Pair( + "com.google.android.youtube.SuggestionProvider", "$BASE_REVANCED_PACKAGE_NAME.SuggestionProvider" + ), + Pair( + "com.google.android.youtube.fileprovider", "$BASE_REVANCED_PACKAGE_NAME.fileprovider" + ) + ) + + data.forEach { + if (it.extension != ".xml") return@forEach + + var content = it.readText() + replacement.filter { translation -> content.contains(translation.first) }.forEach { translation -> + content = content.replace(translation.first, translation.second) + } + it.writeText(content) + } + + return PatchResultSuccess() + } +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/patch/resource/enum/StringReplaceMode.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/microg/patch/resource/enum/StringReplaceMode.kt new file mode 100644 index 00000000..63604edd --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/microg/patch/resource/enum/StringReplaceMode.kt @@ -0,0 +1,5 @@ +package app.revanced.patches.youtube.misc.microg.patch.resource.enum + +enum class StringReplaceMode { + REPLACE_WITH_MICROG, REPLACE_WITH_REVANCED, DO_NOT_REPLACE +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/shared/Constants.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/microg/shared/Constants.kt new file mode 100644 index 00000000..1cf4adde --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/microg/shared/Constants.kt @@ -0,0 +1,6 @@ +package app.revanced.patches.youtube.misc.microg.shared + +object Constants { + internal const val BASE_MICROG_PACKAGE_NAME = "com.mgoogle" + internal const val BASE_REVANCED_PACKAGE_NAME = "app.revanced.android.youtube" +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/signatures/GooglePlayUtilitySignature.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/microg/signatures/GooglePlayUtilitySignature.kt new file mode 100644 index 00000000..4ee53a42 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/microg/signatures/GooglePlayUtilitySignature.kt @@ -0,0 +1,239 @@ +package app.revanced.patches.youtube.misc.microg.signatures + +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.extensions.or +import app.revanced.patcher.signature.implementation.method.MethodSignature +import app.revanced.patcher.signature.implementation.method.annotation.FuzzyPatternScanMethod +import app.revanced.patcher.signature.implementation.method.annotation.MatchingMethod +import app.revanced.patches.youtube.misc.microg.annotations.MicroGPatchCompatibility +import org.jf.dexlib2.AccessFlags +import org.jf.dexlib2.Opcode + +@Name("google-play-utility-signature") +@MatchingMethod( + "Llpe;", "b" +) +@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value. +@MicroGPatchCompatibility +@Version("0.0.1") +object GooglePlayUtilitySignature : MethodSignature( + "I", AccessFlags.PUBLIC or AccessFlags.STATIC, listOf("L", "L"), listOf( + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_OBJECT, + Opcode.CONST, + Opcode.INVOKE_VIRTUAL, + Opcode.GOTO, + Opcode.CONST_STRING, + Opcode.CONST_STRING, + Opcode.INVOKE_STATIC, + Opcode.CONST_STRING, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_OBJECT, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT, + Opcode.CONST_4, + Opcode.IF_NEZ, + Opcode.SGET_OBJECT, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT, + Opcode.IF_EQZ, + Opcode.GOTO, + Opcode.SGET_OBJECT, + Opcode.MONITOR_ENTER, + Opcode.SGET_BOOLEAN, + Opcode.IF_EQZ, + Opcode.MONITOR_EXIT, + Opcode.GOTO, + Opcode.SPUT_BOOLEAN, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_OBJECT, + Opcode.INVOKE_STATIC, + Opcode.MOVE_RESULT_OBJECT, + Opcode.CONST_16, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_OBJECT, + Opcode.IGET_OBJECT, + Opcode.IF_NEZ, + Opcode.MONITOR_EXIT, + Opcode.GOTO, + Opcode.CONST_STRING, + Opcode.INVOKE_VIRTUAL, + Opcode.CONST_STRING, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT, + Opcode.SPUT, + Opcode.GOTO, + Opcode.MOVE_EXCEPTION, + Opcode.CONST_STRING, + Opcode.CONST_STRING, + Opcode.INVOKE_STATIC, + Opcode.MONITOR_EXIT, + Opcode.SGET, + Opcode.IF_EQZ, + Opcode.CONST, + Opcode.IF_NE, + Opcode.GOTO, + Opcode.NEW_INSTANCE, + Opcode.INVOKE_DIRECT, + Opcode.THROW, + Opcode.NEW_INSTANCE, + Opcode.INVOKE_DIRECT, + Opcode.THROW, + Opcode.MOVE_EXCEPTION, + Opcode.MONITOR_EXIT, + Opcode.THROW, + Opcode.INVOKE_STATIC, + Opcode.MOVE_RESULT, + Opcode.CONST_4, + Opcode.IF_NEZ, + Opcode.SGET_OBJECT, + Opcode.IF_NEZ, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_OBJECT, + Opcode.CONST_STRING, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT, + Opcode.IF_NEZ, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_OBJECT, + Opcode.CONST_STRING, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT, + Opcode.IF_EQZ, + Opcode.GOTO, + Opcode.CONST_4, + Opcode.GOTO, + Opcode.CONST_4, + Opcode.INVOKE_STATIC, + Opcode.MOVE_RESULT_OBJECT, + Opcode.SPUT_OBJECT, + Opcode.SGET_OBJECT, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT, + Opcode.IF_NEZ, + Opcode.CONST_4, + Opcode.GOTO, + Opcode.CONST_4, + Opcode.INVOKE_STATIC, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_OBJECT, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_OBJECT, + Opcode.CONST_16, + Opcode.IF_EQZ, + Opcode.CONST_STRING, + Opcode.CONST_16, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_OBJECT, + Opcode.GOTO, + Opcode.CONST_STRING, + Opcode.INVOKE_STATIC, + Opcode.MOVE_RESULT_OBJECT, + Opcode.CONST_STRING, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_OBJECT, + Opcode.INVOKE_STATIC, + Opcode.CONST_16, + Opcode.GOTO_16, + Opcode.CONST_4, + Opcode.CONST_STRING, + Opcode.CONST_16, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_OBJECT, + Opcode.INVOKE_STATIC, + Opcode.INVOKE_STATIC, + Opcode.MOVE_RESULT, + Opcode.IF_NEZ, + Opcode.CONST_STRING, + Opcode.INVOKE_STATIC, + Opcode.MOVE_RESULT_OBJECT, + Opcode.CONST_STRING, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_OBJECT, + Opcode.INVOKE_STATIC, + Opcode.GOTO, + Opcode.IF_EQZ, + Opcode.INVOKE_STATIC, + Opcode.INVOKE_STATIC, + Opcode.MOVE_RESULT, + Opcode.IF_NEZ, + Opcode.CONST_STRING, + Opcode.INVOKE_STATIC, + Opcode.MOVE_RESULT_OBJECT, + Opcode.CONST_STRING, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_OBJECT, + Opcode.INVOKE_STATIC, + Opcode.GOTO, + Opcode.IF_EQZ, + Opcode.IF_EQZ, + Opcode.IGET_OBJECT, + Opcode.AGET_OBJECT, + Opcode.IGET_OBJECT, + Opcode.AGET_OBJECT, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT, + Opcode.IF_NEZ, + Opcode.CONST_STRING, + Opcode.INVOKE_STATIC, + Opcode.MOVE_RESULT_OBJECT, + Opcode.CONST_STRING, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_OBJECT, + Opcode.INVOKE_STATIC, + Opcode.GOTO, + Opcode.IGET, + Opcode.INVOKE_STATIC, + Opcode.MOVE_RESULT, + Opcode.INVOKE_STATIC, + Opcode.MOVE_RESULT, + Opcode.IF_GE, + Opcode.IGET, + Opcode.NEW_INSTANCE, + Opcode.INVOKE_DIRECT, + Opcode.CONST_STRING, + Opcode.INVOKE_VIRTUAL, + Opcode.INVOKE_VIRTUAL, + Opcode.CONST_STRING, + Opcode.INVOKE_VIRTUAL, + Opcode.INVOKE_VIRTUAL, + Opcode.CONST_STRING, + Opcode.INVOKE_VIRTUAL, + Opcode.INVOKE_VIRTUAL, + Opcode.CONST_STRING, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_OBJECT, + Opcode.INVOKE_STATIC, + Opcode.CONST_4, + Opcode.GOTO, + Opcode.IGET_OBJECT, + Opcode.IF_NEZ, + Opcode.CONST_STRING, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_OBJECT, + Opcode.GOTO, + Opcode.MOVE_EXCEPTION, + Opcode.CONST_STRING, + Opcode.INVOKE_STATIC, + Opcode.MOVE_RESULT_OBJECT, + Opcode.CONST_STRING, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_OBJECT, + Opcode.INVOKE_STATIC, + Opcode.GOTO, + Opcode.IGET_BOOLEAN, + Opcode.IF_NEZ, + Opcode.CONST_4, + Opcode.GOTO, + Opcode.RETURN, + Opcode.CONST_STRING, + Opcode.INVOKE_STATIC, + Opcode.MOVE_RESULT_OBJECT, + Opcode.CONST_STRING, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_OBJECT, + Opcode.INVOKE_STATIC, + Opcode.RETURN + ), listOf("This should never happen.", "MetadataValueReader", "com.google.android.gms") +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/signatures/IntegrityCheckSignature.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/microg/signatures/IntegrityCheckSignature.kt new file mode 100644 index 00000000..bb0cd28a --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/microg/signatures/IntegrityCheckSignature.kt @@ -0,0 +1,82 @@ +package app.revanced.patches.youtube.misc.microg.signatures + +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.extensions.or +import app.revanced.patcher.signature.implementation.method.MethodSignature +import app.revanced.patcher.signature.implementation.method.annotation.FuzzyPatternScanMethod +import app.revanced.patcher.signature.implementation.method.annotation.MatchingMethod +import app.revanced.patches.youtube.misc.microg.annotations.MicroGPatchCompatibility +import org.jf.dexlib2.AccessFlags +import org.jf.dexlib2.Opcode + +@Name("google-play-sig-check-signature") +@MatchingMethod( + "Ldsf;", "d" +) +@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value. +@MicroGPatchCompatibility +@Version("0.0.1") +object IntegrityCheckSignature : MethodSignature( + "L", AccessFlags.PUBLIC or AccessFlags.STATIC, listOf("L", "L"), listOf( + Opcode.MOVE_OBJECT_FROM16, + Opcode.CONST_STRING, + Opcode.CONST_STRING, + Opcode.NEW_INSTANCE, + Opcode.MOVE_OBJECT_FROM16, + Opcode.INVOKE_DIRECT, + Opcode.CONST_4, + Opcode.CONST_STRING, + Opcode.INVOKE_STATIC, + Opcode.MOVE_RESULT_OBJECT, + Opcode.INVOKE_STATIC, + Opcode.MOVE_RESULT_OBJECT, + Opcode.IF_EQ, + Opcode.IGET_OBJECT, + Opcode.INVOKE_VIRTUAL, + Opcode.SGET, + Opcode.IGET_OBJECT, + Opcode.INVOKE_STATIC, + Opcode.MOVE_RESULT_WIDE, + Opcode.CONST_WIDE, + Opcode.CONST_STRING, + Opcode.CONST_4, + Opcode.CONST_STRING, + Opcode.CONST_4, + Opcode.CMP_LONG, + Opcode.IF_GEZ, + Opcode.CONST_16, + Opcode.GOTO_16, + Opcode.CONST_STRING, + Opcode.IGET_OBJECT, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_OBJECT, + Opcode.CONST_16, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_OBJECT, + Opcode.GOTO, + Opcode.MOVE_EXCEPTION, + Opcode.CONST_STRING, + Opcode.INVOKE_STATIC, + Opcode.CONST_4, + Opcode.IGET_OBJECT, + Opcode.IF_EQZ, + Opcode.CONST_STRING, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT, + Opcode.CONST, + Opcode.IF_NE, + Opcode.CONST_16, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_OBJECT, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_OBJECT, + Opcode.SGET_OBJECT, + Opcode.INVOKE_STATIC, + Opcode.MOVE_RESULT_OBJECT, + Opcode.IF_NEZ, + Opcode.CONST_STRING, + Opcode.GOTO, + Opcode.NEW_ARRAY + ), listOf("This should never happen.", "GooglePlayServicesUtil", "Google Play Store signature invalid.") +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/signatures/PrimeSignature.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/microg/signatures/PrimeSignature.kt new file mode 100644 index 00000000..598747e1 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/microg/signatures/PrimeSignature.kt @@ -0,0 +1,19 @@ +package app.revanced.patches.youtube.misc.microg.signatures + +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.signature.implementation.method.MethodSignature +import app.revanced.patcher.signature.implementation.method.annotation.DirectPatternScanMethod +import app.revanced.patcher.signature.implementation.method.annotation.MatchingMethod +import app.revanced.patches.youtube.misc.microg.annotations.MicroGPatchCompatibility + +@Name("google-play-prime-signature") +@MatchingMethod( + "Louy;", "e" +) +@DirectPatternScanMethod +@MicroGPatchCompatibility +@Version("0.0.1") +object PrimeSignature : MethodSignature( + null, null, null, null, listOf("com.google.android.GoogleCamera", "com.android.vending") +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/signatures/ServiceCheckSignature.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/microg/signatures/ServiceCheckSignature.kt new file mode 100644 index 00000000..79f6c247 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/microg/signatures/ServiceCheckSignature.kt @@ -0,0 +1,49 @@ +package app.revanced.patches.youtube.misc.microg.signatures + +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.extensions.or +import app.revanced.patcher.signature.implementation.method.MethodSignature +import app.revanced.patcher.signature.implementation.method.annotation.FuzzyPatternScanMethod +import app.revanced.patcher.signature.implementation.method.annotation.MatchingMethod +import app.revanced.patches.youtube.misc.microg.annotations.MicroGPatchCompatibility +import org.jf.dexlib2.AccessFlags +import org.jf.dexlib2.Opcode + +@Name("google-play-service-checker-signature") +@MatchingMethod( + "Llpe;", "d" +) +@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value. +@MicroGPatchCompatibility +@Version("0.0.1") +object ServiceCheckSignature : MethodSignature( + "V", AccessFlags.PUBLIC or AccessFlags.STATIC, listOf("L", "I"), listOf( + Opcode.SGET_OBJECT, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT, + Opcode.IF_EQZ, + Opcode.SGET_OBJECT, + Opcode.CONST_STRING, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_OBJECT, + Opcode.NEW_INSTANCE, + Opcode.INVOKE_DIRECT, + Opcode.CONST_STRING, + Opcode.INVOKE_VIRTUAL, + Opcode.INVOKE_VIRTUAL, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_OBJECT, + Opcode.CONST_STRING, + Opcode.INVOKE_STATIC, + Opcode.IF_NEZ, + Opcode.NEW_INSTANCE, + Opcode.INVOKE_DIRECT, + Opcode.THROW, + Opcode.NEW_INSTANCE, + Opcode.CONST_STRING, + Opcode.INVOKE_DIRECT, + Opcode.THROW, + Opcode.RETURN_VOID + ), listOf("Google Play Services not available") +) \ No newline at end of file