From 7fcfd19179312c0e8561ddcdcec5d05aeea93763 Mon Sep 17 00:00:00 2001 From: JosephHAtWork <193976820+JosephHAtWork@users.noreply.github.com> Date: Mon, 6 Jan 2025 18:57:15 -0700 Subject: [PATCH 1/4] Add check for section header string table in ELF infoextractor --- surfactant/infoextractors/elf_file.py | 148 +++++++++++++------------- 1 file changed, 75 insertions(+), 73 deletions(-) diff --git a/surfactant/infoextractors/elf_file.py b/surfactant/infoextractors/elf_file.py index 250b2a05..ea45521b 100755 --- a/surfactant/infoextractors/elf_file.py +++ b/surfactant/infoextractors/elf_file.py @@ -80,81 +80,83 @@ def extract_elf_info(filename: str) -> object: # Get a human readable name for the OS file_details["OS"] = _EI_OSABI_NAME.get(file_details["elfOsAbi"], "") - for section in elf.iter_sections(): - if section.name == ".interp": - file_details["elfInterpreter"].append(section.data().rstrip(b"\x00").decode()) - if section.name == ".comment": - for v in section.data().rstrip(b"\x00").split(b"\x00"): - file_details["elfComment"].append(v.decode()) - if isinstance(section, NoteSection): - for note in section.iter_notes(): - # Info on contents of NetBSD and PaX notes: https://www.netbsd.org/docs/kernel/elf-notes.html - # Heuristics used by Avast RetDec to identify compiler/OS: https://github.com/avast/retdec/commit/d55b541c26fb110381b2203dc7baa50928e3f473 - note_info = {} - note_info["sectionName"] = section.name - note_info["name"] = note.n_name - note_info["type"] = note.n_type - if note.n_name == "GNU": - if note.n_type == "NT_GNU_ABI_TAG": - note_info["os"] = note.n_desc.abi_os - note_info["abi"] = ( - f"{note.n_desc.abi_major}.{note.n_desc.abi_minor}.{note.n_desc.abi_tiny}" - ) - elif note.n_type in ("NT_GNU_BUILD_ID", "NT_GNU_GOLD_VERSION"): - note_info["desc"] = note.n_desc + # Skip if the section header string table (.shstrtab) is missing + if elf._section_header_stringtable != None: + for section in elf.iter_sections(): + if section.name == ".interp": + file_details["elfInterpreter"].append(section.data().rstrip(b"\x00").decode()) + if section.name == ".comment": + for v in section.data().rstrip(b"\x00").split(b"\x00"): + file_details["elfComment"].append(v.decode()) + if isinstance(section, NoteSection): + for note in section.iter_notes(): + # Info on contents of NetBSD and PaX notes: https://www.netbsd.org/docs/kernel/elf-notes.html + # Heuristics used by Avast RetDec to identify compiler/OS: https://github.com/avast/retdec/commit/d55b541c26fb110381b2203dc7baa50928e3f473 + note_info = {} + note_info["sectionName"] = section.name + note_info["name"] = note.n_name + note_info["type"] = note.n_type + if note.n_name == "GNU": + if note.n_type == "NT_GNU_ABI_TAG": + note_info["os"] = note.n_desc.abi_os + note_info["abi"] = ( + f"{note.n_desc.abi_major}.{note.n_desc.abi_minor}.{note.n_desc.abi_tiny}" + ) + elif note.n_type in ("NT_GNU_BUILD_ID", "NT_GNU_GOLD_VERSION"): + note_info["desc"] = note.n_desc + else: + note_info["descdata"] = note.n_descdata.decode("unicode_escape") else: note_info["descdata"] = note.n_descdata.decode("unicode_escape") - else: - note_info["descdata"] = note.n_descdata.decode("unicode_escape") - file_details["elfNote"].append(note_info) - if isinstance(section, DynamicSection): - for tag in section.iter_tags(): - if tag.entry.d_tag == "DT_NEEDED": - # Shared libraries - file_details["elfDependencies"].append(tag.needed) - elif tag.entry.d_tag == "DT_RPATH": - # Library rpath - file_details["elfRpath"].append(tag.rpath) - elif tag.entry.d_tag == "DT_RUNPATH": - # Library runpath - file_details["elfRunpath"].append(tag.runpath) - elif tag.entry.d_tag == "DT_SONAME": - # Library soname (for linking) - file_details["elfSoname"].append(tag.soname) - elif tag.entry.d_tag == "DT_FLAGS": - # Dynamic Flags, DT_FLAGS - dt_flags_entry: Dict[str, Any] = {} - dt_flags_entry["value"] = hex(tag.entry.d_val) - # $ORIGIN processing is required - dt_flags_entry["DF_ORIGIN"] = bool( - tag.entry.d_val & ENUM_DT_FLAGS["DF_ORIGIN"] - ) - # Perform complete relocation processing (part of Full RELRO) - dt_flags_entry["DF_BIND_NOW"] = bool( - tag.entry.d_val & ENUM_DT_FLAGS["DF_BIND_NOW"] - ) - file_details["elfDynamicFlags"].append(dt_flags_entry) - elif tag.entry.d_tag == "DT_FLAGS_1": - # Dynamic Flags, DT_FLAGS_1 (custom entry first added by binutils) - dt_flags_1_entry: Dict[str, Any] = {} - dt_flags_1_entry["value"] = hex(tag.entry.d_val) - # Position-Independent Executable file - dt_flags_1_entry["DF_1_PIE"] = bool( - tag.entry.d_val & ENUM_DT_FLAGS_1["DF_1_PIE"] - ) - # Perform complete relocation processing - dt_flags_1_entry["DF_1_NOW"] = bool( - tag.entry.d_val & ENUM_DT_FLAGS_1["DF_1_NOW"] - ) - # $ORIGIN processing is required - dt_flags_1_entry["DF_1_ORIGIN"] = bool( - tag.entry.d_val & ENUM_DT_FLAGS_1["DF_1_ORIGIN"] - ) - # Ignore the default library search path - dt_flags_1_entry["DF_1_NODEFLIB"] = bool( - tag.entry.d_val & ENUM_DT_FLAGS_1["DF_1_NODEFLIB"] - ) - file_details["elfDynamicFlags1"].append(dt_flags_1_entry) + file_details["elfNote"].append(note_info) + if isinstance(section, DynamicSection): + for tag in section.iter_tags(): + if tag.entry.d_tag == "DT_NEEDED": + # Shared libraries + file_details["elfDependencies"].append(tag.needed) + elif tag.entry.d_tag == "DT_RPATH": + # Library rpath + file_details["elfRpath"].append(tag.rpath) + elif tag.entry.d_tag == "DT_RUNPATH": + # Library runpath + file_details["elfRunpath"].append(tag.runpath) + elif tag.entry.d_tag == "DT_SONAME": + # Library soname (for linking) + file_details["elfSoname"].append(tag.soname) + elif tag.entry.d_tag == "DT_FLAGS": + # Dynamic Flags, DT_FLAGS + dt_flags_entry: Dict[str, Any] = {} + dt_flags_entry["value"] = hex(tag.entry.d_val) + # $ORIGIN processing is required + dt_flags_entry["DF_ORIGIN"] = bool( + tag.entry.d_val & ENUM_DT_FLAGS["DF_ORIGIN"] + ) + # Perform complete relocation processing (part of Full RELRO) + dt_flags_entry["DF_BIND_NOW"] = bool( + tag.entry.d_val & ENUM_DT_FLAGS["DF_BIND_NOW"] + ) + file_details["elfDynamicFlags"].append(dt_flags_entry) + elif tag.entry.d_tag == "DT_FLAGS_1": + # Dynamic Flags, DT_FLAGS_1 (custom entry first added by binutils) + dt_flags_1_entry: Dict[str, Any] = {} + dt_flags_1_entry["value"] = hex(tag.entry.d_val) + # Position-Independent Executable file + dt_flags_1_entry["DF_1_PIE"] = bool( + tag.entry.d_val & ENUM_DT_FLAGS_1["DF_1_PIE"] + ) + # Perform complete relocation processing + dt_flags_1_entry["DF_1_NOW"] = bool( + tag.entry.d_val & ENUM_DT_FLAGS_1["DF_1_NOW"] + ) + # $ORIGIN processing is required + dt_flags_1_entry["DF_1_ORIGIN"] = bool( + tag.entry.d_val & ENUM_DT_FLAGS_1["DF_1_ORIGIN"] + ) + # Ignore the default library search path + dt_flags_1_entry["DF_1_NODEFLIB"] = bool( + tag.entry.d_val & ENUM_DT_FLAGS_1["DF_1_NODEFLIB"] + ) + file_details["elfDynamicFlags1"].append(dt_flags_1_entry) # Check for presence of special segments (e.g. PT_GNU_RELRO) for segment in elf.iter_segments(): From 96bbcbc056fe6537b566440096724b8acdfdae9f Mon Sep 17 00:00:00 2001 From: JosephHAtWork <193976820+JosephHAtWork@users.noreply.github.com> Date: Fri, 10 Jan 2025 06:37:20 +0000 Subject: [PATCH 2/4] Revert "Add check for section header string table in ELF infoextractor" This reverts commit 7fcfd19179312c0e8561ddcdcec5d05aeea93763. --- surfactant/infoextractors/elf_file.py | 148 +++++++++++++------------- 1 file changed, 73 insertions(+), 75 deletions(-) diff --git a/surfactant/infoextractors/elf_file.py b/surfactant/infoextractors/elf_file.py index ea45521b..250b2a05 100755 --- a/surfactant/infoextractors/elf_file.py +++ b/surfactant/infoextractors/elf_file.py @@ -80,83 +80,81 @@ def extract_elf_info(filename: str) -> object: # Get a human readable name for the OS file_details["OS"] = _EI_OSABI_NAME.get(file_details["elfOsAbi"], "") - # Skip if the section header string table (.shstrtab) is missing - if elf._section_header_stringtable != None: - for section in elf.iter_sections(): - if section.name == ".interp": - file_details["elfInterpreter"].append(section.data().rstrip(b"\x00").decode()) - if section.name == ".comment": - for v in section.data().rstrip(b"\x00").split(b"\x00"): - file_details["elfComment"].append(v.decode()) - if isinstance(section, NoteSection): - for note in section.iter_notes(): - # Info on contents of NetBSD and PaX notes: https://www.netbsd.org/docs/kernel/elf-notes.html - # Heuristics used by Avast RetDec to identify compiler/OS: https://github.com/avast/retdec/commit/d55b541c26fb110381b2203dc7baa50928e3f473 - note_info = {} - note_info["sectionName"] = section.name - note_info["name"] = note.n_name - note_info["type"] = note.n_type - if note.n_name == "GNU": - if note.n_type == "NT_GNU_ABI_TAG": - note_info["os"] = note.n_desc.abi_os - note_info["abi"] = ( - f"{note.n_desc.abi_major}.{note.n_desc.abi_minor}.{note.n_desc.abi_tiny}" - ) - elif note.n_type in ("NT_GNU_BUILD_ID", "NT_GNU_GOLD_VERSION"): - note_info["desc"] = note.n_desc - else: - note_info["descdata"] = note.n_descdata.decode("unicode_escape") + for section in elf.iter_sections(): + if section.name == ".interp": + file_details["elfInterpreter"].append(section.data().rstrip(b"\x00").decode()) + if section.name == ".comment": + for v in section.data().rstrip(b"\x00").split(b"\x00"): + file_details["elfComment"].append(v.decode()) + if isinstance(section, NoteSection): + for note in section.iter_notes(): + # Info on contents of NetBSD and PaX notes: https://www.netbsd.org/docs/kernel/elf-notes.html + # Heuristics used by Avast RetDec to identify compiler/OS: https://github.com/avast/retdec/commit/d55b541c26fb110381b2203dc7baa50928e3f473 + note_info = {} + note_info["sectionName"] = section.name + note_info["name"] = note.n_name + note_info["type"] = note.n_type + if note.n_name == "GNU": + if note.n_type == "NT_GNU_ABI_TAG": + note_info["os"] = note.n_desc.abi_os + note_info["abi"] = ( + f"{note.n_desc.abi_major}.{note.n_desc.abi_minor}.{note.n_desc.abi_tiny}" + ) + elif note.n_type in ("NT_GNU_BUILD_ID", "NT_GNU_GOLD_VERSION"): + note_info["desc"] = note.n_desc else: note_info["descdata"] = note.n_descdata.decode("unicode_escape") - file_details["elfNote"].append(note_info) - if isinstance(section, DynamicSection): - for tag in section.iter_tags(): - if tag.entry.d_tag == "DT_NEEDED": - # Shared libraries - file_details["elfDependencies"].append(tag.needed) - elif tag.entry.d_tag == "DT_RPATH": - # Library rpath - file_details["elfRpath"].append(tag.rpath) - elif tag.entry.d_tag == "DT_RUNPATH": - # Library runpath - file_details["elfRunpath"].append(tag.runpath) - elif tag.entry.d_tag == "DT_SONAME": - # Library soname (for linking) - file_details["elfSoname"].append(tag.soname) - elif tag.entry.d_tag == "DT_FLAGS": - # Dynamic Flags, DT_FLAGS - dt_flags_entry: Dict[str, Any] = {} - dt_flags_entry["value"] = hex(tag.entry.d_val) - # $ORIGIN processing is required - dt_flags_entry["DF_ORIGIN"] = bool( - tag.entry.d_val & ENUM_DT_FLAGS["DF_ORIGIN"] - ) - # Perform complete relocation processing (part of Full RELRO) - dt_flags_entry["DF_BIND_NOW"] = bool( - tag.entry.d_val & ENUM_DT_FLAGS["DF_BIND_NOW"] - ) - file_details["elfDynamicFlags"].append(dt_flags_entry) - elif tag.entry.d_tag == "DT_FLAGS_1": - # Dynamic Flags, DT_FLAGS_1 (custom entry first added by binutils) - dt_flags_1_entry: Dict[str, Any] = {} - dt_flags_1_entry["value"] = hex(tag.entry.d_val) - # Position-Independent Executable file - dt_flags_1_entry["DF_1_PIE"] = bool( - tag.entry.d_val & ENUM_DT_FLAGS_1["DF_1_PIE"] - ) - # Perform complete relocation processing - dt_flags_1_entry["DF_1_NOW"] = bool( - tag.entry.d_val & ENUM_DT_FLAGS_1["DF_1_NOW"] - ) - # $ORIGIN processing is required - dt_flags_1_entry["DF_1_ORIGIN"] = bool( - tag.entry.d_val & ENUM_DT_FLAGS_1["DF_1_ORIGIN"] - ) - # Ignore the default library search path - dt_flags_1_entry["DF_1_NODEFLIB"] = bool( - tag.entry.d_val & ENUM_DT_FLAGS_1["DF_1_NODEFLIB"] - ) - file_details["elfDynamicFlags1"].append(dt_flags_1_entry) + else: + note_info["descdata"] = note.n_descdata.decode("unicode_escape") + file_details["elfNote"].append(note_info) + if isinstance(section, DynamicSection): + for tag in section.iter_tags(): + if tag.entry.d_tag == "DT_NEEDED": + # Shared libraries + file_details["elfDependencies"].append(tag.needed) + elif tag.entry.d_tag == "DT_RPATH": + # Library rpath + file_details["elfRpath"].append(tag.rpath) + elif tag.entry.d_tag == "DT_RUNPATH": + # Library runpath + file_details["elfRunpath"].append(tag.runpath) + elif tag.entry.d_tag == "DT_SONAME": + # Library soname (for linking) + file_details["elfSoname"].append(tag.soname) + elif tag.entry.d_tag == "DT_FLAGS": + # Dynamic Flags, DT_FLAGS + dt_flags_entry: Dict[str, Any] = {} + dt_flags_entry["value"] = hex(tag.entry.d_val) + # $ORIGIN processing is required + dt_flags_entry["DF_ORIGIN"] = bool( + tag.entry.d_val & ENUM_DT_FLAGS["DF_ORIGIN"] + ) + # Perform complete relocation processing (part of Full RELRO) + dt_flags_entry["DF_BIND_NOW"] = bool( + tag.entry.d_val & ENUM_DT_FLAGS["DF_BIND_NOW"] + ) + file_details["elfDynamicFlags"].append(dt_flags_entry) + elif tag.entry.d_tag == "DT_FLAGS_1": + # Dynamic Flags, DT_FLAGS_1 (custom entry first added by binutils) + dt_flags_1_entry: Dict[str, Any] = {} + dt_flags_1_entry["value"] = hex(tag.entry.d_val) + # Position-Independent Executable file + dt_flags_1_entry["DF_1_PIE"] = bool( + tag.entry.d_val & ENUM_DT_FLAGS_1["DF_1_PIE"] + ) + # Perform complete relocation processing + dt_flags_1_entry["DF_1_NOW"] = bool( + tag.entry.d_val & ENUM_DT_FLAGS_1["DF_1_NOW"] + ) + # $ORIGIN processing is required + dt_flags_1_entry["DF_1_ORIGIN"] = bool( + tag.entry.d_val & ENUM_DT_FLAGS_1["DF_1_ORIGIN"] + ) + # Ignore the default library search path + dt_flags_1_entry["DF_1_NODEFLIB"] = bool( + tag.entry.d_val & ENUM_DT_FLAGS_1["DF_1_NODEFLIB"] + ) + file_details["elfDynamicFlags1"].append(dt_flags_1_entry) # Check for presence of special segments (e.g. PT_GNU_RELRO) for segment in elf.iter_segments(): From 49914cd0519158c977538e95d3eb2385750b40cc Mon Sep 17 00:00:00 2001 From: JosephHAtWork <193976820+JosephHAtWork@users.noreply.github.com> Date: Fri, 10 Jan 2025 07:31:22 +0000 Subject: [PATCH 3/4] Catch ELFParseError's when parsing section information on malformed ELF files --- surfactant/infoextractors/elf_file.py | 153 +++++++++++++------------- 1 file changed, 78 insertions(+), 75 deletions(-) diff --git a/surfactant/infoextractors/elf_file.py b/surfactant/infoextractors/elf_file.py index 250b2a05..78349160 100755 --- a/surfactant/infoextractors/elf_file.py +++ b/surfactant/infoextractors/elf_file.py @@ -5,11 +5,12 @@ import struct from typing import Any, Dict -from elftools.common.exceptions import ELFError +from elftools.common.exceptions import ELFError, ELFParseError from elftools.elf.dynamic import DynamicSection from elftools.elf.elffile import ELFFile from elftools.elf.enums import ENUM_DT_FLAGS, ENUM_DT_FLAGS_1 from elftools.elf.sections import NoteSection +from loguru import logger import surfactant.plugin from surfactant.sbomtypes import SBOM, Software @@ -79,82 +80,84 @@ def extract_elf_info(filename: str) -> object: # Get a human readable name for the OS file_details["OS"] = _EI_OSABI_NAME.get(file_details["elfOsAbi"], "") - - for section in elf.iter_sections(): - if section.name == ".interp": - file_details["elfInterpreter"].append(section.data().rstrip(b"\x00").decode()) - if section.name == ".comment": - for v in section.data().rstrip(b"\x00").split(b"\x00"): - file_details["elfComment"].append(v.decode()) - if isinstance(section, NoteSection): - for note in section.iter_notes(): - # Info on contents of NetBSD and PaX notes: https://www.netbsd.org/docs/kernel/elf-notes.html - # Heuristics used by Avast RetDec to identify compiler/OS: https://github.com/avast/retdec/commit/d55b541c26fb110381b2203dc7baa50928e3f473 - note_info = {} - note_info["sectionName"] = section.name - note_info["name"] = note.n_name - note_info["type"] = note.n_type - if note.n_name == "GNU": - if note.n_type == "NT_GNU_ABI_TAG": - note_info["os"] = note.n_desc.abi_os - note_info["abi"] = ( - f"{note.n_desc.abi_major}.{note.n_desc.abi_minor}.{note.n_desc.abi_tiny}" - ) - elif note.n_type in ("NT_GNU_BUILD_ID", "NT_GNU_GOLD_VERSION"): - note_info["desc"] = note.n_desc + try: + for section in elf.iter_sections(): + if section.name == ".interp": + file_details["elfInterpreter"].append(section.data().rstrip(b"\x00").decode()) + if section.name == ".comment": + for v in section.data().rstrip(b"\x00").split(b"\x00"): + file_details["elfComment"].append(v.decode()) + if isinstance(section, NoteSection): + for note in section.iter_notes(): + # Info on contents of NetBSD and PaX notes: https://www.netbsd.org/docs/kernel/elf-notes.html + # Heuristics used by Avast RetDec to identify compiler/OS: https://github.com/avast/retdec/commit/d55b541c26fb110381b2203dc7baa50928e3f473 + note_info = {} + note_info["sectionName"] = section.name + note_info["name"] = note.n_name + note_info["type"] = note.n_type + if note.n_name == "GNU": + if note.n_type == "NT_GNU_ABI_TAG": + note_info["os"] = note.n_desc.abi_os + note_info["abi"] = ( + f"{note.n_desc.abi_major}.{note.n_desc.abi_minor}.{note.n_desc.abi_tiny}" + ) + elif note.n_type in ("NT_GNU_BUILD_ID", "NT_GNU_GOLD_VERSION"): + note_info["desc"] = note.n_desc + else: + note_info["descdata"] = note.n_descdata.decode("unicode_escape") else: note_info["descdata"] = note.n_descdata.decode("unicode_escape") - else: - note_info["descdata"] = note.n_descdata.decode("unicode_escape") - file_details["elfNote"].append(note_info) - if isinstance(section, DynamicSection): - for tag in section.iter_tags(): - if tag.entry.d_tag == "DT_NEEDED": - # Shared libraries - file_details["elfDependencies"].append(tag.needed) - elif tag.entry.d_tag == "DT_RPATH": - # Library rpath - file_details["elfRpath"].append(tag.rpath) - elif tag.entry.d_tag == "DT_RUNPATH": - # Library runpath - file_details["elfRunpath"].append(tag.runpath) - elif tag.entry.d_tag == "DT_SONAME": - # Library soname (for linking) - file_details["elfSoname"].append(tag.soname) - elif tag.entry.d_tag == "DT_FLAGS": - # Dynamic Flags, DT_FLAGS - dt_flags_entry: Dict[str, Any] = {} - dt_flags_entry["value"] = hex(tag.entry.d_val) - # $ORIGIN processing is required - dt_flags_entry["DF_ORIGIN"] = bool( - tag.entry.d_val & ENUM_DT_FLAGS["DF_ORIGIN"] - ) - # Perform complete relocation processing (part of Full RELRO) - dt_flags_entry["DF_BIND_NOW"] = bool( - tag.entry.d_val & ENUM_DT_FLAGS["DF_BIND_NOW"] - ) - file_details["elfDynamicFlags"].append(dt_flags_entry) - elif tag.entry.d_tag == "DT_FLAGS_1": - # Dynamic Flags, DT_FLAGS_1 (custom entry first added by binutils) - dt_flags_1_entry: Dict[str, Any] = {} - dt_flags_1_entry["value"] = hex(tag.entry.d_val) - # Position-Independent Executable file - dt_flags_1_entry["DF_1_PIE"] = bool( - tag.entry.d_val & ENUM_DT_FLAGS_1["DF_1_PIE"] - ) - # Perform complete relocation processing - dt_flags_1_entry["DF_1_NOW"] = bool( - tag.entry.d_val & ENUM_DT_FLAGS_1["DF_1_NOW"] - ) - # $ORIGIN processing is required - dt_flags_1_entry["DF_1_ORIGIN"] = bool( - tag.entry.d_val & ENUM_DT_FLAGS_1["DF_1_ORIGIN"] - ) - # Ignore the default library search path - dt_flags_1_entry["DF_1_NODEFLIB"] = bool( - tag.entry.d_val & ENUM_DT_FLAGS_1["DF_1_NODEFLIB"] - ) - file_details["elfDynamicFlags1"].append(dt_flags_1_entry) + file_details["elfNote"].append(note_info) + if isinstance(section, DynamicSection): + for tag in section.iter_tags(): + if tag.entry.d_tag == "DT_NEEDED": + # Shared libraries + file_details["elfDependencies"].append(tag.needed) + elif tag.entry.d_tag == "DT_RPATH": + # Library rpath + file_details["elfRpath"].append(tag.rpath) + elif tag.entry.d_tag == "DT_RUNPATH": + # Library runpath + file_details["elfRunpath"].append(tag.runpath) + elif tag.entry.d_tag == "DT_SONAME": + # Library soname (for linking) + file_details["elfSoname"].append(tag.soname) + elif tag.entry.d_tag == "DT_FLAGS": + # Dynamic Flags, DT_FLAGS + dt_flags_entry: Dict[str, Any] = {} + dt_flags_entry["value"] = hex(tag.entry.d_val) + # $ORIGIN processing is required + dt_flags_entry["DF_ORIGIN"] = bool( + tag.entry.d_val & ENUM_DT_FLAGS["DF_ORIGIN"] + ) + # Perform complete relocation processing (part of Full RELRO) + dt_flags_entry["DF_BIND_NOW"] = bool( + tag.entry.d_val & ENUM_DT_FLAGS["DF_BIND_NOW"] + ) + file_details["elfDynamicFlags"].append(dt_flags_entry) + elif tag.entry.d_tag == "DT_FLAGS_1": + # Dynamic Flags, DT_FLAGS_1 (custom entry first added by binutils) + dt_flags_1_entry: Dict[str, Any] = {} + dt_flags_1_entry["value"] = hex(tag.entry.d_val) + # Position-Independent Executable file + dt_flags_1_entry["DF_1_PIE"] = bool( + tag.entry.d_val & ENUM_DT_FLAGS_1["DF_1_PIE"] + ) + # Perform complete relocation processing + dt_flags_1_entry["DF_1_NOW"] = bool( + tag.entry.d_val & ENUM_DT_FLAGS_1["DF_1_NOW"] + ) + # $ORIGIN processing is required + dt_flags_1_entry["DF_1_ORIGIN"] = bool( + tag.entry.d_val & ENUM_DT_FLAGS_1["DF_1_ORIGIN"] + ) + # Ignore the default library search path + dt_flags_1_entry["DF_1_NODEFLIB"] = bool( + tag.entry.d_val & ENUM_DT_FLAGS_1["DF_1_NODEFLIB"] + ) + file_details["elfDynamicFlags1"].append(dt_flags_1_entry) + except ELFParseError as e: + logger.warning(f"Error while parsing ELF sections: {repr(e)}") # Check for presence of special segments (e.g. PT_GNU_RELRO) for segment in elf.iter_segments(): From 540560650687b5b8a8da52dd75fe59135e2c0bd6 Mon Sep 17 00:00:00 2001 From: Joseph H <193976820+JosephHAtWork@users.noreply.github.com> Date: Mon, 20 Jan 2025 22:59:27 -0700 Subject: [PATCH 4/4] Add filename to warning output Co-authored-by: Ryan Mast <3969255+nightlark@users.noreply.github.com> --- surfactant/infoextractors/elf_file.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/surfactant/infoextractors/elf_file.py b/surfactant/infoextractors/elf_file.py index 78349160..77e75d3f 100755 --- a/surfactant/infoextractors/elf_file.py +++ b/surfactant/infoextractors/elf_file.py @@ -157,7 +157,7 @@ def extract_elf_info(filename: str) -> object: ) file_details["elfDynamicFlags1"].append(dt_flags_1_entry) except ELFParseError as e: - logger.warning(f"Error while parsing ELF sections: {repr(e)}") + logger.warning(f"Error while parsing ELF sections in {filename}: {repr(e)}") # Check for presence of special segments (e.g. PT_GNU_RELRO) for segment in elf.iter_segments():