Android系统Root与静默安装

静默安装,指的是安装时无需任何用户干预,直接按默认设置安装应用。因为,它的无需用户干预,很多情况下变成了用户压根不知道,应用不知不觉就安装上了。是在推广上极为流氓的手段,很类似PC上的捆绑安装。正因为静默安装时极为流氓的推广行为,所以,其推广价格也极其高。


Android应用安装有如下四种方式

安装形式 完成方式
系统应用安装 开机时完成,需要加入开机执行的脚本,没有安装界面
网络下载应用安装 通过系统market应用完成,没有安装界面
ADB工具中进行安装 使用pm install命令,没有安装界面。
第三方应用安装 通过SD卡里的APK文件安装,有安装界面,由PackageInstaller.apk应用处理安装及卸载过程的界面。

应用安装的流程及路径

目录 主要功能
/system/app 系统自带的应用程序存放,Root权限才可更改
/data/app 用户程序安装的目录,有删除权限。安装时把apk文件复制到此目录
/data/data 存放应用程序的数据
Data/dalvik-cache 将apk中的dex文件安装到dalvik-cache目录下

安装过程 
复制APK安装包到data/app目录下,解压并扫描安装包,把dex文件(Dalvik字节码)保存到dalvik-cache目录,并data/data目录下创建对应的应用数据目录。


卸载过程 
删除安装过程中在上述三个目录下创建的文件及目录。


权限声明

Google的安全策略要求任何应用在安装确认的时候应该提示APK安装包的权限,即确认开发者在AndroidManafest.xml中声明的权限。当然,Google在Android上也做了一些操作,允许一些系统内部的应用不经过授权界面直接进行安装。而系统进入安装界面其实也是根据此intent跳转到了PackageInstaller应用来完成权限的提示与安装的。

