webpad 发表于 2018-3-15 17:38

[未完待续]安卓盒子破解实战系列~第一篇,解除app安装限制

本帖最后由 webpad 于 2019-9-2 12:11 编辑

呃,我的账号还在啊,这贴烂尾楼我得赶紧完结了


安卓盒子破解实战系列

前言
如今国内安卓电视盒子/机顶盒/OTT/STB采用的硬件方案比较多,安卓版本范围从 4.x 到 7.x;研发人员出于各种目的对方案商提供的SDK或多或少都有修改,造成碎片化情况愈演愈烈;
其中营运商定制版安卓盒子的常见限制有:禁止用户安装app、锁定桌面应用以及关键分区和系统文件的校验保护。


第一篇解除app安装限制

一、原理分析
出于国情,国内市面上正式发售的盒子,都没有内置谷歌套件和市场,所以不会用谷歌框架实现对安装文件的合法性验证。
安卓应用的安装最终落实到对.apk安装包的操作,其基本流程如下:
PackageInstaller 或 pm install -> PackageManager -> PackageManagerService

当前国内研发人员实现限制安装的常见方法如下:
1、数字签名白名单
这种方法多见于安卓手机或车机等设备,盒子较少使用,
白名单数字证书一般位于/system/etc/security/;
2、修改版PackageInstaller
如果一个盒子可以在终端中用pm install命令安装.apk,而在盒子的文件管理器中点击.apk却安装失败,
则多半可能是PackageInstaller这个安卓应用层面的安装器被“加强”了;
3、内置文件管理器过滤
原厂固件内置的文件管理器已将 .apk 文件列入过滤列表,不会响应用户的操作;
4、修改版系统框架
pms、ams这些安卓系统服务都位于 framework中,把安卓源代码改得面目全非是每个资深研发人员的“最高”追求,
这也是最常用的限制实现途径。

二、示例

1、实战对象
黑龙江移动魔百和M201-D,硬件方案为晶晨Amlogic S905L ,1+8GB,wifi模块为中龙通Cdtech ,支持蓝牙;

BTW:wifi模块还有可能是 AP6356S 或 RTL8822BS ,非常符合魔百和型号杂乱的现状;


原厂固件包 cmcc_hlj_H1.0.1_S1.0.11_SVN144542_20170918.1519.zip 来自于 /ghost 分区,SDK基于 Android4.4.2,编译版本号为 1.0.11 ;


2、反编译搜寻文本资源
限制安装表现为在试图从文件管理器安装.apk时出现toast警告:
用户您好,本终端已关闭第三方应用的直接安装,请从移动应用商场安装,谢谢!
所以先从这个toast警告文本入手

①、 /system/app/PackageInstaller.apk
此系统应用为应用包安装器,会直接调用pm安装服务,是首要嫌疑犯;
反编译PackageInstaller.apk ,在 /res 资源目录中搜寻文本,没有结果!


在 /smali 目录中搜寻该段文本对应的 unicode编码 ,也没有结果!


②、/system/framework/ framework-res.apk
系统服务使用的资源位于/system/framework/ framework-res.apk,反编译后搜索有结果!
string.xml
    <string name="install_error">用户您好,本终端已关闭第三方应用的直接安装,请从移动应用商场安装,谢谢!</string>
public.xml
    <public type="string" name="install_error" id="0x01040613" />
install_error 的资源 id 为 0x01040613, 这就是下一步需要搜寻的内容,资源id是该文本被调用时的唯一索引。

3、反编译框架之一
/system/framework/ services.jar ,pms 代码位于此处;
反编译后搜索0x01040613 , 没找到!
搜索 0x1040613 ,找到了!
在 PackageManagerService.smali 中找到 两处,有戏:

