解析导入表就需要先认识下面这三个结构体 

//导入表结构体
typedef struct _IMAGE_IMPORT_DESCRIPTOR {
	union {
		DWORD   Characteristics;   

		//主要这个,包含指向INT的RVA
		DWORD   OriginalFirstThunk;
	};

	//时间标识
	DWORD   TimeDateStamp;  

	//与转发有关
	DWORD   ForwarderChain;             

	//这就是DLL文件名
	DWORD   Name;

	//IAT的RVA
	DWORD   FirstThunk; 
} IMAGE_IMPORT_DESCRIPTOR, *PIMAGE_IMPORT_DESCRIPTOR;

 

//
typedef struct _IMAGE_THUNK_DATA32 {
	union {

		//转发器有关
		DWORD ForwarderString;

		//IAT有关
		DWORD Function;

		//当前结构高位为1是有关
		DWORD Ordinal;

		//不是上面三个的时候这个就发挥作用
		//指向输入名称表
		DWORD AddressOfData;
	} u1;
} IMAGE_THUNK_DATA32,*PIMAGE_THUNK_DATA32;
//输入名称表
typedef struct _IMAGE_IMPORT_BY_NAME {

	//导入的函数序号
	WORD    Hint;

	//导入的函数名称
	CHAR   Name[1];
} IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME;

 IMAGE_IMPORT_DESCRIPTOR(导入表)仅仅是一个引导者,引导系统找到那两个保存有真正导入信息的结构体,也就是IMAGE_THUNK_DATA和IMAGE_IMPORT_BY_NAME。

实现代码: 


BOOL PEAnalyseSpace::PEAnalyse::ShowImport()
{
	//执行是否成功
	BOOL bRet = FALSE;

	//导入表指针
	PIMAGE_IMPORT_DESCRIPTOR pImport = NULL;

	//指针
	PIMAGE_THUNK_DATA pThunk = NULL;

	//导入名称表指针
	PIMAGE_IMPORT_BY_NAME pName = NULL;

	//字符串指针
	PCHAR pszName = NULL;

	do 
	{
		//没有解析
		if (m_lpBase == NULL)
		{
			break;
		}

		//没有导入导入表,这个是不可能的
		if (m_pNt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size == NULL)
		{
			break;
		}

		//获取导入表
		pImport = (PIMAGE_IMPORT_DESCRIPTOR)
			(RVAtoOffset(m_pNt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)
				+ (DWORD)m_lpBase);

		//循环遍历
		while (pImport->Name)
		{
			//获取导入地址表
			pThunk = (PIMAGE_THUNK_DATA)
				(RVAtoOffset(pImport->OriginalFirstThunk) + (DWORD)m_lpBase);

			//获取模块名字
			pszName = (PCHAR)(RVAtoOffset(pImport->Name) + (DWORD)m_lpBase);


			cout << "Module Name Is: "
				<< pszName
				<< endl;

			//循环遍历地址
			while (pThunk->u1.AddressOfData)
			{
				//判断是序号导入还是名称导入
				//序号
				if (IMAGE_SNAP_BY_ORDINAL32(pThunk->u1.AddressOfData))
				{
					cout << "Index Import -> ID: "
						<< hex
						<< (pThunk->u1.Ordinal & 0xffff)
						<< endl;
				}
				else//名称导入
				{
					//获取导入名称
					pName = (PIMAGE_IMPORT_BY_NAME)
						(RVAtoOffset(pThunk->u1.AddressOfData)
							+ (DWORD)m_lpBase);
					cout << "Name Import -> ID: "
						<< hex
						<< pName->Hint
						<< "\tName: "
						<< pName->Name
						<< endl;
				}
				pThunk++;
			}
			cout << endl;
			pImport++;
		}
		bRet = TRUE;
	} while (FALSE);
	return bRet;
}

 实际效果:

PE文件导入表代码解析

Github:源代码下载

相关文章:

  • 2021-04-23
  • 2021-09-13
  • 2022-12-23
  • 2021-07-28
  • 2022-12-23
猜你喜欢
  • 2021-08-17
  • 2021-12-18
  • 2021-10-23
  • 2021-08-03
  • 2022-12-23
  • 2021-07-13
相关资源
相似解决方案