windows下一些Structure定义(pe、IMAGE_IMPORT_DESCRIPTOR

=================================
Structure of Import Symbols table
=================================
A portable executable (PE) file contains 

 IMAGE_NT_HEADERS
 
 This struct's members are:
 
	DWORD Signature
	IMAGE_FILE_HEADER FileHeader
	IMAGE_OPTIONAL_HEADER OptionalHeader	// not really optional, fyi

Then 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 table
is -- 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
-------------------------------------
0xc810	FirstThunk		:			0
0xc80c	Name			:			0
0xc808	ForwarderChain		:			0
0xc804	TimeDateStamp		:			0
0xc800	OriginalFirstThunk	:			0

-------------------------------------
// 2nd IMAGE_IMPORT_DESCRIPTOR struct
-------------------------------------
0xc7fc	FirstThunk		:			0x8000
0xc7f8	Name			:			0xc398  (the RVA of the name of this module)
0xc7f4	ForwarderChain		:			0
0xc7f0	TimeDateStamp		:			0
0xc7ec	OriginalFirstThunk	:			0xc084

-------------------------------------
// 1st IMAGE_IMPORT_DESCRIPTOR struct
-------------------------------------
0xc7e8	FirstThunk		:			0xc178
0xc7e4	Name			:			0xc2c0  (the RVA of the name of this module)
0xc7e0	ForwarderChain		:			0
0xc7dc	TimeDateStamp		:			0
0xc7d8	OriginalFirstThunk	:			0xc030

All addresses are RVAs.

------------------------------
Now at locations (from above):	
------------------------------
	0xc2c0		contains	"MSVCR80.DLL"
	0xc398		contains	"KERNEL32.DLL"

Now OriginalFirstThunk points to the Import Name Table for the module and
FirstThunk 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 for
each struct in these two tables. This value (AddressOfData) contains the
RVA for an IMAGE_IMPORT_BY_NAME struct. The contents of an IMAGE_IMPORT_NAME
struct 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 Address
Table 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 starts
at 0xc030 (OriginalFirstThunk address above) and our Import Address Table starts
at 0xc178 (FirstThunk address above).

-------------------------------------
So we might have something like this:
-------------------------------------

------------------------------------
// Import Name Table for MSVCR80.dll
------------------------------------
0xc080	AddressOfData		:		0			// null terminate table
...
0xc044	AddressOfData		:		0xc300
0xc040	AddressOfData		:		0xc2f8
0xc03c	AddressOfData		:		0xc2ea
0xc038	AddressOfData		:		0xc2e0
0xc034	AddressOfData		:		0xc2d8
0xc030	AddressOfData		:		0xc2cc

---------------------------------------
// Import Address Table for MSVCR80.dll
---------------------------------------
0xc1c8	AddressOfData		:		0			// null terminate table
...
0xc18c	AddressOfData		:		0xc300
0xc188	AddressOfData		:		0xc2f8
0xc184	AddressOfData		:		0xc2ea
0xc180	AddressOfData		:		0xc2e0
0xc17c	AddressOfData		:		0xc2d8
0xc178	AddressOfData		:		0xc2cc

Note that the AddressOfData values don't increase by a fixed amount; that's 
because the data contained at those addresses is variable length. So what
is the data contained at those addresses?

Starting at 0xc2cc is an array of IMAGE_IMPORT_BY_NAME structs. Each such
struct contains the name of a function (imported by this module which in
this case is MSVCR80.DLL) as well as a "Hint" for this function.

---------------------------------------------------------------------
Continuing the above example, we have the following values in memory:
---------------------------------------------------------------------
...

0xc312	2-byte hint for mbstowcs		
0xc308	"mbstowcs"				// null-terminated is 9 bytes long

0xc306	2-byte hint for fopen
0xc300	"fopen"					// null-terminated is 6 bytes long

0xc2fe	2-byte hint for atoi
0xc2f8	"atoi"					// null-terminated is 5 bytes long

0xc2f6	2-byte hint for _vsnprintf
0xc2ea	"_vsnprintf"				// null-terminated is 11 bytes long

0xc2e8	2-byte hint for _strdup
0xc2e0	"_strdup"				// null-terminated is 8 bytes long

0xc2de	2-byte hint for _open
0xc2d8	"_open"					// null-terminated is 6 bytes long

0xc2d6	2-byte hint for _memccpy		
0xc2cc	"_memccpy"				// null-terminated is 9 bytes long

0xc2c0	"MSVCR80.DLL"				// null-terminated is 12 bytes long

So now you see what the AddressOfData values -- contained in the Import Name
Table and the Import Address Table -- refer to. One small detail, when the
null-terminated name of a function is an odd number, then an extra byte must
be added to the name so that the WORD hint field starts on a WORD-aligned
boundary. This is why, for example, the size of the IMAGE_IMPORT_BY_NAME
struct for _memccpy is 12 bytes even though null-terminated "_memccpy" is
9 bytes and the WORD hint adds 2 bytes (total of 11 bytes); that extra byte
is 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 WHERE
the various functions will exist in the address space (since these functions
are 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 _memccpy
is 0x49F10. Therefore if MSVCR80.dll is loaded in its usual spot then 
the value stored at 0xc178 (which is originally 0xc2cc) will be changed
to ( 0x00360000 + 0x49F10 ) == 0x003a9f10 since that's the address where
the _memccpy code lives in memory at the time this PE is loaded.

Note that because we have *two* copies of this same initial table, after
we 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 know
which function that address corresponds to) we can consult the Import
Name 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 structs
		PIMAGE_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 things

		PBYTE ForwarderString;	// 4 bytes

		PDWORD Function;	// 4 bytes

		DWORD 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 function


	BYTE Name[1];	// 1 byte; contains name of the import function
			// is an ASCIIZ string

} IMAGE_IMPORT_BY_NAME,*PIMAGE_IMPORT_BY_NAME;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值