导入表解析 导入表结构 在程序加载前INT和IAT内容一致指向同样的结构体,但是在程序加载后INT不变但是IAT会变PE加载器填充为函数地址。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 typedef  struct  _IMAGE_IMPORT_DESCRIPTOR  {    union  {         DWORD Characteristics;          DWORD OriginalFirstThunk;			      };     DWORD   TimeDateStamp;				          DWORD   ForwarderChain;					     DWORD   Name;						        DWORD   FirstThunk;					    } IMAGE_IMPORT_DESCRIPTOR; typedef  struct  _IMAGE_THUNK_DATA32  {    union  {         PBYTE  ForwarderString;         			         PDWORD Function;               				         DWORD Ordinal;                 				         PIMAGE_IMPORT_BY_NAME  AddressOfData;  		  	} u1; } IMAGE_THUNK_DATA32; typedef  struct  _IMAGE_IMPORT_BY_NAME  {    WORD    Hint;	     BYTE    Name[1 ]; } IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME; 
导入表_IMAGE_IMPORT_DESCRIPTOR中主要包含了
Name导入模块的名称OriginalFirstThunk记录函数名称的IAT表(加载前和INT相同)FirstThunk记录函数地址的INT表 
完整解析导入表 
PE -> DOS -> NT -> OPT -> section[1]导入表 -> IAT/INT -> PIMAGE_IMPORT_BY_NAME、Address
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 #include  <Windows.h>  #include  <stdio.h>  #define  PATH L"C:\\Test.dll"  bool  IsPeFile (LPVOID lpFileBuffer) 	PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)lpFileBuffer; 	if  (IMAGE_DOS_SIGNATURE == dosHeader->e_magic) 	{ 		PIMAGE_NT_HEADERS ntHeader = (PIMAGE_NT_HEADERS)((LONG)lpFileBuffer + dosHeader->e_lfanew); 		if  (IMAGE_NT_SIGNATURE == ntHeader->Signature) return  true ; 	} 	return  false ; } DWORD RvaToFoa (DWORD rva, LPVOID lpFileBuffer)  	 	PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)lpFileBuffer; 	PIMAGE_NT_HEADERS ntHeader = (PIMAGE_NT_HEADERS)((LONG)lpFileBuffer + dosHeader->e_lfanew); 	PIMAGE_FILE_HEADER fileHeader = (PIMAGE_FILE_HEADER)&ntHeader->FileHeader; 	PIMAGE_SECTION_HEADER sectionHeader = IMAGE_FIRST_SECTION (ntHeader); 	 	for  (int  i = 0 ; i < fileHeader->NumberOfSections; i++) 	{ 		if  (sectionHeader[i].VirtualAddress <= rva && 			rva <= sectionHeader[i].SizeOfRawData + sectionHeader[i].VirtualAddress) 		{ 			DWORD foa = rva - sectionHeader[i].VirtualAddress + sectionHeader[i].PointerToRawData; 			return  foa; 		} 	} 	return  0 ; } void  ParseImportTable (LPVOID lpFileBuffer) 	PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)lpFileBuffer; 	PIMAGE_NT_HEADERS ntHeader = (PIMAGE_NT_HEADERS)((LONG)lpFileBuffer + dosHeader->e_lfanew); 	PIMAGE_OPTIONAL_HEADER optHeader = (PIMAGE_OPTIONAL_HEADER)&ntHeader->OptionalHeader; 	 	DWORD importTableRva = optHeader->DataDirectory[1 ].VirtualAddress; 	DWORD importTableFoa = RvaToFoa (importTableRva, lpFileBuffer); 	PIMAGE_IMPORT_DESCRIPTOR importTable = (PIMAGE_IMPORT_DESCRIPTOR)(importTableFoa + (DWORD)lpFileBuffer); 	 	while  (importTable->Name != 0 ) 	{ 		 		DWORD moduleNameFoa = RvaToFoa (importTable->Name, lpFileBuffer); 		PCHAR name = (PCHAR)(moduleNameFoa + (DWORD)lpFileBuffer); 		printf ("导入的模块名称为: %s\n" , name); 		 		DWORD iatFoa = RvaToFoa (importTable->FirstThunk, lpFileBuffer); 		PIMAGE_THUNK_DATA iat = (PIMAGE_THUNK_DATA)(iatFoa + (DWORD)lpFileBuffer); 		while  (iat->u1.AddressOfData != 0 )  		{ 			 			  			bool  isOnlyOrdinal = IMAGE_SNAP_BY_ORDINAL (iat->u1.Ordinal); 			if  (isOnlyOrdinal == false ) 			{ 				DWORD importByNameTableRva = RvaToFoa (iat->u1.AddressOfData, lpFileBuffer); 				PIMAGE_IMPORT_BY_NAME nameTable = (PIMAGE_IMPORT_BY_NAME)(importByNameTableRva + (DWORD)lpFileBuffer); 				printf ("导入函数序号为: 0x%02X , 函数名称为: %s \n" , nameTable->Hint, nameTable->Name); 			} 			else   			{ 				printf ("函数的导入序号为: %x\n" , iat->u1.Ordinal & 0x7FFFFFFF ); 			} 			iat++; 		} 		importTable++; 	} } int  main () 	 	HANDLE hFile = CreateFile ( 		PATH, 		GENERIC_READ | GENERIC_WRITE, 		FILE_SHARE_READ, 		NULL , 		OPEN_EXISTING, 		FILE_ATTRIBUTE_NORMAL, 		NULL  	); 	if  (hFile == INVALID_HANDLE_VALUE) 	{ 		printf ("打开文件失败" ); 		system ("pause" ); 		return  0 ; 	} 	 	DWORD real_size = 0 ; 	DWORD file_size = GetFileSize (hFile, NULL ); 	char * pFileBuffer = new  char [file_size]; 	ReadFile (hFile, pFileBuffer, file_size, &real_size, NULL ); 	CloseHandle (hFile);  	 	if  (IsPeFile (pFileBuffer) == true ) 	{ 		printf ("是有效的PE文件\n" ); 		ParseImportTable (pFileBuffer); 	} 	else  	{ 		printf ("不是有效的PE文件\n" ); 	} 	system ("pause" ); 	return  0 ; } 
导出表解析 导出表结构 
name -> ordinal -> address / address -> ordinal -> name // 序号表用作名称和地址转换和函数标识
 
