From a17853bb2082291306a04281cf672dc69f5fe7eb Mon Sep 17 00:00:00 2001 From: Brandon Miller Date: Sun, 10 Mar 2024 20:55:48 -0400 Subject: BinaryView for EFI Terse Executables In its current state it is able to detect and load TEs that target x86, x86-64, and AArch64. RISC-V will need to be added in the future The current implementation doesn't handle relocations. I have only found TEs that are PEIMs and execute in-place (out of flash) and the .reloc section is stripped (along with .debug) --- view/pe/teview.h | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 view/pe/teview.h (limited to 'view/pe/teview.h') diff --git a/view/pe/teview.h b/view/pe/teview.h new file mode 100644 index 00000000..230539b5 --- /dev/null +++ b/view/pe/teview.h @@ -0,0 +1,97 @@ +#pragma once + +#include "binaryninjaapi.h" +#include "peview.h" + +#ifdef WIN32 +#pragma warning(disable: 4005) +#endif + + +// EFI_IMAGE_DATA_DIRECTORY +struct TEImageDataDirectory { + uint32_t virtualAddress; + uint32_t size; +}; + +#define EFI_TE_IMAGE_HEADER_SIZE 40 +#define EFI_TE_SECTION_HEADER_SIZE 40 + +// EFI section header characteristics bit masks +#define EFI_IMAGE_SCN_MEM_EXECUTE 0x20000000 +#define EFI_IMAGE_SCN_MEM_READ 0x40000000 +#define EFI_IMAGE_SCN_MEM_WRITE 0x80000000 + +// EFI_TE_IMAGE_HEADER +struct TEImageHeader { + uint16_t magic; + uint16_t machine; + uint8_t numberOfSections; + uint8_t subsystem; + uint16_t strippedSize; + uint32_t addressOfEntrypoint; + uint32_t baseOfCode; + uint64_t imageBase; + struct TEImageDataDirectory dataDirectory[2]; +}; + +// EFI_IMAGE_SECTION_HEADER +struct TEImageSectionHeader { + std::string name; // 8 bytes + uint32_t virtualSize; + uint32_t virtualAddress; + uint32_t sizeOfRawData; + uint32_t pointerToRawData; + uint32_t pointerToRelocations; + uint32_t pointerToLineNumbers; + uint16_t numberOfRelocations; + uint16_t numberOfLineNumbers; + uint32_t characteristics; +}; + +namespace BinaryNinja +{ + class TEView: public BinaryView + { + bool m_parseOnly; + std::vector m_sections; + bool m_relocatable = false; + Ref m_logger; + bool m_backedByDatabase; + uint64_t m_imageBase; + Ref m_arch; + uint64_t m_entryPoint; + + protected: + 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; + + public: + TEView(BinaryView* data, bool parseOnly = false); + virtual bool Init() override; + + private: + void ReadTEImageHeader(BinaryReader& reader, struct TEImageHeader& imageHeader); + void ReadTEImageSectionHeaders(BinaryReader& reader, uint32_t numSections); + void HandleUserOverrides(); + void CreateSections(); + void AssignHeaderTypes(); + }; + + class TEViewType: public BinaryViewType + { + Ref m_logger; + + public: + TEViewType(); + virtual Ref Create(BinaryView* data) override; + virtual Ref Parse(BinaryView* data) override; + virtual bool IsTypeValidForData(BinaryView* data) override; + virtual Ref GetLoadSettingsForData(BinaryView* data) override; + }; + + void InitTEViewType(); +} -- cgit v1.3.1