HookImportsOfImage function Parsing
The following is the structure of _image_dos_header. it is the header of the dos.exe file under the winnt.h header file.
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;
The pimage_nt_headers structure is as follows. As the header of the PE file, it contains three parts.
Typedef struct _ image_nt_headers {
DWORD signature;
Image_file_header fileheader;
Image_optional_header optionalheader;
} Image_nt_headers, * pimage_nt_headers;
Pimage_import_descriptor previously introduced that the definition in the WINNT. h header file is as follows:
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;
The structure of pimage_import_by_name is as follows:
Typedef struct _ image_import_by_name {
Word hint;
Byte name [1];
} Image_import_by_name, * pimage_import_by_name;
The structure of the above four definitions has been completed. Note that the module name to be hooked is the variable pc_dlltar, and pc_fnctar is the target function to be hooked.
The structure of pmdl is as follows:
// 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) Memory description table, used to describe a Memory area, which contains the starting address, owner process, byte data, and flag of the Memory area.
The execution of specific functions is as follows. Each key statement has a Chinese comment.
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; // Import the PVOID ImageBase variable in the IMAGE_INFO structure. DosHeader = (PIMAGE_DOS_HEADER) image_addr; // Macro, pointer operation PNTHeader = MakePtr (PIMAGE_NT_HEADERS, dosHeader, dosHeader-> e_lfanew ); // Identify whether the file is a standard PE file by using the Signature field of the PE File If (pNTHeader-> Signature! = IMAGE_NT_SIGNATURE) Return STATUS_INVALID_IMAGE_FORMAT; // RVA of the import segment ImportsStartRVA = pNTHeader-> OptionalHeader. DataDirectory [IMAGE_DIRECTORY_ENTRY_IMPORT]. VirtualAddress; If (! ImportsStartRVA) Return STATUS_INVALID_IMAGE_FORMAT; // Add the RVA of the import segment and the starting address (dosHeader) of the module in the memory. // Pointer to the first IMAGE_IMPORT_DESCRIPTOR ImportDesc = (PIMAGE_IMPORT_DESCRIPTOR) (importsStartRVA + (DWORD) dosHeader ); // Filter each IMAGE_IMPORT_DESCRIPTOR For (count = 0; importDesc [count]. Characteristics! = 0; count ++) { // Obtain the dll name of the import module. Dll_name = (char *) (importDesc [count]. Name + (DWORD) dosHeader ); // Obtain IAT Pd_IAT = (PDWORD) (DWORD) dosHeader) + (DWORD) importDesc [count]. FirstThunk ); // Obtain the pointer array pointing to the IMAGE_IMPORT_BY_NAME Structure Pd_INTO = (PDWORD) (DWORD) dosHeader) + (DWORD) importDesc [count]. OriginalFirstThunk ); // Filter in IAT to find the specific dll and function to be hooked 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) { // Obtain the function name Structure P_ibn = (PIMAGE_IMPORT_BY_NAME) (pd_INTO [index] + (DWORD) dosHeader )); // Compare the dll name and function name to find the required 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 // Permissions on the MDL // Modify the Memory attribute to modify the IAT attribute // Modify memory attributes using the MDL method. This will be detailed in future articles. 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" // Point "GetProcAddress" to a defined function * MappedImTable = d_shareM; // Free MDL MmUnmapLoackedPages (MappedImTable, p_mdl ); IoFreeMdl (p_mdl ); } } } Return STATUS_SUCCESS; } |