找TELock加殼的Import Table的方法 (6千字)

看雪資料發表於2001-09-29

目的:在記憶體中將FlashFXP未被破壞的IT完整地提取出來
(至於找TELock的OEP、修復的方法等,zombieys、hying、liotta已經講得很詳細了)

第一步:找到IT的位置

找IT自然要依賴於IT的結構特徵。IT是個陣列,陣列中的每個元素是如下的一個結構(#include <winnt.h>),對應著引入的一個DLL:

typedef struct _IMAGE_IMPORT_DESCRIPTOR {
    union {
        DWORD  Characteristics;            // 0 for terminating null import descriptor
        DWORD  OriginalFirstThunk;        // RVA to original unbound IAT (PIMAGE_THUNK_DATA)
    };
    DWORD  TimeDateStamp;                  // 0 if not bound,
                                            // -1 if bound, and real date\time stamp
                                            //    in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND)
                                            // O.W. date/time stamp of DLL bound to (Old BIND)

    DWORD  ForwarderChain;                // -1 if no forwarders
    DWORD  Name;                          //DLL name
    DWORD  FirstThunk;                    // RVA to IAT (if bound this IAT has actual addresses)
} IMAGE_IMPORT_DESCRIPTOR;

PE Loader/unpacker在載入DLL時,過程大致如下:
1、先根據Name用LoadLibraryA載入一個DLL;
2、根據FirstThunk找到IMAGE_IMPORT_BY_NAME陣列,用GetProcAddress取得該DLL中的相應函式的地址填入IAT。FirstThunk就是指向IAT。

typedef struct _IMAGE_IMPORT_BY_NAME {
    WORD    Hint;
    BYTE    Name[1];
} IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME;

找IT的位置的過程和上面的過程有些相反。利用偵錯程式設bpx LoadLibraryA、bpx GetProcAddress斷點,我們能夠直接得到的條件是DLL檔名

字串及該串的記憶體地址、每個函式的Hint和函式名的記憶體地址、IAT的位置(即GetProcAddress的返回值所要寫入的位置),這樣就至少有3條途

徑可以找到IT的位置,一是根據DLL Name(在看雪教學中已有詳細描述),第二條途徑是根據Hint和函式名的地址,第三條則是根據IAT的位置

,這3條途徑用的是同一種方法(這是找IT的一種通用方法,並不限於TELock加的殼)。

1、用BPMB LoadLibraryA X DO "d *(esp+4)"設斷點,看見載入oleaut32.dll:

0023:00533DBC 61656C6F  32337475  6C6C642E  00000000      oleaut32.dll....
0023:00533DCC 69726156  43746E61  676E6168  70795465      VariantChangeTyp
0023:00533DDC 00784565  61560000  6E616972  706F4374      eEx...VariantCop
0023:00533DEC 646E4979  00000000  69726156  43746E61      yInd....VariantC
0023:00533DFC 7261656C  00000000  53737953  6E697274      lear....SysStrin
0023:00533E0C 6E654C67  00000000  46737953  53656572      gLen....SysFreeS
0023:00533E1C 6E697274  00000067  52737953  6C6C4165      tring...SysReAll
0023:00533E2C 7453636F  676E6972  006E654C  79530000      ocStringLen...Sy

2、先嚐試第一條途徑。字串"oleaut32.dll"的RVA為00133DBC,於是在記憶體中搜尋這個RVA,希望能夠找到存放有該RVA值的某個

IMAGE_IMPORT_DESCRIPTOR結構,也就等於是找到了IT。

:s cs:400000 l 178000 bc,3d,13,00
Pattern not found

沒有找到。因為TELock已經把相應位置上的值清0了。(實際上也可以用下一個DLL的檔名來進行搜尋,因為TELock此時尚未處理下一個DLL,

它不可能提前把下一個DLL的IMAGE_IMPORT_DESCRIPTOR結構清掉。)

3、再嘗試第2條途徑。注意到第一個函式VariantChangeTypeEx的Hint的地址是00533DCA,於是搜尋RVA值00133DCA,希望能夠找到FirstThunk

所指向的那個陣列(其實該陣列也就是IAT),進而再找到FirstThunk的位置。

:s cs:400000 l 178000 ca,3d,13,00
Pattern found at 001B:0053328C (0013328C)

找到之後看一下IAT。由於此時還未把GetProcAddress的返回值寫入IAT,所以此時IAT中存放的都是指向IMAGE_IMPORT_BY_NAME的指標(RVA)



:dd 53328c
001B:0053328C 00133DCA  00133DE0  00133DF2  00133E02      .=...=...=...>..
001B:0053329C 00133E12  00133E22  00133E38  00000000      .>..">..8>......
001B:005332AC 00133E5A  00133E68  00133E76  00133E84      Z>..h>..v>...>..
001B:005332BC 00133E98  00000000  00133EBC  00133ECE      .>.......>...>..
001B:005332CC 00133EE2  00133EF6  00133F06  00133F14      .>...>...?...?..
001B:005332DC 00133F24  00133F36  00133F44  00133F58      $?..6?..D?..X?..
001B:005332EC 00133F70  00000000  00133F96  00133FA2      p?.......?...?..
001B:005332FC 00133FAE  00133FBA  00133FC6  00133FDC      .?...?...?...?..

4、再看究竟是哪個FirstThunk指向了上面的IAT。由於該IAT的RVA為0013328C,故

:s cs:400000 l 178000 8c,32,13,00
Pattern found at 001B:0053304C (0013304C)

5、這樣就找到了oleaut32.dll所對應的FirstThunk的位置是0053304C。在此位置附近看一下,就可以找到IT的起始位置為00533000
,長度為0x1CC(問號表示未被對映的記憶體空間;最初的4個IMAGE_IMPORT_DESCRIPTOR結構已經被清除了一部分):

001B:00532FE0 ????????  ????????  ????????  ????????      ................
001B:00532FF0 ????????  ????????  ????????  ????????      ................
001B:00533000 00000000  00000000  00000000  00000000      ................
001B:00533010 001331CC  00000000  00000000  00000000      .1..............
001B:00533020 00000000  0013326C  00000000  00000000      ....l2..........
001B:00533030 00000000  00000000  0013327C  00000000      ........|2......
001B:00533040 00000000  00000000  00000000  0013328C      .............2..
001B:00533050 00000000  00000000  00000000  00133E4C      ............L>..
001B:00533060 001332AC  00000000  00000000  00000000      .2..............
001B:00533070 00133EAE  001332C4  00000000  00000000      .>...2..........
001B:00533080 00000000  00133F88  001332F4  00000000      .....?...2......
001B:00533090 00000000  00000000  001346D4  0013349C      .........F...4..

第二步:找到破壞IT的程式碼

由於TELock清除了IT中指向DLL檔名的RVA,故只要設個bpm斷點,看它什麼時候清這個檔名的,就可以找到破壞IT的程式碼。
第一個DLL檔名的RVA存放在0053300C處,故BPM 00533000+0C W do "dd 533000",

001B:00576C16  8B95BEAF4000        MOV      EDX,[EBP+0040AFBE]
001B:00576C1C  8BB5AEAF4000        MOV      ESI,[EBP+0040AFAE]
001B:00576C22  85F6                TEST      ESI,ESI
001B:00576C24  0F849D030000        JZ        00576FC7
001B:00576C2A  03F2                ADD      ESI,EDX
001B:00576C2C  83A5AAB0400000      AND      DWORD PTR [EBP+0040B0AA],00
001B:00576C33  8B460C              MOV      EAX,[ESI+0C]
001B:00576C36  83660C00            AND      DWORD PTR [ESI+0C],00      //清除指向每個DLL的Name的RVA值
001B:00576C3A  85C0                TEST      EAX,EAX
001B:00576C3C  0F8485030000        JZ        00576FC7
001B:00576C42  03C2                ADD      EAX,EDX
001B:00576C44  8BD8                MOV      EBX,EAX
001B:00576C46  50                  PUSH      EAX
001B:00576C47  FF9518AF4000        CALL      [EBP+0040AF18]
001B:00576C4D  85C0                TEST      EAX,EAX
001B:00576C4F  0F858C000000        JNZ      00576CE1
001B:00576C55  53                  PUSH      EBX

在第一次執行上面CS:00576C36處的AND之前將533000~535FFF之間的內容(共0x3000位元組,不僅包含IT,還包含IAT等)dump出來就行了。
所以覺得TELock目前還沒有ASProtect強

相關文章