专业的来看下用Xposedxp框架最实用模块模块Xprivacy可以禁梦幻西游手游那些组件只要能正常玩就可以了。

【应用智慧大比拼】Xposed模块大全,亲测可用、
我的图书馆
【应用智慧大比拼】Xposed模块大全,亲测可用、
Xposed框架是一款可以在不修改APK的情况下影响程序运行(修改系统)的框架服务,基于它可以制作出许多功能强大的模块,且在功能不冲突的情况下同时运作。
其实说白了就是可以通过这些Xposed模块达到修改ROM或者软件的效果,从而实现一些特殊功能。
推荐理由:一款非常强大的软件,堪称神器。
安装说明:
1.先安装Xposed主程序
2.安装模板程序apk文件
3.在Xposed程序中模板中激活
4.在框架中选择重启/软重启
目录/下载/截图
主程序Xposed下载:
(530.52 KB, 下载次数: 522)
1.绿色守护
『绿色守护』帮助你甄别那些对系统全局性能和能耗有不良影响的应用程序,并通过独有的『绿色化』专利技术,阻止它们消耗您的电池电量,占用您的宝贵内存。经过『绿色化』工艺处理的应用,在您没有主动启动它们的时候,无法『偷偷』运行,而在您正常启动它们时仍然拥有完整的功能和体验,正如iPhone/iPad应用那样!
新的『应用排查顾问』将帮助您分析设备中安装的应用,找出那些启动长时间后台服务或经常性自动运行(例如网络连接改变时、解锁屏幕时、安装/卸载/更新应用时)的应用。
『绿色守护』要求提升(ROOT)权限以完成对应用的『绿色化』工艺。如果您遇到绿色化的应用无法正常进入休眠,这可能是由于您使用的ROOT权限管理工具(如『SuperUser』)有缺陷所造成,建议换用『SuperSU』。
相比其它流行的同类工具,『绿色守护』拥有独到的技术,带给您远胜它们的体验:
◆ 不同于『钛备份(专业版)』等工具中让应用彻底消失的『冻结』功能,你可以照常使用『绿色化』的应用,通过它们进行分享,创建桌面小工具,没有任何使用上的不便。设定一次,忘却烦恼!
◆ 不同于『App Quarantine』,你可以方便的以往常的方式启动应用,不需要特殊的『应用启动小工具』,不用记得每次运行完后手动冻结(禁用)。
◆ 不同于『Autostarts』,你既能享受到它的绝大部分优势,又不必跟复杂晦涩的底层技术打交道,而且最重要的是,在应用运行期间,你不会失去任何重要功能。
◆ 不同于那些『XXX 进程杀手/任务管理』,你的设备不会陷入『应用偷偷运行,工具疲于猎杀』的『猫鼠游戏』,那样只会无端消耗更多电量,而且显著降低系统响应速度。因为所有经过『绿色化』的应用在你没有启动它们的时候,都处于深度的休眠状态,完全没有需要不断猎杀它们的烦恼。
作为一个底线,『绿色守护』自己必须启动一个后台『清洁工』服务,才能将经过绿色化的应用置于休眠状态。这个后台服务在设计和实现都以『超轻量化』为首要目标,它的平均内存消耗仅有2M左右。
重要说明:『绿色化』一个应用,意味着您确确实实希望这个应用在不启动的时候休眠,也就是说它的所有后台功能(机制)在休眠期间都不再工作。这些后台功能(机制)包括但不限于:(涉及技术术语,仅供专业人士理解)
(841.77 KB, 下载次数: 1044)
2.UniconUnicon图标随便换让你在任何Launcher上使用Nova/Apex/ADW等特制的图标美化包,注意:需要ROOT的Android 4.0+
需要支持JIT的ROM
与MIUI不兼容
(759.94 KB, 下载次数: 789)
3.SIM Number ChangerSIM Number Changer能够帮助你修改sim卡中登记的号码,虚拟一个假电话号码(需要安装Xposed框架后在其中激活使用)SIM Number Changer不是真的去改号码,这个东东对那些无良应用应该是起作用的,他盗走的只是你的假号码。
(25.22 KB, 下载次数: 334)
4.XThemeEngine
XThemeEngine能让你的机器使用CM10的主题,不需要去刷zip主题包,安装对应的主题apk,到XThemeEngine激活即可。(需要安装Xposed框架后在其中激活使用)
就是非cm10的rom来用cm10的主题,这个应该还是很有实用价值的,CM的主题质感都很好。
(1020.06 KB, 下载次数: 861)
安装后请到Xposed框架中激活使用。
Apply any color for lock-screen glow-dot
Change predefined lock icons for lock-screen
Change predefined lockring icons for lock-screen
(470.85 KB, 下载次数: 380)
6.Xposed Tweakbox
Xposed Tweakbox是一款系统定制软件,可以对通知栏、电池、手机等进行功能定制-xda原帖。(需要安装Xposed框架后在其中激活使用)
状态栏酒吧数量为信号强度指示器背景颜色。看起来怪怪的其实是因为大多数应用程序这是不可缺少的。钟彩切换“切换输入法”的通知,同时输入文本CRT (见下文要求 - 可能不会为你工作)CRT离效应CRT上的效果CRT景观检测电池水平的关键/低电量警告禁止三星的“ 100 %收取,现在拔掉我”的通知电话振动对呼叫等待增大铃声音量通话录音(见下文要求 - 可能不会为你工作)内置的SIP杂项从USB / AC拔出时,不要打开屏幕选择长HOME键的行为(什么都不做,古典/图标只,新/缩略图) 。只需设置一个开关,实现了在ROM存在。跳过曲目通过长按音量加/减键上,从这里移植(仅当屏幕关闭)英文:Xposed Tweakbox是一款系统定制软件,可以对通知栏、电池、手机等进行功能定制。(需要安装Xposed框架后在其中激活使用)
Number of bars for signal strength indicator
Background color. Looks weird actually because most apps aren't made for this.
Clock color
Toggle "switch input method" notification while typing text
CRT (see below for requirements - will probably not work for you)
CRT off effect
CRT on effect
CRT landscape detection
Levels for critical/low battery warning
Disable Samsung's "100% charged, unplug me now" notification
Vibrate on Call Wait
Increasing Ringer Volume
Call Recording (see below for requirements - will probably not work for you)
Built-in SIP
Miscellaneous
Don't turn on the screen when unplugging from USB/AC
Choose long HOME key behaviour (do nothing, classical/icon-only, new/thumbnails). Just sets a switch, the implementation has to exist in the ROM.
Skip tracks with a long press on the volume up/down key, ported from here (only when screen is off)
(67.92 KB, 下载次数: 417)
7.Per APP Density Setting
Per APP Density Setting是一款可以针对单个应用进行设置的工具,需要Xposed框架支持。
v1.7.1:Brazilian Portuguese
Chinese (Simplified)
Chinese (Traditional)
(105.29 KB, 下载次数: 233)
8.X隐私XPrivacyX隐私XPrivacy是一款基于Xposed框架的模块应用,可以对所有应用可能泄露隐私的权限进行管理,对禁止可能会导致崩溃的应用采取欺骗策略,提供伪造信息。 v2.0.1:Reverted restriction for time zone (issue)
Updated Norwegian translation
(741.53 KB, 下载次数: 336)
9.XBlast ToolsXBlast Tools(原Status Bar Clock Color Mod)能够在不修改apk的情况下允许你改变颜色的状态栏和通知栏时钟颜色。(需要安装Xposed框架后在其中激活使用)v1.8.0:
★Bug修复 ★增加了状态栏和导航栏的手势像左轻扫,右滑动,长按,双击 ★代码清理 ★新增总开关,以通知面板调整 ★新增总开关导航栏调整 ★新增总开关toast通知调整 ★组织了一些在meaningfull方式的调整 ★更新翻译英文:
★ Bug fixes
★ Added statusbar and navigationbar gestures like left swipe, right swipe, long press, double tap
★ Code Cleanup
★ Added master switch to notification panel tweaks
★ Added master switch to navigationbar tweaks
★ Added master switch to toast notification tweaks
★ Organized some of the tweaks in the meaningfull way
★ Updated translations
(4.68 MB, 下载次数: 971)
10.XBatteries
XBatteries是一款美化软件,可以更换电池图标,同时还可以对颜色等进行自由定制。(需要安装Xposed框架后在其中激活使用)
(15.98 MB, 下载次数: 1340)
11.PeerBlock
PeerBlock为一套P2P防护的软体。有时候我们在下载BT或在网路上与不认识的人传输资料时,往往都会遇到恶意的使用者来干扰您。所以,这时您就可以利用这套软体,来封锁他的IP。
软体特色。(需要安装Xposed框架后在其中激活使用)
自动帮您封锁恶意的IP。
让您与广告、间谍等恶意的网址说再见。
使您在使用P2P或BT可以比较不被受攻击。
软体会定时更新封锁的清单。
1. Install XPosed Framework
2. Install PeerBlock For Android
3. Create a directory in the sdcard called "PeerBlockLists"
4. Go into XPosed Framework Installer and enable "PeerBlock For Android"
5. Reboot your device
6. Now go to the
7. Take any list you wish for example,
8. Press the Update button to download the list (or copy the Update URL into your browser to download it)
9. Now simply copy/paste the .txt file into the sdcard in the folder PeerBlockLists
10. Go into the PeerBlock app and tick "Block DNS" and "Block 'Ad' Keyword in the Host name"
11. Go to the second tab "Block Lists" now hit the "Rebuild cache blocklist"
12. Reboot your device and enjoyv1.03:DNS/Connection counters
double icons
Memory leak fix
Added history, system apps included
Created CSV Format for saving settings
Apps with abnormal I/O behavior will get no internet
Updated error handling in rebuilding the cache list
Block hosts/subnet/ip from the history
App will be shown now in the 'Last Blocked Host'
Added comma's at the 'Blocking xx Ips' to read it better
Hooking a extra API if some rooted apps are calling it directly
Added to changelogs and about scrollbars
(603.88 KB, 下载次数: 254)
12.重力工具箱GravityBox重力工具箱GravityBox是一款依赖Xposed框架支持的全能系统工具,可以修复MTK6589的一些bug,通知支持修改rom参数。
(2.78 MB, 下载次数: 1348)
13.inMinGuard去广告inMinGuard去广告是一款基于xposed框架的去除广告工具。需要安装Xposed框架后在其中激活重启使用)v1.7.0:UI: show detected ad network after execution of apps
API based blocking: Tapfortap ad network is added
(1.03 MB, 下载次数: 831)
14.XMultiWindowXMultiWindow是一款xposed插件,可以实现多窗口效果,安装重启后滑动屏幕侧边激活即可。 (需要安装Xposed框架后在其中激活使用)
(142.38 KB, 下载次数: 639)
15.Tinted Status BarTinted Status Bar是一款Xposed框架的插件,可以将状态栏的颜色和app调整为一体,实现更好的视觉效果。
(364.45 KB, 下载次数: 574)
16.SwipeBackSwipeBack是一款手势加强软件,需要Xposed框架支持(安装后在框架中选择使用,然后重启手机即可),提供的是返回功能,有三种手势,从上到下,从左到右,从右到左。v2.0.0:* New: Per-app settings
* Removed: First-run tutorial
* NOTICE: AFTER UPGRADING TO THIS VERSION, YOUR SETTINGS BEFORE WILL BE LOST
(115.73 KB, 下载次数: 293)
17.XHaloFloatingWindowXHaloFloatingWindow是一款桌面漂浮空间,自定义后可以在桌面快速的开启应用。需要Xposed框架支持。v2.20 Beta:· Add Tinted TitleBar Option (based on Tinted StatusBar by @MohammadAG)
· Add Option to Force Apps in Recents
· Add another Whitelist / Blacklist Option
· Add Customizable TitleBar Separator (Thanks to @pijulius)
· Add option to toggle if app shows a notification in statusbar when you minimize it (Thanks to @pijulius)
· Change "Hide Entire App" to "Minimize App" for Corner Actions.
(125.77 KB, 下载次数: 155)
18.XuiMod XuiMod 一款专门设计用於修改状态栏时钟和置顶电池的模块。注:(需要安装Xposed框架激活后才能使用)功能说明:
- 时钟模块,状态栏时钟(如上午10时59分59秒)
- 电池模块
- 动画模块(ListView中持久的高速缓存、黑名单的应用程式使用ListView动画)
- 其他模块(音量禁用锁屏)
- 支持滑动显示动画
v2.1.1:Fix French Translation not shown (thanks @Micks29 for pointing out)
(238.95 KB, 下载次数: 245)
19.安卓调谐器Android Tuner安卓调谐器Android Tuner是款应用合集,合并了电量显示器小部件、系统调整和多任务切换小部件等。功能说明:
- 支持Android 4.1.x Logcat 阅读器,自动备份的已安装的应用程序
- 可设置自动终止应用程序分类及触发条件,支持创建CWM备份包
- 清理缓存、垃圾、进程等后重新启动,4种图形监视窗口小部件
- 拥有功能超级强大的防火墙功能,管理每个访问网络应用程序
- 支持一键调整、调整ROM、内核、存储访问、内存管理器等
- 支持快速优化及清理,可设置备份更新、优化加载速度等
- 查看电池详细信息及健康状态,并进行估计和图标显示
- 可对系统控制进行调整、备份、还原默认、开机时应用
- 查看并管理开机启动项目、设置自定义程序开机自启
- 支持最大4*6面板的专家模式,便于打开想要的功能
- 开启/关闭 APN、 蓝牙发现、 GPS 和 WiFi本地化
- 可测试和调整SD卡读取速度,支持内存详细分析v1.0RC4:New network connection list in network manager
New shortcut to force-stop/crystallize apps
Updated %/h algorithm to reduce spikes
New pause/play option in task manager
New zip-align option in (de)odexer
... see info in app for all details
(8.88 MB, 下载次数: 1498)
20.终极动态导航栏Ultimate Dynamic Navbar终极动态导航栏Ultimate Dynamic Navbar可以在屏幕上模拟导航键,多种样式,尺寸自定义,最多可以添加5个按钮。
(611.84 KB, 下载次数: 344)
21.BootManagerBootManager是一款可以对开机自动启动的程序进行管理的软件。(需要安装Xposed框架后在其中激活使用)v2.0.0:Android 2.3 Gingerbread (API10) support
Fixed utf-8 displaying again
Translation: Polnisch by Andrev01
(141.67 KB, 下载次数: 230)
TA的最新馆藏
喜欢该文的人也喜欢当前位置:
1. 确保手机已有Root权限,然后安装X框架(Xposed)和X隐私(Xprivacy)  备注:靠谱已默认安装了X框架传奇最经典网页版,多人团战跨服竞技玩法冰火战场,十年最经典游戏,英雄合击,3D特效绚丽,赶紧注册试玩一下!
&&==&&2. 都安装完后打开X框架(Xposed),然后【框架】接着进行【安装/更新】,安装完成后需重启手机如下图所示3. 验证是否框架安装成功,查看是否激活4. 打开X框架(Xposed)的模块,勾选X隐私(Xprivacy),关机重启5. 打开X隐私,按返回键跳过帮助介绍,找到【】并进行勾选6. 点击【梦幻西游】进去详情列表,找到系统选项,展开子选项7. 将系统里的选项全部打钩下,一定要全勾选上8. 勾选完后返回主界面,打开游戏,打开蜂窝,然后就可以了,但是没办法百分百保证不封号,用辅助需谨慎
《梦幻西游手游》常见问题汇总
《梦幻西游手游》教程汇总
游戏版本:v1.128.0
类型:角色
发布大小:233.43MB
游戏语言:中文
操作系统:2.2或更高
更新时间:
《双世宠妃》一播出可谓是非常的火爆啊,许多小伙伴都在狂追这部剧哦…
快手id升级快手号是什么意思?玩快手的小伙伴都希望别人能轻松记住…
手游常见问题
奶块是一款非常好玩的手游,许多小伙伴都在玩,但是有的地方是需要权…
王者荣耀怎么获得荣耀战力?荣耀战力许多小伙伴们都在想办法获取,但…
单机常见问题
微信扫描关注公众号
. Some rights reserved
湘ICP备号-3
苏网文〔-015号
湘公网安备20【图片】【教程】Xposed框架使用教程【三星吧】_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0成为超级会员,使用一键签到本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:635,865贴子:
【教程】Xposed框架使用教程收藏
你,是否羡慕过iOS的流畅吗?你,是否还在为安卓手机复杂的权限烦恼?你,是否还在苦闷自己的手机为什么没有某某品牌机的某个功能?喜欢Cydia内强大的插件?如果,给你说安卓端有一款体积只有几百K就能满足你以上所有需求的软件,它就是XDA大神出品的Xposed框架,拥有骇客级别的功能!Xposed框架是一款可以在不修改APK的情况下影响程序运行(修改系统)的框架服务,基于它可以制作出许多功能强大的模块,且在功能不冲突的情况下同时运作。当然了,运行它是需要Root权限的。
Xposed框架可以帮我们实现很多你希望湖综合你还不知道的一些功能,仿佛我们手中的安卓手机是一款还未被发掘的超级利器,做一个骇客,将其潜能完全发掘出来吧!你,现在也就用了手机的20%能量,其实它还可以做到更好! Xposed框架—————————————————————
先来认识和了解下这个框架吧!我们可以把这个框架理解为我们要造房子的地基,任何需功能的功能就是需有地基才能安装运行。而它却不编辑系统文件,这样就更加安全和放心来运行程序来实现我们需要的功能!
Xposed框架主界面如上图!共三个主要功能:核心框架,应用模块,下载模块。
首次安装后,我们需要进入核心框架内,安装更新,以保证它运行在最新版的状态!点击下图第一个按钮“安装/更新”。
这是Xposed框架会提示需要root权限了,授权下就好了,然后重新启动你的手机。
Xposed框架能做什么?—————————————————————·管理安卓权限
其实Xposed框架搭建好之后,我需要做的就是安装一些应用模块了!先来谈谈安卓的权限吧,印象最深的应该属于腾讯家的应用了,需要权限极多,但是作为我们生活、社交的必须品又不能不装,是不是很头疼呢!?
XPrivacy,又称X隐私。是Xposed框架框架内极其火爆的一款核心应用,可以对所有应用可能泄露隐私的权限进行管理,对禁止可能会导致崩溃的应用采取欺骗策略,提供伪造信息。下面我们来了解下这款神器的应用吧!
第一次时会有引导提示的,下图蓝色内容就是引导指示:
点击应用后还会有相应的提示:
以QQ最新版为例,需要X隐私进行管理和伪造的,请勾选就可以了。没有想象中那么难,还都是中文解释的。
除此之外,X隐私还提供了更多详细的功能,点击右上角就可以了。比如清除权限限制,在线限制规则等。
其实X隐私,还能自动设置某项权限的的伪造信息,比如他有电话权限,当他获取这些信息的时候获取的就是你伪造的,想想就很好玩啊!这不就是骇客在做的么!?获取我手机号,得到的是充值电话,哇咔咔!
绿色守护,帮助你甄别那些对系统全局性能和能耗有不良影响的应用程序,并通过独有的“绿色化”专利技术,阻止它们消耗电池电量及占用内存!经过“绿色化”工艺处理的应用,在您没有主动启动它们的时候,无法“偷偷”运行,而在您正常启动它们时仍然拥有完整的功能和体验,正如iPhone/iPad应用那样!说白了就是阻止他们自动启动!
这里提供一个捐赠版,需要安装顺序就是先安装捐赠包,再安装主程序。
之后进入Xposed框架内,选择应用模块,就会看到我们刚刚安装的绿色守护了。
激活下,如果没有下面这个就直接跳到启用。
启用绿色守护模块!
重启手机之后,找到安装后的应用里,系统应用里哈,不是Xposed框架里的了。运行后就会看到下面这张图了:
首次运行会有相关引导操作。
详细使用方法 是这样的:点击左下角的“+”标识,进入到应用排查顾问列表了。
这里会看到后台运行中的应用以及定期运行的程序等。
点击我们需要监控并组织的应用,支持多选。
之后点击右上角的“√”,就可以啦!
可以慢慢添加,这些被精致的应用都会出现在绿色守护里。
以后这些程序如果后台自动启动了话,程序会将他们自动禁止。
右下角的功能菜单,试验性特性和创建休眠快捷方式。
冰箱购买,苏宁易购,品牌齐全,全国联保,爆款钜惠,全网底价,买到即赚到,急速送达!冰箱购买,极速制冷,节能省电,苏宁易购一站式购物商城,您的放心之选!
以后这些程序如果后台自动启动了话,程序会将他们自动禁止。
右下角的功能菜单,试验性特性和创建休眠快捷方式。
创建快捷方式的话,我们桌面上有一个图标,点击后会立即休眠我们列表里的所有程序。
而试验性功能也是非常先进的,依照自己的需求进行选择吧!
以后这些程序如果后台自动启动了话,程序会将他们自动禁止。
右下角的功能菜单,试验性特性和创建休眠快捷方式。
创建快捷方式的话,我们桌面上有一个图标,点击后会立即休眠我们列表里的所有程序。
而试验性功能也是非常先进的,依照自己的需求进行选择吧!
怎样发现、下载一款Xposed框架应用?—————————————————————
Xposed框架内置了下载功能,我们只需在下载模块里点击之后,进行浏览、下载、搜索就可以了!
默认按时间的先后顺序排列的,顶部有放大镜图标,就是搜索功能了。
找到自己喜欢的就尝试下载吧,看到底部的下载按钮了么? Xposed框架应用模块推荐—————————————————————
XPrivacy,X隐私。可以对所有应用可能泄露隐私的权限进行管理,对禁止可能会导致崩溃的应用采取欺骗策略,提供伪造信息.
绿色守护。帮助你甄别那些对系统全局性能和能耗有不良影响的应用程序,并通过独有的“绿色化”专利技术,阻止它们消耗电池电量,占用内存!
XuiMod。一款专门设计用於修改状态栏时钟和置顶电池的模块。
Icon Themer图标随便换让你在任何Launcher上使用Nova/Apex/ADW等特制的图标美化包。
XLockY定制锁屏是一款能够对你的机子锁屏界面进行定制,比如锁屏图标,发光点颜色,锁环图标,适用于原生系列的ROM(如CM、AOKP、SLIM等)。
Xposed Tweakbox是一款系统定制软件,可以对通知栏、电池、手机等功能进行定制。
XBlast Tools状态栏颜色能够在不修改apk的情况下允许改变你的状态栏和通知栏时钟等颜色。
好!(此评论虽然才1个字,但语法严谨,用词工整,结构巧妙,琅琅上口,可谓言简意赅,足见评论人扎实的文字功底,以及信手拈来的写作技巧和惨绝人寰的创造能力,令人佩服佩服,再加上以感叹号收尾,实在是点睛之笔)
这不是跟360的超强模式差不多么
膜拜六六大神!
怕被砖头啊和无限重启
为什么我的红米note点击安装更新就开不了机了??????????
控制开机启动某软件应该下什么模块
控制权限和后台启动,用lbe就可以了啊!
这是什么东西?有用么?
楼主在吗?急需啊,下载了一个全是英文的,不会弄楼主有没有安装包啊,求一个,好人
曾经用9500,在机锋上找的包,里面就自带这个,可惜当时不会用,现在换S6了,第三方ROM不是很稳定,所以不敢折腾
登录百度帐号推荐应用6576人阅读
1&Introduction
Xposed&是&GitHUB&上&rovo89&大大设计的一个针对&Android&平台的动态劫持项目,通过替换&/system/bin/app_process&程序控制&zygote&进程,使得&app_process&在启动过程中会加载&XposedBridge.jar&这个&jar&包,从而完成对系统应用的劫持。
Xposed&框架的基本运行环境如下:
因为&Xposed&工作原理是在&/system/bin&目录下替换文件,在&install&的时候需要&root&权限,但是运行时不需要&root&权限。
需要在&Android&4.0&以上版本的机器中
&Xposed&在线资源可以参照:&
& & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & &&&
& & & & &2. &GitHub&上的&Xposed&资源梳理一下,可以这么分类:
XposedBridge.jar&:&XposedBridge.jar&是&Xposed&提供的&jar&文件,负责在&Native层与&FrameWork&层进行交互。&/system/bin/app_process&进程启动过程中会加载该&jar&包,其它的&Modules&的开发与运行都是基于该&jar&包的。Xposed&:&Xposed&的&C++&部分,主要是用来替换&/system/bin/app_process&,并为&XposedBridge&提供&JNI&方法。XposedInstaller&:&Xposed&的安装包,负责配置&Xposed&工作的环境并且提供对基于&Xposed&框架的&Modules&的管理。XposedMods&:使用&Xposed&开发的一些&Modules&,其中&AppSettings&是一个可以进行权限动态管理的应用
1.2&Mechanism&:原理
1.2.1&Zygote
在&Android&系统中,应用程序进程都是由&Zygote&进程孵化出来的,而&Zygote&进程是由&Init&进程启动的。&Zygote&进程在启动时会创建一个&Dalvik&虚拟机实例,每当它孵化一个新的应用程序进程时,都会将这个&Dalvik&虚拟机实例复制到新的应用程序进程里面去,从而使得每一个应用程序进程都有一个独立的&Dalvik&虚拟机实例。
Zygote&进程在启动的过程中,除了会创建一个&Dalvik&虚拟机实例之外,还会将&Java&运行时库加载到进程中来,以及注册一些&Android&核心类的&JNI&方法来前面创建的Dalvik&虚拟机实例中去。注意,一个应用程序进程被&Zygote&进程孵化出来的时候,不仅会获得&Zygote&进程中的&Dalvik&虚拟机实例拷贝,还会与&Zygote&一起共享&Java&运行时库&。这也就是可以将XposedBridge&这个&jar&包加载到每一个&Android&应用程序中的原因。&XposedBridge&有一个私有的&Native&(&JNI&)方法&hookMethodNative,这个方法也在&app_process&中使用。这个函数提供一个方法对象利用&Java&的&Reflection机制来对内置方法覆写。具体的实现可以看下文的&Xposed&源代码分析。
1.2.2&Hook/Replace
Xposed&&框架中真正起作用的是对方法的&hook&。在&Repackage&技术中,如果要对APK&做修改,则需要修改&Smali&代码中的指令。而另一种动态修改指令的技术需要在程序运行时基于匹配搜索来替换&smali&代码,但因为方法声明的多样性与复杂性,这种方法也比较复杂。
在&Android&系统启动的时候,&zygote&进程加载&XposedBridge&将所有需要替换的&Method&通过&JNI&方法&hookMethodNative&指向&Native&方法&xposedCallHandler&,&xposedCallHandler&在转入&handleHookedMethod&这个&Java&方法执行用户规定的&Hook&Func&。
XposedBridge&这个&jar&包含有一个私有的本地方法:&hookMethodNative&,该方法在附加的&app_process&程序中也得到了实现。它将一个方法对象作为输入参数(你可以使用&Java&的反射机制来获取这个方法)并且改变&Dalvik&虚拟机中对于该方法的定义。它将该方法的类型改变为&native&并且将这个方法的实现链接到它的本地的通用类的方法。换言之,当调用那个被&hook&的方法时候,通用的类方法会被调用而不会对调用者有任何的影响。在&hookMethodNative&的实现中,会调用&XposedBridge中的handleHookedMethod这个方法来传递参数。&handleHookedMethod&这个方法类似于一个统一调度的&Dispatch&例程,其对应的底层的&C++&函数是&xposedCallHandler&。而&handleHookedMethod&实现里面会根据一个全局结构&hookedMethodCallbacks&来选择相应的&hook&函数,并调用他们的&before,&after&函数。
当多模块同时&Hook&一个方法的时候,&Xposed&会自动根据&Module&的优先级来排序,调用顺序如下:
A.before&-&&B.before&-&&original&method&-&&B.after&-&&A.after
2&&源代码分析
2.1&Cpp&模块
该部分的源代码地址是:&&,其文件分类如下:
app_main.cpp&:类似&AOSP&中的&frameworks/base/cmds/app_process/app_main.cpp,即/system/bin/app_process&这个&zygote&真实身份的应用程序的源代码。关于&zygote&进程的分析可以参照&Android:AOSP&Core&中的&Zygote&进程详解。xposed.cpp&:提供给&app_main.cpp&的调用函数以及&XposedBridge&的&JNI&方法的实现。主要完成初始化工作以及&Framework&层的&Method&的&Hook&操作。xposed.h&,&xposed_offsets.h&:头文件
& Xposed&框架中的&app_main.cpp&相对于&AOSP&的&app_main.cpp&中修改之处主要为区分了调用&runtime.start()&函数的逻辑。&Xposed&框架中的&app_main.cpp&在此处会根据情况选择是加载&XposedBridge&类还是&ZygoteInit&或者&RuntimeInit&类。而实际的加载&XposedBridge&以及注册&JNI&方法的操作发生在第四步:&xposedOnVmCreated中。
1.包含&cutils/properties.h&,主要用于获取、设置环境变量,&xposed.cpp&中需要将&XposedBridge&设置到&ClassPath&中。
2.包含了&dlfcn.h&,用于对动态链接库的操作。
3.包含了&xposed.h&,需要调用&xposed.cpp&中的函数,譬如在虚拟机创建时注册JNI&函数。
4.增加了&initTypePointers&函数,对于&Android&SDK&大于等于&18&的会获取到&atrace_set_tracing_enabled&函数指针,在&Zygote&启动时调用。
5.AppRuntime&类中的&onVmCreated&函数中增加&xposedOnVmCreated&函数调用。
6.源代码中的&Log*&全部重命名为&ALog*,&所以&Logv&替换为&Alogv&,但是功能不变。
7.Main&函数开始处增加了大量的代码,但是对于&SDK&版本小于&16&的可以不用考虑。
2.1.1&Main&函数:&zygote&入口
int main(int argc, char* const argv[])
initTypePointers();
xposedInfo();
xposedEnforceDalvik();
keepLoadingXposed = !isXposedDisabled() && !xposedShouldIgnoreCommand(className, argc, argv) && addXposedToClasspath(zygote);
if (zygote) {
runtime.start(keepLoadingXposed ? XPOSED_CLASS_DOTS : &com.android.internal.os.ZygoteInit&,
startSystemServer ? &start-system-server& : &&);
} else if (className) {
runtime.mClassName = classN
runtime.mArgC = argc -
runtime.mArgV = argv +
runtime.start(keepLoadingXposed ? XPOSED_CLASS_DOTS : &com.android.internal.os.RuntimeInit&,
application ? &application& : &tool&);
fprintf(stderr, &Error: no class name or --zygote supplied.\n&);
app_usage();
LOG_ALWAYS_FATAL(&app_process: no class name or --zygote supplied.&);
return 10;
void initTypePointers()
char sdk[PROPERTY_VALUE_MAX];
const char *
property_get(&ro.build.version.sdk&, sdk, &0&);
RUNNING_PLATFORM_SDK_VERSION = atoi(sdk);
dlerror();
if (RUNNING_PLATFORM_SDK_VERSION &= 18) {
*(void **) (&PTR_atrace_set_tracing_enabled) = dlsym(RTLD_DEFAULT, &atrace_set_tracing_enabled&);
if ((error = dlerror()) != NULL) {
ALOGE(&Could not find address for function atrace_set_tracing_enabled: %s&, error);
上述代码中的keepLoadingXposed&变量主要用于判断是否需要继续加载Xposed&框架,其中&isXposedDisabled&、&xposedShouldIgnoreCommand&以及&addXposedToClasspath&都定义在&xposed.cpp&中。
2.1.2&keepLoadingXposed&:判断是否需要加载&XposedBridge&&
bool isXposedDisabled() {
if (access(XPOSED_LOAD_BLOCKER, F_OK) == 0) {
ALOGE(&found %s, not loading Xposed\n&, XPOSED_LOAD_BLOCKER);
return true;
return false;
该函数通过读取&/data/data/de.robv.android.xposed.installer/conf/disabled&文件(Xposed&框架通过&XposedInstaller&管理,需要安装此&APK&文件),来判断&Xposed&框架是否被禁用,如果该文件存在,则表示禁用&Xposed&。
2.xposedShouldIgnoreCommand
为了避免Superuser类似工具滥用Xposed的log文件,此函数会判断是否是SuperUser等工具的启动请求。
bool xposedShouldIgnoreCommand(const char* className, int argc, const char* const argv[]) {
if (className == NULL || argc & 4 || strcmp(className, &mands.am.Am&) != 0)
return false;
if (strcmp(argv[2], &broadcast&) != 0 && strcmp(argv[2], &start&) != 0)
return false;
bool mightBeSuperuser = false;
for (int i = 3; i & i++) {
if (strcmp(argv[i], &com.noshufou.android.su.RESULT&) == 0
|| strcmp(argv[i], &eu.chainfire.supersu.NativeAccess&) == 0)
return true;
if (mightBeSuperuser && strcmp(argv[i], &--user&) == 0)
return true;
char* lastComponent = strrchr(argv[i], '.');
if (!lastComponent)
if (strcmp(lastComponent, &.RequestActivity&) == 0
|| strcmp(lastComponent, &.NotifyActivity&) == 0
|| strcmp(lastComponent, &.SuReceiver&) == 0)
mightBeSuperuser = true;
return false;
3.addXposedToClasspath
若有新版本的XposedBridge,重命名为XposedBridge.jar并返回判断XposedBridge.jar文件是否存在,若不存在,返回false,否则将XposedBridge.jar添加到CLASSPATH环境变量中,返回true。
2.1.3&runtime.start()&:初始化&Dalvik&虚拟机
一般情况下keepLoadingXposed值为true,以启动Zygote为例(zygote==true),分析接下来的代码。
runtime&.&start&(&keepLoadingXposed&&?&&XPOSED_CLASS_DOTS&&:&&&&com.android.internal.os.RuntimeInit&&,
&&&&&&&&&&&&&&&&application&&?&&&&application&&&&:&&&&tool&&);
这一行代码是根据keepLoadingXposed&的值来判断是加载Xposed&框架还是正常的ZygoteInit&类。&keepLoadingXposed&值为&true,&则会加载&XPOSED_CLASS_DOTS&类,&XPOSED_CLASS_DOTS&值为&de.robv.android.xposed.XposedBridge&,即&XposedBridge&类。
runtime&是&AppRuntime&的实例,&AppRuntime&继承自&AndroidRuntime&。
static AndroidRuntime* gCurRuntime = NULL;
AndroidRuntime::AndroidRuntime()
assert(gCurRuntime == NULL);
gCurRuntime = this;
AndroidRuntime::start(const&char*&className,&const&char*&options)&函数完成&Dalvik&虚拟机的初始化和启动以及运行参数&className&指定的类中的&main&方法。当启动完虚拟机后,会调用&onVmCreated(JNIEnv*&env)&函数。该函数在&AppRuntime&类中被覆盖。因此直接看&AppRuntime::onVmCreated(JNIEnv*&env)&。
virtual void onVmCreated(JNIEnv* env)
keepLoadingXposed = xposedOnVmCreated(env, mClassName);
if (mClassName == NULL) {
char* slashClassName = toSlashClassName(mClassName);
mClass = env-&FindClass(slashClassName);
if (mClass == NULL) {
ALOGE(&ERROR: could not find class '%s'\n&, mClassName);
free(slashClassName);
mClass = reinterpret_cast&jclass&(env-&NewGlobalRef(mClass));
Xposed&相对于&AOSP&就增加了如下代码:
keepLoadingXposed&&=&&xposedOnVmCreated&(&env&,&&mClassName&);
调用了&xposed.cpp&中的&xposedOnVmCreated(JNIEnv*&env,&const&char*&className)&函数。
2.1.4&xposedOnVmCreated:加载Xposedbridge
该函数的主要作用如下:
1.&根据&JIT&是否存在对部分结构体中的成员偏移进行初始化。
xposedInitMemberOffsets&();
即时编译(&Just-in-time&Compilation&,&JIT&),又称动态转译(&Dynamic&Translation&),是一种通过在运行时将&&翻译为机器码,从而改善字节码&&性能的技术。
2.&禁用部分访问检查
patchReturnTrue((uintptr_t) &dvmCheckClassAccess);
patchReturnTrue((uintptr_t) &dvmCheckFieldAccess);
patchReturnTrue((uintptr_t) &dvmInSamePackage);
if (access(XPOSED_DIR &conf/do_not_hook_dvmCheckMethodAccess&, F_OK) != 0)
patchReturnTrue((uintptr_t) &dvmCheckMethodAccess);
3.&针对&MIUI&操作系统移除&android.content.res.MiuiResources&类的&final&修饰符
&&&&jclass&miuiResourcesClass&&=&&env&-&&FindClass&(&MIUI_RESOURCES_CLASS&);
&&&&&if&&&(&miuiResourcesClass&&!=&&NULL&)&&&{
&&&&&&&&ClassObject&*&&clazz&&=&&&(&ClassObject&*)&dvmDecodeIndirectRef&(&dvmThreadSelf&(),&&miuiResourcesClass&);
&&&&&&&&&if&&&(&dvmIsFinalClass&(&clazz&))&&&{
&&&&&&&&&&&&ALOGD&(&&Removing&final&flag&for&class&'%s'&&,&&MIUI_RESOURCES_CLASS);
&&&&&&&&&&&&clazz&-&&accessFlags&&&=&&&~&ACC_FINAL&;
&&&&&&&&&}
4.&获取XposeBridge类并new一个全局引用
&xposedClass&&=&&env&-&&FindClass&(&XPOSED_CLASS&);
&&&&xposedClass&&=&&reinterpret_cast&&&jclass&&(&env&-&&NewGlobalRef&(&xposedClass&));
&&&&&if&&&(&xposedClass&&==&&NULL&)&&&{
&&&&&&&&ALOGE&(&&Error&while&loading&Xposed&class&'%s':\n&&,&&XPOSED_CLASS&);
&&&&&&&&dvmLogExceptionStackTrace&();
&&&&&&&&env&-&&ExceptionClear&();
&&&&&&&&&return&&&false&;
5.&注册JNI函数,xposed.cpp中定义了供XposedBridge类使用的JNI方法,此处进行注册,这样当XposeBridge中的main函数执行时,就可以调用xposed.cpp中定义的JNI方法
&&if&&&(&register_de_robv_android_xposed_XposedBridge&(&env&)&&&!=&&JNI_OK&)&&&{
&&&&&&&&ALOGE&(&&Could&not&register&natives&for&'%s'\n&&,&&XPOSED_CLASS&);
&&&&&&&&&return&&&false&;
Xposed&中&JNI&方法有:
static const JNINativeMethod xposedMethods[] = {
{&getStartClassName&, &()Ljava/lang/S&, (void*)de_robv_android_xposed_XposedBridge_getStartClassName},
{&initNative&, &()Z&, (void*)de_robv_android_xposed_XposedBridge_initNative},
{&hookMethodNative&, &(Ljava/lang/reflect/MLjava/lang/CILjava/lang/O)V&, (void*)de_robv_android_xposed_XposedBridge_hookMethodNative},
static jobject de_robv_android_xposed_XposedBridge_getStartClassName(JNIEnv* env, jclass clazz) {
return env-&NewStringUTF(startClassName);
static int register_de_robv_android_xposed_XposedBridge(JNIEnv* env) {
return env-&RegisterNatives(xposedClass, xposedMethods, NELEM(xposedMethods));
static const JNINativeMethod xresourcesMethods[] = {
{&rewriteXmlReferencesNative&, &(ILandroid/content/res/XRLandroid/content/res/R)V&, (void*)android_content_res_XResources_rewriteXmlReferencesNative},
static int register_android_content_res_XResources(JNIEnv* env) {
return env-&RegisterNatives(xresourcesClass, xresourcesMethods, NELEM(xresourcesMethods));
注册的&JNI&方法见&xposedMethods&数组。
至于这些&JNI&方法的用处,在后续&XposedBridge&的&main&函数调用中会继续分析。
如果对&Zygote&启动过程熟悉的话,对后续&XposedBridge&的&main&函数是如何被调用的应该会很清楚。&AndroidRuntime.cpp&的&start(const&char*&className,&const&char*&options)&函数完成环境变量的设置,&Dalvik&虚拟机的初始化和启动,同时&Xposed在&onVmCreated(JNIEnv*&env)&中完成了自身&JNI&方法的注册。此后&start()&函数会注册Android&系统的&JNI&方法,调用传入的&className&指定类的&main&方法,进入&Java&世界。
void AndroidRuntime::start(const char* className, const bool startSystemServer)
char* slashClassName = NULL;
/* start the virtual machine */
if (startVm(&mJavaVM, &env) != 0)
* Register android functions.
if (startReg(env) & 0) {
LOGE(&Unable to register all android natives\n&);
* We want to call main() with a String array with arguments in it.
* At present we only have one argument, the class name.
* array to hold it.
jclass stringC
jobjectArray strA
jstring classNameS
jstring startSystemServerS
stringClass = env-&FindClass(&java/lang/String&);
assert(stringClass != NULL);
strArray = env-&NewObjectArray(2, stringClass, NULL);
assert(strArray != NULL);
classNameStr = env-&NewStringUTF(className);
assert(classNameStr != NULL);
env-&SetObjectArrayElement(strArray, 0, classNameStr);
startSystemServerStr = env-&NewStringUTF(startSystemServer ?
&true& : &false&);
env-&SetObjectArrayElement(strArray, 1, startSystemServerStr);
* Start VM.
This thread becomes the main thread of the VM, and will
* not return until the VM exits.
jclass startC
jmethodID startM
slashClassName = strdup(className);
for (cp = slashClassN *cp != '\0'; cp++)
if (*cp == '.')
*cp = '/';
startClass = env-&FindClass(slashClassName);
if (startClass == NULL) {
startMeth = env-&GetStaticMethodID(startClass, &main&,
&([Ljava/lang/S)V&);
if (startMeth == NULL) {
env-&CallStaticVoidMethod(startClass, startMeth, strArray);
由于此时参数&className&为&de.robv.android.xposed.XposedBridge&,因此会调用XposedBridge&类的&main&方法,&XposedBridge&源码&/rovo89/XposedBridge&。
2.2&Java&模块
2.2.1&Main&函数:获取所启动的类名
进入&XposedBridge&的&main&函数,首先获取所启动的类名。
String&startClassName&&=&&getStartClassName&();
getStartClassName()&是一个&JNI&方法,定义在&xposed.cpp&中。
static&&jobject&de_robv_android_xposed_XposedBridge_getStartClassName&(&JNIEnv&*&&env&,&&jclass&clazz&)&&&{
&&&&&return&&env&-&&NewStringUTF&(&startClassName&);
startClassName&变量在&xposedOnVmCreated&函数中被赋予需启动的类的名称。
bool&xposedOnVmCreated&(&JNIEnv&*&&env&,&&&const&&&char&*&&className&)&&&{
&&&&startClassName&&=&&className&;
但是需要注意的是,若是启动&Zygote&,则此时&startClassName&值为&null&。如下代码(&app_main.cpp&)所示,当&zygote&为&true&,即启动&Zygote&时,并没有给&AppRuntime&实例&runtime&的&mClassName&成员赋值。
if&&&(&zygote&)&&&{
&&&&&&&&runtime&.&start&(&keepLoadingXposed&&?&&XPOSED_CLASS_DOTS&&:&&&&com.android.internal.os.ZygoteInit&&,
&&&&&&&&&&&&&&&&startSystemServer&&?&&&&start-system-server&&&&:&&&&&&);
&&&&&}&&&else&&&if&&&(&className&)&&&{
&&&&&&&&&//&Remainder&of&args&get&passed&to&startup&class&main()
&&&&&&&&runtime&.&mClassName&&=&&className&;
&&&&&&&&runtime&.&mArgC&&=&&argc&&-&&i&;
&&&&&&&&runtime&.&mArgV&&=&&argv&&+&&i&;
&&&&&&&&runtime&.&start&(&keepLoadingXposed&&?&&XPOSED_CLASS_DOTS&&:&&&&com.android.internal.os.RuntimeInit&&,
&&&&&&&&&&&&&&&&application&&?&&&&application&&&&:&&&&tool&&);
startClassName&的赋值过程为:&AppRuntime&中&mClassName&成员初始值为&NULL;在&app_main.cpp&中的&main&函数中根据&arg&参数解析获得&className&,若是启动Zygote&,则&className&值为&NULL&,否则若&className&有值,则赋值给&AppRuntime&实例&runtime&的&mClassName&成员变量;调用&runtime.start(…)&,进一步调用&onVmCreated(…)&,在&onVmCreated&函数中调用&xposedOnVmCreated(…)&,并传入&mClassName&值,&xposedOnVmCreated&函数将&mClassName&赋值给全局变量&startClassN
jobject&de_robv_android_xposed_XposedBridge_getStartClassName(…)&将此全局变量&startClassName&转换为&Java&字符串返回。&
2.2.2&初始化&log&文件
XposedBridge&会在&XposedInstaller&的目录下生成&log&文件,该&log&文件的路径为:&/data/data/de.robv.android.xposed.installer/log/debug.log&。&log&文件的初始化代码如下:
&&//&initialize&the&Xposed&framework&and&modules
//&initialize&log&file
File&logFile&&=&&&new&&File&(&BASE_DIR&&+&&&&log/debug.log&&);
if&&&(&startClassName&&==&&&null&&&&&&&logFile&.&length&()&&&&&&MAX_LOGFILE_SIZE&)
logFile&.&renameTo&(&new&&File&(&BASE_DIR&&+&&&&log/debug.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&&&(&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&;
若&startClassName==null&并且&log&文件的长度超过阈值,会将&debug.log&重命名为debug.log.old&。调用&determineXposedVersion()&获取&XposedBridge&的版本信息。版本信息存储在&XposedBridge&项目的&assets/VERSION&中。由于&XposedBridge&在&Android&设备上以&Jar&包的形式存在于&XposedInstaller&目录下,因此&determineXposedVersion&以读取&zip&文件的形式获取&VERSION&中的数据,并解析出其中的版本号,赋值给静态成员变量&XPOSED_BRIDGE_VERSION&。
ZipInputStream&is&&=&&&new&&ZipInputStream&(&new&&FileInputStream&(&BASE_DIR&&+&&&bin/XposedBridge.jar&&));
ZipEntry&entry&;
while&&&((&entry&&=&&is&.&getNextEntry&())&&&!=&&&null&)&&&{
if&&&(!&entry&.&getName&().&equals&(&&assets/VERSION&&))
continue&;
BufferedReader&br&&=&&&new&&BufferedReader&(&new&&InputStreamReader&(&is&));
String&version&&=&&br&.&readLine&();
br&.&close&();
XPOSED_BRIDGE_VERSION&&=&&extractIntPart&(&version&);
if&&&(&XPOSED_BRIDGE_VERSION&&==&&&0&)
throw&&&new&&RuntimeException&(&&could&not&parse&XposedBridge&version&from&\&&&&+&&version&&+&&&&\&&&);
throw&&&new&&RuntimeException&(&&could&not&find&assets/VERSION&in&&&&&+&&BASE_DIR&&+&&&&bin/XposedBridge.jar&&);
}&&&finally&&&{
is&.&close&();
}&&&catch&&&(&Exception&e&)&&&{&&&}
2.2.3&获取对&Java&层函数的引用
Xposed&在进入&XposedBridge.main&函数之前,注册了&4&个&JNI&方法,其中一个是&initNative()&,这个函数负责获取&XposedBridge&中&Java&函数的引用。在完成&log&文件的初始化后,&XposedBridge.main&调用&initNative&函数。
if&&&(&initNative&())&&&{
if&&&(&startClassName&&==&&&null&)&&&{
//&Initializations&for&Zygote
initXbridgeZygote&();
loadModules&(&startClassName&);
}&&&else&&&{
log&(&&Errors&during&native&Xposed&initialization&&);
现在回到&xposed.cpp&中,看下&initNative&这个&JNI&方法的实现。
static&&jboolean&de_robv_android_xposed_XposedBridge_initNative&(&JNIEnv&*&&env,&&jclass&clazz&)&&&{
&&&&xposedHandleHookedMethod&&=&&&(&Method&*)&&env&-&&GetStaticMethodID&(&xposedClass&,&&&&handleHookedMethod&&,
&&&&&&&&&&(Ljava/lang/reflect/MILjava/lang/OLjava/lang/O[Ljava/lang/O)Ljava/lang/O&&);
&&&&xresourcesClass&&=&&env&-&&FindClass&(&XRESOURCES_CLASS&);
&&&&xresourcesClass&&=&&reinterpret_cast&&&jclass&&(&env&-&&NewGlobalRef&(&xresourcesClass&));
&&&&&if&&&(&register_android_content_res_XResources&(&env&)&&&!=&&JNI_OK&)&&&{
&&&&&&&&ALOGE&(&&Could&not&register&natives&for&'%s'\n&&,&&XRESOURCES_CLASS&);
&&&&&&&&&return&&&false&;
&&&&xresourcesTranslateResId&&=&&env&-&&GetStaticMethodID&(&xresourcesClass&,&&&&translateResId&&,
&&&&&&&&&&(ILandroid/content/res/XRLandroid/content/res/R)I&&);
&&&&xresourcesTranslateAttrId&&=&&env&-&&GetStaticMethodID&(&xresourcesClass&,&&&&translateAttrId&&,
&&&&&&&&&&(Ljava/lang/SLandroid/content/res/XR)I&&);
&&&&&return&&&true&;
该函数主要完成对&XposedBridge&类中函数的引用,这样可以实现在&Native&层对&Java&层函数的调用。&譬如获取&XposedBridge&类中的&handlHookedMethod&函数的&method&id&,同时赋值给全局变量&xposedHandleHookedMethod&。另外,&initNative&函数还会获取&android.content.res.XResources&类中的方法,完成对资源文件的处理;调用&register_android_content_res_XResources&注册&rewriteXmlReferencesNative&这个JNI&方法。
2.2.4&Hook&:&Java&层获取&hooked&method&与&hook&func
在完成对&Java&层函数的引用赋值后,如果是启动&Zygote&,会接着执行对某些函数的&hook&处理。个人认为这部分是&Xposed&框架实现对函数&hook&的核心。代码如下:
if&&&(&startClassName&&==&&&null&)&&&{
//&Initializations&for&Zygote
initXbridgeZygote&();
initXbridgeZygote&完成对一些函数的&hook&操作,主要是调用&XposedHelpers&类中的&findAndHookMethod&完成。
private&&&static&&&void&&initXbridgeZygote&()&&&throws&&Exception&&{
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&&{
以&hook&ActivityThread&类的&handleBindApplication&函数为例来分析整个&hook&的过程。&ActivityThread&类定义在&frameworks/base/core/java/android/app/ActivityThread.java&文件中。&ActivityThread&的&main&函数是应用程序启动的入口。&findAndHookMethod(Class&?&&clazz,&String&methodName,&Object...&parameterTypesAndCallback)(另一个重载的&findAndHookMethod&最终也会调用前述&findAndHookMethod&函数&)&代码如下:
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&,&&parameterTypesAndCallback&);
return&&XposedBridge&.&hookMethod&(&m&,&&callback&);
findAndHookMethod函数参数的意义分别为:
1.&clazz:&需要hook的函数所在的类;
2.&methodName:&需要hook的函数名;
3.&parameterTypesAndCallback:&不定参数,包括methodName所指函数的参数,以及回调函数,主要是在执行methodName函数之前和之后调用的回调函数。
XC_MethodHook&callback&&=&&&(&XC_MethodHook&)&&parameterTypesAndCallback&[parameterTypesAndCallback&.&length&-&1&];
这段代码是用来parameterTypesAndCallback&值为&[“android.app.ActivityThread.AppBindData”,&XC_MethodHook&实例&]&,因此&callback&值为其中的&XC_MethodHook实例。&XC_MethodHook&类关系图如下:
XC_MethodHook&类中的&beforeHookedMethod&函数会在被&hook&的函数调用之前调用,而&afterHookedMethod&函数会在被&hook&的函数调用之后调用。这两个函数的方法体为空,需要在实例化&XC_MethodHook&时根据情况填充方法体。&XC_MethodHook&的内部类&MethodHookParam&保存了相应的信息,如调用方法的参数,&this&对象,函数的返回值等。
Method&m&&=&&findMethodExact&(&clazz&,&&methodName&,&&parameterTypesAndCallback&);
本行代码根据需要&hook&的函数的类信息、函数名以及参数信息获取对应的&Method实例,同时将其设置为可访问。第&5&行调用的&findMethodExact&函数的签名为&Method&&findMethodExact(Class&?&&clazz,&String&methodName,&Object...&parameterTypes),该函数最终会调用&Method&findMethodExact(Class&?&&clazz,&String&methodName,&Class&?&.parameterTypes)&。在&findMethodExact(Class&?&&clazz,&String&methodName,&Class&?&...&parameterTypes)&函数中,首先将类名、方法名以及参数信息构建成一个键值,以该键值从&methodCache&中查找是否存在&Method&实例,&methodCache相当于缓存了对应的&Method&实例。如果没有找到,会调用&Class&类的&getDeclaredMethod(String&name,Class&?&...&parameterTypes)&方法获取&Method&实例,同时将该&Method&设置为可访问,加入到&methodCache&中。
接下来调用&XposedBridge&类的静态方法&hookMethod&实现对函数的&hook&和回调函数的注册,代码如下:
&*&Hook&any&method&with&the&specified&callback
&*&@param&hookMethod&The&method&to&be&hooked
&*&@param&callback&
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&&);
boolean&&newMethod&&=&&&false&;
CopyOnWriteSortedSet&&&XC_MethodHook&&&&callbacks&;
synchronized&&&(&hookedMethodCallbacks&)&&&{
callbacks&&=&&hookedMethodCallbacks&.&get&(&hookMethod&);
if&&&(&callbacks&&==&&&null&)&&&{
callbacks&&=&&&new&&CopyOnWriteSortedSet&&&XC_MethodHook&&();
hookedMethodCallbacks&.&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&);
HookedMethodCallbacks&是一个&hashMap&的实例,存储每个需要&hook&的&method的回调函数。首先查看&hookedMethodCallbacks&中是否有&hookMethod&对应的&callbacks&的集合,如果没有,则创建一个&TreeSet&,将该&callbacks&加入到&hookedMethodCallbacks&中,同时将&newMethod&标志设为&true&。&接下来将传入的&callback&添加到callbacks&集合中。如果是个新的需要&hook&的&Method&,则获取对应的&Class&对象,得到&hookMethod&的&slot&值,然后调用&hookMethodNative&这个&JNI&方法。&最后实例化&Unhook&类,便于在后期需要对&hook&的方法进行&unhook&的操作。
2.2.5&Hook&:&Native&层&hookMethodNative预处理Hook
进入&hookMethodNative&这个&JNI&方法(&xposed.cpp&中),看下这个方法具体做了哪些操作。
static&&&void&&de_robv_android_xposed_XposedBridge_hookMethodNative&(&JNIEnv*&&env&,&&jclass&clazz&,&&
&&&&&&&&&&&&jobject&&reflectedMethodIndirect&,
&&&&&&&&&&&&jobject&declaredClassIndirect&,&&jint&slot&,&&jobject&additionalInfoIndirect&)&&&{
&&&&&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&&&(&xposedIsHooked&(&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&&=&&&&&xposedCallHandler&;
&&&&method&-&&insns&&=&&&(&const&&u2&*)&&hookInfo&;
&&&&method&-&&registersSize&&=&&method&-&&insSize&;
&&&&method&-&&outsSize&&=&&&0&;
&&&&&if&&&(&PTR_gDvmJit&&!=&&&NULL&)&&&{
&&&&&&&&&//&reset&JIT&cache
&&&&&&&&MEMBER_VAL&(&PTR_gDvmJit&,&&DvmJitGlobals&,&&codeCacheFull&)&&&=&&&true&;
代码中首先获得&Dalvik&中对应的&ClassObject&以及&Method&,接下来判断需要&hook的&Method&是否已经被&hook&处理过,若处理过,则直接返回。所有被&hook&的&Method&都会保存在&xposedOriginalMethods&这个&list&中。对于新的需要&hook&的函数,首先将其添加到&xposedOriginalMethods&的列表中。
&&&&SET_METHOD_FLAG&(&method&,&&ACC_NATIVE&);
&&&&method&-&&nativeFunc&&=&&&&&xposedCallHandler&;
&&&&method&-&&insns&&=&&&(&const&&u2&*)&&hookInfo&;
&&&&method&-&&registersSize&&=&&method&-&&insSize&;
&&&&method&-&&outsSize&&=&&&0&;
如上几行代码是&Xposed&框架实现&hook&的关键。&Dalvik&中&Method&结构体定义在AOSP&中&/dalvik/vm/oo/Object.h&中。&首先将&ACC_NATIVE&添加到&Method&的&accessFlags&标志位中&,&接下来将&Method&的&nativeFunc&设置为&xposedCallHandler&函数地址,&然后将&Method&的&registerSize&设置为&insSize&,&最后将&outsSize&设置为&0&。可参考&Dalvik&虚拟机的运行过程分析一文。&Dalvik&虚拟机在解释执行函数时,会调用&dvmIsNativeMethod(const&Method*&method)(&定义于&/dalvik/vm/oo/Object.h)&判断&Method&是否为&Native&方法,若是,则直接调用&Method-&nativeFunc&指向的函数。那&dvmIsNativeMethod&又是如何判断一个&Method&是否为&Native&方法呢?代码如下:
INLINE&&bool&&dvmIsNativeMethod&(&const&&Method&*&&method&)
return&&&(&method&-&&accessFlags&&&&&ACC_NATIVE&)&&&!=&&&0&;
正是通过比较&Method&的&accessFlags&与&ACC_NATIVE&来判断的,这也就是为什么14&行调用&SET_METHOD_FLAG&将&ACC_NATIVE&添加到&Method&的&accessFlags&中。&SET_METHOD_FLAG&代码如下:
#define&SET_METHOD_FLAG(method,flag)&\
do&{(&method&)&_&&&accessFlags&&|=&&&(&flag&);}&&&while&(&0&)
2.2.6&Native&Hook&:&Native&Function&的&dispatcher&&xposedCallHandler
进入&xposed.cpp&中的&xposedCallHandler&函数,该函数会作为被&hook&的函数的&Native&方法调用,代码如下:
static&&&void&&xposedCallHandler&(&const&&u4&*&&args&,&&JValue&*&&pResult&,&&&const&&Method&*&&method&,&&&::&Thread&*&&self&)&&&{
&&&&&if&&&(!&xposedIsHooked&(&method&))&&&{
&&&&&&&&dvmThrowNoSuchMethodError&(&&could&not&find&Xposed&original&method&-&how&did&you&even&get&here?&&);
&&&&&&&&&return&;
&&&&XposedHookInfo&*&&hookInfo&&=&&&(&XposedHookInfo&*)&&method&-&&insns&;
&&&&Method&*&&original&&=&&&(&Method&*)&&hookInfo&;
&&&&Object&*&&originalReflected&&=&&hookInfo&-&&reflectedMethod&;
&&&&Object&*&&additionalInfo&&=&&hookInfo&-&&additionalInfo&;
&&&&&//&convert/box&arguments
&&&&&const&&&char&*&&desc&&=&&&&&method&-&&shorty&[&1&];&&&//&[0]&is&the&return&type.
&&&&Object&*&&thisObject&&=&&&NULL&;
&&&&size_t&srcIndex&&=&&&0&;
&&&&size_t&dstIndex&&=&&&0&;
&&&&&//&for&non-static&methods&determine&the&&this&&pointer
&&&&&if&&&(!&dvmIsStaticMethod&(&original&))&&&{
&&&&&&&&thisObject&&=&&&(&Object&*)&&args&[&0&];
&&&&&&&&srcIndex&++;
&&&&ArrayObject&*&&argsArray&&=&&dvmAllocArrayByClass&(&objectArrayClass&,&&strlen&(method&-&&shorty&)&&&-&&&1&,&&ALLOC_DEFAULT&);
&&&&&if&&&(&argsArray&&==&&&NULL&)&&&{
&&&&&&&&&return&;
&&&&&while&&&(*&desc&&!=&&&'\0'&)&&&{
&&&&&&&&&char&&descChar&&=&&&*(&desc&++);
&&&&&&&&JValue&value&;
&&&&&&&&Object&*&&obj&;
&&&&&&&&&switch&&&(&descChar&)&&&{
&&&&&&&&&case&&&'Z'&:
&&&&&&&&&case&&&'C'&:
&&&&&&&&&case&&&'F'&:
&&&&&&&&&case&&&'B'&:
&&&&&&&&&case&&&'S'&:
&&&&&&&&&case&&&'I'&:
&&&&&&&&&&&&value&.&i&&=&&args&[&srcIndex&++];
&&&&&&&&&&&&obj&&=&&&(&Object&*)&&dvmBoxPrimitive&(&value&,&&dvmFindPrimitiveClass&(&descChar&));
&&&&&&&&&&&&dvmReleaseTrackedAlloc&(&obj&,&&self&);
&&&&&&&&&&&&&break&;
&&&&&&&&&case&&&'D'&:
&&&&&&&&&case&&&'J'&:
&&&&&&&&&&&&value&.&j&&=&&dvmGetArgLong&(&args&,&&srcIndex&);
&&&&&&&&&&&&srcIndex&&+=&&&2&;
&&&&&&&&&&&&obj&&=&&&(&Object&*)&&dvmBoxPrimitive&(&value&,&&dvmFindPrimitiveClass&(&descChar&));
&&&&&&&&&&&&dvmReleaseTrackedAlloc&(&obj&,&&self&);
&&&&&&&&&&&&&break&;
&&&&&&&&&case&&&'['&:
&&&&&&&&&case&&&'L'&:
&&&&&&&&&&&&obj&&&=&&&(&Object&*)&&args&[&srcIndex&++];
&&&&&&&&&&&&&break&;
&&&&&&&&&default&:
&&&&&&&&&&&&ALOGE&(&&Unknown&method&signature&description&character:&%c\n&&,&&descChar&);
&&&&&&&&&&&&obj&&=&&&NULL&;
&&&&&&&&&&&&srcIndex&++;
&&&&&&&&&}
&&&&&&&&xposedSetObjectArrayElement&(&argsArray&,&&dstIndex&++,&&obj&);
&&&&&//&call&the&Java&handler&function
&&&&JValue&result&;
&&&&dvmCallMethod&(&self&,&&xposedHandleHookedMethod&,&&&NULL&,&&&&&result&,
&&&&&&&&originalReflected&,&&&(&int&)&&original&,&&additionalInfo&,&&thisObject&,&&argsArray&);
&&&&dvmReleaseTrackedAlloc&(&argsArray&,&&self&);
&&&&&//&exceptions&are&thrown&to&the&caller
&&&&&if&&&(&dvmCheckException&(&self&))&&&{
&&&&&&&&&return&;
&&&&&//&return&result&with&proper&type
&&&&ClassObject&*&&returnType&&=&&dvmGetBoxedReturnType&(&method&);
&&&&&if&&&(&returnType&-&&primitiveType&&==&&PRIM_VOID&)&&&{
&&&&&&&&&//&ignored
&&&&&}&&&else&&&if&&&(&result&.&l&&==&&&NULL&)&&&{
&&&&&&&&&if&&&(&dvmIsPrimitiveClass&(&returnType&))&&&{
&&&&&&&&&&&&dvmThrowNullPointerException&(&&null&result&when&primitive&expected&&);
&&&&&&&&&}
&&&&&&&&pResult&-&&l&&=&&&NULL&;
&&&&&}&&&else&&&{
&&&&&&&&&if&&&(!&dvmUnboxPrimitive&(&result&.&l&,&&returnType&,&&pResult&))&&&{
&&&&&&&&&&&&dvmThrowClassCastException&(&result&.&l&-&&clazz&,&&returnType&);
&&&&&&&&&}
第&4-7&获得被&hook&函数的&java.lang.reflect.Method&对象实例。第&9-52&行完成&Java&本地类型到&Java&类型的转换,也就是将被&hook&函数的参数转换为&Java&类型,为后续在&C++&层调用&Java&层代码做准备。&55&行调用&XposedBridge&类中&handleHookedMethod&函数,参数分别为被&hook&的原始函数&Method&实例,&this&对象以及参数信息。这也就是为什么有&9-52&行的参数转换操作。&58-72&行完成对返回值的进一步处理,主要是将&Java&层的返回值类型转换为&C++&层的类型。&74&行将线程状态设置回调用&handleHookedMethod&之前的状态继续运行。
2.2.7&XposedBridge&:&handleHookedMethod
handleHookedMethod&将被&hook&的代码又交还给&java&层实现。
private&static&Object&handleHookedMethod(Member&method,&Object&thisObject,&Object[]&args)&throws&Throwable&{
if&(disableHooks)&{
return&invokeOriginalMethod(method,&thisObject,&args);
}&catch&(InvocationTargetException&e)&{
throw&e.getCause();
首先判断&hook&是否被禁用,若是,则直接调用&invokeOriginalMethod&函数,完成对原始函数的执行。关于如何执行原始函数的,可以继续跟踪下去分析。
TreeSet&&&XC_MethodHook&&&&callbacks&;
synchronized&&(&hookedMethodCallbacks&)&&&{
callbacks&&=&&hookedMethodCallbacks&.&get&(&method&);
if&&&(&callbacks&&==&&null&&||&&callbacks&.&isEmpty&())&&&{
return&&invokeOriginalMethod&(&method&,&&thisObject&,&&args&);
}&&&catch&&&(&InvocationTargetException&e&)&&&{
throw&&e&.&getCause&();
synchronized&&(&callbacks&)&&&{
callbacks&&=&&&((&TreeSet&&&XC_MethodHook&&)&&callbacks&.&clone&());
根据&method&值,从&hookedMethodCallbacks&中获取对应的&callback&信息。&hookedMethodCallbacks&的分析可以参考之前对&hookMethod&的分析。&callbacks&中存储了所有对该&method&进行&hook&的&beforeHookedMethod&和&afterHookedMethod&。接着从&callbacks&中获取&beforeHookedMethod&和&afterHookedMethod&的迭代器。
Iterator&&&XC_MethodHook&&&&before&&=&&callbacks&.&iterator&();
Iterator&&&XC_MethodHook&&&&after&&&=&&callbacks&.&descendingIterator&();
//&call&&before&method&&callbacks
while&&&(&before&.&hasNext&())&&&{
before&.&next&().&beforeHookedMethod&(&param&);
}&&&catch&&&(&Throwable&t&)&&&{
XposedBridge&.&log&(&t&);
//&reset&result&(ignoring&what&the&unexpectedly&exiting&callback&did)
param&.&setResult&(&null&);
param&.&returnEarly&&=&&&false&;
continue&;
if&&&(&param&.&returnEarly&)&&&{
//&skip&remaining&&before&&callbacks&and&corresponding&&after&&callbacks
while&&&(&before&.&hasNext&()&&&&&&&after&.&hasNext&())&&&{
before&.&next&();
after&.&next&();
//&call&original&method&if&not&requested&otherwise
if&&&(!&param&.&returnEarly&)&&&{
param&.&setResult&(&invokeOriginalMethod&(&method&,&&param&.&thisObject&,&&param&.args&));
}&&&catch&&&(&InvocationTargetException&e&)&&&{
param&.&setThrowable&(&e&.&getCause&());
//&call&&after&method&&callbacks
while&&&(&after&.&hasNext&())&&&{
Object&lastResult&&=&&&param&.&getResult&();
Throwable&lastThrowable&&=&&param&.&getThrowable&();
after&.&next&().&afterHookedMethod&(&param&);
}&&&catch&&&(&Throwable&t&)&&&{
XposedBridge&.&log&(&t&);
//&reset&to&last&result&(ignoring&what&the&unexpectedly&exiting&callback&did)
if&&&(&lastThrowable&&==&&null&)
param&.&setResult&(&lastResult&);
param&.&setThrowable&(&lastThrowable&);
if&&&(&param&.&hasThrowable&())
throw&&param&.&getThrowable&();
return&&param&.&getResult&();
通过以上的分析,基本能够弄清楚&Xposed&框架实现&hook&的原理。&Xposed&将需要hook&的函数替换成&Native&方法&xposedCallHandler&,这样&Dalvik&在执行被&hook&的函数时,就会直接调用&xposedCallHandler&,&xposedCallHandler&再调用&XposedBridge&类的&handleHookedMethod&完成注册的&beforeHookedMethod&以及&afterHookedMethod&的调用,这两类回调函数之间,会调用原始函数,完成正常的功能。
2.2.8&&加载基于&Xposed&模块
继续回到&XposedBridge&的&main&函数中,在处理完对&hook&函数的处理后会调用&loadModules(String&startClassName)&加载基于&Xposed&框架的模块。
if&&&(&initNative&())&&&{
if&&&(&startClassName&&==&&null&)&&&{
//&Initializations&for&Zygote
initXbridgeZygote&();
loadModules&(&startClassName&);
}&&&else&&&{
log&(&&Errors&during&native&Xposed&initialization&&);
loadModules&读取&/data/data/de.robv.android.xposed.installer/conf/modules.list文件,获得&Android&设备上安装的模块的&APK&具体路径,若设备上安装了&XPrivacy,则&modules.list&文件内容为:&/data/app/biz.bokhorst.xprivacy-1.apk&。&loadModules&对每个模块调用&loadMoudle&,&loadModule&会根据提供的&APK&路径,实例化类,并根据实例的类型,进行一些初始化工作,主要的类型包括&IXposedHookZygoteInit,&IXposedHookLoadPackage&,&IXposedHookInitPackageResources&,和&IXposedHookCmdInit&。以&XPrivacy&模块为例,&XPrivacy&类实现了&IXposedHookLoadPackage&和&IXposedHookZygoteInit&接口。如果是&IXposedHookZygoteInit&,&loadModule会调用&initZygote(StartupParam&startupParam)&函数。因此在分析基于&Xposed&框架的模块时,需要注意这点。
private&&&static&&&void&&loadModules&(&String&startClassName&)&&throws&IOException&{
BufferedReader&apks&&=&&&new&&BufferedReader&(&new&&FileReader&(&BASE_DIR&&+&&&conf/modules.list&&));
String&apk&;
while&&&((&apk&&=&&apks&.&readLine&())&&&!=&&null&)&&&{
loadModule&(&apk&,&&startClassName&);
apks&.&close&();
2.2.9&调用&ZygoteInit.main&或&RuntimeInit.main
在&Xposed&的&app_main.cpp&中,&runtime.start&调用了&XposedBridge&的&main&函数,对于&Zygote&启动过程来说,还必须完成对&ZygoteInit.main&函数的调用,完成类、资源的预加载以及对应用程序运行请求的处理。所以在&XposedBridge&完成自身的初始化之后,还需要完成对&ZygoteInit.main&的调用,如下代码所示。
//&call&the&original&startup&code
if&&&(&startClassName&&==&&null&)
ZygoteInit&.&main&(&args&);
RuntimeInit&.&main&(&args&);
3&Developer&Wiki
3.1&&创建一个&Xposed&Module
一个&XposedModule&本质上是设定了部分特殊元数据标志位的普通应用程序,需要在&AndroidManifest.xml&文件中添加如下设置:
&&AndroidManifest.xml&=&&Application&=&&Application&Nodes&(at&the&bottom)&=&&Add&=&&Meta&Data
添加节点:&name&=&xposedmodule&,&value&=&true&。&name&=&xposedminiversion,&value&=&API&level&。
&?xml&version=&1.0&&encoding=&utf-8&?&
&manifest&&&xmlns:android=&&/apk/res/android&
&&&&&package=&&de.robv.android.xposed.mods.tutorial&
&&&&&android:versionCode=&&1&
&&&&&android:versionName=&&1.0&&&&&
&&&&&&uses-sdk&&&android:minSdkVersion=&&15&&&&/&
&&&&&&application
&&&&&&&&&android:icon=&&@drawable/ic_launcher&
&&&&&&&&&android:label=&&@string/app_name&&&&&
&&&&&&&&&&meta-data&&&android:value=&&true&&&&android:name=&&xposedmodule&&/&
&&&&&&&&&&meta-data&&&android:value=&&2.0*&&&&android:name=&&xposedminversion&&/&
&&&&&&&&&&meta-data&&&android:value=&&Demonstration&of&the&Xposed&framework.\nMakes&the&status&bar&clock&red.&&&&android:name=&&xposeddescription&&/&
&&&&&&/application&
&/manifest&
然后,将&XposedBridge.jar&这个引用导入到工程中,加入到&reference&path&中。
下面开始创建一个新的工程:
package&&com&.&kevin&.&myxposed&;
import&&android&.&util&.&Log&;
import&&de&.&robv&.&android&.&xposed&.&IXposedHookLoadPackage&;
import&&de&.&robv&.&android&.&xposed&.&XposedBridge&;
import&&de&.&robv&.&android&.&xposed&.&callbacks&.&XC_LoadPackage&.&LoadPackageParam&;
public&&&class&&XposedInterface&&implements&&IXposedHookLoadPackage&&{
public&&&void&&handleLoadPackage&(&final&&LoadPackageParam&lpparam&)&&&throws&&Throwable&&{
&&&&&&&&XposedBridge&.&log&(&&Kevin-Loaded&app:&&&&&+&&lpparam&.&packageName&);
然后在&assets&目录下新建一个&xposed_init&文件,这个文件声明了需要加载到&XposedInstaller&的入口类:
com.kevin.myxposed.XposedInterface
运行程序并在&XposedInstaller&的&Module&选项中激活,重启机器后可以得到如下数据:
3.2&HookedMethod&:定位你要&hook&的方法
在上一步中我们已经定位了需要&Hook&的方法以及所在的类,譬如:
com.android.systemui.statusbar.policy.Clock&类
中的&updateClock&方法。
package&&de&.&robv&.&android&.&xposed&.&mods&.&tutorial&;
import&&&static&&de&.&robv&.&android&.&xposed&.&XposedHelpers&.&findAndHookM
import&&de&.&robv&.&android&.&xposed&.&IXposedHookLoadPackage&;
import&&de&.&robv&.&android&.&xposed&.&XC_MethodHook&;
import&&de&.&robv&.&android&.&xposed&.&callbacks&.&XC_LoadPackage&.&LoadPackageParam&;
public&&&class&&Tutorial&&implements&&IXposedHookLoadPackage&&{
&&&&&public&&&void&&handleLoadPackage&(&final&&LoadPackageParam&lpparam&)&&&throws&&Throwable&&{
&&&&&if&&&(!&lpparam&.&packageName&.&equals&(&&com.android.systemui&&))
&&&&&&&&&&&&&return&;
&&&& findAndHookMethod&(&&com.android.systemui.statusbar.policy.Clock&&,&&lpparam&.&classLoader&,&&&&handleUpdateClock&&,&&&new&&XC_MethodHook&()&&&{
&&&&&protected&&&void&&beforeHookedMethod&(&MethodHookParam&param&)&&&throws&&Throwable&&{
&&&&&//&this&will&be&called&before&the&clock&was&updated&by&the&original&method
&&&&&protected&&&void&&afterHookedMethod&(&MethodHookParam&param&)&&&throws&&Throwable&&{
&&&&&//&this&will&be&called&after&the&clock&was&updated&by&the&original&method
关于findAndHookMethod&方法的说明见下面的&API&Reference&。
3.3&&进行资源替换
3.3.1&&简易资源替换
下面所使用的方法可以适用于&Boolean&、&Color&、&Integer&、&int[]&、&String&与&String[]&。
其中,对于&Android&框架层的资源(所有的&APP&都需要调用的资源)应该在&initZygote&这个方法中完成替换。而对于属于应用程序的资源,应该在&hookInitPackageResources&这个方法中完成替换。
public&&&void&&initZygote&(&IXposedHookZygoteInit&.&StartupParam&startupParam&)&&&throws&&Throwable&&{
XResources&.&setSystemWideReplacement&(&&android&&,&&&&bool&&,&&&&config_unplugTurnsOnScreen&&,&&&false&);
public&&&void&&handleInitPackageResources&(&InitPackageResourcesParam&resparam&)&&&throws&&Throwable&&{
//&replacements&only&for&SystemUI
if&&&(!&resparam&.&packageName&.&equals&(&&com.android.systemui&&))
//&different&ways&to&specify&the&resources&to&be&replaced
resparam&.&res&.&setReplacement&(&0x7f080083&,&&&&YEAH!&&);&&&//&WLAN&toggle&text.&You&should&not&do&this&because&the&id&is&not&fixed.&Only&for&framework&resources,&you&could&use&android.R.string.something
resparam&.&res&.&setReplacement&(&&com.android.systemui:string/quickpanel_bluetooth_text&&,&&&&WOO!&&);
resparam&.&res&.&setReplacement&(&&com.android.systemui&&,&&&&string&&,&&&&quickpanel_gps_text&&,&&&&HOO!&&);
resparam&.&res&.&setReplacement&(&&com.android.systemui&&,&&&&integer&&,&&&&config_maxLevelOfSignalStrengthIndicator&&,&&&6&);
resparam&.&res&.&setReplacement&(&&com.android.systemui&&,&&
&&&&&&&&&&&&&&&&&&&&&&drawable&&,&&&&status_bar_background&&,&&
&&&&&new&&XResources&.&DrawableLoader&()&&&{
public&&Drawable&newDrawable&(&XResources&res&,&&&int&&id&)&&&throws&&Throwable&&{
return&&&new&&ColorDrawable&(&Color&.&WHITE&);
3.3.2&&复杂资源
package&&de&.&robv&.&android&.&xposed&.&mods&.&coloredcirclebattery&;
import&&android&.&content&.&res&.&XModuleResources&;
import&&de&.&robv&.&android&.&xposed&.&IXposedHookInitPackageResources&;
import&&de&.&robv&.&android&.&xposed&.&IXposedHookZygoteInit&;
import&&de&.&robv&.&android&.&xposed&.&callbacks&.&XC_InitPackageResources&.&InitPackageResourcesParam&;
public&&&class&&ColoredCircleBattery&&implements&&IXposedHookZygoteInit&,&&IXposedHookInitPackageResources&&{
private&&&static&&String&MODULE_PATH&&=&&&null&;
public&&&void&&initZygote&(&StartupParam&startupParam&)&&&throws&&Throwable&&{
MODULE_PATH&&=&&startupParam&.&modulePath&;
public&&&void&&handleInitPackageResources&(&InitPackageResourcesParam&resparam&)&&&throws&&Throwable&&{
if&&&(!&resparam&.&packageName&.&equals&(&&com.android.systemui&&))
XModuleResources&modRes&&=&&XModuleResources&.&createInstance&(&MODULE_PATH&,&&resparam&.&res&);
resparam&.&res&.&setReplacement&(&&com.android.systemui&&,&&&&drawable&&,&&&&stat_sys_battery&&,&&modRes&.&fwd&(&R&.&drawable&.&battery_icon&));
resparam&.&res&.&setReplacement&(&&com.android.systemui&&,&&&&drawable&&,&&&&stat_sys_battery_charge&&,&&modRes&.&fwd&(&R&.&drawable&.&battery_icon_charge&));
3.3.3&&修改&layouts
public&&&void&&handleInitPackageResources&(&InitPackageResourcesParam&resparam&)&&&throws&&Throwable&&{
if&&&(!&resparam&.&packageName&.&equals&(&&com.android.systemui&&))
resparam&.&res&.&hookLayout&(&&com.android.systemui&&,&&&&layout&&,&&&&status_bar&&,&&new&&XC_LayoutInflated&()&&&{
public&&&void&&handleLayoutInflated&(&LayoutInflatedParam&liparam&)&&&throws&&Throwable&&{
TextView&clock&&=&&&(&TextView&)&&liparam&.&view&.&findViewById&(
liparam&.&res&.&getIdentifier&(&&clock&&,&&&&id&&,&&&&com.android.systemui&&));
clock&.&setTextColor&(&Color&.&RED&);
4&API&Reference
关键类&/API&说明
IXposedHookLoadPackage
这个方法用于在加载应用程序的包的时候执行用户的操作。
public&class&XposedInterface&implements&IXposedHookLoadPackage&{
public&void&handleLoadPackage(final&LoadPackageParam&lpparam)&throws&Throwable&{
&&&&&&&&XposedBridge.log(&Kevin-Loaded&app:&&&+&lpparam.packageName);
&final&LoadPackageParam&lpparam这个参数包含了加载的应用程序的一些基本信息。
XposedHelpers
这是一个辅助方法,可以通过如下方式静态导入:
import&static&de.robv.android.xposed.XposedHelpers.findAndHookM
findAndHookMethod(&com.android.systemui.statusbar.policy.Clock&,&lpparam.classLoader,&&handleUpdateClock&,&new&XC_MethodHook()&{
&&&& protected&void&beforeHookedMethod(MethodHookParam&param)&throws&Throwable&{
&&&& //&this&will&be&called&before&the&clock&was&updated&by&the&original&method
&&&& protected&void&afterHookedMethod(MethodHookParam&param)&throws&Throwable&{
&&&& //&this&will&be&called&after&the&clock&was&updated&by&the&original&method
v&findAndHookMethod(Class&?&&clazz,&&&//&需要&Hook&的类名
&&&&&&ClassLoader,&&&//&类加载器,可以设置为&null
&&&&&&String&methodName,&&&&//&需要&Hook&的方法名
&&&&&&Object...&parameterTypesAndCallback
该函数的最后一个参数集,包含了:
(1)Hook&的目标方法的参数&,&譬如:
&&&&&&com.android.internal.policy.impl.PhoneWindow.DecorView&
&&&&&是方法的参数的类。
(&2&)回调方法:
&&&&&b.XC_MethodReplacement
辅助项&API
Xposed&框架也为我们提供了很多的辅助项来帮助我们快速开发&XposedModule&。
XposedBridge&类
该方法可以将&log&信息以及&Throwable&抛出的异常信息输出到标准的&logcat&以及&/data/xposed/debug.log这个文件中。
hookAllMethods&/&hookAllConstructors
该方法可以用来hook&某个类中的所有方法或者构造函数,但是不同的&Rom&(非&Android&原生&Rom&}

我要回帖

更多关于 xp框架好用的模块2016 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信