- 浏览: 441740 次
- 性别:
- 来自: 深圳
文章分类
最新评论
-
su6838354:
我有点疑问啊,thread1中的i自增的慢的话,thread2 ...
浅析pthread_cond_wait -
zeronever:
请问pthread_cond_signal有解锁操纵吗?我在p ...
浅析pthread_cond_wait -
paladin1988:
你这帖子真心不错。。
浅谈bitmap算法 -
parabellum_sky:
昨天还有个姑娘让我去考我说会考虑
个人日志
XposedBridge是Xposed框架替代ZygoteInit的文件,其中main方式是其入口,分析main方法可以更好的理解Xposed的运行模式,下面就来分析一下此函数。
initNative()函数对一些JNI函数的注册和回调方法的注册,JNI层对应的方法为XposedBridge_initNative,此方法后续会进行分析。
initXbridgeZygote();对Zygote进行初始化,深入探讨一下此函数,由于比较复杂,耐心跟踪一下
findAndHookMethod是关键,如何hook method,继续往下看
findAndHookMethod(ActivityThread.class, "handleBindApplication", "android.app.ActivityThread.AppBindData", new XC_MethodHook() );
这里是要find ActivityThread对象中的AppBindData方法,AppBindData在ActivityThread中是一个内部类。
XposedBridge.hookMethod(m, callback);
这句就是把find的method和callback进行关联,用callback替代AppBindData,看一下原理:
1. sHookedMethodCallbacks寻找要hook的method,如果不存在,则新建一个callback和hookmethod进行关联,sHookedMethodCallbacks.put(hookMethod, callbacks);callbacks.add(callback);
2. 如果是新hookmethod,进行hookMethodNative,进入JNI层调用XposedBridge_hookMethodNative
private static void main(String[] args) { // the class the VM has been created for or null for the Zygote process String startClassName = getStartClassName(); // initialize the Xposed framework and modules try { // initialize log file try { logFile = new File(BASE_DIR + "log/error.log"); if (startClassName == null && logFile.length() > MAX_LOGFILE_SIZE_SOFT) logFile.renameTo(new File(BASE_DIR + "log/error.log.old")); logWriter = new PrintWriter(new FileWriter(logFile, true)); logFile.setReadable(true, false); logFile.setWritable(true, false); } catch (IOException ignored) {} String date = DateFormat.getDateTimeInstance().format(new Date()); determineXposedVersion(); log("-----------------\n" + date + " UTC\n" + "Loading Xposed v" + XPOSED_BRIDGE_VERSION + " (for " + (startClassName == null ? "Zygote" : startClassName) + ")..."); if (startClassName == null) { // Zygote log("Running ROM '" + Build.DISPLAY + "' with fingerprint '" + Build.FINGERPRINT + "'"); } if (initNative()) { if (startClassName == null) { // Initializations for Zygote initXbridgeZygote(); } loadModules(startClassName); } else { log("Errors during native Xposed initialization"); } } catch (Throwable t) { log("Errors during Xposed initialization"); log(t); disableHooks = true; } // call the original startup code if (startClassName == null) ZygoteInit.main(args); else RuntimeInit.main(args); }
initNative()函数对一些JNI函数的注册和回调方法的注册,JNI层对应的方法为XposedBridge_initNative,此方法后续会进行分析。
initXbridgeZygote();对Zygote进行初始化,深入探讨一下此函数,由于比较复杂,耐心跟踪一下
private static void initXbridgeZygote() throws Throwable { final HashSet<String> loadedPackagesInProcess = new HashSet<String>(1); // normal process initialization (for new Activity, Service, BroadcastReceiver etc.) findAndHookMethod(ActivityThread.class, "handleBindApplication", "android.app.ActivityThread.AppBindData", new XC_MethodHook() { protected void beforeHookedMethod(MethodHookParam param) throws Throwable { ActivityThread activityThread = (ActivityThread) param.thisObject; ApplicationInfo appInfo = (ApplicationInfo) getObjectField(param.args[0], "appInfo"); ComponentName instrumentationName = (ComponentName) getObjectField(param.args[0], "instrumentationName"); if (instrumentationName != null) { XposedBridge.log("Instrumentation detected, disabling framework for " + appInfo.packageName); disableHooks = true; return; } CompatibilityInfo compatInfo = (CompatibilityInfo) getObjectField(param.args[0], "compatInfo"); if (appInfo.sourceDir == null) return; setObjectField(activityThread, "mBoundApplication", param.args[0]); loadedPackagesInProcess.add(appInfo.packageName); LoadedApk loadedApk = activityThread.getPackageInfoNoCheck(appInfo, compatInfo); XResources.setPackageNameForResDir(appInfo.packageName, loadedApk.getResDir()); LoadPackageParam lpparam = new LoadPackageParam(sLoadedPackageCallbacks); lpparam.packageName = appInfo.packageName; lpparam.processName = (String) getObjectField(param.args[0], "processName"); lpparam.classLoader = loadedApk.getClassLoader(); lpparam.appInfo = appInfo; lpparam.isFirstApplication = true; XC_LoadPackage.callAll(lpparam); if (appInfo.packageName.equals(INSTALLER_PACKAGE_NAME)) hookXposedInstaller(lpparam.classLoader); } }); // system thread initialization findAndHookMethod("com.android.server.ServerThread", null, Build.VERSION.SDK_INT < 19 ? "run" : "initAndLoop", new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { loadedPackagesInProcess.add("android"); LoadPackageParam lpparam = new LoadPackageParam(sLoadedPackageCallbacks); lpparam.packageName = "android"; lpparam.processName = "android"; // it's actually system_server, but other functions return this as well lpparam.classLoader = BOOTCLASSLOADER; lpparam.appInfo = null; lpparam.isFirstApplication = true; XC_LoadPackage.callAll(lpparam); } }); // when a package is loaded for an existing process, trigger the callbacks as well hookAllConstructors(LoadedApk.class, new XC_MethodHook() { @Override protected void afterHookedMethod(MethodHookParam param) throws Throwable { LoadedApk loadedApk = (LoadedApk) param.thisObject; String packageName = loadedApk.getPackageName(); XResources.setPackageNameForResDir(packageName, loadedApk.getResDir()); if (packageName.equals("android") || !loadedPackagesInProcess.add(packageName)) return; if ((Boolean) getBooleanField(loadedApk, "mIncludeCode") == false) return; LoadPackageParam lpparam = new LoadPackageParam(sLoadedPackageCallbacks); lpparam.packageName = packageName; lpparam.processName = AndroidAppHelper.currentProcessName(); lpparam.classLoader = loadedApk.getClassLoader(); lpparam.appInfo = loadedApk.getApplicationInfo(); lpparam.isFirstApplication = false; XC_LoadPackage.callAll(lpparam); } }); findAndHookMethod("android.app.ApplicationPackageManager", null, "getResourcesForApplication", ApplicationInfo.class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { ApplicationInfo app = (ApplicationInfo) param.args[0]; XResources.setPackageNameForResDir(app.packageName, app.uid == Process.myUid() ? app.sourceDir : app.publicSourceDir); } }); if (!new File(BASE_DIR + "conf/disable_resources").exists()) { hookResources(); } else { disableResources = true; } }
findAndHookMethod是关键,如何hook method,继续往下看
public static XC_MethodHook.Unhook findAndHookMethod(Class<?> clazz, String methodName, Object... parameterTypesAndCallback) { if (parameterTypesAndCallback.length == 0 || !(parameterTypesAndCallback[parameterTypesAndCallback.length-1] instanceof XC_MethodHook)) throw new IllegalArgumentException("no callback defined"); XC_MethodHook callback = (XC_MethodHook) parameterTypesAndCallback[parameterTypesAndCallback.length-1]; Method m = findMethodExact(clazz, methodName, getParameterClasses(clazz.getClassLoader(), parameterTypesAndCallback)); return XposedBridge.hookMethod(m, callback); }
findAndHookMethod(ActivityThread.class, "handleBindApplication", "android.app.ActivityThread.AppBindData", new XC_MethodHook() );
这里是要find ActivityThread对象中的AppBindData方法,AppBindData在ActivityThread中是一个内部类。
XposedBridge.hookMethod(m, callback);
这句就是把find的method和callback进行关联,用callback替代AppBindData,看一下原理:
public static XC_MethodHook.Unhook hookMethod(Member hookMethod, XC_MethodHook callback) { if (!(hookMethod instanceof Method) && !(hookMethod instanceof Constructor<?>)) { throw new IllegalArgumentException("Only methods and constructors can be hooked: " + hookMethod.toString()); } else if (hookMethod.getDeclaringClass().isInterface()) { throw new IllegalArgumentException("Cannot hook interfaces: " + hookMethod.toString()); } else if (Modifier.isAbstract(hookMethod.getModifiers())) { throw new IllegalArgumentException("Cannot hook abstract methods: " + hookMethod.toString()); } boolean newMethod = false; CopyOnWriteSortedSet<XC_MethodHook> callbacks; synchronized (sHookedMethodCallbacks) { callbacks = sHookedMethodCallbacks.get(hookMethod); if (callbacks == null) { callbacks = new CopyOnWriteSortedSet<XC_MethodHook>(); sHookedMethodCallbacks.put(hookMethod, callbacks); newMethod = true; } } callbacks.add(callback); if (newMethod) { Class<?> declaringClass = hookMethod.getDeclaringClass(); int slot = (int) getIntField(hookMethod, "slot"); Class<?>[] parameterTypes; Class<?> returnType; if (hookMethod instanceof Method) { parameterTypes = ((Method) hookMethod).getParameterTypes(); returnType = ((Method) hookMethod).getReturnType(); } else { parameterTypes = ((Constructor<?>) hookMethod).getParameterTypes(); returnType = null; } AdditionalHookInfo additionalInfo = new AdditionalHookInfo(callbacks, parameterTypes, returnType); hookMethodNative(hookMethod, declaringClass, slot, additionalInfo); } return callback.new Unhook(hookMethod); }
1. sHookedMethodCallbacks寻找要hook的method,如果不存在,则新建一个callback和hookmethod进行关联,sHookedMethodCallbacks.put(hookMethod, callbacks);callbacks.add(callback);
2. 如果是新hookmethod,进行hookMethodNative,进入JNI层调用XposedBridge_hookMethodNative
/** @function hookMethodNative 将输入的Class中的Method方法的nativeFunc替换为xposedCallHandler @para declaredClassIndirect 类对象 @para slot Method在类中的偏移位置 */ void XposedBridge_hookMethodNative(JNIEnv* env, jclass clazz, jobject reflectedMethodIndirect, jobject declaredClassIndirect, jint slot, jobject additionalInfoIndirect) { // Usage errors? if (declaredClassIndirect == NULL || reflectedMethodIndirect == NULL) { dvmThrowIllegalArgumentException("method and declaredClass must not be null"); return; } // Find the internal representation of the method ClassObject* declaredClass = (ClassObject*) dvmDecodeIndirectRef(dvmThreadSelf(), declaredClassIndirect); Method* method = dvmSlotToMethod(declaredClass, slot); if (method == NULL) { dvmThrowNoSuchMethodError("Could not get internal representation for method"); return; } if (isMethodHooked(method)) { // already hooked return; } // Save a copy of the original method and other hook info XposedHookInfo* hookInfo = (XposedHookInfo*) calloc(1, sizeof(XposedHookInfo)); memcpy(hookInfo, method, sizeof(hookInfo->originalMethodStruct)); hookInfo->reflectedMethod = dvmDecodeIndirectRef(dvmThreadSelf(), env->NewGlobalRef(reflectedMethodIndirect)); hookInfo->additionalInfo = dvmDecodeIndirectRef(dvmThreadSelf(), env->NewGlobalRef(additionalInfoIndirect)); // Replace method with our own code SET_METHOD_FLAG(method, ACC_NATIVE); method->nativeFunc = &hookedMethodCallback; method->insns = (const u2*) hookInfo; method->registersSize = method->insSize; method->outsSize = 0; if (PTR_gDvmJit != NULL) { // reset JIT cache char currentValue = *((char*)PTR_gDvmJit + MEMBER_OFFSET_VAR(DvmJitGlobals,codeCacheFull)); if (currentValue == 0 || currentValue == 1) { MEMBER_VAL(PTR_gDvmJit, DvmJitGlobals, codeCacheFull) = true; } else { ALOGE("Unexpected current value for codeCacheFull: %d", currentValue); } } }
发表评论
-
Java NIO
2015-08-09 14:58 1084java 网络编程中,不可避免的要谈论NIO,这篇文章就来谈谈 ... -
jni方法的注册和调用流程
2015-07-07 17:20 3242JNI在android中起重要作用,是连接java层和dalv ... -
MethodHooker--Hook分析
2015-07-03 17:58 2789Hook的原理是修改java层 ... -
XPosed解析--callback_XposedBridge_initNative分析
2015-07-02 10:41 2874callback_XposedBridge_initNativ ... -
ViewGroup onInterceptTouchEvent and OnTouchEvent
2014-09-16 15:46 895ViewGroup 继承View,实现了View各个方法,同时 ... -
libdgx之gdx-vectorpinball分析--整体篇
2013-09-17 09:47 1044gdx-vectorpinball分析--整体篇 gdx-v ... -
Android 归来
2011-10-21 09:09 77时隔半年,重新拾起android开发,相信自己能走下去。
相关推荐
xposed-api-82-sources resources 资源文件 和xposed-api-82放到同一个文件夹下
《Xposed框架详解:深入理解xposed-v89-sdk25-x86.zip》 Xposed框架是一款在Android系统上广泛使用的模块化开发工具,它允许开发者通过编写特定的模块来改变系统的功能或应用的行为,而无需修改APK文件。在本文中,...
- **XposedBridge API**:这是Xposed框架的核心接口,包括`IXposedHookLoadPackage`、`IXposedHookZygoteInit`等,它们定义了如何在系统启动或加载应用时执行自定义逻辑。 - **Hook技术**:理解Java反射和Method ...
由于这两种架构的不同,Xposed框架也需要为每个架构提供相应的版本,即“xposed-x86”和“xposed-x86_64”。这确保了框架在不同硬件平台上能够正常运行。 安装Xposed框架的步骤通常包括以下几步: 1. 获取对应架构...
Xposed提供`XposedBridge.log()`方法用于调试,帮助开发者查看被Hook的方法何时被调用以及传递的参数。 2. **ClassLoader Hook**:这种方法涉及到类加载过程的修改,可以控制哪些类会被加载,或者在类加载后立即...
xposed-v89-sdk25-arm86与xposed-v89-sdk25-arm64两个版本对应的系统是安卓5.0以上的
标题 "xposed-v88-sdk25-x86.zip" 提供了关于这个压缩包的重要信息,它是一个针对特定环境的 Xposed 框架版本。Xposed 是一个在 Android 系统上运行的框架,允许用户通过安装模块来修改系统行为,无需root权限。这里...
而“xposed-uninstaller-20180117-arm.zip”则是专门为Xposed框架提供的卸载工具,适用于基于ARM架构的Android 5.0系统。 在深入探讨Xposed框架之前,我们需要理解Android系统的运行机制。Android系统基于Linux内核...
xposed api 82 AndroidManifest.xml <meta-data android:name="xposedmodule" android:value="true" /> <meta-data android:name="xposeddescription" android:value="..." /> <meta-data ...
"framework-xposed-v89-sdk25-x86"这个标题表明这是Xposed框架的一个版本,针对的是Android SDK Level 25(即Android 7.1.1 Nougat)的x86架构设备。下面我们将深入探讨Xposed框架的基本概念、工作原理以及与SDK 25...
"xposed-v89-sdk25-x86.zip" 文件名表明这是一款针对Android SDK 25(即Android 7.1 Nougat)的Xposed框架版本,适用于x86架构的设备。"script.sh" 文件则可能是一个脚本,用于帮助用户安装或配置Xposed框架。 1. *...
XposedBridge的核心组件就是它的API库,这些API库通常以jar文件的形式存在,例如XposedBridgeApi-54.jar、XposedBridgeApi-82.jar、XposedBridgeApi-87.jar以及XposedBridgeAPI-89.jar。这些文件名中的数字代表了...
"xposed-v89-sdk22-x86.zip"是针对Android SDK 22(即Android 5.1)的Xposed框架的特定版本,适用于x86架构的设备。 首先,我们来详细了解一下Xposed框架的核心功能和工作原理。Xposed框架通过hooking技术在系统层...
《Xposed框架与XposedBridgeApi-89.jar详解》 在Android开发领域,Xposed框架是一个极具影响力的神器,它允许开发者通过修改系统的运行时行为,实现对系统和应用的深度定制,而无需修改APK文件。XposedBridgeApi-89...
xposed-v88-sdk23-x86.zip
XposedBridgeApi是一个用于Android系统的库,它允许开发者在不修改应用程序源代码的情况下,通过使用Xposed框架来实现对应用程序的修改和增强。XposedBridgeApi-54提供了一组API,使得开发者可以在运行时动态地修改...
内有XposedBridgeApi-82.jar XposedBridgeApi-82-source.jar两个文件 api-82.jar SHA-1:35866b507b360d4789ff389ad7386b6e8bbf6cc4 api-82-source.jar SHA-1:2030f71764b06b2f39fa1a85660690aa834cfd84
在本例中,我们有两个版本的Xposed框架:xposed-v90-sdk26-arm64-beta3.zip和xposed-v90-sdk26-arm-beta3.zip。它们分别适用于基于ARM64架构和ARM架构的Android 8.0设备。选择适合自己设备架构的版本至关重要,因为...
XposedBridgeApi是Xposed框架的核心API库,它为开发者提供了与系统底层交互的接口,使得开发者能够实现各种高级功能,如系统级别的Hook、应用程序的定制化修改等。 XposedBridgeApi-54.jar和XposedBridgeApi-87.jar...