開篇先扯幾句題外話,許多朋友都問我怎么不寫防啊,我確實有點猶豫。 hackers 總是想象如果自己是開發(fā)者會怎么寫,然后才能找到入手點。同理,開發(fā)者們也要想象自己是 hackers 會怎么做,才能采取相應(yīng)的防御措施。然后,就是一場遞歸的博弈。
拿越獄檢測這件事來說,起初大家只需判斷有無安裝 Cydia 就好了,hackers 們說好,那我就不安裝 Cydia 也可以動手腳。開發(fā)者們又說,那你一定得用的上 MobileSubstrate ,bash ,ssh 吧,我去檢測手機有沒有安裝這些工具。可是又有什么用呢?你判斷什么我繞過去什么。
當(dāng) class-dump 大肆流行,函數(shù)符號都被暴露,開發(fā)者想盡辦法藏起自己的敏感函數(shù)代碼。hackers 們也知道 class-dump 的死穴在哪里,于是新的檢索辦法油然而生。也就說,當(dāng)一個防御手段成為流行,它就不會再是個讓 hackers 大罵“真特么費勁”的防御手段了。比如之前介紹的一個小技巧:內(nèi)存數(shù)據(jù)擦除 ,hackers 知道開發(fā)者都去擦數(shù)據(jù)了,那我 hook memset 在你擦之前去讀就好了。開發(fā)者說:我直接寫硬盤上然后刪除!hackers 說:難道你沒聽說過文件恢復(fù)?
http://wiki.jikexueyuan.com/project/ios-security-defense/images/data-erase1.png" alt="data-erase1" />
OK,貧的有點多了,本文介紹一下防御相關(guān)的話題—— iOS 的數(shù)據(jù)保護(hù) API 。
文件系統(tǒng)中的文件、keychain 中的項,都是加密存儲的。當(dāng)用戶解鎖設(shè)備后,系統(tǒng)通過 UDID 密鑰和用戶設(shè)定的密碼生成一個用于解密的密碼密鑰,存放在內(nèi)存中,直到設(shè)備再次被鎖,開發(fā)者可以通過 Data Protection API 來設(shè)定文件系統(tǒng)中的文件、keychain 中的項應(yīng)該何時被解密。
/* 為filePath文件設(shè)置保護(hù)等級 */
NSDictionary *attributes = [NSDictionary dictionaryWithObject:NSFileProtectionComplete
forKey:NSFileProtectionKey];
[[NSFileManager defaultManager] setAttributes:attributes
ofItemAtPath:filePath
error:nil];
//文件保護(hù)等級屬性列表
NSFileProtectionNone //文件未受保護(hù),隨時可以訪問 (Default)
NSFileProtectionComplete //文件受到保護(hù),而且只有在設(shè)備未被鎖定時才可訪問
NSFileProtectionCompleteUntilFirstUserAuthentication //文件收到保護(hù),直到設(shè)備啟動且用戶第一次輸入密碼
NSFileProtectionCompleteUnlessOpen //文件受到保護(hù),而且只有在設(shè)備未被鎖定時才可打開,不過即便在設(shè)備被鎖定時,已經(jīng)打開的文件還是可以繼續(xù)使用和寫入
/* 設(shè)置keychain項保護(hù)等級 */
NSDictionary *query = @{(__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
(__bridge id)kSecAttrGeneric:@"MyItem",
(__bridge id)kSecAttrAccount:@"username",
(__bridge id)kSecValueData:@"password",
(__bridge id)kSecAttrService:[NSBundle mainBundle].bundleIdentifier,
(__bridge id)kSecAttrLabel:@"",
(__bridge id)kSecAttrDescription:@"",
(__bridge id)kSecAttrAccessible:(__bridge id)kSecAttrAccessibleWhenUnlocked};
OSStatus result = SecItemAdd((__bridge CFDictionaryRef)(query), NULL);
//keychain項保護(hù)等級列表
kSecAttrAccessibleWhenUnlocked //keychain項受到保護(hù),只有在設(shè)備未被鎖定時才可以訪問
kSecAttrAccessibleAfterFirstUnlock //keychain項受到保護(hù),直到設(shè)備啟動并且用戶第一次輸入密碼
kSecAttrAccessibleAlways //keychain未受保護(hù),任何時候都可以訪問 (Default)
kSecAttrAccessibleWhenUnlockedThisDeviceOnly //keychain項受到保護(hù),只有在設(shè)備未被鎖定時才可以訪問,而且不可以轉(zhuǎn)移到其他設(shè)備
kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly //keychain項受到保護(hù),直到設(shè)備啟動并且用戶第一次輸入密碼,而且不可以轉(zhuǎn)移到其他設(shè)備
kSecAttrAccessibleAlwaysThisDeviceOnly //keychain未受保護(hù),任何時候都可以訪問,但是不能轉(zhuǎn)移到其他設(shè)備
把一段信息 infoStrng 字符串寫進(jìn)文件,然后通過 Data Protection API 設(shè)置保護(hù)。
NSString *documentsPath =[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
NSString *filePath = [documentsPath stringByAppendingPathComponent:@"DataProtect"];
[infoString writeToFile:filePath
atomically:YES
encoding:NSUTF8StringEncoding
error:nil];
NSDictionary *attributes = [NSDictionary dictionaryWithObject:NSFileProtectionComplete
forKey:NSFileProtectionKey];
[[NSFileManager defaultManager] setAttributes:attributes
ofItemAtPath:filePath
error:nil];
設(shè)備鎖屏(帶密碼保護(hù))后,即使是越獄機,在 root 權(quán)限下 cat 讀取那個文件信息也會被拒絕。
http://wiki.jikexueyuan.com/project/ios-security-defense/images/data-erase2.jpeg" alt="data-erase2" />