PE Parser in Windows API
This post hosts code I have written to parse and understand the PE file format.
The code
const CHAR* ImageResourceDirectoryNameToString(ULONG namenumber)
{
// Resource Types
// https://docs.microsoft.com/en-us/windows/win32/menurc/resource-types
const CHAR* name = new const CHAR[50];
switch(namenumber)
{
case 1:
name = "Cursor";
case 2:
name = "Bitmap";
case 3:
name = "Icon";
case 4:
name = "Menu";
case 5:
name = "Dialog";
case 6:
name = "String";
case 7:
name = "Font Directory";
case 8:
name = "Font";
case 9:
name = "Accelerator";
case 10:
name = "RcData";
case 11:
name = "Message Table";
case 16:
name = "Version";
case 17:
name = "DlgInclude";
case 19:
name = "Plug and Play";
case 20:
name = "VXD";
case 21:
name = "Animated Cursor";
case 22:
name = "Animated Icon";
case 23:
name ="HTML";
case 24:
name = "Manifest";
default:
name = "Unknown";
}
return name;
}
void PrintExports64(CHAR* fBuffer, IMAGE_SECTION_HEADER* hdrSection, IMAGE_FILE_HEADER hdrFile)
{
DWORD* ExportDirRVA = (DWORD*)(*(DWORD*)((uint64_t)fBuffer + 0x3c) + 0x88 + (uint64_t)fBuffer);
DWORD ExportDirOffset = RVAToOffset(hdrFile, *ExportDirRVA, hdrSection);
uint64_t AddressOfExportTable = (uint64_t)fBuffer + ExportDirOffset;
DWORD AddressOfNamesRVA = *(DWORD*)((uint64_t)AddressOfExportTable + 0x20);
DWORD AddressOfNamesOffset = RVAToOffset(hdrFile, AddressOfNamesRVA, hdrSection);
uint64_t AddressOfNames = AddressOfNamesOffset + (uint64_t)fBuffer;
DWORD NumberOfNames = *(DWORD*)((uint64_t)AddressOfExportTable + 0x18);
if (NumberOfNames == 0)
{
printf("\tNo exports\n");
exit(1);
}
printf("Export Table:\n");
CHAR* APIName = 0;
for (unsigned int i = 0; i < NumberOfNames; i++)
{
DWORD NameRVA = *(DWORD*)(AddressOfNames + sizeof(DWORD) * i);
DWORD NameOffset = RVAToOffset(hdrFile, NameRVA, hdrSection);
APIName = NameOffset + (CHAR*)fBuffer;
printf("\t%d. Name: %s\n", i + 1, APIName);
}
}
CHAR* ReadFileWrapper(CHAR* infile)
{
BOOL status = FALSE;
HANDLE hFile;
hFile = CreateFileA(infile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
printf("[-] CreateFileA has failed: %d\n", GetLastError());
return 0;
}
DWORD lpFileSizeHigh = 0;
DWORD fSize = GetFileSize(hFile, &lpFileSizeHigh);
if (fSize == INVALID_FILE_SIZE)
{
printf("[-] GetFileSize has failed: %d\n", GetLastError());
return 0;
}
DWORD nNumerOfBytesToRead = fSize;
DWORD lpNumberOfBytesRead = 0;
OVERLAPPED lpOverlapped = { 0 };
CHAR* lpBuffer = new CHAR[nNumerOfBytesToRead];
status = ReadFile(hFile, lpBuffer, nNumerOfBytesToRead, &lpNumberOfBytesRead, &lpOverlapped);
if (!status)
{
printf("[-] ReadFile has failed: %d\n", GetLastError());
return 0;
}
return lpBuffer;
}
int main(int argc, char** argv)
{
CHAR* fBuffer = 0;
printf("[+] In file: %s\n", argv[1]);
fBuffer = ReadFileWrapper(argv[1]);
if (fBuffer == 0)
{
printf("[-] ReadFileWrapper has failed. Exiting...\n");
exit(1);
}
IMAGE_DOS_HEADER* hdrDOS = (IMAGE_DOS_HEADER*)fBuffer;
IMAGE_NT_HEADERS* hdrNT = (IMAGE_NT_HEADERS*)(fBuffer + hdrDOS->e_lfanew);
IMAGE_FILE_HEADER hdrFile = (IMAGE_FILE_HEADER)hdrNT->FileHeader;
//IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
PrintDOSHeader(hdrDOS);
PrintNTHeaderSignature(hdrNT);
PrintFileHeader(hdrFile);
// arch
if (hdrFile.Machine == IMAGE_FILE_MACHINE_I386)
{
IMAGE_NT_HEADERS32* hdrNT = (IMAGE_NT_HEADERS32*)(fBuffer + hdrDOS->e_lfanew);
IMAGE_OPTIONAL_HEADER32 hdrOptional = (IMAGE_OPTIONAL_HEADER32)hdrNT->OptionalHeader;
PrintOptionalHeader<IMAGE_OPTIONAL_HEADER32>(hdrOptional);
PrintImgDataDirectory(hdrOptional);
IMAGE_SECTION_HEADER* hdrSection = IMAGE_FIRST_SECTION(hdrNT);
PrintSectionInformation(hdrSection, hdrFile.NumberOfSections);
}
else if (hdrFile.Machine == IMAGE_FILE_MACHINE_AMD64)
{
IMAGE_NT_HEADERS64* hdrNT = (IMAGE_NT_HEADERS64*)(fBuffer + hdrDOS->e_lfanew);
IMAGE_OPTIONAL_HEADER64 hdrOptional = (IMAGE_OPTIONAL_HEADER64)hdrNT->OptionalHeader;
PrintOptionalHeader<IMAGE_OPTIONAL_HEADER64>(hdrOptional);
PrintImgDataDirectory(hdrOptional);
IMAGE_SECTION_HEADER* hdrSection = IMAGE_FIRST_SECTION(hdrNT);
PrintSectionInformation(hdrSection, hdrFile.NumberOfSections);
PrintExports64(fBuffer, hdrSection, hdrFile);
}
}
tags: #Windows API