讀書筆記_windows下的混合鉤子(HOOK)_part 3_HookImportsOfImage函數解析

來源:互聯網
上載者:User

HookImportsOfImage函數解析

以下是_IMAGE_DOS_HEADER的結構,是在winnt.h標頭檔下的,指的是DOS.exe檔案的頭

typedef struct _IMAGE_DOS_HEADER {      // DOS .EXE header

    WORD   e_magic;                     // Magic number

    WORD   e_cblp;                      // Bytes on last page of file

    WORD   e_cp;                        // Pages in file

    WORD   e_crlc;                      // Relocations

    WORD   e_cparhdr;                   // Size of header in paragraphs

    WORD   e_minalloc;                  // Minimum extra paragraphs needed

    WORD   e_maxalloc;                  // Maximum extra paragraphs needed

    WORD   e_ss;                        // Initial (relative) SS value

    WORD   e_sp;                        // Initial SP value

    WORD   e_csum;                      // Checksum

    WORD   e_ip;                        // Initial IP value

    WORD   e_cs;                        // Initial (relative) CS value

    WORD   e_lfarlc;                    // File address of relocation table

    WORD   e_ovno;                      // Overlay number

    WORD   e_res[4];                    // Reserved words

    WORD   e_oemid;                     // OEM identifier (for e_oeminfo)

    WORD   e_oeminfo;                   // OEM information; e_oemid specific

    WORD   e_res2[10];                  // Reserved words

    LONG   e_lfanew;                    // File address of new exe header

  } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;

PIMAGE_NT_HEADERS結構如下所示,作為PE檔案的頭,包含了三部分內容。

typedef struct _IMAGE_NT_HEADERS {

  DWORD                 Signature;

  IMAGE_FILE_HEADER     FileHeader;

  IMAGE_OPTIONAL_HEADER OptionalHeader;

} IMAGE_NT_HEADERS, *PIMAGE_NT_HEADERS;

PIMAGE_IMPORT_DESCRIPTOR之前介紹過,在winnt.h標頭檔中的定義如下:

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;

    DWORD   FirstThunk;                     // RVA to IAT (if bound this IAT has actual addresses)

} IMAGE_IMPORT_DESCRIPTOR;

typedef IMAGE_IMPORT_DESCRIPTOR UNALIGNED *PIMAGE_IMPORT_DESCRIPTOR;

 

PIMAGE_IMPORT_BY_NAME的結構如下所示:

typedef struct _IMAGE_IMPORT_BY_NAME {

    WORD    Hint;

    BYTE    Name[1];

} IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME;

 

以上四個定義的結構已經完成,注意變數pc_dlltar要hook的模組名稱,pc_fnctar為要hook的目標函數。

PMDL的結構如下:

// MDL references defined in ntddk.h
typedef struct _MDL {
        struct _MDL *Next;
        CSHORT Size;
        CSHORT MdlFlags;
        struct _EPROCESS *Process;
        PVOID MappedSystemVa;
        PVOID StartVa;
        ULONG ByteCount;
        ULONG ByteOffset;
} MDL, *PMDL;
// MDL Flags

MDL(Memory Descriptor List)記憶體描述表,用來描述一塊記憶體地區,其中包含了該記憶體地區的起始地址、擁有者進程、位元組資料以及標誌。

具體函數的執行如下,每個關鍵語句都有中文注釋

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;

              // 匯入的是IMAGE_INFO結構中的 PVOID ImageBase變數

dosHeader = (PIMAGE_DOS_HEADER) image_addr;

 

              // 宏,對指標的操作

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

 

              // 通過PE檔案的Signature欄位來判斷該檔案是否是標準的PE檔案

              if ( pNTHeader->Signature != IMAGE_NT_SIGNATURE)

                            return STATUS_INVALID_IMAGE_FORMAT;

     // 匯入段的RVA

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

 

    if ( !importsStartRVA )

                            return STATUS_INVALID_IMAGE_FORMAT;

// 匯入段的RVA與模組在記憶體中的起始地址(dosHeader)相加,得到

// 指向第一個IMAGE_IMPORT_DESCRIPTOR的指標

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

     // 過濾每個IMAGE_IMPORT_DESCRIPTOR

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

              {

                            // 得到匯入模組的dll的名稱

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

// 得到IAT

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

          // 得到指向IMAGE_IMPORT_BY_NAME結構的指標數組

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

          // IAT中的過濾,找到特定的dll與要hook的函數

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

                            {

                                          // if this is an import by ordinal

                                          // the high bit is set

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

                                          {

                                                        // 得到函數名結構

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

// 對比dll名與函數名,找到所需要的

                                                        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

                           // 改變記憶體屬性,以便修改IAT屬性

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

                          // 將“GetProcAddress”指向自己定義的函數

                                                                      *MappedImTable = d_shareM;

                                                                      // Free MDL

                                                                      MmUnmapLoackedPages(MappedImTable, p_mdl);

                                                                      IoFreeMdl(p_mdl);

 

                                                        }

                                          }

                            }

                            return STATUS_SUCCESS;

 

              }

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.