昨花了點時間,參考github issues 總算實現了基於xposed的系統服務注入,本文目的是為了“解決應用之間hook后數據共享,任意app ServiceManager.getService就可以直接調用aidl實現了進程通信”(比如aidl service實現socket,http server等,或者從某app獲取數據傳遞給另外個app等場景,能做什么大家自己想吧,當然也可以實現非xposed版本的,需要通過直接smali方式。因為需快速實現,我就基於xposed的方案湊活用着用吧)
Xposed我就不介紹了,Xposed有2個重要接口,一個是針對應用級別hook:IXposedHookLoadPackage,另一個就是針對系統級別的:IXposedHookZygoteInit
這里將使用IXposedHookZygoteInit實現aidl添加到系統服務中,當然,通過IXposedHookLoadPackage也是可以實現的,但是因為我們注入的服務是希望像系統服務一樣,開機啟動,關機停止,另外IXposedHookZygoteInit本身就是定位在針對系統hook,所以還是建議使用IXposedHookZygoteInit。
直接進入正題:
1.創建 android.os.ICustomService.aidl
package android.os;
// Declare any non-default types here with import statements
interface ICustomService {
String sayHello();
}
2.創建CustomService實現類
1 public class CustomService extends ICustomService.Stub { 2 private Context mContext; 3 public CustomService(Context context) { 4 mContext = context; 5 } 6 7 @Override 8 public String sayHello() throws RemoteException { 9 return "Just Hello World"; 10 } 11 12 //ActivityManagerService的systemReady在所有服務初始化完成后觸發,這定義這個是為了實現自定義服務的初始化代碼實現 13 public void systemReady() { 14 // Make your initialization here 15 } 16 }
3.創建ApplicationSocket,實現IXposedHookZygoteInit接口,這實現系統啟動時候觸發hook
1 public class ApplicationSocket implements IXposedHookZygoteInit{ 2 public static String TAG = "ApplicationSocket"; 3 @Override 4 public void initZygote(StartupParam startupParam) throws Throwable { 5 XposedBridge.hookAllMethods(ActivityThread.class, "systemMain", new SystemServiceHook()); 6 } 7 }
4.創建SystemServiceHook 重寫XC_MethodHook,實現注冊服務,這也是最核心的類
1 import android.content.Context; 2 import android.os.Build; 3 import android.os.CustomService; 4 import android.os.ICustomService; 5 import android.os.ServiceManager; 6 7 import de.robv.android.xposed.XC_MethodHook; 8 import de.robv.android.xposed.XposedBridge; 9 import de.robv.android.xposed.XposedHelpers; 10 11 /** 12 * Created by bluce on 17/12/5. 13 */ 14 15 public class SystemServiceHook extends XC_MethodHook { 16 private static CustomService oInstance; 17 private static boolean systemHooked; 18 19 @Override 20 protected void afterHookedMethod(MethodHookParam param) throws Throwable { 21 if (systemHooked) { 22 return; 23 } 24 final ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); 25 Class activityManagerServiceClazz = null; 26 try { 27 activityManagerServiceClazz = XposedHelpers.findClass("com.android.server.am.ActivityManagerService", classLoader); 28 } catch (RuntimeException e) { 29 // do nothing 30 } 31 if (!systemHooked && activityManagerServiceClazz!=null) { 32 systemHooked = true; 33 //系統服務啟動完畢,通知自定義服務 34 XposedBridge.hookAllMethods( 35 activityManagerServiceClazz, 36 "systemReady", 37 new XC_MethodHook() { 38 @Override 39 protected final void afterHookedMethod(final MethodHookParam param) { 40 oInstance.systemReady(); 41 XposedBridge.log(">>>systemReady!!!!"); 42 } 43 } 44 ); 45 //注冊自定義服務到系統服務中 46 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 47 XposedBridge.hookAllConstructors(activityManagerServiceClazz, new XC_MethodHook() { 48 @Override 49 protected void afterHookedMethod(MethodHookParam param) throws Throwable { 50 Context context = (Context) XposedHelpers.getObjectField(param.thisObject, "mContext"); 51 registerService(classLoader,context); 52 } 53 }); 54 }else{ 55 XposedBridge.hookAllMethods( 56 activityManagerServiceClazz, 57 "main", 58 new XC_MethodHook() { 59 @Override 60 protected final void afterHookedMethod(final MethodHookParam param) { 61 Context context = (Context) param.getResult(); 62 registerService(classLoader,context); 63 } 64 } 65 ); 66 } 67 } 68 } 69 70 private static void registerService(final ClassLoader classLoader, Context context) { 71 XposedBridge.log(">>>register service, Build.VERSION.SDK_INT"+Build.VERSION.SDK_INT); 72 oInstance = new CustomService(context); 73 Class<?> ServiceManager = XposedHelpers.findClass("android.os.ServiceManager",classLoader); 74 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { 75 //避免java.lang.SecurityException錯誤,從5.0開始,selinux服務名稱需要加前綴"user." 76 XposedHelpers.callStaticMethod( 77 ServiceManager, 78 "addService", 79 "user.custom.service", 80 oInstance, 81 true 82 ); 83 } else { 84 XposedHelpers.callStaticMethod( 85 ServiceManager, 86 "addService", 87 "custom.service", 88 oInstance 89 ); 90 } 91 } 92 93 94 //use service demo 95 public static ICustomService mService; 96 public static String someMethod(Context context) { 97 try { 98 if (mService == null) { 99 mService=ICustomService.Stub.asInterface(ServiceManager.getService("user.wx_custom.service")); 100 //mService =(ICustomService)context.getSystemService("wx_custom.service"); 101 } 102 return mService.sayHello(); 103 } catch (Exception e) { 104 System.out.println(e.getMessage()); 105 e.printStackTrace(); 106 } 107 return ">>> someMethod failed!!! "; 108 } 109 }
5.在當前應用activity中調用系統服務,service實現可以創建成單獨的module,這樣就實現不同項目直接使用,最重要的是在當前項目xposed hook代碼中可以直接使用了,這也是本文的最初衷。
button = (Button) findViewById(R.id.testButton);
button.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
if(true){
//testPattern();return;
//HookTest.registerReceiver(context);
String str = SystemServiceHook.someMethod(MainActivity.context);
if(str!=null){
System.out.println(">>>>:::"+str);
}
return;
}
}
} ;
基於以上,CustomService整體的代碼就實現了,重啟系統就變成了系統服務,可以直接使用。但是以下2點需要特別注意:
1.com.android.server.am.ActivityManagerService是framework不公開的方法和類,所以項目需要導入AndroidHiddenAPI.jar這個包
2.android5.0之前SystemContext通過call ActivityManagerService的main方法就可以直接獲取,但是5.0開始是通過createSystemContext方法生產,所以只能判斷下版本,然后一個通過構造取獲取,一個通過main返回結果獲取
