Skip to content

Commit c1b4476

Browse files
Copilotxusheng6
authored andcommitted
Implement automatic endianness override for x86 ELF files
1 parent 352ab7f commit c1b4476

File tree

2 files changed

+52
-11
lines changed

2 files changed

+52
-11
lines changed

view/elf/elfview.cpp

Lines changed: 51 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -40,19 +40,30 @@ void BinaryNinja::InitElfViewType()
4040
"description" : "Enable ARM BE8 binary detection for mixed little/big endianness for code/data",
4141
"ignore" : ["SettingsProjectScope", "SettingsResourceScope"]
4242
})");
43+
44+
settings->RegisterSetting("files.elf.overrideX86Endianness",
45+
R"~({
46+
"title" : "Override x86 ELF endianness",
47+
"type" : "boolean",
48+
"default" : true,
49+
"description" : "Automatically override endianness to little-endian for x86/x86_64 ELF files (useful for obfuscated binaries)",
50+
"ignore" : ["SettingsProjectScope", "SettingsResourceScope"]
51+
})~");
52+
4353
}
4454

4555

4656
ElfView::ElfView(BinaryView* data, bool parseOnly): BinaryView("ELF", data->GetFile(), data), m_parseOnly(parseOnly)
4757
{
58+
CreateLogger("BinaryView");
59+
m_logger = CreateLogger("BinaryView.ElfView");
60+
4861
Elf64Header header;
4962
string errorMsg;
5063
BNEndianness endian;
51-
if (!g_elfViewType->ParseHeaders(data, m_ident, m_commonHeader, header, &m_arch, &m_plat, errorMsg, endian))
64+
if (!ParseHeaders(data, m_ident, m_commonHeader, header, &m_arch, &m_plat, errorMsg, endian))
5265
throw ElfFormatException(errorMsg);
5366

54-
CreateLogger("BinaryView");
55-
m_logger = CreateLogger("BinaryView.ElfView");
5667
m_elf32 = m_ident.fileClass == 1;
5768
m_addressSize = (m_ident.fileClass == 1 || (m_plat && m_plat->GetName() == "linux-32")) ? 4 : 8;
5869
m_endian = endian;
@@ -71,9 +82,6 @@ ElfView::ElfView(BinaryView* data, bool parseOnly): BinaryView("ELF", data->GetF
7182
memset(&m_sectionStringTable, 0, sizeof(m_sectionStringTable));
7283
memset(&m_sectionOpd, 0, sizeof(m_sectionOpd));
7384

74-
m_logger->LogInfo("Detected %s endian ELF", m_endian == LittleEndian ? "Little Endian" : "Big Endian");
75-
76-
7785
if (m_elf32 && (header.sectionHeaderSize != sizeof(Elf32SectionHeader)))
7886
{
7987
m_logger->LogWarn(
@@ -2873,9 +2881,9 @@ bool ElfViewType::IsTypeValidForData(BinaryView* data)
28732881
}
28742882

28752883

2876-
uint64_t ElfViewType::ParseHeaders(BinaryView* data, ElfIdent& ident, ElfCommonHeader& commonHeader, Elf64Header& header, Ref<Architecture>* arch, Ref<Platform>* plat, string& errorMsg, BNEndianness& endianness)
2884+
uint64_t ElfView::ParseHeaders(BinaryView* data, ElfIdent& ident, ElfCommonHeader& commonHeader, Elf64Header& header, Ref<Architecture>* arch, Ref<Platform>* plat, string& errorMsg, BNEndianness& endianness)
28772885
{
2878-
if (!IsTypeValidForData(data))
2886+
if (!g_elfViewType->IsTypeValidForData(data))
28792887
{
28802888
errorMsg = "invalid signature";
28812889
return 0;
@@ -2889,16 +2897,49 @@ uint64_t ElfViewType::ParseHeaders(BinaryView* data, ElfIdent& ident, ElfCommonH
28892897
}
28902898

28912899
BinaryReader reader(data);
2900+
2901+
// Determine endianness from header encoding
2902+
BNEndianness headerEndianness;
28922903
if (ident.encoding <= 1)
2893-
endianness = LittleEndian;
2904+
headerEndianness = LittleEndian;
28942905
else if (ident.encoding == 2)
2895-
endianness = BigEndian;
2906+
headerEndianness = BigEndian;
28962907
else
28972908
{
28982909
errorMsg = "invalid encoding";
28992910
return 0;
29002911
}
29012912

2913+
// Use header endianness by default
2914+
endianness = headerEndianness;
2915+
2916+
// Check for automatic x86 endianness override
2917+
bool overrideX86Endianness = Settings::Instance()->Get<bool>("files.elf.overrideX86Endianness");
2918+
if (overrideX86Endianness)
2919+
{
2920+
// Peek at e_machine field (2 bytes at offset 0x12) with little-endian interpretation
2921+
uint8_t machineBytes[2];
2922+
if (data->Read(machineBytes, 0x12, 2) == 2)
2923+
{
2924+
uint16_t machineLE = machineBytes[0] | (machineBytes[1] << 8);
2925+
if (machineLE == EM_386 || machineLE == EM_X86_64)
2926+
{
2927+
endianness = LittleEndian;
2928+
if (endianness != headerEndianness)
2929+
{
2930+
m_logger->LogWarn("ELF endianness automatically overridden to little-endian for x86/x86_64 (header specified %s)",
2931+
headerEndianness == LittleEndian ? "little-endian" : "big-endian");
2932+
}
2933+
}
2934+
}
2935+
}
2936+
2937+
// Log detected endianness if no override occurred
2938+
if (endianness == headerEndianness)
2939+
{
2940+
m_logger->LogInfo("Detected %s ELF", endianness == LittleEndian ? "little-endian" : "big-endian");
2941+
}
2942+
29022943
// parse ElfCommonHeader
29032944
reader.SetEndianness(endianness);
29042945
reader.Seek(sizeof(ident));

view/elf/elfview.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,7 @@ namespace BinaryNinja
540540
bool DerefPpc64Descriptor(BinaryReader& reader, uint64_t addr, uint64_t& result);
541541

542542
void ParseMiniDebugInfo();
543+
uint64_t ParseHeaders(BinaryView* data, ElfIdent& ident, ElfCommonHeader& commonHeader, Elf64Header& header, Ref<Architecture>* arch, Ref<Platform>* plat, std::string& errorMsg, BNEndianness& endianness);
543544
public:
544545
ElfView(BinaryView* data, bool parseOnly = false);
545546
~ElfView();
@@ -555,7 +556,6 @@ namespace BinaryNinja
555556
virtual Ref<BinaryView> Create(BinaryView* data) override;
556557
virtual Ref<BinaryView> Parse(BinaryView* data) override;
557558
virtual bool IsTypeValidForData(BinaryView* data) override;
558-
virtual uint64_t ParseHeaders(BinaryView* data, ElfIdent& ident, ElfCommonHeader& commonHeader, Elf64Header& header, Ref<Architecture>* arch, Ref<Platform>* plat, std::string& errorMsg, BNEndianness& endianness);
559559
virtual Ref<Settings> GetLoadSettingsForData(BinaryView* data) override;
560560
};
561561

0 commit comments

Comments
 (0)