这两处都位于安装服务底层方法 installPackageLI() 之中,当满足触发条件时由以下代码实现显示toast警告:

    move-object/from16 v0, p0

    iget-object v2, v0, Lcom/android/server/pm/PackageManagerService;->mContext:Landroid/content/Context;

    const v6, 0x1040613

    const/4 v8, 0x1

    invoke-static {v2, v6, v8}, Landroid/widget/Toast;->makeText(Landroid/content/Context;II)Landroid/widget/Toast;

    move-result-object v2

    invoke-virtual {v2}, Landroid/widget/Toast;->show()V

installPackageLI()方法的部分代码如下:
```
.method private installPackageLI(Lcom/android/server/pm/PackageManagerService$InstallArgs;ZLcom/android/server/pm/PackageManagerService$PackageInstalledInfo;)V
    .locals 25
    .param p1, "args"    # Lcom/android/server/pm/PackageManagerService$InstallArgs;
    .param p2, "newInstall"    # Z
    .param p3, "res"    # Lcom/android/server/pm/PackageManagerService$PackageInstalledInfo;

    .prologue
    .line 9249
    move-object/from16 v0, p1

    iget v0, v0, Lcom/android/server/pm/PackageManagerService$InstallArgs;->flags:I

    move/from16 v16, v0

    .line 9250
    .local v16, "pFlags":I
    move-object/from16 v0, p1

    iget-object v7, v0, Lcom/android/server/pm/PackageManagerService$InstallArgs;->installerPackageName:Ljava/lang/String;

    .line 9251
    .local v7, "installerPackageName":Ljava/lang/String;
    new-instance v24, Ljava/io/File;

    invoke-virtual/range {p1 .. p1}, Lcom/android/server/pm/PackageManagerService$InstallArgs;->getCodePath()Ljava/lang/String;

    move-result-object v2

    move-object/from16 v0, v24

    invoke-direct {v0, v2}, Ljava/io/File;-><init>(Ljava/lang/String;)V

    .line 9252
    .local v24, "tmpPackageFile":Ljava/io/File;
    and-int/lit8 v2, v16, 0x1

    if-eqz v2, :cond_0

    const/4 v10, 0x1

    .line 9253
    .local v10, "forwardLocked":Z
    :goto_0
    and-int/lit8 v2, v16, 0x8

    if-eqz v2, :cond_1

    const/4 v15, 0x1

    .line 9254
    .local v15, "onSd":Z
    :goto_1
    const/16 v22, 0x0

    .line 9255
    .local v22, "replace":Z
    if-eqz v15, :cond_2

    const/4 v2, 0x0

    :goto_2
    or-int/lit8 v2, v2, 0x4

    or-int/lit8 v6, v2, 0x8

    if-eqz p2, :cond_3

    const/16 v2, 0x10

    :goto_3
    or-int v5, v6, v2

    .line 9258
    .local v5, "scanMode":I
    const/4 v2, 0x1

    move-object/from16 v0, p3

    iput v2, v0, Lcom/android/server/pm/PackageManagerService$PackageInstalledInfo;->returnCode:I

    .line 9259
    const-string v2, "ro.jsmobile.launcher"

    const-string v6, "false"

    invoke-static {v2, v6}, Landroid/os/SystemProperties;->get(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;

    move-result-object v12

    .line 9260
    .local v12, "jslauncher":Ljava/lang/String;
    const-string v2, "sys.proj.type"

    const-string v6, "ott"

    invoke-static {v2, v6}, Landroid/os/SystemProperties;->get(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;

    move-result-object v20

    .line 9261
    .local v20, "proj_type":Ljava/lang/String;
    const-string v2, "ro.product.name"

    const-string v6, "false"

    invoke-static {v2, v6}, Landroid/os/SystemProperties;->get(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;

    move-result-object v19

    .line 9262
    .local v19, "proj_name":Ljava/lang/String;
    const-string v2, "true"

    invoke-virtual {v2, v12}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z

    move-result v2

    if-eqz v2, :cond_4

    move-object/from16 v0, p1

    iget v2, v0, Lcom/android/server/pm/PackageManagerService$InstallArgs;->flags:I

    move-object/from16 v0, p0

    move-object/from16 v1, v24

    invoke-direct {v0, v1, v2}, Lcom/android/server/pm/PackageManagerService;->isAllowInstall(Ljava/io/File;I)Z

    move-result v2

if-nez v2, :cond_4

    .line 9263
    move-object/from16 v0, p0

    iget-object v2, v0, Lcom/android/server/pm/PackageManagerService;->mContext:Landroid/content/Context;

    const v6, 0x1040613
# 第一处调用
    const/4 v8, 0x1

    invoke-static {v2, v6, v8}, Landroid/widget/Toast;->makeText(Landroid/content/Context;II)Landroid/widget/Toast;

    move-result-object v2

    invoke-virtual {v2}, Landroid/widget/Toast;->show()V

    .line 9264
    const/16 v2, -0x64

    move-object/from16 v0, p3

    iput v2, v0, Lcom/android/server/pm/PackageManagerService$PackageInstalledInfo;->returnCode:I

    .line 9404
    :goto_4
    return-void

    .line 9252
    .end local v5    # "scanMode":I
    .end local v10    # "forwardLocked":Z
    .end local v12    # "jslauncher":Ljava/lang/String;
    .end local v15    # "onSd":Z
    .end local v19    # "proj_name":Ljava/lang/String;
    .end local v20    # "proj_type":Ljava/lang/String;
    .end local v22    # "replace":Z
    :cond_0
    const/4 v10, 0x0

    goto :goto_0

    .line 9253
    .restart local v10    # "forwardLocked":Z
    :cond_1
    const/4 v15, 0x0

    goto :goto_1

    .line 9255
    .restart local v15    # "onSd":Z
    .restart local v22    # "replace":Z
    :cond_2
    const/4 v2, 0x1

    goto :goto_2

    :cond_3
    const/4 v2, 0x0

    goto :goto_3

    .line 9268
    .restart local v5    # "scanMode":I
    .restart local v12    # "jslauncher":Ljava/lang/String;
    .restart local v19    # "proj_name":Ljava/lang/String;
    .restart local v20    # "proj_type":Ljava/lang/String;
    :cond_4
    const-string v2, "unicom"

    move-object/from16 v0, v20

    invoke-virtual {v2, v0}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z

    move-result v2

    if-eqz v2, :cond_9

    sget-object v2, Lcom/android/server/pm/PackageManagerService;->mPackageNameMap:Ljava/util/HashMap;

    if-eqz v2, :cond_9

    .line 9270
    const/4 v9, 0x0

    .line 9271
    .local v9, "caninstall":Z
    new-instance v18, Landroid/content/pm/PackageParser;

    invoke-virtual/range {v24 .. v24}, Ljava/io/File;->getPath()Ljava/lang/String;

    move-result-object v2

    move-object/from16 v0, v18

    invoke-direct {v0, v2}, Landroid/content/pm/PackageParser;-><init>(Ljava/lang/String;)V

    .line 9272
    .local v18, "pp":Landroid/content/pm/PackageParser;
    const/4 v2, 0x0

    move-object/from16 v0, p0

    iget-object v6, v0, Lcom/android/server/pm/PackageManagerService;->mMetrics:Landroid/util/DisplayMetrics;

    move-object/from16 v0, p0

    iget v8, v0, Lcom/android/server/pm/PackageManagerService;->mDefParseFlags:I

    move-object/from16 v0, v18

    move-object/from16 v1, v24

    invoke-virtual {v0, v1, v2, v6, v8}, Landroid/content/pm/PackageParser;->parsePackage(Ljava/io/File;Ljava/lang/String;Landroid/util/DisplayMetrics;I)Landroid/content/pm/PackageParser$Package;

    move-result-object v3

    .line 9273
    .local v3, "pkg":Landroid/content/pm/PackageParser$Package;
    const/4 v11, 0x0

    .local v11, "i":I
    :goto_5
    sget-object v2, Lcom/android/server/pm/PackageManagerService;->mPackageNameMap:Ljava/util/HashMap;

    invoke-virtual {v2}, Ljava/util/HashMap;->size()I

    move-result v2

    if-ge v11, v2, :cond_7

    .line 9274
    iget-object v2, v3, Landroid/content/pm/PackageParser$Package;->packageName:Ljava/lang/String;

    sget-object v6, Lcom/android/server/pm/PackageManagerService;->mPackageNameMap:Ljava/util/HashMap;

    invoke-static {v11}, Ljava/lang/Integer;->valueOf(I)Ljava/lang/Integer;

    move-result-object v8

    invoke-virtual {v6, v8}, Ljava/util/HashMap;->get(Ljava/lang/Object;)Ljava/lang/Object;

    move-result-object v6

    invoke-virtual {v2, v6}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z

    move-result v2

    if-nez v2, :cond_5

    move-object/from16 v0, p0

    iget-object v2, v0, Lcom/android/server/pm/PackageManagerService;->installapkpath:Ljava/lang/String;

    if-eqz v2, :cond_6

    move-object/from16 v0, p0

    iget-object v2, v0, Lcom/android/server/pm/PackageManagerService;->installapkpath:Ljava/lang/String;

    const-string v6, "com.huawei.dsm"

    invoke-virtual {v2, v6}, Ljava/lang/String;->contains(Ljava/lang/CharSequence;)Z

    move-result v2

    if-eqz v2, :cond_6

    .line 9276
    :cond_5
    const/4 v9, 0x1

    .line 9273
    :cond_6
    add-int/lit8 v11, v11, 0x1

    goto :goto_5

    .line 9278
    :cond_7
    move-object/from16 v0, p0

    iget-object v2, v0, Lcom/android/server/pm/PackageManagerService;->installapkpath:Ljava/lang/String;

    const-string v6, "/storage/emulated/0"

    invoke-virtual {v2, v6}, Ljava/lang/String;->contains(Ljava/lang/CharSequence;)Z

    move-result v2

    if-eqz v2, :cond_8

    const-string v2, "cucc_shandong"

    move-object/from16 v0, v19

    invoke-virtual {v2, v0}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z

    move-result v2

    if-eqz v2, :cond_8

    .line 9280
    const/4 v9, 0x1

    .line 9282
    :cond_8
    if-nez v9, :cond_9

    .line 9283
    move-object/from16 v0, p0

    iget-object v2, v0, Lcom/android/server/pm/PackageManagerService;->mContext:Landroid/content/Context;

    const v6, 0x1040613
# 第二处调用
    const/4 v8, 0x1

    invoke-static {v2, v6, v8}, Landroid/widget/Toast;->makeText(Landroid/content/Context;II)Landroid/widget/Toast;

    move-result-object v2

    invoke-virtual {v2}, Landroid/widget/Toast;->show()V

    .line 9284
    const/16 v2, -0x64

    move-object/from16 v0, p3

    iput v2, v0, Lcom/android/server/pm/PackageManagerService$PackageInstalledInfo;->returnCode:I

    goto/16 :goto_4

    .line 9292
    .end local v3    # "pkg":Landroid/content/pm/PackageParser$Package;
    .end local v9    # "caninstall":Z
    .end local v11    # "i":I
    .end local v18    # "pp":Landroid/content/pm/PackageParser;
    :cond_9
    # 以下为正常安装进程,略...
    *
    *
    *
.end method
```

