iOS 安全之應(yīng)用完整性校驗(yàn)的解決方案(轉(zhuǎn))

為什么要應(yīng)用完整性校驗(yàn)

大家可能聽過(guò)馬甲包類似的概念搔驼。如果惡意攻擊者搞你的App,直接換個(gè)App Icon疙渣,App名字 以及皮膚直接上架了就很尷尬了匙奴。

怎么做

從安全攻防角度講,你了解攻擊的方式妄荔,更容易知道怎么防泼菌,但是也是相對(duì)而言谍肤,只是不斷消磨攻擊者的意志,但愿他們放棄哗伯。

方式一:越獄檢測(cè)

這種方式最簡(jiǎn)單暴力荒揣,我們可以檢測(cè)當(dāng)前設(shè)備是否越獄,在關(guān)鍵性業(yè)務(wù)判斷給出提示強(qiáng)制退出以免造成安全問題焊刹,這里的關(guān)鍵性業(yè)務(wù)可能是需要自己定義范圍系任,比如牽扯到用戶敏感信息等業(yè)務(wù)。下面貼出關(guān)鍵性代碼:

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
}

這種方式其實(shí)是非常間接的方式避免了這個(gè)話題

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

通過(guò)檢測(cè)SignerIdentity判斷是Mach-O文件否被篡改虐块。原理是:SignerIdentity的值在info.plist中是不存在的俩滥,開發(fā)者不會(huì)加上去,蘋果也不會(huì)贺奠,只是當(dāng)ipa包被反編譯后篡改文件再次打包霜旧,需要偽造SignerIdentity。所以只要被攻擊篡改東西如果重新運(yùn)行到手機(jī)上就會(huì)出現(xiàn)這個(gè)東西儡率。

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

方式三:重簽名檢測(cè)

由于要篡改App必然重簽名,至于為什么重簽名儿普,是因?yàn)樘O果做了校驗(yàn)改動(dòng)了任何東西校驗(yàn)失敗是直接閃退的崎逃,其實(shí)原理也是校驗(yàn)文件的hash值。簽名打包過(guò)程會(huì)出現(xiàn)這個(gè)embedded.mobileprovision文件眉孩,這個(gè)文件有teamID的一個(gè)東西我們可以校驗(yàn)是否是我們自己的團(tuán)隊(duì)的teamID來(lái)判斷个绍。或者判斷BundleID 是否被修改勺像。

+ (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];
                    
                    // 對(duì)比簽名ID
                    if (![appIdentifier isEqual:provisionID])
                    {
                        return NO;
                    }
                    else
                    {
                        return YES;
                    }
                }
            }
        }
    return YES;
}

了解簽名的原理有利于防止App被重簽名障贸。

方式四:關(guān)鍵資源hash值檢測(cè)

我們對(duì)Plist文件以及App 的icon資源文件做hash值校驗(yàn)。網(wǎng)上一些對(duì)_CodeSignature的CodeResources以及App二進(jìn)制文件的校驗(yàn)做法有問題吟宦。因?yàn)閄code打包過(guò)程不同環(huán)境造成的hash值不一樣篮洁,通過(guò)下圖可以看出不同環(huán)境打包過(guò)程造成的hash值不一樣的選項(xiàng)。所以我們必須過(guò)濾掉變化的文件殃姓。檢測(cè)Plist文件以及App Icon資源文件這些東西袁波。


關(guān)鍵資源.jpeg
//生成資源文件名及對(duì)應(yīng)的hash的字典
+(NSDictionary *)getBundleFileHash{
    NSMutableDictionary * dicHash = [NSMutableDictionary dictionary];
    NSArray * fileArr = [self allFilesAtPath:[[NSBundle mainBundle]resourcePath]];
    for (NSString * fileName in fileArr) {
        //對(duì)應(yīng)的文件生成hash
        NSString * HashString = [FileHash md5HashOfFileAtPath:[[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:fileName]];
        if (HashString != nil) {
            [dicHash setObject:HashString forKey:fileName];
        }
    }
 //所有資源文件的hash就保存在這數(shù)組里
  return dicHash;
}

有些加密工具為了放進(jìn)加固SDK放在了本地校驗(yàn),但是通過(guò)服務(wù)器校驗(yàn)比較安全點(diǎn)蜗侈。

總結(jié):

通過(guò)下面鏈接了解:

  • Xcode build 對(duì)二進(jìn)制文件以及_CodeSignature的CodeResources造成變化的原理篷牌。

LLVM怎么做Deterministic Build

  • 簽名的原理
    iOS逆向(五)-ipa包重簽名
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市踏幻,隨后出現(xiàn)的幾起案子枷颊,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件夭苗,死亡現(xiàn)場(chǎng)離奇詭異信卡,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)题造,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門傍菇,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人界赔,你說(shuō)我怎么就攤上這事丢习。” “怎么了淮悼?”我有些...
    開封第一講書人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵咐低,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我敛惊,道長(zhǎng)渊鞋,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任瞧挤,我火速辦了婚禮,結(jié)果婚禮上儡湾,老公的妹妹穿的比我還像新娘特恬。我一直安慰自己,他們只是感情好徐钠,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開白布癌刽。 她就那樣靜靜地躺著,像睡著了一般尝丐。 火紅的嫁衣襯著肌膚如雪显拜。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,144評(píng)論 1 285
  • 那天爹袁,我揣著相機(jī)與錄音远荠,去河邊找鬼。 笑死失息,一個(gè)胖子當(dāng)著我的面吹牛譬淳,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播盹兢,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼邻梆,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了绎秒?” 一聲冷哼從身側(cè)響起浦妄,我...
    開封第一講書人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后剂娄,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蠢涝,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年宜咒,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了惠赫。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡故黑,死狀恐怖儿咱,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情场晶,我是刑警寧澤混埠,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布,位于F島的核電站诗轻,受9級(jí)特大地震影響钳宪,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜扳炬,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一吏颖、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧恨樟,春花似錦半醉、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至养晋,卻和暖如春衬吆,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背绳泉。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工逊抡, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人圈纺。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓秦忿,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親蛾娶。 傳聞我的和親對(duì)象是個(gè)殘疾皇子灯谣,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345