推薦閱讀:iOS開發(fā)——BAT面試題合集(持續(xù)更新中)
在應(yīng)用開發(fā)過(guò)程中最盅,我們不僅僅需要完成正常的業(yè)務(wù)邏輯葵蒂,考慮應(yīng)用性能担敌、代碼健壯相關(guān)的問(wèn)題,我們有時(shí)還需要考慮到應(yīng)用安全的問(wèn)題辞槐。
那么應(yīng)用安全的問(wèn)題涉及到很多方面掷漱。比如防止靜態(tài)分析的,代碼混淆榄檬、邏輯混淆卜范;防止重簽名的,應(yīng)用ID檢測(cè)丙号、甚至是代碼的HASH檢測(cè)等等先朦。那么這篇文章我想聊聊關(guān)于代碼的注入檢測(cè),因?yàn)榘l(fā)現(xiàn)隨著iOS系統(tǒng)的更新,我們防護(hù)的手段發(fā)生了一些變化犬缨。
代碼注入的方式
代碼注入的方式大致分為兩種
- 越獄注入:通過(guò)修改
DYLD_INSERT_LIBRARIES
環(huán)境變量的值,來(lái)插入動(dòng)態(tài)庫(kù)并執(zhí)行 - 非越獄注入:
- 直接將自定義的Framwork或者dylib庫(kù)打包進(jìn)入APP并重簽名。
- 利用yololib修改MachO文件,添加庫(kù)路徑.在應(yīng)用啟動(dòng)時(shí),dyld會(huì)加載并執(zhí)行.
早期防護(hù)方式
在工程的Build Settings中找到Other Linker Flages 并添加字段
-Wl,-sectcreate,__RESTRICT,__raestrict,/dev/null
此操作的作用是在可執(zhí)行文件中添加一個(gè)Section.我們使用MachOView分析如下:
當(dāng)MachO文件中擁有這個(gè)字段,那么我們通過(guò)越獄環(huán)境插入動(dòng)態(tài)庫(kù)的方式就會(huì)失效.起到防護(hù)的作用.其原理在DYLD源碼中可以分析到.
dyld源碼分析
首先這里分析的DYLD源碼版本是519.2.2版本.
我們可以通過(guò)檢索DYLD_INSERT_LIBRARIES定位到_main函數(shù)加載插入動(dòng)態(tài)庫(kù)的代碼如下.
// load any inserted libraries
if ( sEnv.DYLD_INSERT_LIBRARIES != NULL ) {
for (const char* const* lib = sEnv.DYLD_INSERT_LIBRARIES; *lib != NULL; ++lib)
loadInsertedDylib(*lib);
}
但是早在這個(gè)環(huán)境變量判斷之前,dyld已經(jīng)做了一個(gè)判斷
if ( gLinkContext.processIsRestricted ) {
pruneEnvironmentVariables(envp, &apple);
// set again because envp and apple may have changed or moved
setContext(mainExecutableMH, argc, argv, envp, apple);
}
如果判斷出進(jìn)程是restricted!也就是當(dāng)前進(jìn)程是限制插入動(dòng)態(tài)庫(kù)的!就會(huì)調(diào)用pruneEnvironmentVariables函數(shù)移除相關(guān)的環(huán)境變量.
那么我們的processIsRestricted值什么時(shí)候?yàn)閠rue呢?
繼續(xù)分析源碼可以發(fā)現(xiàn)兩個(gè)關(guān)鍵函數(shù)影響其值.其中 hasRestrictedSegment 函數(shù)專門檢測(cè)RESTRICT段
// any processes with setuid or setgid bit set or with __RESTRICT segment is restricted
if ( issetugid() || hasRestrictedSegment(mainExecutableMH) ) {
gLinkContext.processIsRestricted = true;
}
通過(guò)注釋也能發(fā)現(xiàn).任意進(jìn)程的__RESTRICT段設(shè)置為restricted動(dòng)態(tài)庫(kù)插入將被限制.
我們進(jìn)入到processIsRestricted函數(shù)內(nèi),實(shí)現(xiàn)如下.
#if __MAC_OS_X_VERSION_MIN_REQUIRED
static bool hasRestrictedSegment(const macho_header* mh)
{
const uint32_t cmd_count = mh->ncmds;
const struct load_command* const cmds = (struct load_command*)(((char*)mh)+sizeof(macho_header));
const struct load_command* cmd = cmds;
for (uint32_t i = 0; i < cmd_count; ++i) {
switch (cmd->cmd) {
case LC_SEGMENT_COMMAND:
{
const struct macho_segment_command* seg = (struct macho_segment_command*)cmd;
//dyld::log("seg name: %s\n", seg->segname);
if (strcmp(seg->segname, "__RESTRICT") == 0) {
const struct macho_section* const sectionsStart = (struct macho_section*)((char*)seg + sizeof(struct macho_segment_command));
const struct macho_section* const sectionsEnd = §ionsStart[seg->nsects];
for (const struct macho_section* sect=sectionsStart; sect < sectionsEnd; ++sect) {
if (strcmp(sect->sectname, "__restrict") == 0)
return true;
}
}
}
break;
}
cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
}
return false;
}
所以通過(guò)添加Other Linker Flags 在MachO中設(shè)置RESTRICT段賦值為restricted可以用來(lái)防護(hù)越獄的代碼注入.
但是新版的dyld源碼中去掉了__RESTRICT檢測(cè).從iOS10開始,這種防護(hù)手段已失效
DYLD_INSERT_LIBRARIES 檢測(cè)
那么既然dyld加載過(guò)程不再檢測(cè)__RESTRICT段了我們就手動(dòng)的檢測(cè)DYLD_INSERT_LIBRARIES
環(huán)境變量.通過(guò)函數(shù)可查看當(dāng)前進(jìn)程環(huán)境變量的值.
char *env = getenv("DYLD_INSERT_LIBRARIES");
NSLog(@"%s",env);
在沒(méi)有插入動(dòng)態(tài)庫(kù)時(shí),env為null.
那么一旦為自己的應(yīng)用寫入插件時(shí),我們就可以看到控制臺(tái)的輸出
2019-01-03 19:20:37.285 antiInject[7482:630392] /Library/MobileSubstrate/MobileSubstrate.dylib
白名單檢測(cè)
那么上面的檢測(cè)只可以檢測(cè)越獄環(huán)境中的代碼注入,在非越獄環(huán)境中,逆向工程師可以利用yololib工具注入動(dòng)態(tài)庫(kù).所以我們可以檢索一下自己的應(yīng)用程序所加載的動(dòng)態(tài)庫(kù)是否是我們?cè)闯绦蛩?/p>
bool HKCheckWhitelist(){
int count = _dyld_image_count();
for (int i = 0; i < count; i++) {
//遍歷拿到庫(kù)名稱棉浸!
const char * imageName = _dyld_get_image_name(i);
//判斷是否在白名單內(nèi),應(yīng)用本身的路徑是不確定的,所以要除外.
if (!strstr(libraries, imageName)&&!strstr(imageName, "/var/mobile/Containers/Bundle/Application")) {
printf("該庫(kù)非白名單之內(nèi);逞Α!\n%s",imageName);
return NO;
}
}
return YES;
}
其中l(wèi)ibraries變量是<q style="box-sizing: border-box;">白名單</q>.
喜歡的話點(diǎn)贊+1或關(guān)注多多支持哦 小編會(huì)經(jīng)常給小伙伴們更新關(guān)于IOS當(dāng)下熱點(diǎn)迷郑。
另外小編給大家推薦一個(gè)iOS技術(shù)交流群:638302184枝恋!群內(nèi)提供數(shù)據(jù)結(jié)構(gòu)與算法、底層進(jìn)階嗡害、swift焚碌、逆向、整合面試題等免費(fèi)資料
附上一份收集的各大廠面試題(附答案) ! 群文件直接獲取
各大廠面試題
文章來(lái)源網(wǎng)絡(luò) 如有侵權(quán)請(qǐng)聯(lián)系小編刪除