diff options
| author | Rusty Wagner <rusty.wagner@gmail.com> | 2024-03-06 19:20:34 -0500 |
|---|---|---|
| committer | Rusty Wagner <rusty.wagner@gmail.com> | 2024-03-06 19:20:34 -0500 |
| commit | 828fff839f4e4de3e9582405dfec567531000ebc (patch) | |
| tree | ee0db0607edb0c76c653078672201c85e8a96d19 /view/pe/coffview.h | |
| parent | 47894a1ce20090849ad304c68e6c0b889665eda3 (diff) | |
Move view modules into the API repo
Diffstat (limited to 'view/pe/coffview.h')
| -rw-r--r-- | view/pe/coffview.h | 372 |
1 files changed, 372 insertions, 0 deletions
diff --git a/view/pe/coffview.h b/view/pe/coffview.h new file mode 100644 index 00000000..b1cf7780 --- /dev/null +++ b/view/pe/coffview.h @@ -0,0 +1,372 @@ +#pragma once + +#include "binaryninjaapi.h" +#include "peview.h" +#include <exception> + +#ifdef WIN32 +#pragma warning(disable: 4005) +#endif + +#define IMAGE_SYM_TYPE_NULL 0 // No type information or unknown base type. +#define IMAGE_SYM_TYPE_VOID 1 // Used with void pointers and functions. +#define IMAGE_SYM_TYPE_CHAR 2 // A character (signed byte). +#define IMAGE_SYM_TYPE_SHORT 3 // A 2-byte signed integer. +#define IMAGE_SYM_TYPE_INT 4 // A natural integer type on the target. +#define IMAGE_SYM_TYPE_LONG 5 // A 4-byte signed integer. +#define IMAGE_SYM_TYPE_FLOAT 6 // A 4-byte floating-point number. +#define IMAGE_SYM_TYPE_DOUBLE 7 // An 8-byte floating-point number. +#define IMAGE_SYM_TYPE_STRUCT 8 // A structure. +#define IMAGE_SYM_TYPE_UNION 9 // An union. +#define IMAGE_SYM_TYPE_ENUM 10 // An enumerated type. +#define IMAGE_SYM_TYPE_MOE 11 // A member of enumeration (a specific value). +#define IMAGE_SYM_TYPE_BYTE 12 // A byte; unsigned 1-byte integer. +#define IMAGE_SYM_TYPE_WORD 13 // A word; unsigned 2-byte integer. +#define IMAGE_SYM_TYPE_UINT 14 // An unsigned integer of natural size. +#define IMAGE_SYM_TYPE_DWORD 15 // An unsigned 4-byte integer. + +#define MS_IMAGE_SYM_TYPE_FUNCTION 0x20 // Microsoft-specific + +#define IMAGE_REL_I386_ABSOLUTE 0x0000 +#define IMAGE_REL_I386_DIR16 0x0001 +#define IMAGE_REL_I386_REL16 0x0002 +#define IMAGE_REL_I386_DIR32 0x0006 +#define IMAGE_REL_I386_DIR32NB 0x0007 +#define IMAGE_REL_I386_SEG12 0x0009 +#define IMAGE_REL_I386_SECTION 0x000A +#define IMAGE_REL_I386_SECREL 0x000B +#define IMAGE_REL_I386_TOKEN 0x000C +#define IMAGE_REL_I386_SECREL7 0x000D +#define IMAGE_REL_I386_REL32 0x0014 + +#define IMAGE_REL_AMD64_ABSOLUTE 0x0000 +#define IMAGE_REL_AMD64_ADDR64 0x0001 +#define IMAGE_REL_AMD64_ADDR32 0x0002 +#define IMAGE_REL_AMD64_ADDR32NB 0x0003 +#define IMAGE_REL_AMD64_REL32 0x0004 +#define IMAGE_REL_AMD64_REL32_1 0x0005 +#define IMAGE_REL_AMD64_REL32_2 0x0006 +#define IMAGE_REL_AMD64_REL32_3 0x0007 +#define IMAGE_REL_AMD64_REL32_4 0x0008 +#define IMAGE_REL_AMD64_REL32_5 0x0009 +#define IMAGE_REL_AMD64_SECTION 0x000A +#define IMAGE_REL_AMD64_SECREL 0x000B +#define IMAGE_REL_AMD64_SECREL7 0x000C +#define IMAGE_REL_AMD64_TOKEN 0x000D +#define IMAGE_REL_AMD64_SREL32 0x000E +#define IMAGE_REL_AMD64_PAIR 0x000F +#define IMAGE_REL_AMD64_SSPAN32 0x0010 + +#define IMAGE_REL_ARM_ABSOLUTE 0x0000 +#define IMAGE_REL_ARM_ADDR32 0x0001 +#define IMAGE_REL_ARM_ADDR32NB 0x0002 +#define IMAGE_REL_ARM_BRANCH24 0x0003 +#define IMAGE_REL_ARM_BRANCH11 0x0004 +#define IMAGE_REL_ARM_BLX24 0x0008 +#define IMAGE_REL_ARM_BLX11 0x0009 +#define IMAGE_REL_ARM_REL32 0x000A +#define IMAGE_REL_ARM_SECTION 0x000E +#define IMAGE_REL_ARM_SECREL 0x000F +#define IMAGE_REL_ARM_MOV32 0x0010 +#define IMAGE_REL_THUMB_MOV32 0x0011 +#define IMAGE_REL_THUMB_BRANCH20 0x0012 +#define IMAGE_REL_THUMB_UNUSED 0x0013 +#define IMAGE_REL_THUMB_BRANCH24 0x0014 +#define IMAGE_REL_THUMB_BLX23 0x0015 +#define IMAGE_REL_ARM_PAIR 0x0016 + +// The following names for armv7/thumb2 relocations are from LLVM source, +// but are commented out in favor of the names defined above, +// which correspond to Microsoft PE Format documentation: +// https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#type-indicators +// #define IMAGE_REL_ARM_ABSOLUTE 0x0000 +// #define IMAGE_REL_ARM_ADDR32 0x0001 +// #define IMAGE_REL_ARM_ADDR32NB 0x0002 +// #define IMAGE_REL_ARM_BRANCH24 0x0003 +// #define IMAGE_REL_ARM_BRANCH11 0x0004 +// #define IMAGE_REL_ARM_TOKEN 0x0005 +// #define IMAGE_REL_ARM_BLX24 0x0008 +// #define IMAGE_REL_ARM_BLX11 0x0009 +// #define IMAGE_REL_ARM_REL32 0x000A +// #define IMAGE_REL_ARM_SECTION 0x000E +// #define IMAGE_REL_ARM_SECREL 0x000F +// #define IMAGE_REL_ARM_MOV32A 0x0010 +// #define IMAGE_REL_ARM_MOV32T 0x0011 +// #define IMAGE_REL_ARM_BRANCH20T 0x0012 +// #define IMAGE_REL_ARM_BRANCH24T 0x0014 +// #define IMAGE_REL_ARM_BLX23T 0x0015 +// #define IMAGE_REL_ARM_PAIR 0x0016 + +#define IMAGE_REL_ARM64_ABSOLUTE 0x0000 +#define IMAGE_REL_ARM64_ADDR32 0x0001 +#define IMAGE_REL_ARM64_ADDR32NB 0x0002 +#define IMAGE_REL_ARM64_BRANCH26 0x0003 +#define IMAGE_REL_ARM64_PAGEBASE_REL21 0x0004 +#define IMAGE_REL_ARM64_REL21 0x0005 +#define IMAGE_REL_ARM64_PAGEOFFSET_12A 0x0006 +#define IMAGE_REL_ARM64_PAGEOFFSET_12L 0x0007 +#define IMAGE_REL_ARM64_SECREL 0x0008 +#define IMAGE_REL_ARM64_SECREL_LOW12A 0x0009 +#define IMAGE_REL_ARM64_SECREL_HIGH12A 0x000A +#define IMAGE_REL_ARM64_SECREL_LOW12L 0x000B +#define IMAGE_REL_ARM64_TOKEN 0x000C +#define IMAGE_REL_ARM64_SECTION 0x000D +#define IMAGE_REL_ARM64_ADDR64 0x000E +#define IMAGE_REL_ARM64_BRANCH19 0x000F +#define IMAGE_REL_ARM64_BRANCH14 0x0010 +#define IMAGE_REL_ARM64_REL32 0x0011 + +namespace BinaryNinja +{ + class COFFFormatException: public std::exception + { + std::string m_message; + + public: + COFFFormatException(const std::string& msg = "invalid format"): m_message(msg) {} + virtual const char* what() const NOEXCEPT { return m_message.c_str(); } + }; + + #pragma pack(push, 2) + struct COFFHeader + { + uint16_t machine; + uint16_t sectionCount; + uint32_t timestamp; + uint32_t coffSymbolTable; + uint32_t coffSymbolCount; + uint16_t optionalHeaderSize; + uint16_t characteristics; + }; + + // Use this for sizeof + struct COFFSectionHeader + { + uint8_t name[8]; + union + { + uint32_t virtualSize; + uint32_t physicalAddress; + }; + uint32_t virtualAddress; + uint32_t sizeOfRawData; + uint32_t pointerToRawData; + uint32_t pointerToRelocs; + uint32_t pointerToLineNumbers; + uint16_t relocCount; + uint16_t lineNumberCount; + uint32_t characteristics; + }; + + // Can only find reference to this alernate COFF header in the LLVM source and docs: + // https://llvm.org/doxygen/structllvm_1_1COFF_1_1BigObjHeader.html + // https://github.com/llvm/llvm-project/commit/44f51e511374f467d70c37324a8e5bbf2ea270d8#diff-c8c9ae93373622c2303ca157ecdc8bf16204567b57e391381ed4740e0c38c82aR67-R82 + struct BigObj_COFFHeader + { + uint16_t sig1; ///< Must be IMAGE_FILE_MACHINE_UNKNOWN (0). + uint16_t sig2; ///< Must be 0xFFFF. + uint16_t version; + uint16_t machine; + uint32_t timestamp; + uint8_t UUID[16]; + uint32_t unused1; + uint32_t unused2; + uint32_t unused3; + uint32_t unused4; + uint32_t sectionCount; + uint32_t coffSymbolTable; + uint32_t coffSymbolCount; + }; + + struct COFFSection + { + std::string name; + union + { + uint32_t virtualSize; + uint32_t physicalAddress; + }; + uint32_t virtualAddress; + uint32_t sizeOfRawData; + uint32_t pointerToRawData; + uint32_t pointerToRelocs; + uint32_t pointerToLineNumbers; + uint16_t relocCount; + uint16_t lineNumberCount; + uint32_t characteristics; + }; + + + template<typename SectionCountType> struct _COFFSymbol + { + union + { + char shortName[8]; + struct { + uint32_t zeroes; + uint32_t offset; + } longName; + } name; + uint32_t value; + // 1-based index into section table + SectionCountType sectionNumber; + uint16_t type; + uint8_t storageClass; + uint8_t numberOfAuxSymbols; + }; + + using COFFSymbol16 = _COFFSymbol<uint16_t>; + using COFFSymbol32 = _COFFSymbol<uint32_t>; + + struct COFFSymbol + { + union + { + char shortName[8]; + struct { + uint32_t zeroes; + uint32_t offset; + } longName; + } name; + uint32_t value; + // 1-based index into section table + union { int16_t i16; int32_t i32; } sectionNumber; + uint16_t type; + uint8_t storageClass; + uint8_t numberOfAuxSymbols; + }; + + struct COFFAuxFunctionDefinition + { + uint32_t tagIndex; + uint32_t totalSize; + uint32_t pointerToLineNumber; + uint32_t pointerToNextFunction; + uint8_t unused[2]; + }; + + struct COFFAux_bf_And_ef_Symbol + { + uint8_t unused0[4]; + uint16_t lineNumber; + uint8_t unused6[6]; + uint32_t pointerToNextFunction; + uint8_t unused16[2]; + }; + + struct COFFAuxWeakExternal + { + uint32_t tagIndex; + uint32_t characteristics; + uint8_t unused[10]; + }; + + struct COFFAuxFile + { + uint8_t fileName[18]; + }; + + #pragma pack(push, 1) + struct COFFAuxSectionDefinition + { + uint32_t length; + uint16_t numberOfRelocations; + uint16_t numberOfLineNumbers; + uint32_t checkSum; + uint16_t number; + uint8_t selection; + union { + uint8_t unused3[3]; + struct + { + uint8_t unused; + uint16_t numberHighPart; + }; + }; + }; + #pragma pack(pop) + + union COFFAuxSymbolRecord + { + COFFAuxFunctionDefinition functionDefinition; + COFFAux_bf_And_ef_Symbol bf_And_ef_Symbol; + COFFAuxWeakExternal weakExternal; + COFFAuxFile file; + COFFAuxSectionDefinition sectionDefinition; + }; + + struct COFFRelocation + { + uint32_t virtualAddress; + uint32_t symbolTableIndex; + // union + // { + // enum x64_coff_reloc_type x64_type; + // enum arm_coff_reloc_type arm_type; + // enum x86_coff_reloc_type x86_type; + uint16_t type; + // }; + // COFFRelocation(uint32_t va, uint32_t i, uint16_t t) : virtualAddress(va), symbolTableIndex(i), type(t) {} + }; + + struct COFF_PdataFunctionTableEntry + { + uint32_t beginAddress; + uint32_t endAddress; + uint32_t unwindInformation; + }; + + #pragma pack(pop) + + class COFFView : public BinaryView + { + bool m_parseOnly; + uint64_t m_entryPoint; + + uint64_t m_imageBase; + uint32_t m_sizeOfHeaders; + std::vector<COFFSection> m_sections; + std::vector<COFFRelocation> m_relocs; + Ref<Architecture> m_arch; + bool m_is64; + bool m_extractMangledTypes; + bool m_simplifyTemplates; + bool m_relocatable = false; + + virtual uint64_t PerformGetEntryPoint() const override; + + virtual bool PerformIsExecutable() const override { return true; } + virtual BNEndianness PerformGetDefaultEndianness() const override { return LittleEndian; } + virtual bool PerformIsRelocatable() const override { return m_relocatable; } + virtual size_t PerformGetAddressSize() const override; + + uint64_t RVAToFileOffset(uint64_t rva, bool except = true); + uint32_t GetRVACharacteristics(uint64_t rva); + std::string ReadString(uint64_t rva); + uint16_t Read16(uint64_t rva); + uint32_t Read32(uint64_t rva); + uint64_t Read64(uint64_t rva); + void AddCOFFSymbol(BNSymbolType type, const std::string& dll, const std::string& name, uint64_t addr, + BNSymbolBinding binding = NoBinding, uint64_t ordinal = 0, TypeLibrary* lib = nullptr); + // void COFFView::GetRelocs(BinaryReader& reader, const vector<COFFSection>& sections, vector<COFFRelocation>& result, const QualifiedName& coffRelocTypeName, const map<uint64_t, string>& symbolNames); + + public: + COFFView(BinaryView* data, bool parseOnly = false); + + virtual bool Init() override; + }; + + class COFFViewType: public BinaryViewType + { + public: + COFFViewType(); + virtual Ref<BinaryView> Create(BinaryView* data) override; + virtual Ref<BinaryView> Parse(BinaryView* data) override; + virtual bool IsTypeValidForData(BinaryView* data) override; + virtual Ref<Settings> GetLoadSettingsForData(BinaryView* data) override; + static bool IsValidMachineType(uint16_t machineType); + static bool IsSupportedMachineType(uint16_t machineType); + }; + + void InitCOFFViewType(); +} |
