Android Root 环境下修改系统源码方案

842 阅读3分钟

参考博客:在有root权限下破解Android系统签名,安装未系统签名的APK

本文将为您介绍在 Android 系统 Root 后,如何安装系统级别的 App 。也是对参考文章《在有root权限下破解Android系统签名,安装未系统签名的APK》的实践。 关于 Root 方法,请自行检索学习。

在一些功能需要使用到系统级 App 才能使用的权限时,最直接的方案就是将你的应用升级为系统应用。如此需要以下步骤:

  • 确保您的手机已 Root 或自行编译的 Android 系统(能够提取到系统签名文件)。

  • 您的 App 签名应该是系统签名;若您的应用不是系统签名,将会报错:

    Installation did not succeed.
    The application could not be installed: INSTALL_FAILED_SHARED_USER_INCOMPATIBLE
    
  • 在您的项目中,AndroidManifest.xml 中 manifest 标签中增加以下内容:

    android:sharedUserId="android.uid.system"
    

首先通过 adb 连接到手机,并切换到超级权限:

adb root

从系统中拉取文件:

adb pull /system/framework/services.jar /你的电脑自定义目录

对文件进行解压:

unzip services.jar 

你将获得以下文件:

image-20230105175705708.png 执行命令查找包含签名报错相关内容的 dex 文件:

grep -lr "has no signatures that match those in shared user" services

此时会输出:services/classes.dex ,下一步就是使用 baksmali 工具对 classes.dex 进行反编译。

baksmali 下载地址:bitbucket.org/JesusFreke/…

java -jar baksmali-2.5.2.jar d classes.dex

此时当前目录下会生成一个 out 文件夹,生成对应的所有 smali 文件。对该文件下的内容进行修改,修改后重新打包成 services.jar 。

此时再文件中搜索 "has no signatures that match those in shared user" ,文件会过滤出 PackageManagerServiceUtils.smali 文件:

image-20230105183207055.png

说明相关逻辑再 PackageManagerServiceUtils 中,去 Android 源码中查找相关内容,会找到相关文件:

frameworks/base/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java

在代码中搜索上面的相关字段,会找到验证签名逻辑的方法,注意查找你的 Android 系统版本的源码:

image-20230105190023401.png

相关逻辑在 verifySignatures 方法中:

           if (!match) {
                throw new PackageManagerException(INSTALL_FAILED_SHARED_USER_INCOMPATIBLE,
                        "Package " + packageName
                        + " has no signatures that match those in shared user "
                        + sharedUserSetting.name + "; ignoring!");
            }
​
            // ...
​
            // If the lineage of this package diverges from the lineage of the sharedUserId then
            // do not allow the installation to proceed.
            if (!parsedSignatures.hasCommonAncestor(
                    sharedUserSetting.signatures.mSigningDetails)) {
                throw new PackageManagerException(INSTALL_FAILED_SHARED_USER_INCOMPATIBLE,
                        "Package " + packageName + " has a signing lineage "
                                + "that diverges from the lineage of the sharedUserId");
            }

在 PackageManagerServiceUtils.smali 中查找对应的相关字段,会定位到相应位置:

//689 行判断了 if(!match)
.line 689 
    :cond_109
    const/4 p3, -0x8
​
    if-eqz p1, :cond_18d // if-nez p1, :cond_18d
​
​
// 725 行判断了 if (!parsedSignatures.hasCommonAncestor(...))
.line 725
    invoke-virtual {p2, p0}, Landroid/content/pm/PackageParser$SigningDetails;->hasCommonAncestor(Landroid/content/pm/PackageParser$SigningDetails;)Z
​
    move-result p0
​
    if-eqz p0, :cond_173 // if-nez p0, :cond_173 即 if==0 改为 if !=0
​
    goto :goto_1b5
​
    .line 727
    :cond_173
    new-instance p0, Lcom/android/server/pm/PackageManagerException;
...

此时需要你去熟悉一下 smali 语法,这里主要是将 if-eqz 修改为 if-nez ,相关语法可参考下面这篇文章:

github.com/JnuSimba/An…

修改位置有两处, 689 行的判断条件:

 if (!match) {
                throw new PackageManagerException(INSTALL_FAILED_SHARED_USER_INCOMPATIBLE,
                        "Package " + packageName
                        + " has no signatures that match those in shared user "
                        + sharedUserSetting.name + "; ignoring!");
            }

725 行判断逻辑:

            if (!parsedSignatures.hasCommonAncestor(
                    sharedUserSetting.signatures.mSigningDetails)) {
                throw new PackageManagerException(INSTALL_FAILED_SHARED_USER_INCOMPATIBLE,
                        "Package " + packageName + " has a signing lineage "
                                + "that diverges from the lineage of the sharedUserId");
            }

修改含义是将其判断条件不成立,不进入抛出异常逻辑即可。

然后对修改后的文件重新打包,这里需要用到 smali 进行打包,

下载链接:bitbucket.org/JesusFreke/…

执行命令:

java -jar smali-2.5.2.jar a out

此时会在当前目录下生成一个 out.dex 文件,将这个文件替换原来的 class.dex 并重新打包 jar 文件。

jar cvfm services1.jar unzip/META-INF/MANIFEST.MF -C unzip/ . &>/dev/null

这里 unzip 目录就是之前解压 service.jar 后的文件所在目录

执行完该命令后,当前文件夹会生成 services1.jar 文件,将修改后的 services1.jar 重命名为 services.jar 并 push 到设备重启:

adb root
adb remount
adb push services.jar /system/framework/services.jar
adb reboot

如此,就可以将 App 安装到手机上了(虽然安装成功了但直接 ANR) 。尽管后续存在一些问题,但是本文提供了修改系统源码逻辑的手段。了解反编译、修改 smali 文件、编译的整体流程。