//==================================
// PEDUMP - Matt Pietrek 1994-2001
// FILE: EXEDUMP.CPP
//==================================
#include <windows.h>
#include <stdio.h>
#include <time.h>
#include <delayimp.h>
#include <wintrust.h>
#pragma hdrstop
#include "common.h"
#include "symboltablesupport.h"
#include "COFFSymbolTable.h"
#include "resdump.h"
#include "extrnvar.h"
//============================================================================
// Bitfield values and names for the DllCharacteritics flags
WORD_FLAG_DESCRIPTIONS DllCharacteristics[] =
{
{ IMAGE_DLLCHARACTERISTICS_NO_BIND, "NO_BIND" }, // Do not bind this image.
{ IMAGE_DLLCHARACTERISTICS_WDM_DRIVER, "WDM_DRIVER" }, // Driver uses WDM model
{ IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE, "TERMINAL_SERVER_AWARE" },
// Old, obsolete flags
// IMAGE_LIBRARY_PROCESS_INIT 0x0001 // Reserved.
// IMAGE_LIBRARY_PROCESS_TERM 0x0002 // Reserved.
// IMAGE_LIBRARY_THREAD_INIT 0x0004 // Reserved.
// IMAGE_LIBRARY_THREAD_TERM 0x0008 // Reserved.
};
#define NUMBER_DLL_CHARACTERISTICS \
(sizeof(DllCharacteristics) / sizeof(WORD_FLAG_DESCRIPTIONS))
// Names of the data directory elements that are defined
char *ImageDirectoryNames[] = {
"EXPORT",
"IMPORT",
"RESOURCE",
"EXCEPTION",
"SECURITY",
"BASERELOC",
"DEBUG",
"ARCHITECTURE",
"GLOBALPTR",
"TLS",
"LOAD_CONFIG",
"BOUND_IMPORT", // These two entries added for NT 3.51
"IAT",
"DELAY_IMPORT", // This entry added in NT 5 time frame
"COM_DESCRPTR" }; // For the .NET runtime (previously called COM+ 2.0)
#define NUMBER_IMAGE_DIRECTORY_ENTRYS \
(sizeof(ImageDirectoryNames)/sizeof(char *))
void DisplayDataDirectoryEntry( PSTR pszName, IMAGE_DATA_DIRECTORY & dataDirEntry )
{
printf( " %-16s rva: %08X size: %08X\n", pszName, dataDirEntry.VirtualAddress, dataDirEntry.Size );
}
//============================================================================
//
// Dump the IMAGE_OPTIONAL_HEADER from a PE file
//
template <class T> void DumpOptionalHeader(T* pImageOptionalHeader) // 'T' is IMAGE_OPTIONAL_HEADER32/64
{
UINT width = 30;
char *s;
UINT i;
bool b64BitHeader = (IMAGE_NT_OPTIONAL_HDR64_MAGIC == pImageOptionalHeader->Magic);
printf("Optional Header\n");
printf(" %-*s%04X\n", width, "Magic", pImageOptionalHeader->Magic);
printf(" %-*s%u.%02u\n", width, "linker version",
pImageOptionalHeader->MajorLinkerVersion,
pImageOptionalHeader->MinorLinkerVersion);
printf(" %-*s%X\n", width, "size of code", pImageOptionalHeader->SizeOfCode);
printf(" %-*s%X\n", width, "size of initialized data",
pImageOptionalHeader->SizeOfInitializedData);
printf(" %-*s%X\n", width, "size of uninitialized data",
pImageOptionalHeader->SizeOfUninitializedData);
printf(" %-*s%X\n", width, "entrypoint RVA",
pImageOptionalHeader->AddressOfEntryPoint);
printf(" %-*s%X\n", width, "base of code", pImageOptionalHeader->BaseOfCode);
// 32/64 bit dependent code
if ( b64BitHeader )
{
printf(" %-*s%I64X\n", width, "image base", pImageOptionalHeader->ImageBase);
}
else
{
// Can't refer to BaseOfData, since this field isn't in an IMAGE_NT_OPTIONAL_HDR64
printf(" %-*s%X\n", width, "base of data", ((PIMAGE_OPTIONAL_HEADER32)pImageOptionalHeader)->BaseOfData );
printf(" %-*s%X\n", width, "image base", pImageOptionalHeader->ImageBase);
}
// end of 32/64 bit dependent code
printf(" %-*s%X\n", width, "section align",
pImageOptionalHeader->SectionAlignment);
printf(" %-*s%X\n", width, "file align", pImageOptionalHeader->FileAlignment);
printf(" %-*s%u.%02u\n", width, "required OS version",
pImageOptionalHeader->MajorOperatingSystemVersion,
pImageOptionalHeader->MinorOperatingSystemVersion);
printf(" %-*s%u.%02u\n", width, "image version",
pImageOptionalHeader->MajorImageVersion,
pImageOptionalHeader->MinorImageVersion);
printf(" %-*s%u.%02u\n", width, "subsystem version",
pImageOptionalHeader->MajorSubsystemVersion,
pImageOptionalHeader->MinorSubsystemVersion);
printf(" %-*s%X\n", width, "Win32 Version",
pImageOptionalHeader->Win32VersionValue);
printf(" %-*s%X\n", width, "size of image", pImageOptionalHeader->SizeOfImage);
printf(" %-*s%X\n", width, "size of headers",
pImageOptionalHeader->SizeOfHeaders);
printf(" %-*s%X\n", width, "checksum", pImageOptionalHeader->CheckSum);
switch( pImageOptionalHeader->Subsystem )
{
case IMAGE_SUBSYSTEM_UNKNOWN: s = "UNKNOWN (0)"; break;
case IMAGE_SUBSYSTEM_NATIVE: s = "Native"; break;
case IMAGE_SUBSYSTEM_WINDOWS_GUI: s = "Windows GUI"; break;
case IMAGE_SUBSYSTEM_WINDOWS_CUI: s = "Windows character"; break;
case IMAGE_SUBSYSTEM_OS2_CUI: s = "OS/2 character"; break;
case IMAGE_SUBSYSTEM_POSIX_CUI: s = "Posix character"; break;
case IMAGE_SUBSYSTEM_NATIVE_WINDOWS: s = "Native Windows (Win9X driver)"; break;
case IMAGE_SUBSYSTEM_WINDOWS_CE_GUI: s = "Windows CE GUI"; break;
case IMAGE_SUBSYSTEM_EFI_APPLICATION: s = "EFI_APPLICATION"; break;
case IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER: s = "EFI_BOOT_SERVICE_DRIVER"; break;
case IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER: s = "EFI_RUNTIME_DRIVER"; break;
case IMAGE_SUBSYSTEM_EFI_ROM: s = "EFI_ROM";
case IMAGE_SUBSYSTEM_XBOX: s = "XBOX";
default: s = "unknown";
}
printf(" %-*s%04X (%s)\n", width, "Subsystem",
pImageOptionalHeader->Subsystem, s);
// Marked as obsolete in MSDN CD 9
printf(" %-*s%04X\n", width, "DLL flags",
pImageOptionalHeader->DllCharacteristics);
for ( i=0; i < NUMBER_DLL_CHARACTERISTICS; i++ )
{
if ( pImageOptionalHeader->DllCharacteristics &
DllCharacteristics[i].flag )
printf( " %-*s%s", width, " ", DllCharacteristics[i].name );
}
if ( pImageOptionalHeader->DllCharacteristics )
printf("\n");
PSTR pszSizeFmtString;
if ( b64BitHeader )
pszSizeFmtString = " %-*s%I64X\n";
else
pszSizeFmtString = " %-*s%X\n";
printf( pszSizeFmtString, width, "stack reserve size",
pImageOptionalHeader->SizeOfStackReserve);
printf( pszSizeFmtString, width, "stack commit size",
pImageOptionalHeader->SizeOfStackCommit);
printf( pszSizeFmtString, width, "heap reserve size",
pImageOptionalHeader->SizeOfHeapReserve);
printf( pszSizeFmtString, width, "heap commit size",
pImageOptionalHeader->SizeOfHeapCommit);
#if 0
// Marked as obsolete in MSDN CD 9
printf(" %-*s%08X\n", width, "loader flags",
pImageOptionalHeader->LoaderFlags);
for ( i=0; i < NUMBER_LOADER_FLAGS; i++ )
{
if ( pImageOptionalHeader->LoaderFlags &
LoaderFlags[i].flag )
printf( " %s", LoaderFlags[i].name );
}
if ( pImageOptionalHeader->LoaderFlags )
printf("\n");
#endif
printf(" %-*s%X\n", width, "RVAs & sizes",
pImageOptionalHeader->NumberOfRvaAndSizes);
printf("\nData Directory\n");
for ( i=0; i < pImageOptionalHeader->NumberOfRvaAndSizes; i++)
{
DisplayDataDirectoryEntry( (i >= NUMBER_IMAGE_DIRECTORY_ENTRYS) ? "unused" : ImageDirectoryNames[i],
pImageOptionalHeader->DataDirectory[i] );
}
}
template <class T> void DumpExeDebugDirectory(PBYTE pImageBase, T * pNTHeader) // 'T' = PIMAGE_NT_HEADERS32 or PIMAGE_NT_HEADERS64
{
PIMAGE_DEBUG_DIRECTORY debugDir;
PIMAGE_SECTION_HEADER header;
DWORD va_debug_dir;
DWORD size;
va_debug_dir = GetImgDirEntryRVA(pNTHeader, IMAGE_DIRECTORY_ENTRY_DEBUG);
if ( va_debug_dir == 0 )
return;