前言
一個項(xiàng)目中的明文字符串不計(jì)其數(shù)吻商,但是有一些是程序的敏感信息的話如果不進(jìn)行加密和混淆處理,反編譯者就會很容易找到我們的敏感信息糟红。拿到這些敏感信息之后就很容易分析我們的程序艾帐,業(yè)務(wù)邏輯進(jìn)而做一些可能對我們不是很友好的事情,所以一些敏感明文字符串還是有必要做一下加密盆偿,讓敏感信息更加安全柒爸。特別是對于我們金融類的APP開發(fā)。
反編譯工具
這里介紹幾個常用的:
(1)class-dump
主要用來反編譯一個庫文件或者app的方法名事扭、屬性等聲明(即.h文件捎稚,強(qiáng)大的是反編譯出來的.h不僅僅包含頭文件中的聲明,.m中的function方法名稱也同樣能夠反編譯出來)求橄。
(2)IDA
主要用來反編譯庫文件的實(shí)現(xiàn)(當(dāng)然方法聲明同樣能夠反編譯出來今野,用class-dump主要是更加形象,有針對性)罐农,這個反編譯工具非常強(qiáng)大能夠?qū)⒑瘮?shù)的實(shí)現(xiàn)及邏輯關(guān)系条霜、流程統(tǒng)統(tǒng)顯示出來,弊端就是反編譯出來的內(nèi)容為匯編語言涵亏,需要一定匯編基礎(chǔ)的才能看懂蛔外。看起來比較頭疼溯乒。
(3)Hopper Disassembler
與IDA功能相似,主要功能都是反編譯查看方法的實(shí)現(xiàn)豹爹,這個軟件的功能相對于IDA來說裆悄,可讀性要強(qiáng)很多,反編譯出來的內(nèi)容類似于匯編與OC的運(yùn)行時的結(jié)合體臂聋,相對比較容易看出方法的具體實(shí)現(xiàn)光稼。本次也是采用此工具進(jìn)行驗(yàn)證。
代碼混淆
在探索明文字符串加密之前先來了解一下代碼混淆:
- 方法名混淆(對關(guān)鍵的類孩等、方法艾君,命名成與真實(shí)意圖無關(guān)的名稱)
- 創(chuàng)建shell腳本
- 聲明要替換的方法名列表
- 生成對應(yīng)的轉(zhuǎn)義之后的無序字符串
- 邏輯混淆(添加無用又不影響邏輯的代碼片段,迷糊逆向人員)
- 類名方法名混淆(例如:ios-class-guard)
Warning!!! 前方高能
Guideline 2.3.1 - Performance
We discovered that your app contains hidden features. Specifically, It would be appropriate to remove all code obfuscation and selector mangling or to explain in detail the purpose of its inclusion before resubmitting for review.
據(jù)說從17年開始蘋果拒審代碼混淆的APP肄方。所以項(xiàng)目整體代碼的混淆目前感覺意義不大冰垄。
第三方加固
第三方的服務(wù)(例如:網(wǎng)易云易盾)這類的加固成效如何不太清楚,這里拿出來給個參考权她,畢竟沒用過虹茶,可能是否選用要看公司的決策了逝薪。
第三方明確說明了加固中使用了代碼混淆,不知道是使用什么黑科技混淆的蝴罪,肯定不是跑腳本的方式董济,好奇寶寶可以研究一下~~
字符串加密調(diào)研和嘗試
對于被砸殼的二進(jìn)制文件,逆向分析人員分析代碼有一條重要線索要门,也就是被硬編碼的明文字符串虏肾。比如說,你的 app 被人抓包了欢搜,某些數(shù)據(jù)請求接口也被人發(fā)現(xiàn)了封豪,那么很簡單,逆向人員可以直接拷貝特征比較明顯的字符串到 hopper 中搜索狂巢,通過查看該字符串被引用的地方撑毛,可以很快的找到相應(yīng)的邏輯代碼。對于這一步的防范唧领,需要做的就是對硬編碼的明文進(jìn)行加密藻雌。
使用靜態(tài)內(nèi)連 C 函數(shù)
- inline函數(shù)避免了普通函數(shù)的,在匯編時必須調(diào)用call的缺點(diǎn)。
- 取消了函數(shù)的參數(shù)壓棧斩个,減少了調(diào)用的開銷胯杭,提高效率。所以執(zhí)行速度確比一般函數(shù)的執(zhí)行速度要快受啥。
定義:
UIKIT_STATIC_INLINE NSString *testScheme() {
return @"testtesttesttest";
}
static inline NSString * testName() {
return @"test";
}
使用:
@"appId": testRrd(),
@"scheme" : testScheme()
結(jié)果:
很明顯明文字符串還是很容易暴露出來~~
方案PASS做个!
Swift 安全性更高
- 越獄開源社區(qū)對反編譯 Swift 的支持也不是很即時。
- 一些反編譯工具并不支持反編譯含有 Swift 的二進(jìn)制文件(例如:class-dump)滚局。
- 能夠反編譯 Swift 的工具也表現(xiàn)出 Swift 更安全的一面居暖。
我對同樣邏輯的同樣代碼(只是語法不同)的 OC 和 Swift 方法(方法中包含明文字符串)進(jìn)行了測試:
上面對比明顯可以看出 OC 經(jīng)過反編譯之后暴露出來的信息更能多,并且明文字符串顯而易見藤肢。
但是如果 Swift 方法添加了對 OC 的支持(@objc)也會使安全性降低太闺。
現(xiàn)階段 Swift 相對 OC 來說更安全一些,等 Swift 日趨穩(wěn)定嘁圈,以及越獄開源社區(qū)的逐漸支持省骂,可能這一點(diǎn)優(yōu)勢可能就不明顯了。
UAObfuscatedString
有個開源代碼可以用最住,UAObfuscatedString钞澳,這個開源混淆代碼寫出來的字符串是以點(diǎn)語法的方式連接起來。
語法:
@"url" : NSMutableString.string.w.w.w.dot.b.a.i.d.u.dot.c.o.m
測試混淆結(jié)果:
UAObfuscatedString 是通過 Category 和 Extension 來實(shí)現(xiàn)這種點(diǎn)語法拼接字符串涨缚,存在比較明顯的規(guī)律轧粟,外加它是開源的可能安全性不是很高,如單從加密的角度去使用這個開源庫感覺意義不大。
使用異或加密
原理:通過位運(yùn)算的 ^ 異或運(yùn)算符把字符串與一個指定的值進(jìn)行運(yùn)算逃延,從而改變字符串中每個字符的值览妖,這樣就可以得到一個加密后的字符串;當(dāng)把加密后的字符串作為程序輸入內(nèi)容后揽祥,異或運(yùn)算會把加密后的字符串還原為原有字符串的值讽膏。
使用:
@"key" : testMethod()
// Key 可以是0~255的Int
#define XORKEY 0xC9
static void XOREncrypt(unsigned char *str, unsigned char key) {
unsigned char *p = str;
while (((*p) ^= key) != '\0') {
p++;
}
}
static id testMethod(void) {
unsigned char str[] = {(XORKEY ^ 'e'), (XORKEY ^ 'n'), (XORKEY ^ 'c'), (XORKEY ^ 'r'),
(XORKEY ^ 'y'), (XORKEY ^ 'p'), (XORKEY ^ 't'), (XORKEY ^ '\0')};
XOREncrypt(str, XORKEY);
static unsigned char result[7];
memcpy(result, str, 7);
return [[NSString alloc] initWithFormat:@"%s", result];
}
這里將字符用函數(shù)指針成員的形式存儲,反編譯后拄丰,只留下了地址府树,去掉了明文字符串直接暴露的風(fēng)險(xiǎn)。