It's not a duplicate of PE file: Debug directory of type IMAGE_DEBUG_TYPE_VC_FEATURE. It's out of 0 to 16.
I'm trying to parse the PE header and its directory, as the IMAGE_DATA_DIRECTORY structure said, the debugging information offset is 144 bytes from the optional header. And this is the way I accessed entire PE header and the debug directory:
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <cstring>
#include <exception>
BOOL CALLBACK ENUMRESPROCCALLBACK(
HMODULE hModule,
LPCSTR lpType,
LPSTR lpName,
LONG_PTR lParam
)
{
HRSRC hResource=FindResource(hModule,lpName,lpType);
printf("\t%02X\t\tSize\n", SizeofResource(hModule,hResource));
return TRUE;
}
int main(int argc, char* argv[]) {
HANDLE file = NULL;
DWORD fileSize = NULL;
DWORD bytesRead = NULL;
LPVOID fileData = NULL;
PIMAGE_DOS_HEADER dosHeader = {};
PIMAGE_NT_HEADERS imageNTHeaders = {};
PIMAGE_SECTION_HEADER sectionHeader = {};
PIMAGE_SECTION_HEADER importSection = {};
IMAGE_IMPORT_DESCRIPTOR* importDescriptor = {};
PIMAGE_SECTION_HEADER exportSection = {};
PIMAGE_EXPORT_DIRECTORY exportDescriptor={};
PIMAGE_THUNK_DATA thunkData = {};
DWORD thunk = NULL;
DWORD rawOffset = NULL;
// open file
file = CreateFileA(argv[1], GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (file == INVALID_HANDLE_VALUE) printf("Could not read file");
// allocate heap
fileSize = GetFileSize(file, NULL);
fileData = HeapAlloc(GetProcessHeap(), 0, fileSize);
// read file bytes to memory
ReadFile(file, fileData, fileSize, &bytesRead, NULL);
// IMAGE_DOS_HEADER
dosHeader = (PIMAGE_DOS_HEADER)fileData;
printf("******* DOS HEADER *******\n");
printf("\t0x%x\t\tMagic number\n", dosHeader->e_magic);
printf("\t0x%x\t\tBytes on last page of file\n", dosHeader->e_cblp);
printf("\t0x%x\t\tPages in file\n", dosHeader->e_cp);
printf("\t0x%x\t\tRelocations\n", dosHeader->e_crlc);
printf("\t0x%x\t\tSize of header in paragraphs\n", dosHeader->e_cparhdr);
printf("\t0x%x\t\tMinimum extra paragraphs needed\n", dosHeader->e_minalloc);
printf("\t0x%x\t\tMaximum extra paragraphs needed\n", dosHeader->e_maxalloc);
printf("\t0x%x\t\tInitial (relative) SS value\n", dosHeader->e_ss);
printf("\t0x%x\t\tInitial SP value\n", dosHeader->e_sp);
printf("\t0x%x\t\tInitial SP value\n", dosHeader->e_sp);
printf("\t0x%x\t\tChecksum\n", dosHeader->e_csum);
printf("\t0x%x\t\tInitial IP value\n", dosHeader->e_ip);
printf("\t0x%x\t\tInitial (relative) CS value\n", dosHeader->e_cs);
printf("\t0x%x\t\tFile address of relocation table\n", dosHeader->e_lfarlc);
printf("\t0x%x\t\tOverlay number\n", dosHeader->e_ovno);
printf("\t0x%x\t\tOEM identifier (for e_oeminfo)\n", dosHeader->e_oemid);
printf("\t0x%x\t\tOEM information; e_oemid specific\n", dosHeader->e_oeminfo);
printf("\t0x%x\t\tFile address of new exe header\n", dosHeader->e_lfanew);
// IMAGE_NT_HEADERS
imageNTHeaders = (PIMAGE_NT_HEADERS)((DWORD)fileData + dosHeader->e_lfanew);
printf("\n******* NT HEADERS *******\n");
printf("\t%x\t\tSignature\n", imageNTHeaders->Signature);
// FILE_HEADER
printf("\n******* FILE HEADER *******\n");
printf("\t0x%x\t\tMachine\n", imageNTHeaders->FileHeader.Machine);
printf("\t0x%x\t\tNumber of Sections\n", imageNTHeaders->FileHeader.NumberOfSections);
printf("\t0x%x\tTime Stamp\n", imageNTHeaders->FileHeader.TimeDateStamp);
printf("\t0x%x\t\tPointer to Symbol Table\n", imageNTHeaders->FileHeader.PointerToSymbolTable);
printf("\t0x%x\t\tNumber of Symbols\n", imageNTHeaders->FileHeader.NumberOfSymbols);
printf("\t0x%x\t\tSize of Optional Header\n", imageNTHeaders->FileHeader.SizeOfOptionalHeader);
printf("\t0x%x\t\tCharacteristics\n", imageNTHeaders->FileHeader.Characteristics);
// OPTIONAL_HEADER
printf("\n******* OPTIONAL HEADER *******\n");
printf("\t0x%x\t\tMagic\n", imageNTHeaders->OptionalHeader.Magic);
printf("\t0x%x\t\tMajor Linker Version\n", imageNTHeaders->OptionalHeader.MajorLinkerVersion);
printf("\t0x%x\t\tMinor Linker Version\n", imageNTHeaders->OptionalHeader.MinorLinkerVersion);
printf("\t0x%x\t\tSize Of Code\n", imageNTHeaders->OptionalHeader.SizeOfCode);
printf("\t0x%x\t\tSize Of Initialized Data\n", imageNTHeaders->OptionalHeader.SizeOfInitializedData);
printf("\t0x%x\t\tSize Of UnInitialized Data\n", imageNTHeaders->OptionalHeader.SizeOfUninitializedData);
printf("\t0x%x\t\tAddress Of Entry Point (.text)\n", imageNTHeaders->OptionalHeader.AddressOfEntryPoint);
printf("\t0x%x\t\tBase Of Code\n", imageNTHeaders->OptionalHeader.BaseOfCode);
printf("\t0x%x\t\tBase Of Data\n", imageNTHeaders->OptionalHeader.BaseOfData);
printf("\t0x%x\t\tImage Base\n", imageNTHeaders->OptionalHeader.ImageBase);
printf("\t0x%x\t\tSection Alignment\n", imageNTHeaders->OptionalHeader.SectionAlignment);
printf("\t0x%x\t\tFile Alignment\n", imageNTHeaders->OptionalHeader.FileAlignment);
printf("\t0x%x\t\tMajor Operating System Version\n", imageNTHeaders->OptionalHeader.MajorOperatingSystemVersion);
printf("\t0x%x\t\tMinor Operating System Version\n", imageNTHeaders->OptionalHeader.MinorOperatingSystemVersion);
printf("\t0x%x\t\tMajor Image Version\n", imageNTHeaders->OptionalHeader.MajorImageVersion);
printf("\t0x%x\t\tMinor Image Version\n", imageNTHeaders->OptionalHeader.MinorImageVersion);
printf("\t0x%x\t\tMajor Subsystem Version\n", imageNTHeaders->OptionalHeader.MajorSubsystemVersion);
printf("\t0x%x\t\tMinor Subsystem Version\n", imageNTHeaders->OptionalHeader.MinorSubsystemVersion);
printf("\t0x%x\t\tWin32 Version Value\n", imageNTHeaders->OptionalHeader.Win32VersionValue);
printf("\t0x%x\t\tSize Of Image\n", imageNTHeaders->OptionalHeader.SizeOfImage);
printf("\t0x%x\t\tSize Of Headers\n", imageNTHeaders->OptionalHeader.SizeOfHeaders);
printf("\t0x%x\t\tCheckSum\n", imageNTHeaders->OptionalHeader.CheckSum);
printf("\t0x%x\t\tSubsystem\n", imageNTHeaders->OptionalHeader.Subsystem);
printf("\t0x%x\t\tDllCharacteristics\n", imageNTHeaders->OptionalHeader.DllCharacteristics);
printf("\t0x%x\t\tSize Of Stack Reserve\n", imageNTHeaders->OptionalHeader.SizeOfStackReserve);
printf("\t0x%x\t\tSize Of Stack Commit\n", imageNTHeaders->OptionalHeader.SizeOfStackCommit);
printf("\t0x%x\t\tSize Of Heap Reserve\n", imageNTHeaders->OptionalHeader.SizeOfHeapReserve);
printf("\t0x%x\t\tSize Of Heap Commit\n", imageNTHeaders->OptionalHeader.SizeOfHeapCommit);
printf("\t0x%x\t\tLoader Flags\n", imageNTHeaders->OptionalHeader.LoaderFlags);
printf("\t0x%x\t\tNumber Of Rva And Sizes\n", imageNTHeaders->OptionalHeader.NumberOfRvaAndSizes);
// DATA_DIRECTORIES
printf("\n******* DATA DIRECTORIES *******\n");
printf("\tExport Directory Address: 0x%x; Size: 0x%x\n", imageNTHeaders->OptionalHeader.DataDirectory[0].VirtualAddress, imageNTHeaders->OptionalHeader.DataDirectory[0].Size);
printf("\tImport Directory Address: 0x%x; Size: 0x%x\n", imageNTHeaders->OptionalHeader.DataDirectory[1].VirtualAddress, imageNTHeaders->OptionalHeader.DataDirectory[1].Size);
printf("\tResource Directory Address: 0x%x; Size: 0x%x\n", imageNTHeaders->OptionalHeader.DataDirectory[2].VirtualAddress, imageNTHeaders->OptionalHeader.DataDirectory[2].Size);
printf("\tDebug Directory Address: 0x%x; Size: 0x%x\n", imageNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress, imageNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size);
// SECTION_HEADERS
printf("\n******* SECTION HEADERS *******\n");
// get offset to first section headeer
DWORD sectionLocation = (DWORD)imageNTHeaders + sizeof(DWORD) + (DWORD)(sizeof(IMAGE_FILE_HEADER)) + (DWORD)imageNTHeaders->FileHeader.SizeOfOptionalHeader;
DWORD sectionSize = (DWORD)sizeof(IMAGE_SECTION_HEADER);
// get offset to the import directory RVA
DWORD importDirectoryRVA = imageNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
// get offset to the export directory RVA
//DWORD exportDirectoryRVA = imageNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
// print section data
for (int i = 0; i < imageNTHeaders->FileHeader.NumberOfSections; i++) {
sectionHeader = (PIMAGE_SECTION_HEADER)sectionLocation;
printf("\t%s\n", sectionHeader->Name);
printf("\t\t0x%x\t\tVirtual Size\n", sectionHeader->Misc.VirtualSize);
printf("\t\t0x%x\t\tVirtual Address\n", sectionHeader->VirtualAddress);
printf("\t\t0x%x\t\tSize Of Raw Data\n", sectionHeader->SizeOfRawData);
printf("\t\t0x%x\t\tPointer To Raw Data\n", sectionHeader->PointerToRawData);
printf("\t\t0x%x\t\tPointer To Relocations\n", sectionHeader->PointerToRelocations);
printf("\t\t0x%x\t\tPointer To Line Numbers\n", sectionHeader->PointerToLinenumbers);
printf("\t\t0x%x\t\tNumber Of Relocations\n", sectionHeader->NumberOfRelocations);
printf("\t\t0x%x\t\tNumber Of Line Numbers\n", sectionHeader->NumberOfLinenumbers);
printf("\t\t0x%x\tCharacteristics\n", sectionHeader->Characteristics);
// save section that contains import directory table
if (importDirectoryRVA >= sectionHeader->VirtualAddress && importDirectoryRVA < sectionHeader->VirtualAddress + sectionHeader->Misc.VirtualSize) {
importSection = sectionHeader;
}
if (sectionHeader->Characteristics & IMAGE_SCN_CNT_CODE) printf("\t\tCode\t\tFlags\n");
sectionLocation += sectionSize;
}
// get file offset to import table
rawOffset = (DWORD)fileData + importSection->PointerToRawData;
// get pointer to import descriptor's file offset. Note that the formula for calculating file offset is: imageBaseAddress + pointerToRawDataOfTheSectionContainingRVAofInterest + (RVAofInterest - SectionContainingRVAofInterest.VirtualAddress)
importDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)(rawOffset + (imageNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress - importSection->VirtualAddress));
printf("\n******* DLL IMPORTS *******\n");
for (; importDescriptor->Name != 0; importDescriptor++) {
// imported dll modules
printf("\t%s\n", rawOffset + (importDescriptor->Name - importSection->VirtualAddress));
thunk = importDescriptor->OriginalFirstThunk == 0 ? importDescriptor->FirstThunk : importDescriptor->OriginalFirstThunk;
thunkData = (PIMAGE_THUNK_DATA)(rawOffset + (thunk - importSection->VirtualAddress));
// dll exported functions
for (; thunkData->u1.AddressOfData != 0; thunkData++) {
//a cheap and probably non-reliable way of checking if the function is imported via its ordinal number ¯\_(ツ)_/¯
if (imageNTHeaders->OptionalHeader.Magic==IMAGE_NT_OPTIONAL_HDR32_MAGIC){
if (thunkData->u1.AddressOfData > 0x80000000) {
//show lower bits of the value to get the ordinal ¯\_(ツ)_/¯
printf("\t\tOrdinal: %x\n", (WORD)thunkData->u1.AddressOfData);
} else {
printf("\t\t%s\n", (rawOffset + (thunkData->u1.AddressOfData - importSection->VirtualAddress + 2)));
}
}
else if (imageNTHeaders->OptionalHeader.Magic==IMAGE_NT_OPTIONAL_HDR64_MAGIC){
if (thunkData->u1.AddressOfData > 0x8000000000000000) {
//show lower bits of the value to get the ordinal ¯\_(ツ)_/¯
printf("\t\tOrdinal: %x\n", (WORD)thunkData->u1.AddressOfData);
} else {
printf("\t\t%s\n", (rawOffset + (thunkData->u1.AddressOfData - importSection->VirtualAddress + 2)));
}
}
}
}
PIMAGE_EXPORT_DIRECTORY exportDir = (PIMAGE_EXPORT_DIRECTORY)((DWORD_PTR)fileData + imageNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
DWORD* functions = (DWORD*)((DWORD_PTR)fileData + exportDir->AddressOfFunctions);
DWORD* names = (DWORD*)((DWORD_PTR)fileData + exportDir->AddressOfNames);
WORD* ordinals = (WORD*)((DWORD_PTR)fileData + exportDir->AddressOfNameOrdinals);
HMODULE hModule=LoadLibraryEx(argv[1],NULL,DONT_RESOLVE_DLL_REFERENCES);
DWORD moduleBase = (DWORD)hModule;
printf("******* DLL EXPORTS *******\n");
printf("\t%i of functions\n\t%i of names\n",sizeof(functions)/sizeof(DWORD*),sizeof(names)/sizeof(DWORD*));
printf("\tordinal\t\thint\t\tRVA\t\tname\n");
for (DWORD j=0;j<exportDir->NumberOfFunctions;j++){
try
{
printf("\t%i\t\t%02X\t\t%0002X\t\t%s\n", ((DWORD)fileData + ordinals[j]) - (((DWORD)fileData + ordinals[0])), j, ((DWORD*)((BYTE*)moduleBase + exportDir->AddressOfFunctions))[j], ((DWORD)fileData + names[j]));
}
catch (...){
continue;
}
}
FreeLibrary(hModule);
if (!imageNTHeaders->FileHeader.Characteristics & IMAGE_FILE_DLL) printf("\t1\t\t01\t\t%i\t\tstart\n",imageNTHeaders->OptionalHeader.AddressOfEntryPoint);
printf("******** .IDATA DISASSEMBLY ********\n");
// get file offset to import table
rawOffset = (DWORD)fileData + importSection->PointerToRawData;
// get pointer to import descriptor's file offset. Note that the formula for calculating file offset is: imageBaseAddress + pointerToRawDataOfTheSectionContainingRVAofInterest + (RVAofInterest - SectionContainingRVAofInterest.VirtualAddress)
importDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)(rawOffset + (imageNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress - importSection->VirtualAddress));
for (; importDescriptor->Name != 0; importDescriptor++) {
thunk = importDescriptor->OriginalFirstThunk == 0 ? importDescriptor->FirstThunk : importDescriptor->OriginalFirstThunk;
thunkData = (PIMAGE_THUNK_DATA)(rawOffset + (thunk - importSection->VirtualAddress));
// dll exported functions
for (; thunkData->u1.AddressOfData != 0; thunkData++) {
//a cheap and probably non-reliable way of checking if the function is imported via its ordinal number ¯\_(ツ)_/¯
try
{
printf("\textern __imp__%s@%i(...)\n",(rawOffset + (thunkData->u1.AddressOfData - importSection->VirtualAddress + 2)),(WORD)thunkData->u1.AddressOfData);
}
catch (std::exception e){
printf("Exception thrown at %i\n", e.what());
continue;
}
}
}
printf("******** DEPENDENCIES ********\n");
// get file offset to import table
rawOffset = (DWORD)fileData + importSection->PointerToRawData;
// get pointer to import descriptor's file offset. Note that the formula for calculating file offset is: imageBaseAddress + pointerToRawDataOfTheSectionContainingRVAofInterest + (RVAofInterest - SectionContainingRVAofInterest.VirtualAddress)
importDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)(rawOffset + (imageNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress - importSection->VirtualAddress));
for (; importDescriptor->Name != 0; importDescriptor++) {
printf("\t%s\n", rawOffset + (importDescriptor->Name - importSection->VirtualAddress));
thunk = importDescriptor->OriginalFirstThunk == 0 ? importDescriptor->FirstThunk : importDescriptor->OriginalFirstThunk;
thunkData = (PIMAGE_THUNK_DATA)(rawOffset + (thunk - importSection->VirtualAddress));
}
hModule=LoadLibraryEx(argv[1],NULL,DONT_RESOLVE_DLL_REFERENCES);
printf("******** RESOURCES ********\n");
printf("******** Accelerators ********\n");
EnumResourceNamesA(hModule,RT_ACCELERATOR,ENUMRESPROCCALLBACK,NULL);
printf("******** Animation cursors ********\n");
EnumResourceNamesA(hModule,RT_ANICURSOR,ENUMRESPROCCALLBACK,NULL);
printf("******** Animation icons ********\n");
EnumResourceNamesA(hModule,RT_ANIICON,ENUMRESPROCCALLBACK,NULL);
printf("******** Bitmaps ********\n");
EnumResourceNamesA(hModule,RT_BITMAP,ENUMRESPROCCALLBACK,NULL);
printf("******** Cursors ********\n");
EnumResourceNamesA(hModule,RT_CURSOR,ENUMRESPROCCALLBACK,NULL);
printf("******** Dialogs ********\n");
EnumResourceNamesA(hModule,RT_DIALOG,ENUMRESPROCCALLBACK,NULL);
printf("******** Dialog includes ********\n");
EnumResourceNamesA(hModule,RT_DLGINCLUDE,ENUMRESPROCCALLBACK,NULL);
printf("******** Fonts ********\n");
EnumResourceNamesA(hModule,RT_FONT,ENUMRESPROCCALLBACK,NULL);
printf("******** Font directory ********\n");
EnumResourceNamesA(hModule,RT_FONTDIR,ENUMRESPROCCALLBACK,NULL);
printf("******** Cursor groups ********\n");
EnumResourceNamesA(hModule,RT_GROUP_CURSOR,ENUMRESPROCCALLBACK,NULL);
printf("******** Group of icons ********\n");
EnumResourceNamesA(hModule,RT_GROUP_ICON,ENUMRESPROCCALLBACK,NULL);
printf("******** HTML documents ********\n");
EnumResourceNamesA(hModule,RT_HTML,ENUMRESPROCCALLBACK,NULL);
printf("******** Icons ********\n");
EnumResourceNamesA(hModule,RT_ICON,ENUMRESPROCCALLBACK,NULL);
printf("******** Manifest ********\n");
EnumResourceNamesA(hModule,RT_MANIFEST,ENUMRESPROCCALLBACK,NULL);
printf("******** Menu ********\n");
EnumResourceNamesA(hModule,RT_MENU,ENUMRESPROCCALLBACK,NULL);
printf("******** Message table ********\n");
EnumResourceNamesA(hModule,RT_MESSAGETABLE,ENUMRESPROCCALLBACK,NULL);
printf("******** Plug and Play (PnP) ********\n");
EnumResourceNamesA(hModule,RT_PLUGPLAY,ENUMRESPROCCALLBACK,NULL);
printf("******** Binary data ********\n");
EnumResourceNamesA(hModule,RT_RCDATA,ENUMRESPROCCALLBACK,NULL);
printf("******** String table ********\n");
EnumResourceNamesA(hModule,RT_STRING,ENUMRESPROCCALLBACK,NULL);
printf("******** Version table ********\n");
EnumResourceNamesA(hModule,RT_VERSION,ENUMRESPROCCALLBACK,NULL);
printf("******** VXD (Win9x) ********\n");
EnumResourceNamesA(hModule,RT_VXD,ENUMRESPROCCALLBACK,NULL);
printf("Nobody uses this app in Win9x except running with VC6.\n");
if (imageNTHeaders->OptionalHeader.Magic==IMAGE_NT_OPTIONAL_HDR32_MAGIC){
DWORD debugLocation=sizeof(imageNTHeaders->Signature)+sizeof(imageNTHeaders->FileHeader)+144;
PIMAGE_DEBUG_DIRECTORY debugDirectory=(PIMAGE_DEBUG_DIRECTORY)((DWORD)fileData+debugLocation);
printf("\t%i\t\tType\n",debugDirectory->Type);
}
else if (imageNTHeaders->OptionalHeader.Magic==IMAGE_NT_OPTIONAL_HDR64_MAGIC){
DWORD debugLocation=sizeof(imageNTHeaders->Signature)+sizeof(imageNTHeaders->FileHeader)+160;
PIMAGE_DEBUG_DIRECTORY debugDirectory=(PIMAGE_DEBUG_DIRECTORY)((DWORD)fileData+debugLocation);
int n = debugDirectory->Type;
int m = n % 256; // get the modulo 256 value
printf("\t%d\t\tType\n",m);
}
return 0;
}
Problem:
4194304 Type
What I'm doing wrong?
Use ImageDirectoryEntryToData
or ImageDirectoryEntryToDataEx
instead.
Code:
BOOL dumpDebugDirectory(PVOID Base){
ULONG bytes;
PIMAGE_DEBUG_DIRECTORY debugDirectory;
IMAGE_SECTION_HEADER debugSection; // optional, if you use
// ImageDirectoryEntryToData
debugDirectory=ImageDirectoryEntryToDataEx(Base, FALSE,
IMAGE_DIRECTORY_ENTRY_DEBUG,
&bytes, debugSection);
if (debugSection==NULL)
return 1; // that mean there are no debug section
printf("\t%s\tType",debugDirectory->Type);
// do other stuff like printing PDB filename here
return 0;
}