天天看點

iOS APP 逆向安全雜談之三 0x04 可以動手了 0x05 道高一尺魔高一丈 0x06 魔高一尺道高一丈 0x07 冤冤相報何時了

圖3 使用itools檢視fstab檔案大小

ios的磁盤被劃分為兩個分區:容量較小的是系統分區,另一個是比較大的資料分區。ios預裝的app會安裝在系統分區下的/applications檔案夾下,但是系統分區在裝置更新時會被覆寫且容量太小,是以一些越獄工具會重定向這個目錄到一個大的使用者分區。通常情況下/applications檔案夾會被符号連結到/var/stash檔案目錄下,app可以通過lstat函數檢測/applications的屬性,如若是目錄則代表未越獄,如若是符号連結則代表是越獄裝置。

iOS APP 逆向安全雜談之三 0x04 可以動手了 0x05 道高一尺魔高一丈 0x06 魔高一尺道高一丈 0x07 冤冤相報何時了

圖4 使用itools檢視符号連結

iOS APP 逆向安全雜談之三 0x04 可以動手了 0x05 道高一尺魔高一丈 0x06 魔高一尺道高一丈 0x07 冤冤相報何時了

圖5 使用指令行檢視符号連結

我們使用檔案檢測的第一種方法來動手測試一下我們的越獄裝置。代碼如下:

<code>#include &lt;sys/stat.h&gt;</code>

<code>#include &lt;stdio.h&gt;</code>

<code></code>

<code>int</code><code>isjailbroken(</code><code>);</code>

<code>int</code><code>main(){</code>

<code>    </code><code>if</code><code>(isjailbroken()){</code>

<code>        </code><code>printf</code><code>(</code><code>"device is jailbroken\n"</code><code>);</code>

<code>    </code><code>}</code><code>else</code><code>{</code>

<code>        </code><code>printf</code><code>(</code><code>"device is not jailbroken\n"</code><code>);</code>

<code>    </code><code>}</code>

<code>    </code><code>return</code><code>0;</code>

<code>}</code>

