iOS App的幾種安全防范

雖然公司的項(xiàng)目目前還不算健壯团滥,安全問題對于大部分小公司來說似乎并沒什么必要昏兆,不過要攻擊的話枫虏,我有十足的把握,我們是無法承受沖擊的爬虱。嘿嘿嘿~不過帶著一顆入坑iOS的心思隶债,搜集了一下資料后,還是做了一些嘗試饮潦。

iOS App安全防范總結(jié):

1.防止抓包篡改數(shù)據(jù)
2.防止反編譯
3.阻止動態(tài)調(diào)試
4.防止二次打包

關(guān)鍵檢測:越獄檢測

  • OK燃异,下面是正文開始。

1.防止抓包篡改數(shù)據(jù)

對于抓包继蜡,利用神器charles的操作會在另外的文章單獨(dú)介紹。如果不懂以下為利用charles抓包逛腿。
charles抓包教程

若別人真想抓你程序包稀并,該如何防范呢?我目前只能說单默,let it go ~ let it go~隨他抓碘举,隨他抓。因?yàn)榛旧现灰胱ト〕绦蛟L問的數(shù)據(jù)搁廓,基本上是能抓取到的引颈。對于iOS來說,目前我是做了兩種操作境蜕。

1)判斷是否設(shè)置了代理
對于抓包蝙场,現(xiàn)在的手段基本是設(shè)置代理,所以我們可以通過判斷是否設(shè)置了代理的方式來進(jìn)行下一步的防范粱年。

#在網(wǎng)絡(luò)請求前插入這個方法售滤,再根據(jù)需求做相應(yīng)的防范
+ (BOOL)getDelegateStatus
{
    NSDictionary *proxySettings = CFBridgingRelease((__bridge CFTypeRef _Nullable)((__bridge NSDictionary *)CFNetworkCopySystemProxySettings()));
    NSArray *proxies = CFBridgingRelease((__bridge CFTypeRef _Nullable)((__bridge NSArray *)CFNetworkCopyProxiesForURL((__bridge CFURLRef)[NSURL URLWithString:@"http://www.google.com"], (__bridge CFDictionaryRef)proxySettings)));
    NSDictionary *settings = [proxies objectAtIndex:0];
    NSLog(@"host=%@", [settings objectForKey:(NSString *)kCFProxyHostNameKey]);
    NSLog(@"port=%@", [settings objectForKey:(NSString *)kCFProxyPortNumberKey]);
    NSLog(@"type=%@", [settings objectForKey:(NSString *)kCFProxyTypeKey]);
    if ([[settings objectForKey:(NSString *)kCFProxyTypeKey] isEqualToString:@"kCFProxyTypeNone"])
    {
        //沒有設(shè)置代理
        return NO;
        
    } else {
        //設(shè)置代理了
        return YES;
    }
}

2)RSA
通過與后臺的配合,設(shè)置公鑰與私鑰台诗,對請求數(shù)據(jù)和返回?cái)?shù)據(jù)進(jìn)行加密完箩。這里另外起一篇單獨(dú)介紹。

2.防止反編譯(防止class-dump拉队、hopper反編)

越獄檢測

一般能拿到自己ipa包都需要有一臺越獄的手機(jī)

  • 判斷設(shè)備是否安裝了越獄常用工具:
    一般安裝了越獄工具的設(shè)備都會存在以下文件:
    /Applications/Cydia.app
    /Library/MobileSubstrate/MobileSubstrate.dylib
    /bin/bash
    /usr/sbin/sshd
    /etc/apt

  • 判斷設(shè)備上是否存在cydia應(yīng)用

  • 是否有權(quán)限讀取系統(tǒng)應(yīng)用列表
    沒有越獄的設(shè)備是沒有讀取所有應(yīng)用名稱的權(quán)限

  • 檢測當(dāng)前程序運(yùn)行的環(huán)境變量 DYLD_INSERT_LIBRARIES
    非越獄手機(jī)DYLD_INSERT_LIBRARIES獲取到的環(huán)境變量為NULL弊知。

綜上所述,檢查設(shè)備是否越獄

+ (BOOL)isJailbroken {
    // 檢查是否存在越獄常用文件
    NSArray *jailFilePaths = @[@"/Applications/Cydia.app",
                               @"/Library/MobileSubstrate/MobileSubstrate.dylib",
                               @"/bin/bash",
                               @"/usr/sbin/sshd",
                               @"/etc/apt"];
    for (NSString *filePath in jailFilePaths) {
        if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
            return YES;
        }
    }

    // 檢查是否安裝了越獄工具Cydia
    if([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"cydia://package/com.example.package"]]){
        return YES;
    }

    // 檢查是否有權(quán)限讀取系統(tǒng)應(yīng)用列表
    if ([[NSFileManager defaultManager] fileExistsAtPath:@"/User/Applications/"]){
        NSArray *applist = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:@"/User/Applications/"
                                                                               error:nil];
        NSLog(@"applist = %@",applist);
        return YES;
    }

    //  檢測當(dāng)前程序運(yùn)行的環(huán)境變量
    char *env = getenv("DYLD_INSERT_LIBRARIES");
    if (env != NULL) {
        return YES;
    }

    return NO;
}

