diff --git a/app/src/main/cpp/binder_interceptor.cpp b/app/src/main/cpp/binder_interceptor.cpp index 4104a39..43b9a68 100644 --- a/app/src/main/cpp/binder_interceptor.cpp +++ b/app/src/main/cpp/binder_interceptor.cpp @@ -386,6 +386,15 @@ void inspectAndRewriteTransaction(binder_transaction_data *txn_data) { } if (hijack) { + // The kernel driver fills sender_euid. libbinder trusts this value + // to populate IPCThreadState. By changing it here, we fool the + // entire process (including the TEE implementation) into thinking + // the call came from system (1000). + if (txn_data->sender_euid == 0) { + LOGV("[Hook] Spoofing UID for transaction: 0 -> 1000"); + txn_data->sender_euid = 1000; + } + uint64_t tx_id = ++g_transaction_id_counter; info.transaction_id = tx_id; diff --git a/app/src/main/java/org/matrix/TEESimulator/App.kt b/app/src/main/java/org/matrix/TEESimulator/App.kt index 29762b5..6e41fbd 100644 --- a/app/src/main/java/org/matrix/TEESimulator/App.kt +++ b/app/src/main/java/org/matrix/TEESimulator/App.kt @@ -1,6 +1,11 @@ package org.matrix.TEESimulator +import android.app.ActivityThread +import android.app.Application +import android.content.Context +import android.content.ContextWrapper import android.os.Build +import android.os.Looper import java.security.Security import org.bouncycastle.jce.provider.BouncyCastleProvider import org.matrix.TEESimulator.config.ConfigurationManager @@ -30,13 +35,15 @@ object App { SystemLogger.info("Welcome to TEESimulator!") try { + // Initialize the Android framework environment + prepareEnvironment() + // Initialize and start the appropriate keystore interceptors. + initializeInterceptors() + // Load the package configuration. ConfigurationManager.initialize() // Set up the device's boot key and hash, which are crucial for attestation. AndroidDeviceUtils.setupBootKeyAndHash() - // Initialize and start the appropriate keystore interceptors. - initializeInterceptors() - // Enter an infinite loop to keep the service running. // Android ships with a stripped-down Bouncy Castle provider under the name "BC". // We must remove the system provider first to ensure the full Bouncy Castle library @@ -44,13 +51,43 @@ object App { Security.removeProvider(BouncyCastleProvider.PROVIDER_NAME) Security.addProvider(BouncyCastleProvider()) - maintainService() + // This starts the message queue processing. It blocks here indefinitely + // processing messages until Looper.myLooper().quit() is called. + Looper.loop() } catch (e: Exception) { SystemLogger.error("A fatal error occurred in the main application thread.", e) throw e } } + /** Initializes the necessary Android framework internals to satisfy KeyStore requirements. */ + private fun prepareEnvironment() { + // 1. Prepare Main Looper + if (Looper.getMainLooper() == null) { + @Suppress("deprecation") Looper.prepareMainLooper() + } + + // 2. Initialize ActivityThread for the current process + val activityThread = ActivityThread.systemMain() + + // 3. Get the system context + val systemContext = activityThread.getSystemContext() + + // 4. Create a dummy Application object and attach the context + val app = Application() + val attachMethod = + ContextWrapper::class.java.getDeclaredMethod("attachBaseContext", Context::class.java) + attachMethod.isAccessible = true + attachMethod.invoke(app, systemContext) + + // 5. Inject this application object into ActivityThread's mInitialApplication field. + // This is what KeyStore.getApplicationContext() looks for. + val mInitialApplicationField = + ActivityThread::class.java.getDeclaredField("mInitialApplication") + mInitialApplicationField.isAccessible = true + mInitialApplicationField.set(activityThread, app) + } + /** * Selects and initializes the correct keystore interceptor based on the Android SDK version. It * retries initialization until it succeeds. @@ -89,15 +126,4 @@ object App { Keystore2Interceptor } } - - /** - * Puts the main thread into a long-running sleep loop. This is a common pattern to keep a - * background service process alive indefinitely. - */ - private fun maintainService() { - SystemLogger.info("Service started successfully. Entering maintenance mode.") - while (true) { - Thread.sleep(SERVICE_SLEEP_MS) - } - } } diff --git a/stub/src/main/java/android/app/ActivityThread.java b/stub/src/main/java/android/app/ActivityThread.java index a62e724..58f8e2c 100644 --- a/stub/src/main/java/android/app/ActivityThread.java +++ b/stub/src/main/java/android/app/ActivityThread.java @@ -4,4 +4,12 @@ public class ActivityThread { public static void initializeMainlineModules() { throw new UnsupportedOperationException("STUB!"); } + + public static ActivityThread systemMain() { + throw new UnsupportedOperationException("STUB!"); + } + + public ContextImpl getSystemContext() { + throw new UnsupportedOperationException("STUB!"); + } } diff --git a/stub/src/main/java/android/app/ContextImpl.java b/stub/src/main/java/android/app/ContextImpl.java new file mode 100644 index 0000000..62daab0 --- /dev/null +++ b/stub/src/main/java/android/app/ContextImpl.java @@ -0,0 +1,4 @@ +package android.app; + +public class ContextImpl { +}