// PEDemo.cpp : Defines the entry point for the console application.
// I think this is a good starting to learn PE. Src attached here is with security check code stripped out.
// It is the simpliest way to dump out an imported table of a .Dll or .EXE.
#include "stdafx.h"
#include "windows.h"
#include "Dbghelp.h"
#pragma comment(lib, "Dbghelp.lib")
DWORD RVA2Offset(PIMAGE_NT_HEADERS pNTHeader, LPVOID pFileBase, DWORD dwRVA);
int _tmain(int argc, _TCHAR* argv[])
{
PIMAGE_DOS_HEADER pDosHeader;
PIMAGE_NT_HEADERS pNTHeader;
PIMAGE_FILE_HEADER pFileHeader;
PIMAGE_OPTIONAL_HEADER pOptionalHeader;
TCHAR * filename = _T("C:\\WINDOWS\\notepad.exe");
HANDLE hFile = CreateFile(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);
HANDLE hMappingFile = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
LPVOID pFileBase = MapViewOfFile(hMappingFile, FILE_MAP_READ, 0, 0, 0);
pDosHeader = (PIMAGE_DOS_HEADER)pFileBase;
pNTHeader = (PIMAGE_NT_HEADERS)((BYTE*)pFileBase + pDosHeader->e_lfanew); // e_lfanew is a File Address.
pFileHeader = &pNTHeader->FileHeader;
pOptionalHeader = &pNTHeader->OptionalHeader;
// Need to convert RVA to File Offset first
DWORD dwRVA = pOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
DWORD dwOffset = RVA2Offset(pNTHeader, pFileBase, dwRVA);
PIMAGE_IMPORT_DESCRIPTOR pDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)((BYTE*) pFileBase + dwOffset);
while (pDescriptor->OriginalFirstThunk != 0)
{
char * dllname = (char*)((BYTE*)pFileBase + RVA2Offset(pNTHeader, pFileBase, pDescriptor->Name));
printf("Dll Name: %s\n", dllname);
PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA)((BYTE*)pFileBase + RVA2Offset(pNTHeader, pFileBase, pDescriptor->OriginalFirstThunk));
while (pThunk->u1.Function)
{
// u1.AddressOfData is the RVA of IMAGE_IMPORT_BY_NAME
char * functionname = (char*)((BYTE*)pFileBase + RVA2Offset(pNTHeader, pFileBase, (DWORD)pThunk->u1.AddressOfData + 2));
BYTE * functionordinal = (BYTE*)((BYTE*)pFileBase + RVA2Offset(pNTHeader, pFileBase, (DWORD)pThunk->u1.AddressOfData));
printf("\t%X\t%s\n", *functionordinal, functionname);
pThunk++;
}
pDescriptor++;
}
UnmapViewOfFile(pFileBase);
CloseHandle(hMappingFile);
CloseHandle(hFile);
return 0;
}
DWORD RVA2Offset(PIMAGE_NT_HEADERS pNTHeader, LPVOID pFileBase, DWORD dwRVA)
{
DWORD dwOffset;
// Need to convert RVA to File Offset first
PIMAGE_SECTION_HEADER pSectionHeader = ImageRvaToSection(pNTHeader, pFileBase, dwRVA);
dwOffset = dwRVA + pSectionHeader->PointerToRawData – pSectionHeader->VirtualAddress;
return dwOffset;
}