黑科技——靜默卸載蛇券、清除數(shù)據(jù)及降級安裝

近期在做微信數(shù)據(jù)備份項目時缀壤,所探索出來的一些“黑科技”,可以實現(xiàn)靜默卸載第三方app纠亚、靜默清除第三方app的數(shù)據(jù)塘慕、靜默降級安裝app等功能

首先這些都需要系統(tǒng)簽名才有這個能力,其次蒂胞,通過反射去調(diào)用系統(tǒng)的隱藏api去實現(xiàn)這些功能图呢。隱藏api,顧名思義骗随,普通情況下肯定是調(diào)用不到的蛤织,所以需要一些特殊的方法去調(diào)用它。

0.反射方法

這里先提供反射的通用方法鸿染,后面示例代碼將從這里調(diào)用指蚜,可做一個util工具類使用。

public class ReflectUtil {
    // 通過反射去調(diào)用target類下的實例方法
    public static Object callObjectMethod(Object target, String method, Class<?>[] parameterTypes, Object... values)
            throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        Class<? extends Object> clazz = target.getClass();
        Method declaredMethod = clazz.getDeclaredMethod(method, parameterTypes);
        return declaredMethod.invoke(target, values);
    }

  //通過反射去拿到實例對象
    public static Object callStaticObjectMethod(Class<?> clazz, String method, Class<?>[] parameterTypes, Object... values)
            throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        Method declaredMethod = clazz.getDeclaredMethod(method, parameterTypes);
        declaredMethod.setAccessible(true);
        return declaredMethod.invoke(null, values);
    }
}

1.卸載

首先安裝卸載的相關邏輯存在系統(tǒng)的framework層涨椒,路徑為/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java摊鸡,即PMS。
通過翻android源碼(這里推薦一個在線看源碼的網(wǎng)站http://androidxref.com/)蚕冬,可以知道卸載的方法為deletePackageAsUser免猾,如下圖:

deletePackageAsUser部分源碼

可以看到該方法所需參數(shù)有packageName、versionCode播瞳、observer(通過aidl獲取該類掸刊,后續(xù)會提到)、userId赢乓、flags忧侧。

參數(shù)中的IPackageDeleteObserver類,是一個aidl回調(diào)通知接口牌芋,在源碼中找到這個接口:

package android.content.pm;

/**
 * API for deletion callbacks from the Package Manager.
 *
 * {@hide}
 */
oneway interface IPackageDeleteObserver {
    void packageDeleted(in String packageName, in int returnCode);
}

將該aidl文件按照以上Package:android.content.pm的層級關系放置于項目源碼中蚓炬,會自動生成class文件供調(diào)用。生成文件如下圖:


aidl生成的類文件

成功生成這個之后躺屁,就可以使用反射實現(xiàn)卸載操作了肯夏。直接上代碼:

//卸載操作
  try {
          // 拿到PackageName對應的PackageInfo
            PackageInfo packageInfo = context.getPackageManager().getPackageInfo(yourPackageName, 0);
            PackageDeleteObserver observer = new PackageDeleteObserver();
           //通過反射拿到IBinder對象
            IBinder pgmService = (IBinder) ReflectUtil.callStaticObjectMethod(Class.forName("android.os.ServiceManager"), "getService", new Class[]{String.class}, "package");
           //通過反射拿到IPackageManager對象 
           Object mIPm = ReflectUtil.callStaticObjectMethod(Class.forName("android.content.pm.IPackageManager$Stub"),
                    "asInterface", new Class[]{IBinder.class}, pgmService);
           //通過反射使用IPackageManager接口調(diào)用到PackageManagerService里的deletePackageAsUser方法
          //其中后面兩個0,第一個是傳入userId犀暑,一般傳入0即可驯击,不同的系統(tǒng)會有不同的分身userid,第二個是flag耐亏,也是傳入0即可徊都。
            ReflectUtil.callObjectMethod(mIPm, "deletePackageAsUser",
                    new Class[]{String.class, int.class, IPackageDeleteObserver.class, int.class, int.class},
                    yourPackageName, packageInfo.versionCode, observer, 0, 0);
        } catch (Exception e) {
            
        }


//重寫IPackageDeleteObserver的packageDeleted方法,監(jiān)聽應用卸載情況
private class PackageDeleteObserver extends IPackageDeleteObserver.Stub {

        @Override
        public void packageDeleted(String packageName, int returnCode) {
            Log.d(TAG, "packageName:"+packageName+" returnCode:"+returnCode);
            if (returnCode == 1) {
                //returnCode = 1即成功
            }
        }
    }

然后再在AndroidManifest.xml文件里添加兩行權限聲明:

    <uses-permission android:name="android.permission.DELETE_PACKAGES"/>
    <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />

即可靜默卸載第三方app广辰。


2.清除數(shù)據(jù)

清除數(shù)據(jù)同樣是調(diào)用了PackageManagerService里的方法暇矫,方法名為clearApplicationUserData主之,源碼如下:


clearApplicationUserData部分源碼

可以看到該方法需要傳入packageName、IPackageDataObserver李根、userId等參數(shù)槽奕,其中IPackageDataObserver同上面的IPackageDeleteObserver接入方法,代碼如下:

package android.content.pm;

/**
 * API for package data change related callbacks from the Package Manager.
 * Some usage scenarios include deletion of cache directory, generate
 * statistics related to code, data, cache usage(TODO)
 * {@hide}
 */
oneway interface IPackageDataObserver {
    void onRemoveCompleted(in String packageName, boolean succeeded);
}

編譯后可正常拿到IPackageDataObserver.class房轿,接下來即可通過反射調(diào)用clearApplicationUserData方法了粤攒,代碼如下:

//清數(shù)據(jù)操作
  try {
            DeleteUserDataObserver observer = new DeleteUserDataObserver();
            IBinder pgmService = (IBinder) ReflectUtil.callStaticObjectMethod(Class.forName("android.os.ServiceManager"),
                    "getService", new Class[]{String.class}, "package");
            Object mIPm = ReflectUtil.callStaticObjectMethod(Class.forName("android.content.pm.IPackageManager$Stub"),
                    "asInterface", new Class[]{IBinder.class}, pgmService);
            ReflectUtil.callObjectMethod(mIPm, "clearApplicationUserData",
                    new Class[]{String.class, IPackageDataObserver.class, int.class},
                    yourPackageName, observer, 0);
        } catch (Exception e) {
         
        }

//實現(xiàn)IPackageDataObserver
private class DeleteUserDataObserver extends IPackageDataObserver.Stub {
        @Override
        public void onRemoveCompleted(String packageName, boolean succeeded) {
            Log.d(TAG, "packageName:" + packageName + " isSuccess:" + succeeded);
        }
    }

此操作需要聲明如下權限:

<uses-permission android:name="android.permission.CLEAR_APP_USER_DATA" />

3.降級安裝

這個就厲害了,在leader的啟示下囱持,原來adb命令都是在源碼工程中能找到對應的執(zhí)行方法琼讽。adb中有一個命令可以實現(xiàn)降級安裝adb install -r -d


adb install

通過在源碼中溯源,具體過程就不展示了洪唐,最終調(diào)用了PackageInstaller.SessionParams中的setRequestDowngrade方法钻蹬,具體如下圖:


setRequestDowngrade

可以看到這同樣是一個hide的api,同樣需要用反射去調(diào)用凭需。在安裝過程中拿到SessionParams的實例對象问欠,然后使用反射調(diào)用上述方法,傳入true粒蜈,即可實現(xiàn)降級安裝顺献,具體安裝流程可參考其他博客,這里給出反射代碼:

PackageInstaller.SessionParams sp =
                    new PackageInstaller.SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL);
            ReflectUtil.callObjectMethod(sp, "setRequestDowngrade",
                    new Class[]{boolean.class}, true);

