//------------------------------------------------ //--- 010 Editor v4.0.3 Binary Template // // File: COFF.bt // Authors: guage // E-mail: zhaopeiyuan6@gmail.com // Website: https://guage.cool https://github.com/howmp/ // Version: 0.2 // Purpose: Parse Common Object File Format files. // Supports 32 and 64 bit. // Category: Executable // File Mask: *.o,*.obj,*.exp // ID Bytes: 4C 01, 00 20, 66 03, 66 04, f0 10, f1 01, 68 02, c0 01, 84 01, 64 86, 64 AA // History: // 0.2 2023-12-15 OS: Added ID bytes for AMD64, ARM64 // 0.1 2022-08-12 guage: Initial commit // // Recommended reading: // 1. https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#other-contents-of-the-file // 2. https://github.com/llvm/llvm-project/blob/main/llvm/include/llvm/BinaryFormat/COFF.h typedef struct { WORD IMAGE_FILE_RELOCS_STRIPPED:1 ; WORD IMAGE_FILE_EXECUTABLE_IMAGE:1 ; WORD IMAGE_FILE_LINE_NUMS_STRIPPED:1 ; WORD IMAGE_FILE_LOCAL_SYMS_STRIPPED:1 ; WORD IMAGE_FILE_AGGRESIVE_WS_TRIM:1 ; WORD IMAGE_FILE_LARGE_ADDRESS_AWARE:1 2gb addresses">; WORD :1 ; WORD IMAGE_FILE_BYTES_REVERSED_LO:1 ; WORD IMAGE_FILE_32BIT_MACHINE:1 ; WORD IMAGE_FILE_DEBUG_STRIPPED:1 ; WORD IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP:1 ; WORD IMAGE_FILE_NET_RUN_FROM_SWAP:1 ; WORD IMAGE_FILE_SYSTEM:1 ; WORD IMAGE_FILE_DLL:1 ; WORD IMAGE_FILE_UP_SYSTEM_ONLY:1 ; WORD IMAGE_FILE_BYTES_REVERSED_HI:1 ; } FILE_CHARACTERISTICS ; typedef enum { IMAGE_MACHINE_UNKNOWN = 0, I386 = 0x014c, // Intel 386 or later processors and compatible processors R3000 = 0x0162, // MIPS little-endian, 0x160 big-endian R4000 = 0x0166, // MIPS little-endian R10000 = 0x0168, // MIPS little-endian WCEMIPSV2 = 0x0169, // MIPS little-endian WCE v2 ALPHA = 0x0184, // Alpha_AXP SH3 = 0x01a2, // Hitachi SH3 SH3DSP = 0x01a3, // Hitachi SH3 DSP SH3E = 0x01a4, // Hitachi SH3E little-endian SH4 = 0x01a6, // Hitachi SH4 SH5 = 0x01a8, // Hitachi SH5 ARM = 0x01c0, // ARM little-endian THUMB = 0x01c2, // Thumb ARMNT = 0x01c4, // Arm Thumb-2 little-endian AM33 = 0x01d3, // Matsushita AM33 POWERPC = 0x01f0, // Power PC little endian POWERPCFP = 0x01f1, // Power PC with floating point support IA64 = 0x0200, // Intel Itanium processor family MIPS16 = 0x0266, // MIPS16 ALPHA64 = 0x0284, // ALPHA64 MIPSFPU = 0x0366, // MIPS with FPU MIPSFPU16 = 0x0466, // MIPS16 with FPU TRICORE = 0x0520, // Infineon CEF = 0x0CEF, EBC = 0x0EBC, // EFI Byte Code RISCV32 = 0x5032, // RISC-V 32-bit address space RISCV64 = 0x5064, // RISC-V 64-bit address space RISCV128 = 0x5128, // RISC-V 128-bit address space AMD64 = 0x8664, // x64 M32R = 0x9041, // Mitsubishi M32R little-endian ARM64 = 0xAA64, // ARM64 little-endian CEE = 0xC0EE } IMAGE_MACHINE ; typedef enum { I386_ABSOLUTE = 0x0000, I386_DIR16 = 0x0001, I386_REL16 = 0x0002, I386_DIR32 = 0x0006, I386_DIR32NB = 0x0007, I386_SEG12 = 0x0009, I386_SECTION = 0x000A, I386_SECREL = 0x000B, I386_TOKEN = 0x000C, I386_SECREL7 = 0x000D, I386_REL32 = 0x0014 } RelocationTypeI386; typedef enum { AMD64_ABSOLUTE = 0x0000, AMD64_ADDR64 = 0x0001, AMD64_ADDR32 = 0x0002, AMD64_ADDR32NB = 0x0003, AMD64_REL32 = 0x0004, AMD64_REL32_1 = 0x0005, AMD64_REL32_2 = 0x0006, AMD64_REL32_3 = 0x0007, AMD64_REL32_4 = 0x0008, AMD64_REL32_5 = 0x0009, AMD64_SECTION = 0x000A, AMD64_SECREL = 0x000B, AMD64_SECREL7 = 0x000C, AMD64_TOKEN = 0x000D, AMD64_SREL32 = 0x000E, AMD64_PAIR = 0x000F, AMD64_SSPAN32 = 0x0010 } RelocationTypeAMD64; typedef enum { ARM_ABSOLUTE = 0x0000, ARM_ADDR32 = 0x0001, ARM_ADDR32NB = 0x0002, ARM_BRANCH24 = 0x0003, ARM_BRANCH11 = 0x0004, ARM_TOKEN = 0x0005, ARM_BLX24 = 0x0008, ARM_BLX11 = 0x0009, ARM_REL32 = 0x000A, ARM_SECTION = 0x000E, ARM_SECREL = 0x000F, ARM_MOV32A = 0x0010, ARM_MOV32T = 0x0011, ARM_BRANCH20T = 0x0012, ARM_BRANCH24T = 0x0014, ARM_BLX23T = 0x0015, ARM_PAIR = 0x0016, } RelocationTypesARM; typedef enum { ARM64_ABSOLUTE = 0x0000, ARM64_ADDR32 = 0x0001, ARM64_ADDR32NB = 0x0002, ARM64_BRANCH26 = 0x0003, ARM64_PAGEBASE_REL21 = 0x0004, ARM64_REL21 = 0x0005, ARM64_PAGEOFFSET_12A = 0x0006, ARM64_PAGEOFFSET_12L = 0x0007, ARM64_SECREL = 0x0008, ARM64_SECREL_LOW12A = 0x0009, ARM64_SECREL_HIGH12A = 0x000A, ARM64_SECREL_LOW12L = 0x000B, ARM64_TOKEN = 0x000C, ARM64_SECTION = 0x000D, ARM64_ADDR64 = 0x000E, ARM64_BRANCH19 = 0x000F, ARM64_BRANCH14 = 0x0010, ARM64_REL32 = 0x0011, } RelocationTypesARM64; typedef struct { ULONG IMAGE_SCN_TYPE_DSECT:1 ; ULONG IMAGE_SCN_TYPE_NOLOAD:1 ; ULONG IMAGE_SCN_TYPE_GROUP:1 ; ULONG IMAGE_SCN_TYPE_NO_PAD:1 ; ULONG IMAGE_SCN_TYPE_COPY:1 ; ULONG IMAGE_SCN_CNT_CODE:1 ; ULONG IMAGE_SCN_CNT_INITIALIZED_DATA:1 ; ULONG IMAGE_SCN_CNT_UNINITIALIZED_DATA:1 ; ULONG IMAGE_SCN_LNK_OTHER:1 ; ULONG IMAGE_SCN_LNK_INFO:1 ; ULONG IMAGE_SCN_TYPE_OVER:1 ; ULONG IMAGE_SCN_LNK_REMOVE:1 ; ULONG IMAGE_SCN_LNK_COMDAT:1 ; ULONG :1 ; ULONG IMAGE_SCN_NO_DEFER_SPEC_EXC:1 ; ULONG IMAGE_SCN_GPREL:1 ; ULONG IMAGE_SCN_MEM_SYSHEAP:1 ; ULONG IMAGE_SCN_MEM_16BIT:1 ; ULONG IMAGE_SCN_MEM_LOCKED:1 ; ULONG IMAGE_SCN_MEM_PRELOAD:1 ; ULONG IMAGE_SCN_ALIGN_1BYTES:1 ; ULONG IMAGE_SCN_ALIGN_2BYTES:1 ; ULONG IMAGE_SCN_ALIGN_8BYTES:1 ; ULONG IMAGE_SCN_ALIGN_128BYTES:1 ; ULONG IMAGE_SCN_LNK_NRELOC_OVFL:1 ; ULONG IMAGE_SCN_MEM_DISCARDABLE:1 ; ULONG IMAGE_SCN_MEM_NOT_CACHED:1 ; ULONG IMAGE_SCN_MEM_NOT_PAGED:1 ; ULONG IMAGE_SCN_MEM_SHARED:1 ; ULONG IMAGE_SCN_MEM_EXECUTE:1 ; ULONG IMAGE_SCN_MEM_READ:1 ; ULONG IMAGE_SCN_MEM_WRITE:1 ; } SECTION_CHARACTERISTICS; typedef enum { IMAGE_SYM_TYPE_NULL = 0, IMAGE_SYM_TYPE_VOID = 1, IMAGE_SYM_TYPE_CHAR = 2, IMAGE_SYM_TYPE_SHORT = 3, IMAGE_SYM_TYPE_INT = 4, IMAGE_SYM_TYPE_LONG = 5, IMAGE_SYM_TYPE_FLOAT = 6, IMAGE_SYM_TYPE_DOUBLE = 7, IMAGE_SYM_TYPE_STRUCT = 8, IMAGE_SYM_TYPE_UNION = 9, IMAGE_SYM_TYPE_ENUM = 10, IMAGE_SYM_TYPE_MOE = 11, IMAGE_SYM_TYPE_BYTE = 12, IMAGE_SYM_TYPE_WORD = 13, IMAGE_SYM_TYPE_UINT = 14, IMAGE_SYM_TYPE_DWORD = 15 } SymbolBaseType; typedef enum { IMAGE_SYM_DTYPE_NULL = 0, IMAGE_SYM_DTYPE_POINTER = 1, IMAGE_SYM_DTYPE_FUNCTION = 2, IMAGE_SYM_DTYPE_ARRAY = 3, } SymbolComplexType; /// Storage class tells where and what the symbol represents typedef enum { IMAGE_SYM_CLASS_END_OF_FUNCTION = -1, IMAGE_SYM_CLASS_NULL = 0, IMAGE_SYM_CLASS_AUTOMATIC = 1, IMAGE_SYM_CLASS_EXTERNAL = 2, IMAGE_SYM_CLASS_STATIC = 3, IMAGE_SYM_CLASS_REGISTER = 4, IMAGE_SYM_CLASS_EXTERNAL_DEF = 5, IMAGE_SYM_CLASS_LABEL = 6, IMAGE_SYM_CLASS_UNDEFINED_LABEL = 7, IMAGE_SYM_CLASS_MEMBER_OF_STRUCT = 8, IMAGE_SYM_CLASS_ARGUMENT = 9, IMAGE_SYM_CLASS_STRUCT_TAG = 10, IMAGE_SYM_CLASS_MEMBER_OF_UNION = 11, IMAGE_SYM_CLASS_UNION_TAG = 12, IMAGE_SYM_CLASS_TYPE_DEFINITION = 13, IMAGE_SYM_CLASS_UNDEFINED_STATIC = 14, IMAGE_SYM_CLASS_ENUM_TAG = 15, IMAGE_SYM_CLASS_MEMBER_OF_ENUM = 16, IMAGE_SYM_CLASS_REGISTER_PARAM = 17, IMAGE_SYM_CLASS_BIT_FIELD = 18, IMAGE_SYM_CLASS_BLOCK = 100, IMAGE_SYM_CLASS_FUNCTION = 101, IMAGE_SYM_CLASS_END_OF_STRUCT = 102, IMAGE_SYM_CLASS_FILE = 103, IMAGE_SYM_CLASS_SECTION = 104, IMAGE_SYM_CLASS_WEAK_EXTERNAL = 105, IMAGE_SYM_CLASS_CLR_TOKEN = 107 } SymbolStorageClass; typedef struct { IMAGE_MACHINE Machine ; WORD NumberOfSections ; time_t TimeDateStamp ; DWORD PointerToSymbolTable ; DWORD NumberOfSymbols; WORD SizeOfOptionalHeader; FILE_CHARACTERISTICS Characteristics ; } IMAGE_FILE_HEADER; typedef struct { BYTE Name[8] ; DWORD VirtualSize; DWORD VirtualAddress ; DWORD SizeOfRawData ; DWORD PointerToRawData ; DWORD PointerToRelocations ; DWORD PointerToLinenumbers; WORD NumberOfRelocations; WORD NumberOfLinenumbers; SECTION_CHARACTERISTICS Characteristics ; } IMAGE_SECTION_HEADER ; typedef struct (IMAGE_SECTION_HEADER& SecHeader) { local string sSecName = SecHeader.Name; if( sSecName == ".text" ) { // Disassemble .text section if( FileHeader.Machine == AMD64 ) DisasmSetMode( DISASM_X86_64 ); else if ( FileHeader.Machine == I386 ) DisasmSetMode( DISASM_X86_32 ); else if ( FileHeader.Machine == ARM ) DisasmSetMode( DISASM_ARM_32 ); else if ( FileHeader.Machine == ARM64 ) DisasmSetMode( DISASM_ARM_64 ); Opcode Data[SecHeader.SizeOfRawData]; } else UCHAR Data[SecHeader.SizeOfRawData]; } IMAGE_SECTION_DATA ; typedef struct (IMAGE_SECTION_HEADER& SecHeader) { local string sSecName = SecHeader.Name; DWORD VirtualAddress ; DWORD SymbolTableIndex; if( FileHeader.Machine == AMD64 ) RelocationTypeAMD64 Type; else if ( FileHeader.Machine == I386 ) RelocationTypeI386 Type; else if ( FileHeader.Machine == ARM ) RelocationTypesARM Type; else if ( FileHeader.Machine == ARM64 ) RelocationTypesARM64 Type; } IMAGE_RELOC_DATA ; typedef struct { union { BYTE Name[8]; struct { DWORD Zeroes ; DWORD Offset ; }LongName; } Name; DWORD Value ; WORD SectionNumber; SymbolBaseType BaseType:4; SymbolComplexType ComplexType:4; BYTE Reserved ; SymbolStorageClass StorageClass; BYTE NumberOfAuxSymbols; } IMAGE_SYMBOL_DATA ; typedef struct { BYTE Name[]; }String ;; string ReadImageSectionHeader(IMAGE_SECTION_HEADER& h) { return h.Name; } string ReadRelocData(IMAGE_RELOC_DATA& r){ return ReadImageSymbolData(Symbol[r.SymbolTableIndex]); } string ReadImageSymbolData(IMAGE_SYMBOL_DATA& s) { if(s.StorageClass == IMAGE_SYM_CLASS_NULL) return ""; if(s.Name.LongName.Zeroes !=0) return s.Name.Name; return ReadString(dwStringTableOffset + s.Name.LongName.Offset); } string ReadSectionData(IMAGE_SECTION_DATA& SecData) { if (SecData.sSecName[0] == '/'){ return ReadString(dwStringTableOffset + Atoi(SubStr(SecData.sSecName,1))); } return SecData.sSecName; } string ReadStringData(String& s) { return s.Name; } /**** PARSING CODE ****/ LittleEndian(); // COFF Header IMAGE_FILE_HEADER FileHeader ; // COFF Sections IMAGE_SECTION_HEADER SectionHeaders[FileHeader.NumberOfSections] ; // COFF Sections Data local ULONG sIndex=0; local ULONG rIndex=0; for (sIndex=0; sIndex < FileHeader.NumberOfSections; sIndex++) { if ( 0 == SectionHeaders[sIndex].PointerToRawData ) { continue; } if ( 0 == SectionHeaders[sIndex].SizeOfRawData ) { continue; } FSeek(SectionHeaders[sIndex].PointerToRawData); IMAGE_SECTION_DATA Section(SectionHeaders[sIndex]) ; } // COFF Relocations Data for (sIndex=0; sIndex < FileHeader.NumberOfSections; sIndex++) { if ( 0 == SectionHeaders[sIndex].NumberOfRelocations ) { continue; } FSeek(SectionHeaders[sIndex].PointerToRelocations); for (rIndex=0; rIndex < SectionHeaders[sIndex].NumberOfRelocations; rIndex++) { IMAGE_RELOC_DATA Reloc(SectionHeaders[sIndex]) ; } } // COFF Symbols Data FSeek(FileHeader.PointerToSymbolTable); for (sIndex=0; sIndex < FileHeader.NumberOfSymbols; sIndex++) { IMAGE_SYMBOL_DATA Symbol ; } // COFF String Data local DWORD dwStringTableOffset = FTell(); DWORD StringTableLen; while(!FEof()){ String StringTable ; }