上述已经解析过PE头,这里直接就展示核心函数,解析导出表。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 void  get_export_information (LPVOID fileBuff) 	 	PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)fileBuff; 	PIMAGE_NT_HEADERS ntHeader = (PIMAGE_NT_HEADERS)((LONG)fileBuff + dosHeader->e_lfanew); 	PIMAGE_OPTIONAL_HEADER optHeader = (PIMAGE_OPTIONAL_HEADER)&ntHeader->OptionalHeader; 	DWORD exportTableRva = optHeader->DataDirectory[0 ].VirtualAddress; 	DWORD exportTableFoa = RvaToFoa (exportTableRva, fileBuff); 	PIMAGE_EXPORT_DIRECTORY exportTable = (PIMAGE_EXPORT_DIRECTORY)((DWORD)fileBuff + exportTableFoa); 	 	DWORD exportTableModuleName = RvaToFoa (exportTable->Name, fileBuff); 	printf ("模块的名称为:%s\n" , exportTableModuleName + (DWORD)fileBuff); 	 	DWORD base = exportTable->Base; 	 	DWORD exportOrdinalTableRva = RvaToFoa (exportTable->AddressOfNameOrdinals, fileBuff); 	PWORD ordinalTable = (PWORD)(exportOrdinalTableRva + (DWORD)fileBuff); 	 	DWORD exportNameTableRva = RvaToFoa (exportTable->AddressOfNames, fileBuff); 	PDWORD nameTable = (PDWORD)(exportNameTableRva + (DWORD)fileBuff); 	 	DWORD exportAddressTable = RvaToFoa (exportTable->AddressOfFunctions, fileBuff); 	PDWORD addressTable = (PDWORD)(exportAddressTable + (DWORD)fileBuff); 	 	for  (int  index = 0 ; index < exportTable->NumberOfFunctions; index++) 	{ 		int  i = 0 ; 		bool  isNameExport = false ; 		for  (; i < exportTable->NumberOfNames; i++)  		{ 			if  (index == ordinalTable[i])  									     			{ 				isNameExport = true ;  				break ; 			} 		} 		if  (isNameExport)  		{ 			DWORD nameRva = nameTable[i]; 			DWORD nameFoa = RvaToFoa (nameRva, fileBuff); 			printf ("函数名称为:%s\n" , nameFoa + (DWORD)fileBuff); 		} 		else  if  (addressTable[index] != 0 )  		{ 			printf ("函数名字为 NULL, 地址RVA为:0x%08X\n" , addressTable[index]); 		} 	} } 
三个表之间的寻找对应关系如下图所示:
参考文章
 
https://blog.csdn.net/Apollon_krj/article/details/77417063 
https://blog.51cto.com/u_15744744/6121082 
《加密与解密》