iOS-如何判断安装的APP被第三方企业证书重新签名

最近接了个需求,需要判断手机上安装的包是从第三方越狱渠道下载的,也就是你的APP被第三方从App Store拔下来后重新用他们的企业证书进行签名,放到他们的越狱商城上供用户下载。这里不讨论具体怎么重新签名,讨论如何判断你的APP被重新签名了。

具体方法如下:

1.用Charles抓了海马助手的包,找到了下载ipa的链接,然后把对应的ipa下载下来。

53DB0A6D-3E50-4332-8027-14F20AA3C0DD.png

2.ipa其实就是个压缩包,把文件的扩展名修改成.zip就可以解压缩了,解压缩完获取到对应的APP,右键显示包内容,找到这个XXX.mobileprovision文件,xxx.mobileprovision是ios开发中的设备描述文件,里面有证书信息、调试设备的UUID信息、bundle identifier等。如下图所示:

91618C5B-09A2-4C66-AF51-D4F7BF3A92BC.png

注意:此文件是二进制格式不能直接打开,那么如何查看其中信息呢,baidu有很多方法,我用的是下面这种:

使用mac自带security命令行

用mac自带的命令security,cd到mobileprovision所在的文件夹,执行

security cms -D -i XXX.mobileprovision

会得到下面的dict结构的详细信息:下面是海马给我的APP重新签名后的信息:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>AppIDName</key>
    <string>resong</string>
    <key>ApplicationIdentifierPrefix</key>
    <array>
    <string>RZJM442J8M</string>
    </array>
    <key>CreationDate</key>
    <date>2017-01-23T05:40:10Z</date>
    <key>Platform</key>
    <array>
        <string>iOS</string>
    </array>
    <key>DeveloperCertificates</key>
    <array>
        <data>MIIFiDCCBHCgAwIBAgIIZYIIqChm21AwDQYJKoZIhvcNAQEFBQAwgZYxCzAJBgNVBAYTAlVTMRMwEQYDVQQKDApBcHBsZSBJbmMuMSwwKgYDVQQLDCNBcHBsZSBXb3JsZHdpZGUgRGV2ZWxvcGVyIFJlbGF0aW9uczFEMEIGA1UEAww7QXBwbGUgV29ybGR3aWRlIERldmVsb3BlciBSZWxhdGlvbnMgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTcwMTIzMDUyNzQ3WhcNMjAwMTIzMDUyNzQ3WjCBiTEaMBgGCgmSJomT8ixkAQEMClJaSk00NDJKOE0xLjAsBgNVBAMMJWlQaG9uZSBEaXN0cmlidXRpb246IEJyIEhvbGRpbmdzLCBMbGMxEzARBgNVBAsMClJaSk00NDJKOE0xGTAXBgNVBAoMEEJyIEhvbGRpbmdzLCBMbGMxCzAJBgNVBAYTAlVTMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArp8MZlVUwiqtvaWHtes22BCUDHM5MOciVG6CdkWyYQJVf9fVEN6xHDkHRLP8vpnD260dIBxPcQLHWmUClphy24EKZocPBwO2gpPXF2U4IPshYBHTAweUHuwE+bolzOqa9Gm9nnxdH/GDXiF9qNczcvqhVqDM9mTIdjA3RUd3AKOs4j2R2VfCHlCg0rifL7WJxWihbY+vuVA9Tosrp09K7LGLpC3M2z5a00bPX8OCmdrQhSIMIAoOlSuzR6W7RACOSGm/+BbwdbcnqfSyKsBwHIUadsTDJ/LX+8KBjmn77F3J587YlDAuzZeQHj6uS/uYnV60apS+2070birC43e8lQIDAQABo4IB4zCCAd8wPwYIKwYBBQUHAQEEMzAxMC8GCCsGAQUFBzABhiNodHRwOi8vb2NzcC5hcHBsZS5jb20vb2NzcDAyLXd3ZHIwMTAdBgNVHQ4EFgQUE1+f/fuSeNqlWKSpmPFjkFempl0wDAYDVR0TAQH/BAIwADAfBgNVHSMEGDAWgBSIJxcJqbYYYIvs67r2R1nFUlSjtzCCAQ8GA1UdIASCAQYwggECMIH/BgkqhkiG92NkBQEwgfEwgcMGCCsGAQUFBwICMIG2DIGzUmVsaWFuY2Ugb24gdGhpcyBjZXJ0aWZpY2F0ZSBieSBhbnkgcGFydHkgYXNzdW1lcyBhY2NlcHRhbmNlIG9mIHRoZSB0aGVuIGFwcGxpY2FibGUgc3RhbmRhcmQgdGVybXMgYW5kIGNvbmRpdGlvbnMgb2YgdXNlLCBjZXJ0aWZpY2F0ZSBwb2xpY3kgYW5kIGNlcnRpZmljYXRpb24gcHJhY3RpY2Ugc3RhdGVtZW50cy4wKQYIKwYBBQUHAgEWHWh0dHA6Ly93d3cuYXBwbGUuY29tL2FwcGxlY2EvMA4GA1UdDwEB/wQEAwIHgDAWBgNVHSUBAf8EDDAKBggrBgEFBQcDAzATBgoqhkiG92NkBgEEAQH/BAIFADANBgkqhkiG9w0BAQUFAAOCAQEAQ7mnLeR5/NWNlofsFw0+2Tg8eTYNFE4E3sKaf2yq7v4GYSstgGwitTOszQ/rCFoqPyTQuz5m4SwdDaMNyVn48Fq/N6c6+rwxJg0fAcZP13T0Is9F1QuN1yBQ6NJRc6AeTcAy6BXty/nkXU2AbNuQGVk46Yg00zMpExev24qm8Dyb/9HsTmozTMS2MkjvLh2CqJLStaUOeDqpGIjuG0eBBf30GNKhf05FP0lPJ88IpJEVTlBGUMtiOjF/LurUUc66oCvV+wW0uwsGxbwTREFse+i+hl4vIRDqKH/v+7xkvoAz+L29VzOxTOTTNAorvCXdkkQ8fOH0TEQ3K7n/yfNoDQ==</data>
    </array>
    <key>Entitlements</key>
    <dict>
        <key>keychain-access-groups</key>
        <array>
            <string>RZJM442J8M.*</string>       
        </array>
        <key>inter-app-audio</key>
        <true/>
        <key>get-task-allow</key>
        <false/>
        <key>application-identifier</key>
        <string>RZJM442J8M.com.brhod.resong</string>
        <key>com.apple.developer.ubiquity-kvstore-identifier</key>
        <string>RZJM442J8M.*</string>
        <key>com.apple.developer.ubiquity-container-identifiers</key>
        <array>
            <string>RZJM442J8M.*</string>
        </array>
        <key>com.apple.developer.team-identifier</key>
        <string>RZJM442J8M</string>
        <key>aps-environment</key>
        <string>production</string>
        <key>com.apple.developer.siri</key>
        <true/>
    </dict>
    <key>ExpirationDate</key>
    <date>2018-01-23T05:40:10Z</date>
    <key>Name</key>
    <string>resong_dis</string>
    <key>ProvisionsAllDevices</key>
    <true/>
    <key>TeamIdentifier</key>
    <array>
        <string>RZJM442J8M</string>
    </array>
    <key>TeamName</key>
    <string>Br Holdings, Llc</string>
    <key>TimeToLive</key>
    <integer>365</integer>
    <key>UUID</key>
    <string>82a5bed2-3b37-4f3d-807d-83e45fb05e21</string>
    <key>Version</key>
    <integer>1</integer>
