讀書筆記_windows下的混合鉤子(HOOK)_part 2

來源:互聯網
上載者:User

 

讀書筆記_windows下的混合鉤子(HOOK)_part 2

1.       分析PE檔案

下面接著看如果分析PE檔案,從而找到其要匯入的DLL。

首先看PE檔案的匯入資料.idata段。.idata段是匯入資料,包括匯入庫和匯入位址名稱表。在WINNT.H中所定義的資料目錄為:

// 目錄入口

// 匯出目錄

#define IMAGE_DIRECTORY_ENTRY_EXPORT 0

// 匯入目錄

#define IMAGE_DIRECTORY_ENTRY_IMPORT 1

// 資來源目錄

#define IMAGE_DIRECTORY_ENTRY_RESOURCE 2

// 異常目錄

#define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3

// 安全目錄

#define IMAGE_DIRECTORY_ENTRY_SECURITY 4

// 重定位基本表

#define IMAGE_DIRECTORY_ENTRY_BASERELOC 5

// 調試目錄

#define IMAGE_DIRECTORY_ENTRY_DEBUG 6

// 描述字串

#define IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7

// 機器值(MIPS GP)

#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8

// TLS目錄

#define IMAGE_DIRECTORY_ENTRY_TLS 9

// 載入配置目錄

#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10

在分析PE時,首先要得到匯入段(即DataDirectory的IMAGE_DIRECTROY_ENTRY_IMPORT)的RVA。將RVA與模組在記憶體中的起始地址相加(基地址),就會得到虛擬位址,這個地址也就是指向IMAGE_IMPORT_DESCRIPTOR的指標。

關於IMAGE_IMPORT_DESCRIPTOR的描述如下:

   IMAGE_IMPORT_DESCRIPTOR是在匯入段中(Imports Section)中,DataDirectory 入口的匯入點都是指向IMAGE_IMPORT_DESCRIPTOR結構的,具體的結構如下表所示:

Size

Member

Description

DWORD

OriginalFirstThunk

This field is badly named. It contains the RVA of the Import Name Table (INT). This is an array of IMAGE_THUNK_DATA structures. This field is set to 0 to indicate the end of the array of IMAGE_IMPORT_DESCRIPTORs.

DWORD

TimeDateStamp

This is 0 if this executable is not bound against the imported DLL. When binding in the old style (see the section on Binding), this field contains the time/date stamp (number of seconds since 1/1/1970 GMT) when the binding occurred. When binding
in the new style, this field is set to -1.

DWORD

ForwarderChain

This is the Index of the first forwarded API. Set to -1 if no forwarders. Only used for old-style binding, which could not handle forwarded APIs efficiently.

DWORD

Name

The RVA of the ASCII string with the name of the imported DLL.

DWORD

FirstThunk

Contains the RVA of the Import Address Table (IAT). This is array of IMAGE_THUNK_DATA structures.

每個匯入執行塊都有一個IMAGE_IMPORT_DESCRIPTOR結構。

     通過得到第一個IMAGE_IMPORT_DESCRIPTOR結構後,由於所有的DLL都具有相應的IMAGE_IMPORT_DESCRIPTOR結構,當發現Characteristics域為0的結構時,就已經達到該模組所匯入的最後一個DLL。

     每個IMAGE_IMPORT_DESCRIPTOR結構中包含指向兩個獨立數組的指標。其中一個是該模組從給定的DLL中匯入的所有函數的地址資料指標,通過IMAGE_IMPORT_DESCRIPTOR的FirstThunk成員到達該地址表,IMAGE_IMPORT_DESCRIPTOR中的OriginalFirstThunk用於尋找指向IMAGE_IMPORT_BY_NAME結構的指標數組,這些結構包含了被匯入函數的名稱,除非函數是根據序號匯入的。

2. HookImportsOfImage函數

