xposed开发之清除应用数据(研究历程)

    最近在研究xposed,有个需求要做到清除其他应用数据,xposed功能足够强大,应该可以实现这个功能,下面是基于android4.4.4研究的思路。

    google只能开放了清楚缓存的API,清除数据的API隐藏了,而调用清理数据的方法在“设置”中的“应用”里,找到设置功能的源码,代码位置 com.android.settings.applications.InstalledAppDetails ,点击事件在这

103842_bfxz_1786928.png

调用了initiateClearUserData,看看这里面怎么实现的

104013_lZCJ_1786928.png

调用了ActivityManager的clearApplicationUserData,参数是该应用的包名和一个ClearUserDataObserver的实例

104307_sfW8_1786928.png

IPackageDataObserver是有AIDL生成的,位于android.content.pm包内,我们可以新建一个相同的包名,把AIDL放在这里。

104552_hWSU_1786928.png

注:有些应用详情里该按钮不是清除数据,是管理空间,清除数据的按钮在应用自定义的界面里,但是最终实现清除数据还是调用的clearApplicationUserData

clearApplicationUserData是隐藏方法,直接调用了ActivityManagerNative的方法

105117_oiUR_1786928.png

ActivityManagerNative:

105443_QOQB_1786928.png

这里直接使用反射或者Xposed的callmethod调用这两个方法都会报错,缺少权限

android.permission.CLEAR_APP_USER_DATA

这里并没有实现具体的方法,真正的实现在ActivityManagerService中,参考http://www.jianshu.com/p/18517a4ef8e1

ActivityManagerService:

112417_eQWA_1786928.png

112625_AswM_1786928.png

该方法上面部分是获取pid、uid,给IPackageManager的对象赋值和权限检测,下面执行清除数据。最开始的思路是直接hook AppGlobals.getPackageManager()的clearApplicationUserData,但是仍旧报缺少权限错误。。。继续分析:

AppGlobals:

112941_TqUX_1786928.png

ActivityThread:

113033_lcgM_1786928.png

到这里遇到IPackageManager.aidl生成的Stub类,PackageManagerService继承了IPackageManager.Stub

PackageManagerService:

113701_9Dfv_1786928.png

又是权限检测,跳过,进入clearApplicationUserDataLI

113853_EbaY_1786928.png

int retCode = mInstaller.clearUserData(packageName, userId);

进入Installer方法

114039_im0I_1786928.png

114552_jDuv_1786928.png

134326_W8W9_1786928.png

该类大概是创建本地socket,执行linux命令行,进行各种应用的安装、移动、卸载、清除数据等

但是hook此方法,仍旧报错,空指针异常,而且hook connect也连接不上

Class installCls = XposedHelpers.findClass("com.android.server.pm.Installer",lpp.classLoader);
Object installObj = XposedHelpers.newInstance(installCls);
boolean lean = (boolean) XposedHelpers.callMethod(installObj,"ping");
boolean bo = (boolean) XposedHelpers.callMethod(installObj,"connect");
XposedBridge.log("lean:"+lean+"--bo:"+bo);

实例化Installer出的问题.查了资料,Installer在系统启动时由其他类调用,启动完成后用findAndHookMethod无法hook到。于是实现Xposed另一接口XposedHookZygoteInit 

@Override
public void initZygote(StartupParam startupParam) throws Throwable {
    Class installCls = XposedHelpers.findClass("com.android.server.pm.Installer",null);
    XposedHelpers.findAndHookMethod(installCls, "writeCommand",String.class, new XC_MethodHook() {
        @Override
        protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
            String string = (String) param.args[0];
            XposedBridge.log("string:"+string);
            if(string.contains("com.google.android.gms"))
                param.args[0] = "rmuserdata com.google.android.gms 0";
        }

    });

}

以google play service为例,这种情况下可以清除此app的数据。但是这种方法不可控,必须放在initZygote中,而且Installer不能通过反射实例化,只能另想办法。

    郁闷两天后,想到既然从ActivityManager、PackageManagerService等类中不能调用是因为权限限制,那就hook检测权限的方法,让我的应用通过权限检测。最开始打算以外部调用的方式(在非Xposed中,例如activity,以反射的方式调用清除数据的方法,Xposed hook权限检测方法)从 ActivityManagerService入手,因为PackageManagerService的构造方法需要传多个参数,包括Installer的对象。ActivityManagerService里检测权限的是checkComponentPermission方法,但是通过反射获取ActivityManagerService对象时又报错,FileNotFoundException,引发异常的位置是mBatteryStatsService = new BatteryStatsService(new File( systemDir, "batterystats.bin").toString());

batterystats.bin文件位于/data/system/下,但即使我获得了root权限依然触发异常,不知道什么原因。这样只能在handleLoadPackage中调用清除数据,在Xposed外部设置个合适方法触发清理数据,比如获得IMEI、杀掉某个进程等,通过hook这些方法,然后调用清除数据的方法:

XposedHelpers.findAndHookMethod("android.app.ActivityManager", lpp.classLoader, "killBackgroundProcesses",String.class, new XC_MethodHook() {
            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                String process = (String) param.args[0];
                XposedBridge.log("process:"+process);
                if("com.google.android.gsf".equals(process)){
                    ActivityManager manager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
                    XposedHelpers.callMethod(manager,"clearApplicationUserData",packageName,clearDataUserData);

                }

            }
        });

这是以杀死com.google.android.gsf为例。

    权限检测这里有两部分,就是ActivityManagerService 的checkComponentPermission了:

XposedHelpers.findAndHookMethod("com.android.server.am.ActivityManagerService", lpp.classLoader, "checkComponentPermission", String.class, int.class, int.class, int.class, boolean.class, new XC_MethodHook() {
            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                if(Manifest.permission.CLEAR_APP_USER_DATA.equals(param.args[0])) {
                    int re = (int) param.getResult();
                    XposedBridge.log("ActivityManagerService re:"+re);
                    param.setResult(0);//PackageManager.PERMISSION_GRANTED

                }
            }
        });

    总结:最终实现的方法很简单,但是过程分析花费的时间很长,一方面源于对源码的不了解,比如AIDL原理,系统启动的顺序等等。好在源码结构好,容易看懂,不然还没分析完就歇菜放弃了。这里主要是为学习做个笔记,清除其他应用的数据是很危险的行为,一定要慎用!慎用

转载于:https://my.oschina.net/u/1786928/blog/983476

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值