代碼混淆

這里生成混淆代碼的方法我們通過shell腳本來實(shí)現(xiàn)粱快,同時我們需要一個文檔來寫入我們需要進(jìn)行混淆的方法名或是變量名秩彤。

  • 打開終端叔扼,cd到文件所在目錄,使用

touch confuse.sh
touch func.list

此時將目錄中的.sh和.list文件拖入項(xiàng)目中

  • 寫入shell腳本

在項(xiàng)目中找到剛剛拖進(jìn)來的.sh文件呐舔,在confuse.sh中寫入腳本

#!/bin/bash

# 這是Shell腳本币励,如果不懂shell,自行修煉:http://www.runoob.com/linux/linux-shell.html

# 以下使用sqlite3進(jìn)行增加數(shù)據(jù)珊拼,如果不了解sqlite3命令食呻,自行修煉:http://www.runoob.com/sqlite/sqlite-tutorial.html

#數(shù)據(jù)表名
TABLENAME="CodeObfuscationOC"

#數(shù)據(jù)庫名
SYMBOL_DB_FILE="CodeObfuscation.db"

#要被替換的方法列表文件
STRING_SYMBOL_FILE="$PROJECT_DIR/ConfusionDemo/func.list"

#被替換后的宏定義在此文件里
HEAD_FILE="$PROJECT_DIR/$PROJECT_NAME/CodeObfuscation.h"

#維護(hù)數(shù)據(jù)庫方便日后做bug排查
createTable()
{
echo "create table $TABLENAME(src text,des text);" | sqlite3 $SYMBOL_DB_FILE
}

insertValue()
{
echo "insert into $TABLENAME values('$1','$2');" | sqlite3 $SYMBOL_DB_FILE
}

query()
{
echo "select * from $TABLENAME where src='$1';" | sqlite3 $SYMBOL_DB_FILE
}

#生成隨機(jī)16位名稱
randomString()
{
openssl rand -base64 64 | tr -cd 'a-zA-Z' | head -c 16
}

#刪除舊數(shù)據(jù)庫文件
rm -f $SYMBOL_DB_FILE

#刪除就宏定義文件
rm -f $HEAD_FILE

#創(chuàng)建數(shù)據(jù)表
createTable

#touch命令創(chuàng)建空文件,根據(jù)指定的路徑
touch $HEAD_FILE
echo '#ifndef CodeObfuscation_h
#define CodeObfuscation_h' >> $HEAD_FILE
echo "http://confuse string at `date`" >> $HEAD_FILE

#使用cat將方法列表文件里的內(nèi)容全部讀取出來澎现,形成數(shù)組仅胞,然后逐行讀取,并進(jìn)行替換
cat "$STRING_SYMBOL_FILE" | while read -ra line;
do
if [[ ! -z "$line" ]]
then
random=`randomString`
echo $line $random

#將生成的隨機(jī)字符串插入到表格中
insertValue $line $random

#將生成的字符串寫入到宏定義文件中剑辫,變量是$HEAD_FILE
echo "#define $line $random" >> $HEAD_FILE
fi
done
echo "#endif" >> $HEAD_FILE
sqlite3 $SYMBOL_DB_FILE .dump
  • 添加run script命令

640.jpg
  • 然后添加$PROJECT_DIR/ConfusionDemo/confuse.sh

  • 給腳本授權(quán)

接下來還是在我們項(xiàng)目的文件夾下干旧,通過終端給我們的腳本賦予最高權(quán)限

chmod 777 confuse.sh
  • 添加預(yù)編譯文件PCH

6401.jpg

然后配置PCH文件


6402.jpg
  • 添加$PROJECT_DIR/ConfusionDemo/PrefixHeader.pch

  • 生成CodeObfuscation.h文件

這時候我們編譯一下代碼,會發(fā)現(xiàn)項(xiàng)目中多出了一個CodeObfuscation.h文件(如果沒有妹蔽,可到項(xiàng)目文件夾中找椎眯,我的就是在文件夾里找到的- -,然后拖進(jìn)項(xiàng)目)胳岂。這個文件就是替換方法名的文件编整,我們在PCH文件中引入他。

  • 在func.list中添加準(zhǔn)備替換的方法名

