iOS 安全之應用完整性校驗的解決方案

爲何要應用完整性校驗

你們可能聽過馬甲包相似的概念。若是惡意攻擊者搞你的App,直接換個App Icon,App名字 以及皮膚直接上架了就很尷尬了。數組

怎麼作

從安全攻防角度講,你瞭解攻擊的方式,更容易知道怎麼防,可是也是相對而言,只是不斷消磨攻擊者的意志,希望他們放棄。安全

方式一:越獄檢測

這種方式最簡單暴力,咱們能夠檢測當前設備是否越獄,在關鍵性業務判斷給出提示強制退出以避免形成安全問題,這裏的關鍵性業務多是須要本身定義範圍,好比牽扯到用戶敏感信息等業務。下面貼出關鍵性代碼:bash

const char* jailbreak_tool_pathes[] = {
       "/Applications/Cydia.app",
       "/Library/MobileSubstrate/MobileSubstrate.dylib",
       "/bin/bash",
       "/usr/sbin/sshd",
       "/etc/apt"
       };
       #define ARRAY_SIZE(a) sizeof(a)/sizeof(a[0])
+ (BOOL)isJailBroken
{
    if ([self isSimulator] == YES)
    {
        return NO;
    }
    
    for (int i=0; i<ARRAY_SIZE(jailbreak_tool_pathes); i++) {
           if ([[NSFileManager defaultManager] fileExistsAtPath:[NSString stringWithUTF8String:jailbreak_tool_pathes[i]]]) {
               NSLog(@"The device is jail broken!");
               return YES;
            }
       }
      NSLog(@"The device is NOT jail broken!");
      return NO;
}


+ (BOOL)isSimulator {
#if TARGET_OS_SIMULATOR
    return YES;
#else
    return NO;
#endif
}
複製代碼

這種方式實際上是很是間接的方式避免了這個話題服務器

方式二:判斷Mach-O文件否被篡改

經過檢測SignerIdentity判斷是Mach-O文件否被篡改。原理是:SignerIdentity的值在info.plist中是不存在的,開發者不會加上去,蘋果也不會,只是當ipa包被反編譯後篡改文件再次打包,須要僞造SignerIdentity。因此只要被攻擊篡改東西若是從新運行到手機上就會出現這個東西。app

+ (BOOL)checkMach_O
{
    
    NSBundle *bundle = [NSBundle mainBundle];
    NSDictionary *info = [bundle infoDictionary];
    if ([info objectForKey: @"SignerIdentity"] != nil){
        //存在這個key,則說明被二次打包了
        return YES;
    }
    
    return NO;
}


複製代碼

方式三:重簽名檢測

因爲要篡改App必然重簽名,至於爲何重簽名,是由於蘋果作了校驗改動了任何東西校驗失敗是直接閃退的,其實原理也是校驗文件的hash值。簽名打包過程會出現這個embedded.mobileprovision文件,這個文件有teamID的一個東西咱們能夠校驗是不是咱們本身的團隊的teamID來判斷。或者判斷BundleID 是否被修改。ssh

+ (BOOL)checkCodeSignWithProvisionID:(NSString *)provisionID
{
     // 描述文件路徑
        NSString *embeddedPath = [[NSBundle mainBundle] pathForResource:@"embedded" ofType:@"mobileprovision"];
        if ([[NSFileManager defaultManager] fileExistsAtPath:embeddedPath]) {
            
            // 讀取application-identifier
            NSString *embeddedProvisioning = [NSString stringWithContentsOfFile:embeddedPath encoding:NSASCIIStringEncoding error:nil];
            NSArray *embeddedProvisioningLines = [embeddedProvisioning componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];
            
            for (int i = 0; i < [embeddedProvisioningLines count]; i++) {
                if ([[embeddedProvisioningLines objectAtIndex:i] rangeOfString:@"application-identifier"].location != NSNotFound) {
                    
                    NSInteger fromPosition = [[embeddedProvisioningLines objectAtIndex:i+1] rangeOfString:@"<string>"].location+8;
                    
                    NSInteger toPosition = [[embeddedProvisioningLines objectAtIndex:i+1] rangeOfString:@"</string>"].location;
                    
                    NSRange range;
                    range.location = fromPosition;
                    range.length = toPosition - fromPosition;
                    
                    NSString *fullIdentifier = [[embeddedProvisioningLines objectAtIndex:i+1] substringWithRange:range];
                    
    //                NSLog(@"%@", fullIdentifier);
                    
                    NSArray *identifierComponents = [fullIdentifier componentsSeparatedByString:@"."];
                    NSString *appIdentifier = [identifierComponents firstObject];
                    
                    // 對比簽名ID
                    if (![appIdentifier isEqual:provisionID])
                    {
                        return NO;
                    }
                    else
                    {
                        return YES;
                    }
                }
            }
        }
        return YES;

}
複製代碼

瞭解簽名的原理有利於防止App被重簽名。ide

方式四:關鍵資源hash值檢測

咱們對Plist文件以及App 的icon資源文件作hash值校驗。網上一些對_CodeSignature的CodeResources以及App二進制文件的校驗作法有問題。由於Xcode打包過程不一樣環境形成的hash值不同,經過下圖能夠看出不一樣環境打包過程形成的hash值不同的選項。因此咱們必須過濾掉變化的文件。檢測Plist文件以及App Icon資源文件這些東西。工具

關鍵性代碼:ui

//生成資源文件名及對應的hash的字典
+(NSDictionary *)getBundleFileHash{
    NSMutableDictionary * dicHash = [NSMutableDictionary dictionary];
    NSArray * fileArr = [self allFilesAtPath:[[NSBundle mainBundle]resourcePath]];
    for (NSString * fileName in fileArr) {
        //對應的文件生成hash
        NSString * HashString = [FileHash md5HashOfFileAtPath:[[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:fileName]];
        if (HashString != nil) {
            [dicHash setObject:HashString forKey:fileName];
        }
    }
 //全部資源文件的hash就保存在這數組裏
  return dicHash;
}
複製代碼

有些加密工具爲了放進加固SDK放在了本地校驗,可是經過服務器校驗比較安全點。加密

總結:

經過下面連接瞭解:

  • Xcode build 對二進制文件以及_CodeSignature的CodeResources形成變化的原理。

LLVM怎麼作Deterministic Build

  • 簽名的原理

iOS逆向(五)-ipa包重簽名

相關文章
相關標籤/搜索