含有两处toast警告的java代码大致如下:
      p3.returnCode = 0x1;
      String "jslauncher" = SystemProperties.get("ro.jsmobile.launcher", "false");
      String "proj_type" = SystemProperties.get("sys.proj.type", "ott");
      String "proj_name" = SystemProperties.get("ro.product.name", "false");
      if ("true".equals("jslauncher")) && (!isAllowInstall("tmpPackageFile", p1.flags))){
                Toast.makeText(mContext, 0x1040613, 0x1).show(); #第一处toast
                p3.returnCode = -0x64;
                return;
            }
      }
      if(("unicom".equals( "proj_type")) && (mPackageNameMap != null)) {
            boolean "caninstall" = false;
            PackageParser "pp" = new PackageParser("tmpPackageFile".getPath());
            PackageParser.Package "pkg" = "pp".parsePackage("tmpPackageFile", 0x0, mMetrics, mDefParseFlags);
            for(int "i" = 0x0; "i" < mPackageNameMap.size(); "i" = "i" + 0x1) {
                if((!"pkg".packageName.equals(mPackageNameMap.get(Integer.valueOf("i")))) || (installapkpath == null) && (!installapkpath.contains("com.huawei.dsm"))) {
                  continue;
                }
                "caninstall" = true;
            }
            if((installapkpath.contains("/storage/emulated/0")) && ("cucc_shandong".equals( "proj_name"))) {
                "caninstall" = true;
            }
            if(!"caninstall") {
                Toast.makeText(mContext, 0x1040613, 0x1).show(); #第二处toast
                p3.returnCode = -0x64;
            }
            return;
      }



