pe结构学习心得(四)--获取导入表
// PEImportTable.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <windows.h>
#include <time.h>
#include <imagehlp.h>
#pragma comment (lib, "imagehlp.lib")
int _tmain(int argc, _TCHAR* argv[])
{
while (TRUE) {
WCHAR cFile[256] = {0};
printf("Please enter the file name and path:");
wscanf(L"%s",cFile);
HANDLE hFile = NULL;
hFile = ::CreateFile((LPCWSTR)cFile,GENERIC_READ,0,NULL,OPEN_EXISTING,NULL,NULL);
if (hFile == INVALID_HANDLE_VALUE){
printf("Create file failed! (%d).\n\n", GetLastError());
system("pause");
return 0;
}
//创建文件映射
HANDLE hMap = NULL;
hMap = ::CreateFileMapping(hFile,NULL,PAGE_READONLY,0,0,0);
if (!hMap){
printf("Create file mapping failed! (%d).\n\n", GetLastError());
system("pause");
return 0;
}
//映射要自己进程的空间
LPVOID pMap = NULL;
pMap = ::MapViewOfFile(hMap,FILE_MAP_READ,0,0,0);
if (!pMap){
printf("Mapping file failed (%d).\n\n", GetLastError());
system("pause");
return 0;
}
//后面计算文件偏移的时候要用到的
ULONG dwImageBase = (ULONG)pMap;
//获得DOS头文件指针
PIMAGE_DOS_HEADER pDosHeader = NULL;//DOS头文件
pDosHeader = (PIMAGE_DOS_HEADER)pMap;
//判断DOS头标志 IMAGE_DOS_SIGNATURE 0x5A4D MZ
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE){
printf("Not DOS Header! (%d).\n\n", GetLastError());
system("pause");
return 0;
}
//获得PE头文件指针
PIMAGE_NT_HEADERS pPeHeaders = NULL;//PE头文件
pPeHeaders = (PIMAGE_NT_HEADERS)((LONG)pMap + pDosHeader->e_lfanew);
//判断PE头标志 IMAGE_NT_SIGNATURE 0x00004550 PE00
if (pPeHeaders->Signature != IMAGE_NT_SIGNATURE){
printf("Not PE Header! (%d).\n\n", GetLastError());
system("pause");
return 0;
}
//获得输入表指针
//这个函数返回的是内存映像中的文件偏移量
PIMAGE_IMPORT_DESCRIPTOR pImportTable = (PIMAGE_IMPORT_DESCRIPTOR)::ImageRvaToVa(pPeHeaders, pMap, pPeHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress, NULL);
//tm *pTime; //时间结构,用于返回一个格林威治时间
//如果没有输入表就打印信息并返回
if (pImportTable == NULL) {
printf("Can't find import table!\n\n");
system("pause");
return 0;
}
//打印输入表
printf("Image import table infomation:\n");
printf("-------------------------------------------------------------------\n");
for (int i = 0; pImportTable->Name != NULL; i++){
//pTime = gmtime((time_t *)::ImageRvaToVa(pPeHeaders, pMap, pImportTable->TimeDateStamp, NULL)); //把时间戳转换为字符串
//打印IMAGE_IMPORT_DESCRIPTOR结构的一些信息
printf("%d. IMAGE_IMPORT_DESCRIPTOR\n\tOriginalFirstThunk:\t0x%08x\tOffset:0x%08x\n\tTimeDateStamp:\t\t0x%08x\t%s\n\tForwarderChain:\t\t0x%08x\n\tName:\t\t\t0x%08x\tOffset:0x%08x\t%s\n\tFirstThunk:\t\t0x%08x\tOffset:0x%08x\n\n",
i + 1,
pImportTable->OriginalFirstThunk, (ULONG)::ImageRvaToVa(pPeHeaders, pMap, pImportTable->OriginalFirstThunk, NULL) - dwImageBase, //减去起始地址才是在文件中的偏移量
pImportTable->TimeDateStamp, "GMT",
pImportTable->ForwarderChain,
pImportTable->Name, (ULONG)::ImageRvaToVa(pPeHeaders, pMap, pImportTable->Name, NULL) - dwImageBase, //RVA & Offset
::ImageRvaToVa(pPeHeaders, pMap, pImportTable->Name, NULL), //字符串
pImportTable->FirstThunk, (ULONG)::ImageRvaToVa(pPeHeaders, pMap, pImportTable->FirstThunk, NULL) - dwImageBase); //减去起始地址才是在文件中的偏移量
//打印输出函数列表
//注意有的时候pImportTable->OriginalFirstThunk会是NULL值,这个时候pImageThunkData就要取pImportTable->OriginalFirstThunk
PIMAGE_THUNK_DATA pImageThunkData = (PIMAGE_THUNK_DATA)::ImageRvaToVa(pPeHeaders, pMap, pImportTable->OriginalFirstThunk, NULL) != NULL ? (IMAGE_THUNK_DATA *)::ImageRvaToVa(pPeHeaders, pMap, pImportTable->OriginalFirstThunk, NULL) : pImageThunkData = (IMAGE_THUNK_DATA *)::ImageRvaToVa(pPeHeaders, pMap, pImportTable->FirstThunk, NULL);
PIMAGE_IMPORT_BY_NAME pImageImportByName = NULL;
printf("\tHint\t\tAPI Name\n");
printf("\t-----------------------------------------------------------\n");
for (int j = 0; pImageThunkData->u1.AddressOfData != NULL ; j++){
if (!(pImageThunkData->u1.AddressOfData & IMAGE_ORDINAL_FLAG)) { //IMAGE_THUNK_DATA如果最高位为0,名字
pImageImportByName = (PIMAGE_IMPORT_BY_NAME)::ImageRvaToVa(pPeHeaders, pMap, pImageThunkData->u1.AddressOfData, NULL);
printf("\t0x%08x\t%s\n", pImageImportByName->Hint, pImageImportByName->Name);
}
else { //IMAGE_THUNK_DATA如果最高位为1,序号--pImageThunkData->u1.AddressOfData的低16位就是序号
printf("\t0x%08x\n", (pImageThunkData->u1.AddressOfData) & 0xffff);
}
pImageThunkData++;
}
printf("\n");
pImportTable++;
}
//关闭打开的句柄,释放资源
::UnmapViewOfFile(pMap);
::CloseHandle(hMap);
::CloseHandle(hFile);
}
system("pause");
return 0;
}
