Android 6.0 签名校验安装apk

一. 签名分析

使用:

Auto-sign 执行命令

    java -jar signapk.jar testkey.x509.pem testkey.pk8 update.apk update_signed.apk

通过signapk.jar这个可执行jar包,以“testkey.x509.pem”这个公钥文件和“testkey.pk8”这个私钥文件对“update.apk”进行签名,签名后的文件保存为“update_signed.apk”

签名的APK差异:

MANIFEST.MF: 遍历所有文件entry 逐个生成SHA1的数字签名信息,再用Base64进行编码(build/tools/signapk/SignApk.java addDigestsToManifest)

SHA1数字签名。简单地说,它就是一种安全哈希算法,类似于MD5算法。它把任意长度的输入,通过散列算法变成固定长度的输出(摘要信息)

CERT.SF Manifest,使用SHA1-RSA算法,用私钥进行签名

CERT.RSA 公钥签名, 同时对比差异的位置。

获取签名的api:

frameworks/base/core/java/android/content/pm/PackageParser.java

//archiveFilePath指定APK文件路径;flags需设置PackageManager.GET_SIGNATURES

parsePackage(String archiveFilePath, int flags) {

....

//根据包名收集签名信息至PackageParser.Package 签名在PackageParser.Package.mSignatures

packageParser.collectCertificates(pkg, 0);

....

}


二.PMS分析

调用

PackageManagerService是通过使用Context的getPackageManager,在ContextImpl返回的PackageManager实际上是new的ApplicationPackageManager

概括

1.启动

和安装的重要变量 mInstaller(InstallerConnection) 和 mInstallerService (管理安装)

ApplicationPackageManager.installCommon {mPM.installPackage}-> PMS installPackageAsUser->PMS (doHandleMessage)INIT_COPY-> MCS_BOUND

startCopy->handleStartCopy()


Android 6.0 签名校验安装apk_第1张图片
关系图


Android 6.0 签名校验安装apk_第2张图片
应用安装序列图

2.Setting.java 解析 packages.xml 对包名信息解析。

3.解析安装APK

过程比较繁杂,整理一下调用关系更容易分析。从扫描开始:

1. PMS construction { scanDirLI } -> scanDirLI -> scanPackageLI -> scanPackageInternalLI

2. handleStartCopy-> Handler msg case:CHECK_PENDING_VERIFICATION -> processPendingInstall ->

  installPackageLI -> installNewPackageLIF (安装新apk) -> scanPackageTracedLI -> scanPackageLI -> scanPackageInternalLI

---------------------------------------------------------------------------------------------

  installPackageLI ->  replacePackageLI -> replaceNonSystemPackageLI -> scanPackageTracedLI -> scanPackageLI -> scanPackageInternalLI

  installPackageLI ->  replacePackageLI -> replaceSystemPackageLI -> scanPackageTracedLI -> scanPackageLI -> scanPackageInternalLI

---------------------------------------------------------------------------------------------

  most of method invoke deletePackageLIF ->  deleteSystemPackageLIF

---------------------------------------------------------------------------------------------

  StorageEventListener onVolumeStateChanged ->

  1.loadPrivatePackages -> loadPrivatePackagesInner -> scanPackageTracedLI -> scanPackageLI -> scanPackageInternalLI

  2.unloadPrivatePackages -> unloadPrivatePackagesInner -> scanPackageTracedLI -> scanPackageLI -> scanPackageInternalLI

  3.updateExternalMediaStatus -> updateExternalMediaStatusInner ->

    1.loadMediaPackages -> scanPackageTracedLI -> scanPackageLI -> scanPackageInternalLI

    2.unloadMediaPackages -> scanPackageTracedLI -> scanPackageLI -> scanPackageInternalLI

---------------------------------------------------------------------------------------------



三.修改

分析代码我们可以从调用关系入手 installNewPackageLIF 看起来比较合理,于是在:

installNewPackageLI

    private void installNewPackageLI(PackageParser.Package pkg, int parseFlags, int scanFlags,

            UserHandle user, String installerPackageName, String volumeUuid,

            PackageInstalledInfo res) {

        // Remember this for later, in case we need to rollback this install

        String pkgName = pkg.packageName;

//checkSignature here ok

//2.后来修改在这里使用pkg.mSignatures 是可以的。

if (!checkSystemSignature(pkg.mSignatures)) {

    res.setError(INSTALL_FAILED_INVALID_APK, "Can't install unsigned apk");

    return;

}

//getDataUserPackageDirectory will new file in data/data/xxx.xxx(packageName)

        if (DEBUG_INSTALL) Slog.d(TAG, "installNewPackageLI: " + pkg);

        final boolean dataDirExists = Environment

                .getDataUserPackageDirectory(volumeUuid, UserHandle.USER_OWNER, pkgName).exists();

PackageParser.Package newPackage = scanPackageLI(pkg, parseFlags, scanFlags,

                    System.currentTimeMillis(), user);

//checkSignature here only effect first time install

//1. 刚开始是在这里加入 使用newPackage.mSignatures check签名最后发现有问题: 只有第一次有效,第二次无法拦截。

//原因: getDataUserPackageDirectory 在data/data/目录创建了相应 apk的包名信息导致在 installPackageLI() 检查mPackages.containsKey(pkgName)

//已经包含了创建的包名导致replace = true 从而走到 replacePackageLIF

/*   installPackageLI.java

         if (replace) {

            .......

                replacePackageLIF(pkg, parseFlags, scanFlags | SCAN_REPLACING, args.user,

                        installerPackageName, res, args.installReason);

            } else {

                installNewPackageLIF(pkg, parseFlags, scanFlags | SCAN_DELETE_DATA_ON_FAILURES,

                        args.user, installerPackageName, volumeUuid, res, args.installReason);

            }

        */

检查签名:

  在Android.mk 中有三种签名,默认是release 签名。

  LOCAL_CERTIFICATE := platform

  LOCAL_CERTIFICATE := shared

  LOCAL_CERTIFICATE := media

  需求是除了platform shared media外的的签名不安装

    public boolean checkSystemSignature(Signature[] sig) {

        synchronized (mPackages) {

            final PackageParser.Package p2 = mPackages.get("com.android.xxx");

            if (p2 == null || p2.mExtras == null) {

                return false;

            }

            final PackageParser.Package p3 = mPackages.get("com.android.xxxxx");

            if (p3 == null || p3.mExtras == null) {

                return false;

            }

            final PackageParser.Package p4 = mPackages.get("com.android.xxxxxxx");

            if (p4 == null || p4.mExtras == null) {

                Log.d(TAG, "p4 = null");

                return false;

            }

            if (compareSignatures(sig, p2.mSignatures) == PackageManager.SIGNATURE_MATCH

                || compareSignatures(sig, p3.mSignatures) == PackageManager.SIGNATURE_MATCH

                || compareSignatures(sig, p4.mSignatures) == PackageManager.SIGNATURE_MATCH) {

                return true;

            }else {

                return false;

            }

        }

    }

这样功能已经完成,最后优化下,在installPackageLI 中修改 可以更快的生效 因为 installPackageLI 调用的 installNewPackageLI.

参考: https://blog.csdn.net/long375577908/article/details/78550913

你可能感兴趣的:(Android 6.0 签名校验安装apk)