可以发现第一处的逻辑如下:
若系统属性com.jsmobile.launcher 为true (江苏移动定制版)且安装包不在允许列表内(isAllowInstall方法会从TR069服务取得允许列表并返回判断结果),
就会触发显示toast警告,并退出安装进程;
但build.prop 中没有 com.jsmobile.launcher 条目,默认赋值为 false,所以安装流程不会走入此if分支;


第二处逻辑如下:
若系统属性sys.proj.type 等于unicom(联通定制版)才会进行后续的条件判断,而本固件build.prop中没有sys.proj.type条目(将会赋值为默认值 ott),
也就是说安装流程并不会走入此 if 分支。


综上所述,这两处禁止安装的toast都不会被触发,显然另有其它机关。


4、反编译框架之二






未完待续








webpad 发表于 2019-9-2 11:34

萌十七 发表于 2019-5-18 02:03
现在一些国内大厂(如小米应用商店,华为应用市场,魅族应用商店)的软件下载在没有root的可以自动安装,不 ...

可以这么理解:
系统级别的应用市场具有system级别的签名,有使用静默安装(silent install)的权限,可以直接调用Pmservice服务,第三方应用商店在未获得root权限/未被赋予root权限的情况下当然是被禁止这么做的。

25soft 发表于 2019-9-9 05:17

