日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android系统Root与静默安装

發(fā)布時間:2024/1/1 Android 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android系统Root与静默安装 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

Android系統(tǒng)Root與靜默安裝

靜默安裝,指的是安裝時無需任何用戶干預(yù),直接按默認(rèn)設(shè)置安裝應(yīng)用。因?yàn)?#xff0c;它的無需用戶干預(yù),很多情況下變成了用戶壓根不知道,應(yīng)用不知不覺就安裝上了。是在推廣上極為流氓的手段,很類似PC上的捆綁安裝。正因?yàn)殪o默安裝時極為流氓的推廣行為,所以,其推廣價格也極其高。


Android應(yīng)用安裝有如下四種方式

安裝形式完成方式
系統(tǒng)應(yīng)用安裝開機(jī)時完成,需要加入開機(jī)執(zhí)行的腳本,沒有安裝界面
網(wǎng)絡(luò)下載應(yīng)用安裝通過系統(tǒng)market應(yīng)用完成,沒有安裝界面
ADB工具中進(jìn)行安裝使用pm install命令,沒有安裝界面。
第三方應(yīng)用安裝通過SD卡里的APK文件安裝,有安裝界面,由PackageInstaller.apk應(yīng)用處理安裝及卸載過程的界面。

應(yīng)用安裝的流程及路徑

目錄主要功能
/system/app系統(tǒng)自帶的應(yīng)用程序存放,Root權(quán)限才可更改
/data/app用戶程序安裝的目錄,有刪除權(quán)限。安裝時把a(bǔ)pk文件復(fù)制到此目錄
/data/data存放應(yīng)用程序的數(shù)據(jù)
Data/dalvik-cache將apk中的dex文件安裝到dalvik-cache目錄下

安裝過程
復(fù)制APK安裝包到data/app目錄下,解壓并掃描安裝包,把dex文件(Dalvik字節(jié)碼)保存到dalvik-cache目錄,并data/data目錄下創(chuàng)建對應(yīng)的應(yīng)用數(shù)據(jù)目錄。


卸載過程
刪除安裝過程中在上述三個目錄下創(chuàng)建的文件及目錄。


權(quán)限聲明

Google的安全策略要求任何應(yīng)用在安裝確認(rèn)的時候應(yīng)該提示APK安裝包的權(quán)限,即確認(rèn)開發(fā)者在AndroidManafest.xml中聲明的權(quán)限。當(dāng)然,Google在Android上也做了一些操作,允許一些系統(tǒng)內(nèi)部的應(yīng)用不經(jīng)過授權(quán)界面直接進(jìn)行安裝。而系統(tǒng)進(jìn)入安裝界面其實(shí)也是根據(jù)此intent跳轉(zhuǎn)到了PackageInstaller應(yīng)用來完成權(quán)限的提示與安裝的。

