Skip to content

Commit

Permalink
feat(Gboard): Add Bypass Gboard signature verification checks patch
Browse files Browse the repository at this point in the history
  • Loading branch information
jkennethcarino committed Mar 29, 2024
1 parent 5e20055 commit 8b5da89
Show file tree
Hide file tree
Showing 3 changed files with 136 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package dev.jkcarino.revanced.integrations.gboard

import android.content.Context
import com.google.android.apps.inputmethod.latin.ImeLatinApp
import dev.jkcarino.revanced.integrations.shared.PmsHookApplication

class SignatureHookApp : ImeLatinApp() {

override fun attachBaseContext(base: Context) {
val pmsHookApplication = PmsHookApplication(
signature = "AQAABEcwggRDMIIDK6ADAgECAgkAwuCHRmRKMI0wDQYJKoZIhvcNAQEEBQAwdDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDU1vdW50YWluIFZpZXcxFDASBgNVBAoTC0dvb2dsZSBJbmMuMRAwDgYDVQQLEwdBbmRyb2lkMRAwDgYDVQQDEwdBbmRyb2lkMB4XDTA4MDgyMTIzMTMzNFoXDTM2MDEwNzIzMTMzNFowdDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDU1vdW50YWluIFZpZXcxFDASBgNVBAoTC0dvb2dsZSBJbmMuMRAwDgYDVQQLEwdBbmRyb2lkMRAwDgYDVQQDEwdBbmRyb2lkMIIBIDANBgkqhkiG9w0BAQEFAAOCAQ0AMIIBCAKCAQEAq1YuANg7ogiuCpZvEk4p2hHyq1bQj1jizKkTA+m3VNNy9kCnGx3LEwlnYk5GVqd3apIZPbLlv7ckqR53GIsOakekOzPZYJt3GDFFzN97LlhmdMnhVlsfTGpZVb/yUaY9q/nFXCciIlLodeT4FUpkX4lxaMCxv8YS6r94V2m7NKp5hNx+LqJ2TK6DB9jBcVTX7l9kpRpEpgLCSQVBV9wCzV9cDlX774UZ++Mn8LFRFpLFoG8Z0YOF9cTbwta5P2jMKXnHDhirk4ZrO9XbiZlVKg47TJnfWPuRi+3Bgro14APBtLEN0kSo7iT//TM4cqtSIZhe2rD8DQsUW2qhkoWOeQIBA6OB2TCB1jAdBgNVHQ4EFgQUx32MwiEXViWaf9OC32vjmOTXhqUwgaYGA1UdIwSBnjCBm4AUx32MwiEXViWaf9OC32vjmOTXhqWheKR2MHQxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRQwEgYDVQQKEwtHb29nbGUgSW5jLjEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZIIJAMLgh0ZkSjCNMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEEBQADggEBAG3SUs7vhTAsNgqqzpObz/LMqQS7XXoWYfiuRrKZQgTQ/0pox+0aUx7EWVpiPOYHY7FnKXp641cSxAfyCPDLEJQpEk17EGIZwITKPrP5rV+4ce+SJpqL4ovxbUTI2aCObLLwBbs/4suWRH6GjnMQdq1Fsz9gCeoZwWHmJkGqmScd/VIoxcWHh13bf0UnWNZh9swMzLc1LkJMxDZcUjUy9zJRN1k8SuNB9NtB7doNCxBxp8RA8P6eoBy2J8pnQ2nQhL0v2RH/Bs2/LPoQ3A+JOuNXYpGQSMfvxkxxRBeDQvcFgcneVzr1WzkN1/25QYYxiV1fdZ8wESaH/2IUEMBpMIo="
)
pmsHookApplication.hook(base)
super.attachBaseContext(base)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package dev.jkcarino.revanced.integrations.shared

import android.annotation.SuppressLint
import android.app.Application
import android.content.Context
import android.content.pm.PackageInfo
import android.content.pm.Signature
import android.util.Base64
import java.io.ByteArrayInputStream
import java.io.DataInputStream
import java.lang.reflect.InvocationHandler
import java.lang.reflect.Method
import java.lang.reflect.Proxy

/**
* A custom [Application] class that hooks into the Android's [PackageManager] to modify the
* package information returned for the app. This is used to override the package signatures,
* allowing us to bypass signature verification checks.
*
* Source: https://github.com/L-JINBIN/ApkSignatureKiller/blob/master/hook/cc/binmt/signature/PmsHookApplication.java
*/
internal class PmsHookApplication(
private val signature: String
) {
/**
* This hooks into the [PackageManager] and replaces the original package manager with a
* proxy object that modifies the package information returned for the app.
*/
@SuppressLint("PrivateApi", "DiscouragedPrivateApi")
fun hook(context: Context) {
try {
val byteArray = Base64.decode(signature, Base64.DEFAULT)
val signatures = ByteArrayInputStream(byteArray).use { inputStream ->
DataInputStream(inputStream).use { dataInputStream ->
val signatureCount = dataInputStream.read() and 0xFF
Array(signatureCount) {
ByteArray(dataInputStream.readInt()).also {
dataInputStream.readFully(it)
}
}
}
}

// Get the global ActivityThread object
val activityThreadClass = Class.forName("android.app.ActivityThread")
val currentActivityThreadMethod =
activityThreadClass.getDeclaredMethod("currentActivityThread")
val currentActivityThread = currentActivityThreadMethod.invoke(null)

// Get the original sPackageManager from ActivityThread
val sPackageManagerField = activityThreadClass.getDeclaredField("sPackageManager")
sPackageManagerField.isAccessible = true
val sPackageManager = sPackageManagerField.get(currentActivityThread)

// Prepare a proxy object to replace the original one
val iPackageManagerInterface = Class.forName("android.content.pm.IPackageManager")
val proxy = Proxy.newProxyInstance(
iPackageManagerInterface.classLoader,
arrayOf<Class<*>>(iPackageManagerInterface),
PmsHookInvocationHandler(
packageManager = sPackageManager,
signatures = signatures,
appPackageName = context.packageName
)
)

// Replace the sPackageManager field in ActivityThread
sPackageManagerField.set(currentActivityThread, proxy)

// Replace mPM object in ApplicationPackageManager
val pm = context.packageManager
val mPmField = pm.javaClass.getDeclaredField("mPM")
mPmField.isAccessible = true
mPmField.set(pm, proxy)

println("PmsHook success.")
} catch (error: Exception) {
System.err.println("PmsHook failed.")
error.printStackTrace()
}
}
}

/**
* This class is used as part of the package manager hooking mechanism implemented in the
* [PmsHookApplication] class.
*/
private class PmsHookInvocationHandler(
private val packageManager: Any?,
private val signatures: Array<ByteArray>,
private val appPackageName: String
) : InvocationHandler {

/**
* This intercepts calls to the [getPackageInfo] method of the package manager and
* modifies the returned [PackageInfo] object to use the new package signatures.
*/
override fun invoke(proxy: Any, method: Method, args: Array<Any>?): Any? {
if ("getPackageInfo" == method.name) {
val packageName = args!![0].toString()
val flag = args[1].toString().toInt()
if (flag and GET_SIGNATURES != 0 && appPackageName == packageName) {
val packageInfo = method.invoke(packageManager, *args) as PackageInfo
packageInfo.signatures = Array(signatures.size) { Signature(signatures[it]) }
return packageInfo
}
}
return method.invoke(packageManager, *args.orEmpty())
}

companion object {
private const val GET_SIGNATURES = 0x00000040
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.google.android.apps.inputmethod.latin;

import android.app.Application;

public class ImeLatinApp extends Application {
}

0 comments on commit 8b5da89

Please sign in to comment.