// ShowPE.c
// Show The Main Structures Of the PE file
// Author: thinker
// Date: 11/28/2008
// E-Mail: cnhnyu@gmail.com
// QQ: 94483026
/*********************************************************
PE File Format ------------------------------- <--+ | MZ MS-DOS Header | | ------------------------------- | Dos Headers | MS DOS Stub | | ------------------------------- <--+ | PE00 | | ------------------------------- | | | | | IMAGE_FILE_HEADER | | IMAGE_NT_HEADERS32 ------------------------------- | | | | | IMAGE_OPTIONAL_HEADER32 | | | | | ------------------------------- <--+ | Section Header 1 | | |-----------------------------| | | Section Header 2 | | ------------------------------- | Section Headers | .............. | | |-----------------------------| | | Section Header N | | ------------------------------- <--+ | Section Data 1 | | |-----------------------------| | | Section Data 2 | | ------------------------------- | Section Datas | ............... | | ------------------------------- | | Section Data N | | ------------------------------- <--+
**********************************************************/
#include <stdio.h>
#include <windows.h>
#include <time.h>
// Data Directory Description
char szDataDirectory[16][64] = {
"Export Directory",
"Import Directory",
"Resource Directory",
"Exception Directory",
"Security Directory",
"Base Relocation Table",
"Debug Directory",
"Architecture Specific Data",
"RVA of GP",
"TLS Directory",
"Load Configuration Directory",
"Bound Import Directory in headers",
"Import Address Table",
"Delay Load Import Descriptors",
"COM Runtime descriptor"
};
HANDLE hFile = NULL;
HANDLE hFileMapping = NULL;
void* pFileBase = NULL;
IMAGE_DOS_HEADER *pDosHeader = NULL;
IMAGE_NT_HEADERS *pNTHeader = NULL;
IMAGE_SECTION_HEADER *pSectionHeader = NULL;
DWORD RVA2FileOffset(DWORD dwRVA);
int main(int argc, char **argv)
{
struct tm* ptm;
DWORD dwIndex;
IMAGE_IMPORT_DESCRIPTOR *pImportDescriptor = NULL;
IMAGE_THUNK_DATA *pThunkData = NULL;
IMAGE_IMPORT_BY_NAME *pImportByName = NULL;
IMAGE_EXPORT_DIRECTORY *pExportDirectory = NULL;
DWORD *pdw;
WORD *pw;
if ( argc != 2 )
{
printf("Usage:\n\t%s PEFile\n", argv[0]);
return -1;
}
/*********************** Map the file to memory *************************/
hFile = CreateFile(argv[1], GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE, NULL);
if ( hFile == INVALID_HANDLE_VALUE )
{
printf("Open File Error.\n");
return -1;
}
hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
if ( !hFileMapping )
{
CloseHandle(hFile);
printf("Create File Mapping Error.\n");
return -1;
}
pFileBase = MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, 0);
if ( !pFileBase )
{
CloseHandle(hFileMapping);
CloseHandle(hFile);
printf("Map View Of File Error.\n");
return -1;
}
/*********************** Map end *****************************************/
// get the dos heaader pointer
pDosHeader = (IMAGE_DOS_HEADER*)pFileBase;
if ( pDosHeader->e_magic != IMAGE_DOS_SIGNATURE )
{
printf("Unknow File Format.\n");
goto End;
}
printf("%-35s%s\n\n", "FileName:", argv[1]);
printf("%-35s%#010x\n", "Dos Stub Size:", pDosHeader->e_lfanew - sizeof(IMAGE_DOS_HEADER));
printf("%-35s%#010x\n", "NT File RVA:", pDosHeader->e_lfanew);
// get the nt header pointer
pNTHeader = (IMAGE_NT_HEADERS*)((char*)pFileBase + pDosHeader->e_lfanew);
if ( pNTHeader->Signature != IMAGE_NT_SIGNATURE )
{
printf("Not NT File.\n");
goto End;
}
// get the section header pointer
pSectionHeader = (IMAGE_SECTION_HEADER*)((char*)pNTHeader + sizeof(IMAGE_NT_HEADERS));
printf("\n%-35s%s\n", "nRun Platform:", (pNTHeader->FileHeader.Machine == IMAGE_FILE_MACHINE_I386) ? "Intel 386" : "Other" );
printf("%-35s%d\n", "NumOfSections:", pNTHeader->FileHeader.NumberOfSections);
ptm = localtime(&pNTHeader->FileHeader.TimeDateStamp);
printf("%-35s%02d/%02d/%04d %02d:%02d:%02d\n", "FileCreateTime:", ptm->tm_mon + 1, ptm->tm_mday, ptm->tm_year + 1900,
ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
//printf("%.19s\n", asctime(ptm));
printf("%-35s%#010x\n", "SizeofOptionHdr:", pNTHeader->FileHeader.SizeOfOptionalHeader);
printf("%-35s%s\n", "File Type:", (pNTHeader->FileHeader.Characteristics & IMAGE_FILE_DLL) ? "DLL" : "EXE");
printf("\n%-35s%s\n", "Image Type:", (pNTHeader->OptionalHeader.Magic == 0x10B) ? "Exe Image" : "Other");
printf("%-35s%d.%d\n", "Linker Version:", pNTHeader->OptionalHeader.MajorLinkerVersion, pNTHeader->OptionalHeader.MinorLinkerVersion);
printf("%-35s%#010x\n", "SizeofCode:", pNTHeader->OptionalHeader.SizeOfCode);
printf("%-35s%#010x\n", "AddressOfEntryPoint:", pNTHeader->OptionalHeader.AddressOfEntryPoint);
printf("%-35s%#010x\n", "DefaultLoadAddress:", pNTHeader->OptionalHeader.ImageBase);
printf("%-35s%#010x\n", "SectionAlignment:", pNTHeader->OptionalHeader.SectionAlignment);
printf("%-35s%#010x\n", "FileAlignment:", pNTHeader->OptionalHeader.FileAlignment);
printf("%-35s%d.%d\n", "OS SystemVersion:", pNTHeader->OptionalHeader.MajorOperatingSystemVersion,
pNTHeader->OptionalHeader.MinorOperatingSystemVersion);
printf("%-35s%d.%d\n", "ImageVersion:", pNTHeader->OptionalHeader.MajorImageVersion,
pNTHeader->OptionalHeader.MinorImageVersion);
printf("%-35s%d.%d\n", "SubSystemVersion:", pNTHeader->OptionalHeader.MajorSubsystemVersion,
pNTHeader->OptionalHeader.MinorSubsystemVersion);
printf("%-35s%#010d\n", "SizeOfIamge:", pNTHeader->OptionalHeader.SizeOfImage);
printf("%-35s%#010d\n", "SizeOfHeaders:", pNTHeader->OptionalHeader.SizeOfHeaders);
if ( pNTHeader->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI )
printf("%-35s%s\n", "GUI System:", "Windows GUI");
else if ( pNTHeader->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI)
printf("%-35s%s\n", "GUI System:", "Windows Console");
else
printf("%-35s%s\n", "GUI System:", "Other");
printf("\n-----------------------------Data Directory----------------------------------\n");
printf("#Index\t#Virtual Address\t#Size\t\t#%-32s\n", "Directory Name");
for (dwIndex = 0; dwIndex < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; dwIndex++ )
{
printf("0x%02x\t0x%08x\t0x%08x\t%-50s\n", dwIndex,
pNTHeader->OptionalHeader.DataDirectory[dwIndex].VirtualAddress,
pNTHeader->OptionalHeader.DataDirectory[dwIndex].Size, szDataDirectory[dwIndex]);
}
printf("\n\n-----------------------------Section Headers----------------------------------\n");
printf("#VirtualAddress\t#VirtualSize\t#PointerToRawData\t#SizeOfRawData\t#Name\n");
for ( dwIndex = 0; dwIndex < pNTHeader->FileHeader.NumberOfSections; dwIndex++ )
{
printf("0x%08x\t0x%08x\t0x%08x\t\t0x%08x\t%-10s\n", pSectionHeader[dwIndex].VirtualAddress,
pSectionHeader[dwIndex].Misc.VirtualSize, pSectionHeader[dwIndex].PointerToRawData,
pSectionHeader[dwIndex].SizeOfRawData, pSectionHeader[dwIndex].Name);
}
// Import Table
printf("\n\n-------------------------Import Table-------------------------------------\n");
pImportDescriptor = (IMAGE_IMPORT_DESCRIPTOR*)((char*)pFileBase + RVA2FileOffset(pNTHeader->OptionalHeader.DataDirectory[1].VirtualAddress));
for ( ; *(char*)pImportDescriptor ; pImportDescriptor++ )
{
printf("Import Lib: %s\n", (char*)(RVA2FileOffset(pImportDescriptor->Name) + (char*)pFileBase));
pThunkData = (IMAGE_THUNK_DATA*)(RVA2FileOffset(pImportDescriptor->OriginalFirstThunk) + (char*)pFileBase);
for ( ; pThunkData->u1.AddressOfData; pThunkData++ )
{
if ( pThunkData->u1.Ordinal & IMAGE_ORDINAL_FLAG32 ) // import by index
{
printf("\t0x%04x\n", pThunkData->u1.Ordinal & 0xffff);
}
else // import by name
{
pImportByName = (IMAGE_IMPORT_BY_NAME*)(RVA2FileOffset(pThunkData->u1.Ordinal) + (char*)pFileBase);
printf("\t0x%04x\t%s\n", pImportByName->Hint, pImportByName->Name);
}
}
printf("\n");
}
if ( pNTHeader->OptionalHeader.DataDirectory[0].Size == 0 ) // Export Table Not Exist
goto End;
// Export Table
printf("\n\n------------------------Export Table---------------------------------\n");
pExportDirectory = (IMAGE_EXPORT_DIRECTORY*)(RVA2FileOffset(pNTHeader->OptionalHeader.DataDirectory[0].VirtualAddress) + (char*)pFileBase);
printf("Export Lib: \t%s\n", (char*)(RVA2FileOffset(pExportDirectory->Name) + (char*)pFileBase));
printf("\tIndex\tName\t\t\n");
printf("\t------------------------------\n");
for ( dwIndex = 0; dwIndex < pExportDirectory->NumberOfNames; dwIndex++ )
{
pdw = (DWORD*)(RVA2FileOffset(pExportDirectory->AddressOfNames) + (char*)pFileBase);
pw = (WORD*)(RVA2FileOffset(pExportDirectory->AddressOfFunctions) + (char*)pFileBase);
printf("\t0x%04x\t%-20s\n", dwIndex, (char*)(RVA2FileOffset(pdw[dwIndex]) + (char*)pFileBase), pw[dwIndex]);
}
End:
UnmapViewOfFile(pFileBase);
CloseHandle(hFileMapping);
CloseHandle(hFile);
return 0;
}
/*
Convert RVA To File Offset
*/
DWORD RVA2FileOffset(DWORD dwRVA)
{
DWORD dwNum, dwIndex;
if ( pNTHeader == NULL )
return 0;
if ( pSectionHeader == NULL )
return 0;
dwNum = pNTHeader->FileHeader.NumberOfSections;
for ( dwIndex = 0; dwIndex < dwNum; dwIndex++ )
{
if ( dwRVA >= pSectionHeader[dwIndex].VirtualAddress &&
dwRVA <= pSectionHeader[dwIndex].VirtualAddress + pSectionHeader[dwIndex].SizeOfRawData)
{
return dwRVA - pSectionHeader[dwIndex].VirtualAddress + pSectionHeader[dwIndex].PointerToRawData;
}
}
return 0;
}
|