From 39555ceb8576bb3ed241933b9b467b6db13c9fa5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 4 Sep 2025 02:48:26 +0000 Subject: [PATCH] Implement automatic endianness override for x86 ELF files --- view/elf/elfview.cpp | 61 ++++++++++++++++++++++++++++++++++++-------- view/elf/elfview.h | 2 +- 2 files changed, 52 insertions(+), 11 deletions(-) diff --git a/view/elf/elfview.cpp b/view/elf/elfview.cpp index e473795f19..8d0fde4676 100644 --- a/view/elf/elfview.cpp +++ b/view/elf/elfview.cpp @@ -40,19 +40,30 @@ void BinaryNinja::InitElfViewType() "description" : "Enable ARM BE8 binary detection for mixed little/big endianness for code/data", "ignore" : ["SettingsProjectScope", "SettingsResourceScope"] })"); + + settings->RegisterSetting("files.elf.overrideX86Endianness", + R"~({ + "title" : "Override x86 ELF endianness", + "type" : "boolean", + "default" : true, + "description" : "Automatically override endianness to little-endian for x86/x86_64 ELF files (useful for obfuscated binaries)", + "ignore" : ["SettingsProjectScope", "SettingsResourceScope"] + })~"); + } ElfView::ElfView(BinaryView* data, bool parseOnly): BinaryView("ELF", data->GetFile(), data), m_parseOnly(parseOnly) { + CreateLogger("BinaryView"); + m_logger = CreateLogger("BinaryView.ElfView"); + Elf64Header header; string errorMsg; BNEndianness endian; - if (!g_elfViewType->ParseHeaders(data, m_ident, m_commonHeader, header, &m_arch, &m_plat, errorMsg, endian)) + if (!ParseHeaders(data, m_ident, m_commonHeader, header, &m_arch, &m_plat, errorMsg, endian)) throw ElfFormatException(errorMsg); - CreateLogger("BinaryView"); - m_logger = CreateLogger("BinaryView.ElfView"); m_elf32 = m_ident.fileClass == 1; m_addressSize = (m_ident.fileClass == 1 || (m_plat && m_plat->GetName() == "linux-32")) ? 4 : 8; m_endian = endian; @@ -71,9 +82,6 @@ ElfView::ElfView(BinaryView* data, bool parseOnly): BinaryView("ELF", data->GetF memset(&m_sectionStringTable, 0, sizeof(m_sectionStringTable)); memset(&m_sectionOpd, 0, sizeof(m_sectionOpd)); - m_logger->LogInfo("Detected %s endian ELF", m_endian == LittleEndian ? "Little Endian" : "Big Endian"); - - if (m_elf32 && (header.sectionHeaderSize != sizeof(Elf32SectionHeader))) { m_logger->LogWarn( @@ -2873,9 +2881,9 @@ bool ElfViewType::IsTypeValidForData(BinaryView* data) } -uint64_t ElfViewType::ParseHeaders(BinaryView* data, ElfIdent& ident, ElfCommonHeader& commonHeader, Elf64Header& header, Ref* arch, Ref* plat, string& errorMsg, BNEndianness& endianness) +uint64_t ElfView::ParseHeaders(BinaryView* data, ElfIdent& ident, ElfCommonHeader& commonHeader, Elf64Header& header, Ref* arch, Ref* plat, string& errorMsg, BNEndianness& endianness) { - if (!IsTypeValidForData(data)) + if (!g_elfViewType->IsTypeValidForData(data)) { errorMsg = "invalid signature"; return 0; @@ -2889,16 +2897,49 @@ uint64_t ElfViewType::ParseHeaders(BinaryView* data, ElfIdent& ident, ElfCommonH } BinaryReader reader(data); + + // Determine endianness from header encoding + BNEndianness headerEndianness; if (ident.encoding <= 1) - endianness = LittleEndian; + headerEndianness = LittleEndian; else if (ident.encoding == 2) - endianness = BigEndian; + headerEndianness = BigEndian; else { errorMsg = "invalid encoding"; return 0; } + // Use header endianness by default + endianness = headerEndianness; + + // Check for automatic x86 endianness override + bool overrideX86Endianness = Settings::Instance()->Get("files.elf.overrideX86Endianness"); + if (overrideX86Endianness) + { + // Peek at e_machine field (2 bytes at offset 0x12) with little-endian interpretation + uint8_t machineBytes[2]; + if (data->Read(machineBytes, 0x12, 2) == 2) + { + uint16_t machineLE = machineBytes[0] | (machineBytes[1] << 8); + if (machineLE == EM_386 || machineLE == EM_X86_64) + { + endianness = LittleEndian; + if (endianness != headerEndianness) + { + m_logger->LogWarn("ELF endianness automatically overridden to little-endian for x86/x86_64 (header specified %s)", + headerEndianness == LittleEndian ? "little-endian" : "big-endian"); + } + } + } + } + + // Log detected endianness if no override occurred + if (endianness == headerEndianness) + { + m_logger->LogInfo("Detected %s ELF", endianness == LittleEndian ? "little-endian" : "big-endian"); + } + // parse ElfCommonHeader reader.SetEndianness(endianness); reader.Seek(sizeof(ident)); diff --git a/view/elf/elfview.h b/view/elf/elfview.h index a43716b747..b9690bef17 100644 --- a/view/elf/elfview.h +++ b/view/elf/elfview.h @@ -540,6 +540,7 @@ namespace BinaryNinja bool DerefPpc64Descriptor(BinaryReader& reader, uint64_t addr, uint64_t& result); void ParseMiniDebugInfo(); + uint64_t ParseHeaders(BinaryView* data, ElfIdent& ident, ElfCommonHeader& commonHeader, Elf64Header& header, Ref* arch, Ref* plat, std::string& errorMsg, BNEndianness& endianness); public: ElfView(BinaryView* data, bool parseOnly = false); ~ElfView(); @@ -555,7 +556,6 @@ namespace BinaryNinja virtual Ref Create(BinaryView* data) override; virtual Ref Parse(BinaryView* data) override; virtual bool IsTypeValidForData(BinaryView* data) override; - virtual uint64_t ParseHeaders(BinaryView* data, ElfIdent& ident, ElfCommonHeader& commonHeader, Elf64Header& header, Ref* arch, Ref* plat, std::string& errorMsg, BNEndianness& endianness); virtual Ref GetLoadSettingsForData(BinaryView* data) override; };