/* * Copyright (C) 2005-2018 Team Kodi * This file is part of Kodi - https://kodi.tv * * SPDX-License-Identifier: GPL-2.0-or-later * See LICENSES/README.md for more information. */ #include #include #include "coff.h" #include "coffldr.h" //#define DUMPING_DATA 1 #ifndef __GNUC__ #pragma warning (disable:4806) #endif #include "utils/log.h" #define printf(format, ...) CLog::Log(LOGDEBUG, format , ##__VA_ARGS__) const char *DATA_DIR_NAME[16] = { "Export Table", "Import Table", "Resource Table", "Exception Table", "Certificate Table", "Base Relocation Table", "Debug", "Architecture", "Global Ptr", "TLS Table", "Load Config Table", "Bound Import", "IAT", "Delay Import Descriptor", "COM+ Runtime Header", "Reserved" }; CoffLoader::CoffLoader() { CoffFileHeader = 0; OptionHeader = 0; WindowsHeader = 0; Directory = 0; SectionHeader = 0; SymTable = 0; StringTable = 0; SectionData = 0; NumberOfSymbols = 0; SizeOfStringTable = 0; NumOfDirectories = 0; NumOfSections = 0; FileHeaderOffset = 0; EntryAddress = 0; hModule = NULL; } CoffLoader::~CoffLoader() { if ( hModule ) { #ifdef TARGET_POSIX free(hModule); #else VirtualFree(hModule, 0, MEM_RELEASE); #endif hModule = NULL; } if ( SymTable ) { delete [] SymTable; SymTable = 0; } if ( StringTable ) { delete [] StringTable; StringTable = 0; } if ( SectionData ) { delete [] SectionData; SectionData = 0; } } // Has nothing to do with the coff loader itself // it can be used to parse the headers of a dll // already loaded into memory int CoffLoader::ParseHeaders(void* hModule) { if (strncmp((char*)hModule, "MZ", 2) != 0) return 0; int* Offset = (int*)((char*)hModule+0x3c); if (*Offset <= 0) return 0; if (strncmp((char*)hModule+*Offset, "PE\0\0", 4) != 0) return 0; FileHeaderOffset = *Offset + 4; CoffFileHeader = (COFF_FileHeader_t *) ( (char*)hModule + FileHeaderOffset ); NumOfSections = CoffFileHeader->NumberOfSections; OptionHeader = (OptionHeader_t *) ( (char*)CoffFileHeader + sizeof(COFF_FileHeader_t) ); WindowsHeader = (WindowsHeader_t *) ( (char*)OptionHeader + OPTHDR_SIZE ); EntryAddress = OptionHeader->Entry; NumOfDirectories = WindowsHeader->NumDirectories; Directory = (Image_Data_Directory_t *) ( (char*)WindowsHeader + WINHDR_SIZE); SectionHeader = (SectionHeader_t *) ( (char*)Directory + sizeof(Image_Data_Directory_t) * NumOfDirectories); if (CoffFileHeader->MachineType != IMAGE_FILE_MACHINE_I386) return 0; #ifdef DUMPING_DATA PrintFileHeader(CoffFileHeader); #endif if ( CoffFileHeader->SizeOfOptionHeader == 0 ) //not an image file, object file maybe return 0; // process Option Header if (OptionHeader->Magic == OPTMAGIC_PE32P) { printf("PE32+ not supported\n"); return 0; } else if (OptionHeader->Magic == OPTMAGIC_PE32) { #ifdef DUMPING_DATA PrintOptionHeader(OptionHeader); PrintWindowsHeader(WindowsHeader); #endif } else { //add error message return 0; } #ifdef DUMPING_DATA for (int DirCount = 0; DirCount < NumOfDirectories; DirCount++) { printf("Data Directory %02d: %s\n", DirCount + 1, DATA_DIR_NAME[DirCount]); printf(" RVA: %08X\n", Directory[DirCount].RVA); printf(" Size: %08X\n\n", Directory[DirCount].Size); } #endif return 1; } int CoffLoader::LoadCoffHModule(FILE *fp) { //test file signatures char Sig[4]; rewind(fp); memset(Sig, 0, sizeof(Sig)); if (!fread(Sig, 1, 2, fp) || strncmp(Sig, "MZ", 2) != 0) return 0; if (fseek(fp, 0x3c, SEEK_SET) != 0) return 0; int Offset = 0; if (!fread(&Offset, sizeof(int), 1, fp) || (Offset <= 0)) return 0; if (fseek(fp, Offset, SEEK_SET) != 0) return 0; memset(Sig, 0, sizeof(Sig)); if (!fread(Sig, 1, 4, fp) || strncmp(Sig, "PE\0\0", 4) != 0) return 0; Offset += 4; FileHeaderOffset = Offset; // Load and process Header if (fseek(fp, FileHeaderOffset + sizeof(COFF_FileHeader_t) + OPTHDR_SIZE, SEEK_SET)) //skip to winows headers return 0; WindowsHeader_t tempWindowsHeader; size_t readcount = fread(&tempWindowsHeader, 1, WINHDR_SIZE, fp); if (readcount != WINHDR_SIZE) //test file size error return 0; // alloc aligned memory #ifdef TARGET_POSIX hModule = malloc(tempWindowsHeader.SizeOfImage); #elif defined TARGET_WINDOWS_STORE hModule = VirtualAllocFromApp(GetCurrentProcess(), tempWindowsHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); #else hModule = VirtualAllocEx(GetCurrentProcess(), (PVOID)tempWindowsHeader.ImageBase, tempWindowsHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); if (hModule == NULL) hModule = VirtualAlloc(GetCurrentProcess(), tempWindowsHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); #endif if (hModule == NULL) return 0; //memory allocation fails rewind(fp); readcount = fread(hModule, 1, tempWindowsHeader.SizeOfHeaders, fp); if (readcount != tempWindowsHeader.SizeOfHeaders) //file size error return 0; CoffFileHeader = (COFF_FileHeader_t *) ( (char*)hModule + FileHeaderOffset ); NumOfSections = CoffFileHeader->NumberOfSections; OptionHeader = (OptionHeader_t *) ( (char*)CoffFileHeader + sizeof(COFF_FileHeader_t) ); WindowsHeader = (WindowsHeader_t *) ( (char*)OptionHeader + OPTHDR_SIZE ); EntryAddress = OptionHeader->Entry; NumOfDirectories = WindowsHeader->NumDirectories; Directory = (Image_Data_Directory_t *) ( (char*)WindowsHeader + WINHDR_SIZE); SectionHeader = (SectionHeader_t *) ( (char*)Directory + sizeof(Image_Data_Directory_t) * NumOfDirectories); if (CoffFileHeader->MachineType != IMAGE_FILE_MACHINE_I386) return 0; #ifdef DUMPING_DATA PrintFileHeader(CoffFileHeader); #endif if ( CoffFileHeader->SizeOfOptionHeader == 0 ) //not an image file, object file maybe return 0; // process Option Header if (OptionHeader->Magic == OPTMAGIC_PE32P) { printf("PE32+ not supported\n"); return 0; } else if (OptionHeader->Magic == OPTMAGIC_PE32) { #ifdef DUMPING_DATA PrintOptionHeader(OptionHeader); PrintWindowsHeader(WindowsHeader); #endif } else { //add error message return 0; } #ifdef DUMPING_DATA for (int DirCount = 0; DirCount < NumOfDirectories; DirCount++) { printf("Data Directory %02d: %s\n", DirCount + 1, DATA_DIR_NAME[DirCount]); printf(" RVA: %08X\n", Directory[DirCount].RVA); printf(" Size: %08X\n\n", Directory[DirCount].Size); } #endif return 1; } int CoffLoader::LoadSymTable(FILE *fp) { int Offset = ftell(fp); if (Offset < 0) return 0; if ( CoffFileHeader->PointerToSymbolTable == 0 ) return 1; if (fseek(fp, CoffFileHeader->PointerToSymbolTable /* + CoffBeginOffset*/, SEEK_SET) != 0) return 0; SymbolTable_t *tmp = new SymbolTable_t[CoffFileHeader->NumberOfSymbols]; if (!tmp) { printf("Could not allocate memory for symbol table!\n"); return 0; } if (!fread((void *)tmp, CoffFileHeader->NumberOfSymbols, sizeof(SymbolTable_t), fp)) { delete[] tmp; return 0; } NumberOfSymbols = CoffFileHeader->NumberOfSymbols; SymTable = tmp; if (fseek(fp, Offset, SEEK_SET) != 0) return 0; return 1; } int CoffLoader::LoadStringTable(FILE *fp) { int StringTableSize; char *tmp = NULL; int Offset = ftell(fp); if (Offset < 0) return 0; if ( CoffFileHeader->PointerToSymbolTable == 0 ) return 1; if (fseek(fp, CoffFileHeader->PointerToSymbolTable + CoffFileHeader->NumberOfSymbols * sizeof(SymbolTable_t), SEEK_SET) != 0) return 0; if (!fread(&StringTableSize, 1, sizeof(int), fp)) return 0; StringTableSize -= 4; if (StringTableSize != 0) { tmp = new char[StringTableSize]; if (tmp == NULL) { printf("Could not allocate memory for string table\n"); return 0; } if (!fread((void *)tmp, StringTableSize, sizeof(char), fp)) { delete[] tmp; return 0; } } SizeOfStringTable = StringTableSize; StringTable = tmp; if (fseek(fp, Offset, SEEK_SET) != 0) return 0; return 1; } int CoffLoader::LoadSections(FILE *fp) { NumOfSections = CoffFileHeader->NumberOfSections; SectionData = new char * [NumOfSections]; if ( !SectionData ) return 0; // Bobbin007: for debug dlls this check always fails //////check VMA size!!!!! //unsigned long vma_size = 0; //for (int SctnCnt = 0; SctnCnt < NumOfSections; SctnCnt++) //{ // SectionHeader_t *ScnHdr = (SectionHeader_t *)(SectionHeader + SctnCnt); // vma_size = max(vma_size, ScnHdr->VirtualAddress + ScnHdr->SizeOfRawData); // vma_size = max(vma_size, ScnHdr->VirtualAddress + ScnHdr->VirtualSize); //} //if (WindowsHeader->SizeOfImage < vma_size) // return 0; //something wrong with file for (int SctnCnt = 0; SctnCnt < NumOfSections; SctnCnt++) { SectionHeader_t *ScnHdr = SectionHeader + SctnCnt; SectionData[SctnCnt] = ((char*)hModule + ScnHdr->VirtualAddress); if (fseek(fp, ScnHdr->PtrToRawData, SEEK_SET) != 0) return 0; if (!fread(SectionData[SctnCnt], 1, ScnHdr->SizeOfRawData, fp)) return 0; #ifdef DUMPING_DATA //debug blocks char szBuf[128]; char namebuf[9]; for (int i = 0; i < 8; i++) namebuf[i] = ScnHdr->Name[i]; namebuf[8] = '\0'; sprintf(szBuf, "Load code Sections %s Memory %p,Length %x\n", namebuf, SectionData[SctnCnt], max(ScnHdr->VirtualSize, ScnHdr->SizeOfRawData)); OutputDebugString(szBuf); #endif if ( ScnHdr->SizeOfRawData < ScnHdr->VirtualSize ) //initialize BSS data in the end of section { memset((char*)((long)(SectionData[SctnCnt]) + ScnHdr->SizeOfRawData), 0, ScnHdr->VirtualSize - ScnHdr->SizeOfRawData); } if (ScnHdr->Characteristics & IMAGE_SCN_CNT_BSS) //initialize whole .BSS section, pure .BSS is obsolete { memset(SectionData[SctnCnt], 0, ScnHdr->VirtualSize); } #ifdef DUMPING_DATA PrintSection(SectionHeader + SctnCnt, SectionData[SctnCnt]); #endif } return 1; } //FIXME: Add the Free Resources functions int CoffLoader::RVA2Section(unsigned long RVA) { NumOfSections = CoffFileHeader->NumberOfSections; for ( int i = 0; i < NumOfSections; i++) { if ( SectionHeader[i].VirtualAddress <= RVA ) { if ( i + 1 != NumOfSections ) { if ( RVA < SectionHeader[i + 1].VirtualAddress ) { if ( SectionHeader[i].VirtualAddress + SectionHeader[i].VirtualSize <= RVA ) printf("Warning! Address outside of Section: %lx!\n", RVA); // else return i; } } else { if ( SectionHeader[i].VirtualAddress + SectionHeader[i].VirtualSize <= RVA ) printf("Warning! Address outside of Section: %lx!\n", RVA); // else return i; } } } printf("RVA2Section lookup failure!\n"); return 0; } void* CoffLoader::RVA2Data(unsigned long RVA) { int Sctn = RVA2Section(RVA); if( RVA < SectionHeader[Sctn].VirtualAddress || RVA >= SectionHeader[Sctn].VirtualAddress + SectionHeader[Sctn].VirtualSize) { // RVA2Section is lying, let's use base address of dll instead, only works if // DLL has been loaded fully into memory, which we normally do return (void*)(RVA + (unsigned long)hModule); } return SectionData[Sctn] + RVA - SectionHeader[Sctn].VirtualAddress; } unsigned long CoffLoader::Data2RVA(void* address) { for ( int i = 0; i < CoffFileHeader->NumberOfSections; i++) { if(address >= SectionData[i] && address < SectionData[i] + SectionHeader[i].VirtualSize) return (unsigned long)address - (unsigned long)SectionData[i] + SectionHeader[i].VirtualAddress; } // Section wasn't found, so use relative to main load of dll return (unsigned long)address - (unsigned long)hModule; } char *CoffLoader::GetStringTblIndex(int index) { char *table = StringTable; while (index--) table += strlen(table) + 1; return table; } char *CoffLoader::GetStringTblOff(int Offset) { return StringTable + Offset - 4; } char *CoffLoader::GetSymbolName(SymbolTable_t *sym) { long long index = sym->Name.Offset; int low = (int)(index & 0xFFFFFFFF); int high = (int)((index >> 32) & 0xFFFFFFFF); if (low == 0) { return GetStringTblOff(high); } else { static char shortname[9]; memset(shortname, 0, 9); strncpy(shortname, (char *)sym->Name.ShortName, 8); return shortname; } } char *CoffLoader::GetSymbolName(int index) { SymbolTable_t *sym = &(SymTable[index]); return GetSymbolName(sym); } void CoffLoader::PrintStringTable(void) { int size = SizeOfStringTable; int index = 0; char *table = StringTable; printf("\nSTRING TABLE\n"); while (size) { printf("%2d: %s\n", index++, table); size -= strlen(table) + 1; table += strlen(table) + 1; } printf("\n"); } void CoffLoader::PrintSymbolTable(void) { int SymIndex; printf("COFF SYMBOL TABLE\n"); for (SymIndex = 0; SymIndex < NumberOfSymbols; SymIndex++) { printf("%03X ", SymIndex); printf("%08lX ", SymTable[SymIndex].Value); if (SymTable[SymIndex].SectionNumber == IMAGE_SYM_ABSOLUTE) printf("ABS "); else if (SymTable[SymIndex].SectionNumber == IMAGE_SYM_DEBUG) printf("DEBUG "); else if (SymTable[SymIndex].SectionNumber == IMAGE_SYM_UNDEFINED) printf("UNDEF "); else { printf("SECT%d ", SymTable[SymIndex].SectionNumber); if (SymTable[SymIndex].SectionNumber < 10) printf(" "); if (SymTable[SymIndex].SectionNumber < 100) printf(" "); } if (SymTable[SymIndex].Type == 0) printf("notype "); else { printf("%X ", SymTable[SymIndex].Type); if (SymTable[SymIndex].Type < 0x10) printf(" "); if (SymTable[SymIndex].Type < 0x100) printf(" "); if (SymTable[SymIndex].Type < 0x1000) printf(" "); } if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_END_OF_FUNCTION) printf("End of Function "); if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_NULL) printf("Null "); if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_AUTOMATIC) printf("Automatic "); if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_EXTERNAL) printf("External "); if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_STATIC) printf("Static "); if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_REGISTER) printf("Register "); if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_EXTERNAL_DEF) printf("External Def "); if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_LABEL) printf("Label "); if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_UNDEFINED_LABEL) printf("Undefined Label "); if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_MEMBER_OF_STRUCT) printf("Member Of Struct "); if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_ARGUMENT) printf("Argument "); if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_STRUCT_TAG) printf("Struct Tag "); if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_MEMBER_OF_UNION) printf("Member Of Union "); if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_UNION_TAG) printf("Union Tag "); if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_TYPE_DEFINITION) printf("Type Definition "); if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_UNDEFINED_STATIC) printf("Undefined Static "); if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_ENUM_TAG) printf("Enum Tag "); if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_MEMBER_OF_ENUM) printf("Member Of Enum "); if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_REGISTER_PARAM) printf("Register Param "); if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_BIT_FIELD) printf("Bit Field "); if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_BLOCK) printf("Block "); if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_FUNCTION) printf("Function "); if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_END_OF_STRUCT) printf("End Of Struct "); if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_FILE) printf("File "); if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_SECTION) printf("Section "); if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_WEAK_EXTERNAL) printf("Weak External "); printf("| %s", GetSymbolName(SymIndex)); SymIndex += SymTable[SymIndex].NumberOfAuxSymbols; printf("\n"); } printf("\n"); } void CoffLoader::PrintFileHeader(COFF_FileHeader_t *FileHeader) { printf("COFF Header\n"); printf("------------------------------------------\n\n"); printf("MachineType: 0x%04X\n", FileHeader->MachineType); printf("NumberOfSections: 0x%04X\n", FileHeader->NumberOfSections); printf("TimeDateStamp: 0x%08lX\n",FileHeader->TimeDateStamp); printf("PointerToSymbolTable: 0x%08lX\n",FileHeader->PointerToSymbolTable); printf("NumberOfSymbols: 0x%08lX\n",FileHeader->NumberOfSymbols); printf("SizeOfOptionHeader: 0x%04X\n", FileHeader->SizeOfOptionHeader); printf("Characteristics: 0x%04X\n", FileHeader->Characteristics); if (FileHeader->Characteristics & IMAGE_FILE_RELOCS_STRIPPED) printf(" IMAGE_FILE_RELOCS_STRIPPED\n"); if (FileHeader->Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE) printf(" IMAGE_FILE_EXECUTABLE_IMAGE\n"); if (FileHeader->Characteristics & IMAGE_FILE_LINE_NUMS_STRIPPED) printf(" IMAGE_FILE_LINE_NUMS_STRIPPED\n"); if (FileHeader->Characteristics & IMAGE_FILE_LOCAL_SYMS_STRIPPED) printf(" IMAGE_FILE_LOCAL_SYMS_STRIPPED\n"); if (FileHeader->Characteristics & IMAGE_FILE_AGGRESSIVE_WS_TRIM) printf(" IMAGE_FILE_AGGRESSIVE_WS_TRIM\n"); if (FileHeader->Characteristics & IMAGE_FILE_LARGE_ADDRESS_AWARE) printf(" IMAGE_FILE_LARGE_ADDRESS_AWARE\n"); if (FileHeader->Characteristics & IMAGE_FILE_16BIT_MACHINE) printf(" IMAGE_FILE_16BIT_MACHINE\n"); if (FileHeader->Characteristics & IMAGE_FILE_BYTES_REVERSED_LO) printf(" IMAGE_FILE_BYTES_REVERSED_LO\n"); if (FileHeader->Characteristics & IMAGE_FILE_32BIT_MACHINE) printf(" IMAGE_FILE_32BIT_MACHINE\n"); if (FileHeader->Characteristics & IMAGE_FILE_DEBUG_STRIPPED) printf(" IMAGE_FILE_DEBUG_STRIPPED\n"); if (FileHeader->Characteristics & IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP) printf(" IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP\n"); if (FileHeader->Characteristics & IMAGE_FILE_SYSTEM) printf(" IMAGE_FILE_SYSTEM\n"); if (FileHeader->Characteristics & IMAGE_FILE_DLL) printf(" IMAGE_FILE_DLL\n"); if (FileHeader->Characteristics & IMAGE_FILE_UP_SYSTEM_ONLY) printf(" IMAGE_FILE_UP_SYSTEM_ONLY\n"); if (FileHeader->Characteristics & IMAGE_FILE_BYTES_REVERSED_HI) printf(" IMAGE_FILE_BYTES_REVERSED_HI\n"); printf("\n"); } void CoffLoader::PrintOptionHeader(OptionHeader_t *OptHdr) { printf("Option Header\n"); printf("------------------------------------------\n\n"); printf("Magic: 0x%04X\n", OptHdr->Magic); printf("Linker Major Ver: 0x%02X\n", VERSION_MAJOR(OptHdr->LinkVersion)); printf("Linker Minor Ver: 0x%02X\n", VERSION_MINOR(OptHdr->LinkVersion)); printf("Code Size: 0x%08lX\n", OptHdr->CodeSize); printf("Data Size: 0x%08lX\n", OptHdr->DataSize); printf("BSS Size: 0x%08lX\n", OptHdr->BssSize); printf("Entry: 0x%08lX\n", OptHdr->Entry); printf("Code Base: 0x%08lX\n", OptHdr->CodeBase); printf("Data Base: 0x%08lX\n", OptHdr->DataBase); printf("\n"); } void CoffLoader::PrintWindowsHeader(WindowsHeader_t *WinHdr) { printf("Windows Specific Option Header\n"); printf("------------------------------------------\n\n"); printf("Image Base: 0x%08lX\n", WinHdr->ImageBase); printf("Section Alignment: 0x%08lX\n", WinHdr->SectionAlignment); printf("File Alignment: 0x%08lX\n", WinHdr->FileAlignment); printf("OS Version: %d.%08d\n", BIGVERSION_MAJOR(WinHdr->OSVer), BIGVERSION_MINOR(WinHdr->OSVer)); printf("Image Version: %d.%08d\n", BIGVERSION_MAJOR(WinHdr->ImgVer), BIGVERSION_MINOR(WinHdr->ImgVer)); printf("SubSystem Version: %d.%08d\n", BIGVERSION_MAJOR(WinHdr->SubSysVer), BIGVERSION_MINOR(WinHdr->SubSysVer)); printf("Size of Image: 0x%08lX\n", WinHdr->SizeOfImage); printf("Size of Headers: 0x%08lX\n", WinHdr->SizeOfHeaders); printf("Checksum: 0x%08lX\n", WinHdr->CheckSum); printf("Subsystem: 0x%04X\n", WinHdr->Subsystem); printf("DLL Flags: 0x%04X\n", WinHdr->DLLFlags); printf("Sizeof Stack Resv: 0x%08lX\n", WinHdr->SizeOfStackReserve); printf("Sizeof Stack Comm: 0x%08lX\n", WinHdr->SizeOfStackCommit); printf("Sizeof Heap Resv: 0x%08lX\n", WinHdr->SizeOfHeapReserve); printf("Sizeof Heap Comm: 0x%08lX\n", WinHdr->SizeOfHeapCommit); printf("Loader Flags: 0x%08lX\n", WinHdr->LoaderFlags); printf("Num Directories: %ld\n", WinHdr->NumDirectories); printf("\n"); } void CoffLoader::PrintSection(SectionHeader_t* ScnHdr, const char* data) { char SectionName[9]; strncpy(SectionName, (char *)ScnHdr->Name, 8); SectionName[8] = 0; printf("Section: %s\n", SectionName); printf("------------------------------------------\n\n"); printf("Virtual Size: 0x%08lX\n", ScnHdr->VirtualSize); printf("Virtual Address: 0x%08lX\n", ScnHdr->VirtualAddress); printf("Sizeof Raw Data: 0x%08lX\n", ScnHdr->SizeOfRawData); printf("Ptr To Raw Data: 0x%08lX\n", ScnHdr->PtrToRawData); printf("Ptr To Relocations: 0x%08lX\n", ScnHdr->PtrToRelocations); printf("Ptr To Line Nums: 0x%08lX\n", ScnHdr->PtrToLineNums); printf("Num Relocations: 0x%04X\n", ScnHdr->NumRelocations); printf("Num Line Numbers: 0x%04X\n", ScnHdr->NumLineNumbers); printf("Characteristics: 0x%08lX\n", ScnHdr->Characteristics); if (ScnHdr->Characteristics & IMAGE_SCN_CNT_CODE) printf(" IMAGE_SCN_CNT_CODE\n"); if (ScnHdr->Characteristics & IMAGE_SCN_CNT_DATA) printf(" IMAGE_SCN_CNT_DATA\n"); if (ScnHdr->Characteristics & IMAGE_SCN_CNT_BSS) printf(" IMAGE_SCN_CNT_BSS\n"); if (ScnHdr->Characteristics & IMAGE_SCN_LNK_INFO) printf(" IMAGE_SCN_LNK_INFO\n"); if (ScnHdr->Characteristics & IMAGE_SCN_LNK_REMOVE) printf(" IMAGE_SCN_LNK_REMOVE\n"); if (ScnHdr->Characteristics & IMAGE_SCN_LNK_COMDAT) printf(" IMAGE_SCN_LNK_COMDAT\n"); if ((ScnHdr->Characteristics & IMAGE_SCN_ALIGN_MASK) == IMAGE_SCN_ALIGN_1BYTES) printf(" IMAGE_SCN_ALIGN_1BYTES\n"); if ((ScnHdr->Characteristics & IMAGE_SCN_ALIGN_MASK) == IMAGE_SCN_ALIGN_2BYTES) printf(" IMAGE_SCN_ALIGN_2BYTES\n"); if ((ScnHdr->Characteristics & IMAGE_SCN_ALIGN_MASK) == IMAGE_SCN_ALIGN_4BYTES) printf(" IMAGE_SCN_ALIGN_4BYTES\n"); if ((ScnHdr->Characteristics & IMAGE_SCN_ALIGN_MASK) == IMAGE_SCN_ALIGN_8BYTES) printf(" IMAGE_SCN_ALIGN_8BYTES\n"); if ((ScnHdr->Characteristics & IMAGE_SCN_ALIGN_MASK) == IMAGE_SCN_ALIGN_16BYTES) printf(" IMAGE_SCN_ALIGN_16BYTES\n"); if ((ScnHdr->Characteristics & IMAGE_SCN_ALIGN_MASK) == IMAGE_SCN_ALIGN_32BYTES) printf(" IMAGE_SCN_ALIGN_32BYTES\n"); if ((ScnHdr->Characteristics & IMAGE_SCN_ALIGN_MASK) == IMAGE_SCN_ALIGN_64BYTES) printf(" IMAGE_SCN_ALIGN_64BYTES\n"); if ((ScnHdr->Characteristics & IMAGE_SCN_ALIGN_MASK) == IMAGE_SCN_ALIGN_128BYTES) printf(" IMAGE_SCN_ALIGN_128BYTES\n"); if ((ScnHdr->Characteristics & IMAGE_SCN_ALIGN_MASK) == IMAGE_SCN_ALIGN_256BYTES) printf(" IMAGE_SCN_ALIGN_256BYTES\n"); if ((ScnHdr->Characteristics & IMAGE_SCN_ALIGN_MASK) == IMAGE_SCN_ALIGN_512BYTES) printf(" IMAGE_SCN_ALIGN_512BYTES\n"); if ((ScnHdr->Characteristics & IMAGE_SCN_ALIGN_MASK) == IMAGE_SCN_ALIGN_1024BYTES) printf(" IMAGE_SCN_ALIGN_1024BYTES\n"); if ((ScnHdr->Characteristics & IMAGE_SCN_ALIGN_MASK) == IMAGE_SCN_ALIGN_2048BYTES) printf(" IMAGE_SCN_ALIGN_2048BYTES\n"); if ((ScnHdr->Characteristics & IMAGE_SCN_ALIGN_MASK) == IMAGE_SCN_ALIGN_4096BYTES) printf(" IMAGE_SCN_ALIGN_4096BYTES\n"); if ((ScnHdr->Characteristics & IMAGE_SCN_ALIGN_MASK) == IMAGE_SCN_ALIGN_8192BYTES) printf(" IMAGE_SCN_ALIGN_8192BYTES\n"); if (ScnHdr->Characteristics & IMAGE_SCN_LNK_NRELOC_OVFL) printf(" IMAGE_SCN_LNK_NRELOC_OVFL\n"); if (ScnHdr->Characteristics & IMAGE_SCN_MEM_DISCARDABLE) printf(" IMAGE_SCN_MEM_DISCARDABLE\n"); if (ScnHdr->Characteristics & IMAGE_SCN_MEM_NOT_CACHED) printf(" IMAGE_SCN_MEM_NOT_CACHED\n"); if (ScnHdr->Characteristics & IMAGE_SCN_MEM_NOT_PAGED) printf(" IMAGE_SCN_MEM_NOT_PAGED\n"); if (ScnHdr->Characteristics & IMAGE_SCN_MEM_SHARED) printf(" IMAGE_SCN_MEM_SHARED\n"); if (ScnHdr->Characteristics & IMAGE_SCN_MEM_EXECUTE) printf(" IMAGE_SCN_MEM_EXECUTE\n"); if (ScnHdr->Characteristics & IMAGE_SCN_MEM_READ) printf(" IMAGE_SCN_MEM_READ\n"); if (ScnHdr->Characteristics & IMAGE_SCN_MEM_WRITE) printf(" IMAGE_SCN_MEM_WRITE\n"); printf("\n"); // Read the section Data, Relocations, & Line Nums // Save the offset if (ScnHdr->SizeOfRawData > 0) { unsigned int i; // Print the Raw Data printf("\nRAW DATA"); for (i = 0; i < ScnHdr->VirtualSize; i++) { if ((i % 16) == 0) printf("\n %08X: ", i); char ch = data[i]; printf("%02X ", (unsigned int)ch); } printf("\n\n"); } /* #if 0 if (ScnHdr->NumRelocations > 0) { // Print Section Relocations ObjReloc_t ObjReloc; fseek(fp, ScnHdr->PtrToRelocations/ * + CoffBeginOffset* /, SEEK_SET); printf("RELOCATIONS\n"); printf(" Symbol Symbol\n"); printf(" Offset Type Index Name\n"); printf(" -------- -------- -------- ------\n"); for (int i = 0; i < ScnHdr->NumRelocations; i++) { fread(&ObjReloc, 1, sizeof(ObjReloc_t), fp); printf(" %08X ", ObjReloc.VirtualAddress); if (ObjReloc.Type == IMAGE_REL_I386_ABSOLUTE) printf("ABSOLUTE "); if (ObjReloc.Type == IMAGE_REL_I386_DIR16) printf("DIR16 "); if (ObjReloc.Type == IMAGE_REL_I386_REL16) printf("REL16 "); if (ObjReloc.Type == IMAGE_REL_I386_DIR32) printf("DIR32 "); if (ObjReloc.Type == IMAGE_REL_I386_DIR32NB) printf("DIR32NB "); if (ObjReloc.Type == IMAGE_REL_I386_SEG12) printf("SEG12 "); if (ObjReloc.Type == IMAGE_REL_I386_SECTION) printf("SECTION "); if (ObjReloc.Type == IMAGE_REL_I386_SECREL) printf("SECREL "); if (ObjReloc.Type == IMAGE_REL_I386_REL32) printf("REL32 "); printf("%8X ", ObjReloc.SymTableIndex); printf("%s\n", GetSymbolName(ObjReloc.SymTableIndex)); } printf("\n"); } if (ScnHdr->NumLineNumbers > 0) { // Print The Line Number Info LineNumbers_t LineNumber; int LineCnt = 0; int BaseLineNum = -1; fseek(fp, ScnHdr->PtrToLineNums/ * + CoffBeginOffset* /, SEEK_SET); printf("LINE NUMBERS"); for (int i = 0; i < ScnHdr->NumLineNumbers; i++) { int LNOffset = ftell(fp); fread(&LineNumber, 1, sizeof(LineNumbers_t), fp); if (LineNumber.LineNum == 0) { SymbolTable_t *Sym; int SymIndex; printf("\n"); SymIndex = LineNumber.Type.SymbolTableIndex; Sym = &(SymTable[SymIndex]); if (Sym->NumberOfAuxSymbols > 0) { Sym = &(SymTable[SymIndex+1]); AuxFuncDef_t *FuncDef = (AuxFuncDef_t *)Sym; if (FuncDef->PtrToLineNumber == LNOffset) { Sym = &(SymTable[FuncDef->TagIndex]); if (Sym->NumberOfAuxSymbols > 0) { Sym = &(SymTable[FuncDef->TagIndex+1]); AuxBfEf_t *Bf = (AuxBfEf_t *)Sym; BaseLineNum = Bf->LineNumber; } } } printf(" Symbol Index: %8x ", SymIndex); printf(" Base line number: %8d\n", BaseLineNum); printf(" Symbol name = %s", GetSymbolName(SymIndex)); LineCnt = 0; } else { if ((LineCnt%4) == 0) { printf("\n "); LineCnt = 0; } printf("%08X(%5d) ", LineNumber.Type.VirtualAddress, LineNumber.LineNum + BaseLineNum); LineCnt ++; } } printf("\n"); } #endif */ printf("\n"); } int CoffLoader::ParseCoff(FILE *fp) { if ( !LoadCoffHModule(fp) ) { printf("Failed to load/find COFF hModule header\n"); return 0; } if ( !LoadSymTable(fp) || !LoadStringTable(fp) || !LoadSections(fp) ) return 0; PerformFixups(); #ifdef DUMPING_DATA PrintSymbolTable(); PrintStringTable(); #endif return 1; } void CoffLoader::PerformFixups(void) { int FixupDataSize; char *FixupData; char *EndData; EntryAddress = (unsigned long)RVA2Data(EntryAddress); if( reinterpret_cast(WindowsHeader->ImageBase) == hModule ) return; if ( !Directory ) return ; if ( NumOfDirectories <= BASE_RELOCATION_TABLE ) return ; if ( !Directory[BASE_RELOCATION_TABLE].Size ) return ; FixupDataSize = Directory[BASE_RELOCATION_TABLE].Size; FixupData = (char*)RVA2Data(Directory[BASE_RELOCATION_TABLE].RVA); EndData = FixupData + FixupDataSize; while (FixupData < EndData) { // Starting a new Fixup Block unsigned long PageRVA = *((unsigned long*)FixupData); FixupData += 4; unsigned long BlockSize = *((unsigned long*)FixupData); FixupData += 4; BlockSize -= 8; for (unsigned int i = 0; i < BlockSize / 2; i++) { unsigned short Fixup = *((unsigned short*)FixupData); FixupData += 2; int Type = (Fixup >> 12) & 0x0f; Fixup &= 0xfff; if (Type == IMAGE_REL_BASED_HIGHLOW) { unsigned long *Off = (unsigned long*)RVA2Data(Fixup + PageRVA); *Off = (unsigned long)RVA2Data(*Off - WindowsHeader->ImageBase); } else if (Type == IMAGE_REL_BASED_ABSOLUTE) {} else { printf("Unsupported fixup type!!\n"); } } } }