<form id="hz9zz"></form>
  • <form id="hz9zz"></form>

      <nobr id="hz9zz"></nobr>

      <form id="hz9zz"></form>

    1. 明輝手游網中心:是一個免費提供流行視頻軟件教程、在線學習分享的學習平臺!

      DLL文件脫殼

      [摘要]DLL文件的脫殼與EXE文件步驟差不多, 所不同的是, DLL文件多了個基址重定位表等要考慮。 在2003年出版的《加密與解密》(第二版)中以UPX, PECompact為例講述了DLL...

      DLL文件的脫殼與EXE文件步驟差不多, 所不同的是, DLL文件多了個基址重定位表等要考慮。

       

      在2003年出版的《加密與解密》(第二版)中以UPX, PECompact為例講述了DLL重定位重建的方法, 由于本人的思路限制, 當時只是從UPX, PECompact自身特點找思路解決這問題, 即先分析UPX, PECompact對重定位表處理算法, 然后寫工具逆算法還原重定位表, 如UPXAngela.exe等工具。 這種思路的通用性不好, 針對不同的殼和版本, 要重寫工具, 并且逆算法可能不完美, 從而存在bug。

       

      后來, askformore在“重建重定位表腳本”一文中, 提出了一種更通用性的解決辦法, 利用外殼重定位相關數據時, 會根據外殼轉儲的重定位表確定要重定位的RVA, 完成代碼重定位工作。 將這些要重定位的RVA提取出來, 再將這些RVA根據重定位表的定義重新生成一份新的重定位表。 shoooo也曾提到過這個思路。 于是, 在第三版重寫這部分時, 根據這個思路寫了一款工具來完成這個重建功能, 詳見附件的ReloREC。 另外, ReloREC重構重定位表的算法代碼, 參考了ccfer在看雪論壇.珠海金山2007逆向分析挑戰賽 第二階段第三題 提交的代碼。 在此一并表示感謝!

       

       

      聲明:本文以第三版“13.5 DLL文件脫殼”一文和其他章節臨時整理組織, 稍有簡化, 可能有部分地方用詞和描述不是太連貫。

      加殼的DLL處理重定位表有以下幾種情況:

      1)完整的保留了原重定位表;

      2)對原重定位表進行了加密處理;

      等等

       

      像ASPack,ASProtect等殼屬于第1種情況, 沒有加密重定位表, 脫殼后, 只需找到重定位的地址和大小即可。

      像UPX, PECompact等殼屬于第2種情況, 必須重建重定位表, 這也是本文所要討論的, 本文以UPX為例來講述一下重定位的重建。

      用UPX v3.01將EdrLib.dll文件加殼, 用PE工具查看其PE信息。

      EntryPoint:E640h

      ImageBase:400000h

       

       

      13.5.1 尋找OEP

       

      當DLL被初次映射到進程的地址空間中時, 系統將調用DllMain函數, 當卸載DLL時也會再次調用DllMain函數。 也就是說, DLL文件相比EXE文件運行有一些特殊性, EXE的入口點只在開始時執行一次, 而DLL的入口點在整個執行過程中至少要執行兩次。 一次是在開始時, 用來對DLL做一些初始化。 至少還有一次是在退出時, 用來清理DLL再退出。 所以DLL找OEP也有兩條路可以走, 一是載入時找, 另一方法是在退出時找。 而且一般來說前一種方法外殼代碼較復雜, 建議用第二種方法。

      UPX殼比較簡單, 往下翻翻, 就可看到跳到OEP的代碼:

       

      代碼:

      003DE7F5   .  58              pop     eax

      003DE7F6   .  61              popad

      003DE7F7   .  8D4424 80       lea     eax, dword ptr [esp-80]

      003DE7FB   >  6A 00           push    0

      003DE7FD   .  39C4            cmp     esp, eax

      003DE7FF   .^ 75 FA           jnz     short 003DE7FB

      003DE801   .  83EC 80         sub     esp, -80

      003DE804   >- E9 372AFFFF     jmp     003D1240  //跳到OEP

      13.5.2 Dump映像文件

       

      停在OEP后, 運行LordPE, 在進程窗口選擇loaddll.exe進程, 在下方窗口中的EdrLib.dll模塊上單擊右鍵, 執行“dump full”菜單命令, 將文件抓取并保存到文件里, 如圖13.43所示。

       

      dll.gif

      圖13.45 抓取DLL內存映像

       

      對于DLL文件來說, Windows系統沒有辦法保證每一次運行時提供相同的基地址。 如果DLL基址所在內存空間被占用或該區域不夠大, 系統會尋找另一個地址空間的區域來映射DLL, 此時外殼將對DLL執行某些重定位操作。 從圖13.43得知, 此時DLL被映射到內存的地址是03D000h, 與EdrLib.dll默認的基址400000h不同, 被重定位項所指向的地方是已經重定位了的代碼數據。

      例如這句:

       

      代碼:

      003D1266     A1 58B43D00        mov     eax, dword ptr [3DB458]

      為了得到與加殼前一樣的文件, 必須找到重定位的代碼, 跳過它, 讓其不被重定位。 重新加載DLL, 對上句重定位的地址3D1267h下內存寫斷點, 中斷幾下, 就可來到重定位的處理代碼。

       

       

      代碼:

      003DE79E  mov     al, byte ptr [edi]              ;指向UPX自己加密過的重定位表

      003DE7A0  inc     edi                                  ;指針移向下一位

      003DE7A1  or      eax, eax                            ;EAX=0?結束標志

      003DE7A3  je      short 003DE7C7              

      003DE7A5  cmp     al, 0EF

      003DE7A7  ja      short 003DE7BA                  

      003DE7A9  add     ebx, eax                          ;EBX的初值為(0xFFC+基址)

      003DE7AB  mov     eax, dword ptr [ebx]             ;EBX指向需要重定位的數據, 取出放到EAX

      003DE7AD  xchg    ah, al

      003DE7AF  rol     eax, 10

      003DE7B2  xchg    ah, al

      003DE7B4  add     eax, esi                          ; ESI指向UPX0區塊的VA, 本例=3D1000

      003DE7B6  mov     dword ptr [ebx], eax           ;重定位

      003DE7B8  jmp     short 003DE79C             

      003DE7BA  and     al, 0F

      003DE7BC  shl     eax, 10

      003DE7BF  mov     ax, word ptr [edi]

      003DE7C2  add     edi, 2

      003DE7C5  jmp     short 003DE7A9           

      003DE7C7  mov     ebp, dword ptr [esi+E044]        ;改好ESI為401000后, 按F4到這里

      UPX殼己將原基址重定位表清零, 重定位操作時, 使用其自己的重定位表。 地址3DE7B4h處ESI指向UPX0區塊的VA, 本例為3D1000h, 為了讓代碼以默認ImageBase的值400000h重定位代碼, 可以在這句強制將ESI的值改為401000h。 來到這句后, 雙擊ESI寄存器, 改成401000h, 然后按F4來到3DE7C7h這時。 此時代碼段的數據沒被重定位, 可以Dump了。

       

      代碼:

      003D1253     833D 68AD4000 00     cmp     dword ptr [40AD68], 0

      運行LordPE將DLL映像抓取, 并保存為upx_dumped.dll。

       

      13.5.3 重建DLL的輸入表

       

      ImportREC能很好地支持DLL的輸入表的重建, 首先, 在Options里將“Use PE Header From Disk”默認的選項去除。 這是因為ImportREC需要獲得基址計算RVA值, DLL如果重定位了, 從磁盤取默認基址計算會導致結果錯誤。

       

      1)在ImportREC下拉列表框中選擇DLL裝載器的進程, 此處為loaddll.exe進程。

      2)單擊“Pick DLL”按鈕, 在DLL進程列表中選擇EdrLib.dll進程(見圖13.47)。

       

      dll2.gif

      圖13.47 選擇DLL進程

      3)在OEP處, 填上DLL入口的RVA值1240h, 單擊IAT AutoSearch按鈕獲取IAT地址。 如果失敗, 必須手工判斷DLL的IAT位置和大小, 其RVA為7000h, Size為E8h。

      4)單擊“Get Import”按鈕, 讓其分析IAT結構重建輸入表。

      5)勾選Add new section, 單擊“Fix Dump”按鈕, 并選擇剛抓取的映像文件dumped.dll, 它將創建一個dumped_.dll文件。

       

      13.5.4 構造重定位表

       

      原理請參考本文開始處的說明。

      先來回顧一個重定位表的結構:

       

      代碼:

      IMAGE_BASE_RELOCATION STRUCT

          VirtualAddress    dd    0

          SizeOfBlock        dd    0

          Type1            dw    0; 其中:Bit15—Bit12為類型 type, Bit11--Bit0 為ItemOffset

      IMAGE_RELOCATION ENDS

      重定位表以1000h大小為一個段, 因為ItemOffset最長為12位, 即剛好為1000h。 如果還有更多段, 將重復上面數據結構, 直到VirtualAddress為NULL, 表示結束。

      ReloREC工具可以根據一組重定位的RVA, 重新構造一個新的重定位表。 首先要做的工作是將UPX外殼這些要重定位的RVA提取出來。

       在處理重定位代碼語句中, 下面這句就是對代碼重定位, 其中EBX保存的就是要重定位的地址。

       

      代碼:

      003DE7B6     mov     dword ptr [ebx], eax      ;EBX指向要重定位的RVA

      補丁的思路是找塊代碼空間, 跳過去執行補丁代碼, 將重定位的地址轉成RVA, 并保存下來。 如下語句跳到補丁代碼處:

       

      代碼:

      003DE7B8   jmp     short 003DE80A

      我們鍵入的補丁代碼:

      003DE80A   pushad

      003DE80B   mov     edx, dword ptr [3E0000]    ;從全局變量3E0000h取一地址指針

      003DE811   sub     ebx, 3D0000                  ;減外殼基址, 將ebx中的地址轉成RVA

      003DE817   mov     dword ptr [edx], ebx       ;將獲得的RVA保存下來

      003DE819   add     edx, 4                        ;指向下一個DWRD地址

      003DE81C   mov     dword ptr [3E0000], edx  ;將指針保存到全局變量中

      003DE822   popad

      003DE823   jmp     003DE79C                       ;跳回外殼代碼

      3E0000h這個地址是OllyDbg的插件HideOD臨時分配的, 其初始值設為3E0010h, 如圖13.71。

      dll3.gif

       

       補丁代碼鍵入完成后, 外殼在處理重定位相關代碼時, 這段補丁代碼將需要重定位的RVA全部提取出來。 執行完補丁代碼, 數據窗口將保存需要重定位的RVA,

       將需要重定位的RVA復制出來(選取數據時, 最后一個DWORD數據是0), 操作時單擊鼠標右鍵, 執行菜單Binary/Binary copy(二進制復制)功能, 再運行WinHex, 新建一文檔, 將這段二進制數據粘貼進去, 粘貼時, 選擇ASCII Hex模式(圖13.52), 然后將提取的數據保存為Relo.bin。

      Relo.bin中保存的就是需要重定位的地址, 以RVA表示。 部分數據如下:

      代碼:

      0000101D

      00001031

      0000106E

      0000108D

      000010A1

      000010DE

      000010FB

      00001109

      0000110F

      ……

      ReloREC這款工具, 就是根據這些RVA重新生成一份新的重定位表

       準備工作完成, 運行ReloREC, 將Relo.bin拖放到ReloREC主界面上可打開此文件, 如圖13.53。 然后在dumped_.dll里找一塊空白代碼處保存重定位表(一般在UPX1或UPX2區塊里找), 在這選擇C000h處。 在Relocation's RVA域里填上原始重定位表的RVA地址, 本例為C000h, 最后單擊“Fix Dump”按鈕, 打開上節剛修復輸入表的dumped_.dll文件, 即可完成重定位表的修復。


      上面是電腦上網安全的一些基礎常識,學習了安全知識,幾乎可以讓你免費電腦中毒的煩擾。




      標簽:DLL文件脫殼 
      日韩精品一区二区三区高清