Tweak原理與越獄防護

本文不包含具體編寫插件的內(nèi)容吨瞎,只是從Tweak的原理去探究怎么防護插件的注入。

生成一個Tweak插件

有兩種方式生成Tweak插件,一種是MonkeyDev爷恳,一種是Theos。

安裝MonkeyDev

MonkeyDev安裝與說明https://github.com/AloneMonkey/MonkeyDev
Monkey的使用

  • MonkeyApp 重簽名app象踊,可以選擇一個脫殼的ipa直接跑起來debug
  • MonkeyPod 通過pod集成插件
  • Command-line 命令行工具
  • Tweak 越獄插件

我們選擇Logos Tweak 來創(chuàng)建插件
項目中xm就是需要編寫的hook文件温亲、mm生成的目標文件
plist是注入目標的配置,截圖上默認的是springboard應(yīng)用



build settings里的設(shè)置杯矩,有三個空的需要填一下栈虚,如果是ssl登錄,則不需要填寫密碼史隆。最后一個是安裝插件的時候魂务,殺掉的目標進程。


安裝Theos

Thoes的安裝與使用https://github.com/theos/theos

編譯生成Tweak

從編譯產(chǎn)物中泌射,可看出是一個dylib動態(tài)庫文件

原理

Tweak通過dyld insert librarys 環(huán)境變量 插入到系統(tǒng)里

插入動態(tài)庫的核心源碼

        // load any inserted libraries(越獄的環(huán)境都是用這個U辰)
        if  ( sEnv.DYLD_INSERT_LIBRARIES != NULL ) {
            for (const char* const* lib = sEnv.DYLD_INSERT_LIBRARIES; *lib != NULL; ++lib) 
                loadInsertedDylib(*lib);
        }

通過dyld源碼查看到環(huán)境變量sEnv.DYLD_INSERT_LIBRARIES不為空的時候,會插入動態(tài)庫熔酷,所以我們繼續(xù)看源碼環(huán)境變量相關(guān)的部分
在insert之前pruneEnvironmentVariables這行代碼表示移除相關(guān)的環(huán)境變量孤紧,因此我們只要關(guān)注!gLinkContext.allowEnvVarsPrint && !gLinkContext.allowEnvVarsPath && !gLinkContext.allowEnvVarsSharedCache這個判斷為true就可以

    if ( !gLinkContext.allowEnvVarsPrint && !gLinkContext.allowEnvVarsPath && !gLinkContext.allowEnvVarsSharedCache ) {
        pruneEnvironmentVariables(envp, &apple);
        // set again because envp and apple may have changed or moved
        setContext(mainExecutableMH, argc, argv, envp, apple);
    }

繼續(xù)查看源碼看到hasRestrictedSegment這個函數(shù),Mach-O里如果包含了Restricted段就可以是值為true.

        // support chrooting from old kernel
        bool isRestricted = false;
        bool libraryValidation = false;
        // any processes with setuid or setgid bit set or with __RESTRICT segment is restricted
  // issetugid 這個函數(shù)不能在上架的app使用
        if ( issetugid() || hasRestrictedSegment(mainExecutableMH) ) {
            isRestricted = true;
        }
        bool usingSIP = (csr_check(CSR_ALLOW_TASK_FOR_PID) != 0);
        uint32_t flags;
        if ( csops(0, CS_OPS_STATUS, &flags, sizeof(flags)) != -1 ) {
            // On OS X CS_RESTRICT means the program was signed with entitlements
            if ( ((flags & CS_RESTRICT) == CS_RESTRICT) && usingSIP ) {
                isRestricted = true;
            }
            // Library Validation loosens searching but requires everything to be code signed
            if ( flags & CS_REQUIRE_LV ) {
                isRestricted = false;
                libraryValidation = true;
            }
        }
        gLinkContext.allowAtPaths                = !isRestricted;
        gLinkContext.allowEnvVarsPrint           = !isRestricted;
        gLinkContext.allowEnvVarsPath            = !isRestricted;
        gLinkContext.allowEnvVarsSharedCache     = !libraryValidation || !usingSIP;
        gLinkContext.allowClassicFallbackPaths   = !isRestricted;
        gLinkContext.allowInsertFailures         = false;

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 = &sectionsStart[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;
}