</dict>
</plist>

里面有一个重要的key:application-identifier,这里就可以判断签名证书是不是你们自己的的啦。

D52EB29F-72AA-42AD-ABF3-6249B42C4026.png

只要我们读取到里面plist的部分,再把,application-identifier对应的value和自己APP本身的APPID作对比,就可以分辨出是否被第三方企业证书重新签名过了。

3.使用OC代码获取证书签名的代码:

+ (BOOL)isFromJailbrokenChannel
{
    NSString *bundleId = [[[NSBundle mainBundle] infoDictionary] objectForKey:(__bridge NSString *)kCFBundleIdentifierKey];
    if (![bundleId isEqualToString:@"your bundle id"]) {
        return YES;
    }
    //取出embedded.mobileprovision这个描述文件的内容进行判断
    NSString *mobileProvisionPath = [[NSBundle mainBundle] pathForResource:@"embedded" ofType:@"mobileprovision"];
    NSData *rawData = [NSData dataWithContentsOfFile:mobileProvisionPath];
    NSString *rawDataString = [[NSString alloc] initWithData:rawData encoding:NSASCIIStringEncoding];
    NSRange plistStartRange = [rawDataString rangeOfString:@"<plist"];
    NSRange plistEndRange = [rawDataString rangeOfString:@"</plist>"];
    if (plistStartRange.location != NSNotFound && plistEndRange.location != NSNotFound) {
        NSString *tempPlistString = [rawDataString substringWithRange:NSMakeRange(plistStartRange.location, NSMaxRange(plistEndRange))];
        NSData *tempPlistData = [tempPlistString dataUsingEncoding:NSUTF8StringEncoding];
        NSDictionary *plistDic =  [NSPropertyListSerialization propertyListWithData:tempPlistData options:NSPropertyListImmutable format:nil error:nil];
        
        NSArray *applicationIdentifierPrefix = [plistDic getArrayValueForKey:@"ApplicationIdentifierPrefix" defaultValue:nil];
        NSDictionary *entitlementsDic = [plistDic getDictionaryValueForKey:@"Entitlements" defaultValue:nil];
        NSString *mobileBundleID = [entitlementsDic getStringValueForKey:@"application-identifier" defaultValue:nil];
        if (applicationIdentifierPrefix.count > 0 && mobileBundleID != nil) {
            if (![mobileBundleID isEqualToString:[NSString stringWithFormat:@"%@.%@",[applicationIdentifierPrefix firstObject],@"your applicationId"]]) {
                return YES;
            }
        }
    }

    return NO;
    
}

推荐阅读更多精彩内容