楼主可否告知
改固件没这个能力了,
情况是:现有魔百和CM201,想实现不拆机更换开机桌面
1、盒子开机后会自动更新自带桌面启动app
2、安卓手机root了已经安装zANTI,并开启了中间人
请问:因盒子完全删除了文件管理器及安装应用的入口,可否通过zANTI等实现中间人替换盒子下载的app并进行安装?
注:无法获取盒子后台下载app的名字。

fnp902003 发表于 2018-3-15 17:52

下面呢?????

冷月白狐 发表于 2018-3-15 17:54

左手叼根烟 发表于 2018-3-15 17:55

这就结束了?

余生余你余于余 发表于 2018-3-15 17:56

提前占楼观看

ydh423 发表于 2018-3-15 17:57

期待下文{:1_927:}

8438 发表于 2018-3-15 17:58

机顶盒破解方法不会的话,新手可以用悟空遥控器,可以安装一切播放器

无影 发表于 2018-3-15 17:59

楼主这是那啥了?

trombe108 发表于 2018-3-15 18:01

感谢分享!

xxxxu 发表于 2018-3-15 18:05

我昨天帮人弄了安装了几个破解APP 到中国电信的定制的机器上
页: [1] 2 3 4 5 6 7 8 9 10
查看完整版本: [未完待续]安卓盒子破解实战系列~第一篇,解除app安装限制