From 85e6b88bf5d945ca8eb94f3a8117060e0b91312a Mon Sep 17 00:00:00 2001 From: LoveSy Date: Wed, 17 Feb 2021 23:32:10 +0800 Subject: [PATCH] [core] Fix binder for system server --- core/src/main/cpp/main/src/context.cpp | 11 ++- core/src/main/cpp/main/src/service.cpp | 89 +++++++++++-------- core/src/main/cpp/main/src/service.h | 25 +++--- .../io/github/lsposed/lspd/core/Main.java | 16 ---- .../lsposed/lspd/service/BridgeService.java | 17 +++- .../lspd/service/LSPApplicationService.java | 2 +- .../lsposed/lspd/service/LSPosedService.java | 18 ---- .../lsposed/lspd/service/ServiceManager.java | 37 ++++++++ 8 files changed, 126 insertions(+), 89 deletions(-) diff --git a/core/src/main/cpp/main/src/context.cpp b/core/src/main/cpp/main/src/context.cpp index df90a388..e76a3d5e 100644 --- a/core/src/main/cpp/main/src/context.cpp +++ b/core/src/main/cpp/main/src/context.cpp @@ -197,7 +197,9 @@ namespace lspd { void Context::OnNativeForkSystemServerPost(JNIEnv *env, jint res) { if (res != 0) return; - auto binder = Service::instance()->RequestBinder(env); + LoadDex(env); + Service::instance()->HookBridge(*this, env); + auto binder = Service::instance()->RequestBinderForSystemServer(env); if (binder) { if (void *buf = mmap(nullptr, 1, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANONYMOUS | MAP_PRIVATE, -1, @@ -208,14 +210,15 @@ namespace lspd { } else { munmap(buf, 1); } + } else { + skip_ = true; + LOGD("skip injecting into android because no module is hooking it"); } - LoadDex(env); - if (!skip_ && binder) { + if (!skip_) { InstallInlineHooks(); Init(env); FindAndCall(env, "forkSystemServerPost", "(Landroid/os/IBinder;)V", binder); } - Service::instance()->HookBridge(*this, env); } void Context::OnNativeForkAndSpecializePre(JNIEnv *env, diff --git a/core/src/main/cpp/main/src/service.cpp b/core/src/main/cpp/main/src/service.cpp index f4ea7648..ff2ad5a6 100644 --- a/core/src/main/cpp/main/src/service.cpp +++ b/core/src/main/cpp/main/src/service.cpp @@ -10,7 +10,9 @@ #include "JNIHelper.h" namespace lspd { - jboolean Service::exec_transact_replace(jboolean *res, JNIEnv *env, [[maybe_unused]] jobject obj, va_list args) { + jboolean + Service::exec_transact_replace(jboolean *res, JNIEnv *env, [[maybe_unused]] jobject obj, + va_list args) { jint code; va_list copy; @@ -44,39 +46,40 @@ namespace lspd { initialized_ = true; // ServiceManager - serviceManagerClass_ = env->FindClass("android/os/ServiceManager"); - if (serviceManagerClass_) { - serviceManagerClass_ = (jclass) env->NewGlobalRef(serviceManagerClass_); + service_manager_class_ = env->FindClass("android/os/ServiceManager"); + if (service_manager_class_) { + service_manager_class_ = (jclass) env->NewGlobalRef(service_manager_class_); } else { env->ExceptionClear(); return; } - getServiceMethod_ = env->GetStaticMethodID(serviceManagerClass_, "getService", - "(Ljava/lang/String;)Landroid/os/IBinder;"); - if (!getServiceMethod_) { + get_service_method_ = env->GetStaticMethodID(service_manager_class_, "getService", + "(Ljava/lang/String;)Landroid/os/IBinder;"); + if (!get_service_method_) { env->ExceptionClear(); return; } // IBinder - jclass iBinderClass = env->FindClass("android/os/IBinder"); - transactMethod_ = env->GetMethodID(iBinderClass, "transact", - "(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z"); + jclass ibinder_class = env->FindClass("android/os/IBinder"); + transact_method_ = env->GetMethodID(ibinder_class, "transact", + "(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z"); // Parcel - parcelClass_ = env->FindClass("android/os/Parcel"); - if (parcelClass_) parcelClass_ = (jclass) env->NewGlobalRef(parcelClass_); - obtainMethod_ = env->GetStaticMethodID(parcelClass_, "obtain", "()Landroid/os/Parcel;"); - recycleMethod_ = env->GetMethodID(parcelClass_, "recycle", "()V"); - writeInterfaceTokenMethod_ = env->GetMethodID(parcelClass_, "writeInterfaceToken", - "(Ljava/lang/String;)V"); - writeIntMethod_ = env->GetMethodID(parcelClass_, "writeInt", "(I)V"); - writeStringMethod_ = env->GetMethodID(parcelClass_, "writeString", "(Ljava/lang/String;)V"); - readExceptionMethod_ = env->GetMethodID(parcelClass_, "readException", "()V"); - readStrongBinderMethod_ = env->GetMethodID(parcelClass_, "readStrongBinder", - "()Landroid/os/IBinder;"); - createStringArray_ = env->GetMethodID(parcelClass_, "createStringArray", - "()[Ljava/lang/String;"); + parcel_class_ = env->FindClass("android/os/Parcel"); + if (parcel_class_) parcel_class_ = (jclass) env->NewGlobalRef(parcel_class_); + obtain_method_ = env->GetStaticMethodID(parcel_class_, "obtain", "()Landroid/os/Parcel;"); + recycleMethod_ = env->GetMethodID(parcel_class_, "recycle", "()V"); + write_interface_token_method_ = env->GetMethodID(parcel_class_, "writeInterfaceToken", + "(Ljava/lang/String;)V"); + write_int_method_ = env->GetMethodID(parcel_class_, "writeInt", "(I)V"); +// writeStringMethod_ = env->GetMethodID(parcel_class_, "writeString", +// "(Ljava/lang/String;)V"); + read_exception_method_ = env->GetMethodID(parcel_class_, "readException", "()V"); + read_strong_binder_method_ = env->GetMethodID(parcel_class_, "readStrongBinder", + "()Landroid/os/IBinder;"); +// createStringArray_ = env->GetMethodID(parcel_class_, "createStringArray", +// "()[Ljava/lang/String;"); deadObjectExceptionClass_ = env->FindClass("android/os/DeadObjectException"); if (deadObjectExceptionClass_) @@ -94,16 +97,16 @@ namespace lspd { return; } bridge_service_class_ = (jclass) env->NewGlobalRef(bridge_service_class_); - exec_transact_replace_methodID_ = env->GetStaticMethodID(bridge_service_class_, - "execTransact", - "(IJJI)Z"); + exec_transact_replace_methodID_ = JNI_GetStaticMethodID(env, bridge_service_class_, + "execTransact", + "(IJJI)Z"); if (!exec_transact_replace_methodID_) { LOGE("execTransact class not found"); return; } ScopedLocalRef binderClass(env, env->FindClass("android/os/Binder")); - exec_transact_backup_methodID_ = env->GetMethodID(binderClass.get(), "execTransact", + exec_transact_backup_methodID_ = JNI_GetMethodID(env, binderClass.get(), "execTransact", "(IJJI)Z"); auto set_table_override = reinterpret_cast(DobbySymbolResolver(nullptr, @@ -129,32 +132,31 @@ namespace lspd { return nullptr; } - auto bridgeServiceName = env->NewStringUTF(BRIDGE_SERVICE_NAME.data()); - auto bridgeService = JNI_CallStaticObjectMethod(env, serviceManagerClass_, - getServiceMethod_, bridgeServiceName); + auto bridgeService = JNI_CallStaticObjectMethod(env, service_manager_class_, + get_service_method_, bridgeServiceName); if (!bridgeService) { LOGD("can't get %s", BRIDGE_SERVICE_NAME.data()); return nullptr; } - auto data = JNI_CallStaticObjectMethod(env, parcelClass_, obtainMethod_); - auto reply = JNI_CallStaticObjectMethod(env, parcelClass_, obtainMethod_); + auto data = JNI_CallStaticObjectMethod(env, parcel_class_, obtain_method_); + auto reply = JNI_CallStaticObjectMethod(env, parcel_class_, obtain_method_); auto descriptor = env->NewStringUTF(BRIDGE_SERVICE_DESCRIPTOR.data()); - JNI_CallVoidMethod(env, data, writeInterfaceTokenMethod_, descriptor); - JNI_CallVoidMethod(env, data, writeIntMethod_, BRIDGE_ACTION_GET_BINDER); + JNI_CallVoidMethod(env, data, write_interface_token_method_, descriptor); + JNI_CallVoidMethod(env, data, write_int_method_, BRIDGE_ACTION_GET_BINDER); - auto res = JNI_CallBooleanMethod(env, bridgeService, transactMethod_, + auto res = JNI_CallBooleanMethod(env, bridgeService, transact_method_, BRIDGE_TRANSACTION_CODE, data, reply, 0); jobject service = nullptr; if (res) { - env->CallVoidMethod(reply, readExceptionMethod_); + env->CallVoidMethod(reply, read_exception_method_); if (!ClearException(env)) { - service = JNI_CallObjectMethod(env, reply, readStrongBinderMethod_); + service = JNI_CallObjectMethod(env, reply, read_strong_binder_method_); } } JNI_CallVoidMethod(env, data, recycleMethod_); @@ -162,4 +164,17 @@ namespace lspd { return service; } + + jobject Service::RequestBinderForSystemServer(JNIEnv *env) { + auto bridgeServiceName = env->NewStringUTF(SYSTEM_SERVER_BRIDGE_SERVICE_NAME.data()); + auto binder = JNI_CallStaticObjectMethod(env, service_manager_class_, + get_service_method_, bridgeServiceName); + if(!binder) { + LOGD("Fail to get binder for system server"); + return nullptr; + } + auto method = JNI_GetStaticMethodID(env, bridge_service_class_, "getApplicationServiceForSystemServer", "(Landroid/os/IBinder;)Landroid/os/IBinder;"); + auto app_binder = JNI_CallStaticObjectMethod(env, bridge_service_class_, method, binder); + return app_binder; + } } \ No newline at end of file diff --git a/core/src/main/cpp/main/src/service.h b/core/src/main/cpp/main/src/service.h index b14c7ed0..94f08e5f 100644 --- a/core/src/main/cpp/main/src/service.h +++ b/core/src/main/cpp/main/src/service.h @@ -13,8 +13,9 @@ using namespace std::literals::string_view_literals; namespace lspd { class Service { constexpr static jint BRIDGE_TRANSACTION_CODE = 1598837584; - constexpr static auto BRIDGE_SERVICE_DESCRIPTOR = "android.app.IActivityManager"sv; + constexpr static auto BRIDGE_SERVICE_DESCRIPTOR = "LSPosed"sv; constexpr static auto BRIDGE_SERVICE_NAME = "activity"sv; + constexpr static auto SYSTEM_SERVER_BRIDGE_SERVICE_NAME = "serial"sv; constexpr static jint BRIDGE_ACTION_GET_BINDER = 2; public: @@ -32,6 +33,8 @@ namespace lspd { jobject RequestBinder(JNIEnv *env); + jobject RequestBinderForSystemServer(JNIEnv *env); + private: inline static std::unique_ptr instance_ = std::make_unique(); bool initialized_ = false; @@ -52,20 +55,18 @@ namespace lspd { jclass bridge_service_class_ = nullptr; jmethodID exec_transact_replace_methodID_ = nullptr; - jclass serviceManagerClass_ = nullptr; - jmethodID getServiceMethod_ = nullptr; + jclass service_manager_class_ = nullptr; + jmethodID get_service_method_ = nullptr; - jmethodID transactMethod_ = nullptr; + jmethodID transact_method_ = nullptr; - jclass parcelClass_ = nullptr; - jmethodID obtainMethod_ = nullptr; + jclass parcel_class_ = nullptr; + jmethodID obtain_method_ = nullptr; jmethodID recycleMethod_ = nullptr; - jmethodID writeInterfaceTokenMethod_ = nullptr; - jmethodID writeIntMethod_ = nullptr; - jmethodID writeStringMethod_ = nullptr; - jmethodID readExceptionMethod_ = nullptr; - jmethodID readStrongBinderMethod_ = nullptr; - jmethodID createStringArray_ = nullptr; + jmethodID write_interface_token_method_ = nullptr; + jmethodID write_int_method_ = nullptr; + jmethodID read_exception_method_ = nullptr; + jmethodID read_strong_binder_method_ = nullptr; jclass deadObjectExceptionClass_ = nullptr; diff --git a/core/src/main/java/io/github/lsposed/lspd/core/Main.java b/core/src/main/java/io/github/lsposed/lspd/core/Main.java index d41d566e..75c8d89d 100644 --- a/core/src/main/java/io/github/lsposed/lspd/core/Main.java +++ b/core/src/main/java/io/github/lsposed/lspd/core/Main.java @@ -104,28 +104,12 @@ public class Main implements KeepAll { return getEdxpImpl().getVariant(); } - private static void waitSystemService(String name) { - while (android.os.ServiceManager.getService(name) == null) { - try { - Log.i(TAG, "service " + name + " is not started, wait 1s."); - Thread.sleep(1000); - } catch (InterruptedException e) { - Log.i(TAG, Log.getStackTraceString(e)); - } - } - } - public static void main(String[] args) { for (String arg : args) { if (arg.equals("--debug")) { DdmHandleAppName.setAppName("lspd", 0); } } - waitSystemService("package"); - waitSystemService("activity"); - waitSystemService(Context.USER_SERVICE); - waitSystemService(Context.APP_OPS_SERVICE); - ServiceManager.start(); } } diff --git a/core/src/main/java/io/github/lsposed/lspd/service/BridgeService.java b/core/src/main/java/io/github/lsposed/lspd/service/BridgeService.java index 05d24aa3..41adcb50 100644 --- a/core/src/main/java/io/github/lsposed/lspd/service/BridgeService.java +++ b/core/src/main/java/io/github/lsposed/lspd/service/BridgeService.java @@ -9,6 +9,7 @@ import android.os.Parcel; import android.os.RemoteException; import android.os.ServiceManager; import android.util.Log; +import android.os.Process; import androidx.annotation.Keep; import androidx.annotation.NonNull; @@ -22,7 +23,7 @@ import static io.github.lsposed.lspd.service.ServiceManager.TAG; public class BridgeService { private static final int TRANSACTION_CODE = ('_' << 24) | ('L' << 16) | ('S' << 8) | 'P'; - private static final String DESCRIPTOR = "android.app.IActivityManager"; + private static final String DESCRIPTOR = "LSPosed"; private static final String SERVICE_NAME = "activity"; enum ACTION { @@ -194,6 +195,7 @@ public class BridgeService { data.enforceInterface(DESCRIPTOR); ACTION action = ACTION.values()[data.readInt()]; + Log.d(TAG, "onTransact: action=" + action + ", callingUid=" + Binder.getCallingUid() + ", callingPid=" + Binder.getCallingPid()); switch (action) { @@ -264,4 +266,17 @@ public class BridgeService { return res; } + + @Keep + public static IBinder getApplicationServiceForSystemServer(IBinder binder) { + if (binder == null) return null; + try { + ILSPosedService service = ILSPosedService.Stub.asInterface(binder); + ILSPApplicationService applicationService = service.requestApplicationService(Process.myUid(), Process.myPid()); + if (applicationService != null) applicationService.asBinder(); + } catch (Throwable e) { + Log.e(TAG, Log.getStackTraceString(e)); + } + return null; + } } diff --git a/core/src/main/java/io/github/lsposed/lspd/service/LSPApplicationService.java b/core/src/main/java/io/github/lsposed/lspd/service/LSPApplicationService.java index 3add1b12..1b087013 100644 --- a/core/src/main/java/io/github/lsposed/lspd/service/LSPApplicationService.java +++ b/core/src/main/java/io/github/lsposed/lspd/service/LSPApplicationService.java @@ -6,7 +6,6 @@ import android.os.RemoteException; import android.util.Log; import android.util.Pair; -import java.util.List; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; @@ -22,6 +21,7 @@ public class LSPApplicationService extends ILSPApplicationService.Stub { handles.add(handle); int uid = Binder.getCallingUid(); int pid = Binder.getCallingPid(); + cache.add(new Pair<>(uid, pid)); handle.linkToDeath(new DeathRecipient() { @Override diff --git a/core/src/main/java/io/github/lsposed/lspd/service/LSPosedService.java b/core/src/main/java/io/github/lsposed/lspd/service/LSPosedService.java index e812440c..510e907b 100644 --- a/core/src/main/java/io/github/lsposed/lspd/service/LSPosedService.java +++ b/core/src/main/java/io/github/lsposed/lspd/service/LSPosedService.java @@ -11,24 +11,6 @@ import android.util.Log; import static io.github.lsposed.lspd.service.ServiceManager.TAG; public class LSPosedService extends ILSPosedService.Stub { - LSPosedService() { - BridgeService.send(this, new BridgeService.Listener() { - @Override - public void onSystemServerRestarted() { - Log.w(TAG, "system restarted..."); - } - - @Override - public void onResponseFromBridgeService(boolean response) { - if (response) { - Log.i(TAG, "sent service to bridge"); - } else { - Log.w(TAG, "no response from bridge"); - } - } - }); - } - @Override public ILSPApplicationService requestApplicationService(int uid, int pid) { if (Binder.getCallingUid() != 1000) { diff --git a/core/src/main/java/io/github/lsposed/lspd/service/ServiceManager.java b/core/src/main/java/io/github/lsposed/lspd/service/ServiceManager.java index 449bc608..1e009314 100644 --- a/core/src/main/java/io/github/lsposed/lspd/service/ServiceManager.java +++ b/core/src/main/java/io/github/lsposed/lspd/service/ServiceManager.java @@ -1,5 +1,6 @@ package io.github.lsposed.lspd.service; +import android.content.Context; import android.os.Looper; import android.util.Log; @@ -9,6 +10,18 @@ public class ServiceManager { private static LSPApplicationService applicationService = null; private static LSPManagerService managerService = null; public static final String TAG = "LSPosedService"; + + private static void waitSystemService(String name) { + while (android.os.ServiceManager.getService(name) == null) { + try { + Log.i(TAG, "service " + name + " is not started, wait 1s."); + Thread.sleep(1000); + } catch (InterruptedException e) { + Log.i(TAG, Log.getStackTraceString(e)); + } + } + } + // call by ourselves public static void start() { Log.i(TAG, "starting server..."); @@ -18,6 +31,30 @@ public class ServiceManager { moduleService = new LSPModuleService(); applicationService = new LSPApplicationService(); managerService = new LSPManagerService(); + + android.os.ServiceManager.addService("serial", mainService); + + waitSystemService("package"); + waitSystemService("activity"); + waitSystemService(Context.USER_SERVICE); + waitSystemService(Context.APP_OPS_SERVICE); + + BridgeService.send(mainService, new BridgeService.Listener() { + @Override + public void onSystemServerRestarted() { + Log.w(TAG, "system restarted..."); + } + + @Override + public void onResponseFromBridgeService(boolean response) { + if (response) { + Log.i(TAG, "sent service to bridge"); + } else { + Log.w(TAG, "no response from bridge"); + } + } + }); + Looper.loop(); Log.i(TAG, "server exited");