如果一个菲系统签名的APK,安装系统中需要platform的权限,如何做?思路有以下几个:
-
修改APK的签名,也就是伪装签名,(常用在游戏破解)
-
增加用户分组,需要Linux系统底层支持,改起来比较烦。类似与一个文件系统chmod 777这可以让所有用户去读写的方式。
-
伪装APP,需要依附系统APP,取得对应的context。
-
最简单的方法(可以改FW源码)
我们这里对Android的系统packagemanager做下分析,用第一种方式去做,当然方法不止一种。最简单的方式是在install过程中将APK签名给替换掉。
首先找到install方法:
private void installPackageLI(InstallArgs args, PackageInstalledInfo res) {
final int installFlags = args.installFlags;
final String installerPackageName = args.installerPackageName;
final String volumeUuid = args.volumeUuid;
final File tmpPackageFile = new File(args.getCodePath());
final boolean forwardLocked = ((installFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0);
final boolean onExternal = (((installFlags & PackageManager.INSTALL_EXTERNAL) != 0)
|| (args.volumeUuid != null));
final boolean instantApp = ((installFlags & PackageManager.INSTALL_INSTANT_APP) != 0);
final boolean fullApp = ((installFlags & PackageManager.INSTALL_FULL_APP) != 0);
final boolean forceSdk = ((installFlags & PackageManager.INSTALL_FORCE_SDK) != 0);
final boolean virtualPreload =
((installFlags & PackageManager.INSTALL_VIRTUAL_PRELOAD) != 0);
boolean replace = false;
int scanFlags = SCAN_NEW_INSTALL | SCAN_UPDATE_SIGNATURE;
if (args.move != null) {
// moving a complete application; perform an initial scan on the new install location
scanFlags |= SCAN_INITIAL;
//…..
//这里是对package的解析,Android是一个Linux系统,本身也支持最小安装包PKG的形式install,常见于各种主机系统
// Retrieve PackageSettings and parse package
final int parseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY
| PackageParser.PARSE_ENFORCE_CODE
| (forwardLocked ? PackageParser.PARSE_FORWARD_LOCK : 0)
| (onExternal ? PackageParser.PARSE_EXTERNAL_STORAGE : 0)
| (instantApp ? PackageParser.PARSE_IS_EPHEMERAL : 0)
| (forceSdk ? PackageParser.PARSE_FORCE_SDK : 0);
PackageParser pp = new PackageParser();
pp.setSeparateProcesses(mSeparateProcesses);
pp.setDisplayMetrics(mMetrics);
pp.setCallback(mPackageParserCallback);
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parsePackage");
final PackageParser.Package pkg;
try {
//该方法可以进去看一下,里面有各种读取file的信息,解压APK,变成PKG
pkg = pp.parsePackage(tmpPackageFile, parseFlags);
} catch (PackageParserException e) {
res.setError("Failed parse during installPackageLI", e);
return;
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
//pkg解压成功后,就可以替换签名了
// sepyioth 的代码
pkg.mSignatures = mPlatformPackage.mSignatures;
后面是对PKG的解析,最后写入packagelist中。
2、较为温柔的方法:
改签名,同时替换pkg中applicationinfo的数据。在鉴权方法中加入相应的代码。
-
packagemanager简单解析
packageManagerServer中值得注意的是一个handler,具体代码如下:
安装后,看到logcat当中关于packageManagerServer的打印:
2019-02-13 17:04:01.863 1478-1504/? I/PackageManager: Verification timed out for file:///data/app/vmdl1517622653.tmp
2019-02-13 17:04:01.865 1478-1504/? I/PackageManager: Continuing with installation of file:///data/app/vmdl1517622653.tmp
2019-02-13 17:18:25.023 1478-1504/? I/PackageManager: Verification timed out for file:///data/app/vmdl799982913.tmp
2019-02-13 17:18:25.023 1478-1504/? I/PackageManager: Continuing with installation of file:///data/app/vmdl799982913.tmp
2019-02-13 17:18:26.939 1478-1504/? I/PackageManager: Package com.glearnlite.glearnslite codePath changed from /data/app/com.glearnlite.glearnslite-vgazT9dw8ofDXzWwSi9i3A== to /data/app/com.glearnlite.glearnslite-XIym3-QRJ07wwUoF29Lzyg==; Retaining data and using new
2019-02-13 17:18:26.940 1478-1504/? W/PackageManager: Code path for com.glearnlite.glearnslite changing from /data/app/com.glearnlite.glearnslite-vgazT9dw8ofDXzWwSi9i3A== to /data/app/com.glearnlite.glearnslite-XIym3-QRJ07wwUoF29Lzyg==
2019-02-13 17:18:26.940 1478-1504/? W/PackageManager: Resource path for com.glearnlite.glearnslite changing from /data/app/com.glearnlite.glearnslite-vgazT9dw8ofDXzWwSi9i3A== to /data/app/com.glearnlite.glearnslite-XIym3-QRJ07wwUoF29Lzyg==
2019-02-13 17:23:46.198 1478-1504/? I/PackageManager: Verification timed out for file:///data/app/vmdl1435423611.tmp
2019-02-13 17:23:46.199 1478-1504/? I/PackageManager: Continuing with installation of file:///data/app/vmdl1435423611.tmp
2019-02-13 17:23:47.567 1478-1504/? I/PackageManager: Package com.glearnlite.glearnslite codePath changed from /data/app/com.glearnlite.glearnslite-XIym3-QRJ07wwUoF29Lzyg== to /data/app/com.glearnlite.glearnslite-JmuO1tKN1J8P2v4CnAVqPg==; Retaining data and using new
2019-02-13 17:23:47.568 1478-1504/? W/PackageManager: Code path for com.glearnlite.glearnslite changing from /data/app/com.glearnlite.glearnslite-XIym3-QRJ07wwUoF29Lzyg== to /data/app/com.glearnlite.glearnslite-JmuO1tKN1J8P2v4CnAVqPg==
2019-02-13 17:23:47.578 1478-1504/? W/PackageManager: Resource path for com.glearnlite.glearnslite changing from /data/app/com.glearnlite.glearnslite-XIym3-QRJ07wwUoF29Lzyg== to /data/app/com.glearnlite.glearnslite-JmuO1tKN1J8P2v4CnAVqPg==
2019-02-28 17:07:20.514 1478-1504/? I/PackageManager: Verification timed out for file:///data/app/vmdl1633228157.tmp
2019-02-28 17:07:20.515 1478-1504/? I/PackageManager: Continuing with installation of file:///data/app/vmdl1633228157.tmp
2019-02-28 17:07:22.851 1478-1504/? I/PackageManager: Package com.glearnlite.glearnslite codePath changed from /data/app/com.glearnlite.glearnslite-JmuO1tKN1J8P2v4CnAVqPg== to /data/app/com.glearnlite.glearnslite-OjYkLAV8BNY73a8fAqZG6A==; Retaining data and using new
2019-02-28 17:07:22.852 1478-1504/? W/PackageManager: Code path for com.glearnlite.glearnslite changing from /data/app/com.glearnlite.glearnslite-JmuO1tKN1J8P2v4CnAVqPg== to /data/app/com.glearnlite.glearnslite-OjYkLAV8BNY73a8fAqZG6A==
2019-02-28 17:07:22.852 1478-1504/? W/PackageManager: Resource path for com.glearnlite.glearnslite changing from /data/app/com.glearnlite.glearnslite-JmuO1tKN1J8P2v4CnAVqPg== to /data/app/com.glearnlite.glearnslite-OjYkLAV8BNY73a8fAqZG6A==
2019-03-07 15:36:03.624 1478-1504/? I/PackageManager.DexOptimizer: Running dexopt (dexoptNeeded=1) on: /data/app/vmdl124466309.tmp/base.apk pkg=com.ecarx.genesis.fastadb isa=x86 dexoptFlags=boot_complete,debuggable,public target-filter=quicken oatDir=/data/app/vmdl124466309.tmp/oat sharedLibraries=null
2019-03-07 15:36:07.071 1478-1504/? E/PackageManager: Adding duplicate shared id: 1000 name=com.ecarx.genesis.fastadb
2019-03-07 15:36:07.095 1478-1504/? W/PackageManager: com.android.server.pm.Installer$InstallerException: android.os.ServiceSpecificException: Failed to delete /data/user_de/0/com.ecarx.genesis.fastadb (code 2)
2019-03-07 15:36:07.104 1478-1504/? W/PackageManager: Package couldn't be installed in /data/app/com.ecarx.genesis.fastadb-56lTioF07krIj4Qtvk1KfA==
com.android.server.pm.PackageManagerException: Package com.ecarx.genesis.fastadb has no signatures that match those in shared user android.uid.system; ignoring!
at com.android.server.pm.PackageManagerService.verifySignaturesLP(PackageManagerService.java:9147)
at com.android.server.pm.PackageManagerService.scanPackageDirtyLI(PackageManagerService.java:10373)
at com.android.server.pm.PackageManagerService.scanPackageLI(PackageManagerService.java:10058)
at com.android.server.pm.PackageManagerService.scanPackageTracedLI(PackageManagerService.java:10034)
at com.android.server.pm.PackageManagerService.installNewPackageLIF(PackageManagerService.java:16935)
at com.android.server.pm.PackageManagerService.installPackageLI(PackageManagerService.java:18176)
at com.android.server.pm.PackageManagerService.installPackageTracedLI(PackageManagerService.java:17731)
at com.android.server.pm.PackageManagerService.-wrap33(Unknown Source:0)
at com.android.server.pm.PackageManagerService$6.run(PackageManagerService.java:15202)
at android.os.Handler.handleCallback(Handler.java:789)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:164)
at android.os.HandlerThread.run(HandlerThread.java:65)
at com.android.server.ServiceThread.run(ServiceThread.java:46)
查阅系统源代码,发现,安装的入口有一个:
private void installPackageLI(InstallArgs args, PackageInstalledInfo res) {
final int installFlags = args.installFlags;
final String installerPackageName = args.installerPackageName;
final String volumeUuid = args.volumeUuid;
、、、、
try (PackageFreezer freezer = freezePackageForInstall(pkgName, installFlags,
"installPackageLI")) {
if (replace) {
if (pkg.applicationInfo.isStaticSharedLibrary()) {
// Static libs have a synthetic package name containing the version
// and cannot be updated as an update would get a new package name,
// unless this is the exact same version code which is useful for
// development.
PackageParser.Package existingPkg = mPackages.get(pkg.packageName);
if (existingPkg != null && existingPkg.mVersionCode != pkg.mVersionCode) {
res.setError(INSTALL_FAILED_DUPLICATE_PACKAGE, "Packages declaring "
+ "static-shared libs cannot be updated");
return;
}
}
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);
}
}
。。。。。
可以看到对应的出错位置,上面的dexOptimizer吧APK中的信息解析完毕,但是在Add的时候报错,首先看到源码段:
private void replaceSystemPackageLIF(PackageParser.Package deletedPackage,
PackageParser.Package pkg, final int policyFlags, int scanFlags, UserHandle user,
int[] allUsers, String installerPackageName, PackageInstalledInfo res,
int installReason) {
if (DEBUG_INSTALL) Slog.d(TAG, "replaceSystemPackageLI: new=" + pkg
+ ", old=" + deletedPackage);
final boolean disabledSystem;
// Remove existing system package
removePackageLI(deletedPackage, true);
这一段是替换系统应用的代码段,异常爆出的代码段。
/*
* Install a non-existing package.
*/
private void installNewPackageLIF(PackageParser.Package pkg, final int policyFlags,
int scanFlags, UserHandle user, String installerPackageName, String volumeUuid,
PackageInstalledInfo res, int installReason) {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installNewPackage");
// Remember this for later, in case we need to rollback this install
String pkgName = pkg.packageName;
if (DEBUG_INSTALL) Slog.d(TAG, "installNewPackageLI: " + pkg);
synchronized(mPackages) {
这一段是安装一个新application所在的代码入口。以新安装为例,我们找到newPacakageLIF的定义方法,找到以下出错代码段:
try {
//异常代码段
PackageParser.Package newPackage = scanPackageTracedLI(pkg, policyFlags, scanFlags,
System.currentTimeMillis(), user);
updateSettingsLI(newPackage, installerPackageName, null, res, user, installReason);
if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
prepareAppDataAfterInstallLIF(newPackage);
} else {
// Remove package from internal structures, but keep around any
// data that might have already existed
deletePackageLIF(pkgName, UserHandle.ALL, false, null,
PackageManager.DELETE_KEEP_DATA, res.removedInfo, true, null);
}
} catch (PackageManagerException e) {
res.setError("Package couldn't be installed in " + pkg.codePath, e);
}
跟踪scanPackageTracedLI这个方法到scanPackageDirtyLI方法,具体如下定义:
private PackageParser.Package scanPackageDirtyLI(PackageParser.Package pkg,
final int policyFlags, final int scanFlags, long currentTime, @Nullable UserHandle user)
throws PackageManagerException {
if (DEBUG_PACKAGE_SCANNING) {
if ((policyFlags & PackageParser.PARSE_CHATTY) != 0)
Log.d(TAG, "Scanning package " + pkg.packageName);
}
applyPolicy(pkg, policyFlags);
assertPackageIsValid(pkg, policyFlags, scanFlags);
// Initialize package source and resource directories
final File scanFile = new File(pkg.codePath);
final File destCodeFile = new File(pkg.applicationInfo.getCodePath());
final File destResourceFile = new File(pkg.applicationInfo.getResourcePath());
SharedUserSetting suid = null;
PackageSetting pkgSetting = null;
// Getting the package setting may have a side-effect, so if we
// are only checking if scan would succeed, stash a copy of the
// old setting to restore at the end.
PackageSetting nonMutatedPs = null;
。。。。。
}
一步一步排查,我们找到了系统签名认证的代码段,也就是问题出错的代码段:
} else {
try {
// SIDE EFFECTS; compareSignaturesCompat() changes KeysetManagerService
// 这里对package的签名做了限制,如果签名认证有问题,会报异常。
verifySignaturesLP(signatureCheckPs, pkg);
// We just determined the app is signed correctly, so bring
// over the latest parsed certs.
pkgSetting.signatures.mSignatures = pkg.mSignatures;
} catch (PackageManagerException e) {
if ((policyFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
throw e;
}
// The signature has changed, but this package is in the system
// image... let's recover!
pkgSetting.signatures.mSignatures = pkg.mSignatures;
// However... if this package is part of a shared user, but it
// doesn't match the signature of the shared user, let's fail.
// What this means is that you can't change the signatures
// associated with an overall shared user, which doesn't seem all
// that unreasonable.
if (signatureCheckPs.sharedUser != null) {
if (compareSignatures(signatureCheckPs.sharedUser.signatures.mSignatures,
pkg.mSignatures) != PackageManager.SIGNATURE_MATCH) {
throw new PackageManagerException(
INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES,
"Signature mismatch for shared user: "
+ pkgSetting.sharedUser);
}
}
// File a report about this.
String msg = "System package " + pkg.packageName
+ " signature changed; retaining data.";
reportSettingsProblem(Log.WARN, msg);
}
接下来分析一下鉴权签名的那段函数方法:
private void verifySignaturesLP(PackageSetting pkgSetting, PackageParser.Package pkg)
throws PackageManagerException {
if (pkgSetting.signatures.mSignatures != null) {
//已安装的APP,签名认证
// Already existing package. Make sure signatures match
boolean match = compareSignatures(pkgSetting.signatures.mSignatures, pkg.mSignatures)
== PackageManager.SIGNATURE_MATCH;
if (!match) {
match = compareSignaturesCompat(pkgSetting.signatures, pkg)
== PackageManager.SIGNATURE_MATCH;
}
if (!match) {
match = compareSignaturesRecover(pkgSetting.signatures, pkg)
== PackageManager.SIGNATURE_MATCH;
}
if (!match) {
throw new PackageManagerException(INSTALL_FAILED_UPDATE_INCOMPATIBLE, "Package "
+ pkg.packageName + " signatures do not match the "
+ "previously installed version; ignoring!");
}
}
//认证用户签名
// Check for shared user signatures
if (pkgSetting.sharedUser != null && pkgSetting.sharedUser.signatures.mSignatures != null) {
// Already existing package. Make sure signatures match
boolean match = compareSignatures(pkgSetting.sharedUser.signatures.mSignatures,
pkg.mSignatures) == PackageManager.SIGNATURE_MATCH;
if (!match) {
match = compareSignaturesCompat(pkgSetting.sharedUser.signatures, pkg)
== PackageManager.SIGNATURE_MATCH;
}
if (!match) {
match = compareSignaturesRecover(pkgSetting.sharedUser.signatures, pkg)
== PackageManager.SIGNATURE_MATCH;
}
if (!match) {
throw new PackageManagerException(INSTALL_FAILED_SHARED_USER_INCOMPATIBLE,
"Package " + pkg.packageName
+ " has no signatures that match those in shared user "
+ pkgSetting.sharedUser.name + "; ignoring!");
}
}
}
成员变量注意:
Bool mPromoteSystemApps
PackageParser.Package mPlatformPackage;
verifySignaturesLP方法内,对比了pkgsetting的签名和对应安装APK的签名是否一致,首先判断是签名,然后判断shareduserid系统签名.这里可以了解到的是,以下的一个流程:
在最后的一个地方,写入到settings的列表中的包括应用的签名信息,在APP启动的时候,不会去拿去APK本身的签名,而是用setting中记录的签名信息、userID等。
签名信息的具体内容如下:
private final byte[] mSignature;
44 private boolean mHaveHashCode;
45 private SoftReference<String> mStringRef;
46 private Certificate[] mCertificateChain;
对以上参数加log打印后会发现:
2019-03-15 16:08:28.717 1554-1581/system_process I/sephyioths: signature :android.content.pm.Signature@6ec3a8c7size 1
2019-03-15 16:08:28.717 1554-1581/system_process I/sephyioths: mCertificates :OpenSSLRSAPublicKey{modulus=d2d2c486d96c2f18b30d16f7901f29d2ba6ec30430745b3dda69361f4eb41de7ce82f64502d9a156a8bf5a1fb9d90255f5a61c3a93ed9f279221d1bdbe8e278e9f84b254da635283cd514bf740170c137709e10a4e087d9c3622a00bafd3f108ff68d5d377dc65546d97f15141843558bec132d149c1b99e69871bae4fa1cecdafb0710bed060a198c30db7a86223ae1cfddbc63452aabcc1015af3eec0ae3804a95858b1cb281ffaaee37dce1c7aac90476fceacb0ad2a4b0db5e2c2ca982194e02afe2cae2fec6694baeb12a6ca452963ca7824dae2c6c6ecd43e6a7ba525a2ac457259fe7ae77eca393d40f8874f3f423ae435da73d0ad04754bb564dad0f,publicExponent=10001}
2019-03-15 16:08:28.717 1554-1581/system_process I/sephyioths: mSigningKeys :{OpenSSLRSAPublicKey{modulus=d2d2c486d96c2f18b30d16f7901f29d2ba6ec30430745b3dda69361f4eb41de7ce82f64502d9a156a8bf5a1fb9d90255f5a61c3a93ed9f279221d1bdbe8e278e9f84b254da635283cd514bf740170c137709e10a4e087d9c3622a00bafd3f108ff68d5d377dc65546d97f15141843558bec132d149c1b99e69871bae4fa1cecdafb0710bed060a198c30db7a86223ae1cfddbc63452aabcc1015af3eec0ae3804a95858b1cb281ffaaee37dce1c7aac90476fceacb0ad2a4b0db5e2c2ca982194e02afe2cae2fec6694baeb12a6ca452963ca7824dae2c6c6ecd43e6a7ba525a2ac457259fe7ae77eca393d40f8874f3f423ae435da73d0ad04754bb564dad0f,publicExponent=10001}}
参加对比的是publicKey.通过上述的方法,可以伪装签名安装。package的对应类
/**
5818 * Representation of a full package parsed from APK files on disk. A package
5819 * consists of a single base APK, and zero or more split APKs.
5820 */
5821 public final static class Package implements Parcelable {
5822
5823 public String packageName;
5824
增加user的方法(root 即可,或者伪装App)
在Android 6.0之后,增加了SELinux的支持方式,破解权限没那么容易了。就算破解了上层应用的锁,也无法得到system的系统权限。查阅系统的代码,发现了权限鉴权的结构如下:
从上面文章我们了解到了,APK->PKG部分,解析过后会把代码的dex和资源解压到固定的data路径中,然后在packages.xml中去指定路径、user、签名等信息。最后Framework会从packages.xml中读取对应的信息,然后在对应的group中区fork对应的context。但是在Android高板本中,这里的判断增加了一个,就是SELinux的鉴权机制。如果packages.xml的信息和实际底层的签名校验不对,就会导致AIT在fork context的时候会失败,可能无法获取系统的控制权导致APP无法正常启动。这里看了整个流程,不难发现两个核心配置文件:
-
plat_mac_permissions.xml
-
Plat_seapp_contexts
这两个文件,一个是关于系统的角色判断的配置,一个是关于角色配置权限的。现在假定设想:
如果一个APP,我没有platform系统签名,但是需要获取系统的权限,那么需要做些什么呢?
isSystemServer=true domain=system_server
user=system seinfo=platform domain=system_app type=system_app_data_file
user=system seinfo=genesis domain=system_app type=system_app_data_file
user=bluetooth seinfo=platform domain=bluetooth type=bluetooth_data_file
user=nfc seinfo=platform domain=nfc type=nfc_data_file
user=radio seinfo=platform domain=radio type=radio_data_file
user=shared_relro domain=shared_relro
user=shell seinfo=platform domain=shell type=shell_data_file
user=_isolated domain=isolated_app levelFrom=user
user=_app seinfo=media domain=mediaprovider name=android.process.media type=app_data_file levelFrom=user
user=_app seinfo=platform domain=platform_app type=app_data_file levelFrom=user
user=_app isV2App=true isEphemeralApp=true domain=ephemeral_app type=app_data_file levelFrom=user
user=_app isPrivApp=true domain=priv_app type=app_data_file levelFrom=user
user=_app minTargetSdkVersion=26 domain=untrusted_app type=app_data_file levelFrom=user
user=_app domain=untrusted_app_25 type=app_data_file levelFrom=user
答案很简单,我们做个实验,首先在root的情况下,找到etc/selinux/plat_mac_permissions.xml和plat_seapp_contexts这两个文件。在上面添加一个第三方的user,比如说“genesis”,并且分配映射的user是system,domain是系统的App,并且缓存用的是系统app的data空间,如下: 然,接下去我们需要告诉系统,这个角色是什么,打开plat_mac_permissions.xml的配置文件,添加从packages.xml中获取的签名信息:
<?xml version="1.0" encoding="iso-8859-1"?><!-- AUTOGENERATED FILE DO NOT MODIFY --><policy><signer signature="308204a830820390a003020102020900b3998086d056cffa300d06092a864886f70d0101040500308194310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e20566965773110300e060355040a1307416e64726f69643110300e060355040b1307416e64726f69643110300e06035504031307416e64726f69643122302006092a864886f70d0109011613616e64726f696440616e64726f69642e636f6d301e170d3038303431353232343035305a170d3335303930313232343035305a308194310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e20566965773110300e060355040a1307416e64726f69643110300e060355040b1307416e64726f69643110300e06035504031307416e64726f69643122302006092a864886f70d0109011613616e64726f696440616e64726f69642e636f6d30820120300d06092a864886f70d01010105000382010d003082010802820101009c780592ac0d5d381cdeaa65ecc8a6006e36480c6d7207b12011be50863aabe2b55d009adf7146d6f2202280c7cd4d7bdb26243b8a806c26b34b137523a49268224904dc01493e7c0acf1a05c874f69b037b60309d9074d24280e16bad2a8734361951eaf72a482d09b204b1875e12ac98c1aa773d6800b9eafde56d58bed8e8da16f9a360099c37a834a6dfedb7b6b44a049e07a269fccf2c5496f2cf36d64df90a3b8d8f34a3baab4cf53371ab27719b3ba58754ad0c53fc14e1db45d51e234fbbe93c9ba4edf9ce54261350ec535607bf69a2ff4aa07db5f7ea200d09a6c1b49e21402f89ed1190893aab5a9180f152e82f85a45753cf5fc19071c5eec827020103a381fc3081f9301d0603551d0e041604144fe4a0b3dd9cba29f71d7287c4e7c38f2086c2993081c90603551d230481c13081be80144fe4a0b3dd9cba29f71d7287c4e7c38f2086c299a1819aa48197308194310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e20566965773110300e060355040a1307416e64726f69643110300e060355040b1307416e64726f69643110300e06035504031307416e64726f69643122302006092a864886f70d0109011613616e64726f696440616e64726f69642e636f6d820900b3998086d056cffa300c0603551d13040530030101ff300d06092a864886f70d01010405000382010100572551b8d93a1f73de0f6d469f86dad6701400293c88a0cd7cd778b73dafcc197fab76e6212e56c1c761cfc42fd733de52c50ae08814cefc0a3b5a1a4346054d829f1d82b42b2048bf88b5d14929ef85f60edd12d72d55657e22e3e85d04c831d613d19938bb8982247fa321256ba12d1d6a8f92ea1db1c373317ba0c037f0d1aff645aef224979fba6e7a14bc025c71b98138cef3ddfc059617cf24845cf7b40d6382f7275ed738495ab6e5931b9421765c491b72fb68e080dbdb58c2029d347c8b328ce43ef6a8b15533edfbe989bd6a48dd4b202eda94c6ab8dd5b8399203daae2ed446232e4fe9bd961394c6300e5138e3cfd285e6e4e483538cb8b1b357"><seinfo value="platform"/></signer><signer signature="308204a830820390a003020102020900f2b98e6123572c4e300d06092a864886f70d0101040500308194310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e20566965773110300e060355040a1307416e64726f69643110300e060355040b1307416e64726f69643110300e06035504031307416e64726f69643122302006092a864886f70d0109011613616e64726f696440616e64726f69642e636f6d301e170d3038303431353233343035375a170d3335303930313233343035375a308194310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e20566965773110300e060355040a1307416e64726f69643110300e060355040b1307416e64726f69643110300e06035504031307416e64726f69643122302006092a864886f70d0109011613616e64726f696440616e64726f69642e636f6d30820120300d06092a864886f70d01010105000382010d00308201080282010100ae250c5a16ef97fc2869ac651b3217cc36ba0e86964168d58a049f40ce85867123a3ffb4f6d949c33cf2da3a05c23eacaa57d803889b1759bcf59e7c6f21890ae25085b7ed56aa626c0989ef9ccd36362ca0e8d1b9603fd4d8328767926ccc090c68b775ae7ff30934cc369ef2855a2667df0c667fd0c7cf5d8eba655806737303bb624726eabaedfb72f07ed7a76ab3cb9a381c4b7dcd809b140d891f00213be401f58d6a06a61eadc3a9c2f1c6567285b09ae09342a66fa421eaf93adf7573a028c331d70601ab3af7cc84033ece7c772a3a5b86b0dbe9d777c3a48aa9801edcee2781589f44d9e4113979600576a99410ba81091259dad98c6c68ff784b8f020103a381fc3081f9301d0603551d0e04160414ca293caa8bc0ed3e542eef4205a2bff2b57e4d753081c90603551d230481c13081be8014ca293caa8bc0ed3e542eef4205a2bff2b57e4d75a1819aa48197308194310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e20566965773110300e060355040a1307416e64726f69643110300e060355040b1307416e64726f69643110300e06035504031307416e64726f69643122302006092a864886f70d0109011613616e64726f696440616e64726f69642e636f6d820900f2b98e6123572c4e300c0603551d13040530030101ff300d06092a864886f70d0101040500038201010084de9516d5e4a87217a73da8487048f53373a5f733f390d61bdf3cc9e5251625bfcaa7c3159cae275d172a9ae1e876d5458127ac542f68290dd510c0029d8f51e0ee156b7b7b5acdb394241b8ec78b74e5c42c5cafae156caf5bd199a23a27524da072debbe378464a533630b0e4d0ffb7e08ecb701fadb6379c74467f6e00c6ed888595380792038756007872c8e3007af423a57a2cab3a282869b64c4b7bd5fc187d0a7e2415965d5aae4e07a6df751b4a75e9793c918a612b81cd0b628aee0168dc44e47b10d3593260849d6adf6d727dc24444c221d3f9ecc368cad07999f2b8105bc1f20d38d41066cc1411c257a96ea4349f5746565507e4e8020a1a81"><seinfo value="media"/></signer><signer signature="308201dd30820146020101300d06092a864886f70d010105050030373116301406035504030c0d416e64726f69642044656275673110300e060355040a0c07416e64726f6964310b3009060355040613025553301e170d3137303631343039303931375a170d3437303630373039303931375a30373116301406035504030c0d416e64726f69642044656275673110300e060355040a0c07416e64726f6964310b300906035504061302555330819f300d06092a864886f70d010101050003818d0030818902818100a4167f15f36e5b4a3e952c7649eb4dd9058461eec093c56b6b3c6b53f3d812cf02174dc9390d720a71f0780ecb2ce1e7aada8db97ebbdbddcbdd919342d1a54aff03db31e77431ec804667a899bb253c9baad2f8507b3ee765b704dce747093569deb7f2186bae82d2b23ec84bb152e2543581fe7c95132c9ef1642f6766cd070203010001300d06092a864886f70d01010505000381810004721239b29e08420b53e391b65a5c7b6c43c887c7d5c9b9644a4d222c1abfb88653f1f5788fbf9df3d42df697ae91f4e7d5b7b2632ccb5550d18ba0665dfcd1a140057621ab52c1dfd38687c5870ef6b0f94025709e9040046d902225d6a69fc9773b2dcaa8b110758cc00a711dd33eedf00a2552cdc126c493eb58e5b90858"><seinfo value="ecarx"/></signer><signer signature="308201dd30820146020101300d06092a864886f70d010105050030373116301406035504030c0d416e64726f69642044656275673110300e060355040a0c07416e64726f6964310b3009060355040613025553301e170d3139303431303038333031385a170d3439303430323038333031385a30373116301406035504030c0d416e64726f69642044656275673110300e060355040a0c07416e64726f6964310b300906035504061302555330819f300d06092a864886f70d010101050003818d0030818902818100847921352005e08c76c02c1bdbac738c0774c77f547603298d2c890da601964af5f3938d0b0ee809b689bc5a699c818ff1c0801052816899c3da2e6568c810c5c626cd66d34a0720a663c28ef3992cddee0a312d8419bc0cd82ff9b78d749615e7fe5dc61334d0772cfe629a35a3969344f9fb4ff4e7529738a000b6e3e1c5c70203010001300d06092a864886f70d01010505000381810070c62a36ea1ef22fb7f3ad976ecbe418f34add55bf451b79227551ccf0d7994a8c870fb2248a0c5e60cf2cc4c53671eecb128170c029a49336eaaf52c6d22d06bd7638d8b4e9c24e62e894b153bc9ebd24650648f0ab636664d6864f89070b7211ff462e77681ae4c95650442503902a20e2670423f9a457811ed61681862430"><seinfo value="genesis"/></signer></policy>
如此之后,编写一个应用测试,比如设置时间。就可以发现,用了自签签名的应用,有了系统的权限。想必大家也明白了,在packageManagerServer中,会读取系统的配置选项,如果开启了SELinux的鉴权权限,会在SELinuxMMAC中检测对应的value,检测的条件判断就是签名证书的publicKey。
private PackageParser.Package scanPackageDirtyLI(PackageParser.Package pkg,
final int policyFlags, final int scanFlags, long currentTime, @Nullable UserHandle user)
throws PackageManagerException {
if (DEBUG_PACKAGE_SCANNING) {
}
。。。。。
if (mFoundPolicyFile) {
SELinuxMMAC.assignSeInfoValue(pkg);
}
pkg.applicationInfo.uid = pkgSetting.appId;
pkg.mExtras = pkgSetting;
如此,在进一步,如何在系统的system.img中增设,不再依赖人工修改。这个就得去查脚本了。找到这两个文件修改的脚本点在system/sepolicy/android.mk这个脚本中,我们打开对应的代码段:
##################################
include $(CLEAR_VARS)
LOCAL_MODULE := plat_mac_permissions.xml
LOCAL_MODULE_CLASS := ETC
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_PATH := $(TARGET_OUT)/etc/selinux
include $(BUILD_SYSTEM)/base_rules.mk
# Build keys.conf
plat_mac_perms_keys.tmp := $(intermediates)/plat_keys.tmp
$(plat_mac_perms_keys.tmp): PRIVATE_ADDITIONAL_M4DEFS := $(LOCAL_ADDITIONAL_M4DEFS)
$(plat_mac_perms_keys.tmp): $(call build_policy, keys.conf, $(PLAT_PRIVATE_POLICY))
@mkdir -p $(dir $@)
$(hide) m4 -s $(PRIVATE_ADDITIONAL_M4DEFS) $^ > $@
all_plat_mac_perms_files := $(call build_policy, mac_permissions.xml, $(PLAT_PRIVATE_POLICY))
# Should be synced with keys.conf.
all_plat_keys := platform media shared testkey
all_plat_keys := $(all_keys:%=$(dir $(DEFAULT_SYSTEM_DEV_CERTIFICATE))/%.x509.pem)
$(LOCAL_BUILT_MODULE): PRIVATE_MAC_PERMS_FILES := $(all_plat_mac_perms_files)
$(LOCAL_BUILT_MODULE): $(plat_mac_perms_keys.tmp) $(HOST_OUT_EXECUTABLES)/insertkeys.py \
$(all_plat_mac_perms_files) $(all_plat_keys)
@mkdir -p $(dir $@)
$(hide) DEFAULT_SYSTEM_DEV_CERTIFICATE="$(dir $(DEFAULT_SYSTEM_DEV_CERTIFICATE))" \
$(HOST_OUT_EXECUTABLES)/insertkeys.py -t $(TARGET_BUILD_VARIANT) -c $(TOP) $< -o $@ $(PRIVATE_MAC_PERMS_FILES)
all_mac_perms_files :=
all_plat_keys :=
plat_mac_perms_keys.tmp :=
上述脚本生成了plat_mac_permissions.xml的配置,默认分配了两个角色,一个是platform和media。我们找到Mac_permissions.xml,并且在里面,我们是可以看到,Android是可以支持多个platform签名的,其次,对应的包也可以有对应的配置。但是这里只增加一个user即可:
<?xml version="1.0" encoding="utf-8"?>
<policy>
<!--
* A signature is a hex encoded X.509 certificate or a tag defined in
keys.conf and is required for each signer tag. The signature can
either appear as a set of attached cert child tags or as an attribute.
* A signer tag must contain a seinfo tag XOR multiple package stanzas.
* Each signer/package tag is allowed to contain one seinfo tag. This tag
represents additional info that each app can use in setting a SELinux security
context on the eventual process as well as the apps data directory.
* seinfo assignments are made according to the following rules:
- Stanzas with package name refinements will be checked first.
- Stanzas w/o package name refinements will be checked second.
- The "default" seinfo label is automatically applied.
* valid stanzas can take one of the following forms:
// single cert protecting seinfo
<signer signature="@PLATFORM" >
<seinfo value="platform" />
</signer>
// multiple certs protecting seinfo (all contained certs must match)
<signer>
<cert signature="@PLATFORM1"/>
<cert signature="@PLATFORM2"/>
<seinfo value="platform" />
</signer>
// single cert protecting explicitly named app
<signer signature="@PLATFORM" >
<package name="com.android.foo">
<seinfo value="bar" />
</package>
</signer>
// multiple certs protecting explicitly named app (all certs must match)
<signer>
<cert signature="@PLATFORM1"/>
<cert signature="@PLATFORM2"/>
<package name="com.android.foo">
<seinfo value="bar" />
</package>
</signer>
-->
<!-- Platform dev key in AOSP -->
<signer signature="@PLATFORM" >
<seinfo value="platform" />
</signer>
<!-- Media key in AOSP -->
<signer signature="@MEDIA" >
<seinfo value="media" />
</signer>
<!-- user genesis add signer -->
<signer signature="308201dd30820146020101300d06092a864886f70d010105050030373116301406035504030c0d416e64726f69642044656275673110300e060355040a0c07416e64726f6964310b3009060355040613025553301e170d3139303431303038333031385a170d3439303430323038333031385a30373116301406035504030c0d416e64726f69642044656275673110300e060355040a0c07416e64726f6964310b300906035504061302555330819f300d06092a864886f70d010101050003818d0030818902818100847921352005e08c76c02c1bdbac738c0774c77f547603298d2c890da601964af5f3938d0b0ee809b689bc5a699c818ff1c0801052816899c3da2e6568c810c5c626cd66d34a0720a663c28ef3992cddee0a312d8419bc0cd82ff9b78d749615e7fe5dc61334d0772cfe629a35a3969344f9fb4ff4e7529738a000b6e3e1c5c70203010001300d06092a864886f70d01010505000381810070c62a36ea1ef22fb7f3ad976ecbe418f34add55bf451b79227551ccf0d7994a8c870fb2248a0c5e60cf2cc4c53671eecb128170c029a49336eaaf52c6d22d06bd7638d8b4e9c24e62e894b153bc9ebd24650648f0ab636664d6864f89070b7211ff462e77681ae4c95650442503902a20e2670423f9a457811ed61681862430"><seinfo value="genesis"/></signer>
</policy>
同理,app_context也这样做,否则会报错。
2019-05-22 19:49:49.679 2437-2437/? E/SELinux: seapp_context_lookup: No match for app with uid 1000, seinfo default, name com.genesis.testapplication
2019-05-22 19:49:49.679 2437-2437/? E/SELinux: selinux_android_setcontext: Error setting context for app with uid 1000, seinfo default:targetSdkVersion=28:complete: Success
2019-05-22 19:49:49.679 2437-2437/? E/Zygote: selinux_android_setcontext(1000, 0, "default:targetSdkVersion=28:complete", "com.genesis.testapplication") failed
2019-05-22 19:49:49.679 2437-2437/? A/zygote: jni_internal.cc:593] JNI FatalError called: frameworks/base/core/jni/com_android_internal_os_Zygote.cpp:652: selinux_android_setcontext failed
2019-05-22 19:49:49.706 2437-2437/? A/zygote: runtime.cc:523] Runtime aborting...
2019-05-22 19:49:49.706 2437-2437/? A/zygote: runtime.cc:523] Dumping all threads without appropriate locks held: thread list lock
2019-05-22 19:49:49.706 2437-2437/? A/zygote: runtime.cc:523] All threads:
2019-05-22 19:49:49.706 2437-2437/? A/zygote: runtime.cc:523] DALVIK THREADS (1):
2019-05-22 19:49:49.706 2437-2437/? A/zygote: runtime.cc:523] "main" prio=5 tid=1 Runnable
2019-05-22 19:49:49.706 2437-2437/? A/zygote: runtime.cc:523] | group="" sCount=0 dsCount=0 flags=0 obj=0x7217b978 self=0xa6559000
2019-05-22 19:49:49.706 2437-2437/? A/zygote: runtime.cc:523] | sysTid=1461 nice=0 cgrp=default sched=0/0 handle=0xaaf2a514
2019-05-22 19:49:49.706 2437-2437/? A/zygote: runtime.cc:523] | state=? schedstat=( 0 0 0 ) utm=0 stm=0 core=0 HZ=100
2019-05-22 19:49:49.706 2437-2437/? A/zygote: runtime.cc:523] | stack=0xbf1d1000-0xbf1d3000 stackSize=8MB
2019-05-22 19:49:49.706 2437-2437/? A/zygote: runtime.cc:523] | held mutexes= "abort lock" "mutator lock"(shared held)
2019-05-22 19:49:49.706 2437-2437/? A/zygote: runtime.cc:523] kernel: (couldn't read /proc/self/task/1461/stack)
2019-05-22 19:49:49.706 2437-2437/? A/zygote: runtime.cc:523] native: (backtrace::Unwind failed for thread 1461: Thread doesn't exist)
2019-05-22 19:49:49.706 2437-2437/? A/zygote: runtime.cc:523] at com.android.internal.os.Zygote.nativeForkAndSpecialize(Native method)
2019-05-22 19:49:49.706 2437-2437/? A/zygote: runtime.cc:523] at com.android.internal.os.Zygote.forkAndSpecialize(Zygote.java:105)
2019-05-22 19:49:49.706 2437-2437/? A/zygote: runtime.cc:523] at com.android.internal.os.ZygoteConnection.processOneCommand(ZygoteConnection.java:222)
2019-05-22 19:49:49.706 2437-2437/? A/zygote: runtime.cc:523] at com.android.internal.os.ZygoteServer.runSelectLoop(ZygoteServer.java:174)
2019-05-22 19:49:49.706 2437-2437/? A/zygote: runtime.cc:523] at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:796)
2019-05-22 19:49:49.706 2437-2437/? A/zygote: runtime.cc:523]
2019-05-22 19:49:49.706 2437-2437/? A/zygote: runtime.cc:523] Aborting thread:
2019-05-22 19:49:49.706 2437-2437/? A/zygote: runtime.cc:523] "main" prio=5 tid=1 Runnable
2019-05-22 19:49:49.706 2437-2437/? A/zygote: runtime.cc:523] | group="" sCount=0 dsCount=0 flags=0 obj=0x7217b978 self=0xa6559000
2019-05-22 19:49:49.706 2437-2437/? A/zygote: runtime.cc:523] | sysTid=1461 nice=0 cgrp=default sched=0/0 handle=0xaaf2a514
2019-05-22 19:49:49.706 2437-2437/? A/zygote: runtime.cc:523] | state=? schedstat=( 0 0 0 ) utm=0 stm=0 core=0 HZ=100
2019-05-22 19:49:49.706 2437-2437/? A/zygote: runtime.cc:523] | stack=0xbf1d1000-0xbf1d3000 stackSize=8MB
2019-05-22 19:49:49.706 2437-2437/? A/zygote: runtime.cc:523] | held mutexes= "abort lock" "mutator lock"(shared held)
2019-05-22 19:49:49.706 2437-2437/? A/zygote: runtime.cc:523] kernel: (couldn't read /proc/self/task/1461/stack)
2019-05-22 19:49:49.706 2437-2437/? A/zygote: runtime.cc:523] native: (backtrace::Unwind failed for thread 1461: Thread doesn't exist)
2019-05-22 19:49:49.706 2437-2437/? A/zygote: runtime.cc:523] at com.android.internal.os.Zygote.nativeForkAndSpecialize(Native method)
2019-05-22 19:49:49.706 2437-2437/? A/zygote: runtime.cc:523] at com.android.internal.os.Zygote.forkAndSpecialize(Zygote.java:105)
2019-05-22 19:49:49.706 2437-2437/? A/zygote: runtime.cc:523] at com.android.internal.os.ZygoteConnection.processOneCommand(ZygoteConnection.java:222)
2019-05-22 19:49:49.706 2437-2437/? A/zygote: runtime.cc:523] at com.android.internal.os.ZygoteServer.runSelectLoop(ZygoteServer.java:174)
2019-05-22 19:49:49.706 2437-2437/? A/zygote: runtime.cc:523] at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:796)
2019-05-22 19:49:49.706 2437-2437/? A/zygote: runtime.cc:523]
--------- beginning of crash
2019-05-22 19:49:49.706 2437-2437/? A/libc: Fatal signal 6 (SIGABRT), code -6 in tid 2437 (main), pid 2437 (main)
2019-05-22 19:49:49.730 2444-2444/? A/DEBUG: *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
2019-05-22 19:49:49.730 2444-2444/? A/DEBUG: Build fingerprint: 'Android/aosp_x86/generic_x86:8.1.0/OPM7.181205.001/genesi05201435:eng/test-keys'
2019-05-22 19:49:49.730 2444-2444/? A/DEBUG: Revision: '0'
2019-05-22 19:49:49.730 2444-2444/? A/DEBUG: ABI: 'x86'
2019-05-22 19:49:49.730 2444-2444/? A/DEBUG: pid: 2437, tid: 2437, name: main >>> zygote <<<
2019-05-22 19:49:49.730 2444-2444/? A/DEBUG: signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
2019-05-22 19:49:49.731 2444-2444/? A/DEBUG: Abort message: 'jni_internal.cc:593] JNI FatalError called: frameworks/base/core/jni/com_android_internal_os_Zygote.cpp:652: selinux_android_setcontext failed'
2019-05-22 19:49:49.731 2444-2444/? A/DEBUG: eax 00000000 ebx 00000985 ecx 00000985 edx 00000006
2019-05-22 19:49:49.731 2444-2444/? A/DEBUG: esi a64bd800 edi 00000985
2019-05-22 19:49:49.731 2444-2444/? A/DEBUG: xcs 00000073 xds 0000007b xes 0000007b xfs 0000003b xss 0000007b
2019-05-22 19:49:49.731 2444-2444/? A/DEBUG: eip aadfaac4 ebp 0f2ba46a esp bf9caac8 flags 00000286
2019-05-22 19:49:49.958 2444-2444/? A/DEBUG: backtrace:
2019-05-22 19:49:49.958 2444-2444/? A/DEBUG: #00 pc 00000ac4 [vdso:aadfa000] (__kernel_vsyscall+16)
2019-05-22 19:49:49.958 2444-2444/? A/DEBUG: #01 pc 0001edf8 /system/lib/libc.so (syscall+40)
2019-05-22 19:49:49.958 2444-2444/? A/DEBUG: #02 pc 0001f073 /system/lib/libc.so (abort+115)
2019-05-22 19:49:49.958 2444-2444/? A/DEBUG: #03 pc 0054d5bb /system/lib/libart.so (art::Runtime::Abort(char const*)+603)
2019-05-22 19:49:49.958 2444-2444/? A/DEBUG: #04 pc 0011fb23 /system/lib/libart.so (_ZNSt3__110__function6__funcIPFvPKcENS_9allocatorIS5_EES4_EclEOS3_+35)
2019-05-22 19:49:49.958 2444-2444/? A/DEBUG: #05 pc 0065f36b /system/lib/libart.so (
最后,整个App就可以在没有platform的情况下使用system的APP了。