<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/papers/6162

                    0x00 ELF格式簡介:


                    注:本文只討論如何調試被加殼的ELF文件,包括調試中的技巧運用及調試過程中可能遇到的問題的解決方法,不包含如何還原加固的DEX

                    本文將以某加殼程序和某加固為目標

                    ELF全稱:Executable and Linkable Format,是Linux下的一種可執行文件格式。 此種文件格式和WINDOWS一樣,常見分為兩種類型:

                    1. 可執行文件(Executable File),對應PE子類型:EXE

                    2. 共享目標文件(Shared Object File),后綴名:.so,對應PE子類型:DLL

                    0x01 ELF文件加載大概流程:


                    1. 通過Section Header或者Program Header加載需要的鏡像數據 和WINDOWS PE加載機制不同,ELF有些文件數據是不會加載到內存鏡像中
                    2. 加載SO NEED LIB和SYM 類似PE的Import_table
                    3. 執行重定位(如果有) 類似PE的Reloc_table
                    4. 執行INIT_ARRAY段或者INIT段(如果有,數組中的地址不等于0xffffffff,0表示結束)

                      類似PE的TLS,已知的被加殼的ELF,殼代碼都出現在這兩個段里 PE中的TLS也常常出現在殼中,例如Vmprotect, Execryptor等

                    5. 執行入口點代碼(如果有)

                    所有的上述加載流程代碼全部包含在linker.so里,可參看安卓源碼或逆向linker.so

                    0x03 ARM CPU簡介:?1.指令集簡介:


                    ARMCPU采用RISC(精簡指令集)架構(X86是CISC,復雜指令集),指令等長,相對CISC架構更加省電,執行效率更高

                    2. ARM指令集三種類型:

                    ARM(4字節等長),THUMB(2字節等長),THUMB2(4字節等長)。這三種指令集可以在同一執行程序中切換,切換原則為:

                    ARM <-->THUMB,THUMB<-->ARM(PC的最高位確定指令集類型:1為THUMB;0為ARM)

                    THUMB<-->THUMB2(由27-31位決定)

                    thumb2其實就是thumb的擴展,其目的是為了一條4字節指令完成多條2字節指令

                    *|3.寄存器: *|

                    通用寄存器:r0-r15

                    特殊寄存器:r13 = SP(棧地址), r14 = LR(函數返回地址), r15 = PC(當前指令流地址)

                    還包括CPSR,APSR,浮點等寄存器,具體可參照ARM指令集手冊

                    0x04 加殼SO的調試


                    1.ELF代碼執行順序

                    上面介紹了,加殼的SO的殼代碼都在INIT_ARRAY段和INIT段

                    那我們先看下一個被加殼以后的SO,在linux下面用readelf -a命令查看ELF信息

                    enter image description here

                    enter image description here

                    在ELF-HEADER里我們看到有Entry,地址為0x22a8

                    在動態段里看到了INIT_ARRAY數組,數組地址為0x21000,大小是12 BYTES

                    用IDA看看數組的內容

                    enter image description here

                    上面說了,-1為無效,0代表結束,那INIT有效地址僅是0x2418這個地址

                    也就是說,這個SO加載起來以后,會先從0x2418這個地址開始執行,執行完成后再去執行Entry

                    我們再來看下某加固的ELF信息

                    enter image description here

                    enter image description here

                    在ELF-HEADER里我們看到有Entry,地址為0x3860

                    enter image description here

                    DA打開某加固的文件時,會提示錯誤,不能打開,后面在Anti Anti Debugger中會講到為什么

                    在動態段里看到了INIT_ARRAY數組,數組地址為0x28CA4,大小是8 BYTES

                    我們還看到了INIT段,地址是0x11401

                    我們在這里,總結下執行的順序:

                    根據linker的代碼,當INIT段和INIT_ARRAY段都存在的情況下,先運行INIT段,再運行INIT_ARRAY段,否則單獨運行對應指向的函數,最后執行ENTRY

                    enter image description here

                    2. 自己準備SO_LOADER

                    調試SO和PE_DLL其實道理是一樣的,都需要一個宿主進程,這里要寫一個SO_LOADER,參看代碼如下,可通過NDK編譯。(代碼是王晨同學早期提供的)

                    enter image description here

                    3.環境準備:

                    我這里選用IDA6.6做為調試器。

                    第一步:拷貝調試器到安卓手機上

                    enter image description here

                    命令:adb push android_server /data/local/tmp/and

                    這里為什么把android_server 改名成and呢~~~,其實就是為了避免被檢測出調試器,后面我在Anti Anti Debugger中會詳細說一下關于這部分的內容

                    第二步:啟動調試器

                    adb shell回車,進入/data/local/tmp/目錄,啟動調試器,啟動后畫面

                    enter image description here

                    第三步:重定向調試端口

                    adb forward tcp:23946 tcp:23946

                    至此手機端設置完畢,下面來看看IDA里如何設置

                    IDA加載我們自己寫的so_loader,在854C處,按F2下斷點

                    enter image description here

                    選擇菜單欄里面的Debuger-Select Debugger,選擇Remote Arm linux/Andoid debugger

                    enter image description here

                    點擊OK,然后F9運行

                    enter image description here

                    在配置里面,Hostname里面填入127.0.0.1,點擊OK

                    如果你的手機里面沒有這個文件,會提示你COPY,點擊確定即可,如果有這個文件,會出現下面的選擇,一般選擇USE FOUND就可以了,如果你要調試的程序有修改,選擇COPY NEW覆蓋一個新的進去

                    enter image description here

                    然后一路OK,就出現調試狀態了~~,當前PC就是剛才我們F2設置的斷點

                    enter image description here

                    4.如何斷住SO的INIT_ARRAY段和INIT段

                    上面說了,SO的加載在linker.so里完成,我們要做的,就是把斷點設置在linker.so里面

                    先找代碼,IDA打開linker.so,在string窗口里找

                    call_constructors_recursive,雙擊并查看引用

                    enter image description here

                    enter image description here

                    雙擊第二個引用處,然后往上找blx r3(init段的調用),b.w xxxxxxxx(init_array段的調用)

                    enter image description here

                    enter image description here

                    好了,現在我們找到了地址0x54d0, 0x3af0這兩個地方,回到剛才調試的IDA里面,

                    選擇菜單欄debugger-Debugger windows-module list打開進程模塊列表

                    enter image description here

                    linker.so的base是40002000,分別對應的兩個地址就是

                    0x40002000+0x54d0 = 0x400074d0
                    0x40002000+0x3af0 = 0x40005af0
                    

                    我們在IDA View-PC窗口GO 過去

                    enter image description here

                    在0x74d0處,按C鍵,變成代碼.奇怪,為什么沒有反應!!而且在最下面的output window有如下提示

                    enter image description here

                    這里就是我說的很重要的問題了,上面我提到了,被調試的程序可以在3種指令集之間切換,這時的IDA并不知道當前要變成代碼的地址是ARM還是THUMB,這時我們需要對照靜態的來看,或者你對指令集絕對的熟悉,看到BYTE CODE就知道是哪種指令集

                    enter image description here

                    靜態中,顯然IDA給的是2字節指令,那必然是THUMB,我們需要把當前地址改成THUMB

                    方法:按鍵盤的ALT+G,呼喚出窗口

                    enter image description here

                    T,DS不用管,我們只需要把VALUE改成1就是THUMB指令集了,變成1點擊OK以后

                    在原來的地址上出現了CODE16,這時我們再去C一次

                    enter image description here

                    C完以后,就出現代碼了!!!ARM和THUMB就是這么切換的,切記,切記

                    enter image description here

                    再看另外一個地址,0x400a5af0,按照同樣的方法再來一次

                    enter image description here

                    問題又來了,奇怪了,為什么下面不是指令?!這個是IDA的BUG,6.6版本對THUMB2指令在調試狀態的解析就是有問題。。。。,不過沒關系,我們往下看

                    enter image description here

                    這段代碼才是最重要的,執行每一個init_array中地址的函數,就在blx r2這句。 至此,如何斷住INIT段和INIT_ARRAY段,就講完了,剩下的大家就自己調試吧

                    0x05 Anti Anti Debugger


                    1.Anti IDA

                    其實這種問題,是IDA解析ELF和linker解析ELF不一致造成的,IDA更加嚴格

                    用ida打開某加固的so,提示

                    enter image description here

                    這個提示就是說,有個數據描述是無效的,我們來看看,是哪個。

                    SHT說的就是Section Table,來看看ELF頭部數據如下

                    enter image description here

                    shoff就是這個值,我們用16進制編輯器過去看看

                    enter image description here

                    全是0,顯然這里有問題,我們首先要把這個值清0,保存文件。

                    再次加載,還有問題,提示如下:

                    enter image description here

                    這次通過調試IDA的ELF插件,發現當PROGRAM HEADER中的物理偏移大于文件大小時,就會出現該錯誤。

                    enter image description here

                    顯然,Program Header中的第一組數據,p_offset超過了文件大小,根據ELF結構,定位到該數據偏移,改成0,IDA加載成功

                    2.Anti Debugger

                    通過調試該加殼程序,總結他用到的方法:

                    方法1:檢測父進程的文件名

                    調用getppid,獲取父進程的id, open("/proc/ppid/cmdline")獲取父進程名稱,檢測常用調試器的名字,這就是上面我COPY文件時,為啥要把android_server變成隨意一個文件名的原因了

                    對策:修改getppid的返回值,隨便給一個可以用的就行了

                    其實還有其他方法可以獲取ppid,比如open("/proc/pid/status"),read這個handle的內容,在里面尋找ppid也行

                    方法2:異常陷阱

                    和WINDOWS的方法類似,設置一個trap,檢測調試器

                    對策:IDA默認所有的trap都交給調試器處理,所以我們需要修改對應的設置。菜單選擇debugger-debugger options,點擊edit exceptions按鈕

                    enter image description here

                    在trap上,右鍵編輯改成如下即可

                    enter image description here

                    當然,檢測調試器,還有很多方法,見招拆招就可以,這里就不詳述了

                      <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>

                                      这里只有精品视频