這里寫代碼片`我們在應(yīng)用程序中控制安裝應(yīng)用APP,其實(shí)就是發(fā)送一個如下的intent。去調(diào)用packageinstaller進(jìn)行安裝,具體的操作代碼如下:

/* 安裝apk */ Intent intent = new Intent(); intent.setAction(Intent.ACTION_VIEW); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.setDataAndType(Uri.parse("file://"+ fileName),"application/vnd.android.package-archive"); context.startActivity(intent);

對比應(yīng)用正常安裝的流程,靜默安裝的本質(zhì)就是去掉如下圖所示的用戶授權(quán)同意安裝的過程,直接進(jìn)行應(yīng)用安裝。


源碼分析

閱讀過源碼后我們知道,系統(tǒng)的安裝過程其實(shí)是調(diào)用了系統(tǒng)中的PackageInstaller來完成的。希望做到靜默安裝,就是找到一個方法,繞過PackageInstaller中的權(quán)限授予提示,繼續(xù)完成安裝的步驟。
所以,思路很簡單,我們可以從兩方面去操作:

  • 找到PackageInstaller源碼,跳過權(quán)限授予提醒,直接調(diào)用后面的安裝API即可完成安裝。(這樣能夠良好的兼容正常安裝,不易出錯)
  • 使用pm install 命令進(jìn)行安裝。

調(diào)用PackageInstaller中隱藏的API

查看PackageInstaller源碼我們能夠發(fā)現(xiàn),其實(shí)PackageInstaller也是通過使用PackageManager進(jìn)行安裝的。調(diào)用的是其installPackage方法,但是此方法是一個abstract,且是對外不可見的(hide),

定義如下所示:

public abstractclass PackageManager { ……… /*** 安裝應(yīng)用APK文件* @param packageURI 待安裝的APK文件位置,可以是'file:'或'content:' URI.* @param observer 一個APK文件安裝狀態(tài)的觀察器* @param flags 安裝形式 INSTALL_FORWARD_LOCK, INSTALL_REPLACE_EXISTING, INSTALL_ALLOW_TEST.* @paraminstallerPackageName APK安裝包的PackageName*/ // @SystemApi public abstract void installPackage(UripackageURI, PackageInstallObserverobserver,int flags,StringinstallerPackageName); }

且PackageManager與installPackage兩者皆為abstract抽象的。其具體實(shí)現(xiàn)都在ApplicationPackageManager中,其installPackage中的實(shí)現(xiàn)為:

final classApplicationPackageManager extends PackageManager {......ApplicationPackageManager(ContextImpl context, IPackageManager pm) {mContext = context;mPM = pm;}@Overridepublic void installPackage(Uri packageURI, IPackageInstallObserver observer,intflags, String installerPackageName){try {mPM.installPackage(packageURI, observer, flags, installerPackageName);} catch (RemoteException e) {// Should never happen!}} }

可見調(diào)用的installPackage方法為IPackageManager中的installPackage方法。在ContextImpl中通過調(diào)用
ActivityThread.getPackageManager()獲得IPackageManager實(shí)例對象。而在在ActivityThread.getPackageManager()方法中,是調(diào)用SystemService中的名為package的Service來實(shí)例化的。代碼如下:

staticIPackageManager sPackageManager;public staticIPackageManager getPackageManager() {if (sPackageManager != null) {return sPackageManager;}IBinder b = ServiceManager.getService("package");sPackageManager = IPackageManager.Stub.asInterface(b);return sPackageManager; }

因?yàn)?#xff0c;installPackage是系統(tǒng)的API,為了使用PackageManagerService.installPackage(),考慮通過反射機(jī)制可以調(diào)用installPackage()。

但其中難以得到的是其參數(shù)中的IPackageInstallObserver類型,我們看來一下IPackageInstallObserver,發(fā)現(xiàn)IPackageInstallObserver是由aidl文件定義的。這個也難不倒我們,通過aidl文件的特性,將IPackageInstallObserver.aidl文件拷到本地程序中,可以得到類IPackageInstallObserver.calss,通過它反射出installPackage()方法。

但在invoke調(diào)用該方法時,卻無法得到IPackageInstallObserver的實(shí)例對象,IPackageInstallObserver的實(shí)例對象必須通過IPackageInstallObserver.Stub.asInterface(Binder binder)方式得到,無法得到與其綁定的Binder對象,因而無法執(zhí)行反射出來的方法。

其次,應(yīng)為是系統(tǒng)API,需要聲明安裝應(yīng)用的權(quán)限:android.permission.INSTALL_PACKAGES。當(dāng)時這類比較敏感的權(quán)限不是說聲明系統(tǒng)就會給予的,還需要我們的安裝包APK文件擁有與系統(tǒng)相同的簽名,才能完成靜默安裝操作。這個方式的靜默安裝,對于廣泛的推廣應(yīng)用是不現(xiàn)實(shí)的。

使用pm命令安裝

pm 命令是Android里面PackageManage的命令行,用于安裝包的操作。而系統(tǒng)也主要是提供我們在adb
shell中進(jìn)行使用pm命令,因此pm命令也存在與“/system”目錄下,當(dāng)然,擁有了Root權(quán)限后的應(yīng)用程序就能夠使用它進(jìn)行靜默安裝了。

具體的操作代碼如下所示:

// xxx.apk放置在內(nèi)置儲存的根目錄下 execCommand("system/bin/pminstall -r " + "sdcard/xxx.apk"); // 執(zhí)行command public booleanexecCommand(String cmd) {Process process = null;try {process = Runtime.getRuntime().exec(cmd);process.waitFor();} catch (Exception e) {return false;} finally {try {process.destroy();} catch (Exception e) {}}return true; }

pm命令源碼目錄:
/frameworks/base/cmds/pm/src/com/android/commands/pm/Pm.java,

我們查看其源碼,如下:

public finalclass Pm {IPackageManager mPm;IUserManager mUm;private WeakHashMap<String, Resources> mResourceCache= new WeakHashMap<String, Resources>();private String[] mArgs;private int mNextArg;private String mCurArgData;private static final String PM_NOT_RUNNING_ERR ="Error: Could not access thePackage Manager. Is the systemrunning?";public static void main(String[] args) {new Pm().run(args);}/*** 解析命令參數(shù)* @param args 參數(shù)*/public void run(String[] args) {boolean validCommand = false;if (args.length < 1) {showUsage();return;}mUm =IUserManager.Stub.asInterface(ServiceManager.getService("user"));mPm =IPackageManager.Stub.asInterface(ServiceManager.getService("package"));if (mPm == null) {System.err.println(PM_NOT_RUNNING_ERR);return;}......if("install".equals(op)) {runInstall();return;}......}/*** 開始安裝*/private void runInstall() {......// 安裝邏輯的具體調(diào)用PackageInstallObserver obs = newPackageInstallObserver();try {VerificationParamsverificationParams = new VerificationParams(verificationURI,originatingURI, referrerURI, VerificationParams.NO_UID,null);mPm.installPackageWithVerificationAndEncryption(apkURI, obs, installFlags,installerPackageName, verificationParams, encryptionParams);synchronized (obs) {while (!obs.finished) {try {obs.wait();} catch(InterruptedException e) {}}if (obs.result ==PackageManager.INSTALL_SUCCEEDED) {System.out.println("Success");} else {System.err.println("Failure["+installFailureToString(obs.result)+ "]");}}} catch (RemoteException e) {System.err.println(e.toString());System.err.println(PM_NOT_RUNNING_ERR);}}...... }

發(fā)現(xiàn)其實(shí)pm命令也是調(diào)用了PackageManager中的安裝方法,只不過是一個驗(yàn)證和加密的方法installPackageWithVerificationAndEncryption進(jìn)行安裝的。即,它的安裝過程與PackageInstaller是一樣的。

而我們安裝應(yīng)用APP的時候,可以是自己的APK安裝包文件存儲在兩個地方“data/app”與“system/app”下,靜默安裝的時候一般情況都是選擇將自己的APK文件push到“system/app”目錄下, 因?yàn)榇四夸浭窍到y(tǒng)應(yīng)用的目錄,在此目錄下的惡意應(yīng)用,進(jìn)行偷發(fā)短信、竊取郵件等操作,用戶是很難察覺的。


刪除預(yù)裝

大部分的普通用戶Root手機(jī)的主要目的就是刪除系統(tǒng)預(yù)先安裝的應(yīng)用程序,要刪除它們,我們首先要知道什么是預(yù)裝應(yīng)用,它們存放在哪里。或者我們換一個思路來看看,系統(tǒng)制造商將應(yīng)用程序的APK文件存放在哪里才能變?yōu)橄到y(tǒng)的應(yīng)用。

1. 系統(tǒng)默認(rèn)的常規(guī)應(yīng)用存放處

Android系統(tǒng)的捆綁應(yīng)用軟件基本安裝在“/system/app”文件夾下,刪除下面的對應(yīng)的了第三方軟件APK文件即可完美卸載。我們知道“/system”是系統(tǒng)的目錄,對此目錄進(jìn)行操作需要Root權(quán)限,所以我們刪除預(yù)裝應(yīng)用需要Root手機(jī)。每個系統(tǒng)程序基本上都是成對的,對應(yīng)的刪除掉后綴分別是.apk 和.odex(優(yōu)化過的dex文件)文件即可刪除預(yù)裝應(yīng)用。

如下圖,使用了Root Explorer查看“/system/app”目錄。則能夠看到了系統(tǒng)中的所有的系統(tǒng)內(nèi)置應(yīng)用程序。

2. 修改系統(tǒng)引導(dǎo)的預(yù)裝

對于存放Apk文件到”/system/app“目錄下已經(jīng)是很普通的預(yù)裝方式了,這就導(dǎo)致了,預(yù)裝應(yīng)用很容易就被卸載掉。惡意的手機(jī)ROM就會想著更加惡心的方法來留住預(yù)裝應(yīng)用,比如修改系統(tǒng)ROM的邏輯,讓系統(tǒng)在開機(jī)的時候檢測一下自己的預(yù)裝是否完整然后重新安裝。那么,當(dāng)然系統(tǒng)預(yù)裝應(yīng)用的安裝文件也會在另一個保存一份。

這類的預(yù)裝應(yīng)用,又稱為“開機(jī)靜默安裝”,常用的方式就是修改init.rc,添加一個開機(jī)執(zhí)行的腳本,在腳本中調(diào)用一個Service使用pm install命令批量安裝應(yīng)用。
如,自頂一個一個init.local.rc內(nèi)容如下:

#Preinstall onproperty:dev.bootcomplete=1start loadpreinstallsserviceloadpreinstalls /system/bin/logwrapper /system/bin/loadpreinstalls.shdisabledoneshot

在系統(tǒng)的init.rc腳本中調(diào)用init.local.rc如下:

#在sysinit前面加 # Include extrainit fileimport /system/etc/init.local.rc而具體的預(yù)裝腳本存在/system/bin/ loadpreinstalls.sh# do preinstall job if [ ! -e /data/.notfirstrun ] then echo "dopreinstall sys" >> /system/log.txt #安裝/system/preinstall下的所有apk文件APKLIST=`ls /system/preinstall/*.apk`for INFILES in $APKLISTdoecho setup package:$INFILESpm install -r $INFILESdoneecho "dopreinstall sd" >> /system/log.txt #安裝/sdcard/preinstall下的所有apk文件APKLIST=`ls /sdcard/preinstall/*.apk`for INFILES in $APKLISTdoecho setup package:$INFILESpm install -r $INFILESdoneecho "do preinstall ok" >> /system/log.txtbusybox touch /data/.notfirstrun fiecho "============================================">> /system/log.txt exit

此方式做預(yù)裝用戶在使用Root后刪除掉/system/app下的已安裝應(yīng)用后,系統(tǒng)重啟后又會執(zhí)行啟動腳本自動重裝預(yù)裝應(yīng)用回來,且預(yù)裝apk文件的存放目錄根據(jù)不同的系統(tǒng)ROM還不一樣,是極為流氓的推廣策略。當(dāng)然,我們通過分析已經(jīng)看到了,如果要刪除此類的預(yù)裝應(yīng)用,只需要全盤的掃描apk文件再進(jìn)行刪除即可。

/*
* @author zhoushengtao(周圣韜)
* @since 2015年1月27日 上午14:02:22
* @weixin stchou_zst
* @blog http://blog.csdn.net/yzzst
* @交流學(xué)習(xí)QQ群:341989536
* @私人QQ:445914891
/

總結(jié)

以上是生活随笔為你收集整理的Android系统Root与静默安装的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。