在項(xiàng)目中點(diǎn)開之前拖進(jìn)來的func.list文件乳丰,然后在里面加入自己想要混淆的方法名

//此處方法名為項(xiàng)目中自己編碼的方法名掌测,不可混淆系統(tǒng)方法名
viewControllerTestMethodA
viewControllerTestMethodB
viewControllerTestMethodC
viewControllerMethodWithParameter
testString
testArray
testMutDic
  • 結(jié)果

編譯之后

#ifndef CodeObfuscation_h
#define CodeObfuscation_h

#define viewControllerTestMethodA CTBxmOXAbJYekhnH
#define viewControllerTestMethodB RnPEjnXygFXLdikO
#define viewControllerTestMethodC IzHlDYOpaAFYFTXa
#define viewControllerMethodWithParameter nWqyalBcfoUSRVpc
#define testString MNPoVYdmCcklAnCO
#define testArray kHMRxPlGXGeqekxL
#define testMutDic hphPSODIvbBFSTHX
#endif

看到 CodeObfuscation有這種變化,恭喜你产园,已經(jīng)代碼混淆成功汞斧。即使通過class-dump反編出來的,也只是一堆亂碼什燕。

  • 需要注意的幾點(diǎn)

    不可以混淆iOS中的系統(tǒng)方法粘勒;

    不可以混淆iOS中init等初始化方法;

    不可以混淆xib的文件秋冰,會導(dǎo)致找不到對應(yīng)文件仲义;

    不可以混淆storyboard中用到的類名;

    混淆有風(fēng)險(xiǎn)剑勾,有可能會被App Store以2.1大禮包拒掉埃撵。

3.阻止動態(tài)調(diào)試

GDB、LLDB是Xcode內(nèi)置的動態(tài)調(diào)試工具虽另。使用GDB暂刘、LLDB可以動態(tài)的調(diào)試你的應(yīng)用程序(通過下斷點(diǎn)、打印等方式捂刺,查看參數(shù)谣拣、返回值募寨、函數(shù)調(diào)用流程等)。

為了阻止hackers使用調(diào)試器 GDB森缠、LLDB來攻擊你的App拔鹰,你可以在main.m文件中插入以下代碼:

#import <dlfcn.h>
#import <sys/types.h>

typedef int (*ptrace_ptr_t)(int _request, pid_t _pid, caddr_t _addr, int _data);
#if !defined(PT_DENY_ATTACH)
#define PT_DENY_ATTACH 31
#endif  // !defined(PT_DENY_ATTACH)

void disable_gdb() {
    void* handle = dlopen(0, RTLD_GLOBAL | RTLD_NOW);
    ptrace_ptr_t ptrace_ptr = dlsym(handle, "ptrace");
    ptrace_ptr(PT_DENY_ATTACH, 0, 0, 0);
    dlclose(handle);
}

int main(int argc, char *argv[]) {
    // Don't interfere with Xcode debugging sessions.
    #if !(DEBUG) 
        disable_gdb();
    #endif

    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil,
            NSStringFromClass([MyAppDelegate class]));
    }
}

4.防止二次打包

iOS 和 OS X 的應(yīng)用和框架包含了二進(jìn)制代碼和所需要的資源文件(如:圖片、不同的語言文件贵涵、XIB/Storyboard文件列肢、profile文件等),在通過開發(fā)者私鑰簽名程序包時宾茂,對于可執(zhí)行文件( Mach-O )瓷马,會將簽名直接寫入到該文件中,而對于其他的資源文件跨晴,會統(tǒng)一寫到 _CodeSignature 文件下的 CodeResources 文件中欧聘,它僅僅是一個 plist 格式文件。

這個列表文件中不光包含了文件和它們的簽名的列表端盆,還包含了一系列規(guī)則怀骤,這些規(guī)則決定了哪些資源文件應(yīng)當(dāng)被設(shè)置簽名。伴隨 OS X 10.10 DP 5 和 10.9.5 版本的發(fā)布焕妙,蘋果改變了代碼簽名的格式晒喷,也改變了有關(guān)資源的規(guī)則。如果你使用10.9.5或者更高版本的 codesign 工具访敌,在 CodeResources 文件中會有4個不同區(qū)域,其中的 rules 和 files 是為老版本準(zhǔn)備的衣盾,而 files2 和 rules2 是為新的第二版的代碼簽名準(zhǔn)備的寺旺。最主要的區(qū)別是在新版本中你無法再將某些資源文件排除在代碼簽名之外,在過去你是可以的势决,只要在被設(shè)置簽名的程序包中添加一個名為 ResourceRules.plist 的文件阻塑,這個文件會規(guī)定哪些資源文件在檢查代碼簽名是否完好時應(yīng)該被忽略。但是在新版本的代碼簽名中果复,這種做法不再有效陈莽。所有的代碼文件和資源文件都必須 設(shè)置簽名,不再可以有例外虽抄。在新版本的代碼簽名規(guī)定中走搁,一個程序包中的可執(zhí)行程序包,例如擴(kuò)展 (extension)迈窟,是一個獨(dú)立的需要設(shè)置簽名的個體私植,在檢查簽名是否完整時應(yīng)當(dāng)被單獨(dú)對待。

