iOS - app 进行安全加固
研究了大半年逆向工程了,沒在博客做記錄,最近看到篇,跟自己的想法不謀而合,摘要下:
運行在越獄設(shè)備上的 iOS app,非常容易遭到破解分析,這里我列舉一些可以加大破解難度的方法,希望有所幫助。
?
一些實用手段
?
防止 tweak 依附
?
通常來說,我們要分析一個 app,最開始一般是砸殼,
?
?
$?DYLD_INSERT_LIBRARIES=dumpdecrypted.dylib?/path/to/XXX.app/XXX?
然后將解密之后的二進制文件扔給類似 hopper 這樣的反編譯器處理。直接將沒有砸殼的二進制文件扔個 hopper 反編譯出來的內(nèi)容是無法閱讀的(被蘋果加密了)。所以說砸殼是破解分析 app 的第一步。對于這一步的防范,有兩種方式。
?
1.限制二進制文件頭內(nèi)的段
?
通過在 Xcode 里面工程配置 build setting 選項中將
?
?
-Wl,-sectcreate,__RESTRICT,__restrict,/dev/null?
添加到 "Other Linker Flags"(注意這里我在項目中碰到了一個 問題,在 iPod touch iOS 9.3 的設(shè)備上,使用了 swift 的項目會導致莫名奇妙的 swift 標準庫無法找到,而在 iOS 10 的設(shè)備上沒有這個問題。之前并沒有以為是因為添加了這個的原因,直到網(wǎng)上搜了所有解決方案,比如這個 SO Post 都沒有效果的時候,我才發(fā)現(xiàn)是這個設(shè)置的原因)
?
2.setuid 和 setgid (Apple 不接受調(diào)用這兩個函數(shù)的 app,因為它可以通過查看符號表來判斷您的二進制運行文件是否包含這兩個函數(shù))
?
具體原理可以查看參考資料1,2
?
檢測越獄設(shè)備上是否有針對性 tweak
?
一般來說在越獄手機上,我們會使用 TheOS 創(chuàng)建 tweak 類型的工程。然后針對我們要分析的類,使用提供的 logify.pl 命令生成的 mk 文件來打印該類所有方法的入?yún)⒑统鰠ⅰ_@對分析 app 的運行方式有很大的幫助。當然,我們也可以自己創(chuàng)建某個類的 mk,來 hook 某個函數(shù),讓它以我們想要的方式運行,比如說對于一些做了證書綁定的 app,如果它用的框架是 AFNetWorking 的話,那么我們可以創(chuàng)建一個 mk 文件,hook AFSecurityPolicy 類的下列方法:
?
?
-?(BOOL)evaluateServerTrust:(SecTrustRef)serverTrust?forDomain:(NSString?*)domain?
讓這個方法永遠返回 YES,那么大多數(shù)的應用所做的證書綁定也就失效了。用過 TheOS 的 tweak 模版的話,你會發(fā)現(xiàn)這種方式相當簡單快速。
?
對于這一步的防范,可以在工程的 main 函數(shù)里面加入一層判斷,首先讀取 /Library/MobileSubstrate/DynamicLibraries 下所有的 plist 文件的內(nèi)容,查看是否某個 plist 含有你的 app 的 bundle id,是的話,可以判定有人想利用 tweak 攻擊你的 app,這時候你可以采取比如說將 app 給 crash 掉,或者限制某些功能等方式來應對。
?
具體原理可以查看參考資料4,簡單來說,就是 MobileSubstrate 在 app 加載到內(nèi)存的時候會先去檢查 /Library/MobileSubstrate/DynamicLibraries 下面是否有需要加載的 tweak,有的話就加載,怎么判斷有沒有?就是根據(jù) plist 里面的 bundle ID 判斷的。
?
代碼參考如下
?
?
static?__inline__?__attribute__((always_inline))?int?anti_tweak(){
????uint8_t?lmb[]?=?{'S',?'u',?'b',?'s',?'t',?'r',?'a',?'t',?'e',?'/',?'D',?'y',?'n',?'a',?'m',?'i',?'c',?0,?};
????NSString?*dir?=?[NSString?stringWithFormat:@"/%@/%@%s%@",?@"Library",?@"Mobile",?lmb,?@"Libraries"];
????NSArray?*dirFiles?=?[[NSFileManager?defaultManager]?contentsOfDirectoryAtPath:dir?error:nil];
????NSArray?*plistFiles?=?[dirFiles?filteredArrayUsingPredicate:
???????????????????????????[NSPredicate?predicateWithFormat:
????????????????????????????[NSString?stringWithFormat:@"%@?%@%@?'.%@%@'",@"self",?@"EN",?@"DSWITH",?@"pli",?@"st"]]];
????int?cnt?=?0;
????for?(NSString?*file?in?plistFiles)?{
????????NSString?*filePath?=?[dir?stringByAppendingPathComponent:file];
????????NSString?*fileContent?=?[NSString?stringWithContentsOfFile:filePath?encoding:NSUTF8StringEncoding?error:nil];
????????if?(fileContent?&&?[fileContent?rangeOfString:[[NSBundle?mainBundle]?bundleIdentifier]].location?!=?NSNotFound)?{
????????????cnt?++;
????????}
????}
????//?返回有針對本?app?的?tweak?數(shù)量,為?0?說明沒有
????return?cnt;
}
?
防 http 抓包
?
通常破解一個 app,我們會抓包。這樣的話,我們的 app 所有接口,接口數(shù)據(jù)都會暴露在逆向人員的眼皮底下。這時候,我們可以限制 http 抓包。方式很簡單,就是將 NSURLSessionConfiguration 的 connectionProxyDictionary 設(shè)置成空的字典,因為這個屬性就是用來控制會話的可用代理的。可用參見官方文檔,也就是參考資料5。下面是對于 AFNetWorking 的使用方法:
?
//?繼承?AFHTTPSessionManager,重寫下列方法-?(instancetype)initWithServerHost:(PDLServerHost*)serverHost?{
#ifdef?DEBUG
????//?debug?版本的包仍然能夠正常抓包
????self?=?[super?initWithBaseURL:serverHost.baseURL];
#else
//?由于使用?ephemeralSessionConfiguration?session?發(fā)起的請求不帶?cookie?和使用緩存等
????NSURLSessionConfiguration?*conf?=?[NSURLSessionConfiguration?ephemeralSessionConfiguration];
????conf.connectionProxyDictionary?=?@{};
????self?=?[super?initWithBaseURL:serverHost.baseURL?sessionConfiguration:conf];
#endif
????return?self;
}
?
但是由于 OC 方法很容易被 hook,避免抓包是不可能的,所以,個人認為最好的方式是對請求參數(shù)進行加密(最好是非對稱加密,比如 RSA)
?
混淆(或者加密)硬編碼的明文字符串
?
對于被砸殼的二進制文件,逆向分析人員分析代碼有一條重要線索,也就是被硬編碼的明文字符串。比如說,你的 app 被人抓包了,某些數(shù)據(jù)請求接口也被人發(fā)現(xiàn)了,那么很簡單,逆向人員可以直接拷貝特征比較明顯的字符串到 hopper 中搜索,通過查看該字符串被引用的地方,可以很快的找到相應的邏輯代碼。
?
對于這一步的防范,需要做的就是對硬編碼的明文進行加密或混淆。 有個開源代碼可以用,UAObfuscatedString,但是這個開源混淆代碼寫出來的字符串是相當長的(也就是麻煩),同時不支持加密。最近我寫了一個工具,可以在編譯期間加密所有代碼中的明文字符串,在 app 運行的時候解密字符串。這個工具的特點如下:
?
簡單,開發(fā)人員可以硬編碼明文字符串,所有的加密會在編譯開始時自動處理
可以自定義加密或者混淆方式,(為了不影響 app 運行效率,需要提供一個簡單快速的加密或混淆方式)提高解密難度
?
項目地址?MixPlainText
?
使用 Swift 開發(fā)
?
Swift 是目前比較新的開發(fā) iOS 語言,由于 Swift 目前還不是很穩(wěn)定,越獄開源社區(qū)對這個的支持也不是很即時,比如說 class-dump 工具目前就不支持含有 Swift 的二進制文件。 TheOS 也是最近才開始支持 Swift,但是還沒有加到主分支上(可以參見?Features)。所以目前來看,至少 Swift 可能比純 OC 的工程要安全一點點。當然,等 Swift 日趨穩(wěn)定,以及越獄開源社區(qū)的逐漸支持,這一點優(yōu)勢可能就不明顯了。
?
使用靜態(tài)內(nèi)連 C 函數(shù)
?
由于 OC 語言的動態(tài)性,導致 OC 的代碼是最容易被破解分析的。在安全性上,更推薦使用 C 語言寫成的函數(shù)。但是 C 語言的函數(shù)也是可以被 hook 的,主要有3種方式:
?
1.使用 Facebook 開源的?fishhook
?
2.使用 MobileSubstrate 提供的 hook C 語言函數(shù)的方法
?
?
void?MSHookFunction(void*?function,?void*?replacement,?void**?p_original);?
3.使用 mach_override,關(guān)于?mach_override 和 fishhook?的區(qū)別請看 mach_override 和 fishhook 區(qū)別
?
由于上面這三種方式可以 hook C 函數(shù)。要想不被 hook 解決方法是使用靜態(tài)內(nèi)聯(lián)函數(shù),這樣的話需要被 hook 的函數(shù)沒有統(tǒng)一的入口,逆向人員想要破解只能去理解該函數(shù)的邏輯。
?
使用 block
?
嚴格來說使用 block 并不能很大程度提高安全性,因為逆向人員只要找到使用該 block 的方法,一般來說在其附近就會有 block 內(nèi)代碼的邏輯。具體查找方法和原理可以看參考資料6。
?
但是個人認為使用 block 的安全性是比直接使用 oc 方法是要高的。在我的逆向分析 app 的經(jīng)驗中,對于使用了 block 的方法,目前我還不知道到怎么 hook (有知道的話,可以在 blog 上提個 issue 告訴我,先謝過)同時對于含有嵌套的 block 或者是作為參數(shù)傳遞的 block,處理起來就更加復雜了。所以,如果能將內(nèi)斂 C 函數(shù),嵌套 block , block 類型參數(shù)組合起來的話,安全性應該是會有一定提升。
?
2018年3月2日更新:block 的 hook 操作比較麻煩,但是也是可以的。請參見一下資料:
?
MABlockClosure
Hook Objective-C Block with Libffi
Block 實現(xiàn)原理
?
代碼混淆
?
代碼混淆的方式有幾種:
?
添加無用又不影響邏輯的代碼片段,迷糊逆向人員
對關(guān)鍵的類、方法,命名成與真實意圖無關(guān)的名稱
對于第二種,目前有一些自動化工具,比如念茜提到的一個工具參見參考資料7。
?
個人認為最好的一個加密混淆工具是?ios-class-guard,不過目前這個項目已經(jīng)停止維護了。但是這種方式的混淆我覺得才是最終極的方案。
?
其他方法
?
比如 ptrace 反調(diào)試等(不過據(jù)說已經(jīng)可以很容易被繞過)
?
?
//?see?http://iphonedevwiki.net/index.php/Crack_prevention?for?detailstatic?force_inline?void?disable_gdb()?{
#ifndef?DEBUG
????typedef?int?(*ptrace_ptr_t)(int?_request,?pid_t?_pid,?caddr_t?_addr,?int?_data);
#ifndef?PT_DENY_ATTACH
#define?PT_DENY_ATTACH?31
#endif
????//?this?trick?can?be?worked?around,
????//?see?http://stackoverflow.com/questions/7034321/implementing-the-pt-deny-attach-anti-piracy-code
????void*?handle?=?dlopen(0,?RTLD_GLOBAL?|?RTLD_NOW);
????ptrace_ptr_t?ptrace_ptr?=?dlsym(handle,?[@"".p.t.r.a.c.e?UTF8String]);
????ptrace_ptr(PT_DENY_ATTACH,?0,?0,?0);
????dlclose(handle);
#endif
}
?
注意事項
?
通過了解 OC 的運行時特性和 mach-o 二進制文件的結(jié)構(gòu),借助現(xiàn)有的工具,你會發(fā)現(xiàn) hook 方法 是很簡單就能完成的。雖然上面我提到了一些提高安全性的幾個方案,但是,所有這些方式只是增加了逆向人員的逆向難度,并不能讓 app 變的堅不可摧。不過采取一定的措施肯定比什么措施都不采取來的安全,你說呢?
?
參考資料
?
-
防止 tweak 依附
-
Blocking Code Injection on iOS and OS X
-
Crack prevention
-
Cydia Substrate
-
connectionProxyDictionary
-
iOS符號表恢復&逆向支付寶
-
iOS安全攻防(二十三):Objective-C代碼混淆
-
iOS安全攻防(二十四):敏感邏輯的保護方案(1)
-
?
轉(zhuǎn)載于:https://www.cnblogs.com/baitongtong/p/9369875.html
總結(jié)
以上是生活随笔為你收集整理的iOS - app 进行安全加固的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 支付宝怎么重新注册
- 下一篇: Pl/sql 如何将oracle的表数据