昨花了點時間,參考github issues 總算實現(xiàn)了基于xposed的系統(tǒng)服務(wù)注入缘滥,本文目的是為了“解決應(yīng)用之間hook后數(shù)據(jù)共享轰胁,任意app ServiceManager.getService就可以直接調(diào)用aidl實現(xiàn)了進程通信”(比如aidl service實現(xiàn)socket,http server等,或者從某app獲取數(shù)據(jù)傳遞給另外個app等場景朝扼,能做什么大家自己想吧赃阀,當(dāng)然也可以實現(xiàn)非xposed版本的,需要通過直接smali方式擎颖。因為需快速實現(xiàn)榛斯,我就基于xposed的方案湊活用著用吧)
Xposed我就不介紹了,Xposed有2個重要接口搂捧,一個是針對應(yīng)用級別hook:IXposedHookLoadPackage驮俗,另一個就是針對系統(tǒng)級別的:IXposedHookZygoteInit
這里將使用IXposedHookZygoteInit實現(xiàn)aidl添加到系統(tǒng)服務(wù)中,當(dāng)然允跑,通過IXposedHookLoadPackage也是可以實現(xiàn)的王凑,但是因為我們注入的服務(wù)是希望像系統(tǒng)服務(wù)一樣,開機啟動吮蛹,關(guān)機停止,另外IXposedHookZygoteInit本身就是定位在針對系統(tǒng)hook拌屏,所以還是建議使用IXposedHookZygoteInit潮针。
直接進入正題:
1.創(chuàng)建 android.os.ICustomService.aidl
package android.os;
// Declare any non-default types here with import statements
interface ICustomService {
String sayHello();
}
2.創(chuàng)建CustomService實現(xiàn)類
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在所有服務(wù)初始化完成后觸發(fā),這定義這個是為了實現(xiàn)自定義服務(wù)的初始化代碼實現(xiàn)
13? ? public void systemReady() {
14? ? ? ? // Make your initialization here
15? ? }
16 }
3.創(chuàng)建ApplicationSocket倚喂,實現(xiàn)IXposedHookZygoteInit接口每篷,這實現(xiàn)系統(tǒng)啟動時候觸發(fā)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.創(chuàng)建SystemServiceHook 重寫XC_MethodHook,實現(xiàn)注冊服務(wù),這也是最核心的類
import android.content.Context;
import android.os.Build;
import android.os.CustomService;
import android.os.ICustomService;
import android.os.ServiceManager;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XposedHelpers;
/**
* Created by bluce on 17/12/5.
*/
public class SystemServiceHook extends XC_MethodHook {
private static CustomService oInstance;
private static boolean systemHooked;
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
if (systemHooked) {
return;
}
final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
Class activityManagerServiceClazz = null;
try {
activityManagerServiceClazz = XposedHelpers.findClass("com.android.server.am.ActivityManagerService", classLoader);
} catch (RuntimeException e) {
// do nothing
}
if (!systemHooked && activityManagerServiceClazz!=null) {
systemHooked = true;
//系統(tǒng)服務(wù)啟動完畢端圈,通知自定義服務(wù)
XposedBridge.hookAllMethods(
activityManagerServiceClazz,
"systemReady",
new XC_MethodHook() {
@Override
protected final void afterHookedMethod(final MethodHookParam param) {
oInstance.systemReady();
XposedBridge.log(">>>systemReady!!!!");
}
}
);
//注冊自定義服務(wù)到系統(tǒng)服務(wù)中
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
XposedBridge.hookAllConstructors(activityManagerServiceClazz, new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
Context context = (Context) XposedHelpers.getObjectField(param.thisObject, "mContext");
registerService(classLoader,context);
}
});
}else{
XposedBridge.hookAllMethods(
activityManagerServiceClazz,
"main",
new XC_MethodHook() {
@Override
protected final void afterHookedMethod(final MethodHookParam param) {
Context context = (Context) param.getResult();
registerService(classLoader,context);
}
}
);
}
}
}
private static void registerService(final ClassLoader classLoader, Context context) {
XposedBridge.log(">>>register service, Build.VERSION.SDK_INT"+Build.VERSION.SDK_INT);
oInstance = new CustomService(context);
Class ServiceManager = XposedHelpers.findClass("android.os.ServiceManager",classLoader);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
//避免java.lang.SecurityException錯誤,從5.0開始焦读,selinux服務(wù)名稱需要加前綴"user."
XposedHelpers.callStaticMethod(
ServiceManager,
"addService",
"user.custom.service",
oInstance,
true
);
} else {
XposedHelpers.callStaticMethod(
ServiceManager,
"addService",
"custom.service",
oInstance
);
}
}
//use service demo
public static ICustomService mService;
public static String someMethod(Context context) {
try {
if (mService == null) {
mService=ICustomService.Stub.asInterface(ServiceManager.getService("user.wx_custom.service"));
//mService =(ICustomService)context.getSystemService("wx_custom.service");
}
return mService.sayHello();
} catch (Exception e) {
System.out.println(e.getMessage());
e.printStackTrace();
}
return? ">>> someMethod failed!!! ";
}
}
5.在當(dāng)前應(yīng)用activity中調(diào)用系統(tǒng)服務(wù),service實現(xiàn)可以創(chuàng)建成單獨的module,這樣就實現(xiàn)不同項目直接使用,最重要的是在當(dāng)前項目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整體的代碼就實現(xiàn)了宴倍,重啟系統(tǒng)就變成了系統(tǒng)服務(wù)张症,可以直接使用。但是以下2點需要特別注意:
1.com.android.server.am.ActivityManagerService是framework不公開的方法和類鸵贬,所以項目需要導(dǎo)入AndroidHiddenAPI.jar這個包
2.android5.0之前SystemContext通過call ActivityManagerService的main方法就可以直接獲取俗他,但是5.0開始是通過createSystemContext方法生產(chǎn),所以只能判斷下版本阔逼,然后一個通過構(gòu)造取獲取兆衅,一個通過main返回結(jié)果獲取