<pre id="vvttv"><mark id="vvttv"><progress id="vvttv"></progress></mark></pre>
    <pre id="vvttv"></pre>

      <p id="vvttv"></p>

          <p id="vvttv"></p>

                <p id="vvttv"></p>

                <pre id="vvttv"><cite id="vvttv"><progress id="vvttv"></progress></cite></pre>

                  <output id="vvttv"><dfn id="vvttv"><th id="vvttv"></th></dfn></output>

                    <p id="vvttv"></p>

                    原文地址:http://drops.wooyun.org/mobile/15794

                    0x00 前言


                    目前,在iOS中很多dylib是通過DYLDINSERTLIBRARIES來動態注入的,關于這種注入的防范方式最好的方法是在程序編譯時,添加一個空的restict區段,因為dyld在load動態庫時會檢查區段中是否存在restict,如果存在那么就跳過加載。詳情參見:防止tweak依附,App有高招;破解App保護,tweak留一手

                    前段時間,發現自己寫的一個demo加了restict之后,仍然能夠被cycript掛載,順勢分析了cycript的注入原理。

                    0x01 cycript簡介


                    cycript是大神saurik開發的一個非常強大的工具,可以讓開發者在命令行下和應用交互,在運行時查看和修改應用。其中的底層實現,是通過蘋果的JavaScriptCore.framework來打通iOS與javascript的橋梁。具體詳解,參考

                    0x02 cycript結構


                    在安裝cycript過后,通過cydia可以看到安裝cycript之后影響的目錄結構

                    雖然只提到這幾個文件,但是在/usr/bin下,還有一個cynject的可執行文件和cycript相關,后面分析會發現,這個程序才是注入的核心文件。我這里,通過scp把這些文件都下載到本地,方便分析。

                    0x03 cycript主程序


                    分析Cycript主程序時,觀察到里面有一個InjectLibrary的函數被調用

                    #!c
                    void InjectLibrary(int pid, int argc, const char *argv[]) {
                        auto cynject(LibraryFor(reinterpret_cast<void *>(&main)));
                        auto slash(cynject.rfind('/'));
                        _assert(slash != std::string::npos);
                        cynject = cynject.substr(0, slash) + "/cynject";
                        auto library(LibraryFor(reinterpret_cast<void *>(&MSmain0)));
                        bool ios(false);
                        for (decltype(header->ncmds) i(0); i != header->ncmds; ++i) {
                            if (command->cmd == LC_VERSION_MIN_IPHONEOS)
                                ios = true;
                            command = shift(command, command->cmdsize);
                        }
                        _syscall(munmap(map, size)); // XXX: _scope
                        auto length(library.size());
                        _assert(length >= 6);
                        length -= 6;
                        _assert(library.substr(length) == ".dylib");
                        library = library.substr(0, length);
                        library += ios ? "-sim" : "-sys";
                        library += ".dylib";
                    #endif
                        std::ostringstream inject;
                        inject << cynject << " " << std::dec << pid << " " << library;
                        for (decltype(argc) i(0); i != argc; ++i)
                            inject << " " << argv[i];   
                    
                        _assert(system(inject.str().c_str()) == 0);
                    }
                    

                    程序在解析過程中,注入代碼前會對會環境進行檢查,并且進行字符串格式化拼接,構造一個shell命令,用來做調用system函數的參數,來執行cynject注入功能。

                    0x04 cynject注入程序


                    接下來分析cynject,在函數subb308的位置可以看到,通過調用taskfor_pid獲取到進程句柄結構。通過該結構,可以對進程能夠有訪問權限。

                    舉個栗子:

                    #!c
                    mach_port_t rtask;
                    task_for_pid(mach_task_self(), pid, &rtask);
                    

                    程序為了讓內存中的dylib有執行能力,把dylib通過線程的方式來加載。繼續往下看,就發現進程創建一個被掛起的線程

                    拿到句柄結構,在進程的空間中申請內存,將dylib映射之后,寫入到這片申請的空間里面。

                    所以,代碼邏輯大概是這樣的:

                    #!c
                    vm_size_t codeSize = 124;
                    vm_address_t rAddress;
                    vm_allocate(rtask, &rAddress, codeSize, TRUE);
                    vm_write(rtask, rAddress, &code, (mach_msg_type_number_t)codeSize);
                    vm_protect(rtask, rAddress, codeSize, FALSE, VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE);
                    

                    最后,等dylib加載完全后,為dylib恢復啟動并執行使其開始運行

                    梳理一下大體的流程:

                    ( 1 )獲取 PID 的進程句柄
                    ( 2 )在 PID 中創建一個被掛起的線程
                    ( 3 )在 PID 進程中申請一片用于加載 DYLIB 的內存
                    ( 4 )調用 RESUME ,恢復線程

                    OVER~

                    說到這里,流程差不多梳理完了,拿一個dylib測試一下

                    通過lldb連上程序,看一下內存加載模塊:

                    可以發現,我們惡意的dylib已經注入到進程中了。

                    0x05 后記


                    cycript里面還有一些比較有意思的東西,大家可以深挖一下。另外,上面的內容不要用到自己企業的app產品中,按照蘋果appStore原則,調用私有api以及動態注入代碼的操作,是會被下架的。

                      <pre id="vvttv"><mark id="vvttv"><progress id="vvttv"></progress></mark></pre>
                      <pre id="vvttv"></pre>

                        <p id="vvttv"></p>

                            <p id="vvttv"></p>

                                  <p id="vvttv"></p>

                                  <pre id="vvttv"><cite id="vvttv"><progress id="vvttv"></progress></cite></pre>

                                    <output id="vvttv"><dfn id="vvttv"><th id="vvttv"></th></dfn></output>

                                      <p id="vvttv"></p>

                                      这里只有精品视频