windows下一些Structure定义(pe、IMAGE_IMPORT_DESCRIPTOR

来源:互联网 发布:高中数学算法程序框图 编辑:程序博客网 时间:2024/06/05 18:09
=================================Structure of Import Symbols table=================================A portable executable (PE) file contains  IMAGE_NT_HEADERS  This struct's members are: DWORD SignatureIMAGE_FILE_HEADER FileHeaderIMAGE_OPTIONAL_HEADER OptionalHeader// not really optional, fyiThen the IMAGE_OPTIONAL_HEADER struct contains:    //    // Standard fields.    //    WORD    Magic;    BYTE    MajorLinkerVersion;    BYTE    MinorLinkerVersion;    DWORD   SizeOfCode;    DWORD   SizeOfInitializedData;    DWORD   SizeOfUninitializedData;    DWORD   AddressOfEntryPoint;    DWORD   BaseOfCode;    DWORD   BaseOfData;    //    // NT additional fields.    //    DWORD   ImageBase;    DWORD   SectionAlignment;    DWORD   FileAlignment;    WORD    MajorOperatingSystemVersion;    WORD    MinorOperatingSystemVersion;    WORD    MajorImageVersion;    WORD    MinorImageVersion;    WORD    MajorSubsystemVersion;    WORD    MinorSubsystemVersion;    DWORD   Reserved1;    DWORD   SizeOfImage;    DWORD   SizeOfHeaders;    DWORD   CheckSum;    WORD    Subsystem;    WORD    DllCharacteristics;    DWORD   SizeOfStackReserve;    DWORD   SizeOfStackCommit;    DWORD   SizeOfHeapReserve;    DWORD   SizeOfHeapCommit;    DWORD   LoaderFlags;    DWORD   NumberOfRvaAndSizes;    IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];    Then the DataDirectory array : 0'th member:Export Symbols 1'st member:Import Symbols 2'nd member:Resources ... 11'th member:Bound Import 12'th member:Import Address Table ... The IMAGE_DATA_DIRECTORY struct consists of two fields:    DWORD   VirtualAddress;// the RVA of the data structure    DWORD   Size;// the size of the data structure    Then if we have a PE that imports two modules, we'll have: (1) one IMAGE_DATA_DIRECTORY structure for Import Symbols  (2) let's say that struct's VirtualAddress is 0xc7d8 -- recall this is an RVA  (3) then 0xc7d8 is where the first IMAGE_IMPORT_DESCRIPTOR lives  (4) since we are importing two modules, there will be 3 IMAGE_IMPORT_DESCRIPTOR     structs in our array (which starts at 0xc7d8, recall)          --> the 3rd IMAGE_IMPORT_DESCRIPTOR is all zeroes      (5) then the Size field above (for this IMAGE_DATA_DIRECTORY) will be 3 *      sizeof( IMAGE_IMPORT_DESCRIPTOR )        The IMAGE_IMPORT_DESCRIPTOR struct consists of five fields :  Union {DWORD Characteristics;PIMAGE_THUNK_DATA OriginalFirstThunk;  };  DWORD TimeDateStamp;  DWORD ForwarderChain;  DWORD Name;  PIMAGE_THUNK_DATA FirstThunk;  --> Each of these fields is 4 bytes long so sizeof( IMAGE_IMPORT_DESCRIPTOR ) is      20 bytes == 0x1C        --> So the Size field will be 60 bytes == 0x3C  Now let's examine the contents of the Import Symbols table; recall that this tableis -- in this case -- an array of 3 IMAGE_IMPORT_DESCRIPTOR structs.Now here are some potential values for the fields:-------------------------------------// 3rd IMAGE_IMPORT_DESCRIPTOR struct-------------------------------------0xc810FirstThunk:00xc80cName:00xc808ForwarderChain:00xc804TimeDateStamp:00xc800OriginalFirstThunk:0-------------------------------------// 2nd IMAGE_IMPORT_DESCRIPTOR struct-------------------------------------0xc7fcFirstThunk:0x80000xc7f8Name:0xc398  (the RVA of the name of this module)0xc7f4ForwarderChain:00xc7f0TimeDateStamp:00xc7ecOriginalFirstThunk:0xc084-------------------------------------// 1st IMAGE_IMPORT_DESCRIPTOR struct-------------------------------------0xc7e8FirstThunk:0xc1780xc7e4Name:0xc2c0  (the RVA of the name of this module)0xc7e0ForwarderChain:00xc7dcTimeDateStamp:00xc7d8OriginalFirstThunk:0xc030All addresses are RVAs.------------------------------Now at locations (from above):------------------------------0xc2c0contains"MSVCR80.DLL"0xc398contains"KERNEL32.DLL"Now OriginalFirstThunk points to the Import Name Table for the module andFirstThunk points to the Import Address Table for the module.Each of these two tables (Import Name and Import Address) consist of an array of IMAGE_THUNK_DATA structs. An IMAGE_THUNK_DATA struct consists of:  Union {PBYTE ForwarderString;PDWORD Function;DWORD Ordinal;PIMAGE_IMPORT_BY_NAME AddressOfData;  };  In our case the Union member "AddressOfData" will be the member used foreach struct in these two tables. This value (AddressOfData) contains theRVA for an IMAGE_IMPORT_BY_NAME struct. The contents of an IMAGE_IMPORT_NAMEstruct are :    WORD Hint;// recall that WORDs are two bytes each    BYTE Name[1];       // this is NOT really 1 byte long; This is a variable-sized field   For the PE -- before it's loaded -- the Import Name Table and the Import AddressTable are merely two copies of the same table. For example let's say we're importing twenty or so symbols from MSVCR80.dll then our Import Name Table startsat 0xc030 (OriginalFirstThunk address above) and our Import Address Table startsat 0xc178 (FirstThunk address above).-------------------------------------So we might have something like this:-------------------------------------------------------------------------// Import Name Table for MSVCR80.dll------------------------------------0xc080AddressOfData:0// null terminate table...0xc044AddressOfData:0xc3000xc040AddressOfData:0xc2f80xc03cAddressOfData:0xc2ea0xc038AddressOfData:0xc2e00xc034AddressOfData:0xc2d80xc030AddressOfData:0xc2cc---------------------------------------// Import Address Table for MSVCR80.dll---------------------------------------0xc1c8AddressOfData:0// null terminate table...0xc18cAddressOfData:0xc3000xc188AddressOfData:0xc2f80xc184AddressOfData:0xc2ea0xc180AddressOfData:0xc2e00xc17cAddressOfData:0xc2d80xc178AddressOfData:0xc2ccNote that the AddressOfData values don't increase by a fixed amount; that's because the data contained at those addresses is variable length. So whatis the data contained at those addresses?Starting at 0xc2cc is an array of IMAGE_IMPORT_BY_NAME structs. Each suchstruct contains the name of a function (imported by this module which inthis case is MSVCR80.DLL) as well as a "Hint" for this function.---------------------------------------------------------------------Continuing the above example, we have the following values in memory:---------------------------------------------------------------------...0xc3122-byte hint for mbstowcs0xc308"mbstowcs"// null-terminated is 9 bytes long0xc3062-byte hint for fopen0xc300"fopen"// null-terminated is 6 bytes long0xc2fe2-byte hint for atoi0xc2f8"atoi"// null-terminated is 5 bytes long0xc2f62-byte hint for _vsnprintf0xc2ea"_vsnprintf"// null-terminated is 11 bytes long0xc2e82-byte hint for _strdup0xc2e0"_strdup"// null-terminated is 8 bytes long0xc2de2-byte hint for _open0xc2d8"_open"// null-terminated is 6 bytes long0xc2d62-byte hint for _memccpy0xc2cc"_memccpy"// null-terminated is 9 bytes long0xc2c0"MSVCR80.DLL"// null-terminated is 12 bytes longSo now you see what the AddressOfData values -- contained in the Import NameTable and the Import Address Table -- refer to. One small detail, when thenull-terminated name of a function is an odd number, then an extra byte mustbe added to the name so that the WORD hint field starts on a WORD-alignedboundary. This is why, for example, the size of the IMAGE_IMPORT_BY_NAMEstruct for _memccpy is 12 bytes even though null-terminated "_memccpy" is9 bytes and the WORD hint adds 2 bytes (total of 11 bytes); that extra byteis to align the hint on a WORD boundary.===============================================So why do we have two copies of the same table?===============================================Perceptive question, Watson!These two tables are used by the PE loader to map the function names to addresses when loading the PE. Since we don't know at compile time WHEREthe various functions will exist in the address space (since these functionsare part of DLLs), the loader does that resolution for us. In particular the loader will replace each entry in the Import Address Table (IAT) with the actual address of the function. For example, the first entry in the MSVCR80.DLL IAT is 0xc2cc and that corresponds to "_memccpy". Usually MSVCR80.DLL loads at address 0x00360000,i.e. that's the base address for this DLL. Moreover the RVA for _memccpyis 0x49F10. Therefore if MSVCR80.dll is loaded in its usual spot then the value stored at 0xc178 (which is originally 0xc2cc) will be changedto ( 0x00360000 + 0x49F10 ) == 0x003a9f10 since that's the address wherethe _memccpy code lives in memory at the time this PE is loaded.Note that because we have *two* copies of this same initial table, afterwe replace 0xc2cc in the IAT with the address for _memccpy (as above),if for any reason we need to go in the other direction (i.e. to knowwhich function that address corresponds to) we can consult the ImportName Table at 0xc030 which still contains the RVA 0xc2cc and see that"_memccpy" is the function for this resolved address.
===========================From : C:/lcc/include/win.h===========================//// there's one IMAGE_IMPORT_DESCRIPTOR for every DLL that the PE uses//typedef struct _IMAGE_IMPORT_DESCRIPTOR {union {DWORD Characteristics;// points to Import Name Table (INT)// contains RVA of an array of IMAGE_THUNK_DATA structsPIMAGE_THUNK_DATA OriginalFirstThunk;} ;DWORD TimeDateStamp;DWORD ForwarderChain;DWORD Name;// e.g. "USER32.dll"PIMAGE_THUNK_DATA FirstThunk;// points to IAT} IMAGE_IMPORT_DESCRIPTOR,*PIMAGE_IMPORT_DESCRIPTOR;//// the IAT is an array of IMAGE_THUNK_DATA structs//typedef struct _IMAGE_THUNK_DATA {union {// is one of the following 4 thingsPBYTE ForwarderString;// 4 bytesPDWORD Function;// 4 bytesDWORD Ordinal;// 4 bytes// ------------- is usually this ------------- //PIMAGE_IMPORT_BY_NAME AddressOfData; // 4 bytes} ;} IMAGE_THUNK_DATA,*PIMAGE_THUNK_DATA;//// as above, usually we interpret an IMAGE_THUNK_DATA struct as a POINTER to an :// "IMAGE_IMPORT_BY_NAME" struct//typedef struct _IMAGE_IMPORT_BY_NAME {WORD Hint;// 2 bytes// contaisn index into the export table of the DLL// from which we get (import) this functionBYTE Name[1];// 1 byte; contains name of the import function// is an ASCIIZ string} IMAGE_IMPORT_BY_NAME,*PIMAGE_IMPORT_BY_NAME;