防護

通過上邊的源碼纯陨,得到了一個結(jié)論坛芽,只要在Mach-O里包含了__RESTRICT段就能防止insert library。圖里在otherLinker里增加了幾個參數(shù)



增加完后翼抠,用MachOview查看內(nèi)容咙轩,Mach-O里成功的增加了__RESTRICT段,防護住了應(yīng)用插件


再突破

修改Mach-O,使用MachOview阴颖,修改完成后保存活喊。然后需要重簽名后運行,重簽名后量愧,bundleId變了钾菊,可以通過其他方式監(jiān)測Hook情況


再防護

應(yīng)用程序內(nèi)校驗Mach-O情況帅矗,通過上邊的源碼hasRestrictedSegment函數(shù),去查看是否__RESTRICT段被破壞煞烫。

后續(xù)
hook hasRestrictedSegment 方法浑此,繼續(xù)突破與防護,永無止境滞详。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末凛俱,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子料饥,更是在濱河造成了極大的恐慌蒲犬,老刑警劉巖,帶你破解...
    沈念sama閱讀 210,914評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件岸啡,死亡現(xiàn)場離奇詭異原叮,居然都是意外死亡,警方通過查閱死者的電腦和手機巡蘸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評論 2 383
  • 文/潘曉璐 我一進店門奋隶,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人赡若,你說我怎么就攤上這事达布⊥偶祝” “怎么了逾冬?”我有些...
    開封第一講書人閱讀 156,531評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長躺苦。 經(jīng)常有香客問我身腻,道長,這世上最難降的妖魔是什么匹厘? 我笑而不...
    開封第一講書人閱讀 56,309評論 1 282
  • 正文 為了忘掉前任嘀趟,我火速辦了婚禮,結(jié)果婚禮上愈诚,老公的妹妹穿的比我還像新娘她按。我一直安慰自己,他們只是感情好炕柔,可當我...
    茶點故事閱讀 65,381評論 5 384
  • 文/花漫 我一把揭開白布酌泰。 她就那樣靜靜地躺著,像睡著了一般匕累。 火紅的嫁衣襯著肌膚如雪陵刹。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,730評論 1 289
  • 那天欢嘿,我揣著相機與錄音衰琐,去河邊找鬼也糊。 笑死,一個胖子當著我的面吹牛羡宙,可吹牛的內(nèi)容都是我干的狸剃。 我是一名探鬼主播,決...
    沈念sama閱讀 38,882評論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼狗热,長吁一口氣:“原來是場噩夢啊……” “哼捕捂!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起斗搞,我...
    開封第一講書人閱讀 37,643評論 0 266
  • 序言:老撾萬榮一對情侶失蹤指攒,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后僻焚,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體允悦,經(jīng)...
    沈念sama閱讀 44,095評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,448評論 2 325
  • 正文 我和宋清朗相戀三年虑啤,在試婚紗的時候發(fā)現(xiàn)自己被綠了隙弛。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,566評論 1 339
  • 序言:一個原本活蹦亂跳的男人離奇死亡狞山,死狀恐怖全闷,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情萍启,我是刑警寧澤总珠,帶...
    沈念sama閱讀 34,253評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站勘纯,受9級特大地震影響局服,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜驳遵,卻給世界環(huán)境...
    茶點故事閱讀 39,829評論 3 312
  • 文/蒙蒙 一淫奔、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧堤结,春花似錦唆迁、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至来庭,卻和暖如春妒蔚,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評論 1 264
  • 我被黑心中介騙來泰國打工肴盏, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留科盛,地道東北人。 一個月前我還...
    沈念sama閱讀 46,248評論 2 360
  • 正文 我出身青樓菜皂,卻偏偏與公主長得像贞绵,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子恍飘,可洞房花燭夜當晚...
    茶點故事閱讀 43,440評論 2 348