Xposed学习三:基石
在上一篇我们留下问题:handleLoadPackage如何生效即在何时被执行。
先看XposedBridge.class的main(该函数是在appruntime.start函数中替换原先zygoteinit,故结尾处会调用zygoteinit):
1 private static void main(String[] args) {
2 String startClassName = getStartClassName();
3 ......
4 if(initNative()) {
5 if(startClassName == null) {
6 initXbridgeZygote();
7 }
8 // 读取/data/data/de.robv.android.xposed.installer/conf/modules.list内容,存储着模块apk的地址,
9 // 内容:/data/app/com.jason.learnxposed-2.apk
10 // 加载模块loadModule(APK,startClassName)
11 loadModules(startClassName);
12 }
13 ......
14 if(startClassName == null) {
15 ZygoteInit.main(args);
16 } else {
17 RuntimeInit.main(args);
18 }
20 }
main中分三步:initXbridgeZygote、initloadModules、ZygoteInit.main。
先来看initXbridgeZygote:
private static void initXbridgeZygote() throws Throwable {
final HashSet loadedPackagesInProcess = new HashSet(1);
XposedHelpers.findAndHookMethod(ActivityThread.class, "handleBindApplication", new Object[]{"android.app.ActivityThread.AppBindData", new XC_MethodHook() {
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
}});
XposedHelpers.findAndHookMethod("com.android.server.ServerThread", (ClassLoader)null, VERSION.SDK_INT < 19?"run":"initAndLoop", new Object[]{new XC_MethodHook() {
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
}});
hookAllConstructors(LoadedApk.class, new XC_MethodHook() {
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
});
XposedHelpers.findAndHookMethod("android.app.ApplicationPackageManager", (ClassLoader)null, "getResourcesForApplication", new Object[]{ApplicationInfo.class, new XC_MethodHook() {
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
}});
if(!(new File("/data/data/de.robv.android.xposed.installer/conf/disable_resources")).exists()) {
hookResources();
} else {
disableResources = true;
}
}
上面粉红色的诱惑很熟悉对吧,就是前面上篇分析的findAndHookMethod函数。来看下它hooked了什么函数,"handleBindApplication","initAndLoop"
"getResourcesForApplication",不要小看这几个hooked哦,这是xposed的基石。我们先不去看起before回调函数做了什么,等分析完loadModules后再回来有彩蛋。看红色警戒的hookAllConstructors,之前没见过这小子,看看他是干什么吃的。
public static Set<Unhook> hookAllConstructors(Class<?> hookClass, XC_MethodHook callback) {
......
for(int var4 = 0; var4 < var5; ++var4) {
Constructor constructor = var6[var4];
unhooks.add(hookMethod(constructor, callback));
}
......
}
原来他也是要调用hookMethod,与findAndHookMethod区别是少了findMethodExact这步。前面分析过findMethodExact是把参数+返回值+函数名组成method,这样相同的函数如果带不同的参数也可以hook(xposed会根据method来判别是否已hooked),而hookAllConstructors直接来是什么用意呢?因为在hookAllConstructors中会hook所有的构造函数故没有必要去findMethodExact。ok,上面就是几个hooked,看下面if里是hookResources道理不言而喻咯,我们先不分析这个,有空再来^_^。
再来看loadModules
private static void loadModule(String apk, String startClassName) {
......
PathClassLoader mcl = new PathClassLoader(apk, BOOTCLASSLOADER);
InputStream is = mcl.getResourceAsStream("assets/xposed_init");
// 读取apk的assets/xposed_init内容,Xposed学习一中的第五步
if(is == null) {
log("assets/xposed_init not found in the APK");
} else {
BufferedReader moduleClassesReader = new BufferedReader(new InputStreamReader(is));
......
if(startClassName == null) {
if(moduleInstance instanceof IXposedHookZygoteInit) {
StartupParam param = new StartupParam();
param.modulePath = apk;
((IXposedHookZygoteInit)moduleInstance).initZygote(param);
} if(moduleInstance instanceof IXposedHookLoadPackage) {
hookLoadPackage(new Wrapper((IXposedHookLoadPackage)moduleInstance));
} if(moduleInstance instanceof IXposedHookInitPackageResources) {
hookInitPackageResources(new de.robv.android.xposed.IXposedHookInitPackageResources.Wrapper((IXposedHookInitPackageResources)moduleInstance));
}
} else if(moduleInstance instanceof IXposedHookCmdInit) {
de.robv.android.xposed.IXposedHookCmdInit.StartupParam param1 = new de.robv.android.xposed.IXposedHookCmdInit.StartupParam();
param1.modulePath = apk;
param1.startClassName = startClassName;
((IXposedHookCmdInit)moduleInstance).initCmdApp(param1);
}
......
}
}
}
简单说下loadModule中步骤,
1. 读取Xposed_init文本里的内容,里面是我们的类名。我们可以在一个模块中写好几个功能的类,但请注意一定要将类全名字符串写到Xposed_init里且每个类字符串为一行。到此,我们就得到类名可以加载类啦;
2. 根据startClassName是否为空又可分为执行普通的xposed模块和IXposedHookCmdInit。startClassName值我们后面再深究,先继续往下看;
3. 根据功能类实现的接口又可执行多步操作(当然功能类能实现多个接口)
3.1 IXposedHookZygoteInit:
话不多说,直接执行类的initZygote(IXposedHookCmdInit类同)。这个最干脆,不像下面2个还慢慢来^—^
3.2 IXposedHookLoadPackage:——>redClock示例中使用这个接口 貌似在XC_loadPackage的call中被执行,待分析
代码就不贴了,反正在java层就是各种封装和存储。一句话总结:把类添加到
XposedBridge.CopyOnWriteSortedSet<XC_LoadPackage> sLoadedPackageCallbacks
3.3 IXposedHookInitPackageResources:
把类添加到XposedBridge.CopyOnWriteSortedSet<XC_InitPackageResources> sInitPackageResourcesCallbacks
ok,loadMoudle就算结束了。但我们得到2个list,肯定要执行的嘛。记得之前的蛋蛋吗,重新回到initXbridgeZygote分析其before回调:
代码我就不贴了,老是贴代码搞得我很水一样(* ̄rǒ ̄)。先看sLoadedPackageCallbacks,其出现在"handleBindApplication","initAndLoop","loadedAPK"的before回调函数里。那这三个是干什么的呢
handleBindApplication函数:mInstrumentation.callApplicationOnCreate(app);
initAndLoop函数:在serverThread的initAndLoop启动系统服务(在system_server的main函数中)
loadedAPK类:
不用多说,很明显其都和package有关。但是最终要的是在各自的before函数都包含代码:XC_LoadPackage.callAll(lpparam);lpparam包含sLoadedPackageCallbacks,上面的代码回去执行sLoadedPackageCallbacks中所有callbakc也就是我们在hookLoadPackage函数中添加的callback。即在此刻会调用所有实现IXposedHookLoadPackage接口的类中的handleLoadPackage()。有点绕哦,举例子就是redClock中的handleLoadPackage会在此刻被调用,如果package=com.android.systemui则会执行findAndHookMethod函数去hooked "updateClock"函数。现在理清了吧
同理来看sInitPackageResourcesCallbacks,还记得上面initXbridgeZygote中的hookResources不。在hookResources会hooked"getTopLevelResources",而其after回调函数会执行XCallback.callAll(resparam1);当然 resparam1 = new InitPackageResourcesParam(XposedBridge.sInitPackageResourcesCallbacks);
第一步initXbridgeZygote和loadMoudle到此为此了啦。
来看init之前我们还是先看下startClassName这个字符串,它涉及到刚刚分析的loadModule和下面的init。
Android是基于Linux内核构建的,它最早存在的肯定是Native世界,那么Java世界是什么时候创建的呢? ---by 深入理解android
答案就是Zygote,而Zygote是通过init读取init.rc文本中配置来创建。在init.rc(在android5.0中移到/system/core/rootdir/init_zygotexx.rc)中,关于Zygote的配置
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
执行/system/bin/app_process ,参数arg是-Xzygote /system/bin --zygote --start-system-server。在Xposed的app_main的main函数中会判断器参数是否为先前定义的字符串(自行看代码),若不是会赋值为className,而这就是我们上面的startClassName(这里如果表述有错误,往指出)。看完startClassName,我们看这里是是干什么的,执行ZygoteInit.main正式进入java世界。其实对比android原本的app_main执行流程,我们发现在XposedBridge.main中除了这个ZygoteInit.main代码(xposed结合Zygote分析)其他都是xposed自己添加的,而这也正是xposed基石,基石,基石。
疑问:类实现多个接口,但像上转接口时,每个接口时如何协调的。比如class 实现inface1 inface2,(inface1 )class和(inface2)class如何操作???
Xposed学习三:基石的更多相关文章
- Xposed学习一:初探
学习Xposed框架,在github:https://github.com/rovo89 下载XposedInstaller安装到手机上来管理Xposed的模块. 本文记录根据官方文档(资料1)在an ...
- xposed学习四:总结
xposed的学习要告一段落,接下来去学习android apk和so加固,这里我们回顾下xposed吧. xposed是个hook框架,它是基于dalvik(确切来说是目前的版本,作者说ART也快出 ...
- HTTP学习三:HTTPS
HTTP学习三:HTTPS 1 HTTP安全问题 HTTP1.0/1.1在网络中是明文传输的,因此会被黑客进行攻击. 1.1 窃取数据 因为HTTP1.0/1.1是明文的,黑客很容易获得用户的重要数据 ...
- TweenMax动画库学习(三)
目录 TweenMax动画库学习(一) TweenMax动画库学习(二) TweenMax动画库学习(三) ...
- Struts2框架学习(三) 数据处理
Struts2框架学习(三) 数据处理 Struts2框架框架使用OGNL语言和值栈技术实现数据的流转处理. 值栈就相当于一个容器,用来存放数据,而OGNL是一种快速查询数据的语言. 值栈:Value ...
- 4.机器学习——统计学习三要素与最大似然估计、最大后验概率估计及L1、L2正则化
1.前言 之前我一直对于“最大似然估计”犯迷糊,今天在看了陶轻松.忆臻.nebulaf91等人的博客以及李航老师的<统计学习方法>后,豁然开朗,于是在此记下一些心得体会. “最大似然估计” ...
- DjangoRestFramework学习三之认证组件、权限组件、频率组件、url注册器、响应器、分页组件
DjangoRestFramework学习三之认证组件.权限组件.频率组件.url注册器.响应器.分页组件 本节目录 一 认证组件 二 权限组件 三 频率组件 四 URL注册器 五 响应器 六 分 ...
- [ZZ] 深度学习三巨头之一来清华演讲了,你只需要知道这7点
深度学习三巨头之一来清华演讲了,你只需要知道这7点 http://wemedia.ifeng.com/10939074/wemedia.shtml Yann LeCun还提到了一项FAIR开发的,用于 ...
- SVG 学习<三>渐变
目录 SVG 学习<一>基础图形及线段 SVG 学习<二>进阶 SVG世界,视野,视窗 stroke属性 svg分组 SVG 学习<三>渐变 SVG 学习<四 ...
随机推荐
- 【转载】java类加载时机与过程
1 开门见山 以前曾经看到过一个java的面试题,当时觉得此题很简单,可是自己把代码运行起来,可是结果并不是自己想象的那样.题目如下: class SingleTon { private stati ...
- Mybatis系列全解(五):全网最全!详解Mybatis的Mapper映射文件
封面:洛小汐 作者:潘潘 若不是生活所迫,谁愿意背负一身才华. 前言 上节我们介绍了 < Mybatis系列全解(四):全网最全!Mybatis配置文件 XML 全貌详解 >,内容很详细( ...
- MacOS如何调整JD-GUI反编译工具字体大小
how to change the fontsize of JD-GUI in MacOS? MacOS如何调整JD-GUI反编译工具字体大小? 问题描述 JD-GUI是一款比较好用的反编译工具,不小 ...
- FreeBSD——艺术、科学、哲学概论
FreeBSD--艺术.科学.哲学概论→→→→→概论: 信息都有一定的时效性.那么现在是什么时间?现在已经发布了 FreeBSD 12.2,距离下一个版本 13.0 还有约 4 个月. 『约定』 使用 ...
- frameset、frame和div 、iframe
框架一般应用于首页的界面排版工作.把一个网页切割成多个页面管理.frame文件一般只包含框架的布局信息,不会包含其他内容,所有的页面效果都是在各个frameset页面内显示.他们都从属于frame文件 ...
- Solon 框架详解(九)- 渲染控制之定制统一的接口输出
Springboot min -Solon 详解系列文章: Springboot mini - Solon详解(一)- 快速入门 Springboot mini - Solon详解(二)- Solon ...
- fianl关键词
一.final关键字概述 final关键字具有最终或不可改变的含义,可用于修饰类.变量.方法.因此被final修饰的类.变量.方法具有以下特征: --final修饰的类不能被继承: --final修饰 ...
- for-in 语句
for-in 语句循环专门用于遍历范围,列表,元素和字典等可迭代对象. 循环中的变量的值受for-in循环控制,该变量将会在每次循环开始时自动被赋值,因此程序不应该在循环中对该变量进行赋值 for-i ...
- django 自带的用户系统
首先,我要说明一下,下面内容不是必须品,如果各位大神喜欢手写也是可以的,你也可以选择自带的功能来缩减你的代码量,提高效率! 第一步 系统配置用户表 首先,在models中创建用户表,导包 from d ...
- python基础之基本数据类型与基本运算符
一.基本数据类型 1.整数类型 作用:描述年龄.等级,电话号码等数据类型 age = 18 phone_number = 13572839204 2.浮点型 作用:描述薪资.身高等带小数的类型 hei ...