iOS攻防-實戰(2)-反重籤與反注入

前言:上一篇我們講了如何通過重簽名目標ipa文件以及修改Math-O來實現動態注入。知道如何攻擊,是爲了找出攻擊細節來實現防禦。這一篇我們來討論下如何防禦動態注入。

相信瞭解了動態注入過程的同學都會有這樣的體會:動態注入的核心步驟有2點:

  1. 重簽名
  2. 添加自己的framework

反重籤

之前在講重簽名時,我留了一個伏筆:

重簽名時,打包的證書不是原始ipa開發團隊的,證書變了,bundle id自然必須改變。

既然注入必須重籤,重籤bundle id必然要變,那能不能通過比較bundle id來判斷當前運行的app是否被重簽了呢?

答案當然是肯定的!

實際上,每個運行的app都會把bundle id 寫進embedded.mobileprovision文件。並且這個文件存在於main bundle中,可以被當作普通資源文件訪問到。

+ (void)compareBundleID {
    NSString *embeddedPath = [[NSBundle mainBundle] pathForResource:@"embedded" ofType:@"mobileprovision"];
    
    if ([[NSFileManager defaultManager] fileExistsAtPath:embeddedPath])
    {
        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];
                    
                NSArray *identifierComponents = [fullIdentifier componentsSeparatedByString:@"."];
                NSString *appIdentifier = [identifierComponents firstObject];
                    
//                     對比簽名ID
                if ([appIdentifier caseInsensitiveCompare:@"預設的bundle id"] != NSOrderedSame) {
                    NSLog(@"!--- wrong appIdentifier: %@", appIdentifier);
//                  exit(0);
                }
                
                NSLog(@"!--- appIdentifier: %@", appIdentifier);
                break;
            }
        }
    }
}

通過獲取embedded.mobileprovision中現在的bundle id,和預先設定的bundle id進行比較。如果發現不符合,那麼可以確定,現在運行的app已經被重籤,進而採取進一步的攻防策略。

進程白名單

通過比較bundle id的方式來應對動態注入確實簡單粗暴,但還有沒有其它方式?估計很多同學已經想到了:既然動態注入要添加framework,那是否可以獲取當前app加載的framework列表來判斷是否被注入了呢?

+ (void)dyldWhiteList{
        int count = _dyld_image_count();

        for (int i = 0; i < count; i++) {
            //遍歷拿到庫名稱!
            const char * imageName = _dyld_get_image_name(i);
            
            NSString* dyldName = [[NSString alloc]initWithUTF8String:imageName];

            NSLog(@"imageName: %@", dyldName);
        }
}

通過以上代碼獲取系統中運行的庫:

我們發覺打印的庫實在太多了,修改一下上面的代碼,過濾掉系統庫:

if([dyldName containsString:@"/System/Library/Frameworks/"] || [dyldName containsString:@"/System/Library/PrivateFrameworks/"] || [dyldName containsString:@"/usr/lib/system/"])
            {
                continue;
            }

剩下的庫已經不多了,很容易在其中找到我們動態注入的庫

接下來的工作就很簡單了,我們只要記錄項目正常運行時運行的庫名單,隨後定期去和項目中運行的庫名單進行比較,就能識別出是否有被動態注入

後記

關於動態注入,其實還有很多內容可以講,今後再累積一些內容後會和大家分享。關於整個系列,後面想開篇分享一些和越獄有關的知識。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章