<code>int</code><code>isjailbroken(){</code>

<code>   </code><code>struct</code><code>statbuf;</code>

<code>    </code><code>int</code><code>exist = 0;</code>

<code>    </code><code>char</code><code>* jbfiles[] =</code>

<code>{</code><code>"/usr/sbin/sshd"</code><code>,</code><code>"/bin/bash"</code><code>,</code><code>"/applications/cydia.app"</code><code>,</code><code>"/private/var/lib/apt"</code><code>,</code><code>"/libra  ry/mobilesubstrate/mobilesubstrate.dylib"</code><code>};</code>

<code>    </code><code>for</code><code>(</code><code>int</code><code>i=0;i &lt;</code><code>sizeof</code><code>(jbfiles)/</code><code>sizeof</code><code>(</code><code>char</code><code>*);i++){</code>

<code>        </code><code>exist = stat((jbfiles[i]),&amp;buf);</code>

<code>        </code><code>if</code><code>(exist == 0){</code>

<code>            </code><code>return</code><code>1;</code>

<code>        </code><code>}</code>

以上代碼主要檢測了<code>/usr/sbin/sshd</code>、<code>/bin/bash</code>、<code>/applications/cydia.app</code>、<code>/private/var/lib/apt</code>、<code>/library/mobilesubstrate/mobilesubstrate.dylib</code>這幾個檔案是否存在,如果存在則證明該裝置已經越獄。

iOS APP 逆向安全雜談之三 0x04 可以動手了 0x05 道高一尺魔高一丈 0x06 魔高一尺道高一丈 0x07 冤冤相報何時了

圖6 檢測越獄的poc

在mac下使用以下指令編譯代碼:

編譯之後将二進制檔案拷貝到越獄裝置當中并在指令行中運作它。下圖可看到運作程式後顯示裝置已經越獄。

iOS APP 逆向安全雜談之三 0x04 可以動手了 0x05 道高一尺魔高一丈 0x06 魔高一尺道高一丈 0x07 冤冤相報何時了

圖7 賦予檔案權限并執行

一些app正是使用了類似上面的方法來檢測自己所在裝置是否進行了越獄,為了保證自身的安全性如果裝置越獄則自動退出。是的這種做法很明智,但是這也隻是增加了安全測試的難度,我們既然知道了檢測越獄的原理那麼就可以見招拆招了。

(1) 配置好lldb和debugserver,ssh連接配接到裝置,在裝置上使用指令行輸入<code>debugserver -x backboard *:1234 /jailbreak64</code>附加到jailbreak64,并開啟1234端口,等待lldb的接入。

iOS APP 逆向安全雜談之三 0x04 可以動手了 0x05 道高一尺魔高一丈 0x06 魔高一尺道高一丈 0x07 冤冤相報何時了

圖8 在ipad端使用debugserver附加到程式

(2) mac端切換到<code>~/xcode.app/contents/developer/usr/bin/</code>目錄下,輸入<code>lldb</code>,啟動後輸入<code>process connect connect://iosip:1234</code>。

iOS APP 逆向安全雜談之三 0x04 可以動手了 0x05 道高一尺魔高一丈 0x06 魔高一尺道高一丈 0x07 冤冤相報何時了

圖9 mac端使用lldb連接配接ios裝置

(3) 使用ida分析程式邏輯結構,這裡有一點需要注意:ida分析的二進制檔案必須與lldb調試的二進制檔案相同,這樣偏移前基位址、aslr偏移、偏移後基位址才能對應得上。這裡由于我的ipad對應的arm是arm64,是以之前在mac上我使用arm64編譯的程式,将編譯的程式扔到ida中分析,這裡我使用的是idapro6.6中的idaq64.exe進行分析的。(這裡所說的aslr偏移指的是偏移後子產品基位址-偏移前子產品基位址,偏移後子產品基位址:二進制檔案加載到記憶體子產品在記憶體中的首位址;偏移前子產品基位址:子產品在檔案中的首位址)

iOS APP 逆向安全雜談之三 0x04 可以動手了 0x05 道高一尺魔高一丈 0x06 魔高一尺道高一丈 0x07 冤冤相報何時了

圖10 arm64編譯後的程式在ida中的分析

根據上圖我們可以看到位址0x100007d1c下方有兩個分支,即左邊的判斷是裝置已經越獄,而右邊的判斷是裝置沒有越獄。

之是以說這裡需要注意是因為我們在使用lldb調試程式下斷點時需要偏移前基位址,而這個偏移前基位址不同場景下是不一樣的。下圖為armv7編譯後使用ida分析的結果,可以看到我們關注的位址變為了0xbe28。

iOS APP 逆向安全雜談之三 0x04 可以動手了 0x05 道高一尺魔高一丈 0x06 魔高一尺道高一丈 0x07 冤冤相報何時了

圖11 armv7編譯後的程式在ida中的分析

(4) 使用lldb檢視aslr偏移,此時需要知道幾個指令:ni執行下一條指令但不進入函數體,si執行下一條指令會進入函數體,image list列舉目前是以子產品。

iOS APP 逆向安全雜談之三 0x04 可以動手了 0x05 道高一尺魔高一丈 0x06 魔高一尺道高一丈 0x07 冤冤相報何時了

圖12 使用lldb檢視aslr偏移

上圖顯示<code>jailbreak64</code>還未啟動,現在調試還發生在<code>dyld</code>内部,接下來一直執行<code>ni</code>指令,直到輸出結果出現卡頓(大約3秒左右,可以明顯察覺到)。到這裡不要再使用<code>ni</code>指令,<code>dyld</code>已經開始加載<code>jailbreak64</code>,我們使用<code>image list -o -f</code>檢視<code>jailbreak64</code>的aslr偏移。

iOS APP 逆向安全雜談之三 0x04 可以動手了 0x05 道高一尺魔高一丈 0x06 魔高一尺道高一丈 0x07 冤冤相報何時了

圖13 多次執行ni指令後檢視<code>jailbreak64</code>的偏移

根據上圖顯示<code>jailbreak64</code>的aslr偏移為0x40000,是以可以确定斷點位置下在‘0x40000+0x100007d1c’處。

(5) 根據以上資訊我們就可以安心的下斷點了,使用<code>br s -a</code> 位址用來下斷點,使用指令<code>p</code>可以列印某處的值,使用指令<code>register write</code>給指定的寄存器指派。

iOS APP 逆向安全雜談之三 0x04 可以動手了 0x05 道高一尺魔高一丈 0x06 魔高一尺道高一丈 0x07 冤冤相報何時了

圖14 下斷點

上圖是在‘0x40000+0x100007d1c’處設定斷點

iOS APP 逆向安全雜談之三 0x04 可以動手了 0x05 道高一尺魔高一丈 0x06 魔高一尺道高一丈 0x07 冤冤相報何時了

圖15 檢視x0的值并重新指派來更改程式邏輯

我們使用<code>p</code>指令檢視一下此時x0的值,發現x0為1,使用<code>register write</code>指令将該x0的值改為0,然後輸入指令<code>c</code>繼續,可以看到我們成功的繞過了越獄檢測,程式運作結果為裝置未越獄。

在cydia上可以安裝xcon軟體,據說是目前為止最強大的越獄檢測繞過工具,然而我安裝在我的ipad上并不适用,應該暫不支援ios8.4吧。xcon可以繞過四種越獄檢測方法(根據特定的越獄檔案及檔案權限判斷裝置是否越獄;根據沙盒完整性判斷裝置是否越獄;根據檔案系統的分區是否發生變化來檢查裝置是否越獄;根據是否安裝ssh來判斷裝置是否越獄)。用最近比較流行的一句話就是“你有一百種方式來檢測越獄”,而别人也有一百種方式來抵抗你的檢測。

剛才我們示範的是lldb調試來繞過越獄檢測,那麼如果我的程式阻止調試器附加怎麼辦?我們來看下面的測試代碼。

#include &lt;sys/stat.h&gt;

#include &lt;stdio.h&gt;

#include &lt;sys/types.h&gt;

#include &lt;sys/sysctl.h&gt;

#include &lt;unistd.h&gt;

inline int checkdebugger()__attribute__((always_inline));

int main(){

    if(checkdebugger()){

        printf("debugger attached\n");

        return0;

    }

    printf("debug detection bypassed\n");

    return0;

}

int checkdebugger(){

    int name[4];

    structkinfo_proc info;

    size_t info_size =sizeof(info);

    info.kp_proc.p_flag =0;

    name[0] =ctl_kern;

    name[1] =kern_proc;

    name[2] =kern_proc_pid;

    name[3] =getpid();

    if(sysctl(name,4,&amp;info,&amp;info_size,null,0)

== -1){

        return1;

    return(info.kp_proc.p_flag

&amp;p_traced) ?

1 :0;

當一個應用被調試的時候,會給程序設定一個辨別(p_traced),可以檢測該程序是否有設定這個辨別來檢測程序是否正在被調試來保護應用。如果該程式發現自己被調試器附加了程序,那麼将會輸出debugger attached,如果正常運作該程式則會輸出debug detection bypassed。實驗結果如下:

iOS APP 逆向安全雜談之三 0x04 可以動手了 0x05 道高一尺魔高一丈 0x06 魔高一尺道高一丈 0x07 冤冤相報何時了

圖16 正常運作的輸出結果

iOS APP 逆向安全雜談之三 0x04 可以動手了 0x05 道高一尺魔高一丈 0x06 魔高一尺道高一丈 0x07 冤冤相報何時了

圖17 使用lldb調試器附加後的輸出結果

在實際應用中可以在得知自己的程式被調試器附加後自動退出,當然這也是可以通過下斷點的方式繞過,但是可以通過多處調用該方法來增加攻擊的難度。同時上面的代碼采用聲明内聯函數的方法,使編譯器将函數功能插到每處代碼被調用的地方,而不至于某個特定的功能函數被劫持。

當然除了上述的這種反調試的方法,還可以通過優化标記、去除符号等方法使反彙編複雜化。

0x06中所說的反調試還可以通過打更新檔的方式繞過,這樣就不需要每次都下斷點繞過,也會有更多的時間用lldb來調試其他核心業務。是不是感覺有些亂?因為的确是攻擊和防禦的方法都有很多,廠商采用多種防禦手段來增加攻擊成本,而攻擊者為了利益或者抱有挑戰心理的态度來見招拆招,真是冤冤相報啊。

參考文獻:

安全連結:http://wiki.wooyun.org/

[美]jonathan zdziarski《hacking and securing ios application》

沙梓社,吳航《ios應用逆向工程》

<code>http://blog.ioactive.com/2015/09/the-ios-get-out-of-jail-free-card.html</code>

繼續閱讀