这里写代码片`我们在应用程序中控制安装应用APP,其实就是发送一个如下的intent。去调用packageinstaller进行安装,具体的操作代码如下:

<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/* 安装apk */</span>
Intent intent = new Intent()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
intent<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setAction</span>(Intent<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.ACTION</span>_VIEW)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
intent<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.addFlags</span>(Intent<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.FLAG</span>_ACTIVITY_NEW_TASK)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
intent<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setDataAndType</span>(Uri<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.parse</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"file://"</span>+ fileName),
   <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"application/vnd.android.package-archive"</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
context<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.startActivity</span>(intent)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li></ul>

对比应用正常安装的流程,静默安装的本质就是去掉如下图所示的用户授权同意安装的过程,直接进行应用安装。

这里写图片描述


源码分析

阅读过源码后我们知道,系统的安装过程其实是调用了系统中的PackageInstaller来完成的。希望做到静默安装,就是找到一个方法,绕过PackageInstaller中的权限授予提示,继续完成安装的步骤。 
所以,思路很简单,我们可以从两方面去操作:

  • 找到PackageInstaller源码,跳过权限授予提醒,直接调用后面的安装API即可完成安装。(这样能够良好的兼容正常安装,不易出错)
  • 使用pm install 命令进行安装。

调用PackageInstaller中隐藏的API

查看PackageInstaller源码我们能够发现,其实PackageInstaller也是通过使用PackageManager进行安装的。调用的是其installPackage方法,但是此方法是一个abstract,且是对外不可见的(hide),

定义如下所示:

<code class="hljs java has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> abstractclass PackageManager {
………
<span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
 * 安装应用APK文件
 *<span class="hljs-javadoctag" style="color: rgb(102, 0, 102); box-sizing: border-box;"> @param</span> packageURI 待安装的APK文件位置,可以是'file:'或'content:' URI.
 *<span class="hljs-javadoctag" style="color: rgb(102, 0, 102); box-sizing: border-box;"> @param</span> observer 一个APK文件安装状态的观察器
 *<span class="hljs-javadoctag" style="color: rgb(102, 0, 102); box-sizing: border-box;"> @param</span> flags 安装形式 INSTALL_FORWARD_LOCK, INSTALL_REPLACE_EXISTING, INSTALL_ALLOW_TEST.
 *<span class="hljs-javadoctag" style="color: rgb(102, 0, 102); box-sizing: border-box;"> @paraminstallerPackageName</span> APK安装包的PackageName
 */</span>
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// @SystemApi</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">abstract</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">installPackage</span>(UripackageURI, PackageInstallObserverobserver,<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> flags,
        StringinstallerPackageName);
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li></ul>

且PackageManager与installPackage两者皆为abstract抽象的。其具体实现都在ApplicationPackageManager中,其installPackage中的实现为:

<code class="hljs java has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> classApplicationPackageManager extends PackageManager {
   ......

   ApplicationPackageManager(ContextImpl context, IPackageManager pm) {
       mContext = context;
        mPM = pm;
   }

   <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>
   <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">installPackage</span>(Uri packageURI, IPackageInstallObserver observer,intflags, String installerPackageName){
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span> {
            mPM.installPackage(packageURI, observer, flags, installerPackageName);
        } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">catch</span> (RemoteException e) {
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Should never happen!</span>
        }
   }
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li></ul>

可见调用的installPackage方法为IPackageManager中的installPackage方法。在ContextImpl中通过调用 
ActivityThread.getPackageManager()获得IPackageManager实例对象。而在在ActivityThread.getPackageManager()方法中,是调用SystemService中的名为package的Service来实例化的。代码如下:

<code class="hljs cs has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">staticIPackageManager sPackageManager;

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> staticIPackageManager <span class="hljs-title" style="box-sizing: border-box;">getPackageManager</span>() {
   <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (sPackageManager != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> sPackageManager;
   }
   IBinder b = ServiceManager.getService(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"package"</span>);
   sPackageManager = IPackageManager.Stub.asInterface(b);
   <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> sPackageManager;
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li></ul>

因为,installPackage是系统的API,为了使用PackageManagerService.installPackage(),考虑通过反射机制可以调用installPackage()。

但其中难以得到的是其参数中的IPackageInstallObserver类型,我们看来一下IPackageInstallObserver,发现IPackageInstallObserver是由aidl文件定义的。这个也难不倒我们,通过aidl文件的特性,将IPackageInstallObserver.aidl文件拷到本地程序中,可以得到类IPackageInstallObserver.calss,通过它反射出installPackage()方法。

但在invoke调用该方法时,却无法得到IPackageInstallObserver的实例对象,IPackageInstallObserver的实例对象必须通过IPackageInstallObserver.Stub.asInterface(Binder binder)方式得到,无法得到与其绑定的Binder对象,因而无法执行反射出来的方法。

其次,应为是系统API,需要声明安装应用的权限:android.permission.INSTALL_PACKAGES。当时这类比较敏感的权限不是说声明系统就会给予的,还需要我们的安装包APK文件拥有与系统相同的签名,才能完成静默安装操作。这个方式的静默安装,对于广泛的推广应用是不现实的。

使用pm命令安装

pm 命令是Android里面PackageManage的命令行,用于安装包的操作。而系统也主要是提供我们在adb 
shell中进行使用pm命令,因此pm命令也存在与“/system”目录下,当然,拥有了Root权限后的应用程序就能够使用它进行静默安装了。

具体的操作代码如下所示:

<code class="hljs cs has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// xxx.apk放置在内置储存的根目录下</span>
execCommand(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"system/bin/pminstall -r "</span> + <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"sdcard/xxx.apk"</span>);
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 执行command</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-title" style="box-sizing: border-box;">booleanexecCommand</span>(String cmd) {
   Process process = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>;
   <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span> {
        process = Runtime.getRuntime().exec(cmd);
        process.waitFor();
   } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">catch</span> (Exception e) {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>;
   } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">finally</span> {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span> {
           process.destroy();
        } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">catch</span> (Exception e) {
        }
   }
   <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>;
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li></ul>

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

我们查看其源码,如下:

<code class="hljs java has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> finalclass Pm {
   IPackageManager mPm;
   IUserManager mUm;

   <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> WeakHashMap<String, Resources> mResourceCache
            = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> WeakHashMap<String, Resources>();

   <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> String[] mArgs;
   <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> mNextArg;
   <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> String mCurArgData;

   <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> String PM_NOT_RUNNING_ERR =
        <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Error: Could not access thePackage Manager.  Is the systemrunning?"</span>;

   <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">main</span>(String[] args) {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Pm().run(args);
   }

   <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
    * 解析命令参数
    *<span class="hljs-javadoctag" style="color: rgb(102, 0, 102); box-sizing: border-box;"> @param</span> args 参数
    */</span>
   <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">run</span>(String[] args) {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> validCommand = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>;
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (args.length < <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>) {
            showUsage();
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span>;
        }

        mUm =IUserManager.Stub.asInterface(ServiceManager.getService(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"user"</span>));
        mPm =IPackageManager.Stub.asInterface(ServiceManager.getService(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"package"</span>));
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mPm == <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {
           System.err.println(PM_NOT_RUNNING_ERR);
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span>;
        }


        ......

        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"install"</span>.equals(op)) {
            runInstall();
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span>;
        }

        ......
   }

   <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
    * 开始安装
    */</span>
   <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">runInstall</span>() {
        ......

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 安装逻辑的具体调用</span>
        PackageInstallObserver obs = newPackageInstallObserver();
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span> {
            VerificationParamsverificationParams = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> VerificationParams(verificationURI,
                    originatingURI, referrerURI, VerificationParams.NO_UID,<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>);

           mPm.installPackageWithVerificationAndEncryption(apkURI, obs, installFlags,
                    installerPackageName, verificationParams, encryptionParams);

            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">synchronized</span> (obs) {
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">while</span> (!obs.finished) {
                    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span> {
                        obs.wait();
                    } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">catch</span>(InterruptedException e) {
                    }
                }
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (obs.result ==PackageManager.INSTALL_SUCCEEDED) {
                   System.out.println(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Success"</span>);
                } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> {
                    System.err.println(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Failure["</span>
                            +installFailureToString(obs.result)
                            + <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"]"</span>);
                }
            }
        } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">catch</span> (RemoteException e) {
            System.err.println(e.toString());
           System.err.println(PM_NOT_RUNNING_ERR);
        }
   }

   ......
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: border-box; padding: 0px 5px;">62</li><li style="box-sizing: border-box; padding: 0px 5px;">63</li><li style="box-sizing: border-box; padding: 0px 5px;">64</li><li style="box-sizing: border-box; padding: 0px 5px;">65</li><li style="box-sizing: border-box; padding: 0px 5px;">66</li><li style="box-sizing: border-box; padding: 0px 5px;">67</li><li style="box-sizing: border-box; padding: 0px 5px;">68</li><li style="box-sizing: border-box; padding: 0px 5px;">69</li><li style="box-sizing: border-box; padding: 0px 5px;">70</li><li style="box-sizing: border-box; padding: 0px 5px;">71</li><li style="box-sizing: border-box; padding: 0px 5px;">72</li><li style="box-sizing: border-box; padding: 0px 5px;">73</li><li style="box-sizing: border-box; padding: 0px 5px;">74</li><li style="box-sizing: border-box; padding: 0px 5px;">75</li><li style="box-sizing: border-box; padding: 0px 5px;">76</li><li style="box-sizing: border-box; padding: 0px 5px;">77</li><li style="box-sizing: border-box; padding: 0px 5px;">78</li><li style="box-sizing: border-box; padding: 0px 5px;">79</li><li style="box-sizing: border-box; padding: 0px 5px;">80</li><li style="box-sizing: border-box; padding: 0px 5px;">81</li><li style="box-sizing: border-box; padding: 0px 5px;">82</li><li style="box-sizing: border-box; padding: 0px 5px;">83</li><li style="box-sizing: border-box; padding: 0px 5px;">84</li><li style="box-sizing: border-box; padding: 0px 5px;">85</li></ul>

发现其实pm命令也是调用了PackageManager中的安装方法,只不过是一个验证和加密的方法installPackageWithVerificationAndEncryption进行安装的。即,它的安装过程与PackageInstaller是一样的。

而我们安装应用APP的时候,可以是自己的APK安装包文件存储在两个地方“data/app”与“system/app”下,静默安装的时候一般情况都是选择将自己的APK文件push到“system/app”目录下, 因为此目录是系统应用的目录,在此目录下的恶意应用,进行偷发短信、窃取邮件等操作,用户是很难察觉的。


删除预装

大部分的普通用户Root手机的主要目的就是删除系统预先安装的应用程序,要删除它们,我们首先要知道什么是预装应用,它们存放在哪里。或者我们换一个思路来看看,系统制造商将应用程序的APK文件存放在哪里才能变为系统的应用。

1. 系统默认的常规应用存放处

Android系统的捆绑应用软件基本安装在“/system/app”文件夹下,删除下面的对应的了第三方软件APK文件即可完美卸载。我们知道“/system”是系统的目录,对此目录进行操作需要Root权限,所以我们删除预装应用需要Root手机。每个系统程序基本上都是成对的,对应的删除掉后缀分别是.apk 和.odex(优化过的dex文件)文件即可删除预装应用。

如下图,使用了Root Explorer查看“/system/app”目录。则能够看到了系统中的所有的系统内置应用程序。 
这里写图片描述

2. 修改系统引导的预装

对于存放Apk文件到”/system/app“目录下已经是很普通的预装方式了,这就导致了,预装应用很容易就被卸载掉。恶意的手机ROM就会想着更加恶心的方法来留住预装应用,比如修改系统ROM的逻辑,让系统在开机的时候检测一下自己的预装是否完整然后重新安装。那么,当然系统预装应用的安装文件也会在另一个保存一份。

这类的预装应用,又称为“开机静默安装”,常用的方式就是修改init.rc,添加一个开机执行的脚本,在脚本中调用一个Service使用pm install命令批量安装应用。 
如,自顶一个一个init.local.rc内容如下:

<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#Preinstall</span>
<span class="hljs-label" style="box-sizing: border-box;">onproperty:</span>dev<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.bootcomplete</span>=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>
         start loadpreinstalls

serviceloadpreinstalls /system/bin/logwrapper /system/bin/loadpreinstalls<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.sh</span>
         disabled
         oneshot
</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li></ul>

在系统的init.rc脚本中调用init.local.rc如下:

<code class="hljs bash has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">#在sysinit前面加</span>
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># Include extrainit file</span>
             import /system/etc/init.local.rc

         而具体的预装脚本存在/system/bin/ loadpreinstalls.sh

<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># do preinstall job</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> [ ! <span class="hljs-operator" style="box-sizing: border-box;">-e</span> /data/.notfirstrun ]
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">then</span>
<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">echo</span> <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"dopreinstall sys"</span> >> /system/log.txt
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">#安装/system/preinstall下的所有apk文件</span>
    APKLIST=`ls /system/preinstall/*.apk`
   <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> INFILES <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span> <span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">$APKLIST</span>
   <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">do</span>
     <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">echo</span>  setup package:<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">$INFILES</span>
     pm install -r <span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">$INFILES</span>
   <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">done</span>

<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">echo</span> <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"dopreinstall sd"</span> >> /system/log.txt
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">#安装/sdcard/preinstall下的所有apk文件</span>
   APKLIST=`ls /sdcard/preinstall/*.apk`
   <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> INFILES <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span> <span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">$APKLIST</span>
   <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">do</span>
     <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">echo</span>  setup package:<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">$INFILES</span>
     pm install -r <span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">$INFILES</span>
   <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">done</span>
   <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">echo</span> <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"do preinstall ok"</span> >> /system/log.txt
   busybox touch /data/.notfirstrun   
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">fi</span>

<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">echo</span> <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"============================================"</span>>> /system/log.txt
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">exit</span></code>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值