Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 51 additions & 10 deletions view/elf/elfview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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(
Expand Down Expand Up @@ -2873,9 +2881,9 @@ bool ElfViewType::IsTypeValidForData(BinaryView* data)
}


uint64_t ElfViewType::ParseHeaders(BinaryView* data, ElfIdent& ident, ElfCommonHeader& commonHeader, Elf64Header& header, Ref<Architecture>* arch, Ref<Platform>* plat, string& errorMsg, BNEndianness& endianness)
uint64_t ElfView::ParseHeaders(BinaryView* data, ElfIdent& ident, ElfCommonHeader& commonHeader, Elf64Header& header, Ref<Architecture>* arch, Ref<Platform>* plat, string& errorMsg, BNEndianness& endianness)
{
if (!IsTypeValidForData(data))
if (!g_elfViewType->IsTypeValidForData(data))
{
errorMsg = "invalid signature";
return 0;
Expand All @@ -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<bool>("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));
Expand Down
2 changes: 1 addition & 1 deletion view/elf/elfview.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<Architecture>* arch, Ref<Platform>* plat, std::string& errorMsg, BNEndianness& endianness);
public:
ElfView(BinaryView* data, bool parseOnly = false);
~ElfView();
Expand All @@ -555,7 +556,6 @@ namespace BinaryNinja
virtual Ref<BinaryView> Create(BinaryView* data) override;
virtual Ref<BinaryView> Parse(BinaryView* data) override;
virtual bool IsTypeValidForData(BinaryView* data) override;
virtual uint64_t ParseHeaders(BinaryView* data, ElfIdent& ident, ElfCommonHeader& commonHeader, Elf64Header& header, Ref<Architecture>* arch, Ref<Platform>* plat, std::string& errorMsg, BNEndianness& endianness);
virtual Ref<Settings> GetLoadSettingsForData(BinaryView* data) override;
};

Expand Down
Loading