來看HookImportsOfImage函數,它的功能是掃描所有模組,確定它們是否從Kernel32.dll匯入了GetProcAddress函數,如果發現了這個IAT,可以首先修改IAT的記憶體保護機制,改變許可權後就使用鉤子重寫IAT中的地址。來具體看HookImportsOfImage函數,

NTSTATUS HookImportsOfImage ( PIMAGE_DOS_HEADER image_addr, HANDLE h_proc)

{

              PIMAGE_DOS_HEADER dosHeader;

              PIMAGE_NT_HEADERS pNTHeader;

              PIMAGE_IMPORT_DESCRIPTOR importDesc;

              PIMAGE_IMPORT_BY_NAME p_ibn;

              DWORD importsStartRVA;

              PWORD pd_IAT, pd_INTO;

              int count, index;

              char *dll_name = NULL;

              char *pc_dlltar = "kernel32.dll";

              char *pc_fnctar = "GetProcAddress";

              PMDL p_mdl;

              PDWORD MappedImTable;

              dosHeader = (PIMAGE_DOS_HEADER) image_addr;

 

              pNTHeader = MakePtr ( PIMAGE_NT_HEADERS, dosHeader, dosHeader->e_lfanew );

 

              // First, verify that the e_lfanew field gave us a reasonable

              // pointer, then verify the PE signature.

              if ( pNTHeader->Signature != IMAGE_NT_SIGNATURE)

                            return STATUS_INVALID_IMAGE_FORMAT;

              importsStartRVA = pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;

 

    if ( !importsStartRVA )

                            return STATUS_INVALID_IMAGE_FORMAT;

 

    importDesc = ( PIMAGE_IMPORT_DESCRIPTOR ) (importsStartRVA + (DWORD)dosHeader);

 

              for(count = 0; importDesc[count].Characteristics != 0; count++)

              {

                            dll_name = (char*)(importDesc[count].Name + (DWORD)dosHeader);

                            pd_IAT = (PDWORD)(((DWORD)dosHeader) + (DWORD)importDesc[count].FirstThunk);

                            pd_INTO = (PDWORD)(((DWORD)dosHeader) + (DWORD)importDesc[count].OriginalFirstThunk);

                            for ( index = 0; pd_IAT[index] != 0; index++)

                            {

                                          // if this is an import by ordinal

                                          // the high bit is set

                                          if((pd_INT[index] & IMAGE_ORDINAL_FLAG) != IMAGE_ORDINAL_FLAG)

                                          {

                                                        p_ibn = (PIMAGE_IMPORT_BY_NAME)(pd_INTO[index] + ((DWORD)dosHeader));

                                                        if((_stricmp(dll_name, pc_dlltar) == 0) && (strcmp(p_ibn->Name, pc_fnctar) ==0))

                                                        {

                                                                      // Use the trick you already learned to map a different

                                                                      // virtual address to the same physical page so no permission problems

                                                                      //

                                                                      // Map the memory into our domain so we can change the

                                                                      // permissions on the MDL

                                                                      p_mdl = MmCreateMdl(NULL, &pd_IAT[index], 4);

                                                                      if(!p_mdl)

                                                                                    return STATUS_UNSUCCESSFUL;

                                                                      MmBuildMdlForNonPagedPool(p_mdl);

                                                                      // Change the flags of MDL

                                                                      p_mdl->MdlFlags = p_mdl->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA;

                                                                      MappedImTable = MmMapLocakedPages(p_mdl, KernelMode);

 

                                                                      // Address of the "new function"

                                                                      *MappedImTable = d_shareM;

                                                                      // Free MDL

                                                                      MmUnmapLoackedPages(MappedImTable, p_mdl);

                                                                      IoFreeMdl(p_mdl);

 

                                                        }

                                          }

                            }

                            return STATUS_SUCCESS;

 

              }

 

HookImportsOfImage是一個回呼函數,每當將一個映像(進程,裝置驅動程式,DLL等)載入到記憶體中是,都會調用它。代碼已經搜尋了每個映像,檢查它是否匯入了鉤子的目標函數,如果找到該目標函數,則替換它在IAT中的地址。

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.