有些hacker可能會通過篡改你的程序包(包括資源文件和二進(jìn)制代碼)加入一些廣告或則修改你程序的邏輯车酣,然后重新簽名打包曲稼,由于第三方hacker獲取不到簽名證書的私鑰索绪,因此會替換掉程序包中簽名相關(guān)的文件embedded.mobileprovision魁衙,我們可以直接檢查此文件是否被修改巢墅,來判斷是否被二次打包伤塌,如果程序被篡改脖母,則退出程序碰煌。
檢測embedded.mobileprovision是否被篡改:

// 校驗(yàn)值屯吊,可通過上一次打包獲取
#define PROVISION_HASH @"w2vnN9zRdwo0Z0Q4amDuwM2DKhc="
static NSDictionary * rootDic=nil;

void checkSignatureMsg()
{
    NSString *newPath=[[NSBundle mainBundle]resourcePath];

    if (!rootDic) {

        rootDic = [[NSDictionary alloc] initWithContentsOfFile:[newPath stringByAppendingString:@"/_CodeSignature/CodeResources"]];
    }

    NSDictionary*fileDic = [rootDic objectForKey:@"files2"];

    NSDictionary *infoDic = [fileDic objectForKey:@"embedded.mobileprovision"];
    NSData *tempData = [infoDic objectForKey:@"hash"];
    NSString *hashStr = [tempData base64EncodedStringWithOptions:0];
    if (![PROVISION_HASH isEqualToString:hashStr]) {
        abort();//退出應(yīng)用
    }
}

參考

https://blog.csdn.net/u011656331/article/details/81120420
https://mp.weixin.qq.com/s/zD5EtFpSzKQ0h-ORTC9WqQ

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末租悄,一起剝皮案震驚了整個濱河市眶俩,隨后出現(xiàn)的幾起案子嫡丙,更是在濱河造成了極大的恐慌拴袭,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件曙博,死亡現(xiàn)場離奇詭異拥刻,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)父泳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進(jìn)店門般哼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人惠窄,你說我怎么就攤上這事蒸眠。” “怎么了杆融?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵楞卡,是天一觀的道長。 經(jīng)常有香客問我脾歇,道長蒋腮,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任藕各,我火速辦了婚禮池摧,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘激况。我一直安慰自己作彤,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布乌逐。 她就那樣靜靜地躺著竭讳,像睡著了一般。 火紅的嫁衣襯著肌膚如雪黔帕。 梳的紋絲不亂的頭發(fā)上代咸,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天,我揣著相機(jī)與錄音成黄,去河邊找鬼呐芥。 笑死逻杖,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的思瘟。 我是一名探鬼主播荸百,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼滨攻!你這毒婦竟也來了够话?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤光绕,失蹤者是張志新(化名)和其女友劉穎女嘲,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體诞帐,經(jīng)...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡欣尼,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了停蕉。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片愕鼓。...
    茶點(diǎn)故事閱讀 39,722評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖慧起,靈堂內(nèi)的尸體忽然破棺而出菇晃,到底是詐尸還是另有隱情,我是刑警寧澤蚓挤,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布磺送,位于F島的核電站,受9級特大地震影響灿意,放射性物質(zhì)發(fā)生泄漏册着。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一脾歧、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧演熟,春花似錦鞭执、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至化漆,卻和暖如春估脆,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背座云。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工疙赠, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留付材,地道東北人。 一個月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓圃阳,卻偏偏與公主長得像厌衔,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子捍岳,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,614評論 2 353

推薦閱讀更多精彩內(nèi)容

  • 1.科學(xué)帶來的最大創(chuàng)新是發(fā)明了應(yīng)對謬誤的方式富寿。科學(xué)本事就是如何利用負(fù)面結(jié)果锣夹。 2.強(qiáng)化復(fù)雜系統(tǒng)的唯一方法就是了解它...
    呼嗆閱讀 157評論 0 0
  • 今天银萍,是不普通的一天变勇,因?yàn)槲覀優(yōu)槠诎雮€月的軍訓(xùn)即將在今天結(jié)束。 早晨砖顷,聽著鬧鐘的聲音贰锁,我馬上坐起來,心里亂亂的滤蝠,是...
    顏俊唳Aria閱讀 492評論 4 5