4.總結(jié)

源碼是最好的老師枯怖,當有卡殼的地方時注整,看源碼往往能解決99%的問題。例如在靜默卸載過程中度硝,我們app已經(jīng)成功調(diào)用了反射方法肿轨,且沒有catch到異常,但是一直沒實現(xiàn)效果蕊程,且observer中沒有打印出東西椒袍,后面看了miui的源碼,發(fā)現(xiàn)在miui的framework層設置了一個白名單藻茂,只有白名單內(nèi)的app有權限去調(diào)用卸載方法驹暑,于是在白名單中增加了我們的app,編譯后即可正常實現(xiàn)效果辨赐。

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末优俘,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子掀序,更是在濱河造成了極大的恐慌帆焕,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,248評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件森枪,死亡現(xiàn)場離奇詭異视搏,居然都是意外死亡,警方通過查閱死者的電腦和手機县袱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評論 2 381
  • 文/潘曉璐 我一進店門浑娜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人式散,你說我怎么就攤上這事筋遭。” “怎么了暴拄?”我有些...
    開封第一講書人閱讀 153,443評論 0 344
  • 文/不壞的土叔 我叫張陵漓滔,是天一觀的道長。 經(jīng)常有香客問我乖篷,道長响驴,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,475評論 1 279
  • 正文 為了忘掉前任撕蔼,我火速辦了婚禮豁鲤,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘鲸沮。我一直安慰自己琳骡,他們只是感情好,可當我...
    茶點故事閱讀 64,458評論 5 374
  • 文/花漫 我一把揭開白布讼溺。 她就那樣靜靜地躺著楣号,像睡著了一般。 火紅的嫁衣襯著肌膚如雪怒坯。 梳的紋絲不亂的頭發(fā)上炫狱,一...
    開封第一講書人閱讀 49,185評論 1 284
  • 那天,我揣著相機與錄音剔猿,去河邊找鬼毕荐。 笑死,一個胖子當著我的面吹牛艳馒,可吹牛的內(nèi)容都是我干的憎亚。 我是一名探鬼主播,決...
    沈念sama閱讀 38,451評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼弄慰,長吁一口氣:“原來是場噩夢啊……” “哼第美!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起陆爽,我...
    開封第一講書人閱讀 37,112評論 0 261
  • 序言:老撾萬榮一對情侶失蹤什往,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后慌闭,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體别威,經(jīng)...
    沈念sama閱讀 43,609評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡躯舔,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,083評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了省古。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片粥庄。...
    茶點故事閱讀 38,163評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖豺妓,靈堂內(nèi)的尸體忽然破棺而出惜互,到底是詐尸還是另有隱情,我是刑警寧澤琳拭,帶...
    沈念sama閱讀 33,803評論 4 323
  • 正文 年R本政府宣布训堆,位于F島的核電站,受9級特大地震影響白嘁,放射性物質(zhì)發(fā)生泄漏坑鱼。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,357評論 3 307
  • 文/蒙蒙 一絮缅、第九天 我趴在偏房一處隱蔽的房頂上張望姑躲。 院中可真熱鬧,春花似錦盟蚣、人聲如沸黍析。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽阐枣。三九已至,卻和暖如春奄抽,著一層夾襖步出監(jiān)牢的瞬間蔼两,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評論 1 261
  • 我被黑心中介騙來泰國打工逞度, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留额划,地道東北人。 一個月前我還...
    沈念sama閱讀 45,636評論 2 355
  • 正文 我出身青樓档泽,卻偏偏與公主長得像俊戳,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子馆匿,可洞房花燭夜當晚...
    茶點故事閱讀 42,925評論 2 344

推薦閱讀更多精彩內(nèi)容