diff --git a/.gitattributes b/.gitattributes index 95f257b12..875e3c434 100644 --- a/.gitattributes +++ b/.gitattributes @@ -8,3 +8,4 @@ docs/user-guide/gui/assets/* filter=lfs diff=lfs merge=lfs -text ofrak_core/test_ofrak/components/assets/elf/* filter=lfs diff=lfs merge=lfs -text ofrak_core/test_ofrak/components/assets/elf/edge-cases/* filter=lfs diff=lfs merge=lfs -text frontend/public/themes/**/* filter=lfs diff=lfs merge=lfs -text +disassemblers/ofrak_angr/ofrak_angr_test/assets/* filter=lfs diff=lfs merge=lfs -text diff --git a/.gitignore b/.gitignore index 8e7dfdfcd..2596d6b39 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ venv/ .idea/ test/ .DS_Store +.coverage *.iml *.egg-info/ QUESTIONS @@ -17,4 +18,10 @@ ofrak_core/ofrak/core/entropy/entropy.so.1 frontend/public/build ofrak_core/ofrak/core/entropy/entropy_c.cpython* ofrak_core/ofrak/gui/public +ofrak_core/replaced_hello.out +ofrak_core/replaced_simple_arm_gcc.o.elf ofrak_core/build +ofrak_io/build/ +ofrak_patch_maker/build/ +ofrak_type/build/ +disassemblers/ofrak_ghidra/ofrak_ghidra/config/ofrak_ghidra.conf.yml diff --git a/Makefile b/Makefile index 33b7dd8a9..601efe55e 100644 --- a/Makefile +++ b/Makefile @@ -18,3 +18,22 @@ tutorial-image: tutorial-run: make -C ofrak_tutorial run + +OFRAK_INSTALL_PYTHON=python3 + +.PHONY: install_tutorial install_core install_develop install_test_all +install_tutorial: + $(OFRAK_INSTALL_PYTHON) -m pip install pyyaml + $(OFRAK_INSTALL_PYTHON) install.py --config ofrak-tutorial.yml --target install + +install_core: + $(OFRAK_INSTALL_PYTHON) -m pip install pyyaml + $(OFRAK_INSTALL_PYTHON) install.py --config ofrak-core-dev.yml --target install + +install_develop: + $(OFRAK_INSTALL_PYTHON) -m pip install pyyaml + $(OFRAK_INSTALL_PYTHON) install.py --config ofrak-dev.yml --target develop + +install_test_all: + $(OFRAK_INSTALL_PYTHON) -m pip install pyyaml + $(OFRAK_INSTALL_PYTHON) install.py --config ofrak-all.yml --target develop --test diff --git a/build_image.py b/build_image.py index a2b021e02..93071424f 100644 --- a/build_image.py +++ b/build_image.py @@ -192,10 +192,12 @@ def create_dockerfile_base(config: OfrakImageConfig) -> str: continue with open(dockerstage_path) as file_handle: dockerstub = file_handle.read() + # Cannot use ENV here because of multi-stage build FROM, so replace direclty in Docerkstage contents + dockerstub = dockerstub.replace("$PACKAGE_DIR", package_path) dockerfile_base_parts += [f"### {dockerstage_path}", dockerstub] dockerfile_base_parts += [ - "FROM python:3.7-bullseye@sha256:338ead05c1a0aa8bd8fcba8e4dbbe2afd0283b4732fd30cf9b3bfcfcbc4affab", + "FROM python:3.8-bullseye@sha256:e1cd369204123e89646f8c001db830eddfe3e381bd5c837df00141be3bd754cb", "", ] @@ -207,7 +209,11 @@ def create_dockerfile_base(config: OfrakImageConfig) -> str: dockerstub_path = os.path.join(package_path, "Dockerstub") with open(dockerstub_path) as file_handle: dockerstub = file_handle.read() - dockerfile_base_parts += [f"### {dockerstub_path}", dockerstub] + dockerfile_base_parts += [ + f"### {dockerstub_path}", + f"ENV PACKAGE_PATH={package_path}", + dockerstub, + ] # Collect python dependencies python_reqs = [] for suff in requirement_suffixes: @@ -247,19 +253,24 @@ def create_dockerfile_finish(config: OfrakImageConfig) -> str: [ "$INSTALL_TARGET:", "\\n\\\n".join( - [f"\tmake -C {package_name} $INSTALL_TARGET" for package_name in package_names] + [f"\t\\$(MAKE) -C {package_name} $INSTALL_TARGET" for package_name in package_names] ), "\\n", ] ) dockerfile_finish_parts.append(f'RUN printf "{develop_makefile}" >> Makefile\n') dockerfile_finish_parts.append("RUN make $INSTALL_TARGET\n\n") + test_names = " ".join([f"test_{package_name}" for package_name in package_names]) finish_makefile = "\\n\\\n".join( [ - "test:", - "\\n\\\n".join([f"\tmake -C {package_name} test" for package_name in package_names]), - "\\n", + ".PHONY: test " + test_names, + "test: " + test_names, + ] + + [ + f"test_{package_name}:\\n\\\n\t\\$(MAKE) -C {package_name} test" + for package_name in package_names ] + + ["\\n"] ) dockerfile_finish_parts.append(f'RUN printf "{finish_makefile}" >> Makefile\n') if config.entrypoint is not None: diff --git a/disassemblers/ofrak_angr/CHANGELOG.md b/disassemblers/ofrak_angr/CHANGELOG.md index eb673296c..d4ba9f23a 100644 --- a/disassemblers/ofrak_angr/CHANGELOG.md +++ b/disassemblers/ofrak_angr/CHANGELOG.md @@ -5,6 +5,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) ## [Unreleased](https://github.com/redballoonsecurity/ofrak/tree/master) +### Changed +- Update to latest angr==9.2.77, which also necessitates Python >= 3.8. + ### Fixed - Add `importlib-resources` dependency as workaround for z3-solver dependency issue. ([#401](https://github.com/redballoonsecurity/ofrak/pull/401)) diff --git a/disassemblers/ofrak_angr/Makefile b/disassemblers/ofrak_angr/Makefile index f7da7aa5e..8de136b1c 100644 --- a/disassemblers/ofrak_angr/Makefile +++ b/disassemblers/ofrak_angr/Makefile @@ -11,7 +11,7 @@ develop: .PHONY: inspect inspect: - mypy + $(PYTHON) -m mypy .PHONY: test test: inspect diff --git a/disassemblers/ofrak_angr/ofrak_angr/components/angr_decompilation_analyzer.py b/disassemblers/ofrak_angr/ofrak_angr/components/angr_decompilation_analyzer.py new file mode 100644 index 000000000..ad570b39e --- /dev/null +++ b/disassemblers/ofrak_angr/ofrak_angr/components/angr_decompilation_analyzer.py @@ -0,0 +1,73 @@ +from dataclasses import dataclass +import angr +from angr.analyses.decompiler import Decompiler +from ofrak.component.analyzer import Analyzer +from ofrak.component.identifier import Identifier +from ofrak.resource_view import ResourceView + +from ofrak.resource import Resource +from ofrak.core.complex_block import ComplexBlock +from ofrak.service.resource_service_i import ResourceFilter +from ofrak_angr.model import AngrAnalysis, AngrAnalysisResource + + +@dataclass +class AngrDecompilationAnalysis(ResourceView): + decompilation: str + + +class AngrDecompilationAnalysisIdentifier(Identifier): + id = b"AngrDecompilationAnalysisIdentifier" + targets = (ComplexBlock,) + + async def identify(self, resource: Resource, config=None): + resource.add_tag(AngrDecompilationAnalysis) + + +class AngrDecompilatonAnalyzer(Analyzer[None, AngrDecompilationAnalysis]): + id = b"AngrDecompilationAnalyzer" + targets = (ComplexBlock,) + outputs = (AngrDecompilationAnalysis,) + + async def analyze(self, resource: Resource, config: None) -> AngrDecompilationAnalysis: + # Run / fetch angr analyzer + try: + root_resource = await resource.get_only_ancestor( + ResourceFilter(tags=[AngrAnalysisResource], include_self=True) + ) + complex_block = await resource.view_as(ComplexBlock) + angr_analysis = await root_resource.analyze(AngrAnalysis) + + cfg = angr_analysis.project.analyses[angr.analyses.CFGFast].prep()( + data_references=True, normalize=True + ) + + function_s = [ + func + for addr, func in angr_analysis.project.kb.functions.items() + if func.addr == complex_block.virtual_address + ] + if len(function_s) == 0: + # Check for thumb + function_s = [ + func + for addr, func in angr_analysis.project.kb.functions.items() + if func.addr == complex_block.virtual_address + 1 + ] + if len(function_s) != 1: + raise ValueError( + f"Could not find angr function for function at address {complex_block.virtual_address}" + ) + function = function_s[0] + dec: Decompiler = angr_analysis.project.analyses[angr.analyses.Decompiler].prep()( + function, cfg=cfg.model, options=None + ) + if dec.codegen is not None: + decomp = dec.codegen.text + else: + decomp = "No Decompilation available" + return AngrDecompilationAnalysis(decomp) + except Exception as e: + return AngrDecompilationAnalysis( + f"The decompilation for this Complex Block has failed with the error {e}" + ) diff --git a/disassemblers/ofrak_angr/ofrak_angr/components/blocks/unpackers.py b/disassemblers/ofrak_angr/ofrak_angr/components/blocks/unpackers.py index e9c34d525..15b7c803b 100644 --- a/disassemblers/ofrak_angr/ofrak_angr/components/blocks/unpackers.py +++ b/disassemblers/ofrak_angr/ofrak_angr/components/blocks/unpackers.py @@ -228,7 +228,7 @@ def _angr_get_dword_blocks( if xref is None or not any(xref in bb_range for bb_range in valid_data_xref_ranges): continue - LOGGER.debug(f"Creating DataWord for {cb_data_xref.content} @ {cb_data_xref_addr:#x}") + LOGGER.debug(f"Creating DataWord for {cb_data_xref.content!r} @ {cb_data_xref_addr:#x}") format_string = endian_flag + dword_size_map[word_size] diff --git a/disassemblers/ofrak_angr/ofrak_angr_test/assets/hello.x64.elf b/disassemblers/ofrak_angr/ofrak_angr_test/assets/hello.x64.elf new file mode 100755 index 000000000..138e83be8 --- /dev/null +++ b/disassemblers/ofrak_angr/ofrak_angr_test/assets/hello.x64.elf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:af467282f2c4cc3fd6400edae094bea7ac96dff34d925e44fa49c75024b2d67c +size 75568 diff --git a/disassemblers/ofrak_angr/ofrak_angr_test/test_decompilation.py b/disassemblers/ofrak_angr/ofrak_angr_test/test_decompilation.py new file mode 100644 index 000000000..1fd385c3e --- /dev/null +++ b/disassemblers/ofrak_angr/ofrak_angr_test/test_decompilation.py @@ -0,0 +1,36 @@ +from typing import List +import os +from ofrak_angr.components.angr_decompilation_analyzer import AngrDecompilationAnalysis +from ofrak.ofrak_context import OFRAKContext +from ofrak.core.complex_block import ComplexBlock +from ofrak.service.resource_service_i import ResourceFilter + + +async def test_angr_decompilation(ofrak_context: OFRAKContext): + root_resource = await ofrak_context.create_root_resource_from_file( + os.path.join(os.path.dirname(__file__), "assets/hello.x64.elf") + ) + await root_resource.unpack_recursively( + do_not_unpack=[ + ComplexBlock, + ] + ) + complex_blocks: List[ComplexBlock] = await root_resource.get_descendants_as_view( + ComplexBlock, + r_filter=ResourceFilter( + tags=[ + ComplexBlock, + ] + ), + ) + decomps = [] + for complex_block in complex_blocks: + await complex_block.resource.identify() + angr_resource: AngrDecompilationAnalysis = await complex_block.resource.view_as( + AngrDecompilationAnalysis + ) + decomps.append(angr_resource.decompilation) + assert len(decomps) == 11 + assert "" not in decomps + assert "main" in " ".join(decomps) + assert "print" in " ".join(decomps) diff --git a/disassemblers/ofrak_angr/ofrak_angr_test/test_unpackers.py b/disassemblers/ofrak_angr/ofrak_angr_test/test_unpackers.py index 4f09974e3..7e9279d31 100755 --- a/disassemblers/ofrak_angr/ofrak_angr_test/test_unpackers.py +++ b/disassemblers/ofrak_angr/ofrak_angr_test/test_unpackers.py @@ -54,7 +54,7 @@ async def expected_results(self, unpack_verify_test_case: ComplexBlockUnpackerTe 0x110, 0x110, 0x130, - keep_same_is_exit_point=True, + keep_same_is_exit_point=False, ) return self._fixup_test_case_for_pie( @@ -62,6 +62,23 @@ async def expected_results(self, unpack_verify_test_case: ComplexBlockUnpackerTe pie_base_vaddr=0x400000, ) + elif unpack_verify_test_case.binary_md5_digest == "c79d1bea0398d7a9d0faa1ba68786f5e": + # Unlike angr 9.2.6, angr 9.2.77 and 9.2.91 miss this DataWord now + # = the ref to it does not appear in the list of xrefs + + missing_data_words = {0x8030, 0x8060} + + fixed_up_results = { + vaddr: [ + block + for block in original_expected_blocks + if block.virtual_address not in missing_data_words + ] + for vaddr, original_expected_blocks in unpack_verify_test_case.expected_results.items() + } + + return fixed_up_results + return unpack_verify_test_case.expected_results def _split_bb( diff --git a/disassemblers/ofrak_angr/requirements.txt b/disassemblers/ofrak_angr/requirements.txt index a529c3fff..c6a33a3dd 100644 --- a/disassemblers/ofrak_angr/requirements.txt +++ b/disassemblers/ofrak_angr/requirements.txt @@ -1,2 +1,2 @@ -angr==9.2.6 +angr==9.2.77 importlib-resources # A workaround for https://github.com/redballoonsecurity/ofrak/issues/398 diff --git a/disassemblers/ofrak_angr/setup.py b/disassemblers/ofrak_angr/setup.py index a106800d8..481de0e1b 100644 --- a/disassemblers/ofrak_angr/setup.py +++ b/disassemblers/ofrak_angr/setup.py @@ -69,7 +69,7 @@ def read_requirements(requirements_path): "Topic :: Security", "Typing :: Typed", ], - python_requires=">=3.7", + python_requires=">=3.8", license="Proprietary", license_files=["LICENSE"], cmdclass={"egg_info": egg_info_ex}, diff --git a/disassemblers/ofrak_binary_ninja/Dockerstub b/disassemblers/ofrak_binary_ninja/Dockerstub index 19065fa14..22e0e83c0 100644 --- a/disassemblers/ofrak_binary_ninja/Dockerstub +++ b/disassemblers/ofrak_binary_ninja/Dockerstub @@ -1,7 +1,6 @@ RUN apt-get update && apt-get install -y libdbus-1-3 -ARG OFRAK_DIR=. -COPY $OFRAK_DIR/disassemblers/ofrak_binary_ninja/install_binary_ninja_headless_linux.sh /tmp/ -COPY $OFRAK_DIR/disassemblers/ofrak_binary_ninja/pin_version.py /tmp/ +COPY $PACKAGE_PATH/install_binary_ninja_headless_linux.sh /tmp/ +COPY $PACKAGE_PATH/pin_version.py /tmp/ RUN --mount=type=secret,id=serial --mount=type=secret,id=license.dat,dst=/root/.binaryninja/license.dat /tmp/install_binary_ninja_headless_linux.sh && \ python3 /tmp/pin_version.py "3.2.3814 Headless" && \ rm /tmp/install_binary_ninja_headless_linux.sh && \ diff --git a/disassemblers/ofrak_binary_ninja/Makefile b/disassemblers/ofrak_binary_ninja/Makefile index dd2052fa1..d79132149 100644 --- a/disassemblers/ofrak_binary_ninja/Makefile +++ b/disassemblers/ofrak_binary_ninja/Makefile @@ -11,7 +11,7 @@ develop: .PHONY: inspect inspect: - mypy + $(PYTHON) -m mypy .PHONY: test test: inspect diff --git a/disassemblers/ofrak_binary_ninja/install_binary_ninja_headless_linux.sh b/disassemblers/ofrak_binary_ninja/install_binary_ninja_headless_linux.sh index b6e49ed0f..8eab55f2f 100755 --- a/disassemblers/ofrak_binary_ninja/install_binary_ninja_headless_linux.sh +++ b/disassemblers/ofrak_binary_ninja/install_binary_ninja_headless_linux.sh @@ -5,12 +5,13 @@ else echo "Error: BinaryNinja license serial number not found." >&2 exit 1 fi +PACKAGE_NAME="binaryninja-headless.zip" INSTALL_DIR=/opt/rbs mkdir -p $INSTALL_DIR cd $INSTALL_DIR curl -O https://raw.githubusercontent.com/Vector35/binaryninja-api/dev/scripts/download_headless.py python3 -m pip --no-input install requests -python3 download_headless.py --serial $SERIAL -unzip BinaryNinja-headless.zip -rm download_headless.py BinaryNinja-headless.zip +python3 download_headless.py --serial $SERIAL --output "$PACKAGE_NAME" +unzip "$PACKAGE_NAME" +rm download_headless.py "$PACKAGE_NAME" python3 binaryninja/scripts/install_api.py diff --git a/disassemblers/ofrak_binary_ninja/ofrak_binary_ninja/components/binary_ninja_analyzer.py b/disassemblers/ofrak_binary_ninja/ofrak_binary_ninja/components/binary_ninja_analyzer.py index 0ca5a0234..c51404b78 100644 --- a/disassemblers/ofrak_binary_ninja/ofrak_binary_ninja/components/binary_ninja_analyzer.py +++ b/disassemblers/ofrak_binary_ninja/ofrak_binary_ninja/components/binary_ninja_analyzer.py @@ -2,11 +2,17 @@ import tempfile from dataclasses import dataclass from typing import Optional, List +from ofrak.component.abstract import ComponentMissingDependencyError -from binaryninja import open_view, BinaryViewType +try: + from binaryninja import open_view, BinaryViewType + + BINJA_INSTALLED = True +except ImportError: + BINJA_INSTALLED = False from ofrak.component.analyzer import Analyzer -from ofrak.model.component_model import ComponentConfig +from ofrak.model.component_model import ComponentConfig, ComponentExternalTool from ofrak.model.resource_model import ResourceAttributeDependency from ofrak_binary_ninja.components.identifiers import BinaryNinjaAnalysisResource from ofrak_binary_ninja.model import BinaryNinjaAnalysis @@ -15,6 +21,21 @@ LOGGER = logging.getLogger(__file__) +class _BinjaExternalTool(ComponentExternalTool): + def __init__(self): + super().__init__( + "binary_ninja", + "https://ofrak.com/docs/user-guide/disassembler-backends/binary_ninja.html", + install_check_arg="", + ) + + async def is_tool_installed(self) -> bool: + return BINJA_INSTALLED + + +BINJA_TOOL = _BinjaExternalTool() + + @dataclass class BinaryNinjaAnalyzerConfig(ComponentConfig): bndb_file: str # Path to BinaryNinja DB pre-analyzed file @@ -24,10 +45,13 @@ class BinaryNinjaAnalyzer(Analyzer[Optional[BinaryNinjaAnalyzerConfig], BinaryNi id = b"BinaryNinjaAnalyzer" targets = (BinaryNinjaAnalysisResource,) outputs = (BinaryNinjaAnalysis,) + external_dependencies = (BINJA_TOOL,) async def analyze( self, resource: Resource, config: Optional[BinaryNinjaAnalyzerConfig] = None ) -> BinaryNinjaAnalysis: + if not BINJA_INSTALLED: + raise ComponentMissingDependencyError(self, BINJA_TOOL) if not config: resource_data = await resource.get_data() temp_file = tempfile.NamedTemporaryFile() @@ -36,9 +60,9 @@ async def analyze( bv = open_view(temp_file.name) return BinaryNinjaAnalysis(bv) else: - bv = BinaryViewType.get_view_of_file(config.bndb_file) - assert bv is not None - return BinaryNinjaAnalysis(bv) + opt_bv = BinaryViewType.get_view_of_file(config.bndb_file) + assert opt_bv is not None + return BinaryNinjaAnalysis(opt_bv) def _create_dependencies( self, diff --git a/disassemblers/ofrak_binary_ninja/ofrak_binary_ninja/components/blocks/unpackers.py b/disassemblers/ofrak_binary_ninja/ofrak_binary_ninja/components/blocks/unpackers.py index d10725e64..8190b403f 100644 --- a/disassemblers/ofrak_binary_ninja/ofrak_binary_ninja/components/blocks/unpackers.py +++ b/disassemblers/ofrak_binary_ninja/ofrak_binary_ninja/components/blocks/unpackers.py @@ -3,8 +3,8 @@ from typing import Iterable, Tuple, List from typing import Optional from warnings import warn +from ofrak.component.abstract import ComponentMissingDependencyError -from binaryninja import BinaryView, Endianness, TypeClass from ofrak_type.architecture import InstructionSetMode from ofrak_type.range import Range @@ -17,9 +17,15 @@ from ofrak.model.component_model import ComponentConfig from ofrak.resource import Resource from ofrak.service.resource_service_i import ResourceFilter +from ofrak_binary_ninja.components.binary_ninja_analyzer import BINJA_INSTALLED, BINJA_TOOL from ofrak_binary_ninja.components.identifiers import BinaryNinjaAnalysisResource from ofrak_binary_ninja.model import BinaryNinjaAnalysis +if BINJA_INSTALLED: + from binaryninja import BinaryView, Endianness, TypeClass, ReferenceSource +else: + BinaryView = None # type: ignore + LOGGER = logging.getLogger(__name__) @@ -27,7 +33,11 @@ class BinaryNinjaCodeRegionUnpacker(CodeRegionUnpacker): + external_dependencies = (BINJA_TOOL,) + async def unpack(self, resource: Resource, config=None): + if not BINJA_INSTALLED: + raise ComponentMissingDependencyError(self, BINJA_TOOL) region_view = await resource.view_as(CodeRegion) program_r = await region_view.resource.get_only_ancestor_as_view( Program, ResourceFilter.with_tags(Program) @@ -120,7 +130,7 @@ def _binary_ninja_get_complex_blocks( # Add literal pools/data by iterating over data word candidates after the function's # code boundaries, and checking if there are code references to those candidates from # the function's code ranges - data_refs = list() + data_refs: List[ReferenceSource] = list() # Adjust literal pool start address by accounting alignment "nop" instructions while binaryview.get_disassembly(end_ea) == "nop": @@ -148,6 +158,8 @@ def _binary_ninja_get_complex_blocks( class BinaryNinjaComplexBlockUnpacker(ComplexBlockUnpacker): + external_dependencies = (BINJA_TOOL,) + async def unpack(self, resource: Resource, config: Optional[ComponentConfig] = None): cb_view = await resource.view_as(ComplexBlock) program_r = await cb_view.resource.get_only_ancestor_as_view( @@ -240,7 +252,7 @@ async def unpack(self, resource: Resource, config: Optional[ComponentConfig] = N TypeClass.EnumerationTypeClass, ]: LOGGER.debug(f"Potential jump table found at {data_var.address:x}") - word_size = data_var.type.width // data_var.type.count + word_size = data_var.type.width // data_var.type.count # type: ignore else: word_size = data_var.type.width diff --git a/disassemblers/ofrak_binary_ninja/ofrak_binary_ninja/components/data/ref_analyzer.py b/disassemblers/ofrak_binary_ninja/ofrak_binary_ninja/components/data/ref_analyzer.py index 9cc2e7f07..489610281 100644 --- a/disassemblers/ofrak_binary_ninja/ofrak_binary_ninja/components/data/ref_analyzer.py +++ b/disassemblers/ofrak_binary_ninja/ofrak_binary_ninja/components/data/ref_analyzer.py @@ -2,11 +2,14 @@ from collections import defaultdict from typing import DefaultDict, Iterable, List, Tuple -from binaryninja import BinaryView +try: + from binaryninja.binaryview import BinaryView +except ImportError: + BinaryView = None # type: ignore from ofrak.core.data import ReferencedDataAttributes from ofrak.core.program import ReferencedDataAnalyzer -from ofrak_binary_ninja.components.binary_ninja_analyzer import BinaryNinjaAnalyzer +from ofrak_binary_ninja.components.binary_ninja_analyzer import BINJA_TOOL, BinaryNinjaAnalyzer from ofrak_binary_ninja.model import BinaryNinjaAnalysis from ofrak.resource import Resource @@ -19,6 +22,8 @@ class BinaryNinjaReferencedDataAnalyzer(ReferencedDataAnalyzer): Analyzer to get all data references in the program """ + external_dependencies = (BINJA_TOOL,) + async def analyze(self, resource: Resource, config=None) -> Tuple[ReferencedDataAttributes]: if not resource.has_attributes(BinaryNinjaAnalysis): await resource.run(BinaryNinjaAnalyzer) diff --git a/disassemblers/ofrak_binary_ninja/ofrak_binary_ninja/model.py b/disassemblers/ofrak_binary_ninja/ofrak_binary_ninja/model.py index d58fe1da9..35c12fe22 100644 --- a/disassemblers/ofrak_binary_ninja/ofrak_binary_ninja/model.py +++ b/disassemblers/ofrak_binary_ninja/ofrak_binary_ninja/model.py @@ -1,6 +1,9 @@ from dataclasses import dataclass -from binaryninja.binaryview import BinaryView +try: + from binaryninja.binaryview import BinaryView +except ImportError: + BinaryView = None # type: ignore from ofrak.model.resource_model import ResourceAttributes diff --git a/disassemblers/ofrak_binary_ninja/ofrak_binary_ninja_test/test_analyzers.py b/disassemblers/ofrak_binary_ninja/ofrak_binary_ninja_test/test_analyzers.py index 061aeab18..50133a8a7 100644 --- a/disassemblers/ofrak_binary_ninja/ofrak_binary_ninja_test/test_analyzers.py +++ b/disassemblers/ofrak_binary_ninja/ofrak_binary_ninja_test/test_analyzers.py @@ -1,5 +1,7 @@ +from ofrak_binary_ninja.components.binary_ninja_analyzer import BINJA_TOOL from pytest_ofrak.patterns.data_refs_analyzer import DataRefsAnalyzerTestPattern class TestBinjaDataRefsAnalyzer(DataRefsAnalyzerTestPattern): - pass + async def test_installed(self) -> None: + assert await BINJA_TOOL.is_tool_installed() diff --git a/disassemblers/ofrak_capstone/CHANGELOG.md b/disassemblers/ofrak_capstone/CHANGELOG.md index 669a71b1c..bc0b6a026 100644 --- a/disassemblers/ofrak_capstone/CHANGELOG.md +++ b/disassemblers/ofrak_capstone/CHANGELOG.md @@ -5,6 +5,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) ## [Unreleased](https://github.com/redballoonsecurity/ofrak/tree/master) +### Changed +- Update to captione==5.0.0.post1. + ## 1.0.0 - 2022-01-25 ### Added Initial release. Hello world! diff --git a/disassemblers/ofrak_capstone/Makefile b/disassemblers/ofrak_capstone/Makefile index 71746f688..092bf9a46 100644 --- a/disassemblers/ofrak_capstone/Makefile +++ b/disassemblers/ofrak_capstone/Makefile @@ -11,7 +11,7 @@ develop: .PHONY: inspect inspect: - mypy + $(PYTHON) -m mypy .PHONY: test test: inspect diff --git a/disassemblers/ofrak_capstone/requirements.txt b/disassemblers/ofrak_capstone/requirements.txt index ae1c92132..5903f94cb 100644 --- a/disassemblers/ofrak_capstone/requirements.txt +++ b/disassemblers/ofrak_capstone/requirements.txt @@ -1 +1 @@ -capstone==4.0.2 +capstone==5.0.0.post1 diff --git a/disassemblers/ofrak_ghidra/CHANGELOG.md b/disassemblers/ofrak_ghidra/CHANGELOG.md new file mode 100644 index 000000000..f5bcdcb67 --- /dev/null +++ b/disassemblers/ofrak_ghidra/CHANGELOG.md @@ -0,0 +1,14 @@ +# Changelog +All notable changes to `ofrak-ghidra` will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased](https://github.com/redballoonsecurity/ofrak/tree/master) + +## 0.1.1 - 2024-02-15 +### Added +- Added typing support to the ofrak-ghidra package. This is helpful for users who use `mypy` and `ofrak_ghidra` in a project. + +## 0.1.0 - 2022-08-09 +### Added +Initial release. Hello world! diff --git a/disassemblers/ofrak_ghidra/Dockerstub b/disassemblers/ofrak_ghidra/Dockerstub index cb2a840ff..0c6bea09d 100644 --- a/disassemblers/ofrak_ghidra/Dockerstub +++ b/disassemblers/ofrak_ghidra/Dockerstub @@ -9,6 +9,5 @@ RUN mkdir -p /opt/rbs && \ rm -f ghidra_10.1.2_PUBLIC_20220125.zip && \ mv ghidra_10.1.2_PUBLIC/ /opt/rbs/ghidra_10.1.2_PUBLIC -ARG OFRAK_DIR=. WORKDIR / -COPY $OFRAK_DIR/disassemblers/ofrak_ghidra/server.conf /opt/rbs/ghidra_10.1.2_PUBLIC/server/ +COPY $PACKAGE_PATH/server.conf /opt/rbs/ghidra_10.1.2_PUBLIC/server/ diff --git a/disassemblers/ofrak_ghidra/ofrak_ghidra/py.typed b/disassemblers/ofrak_ghidra/ofrak_ghidra/py.typed new file mode 100644 index 000000000..e69de29bb diff --git a/disassemblers/ofrak_ghidra/requirements.txt b/disassemblers/ofrak_ghidra/requirements.txt index 0ef90809a..b423f438a 100644 --- a/disassemblers/ofrak_ghidra/requirements.txt +++ b/disassemblers/ofrak_ghidra/requirements.txt @@ -1,2 +1,2 @@ PyYAML>=5.4 -aiohttp~=3.8.1 +aiohttp~=3.9.3 diff --git a/disassemblers/ofrak_ghidra/setup.py b/disassemblers/ofrak_ghidra/setup.py index 0cd529cf3..a0f2eea93 100644 --- a/disassemblers/ofrak_ghidra/setup.py +++ b/disassemblers/ofrak_ghidra/setup.py @@ -37,6 +37,7 @@ def read_requirements(requirements_path): description="OFRAK Ghidra Components", url="", # TODO packages=setuptools.find_packages(), + package_data={"ofrak_ghidra": ["py.typed"]}, classifiers=[ "Programming Language :: Python :: 3", "Operating System :: OS Independent", diff --git a/docs/environment-setup.md b/docs/environment-setup.md index 7a00c452f..1264320b2 100644 --- a/docs/environment-setup.md +++ b/docs/environment-setup.md @@ -1,13 +1,13 @@ # Environment Setup & Installing OFRAK !!! warning - OFRAK is a Python library supporting Python3.7 and up. First and foremost, make sure your Python and pip installations are for Python3.7+! + OFRAK is a Python library supporting Python3.7 and up. First and foremost, make sure your Python and pip installations are for Python3.7+! Python 3.8 is recommended, as this is the version we primarily test OFRAK with, and some packages (for example, ofrak-angr) require Python >=3.8. There are three main ways one can set up an environment to use OFRAK: 1. From [PyPI](https://pypi.org/project/ofrak/) via `pip`. **This is the simplest setup and generally recommended. Use this!** -2. From the [source code](https://github.com/redballoonsecurity/ofrak) via `pip` or the `setup.py`. +2. From the [source code](https://github.com/redballoonsecurity/ofrak) via a custom install script that relies on `pip`. This is a little more complicated, but allows one to keep with and contribute to OFRAK development. 3. By building the appropriate OFRAK [Docker](https://www.docker.com/get-started) image. This has the most overhead as it requires installing Docker, but provides the most consistent and comprehensive environment. @@ -35,37 +35,40 @@ OFRAK has a system for inspecting and installing such dependencies. See [the sec ## From Source Code -The OFRAK source code can be pulled from [the github page](https://github.com/redballoonsecurity/ofrak): - -```shell -git clone https://github.com/redballoonsecurity/ofrak.git -cd ofrak - -``` +### Prerequisites +#### Git LFS **OFRAK uses Git LFS. This means that you must have Git LFS installed to completely clone the repository!** Install Git LFS by following [the instructions here](https://git-lfs.github.com/). You can install Git LFS before or after you clone OFRAK, but if you clone the OFRAK repo first, you will need to `cd` into the repository and run `git lfs install && git lfs pull`. +#### Python +OFRAK Requires Python 3.7 or higher. Make sure to install the development files as well (e.g. on Ubuntu, run `apt install pythin3.X-dev` for some X>=7). + +#### NPM +OFRAK GUI requires NPM. -Once cloned, go into each directory in the top level and run the installation command `make develop` -(if you do not have and do not wish to have `make` installed, try inspecting the `Makefile` in each directory to see what commands it tries to run, usually something like `pip install -e .`). -The best order to install each directory is as follows: +### Pulling source Code + +The OFRAK source code can be pulled from [the github page](https://github.com/redballoonsecurity/ofrak): + +```shell +git clone https://github.com/redballoonsecurity/ofrak.git +cd ofrak + +``` -1. `ofrak_type` -2. `ofrak_io` -3. `ofrak_patch_maker` -4. `ofrak_core` -5. Any/all others: `frontend`, `ofrak_tutorial`, `disassemblers/ofrak_angr`, `disassemblers/ofrak_binary_ninja`, `disassemblers/ofrak_capstone`, `disassemblers/ofrak_ghidra` +### Installing -You *can* skip the installation step for any of the packages above. -Any subsequent OFRAK packages which require a non-installed package should be able to simply install it from PyPI. -However, this will result in a somewhat confusing environment where some of the OFRAK code in your local repo is actively used by your system, and the rest is not. +Once cloned, run `make install_develop` to create a development install if OFRAK linked to your cloned source tree. +You can also use `make install_tutorial` or `make install_core` to create a standalone install of just the portions of OFRAK needed for the tutorial, or just the core OFRAK respectively. If you have multiple instances of Python 3.X installed on your machine, then prior to running make, you can set the `OFRAK_INSTALL_PYTHON` environment variable to point to a particular version and/or path of python executable (or run `make OFRAK_INSTALL_PYTHON=python3.X install_...`) to have OFRAK installed for a partular Python instance. +There are other installation options - run `./install.py --help` for more information. Installing OFRAK from source code will not install all of OFRAK's non-Python dependencies (for same reason as when installing OFRAK from PyPI - not all of its dependencies are pip-installable). These dependencies are, however, optional, and the OFRAK code that requires them can be disabled in order avoid runtime errors. -OFRAK has a system for inspecting and installing dependencies. See [the section on external dependencies](#handling-non-python-dependencies) for more info on that. +OFRAK has a system for inspecting and installing dependencies. The above `make install_XXX` commands will provide you with a listing of the optional dependencies you are missing. +See [the section on external dependencies](#handling-non-python-dependencies) for more info on that. ### Modifying OFRAK Source Code diff --git a/docs/getting-started.md b/docs/getting-started.md index 7660125b4..25d7ebec7 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -3,7 +3,7 @@ ## Quick Start - Unpack a firmware file and display it in the GUI !!! warning - OFRAK is a Python library supporting Python3.7 and up. First and foremost, make sure your Python and pip installations are for Python3.7+! + OFRAK is a Python library supporting Python3.7 and up. First and foremost, make sure your Python and pip installations are for Python3.7+! Python 3.8 is recommended, as this is the version we primarily test OFRAK with, and some packages (for example, ofrak-angr) require Python >=3.8. ```bash pip install ofrak diff --git a/examples/.gitignore b/examples/.gitignore new file mode 100644 index 000000000..e06558af7 --- /dev/null +++ b/examples/.gitignore @@ -0,0 +1,4 @@ +/src/example_6/program_kitteh +/src/example_6/program_kitteh.o +/src/program +/src/program.o diff --git a/examples/test_examples.py b/examples/test_examples.py index 8e860d876..877394e08 100644 --- a/examples/test_examples.py +++ b/examples/test_examples.py @@ -1,3 +1,4 @@ +import sys import os import subprocess @@ -39,7 +40,7 @@ def test_example_1(tmp_path): Test that the executable built by ex1_simple_string_modification.py prints "Meow!" to stdout. """ file = tmp_path / "example_1.out" - command = ["python3", "ex1_simple_string_modification.py", "--output-file-name", str(file)] + command = [sys.executable, "ex1_simple_string_modification.py", "--output-file-name", str(file)] subprocess.run(command, check=True) os.chmod(str(file), 0o755) stdout = subprocess.run(str(file), capture_output=True).stdout @@ -52,7 +53,7 @@ def test_example_2(tmp_path): infinite loop. """ file = tmp_path / "example_2.out" - command = ["python3", "ex2_simple_code_modification.py", "--output-file-name", str(file)] + command = [sys.executable, "ex2_simple_code_modification.py", "--output-file-name", str(file)] subprocess.run(command, check=True) os.chmod(str(file), 0o755) with pytest.raises(subprocess.TimeoutExpired) as exc_info: @@ -68,7 +69,7 @@ def test_example_3(tmp_path): fault. """ file = tmp_path / "example_3.out" - command = ["python3", "ex3_binary_format_modification.py", "--output-file-name", str(file)] + command = [sys.executable, "ex3_binary_format_modification.py", "--output-file-name", str(file)] subprocess.run(command, check=True) os.chmod(str(file), 0o775) with pytest.raises(subprocess.CalledProcessError, match="Signals.SIGSEGV"): @@ -83,7 +84,7 @@ def test_example_4(tmp_path): * xattrs """ file = tmp_path / "example_4.out" - command = ["python3", "ex4_filesystem_modification.py", "--output-file-name", str(file)] + command = [sys.executable, "ex4_filesystem_modification.py", "--output-file-name", str(file)] subprocess.run(command, check=True) unsquashfs = ["unsquashfs", "-d", tmp_path / "squashfs-root", str(file)] subprocess.run(unsquashfs, check=True) @@ -101,7 +102,7 @@ def test_example_5(tmp_path): Test the the executable built by ex5_binary_extension.py prints seven kitteh. """ file = tmp_path / "example_5.out" - command = ["python3", "ex5_binary_extension.py", "--output-file-name", str(file)] + command = [sys.executable, "ex5_binary_extension.py", "--output-file-name", str(file)] subprocess.run(command, check=True) os.chmod(str(file), 0o755) stdout = subprocess.run(str(file), capture_output=True).stdout @@ -115,7 +116,7 @@ def test_example_6(tmp_path): """ file = tmp_path / "example_6.out" command = [ - "python3", + sys.executable, "ex6_code_modification_without_extension.py", "--output-file-name", str(file), @@ -132,7 +133,12 @@ def test_example_7(tmp_path): "HELLO, WORLD!". """ file = tmp_path / "example_7.out" - command = ["python3", "ex7_code_insertion_with_extension.py", "--output-file-name", str(file)] + command = [ + sys.executable, + "ex7_code_insertion_with_extension.py", + "--output-file-name", + str(file), + ] subprocess.run(command, check=True) os.chmod(str(file), 0o755) stdout = subprocess.run(str(file), capture_output=True).stdout @@ -145,7 +151,7 @@ def test_example_8(tmp_path): the file contains the expected contents """ file = tmp_path / "example_8.tar.gz" - command = ["python3", "ex8_recursive_unpacking.py", "--output-file-name", str(file)] + command = [sys.executable, "ex8_recursive_unpacking.py", "--output-file-name", str(file)] subprocess.run(command, check=True) os.chdir(str(tmp_path)) diff --git a/frontend/Dockerstage b/frontend/Dockerstage index cfc3331fd..e4341f9f0 100644 --- a/frontend/Dockerstage +++ b/frontend/Dockerstage @@ -1,7 +1,6 @@ FROM node:latest AS svelte -ARG OFRAK_DIR=. -COPY --chown=node:node $OFRAK_DIR/frontend /home/node/frontend +COPY --chown=node:node $PACKAGE_DIR /home/node/frontend WORKDIR /home/node/frontend RUN su node -c "npm install && npm run build" diff --git a/frontend/Dockerstub b/frontend/Dockerstub index ebcf772d5..741e45f4e 100644 --- a/frontend/Dockerstub +++ b/frontend/Dockerstub @@ -2,9 +2,8 @@ RUN apt-get update && apt-get install --yes nginx COPY --from=svelte --chown=root:root /home/node/frontend/dist /ofrak_gui -ARG OFRAK_DIR=. -COPY $OFRAK_DIR/frontend/nginx.conf /etc/nginx/sites-enabled/default +COPY $PACKAGE_PATH/nginx.conf /etc/nginx/sites-enabled/default -COPY $OFRAK_DIR/mkdocs.yml /mkdocs.yml -COPY $OFRAK_DIR/docs /docs -COPY $OFRAK_DIR/examples /examples +COPY $PACKAGE_PATH/../mkdocs.yml /mkdocs.yml +COPY $PACKAGE_PATH/../docs /docs +COPY $PACKAGE_PATH/../examples /examples diff --git a/frontend/Makefile b/frontend/Makefile index 2df14a12d..920b2a731 100644 --- a/frontend/Makefile +++ b/frontend/Makefile @@ -96,3 +96,12 @@ develop: .PHONY: test test: + +################################################################################ +# Run for local install from source +################################################################################ + +.PHONY: npm_install_build +npm_install_build: + npm install + npm run build diff --git a/frontend/backend/ofrak_server.Dockerfile b/frontend/backend/ofrak_server.Dockerfile index e6a6dd14b..60d8e8a8d 100644 --- a/frontend/backend/ofrak_server.Dockerfile +++ b/frontend/backend/ofrak_server.Dockerfile @@ -2,7 +2,7 @@ FROM redballoonsecurity/ofrak/dev:latest ARG BACKEND_DIR=. -RUN python3 -m pip install aiohttp~=3.8.1 +RUN python3 -m pip install aiohttp~=3.9.3 ENTRYPOINT python3 -m ofrak_ghidra.server start \ & python3 -m ofrak gui -H 0.0.0.0 -p 8877 \ diff --git a/frontend/public/global.css b/frontend/public/global.css index 28171ad0e..b77e058d0 100644 --- a/frontend/public/global.css +++ b/frontend/public/global.css @@ -13,8 +13,7 @@ * { scrollbar-color: var(--main-fg-color) var(--main-bg-color); - font-family: var(--font), -apple-system, BlinkMacSystemFont, "Segoe UI", - Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; + font-family: var(--font), monospace, monospace; font-variant-ligatures: none; } diff --git a/frontend/src/App.svelte b/frontend/src/App.svelte index ef51d5965..acf3c4ec8 100644 --- a/frontend/src/App.svelte +++ b/frontend/src/App.svelte @@ -3,10 +3,6 @@ box-sizing: border-box; } - .carousel { - margin-top: 1em; - } - .bottomleft { position: absolute; bottom: 0.5em; @@ -29,46 +25,36 @@ -{#await dataLenPromise} - -{:then dataLength} - {#if dataLength > 0} - -
-
- - -
- {#await chunkDataPromise} - - {:then chunks} + + +
+
+ {#if $dataLength > 0} + +
+
+
{#each chunks as _, chunkIndex}
@@ -348,6 +353,7 @@ childRangesResult, byte )} + {/each}
- {/await} +
+ {:else} + Resource has no data! + {/if} +
+ {#if resourceData != undefined} +
+
- {:else} - - - Resource has no data! {/if} -{/await} +
diff --git a/frontend/src/utils/JumpToOffset.svelte b/frontend/src/hex/JumpToOffset.svelte similarity index 56% rename from frontend/src/utils/JumpToOffset.svelte rename to frontend/src/hex/JumpToOffset.svelte index 170b5a071..c139dc7e9 100644 --- a/frontend/src/utils/JumpToOffset.svelte +++ b/frontend/src/hex/JumpToOffset.svelte @@ -16,21 +16,13 @@ diff --git a/frontend/src/views/MagnitudeView.svelte b/frontend/src/hex/MagnitudeView.svelte similarity index 82% rename from frontend/src/views/MagnitudeView.svelte rename to frontend/src/hex/MagnitudeView.svelte index 8d52291bd..ccf322e61 100644 --- a/frontend/src/views/MagnitudeView.svelte +++ b/frontend/src/hex/MagnitudeView.svelte @@ -26,13 +26,14 @@ + +
+ + {#if carouselSelection === "Entropy"} + + {:else if carouselSelection === "Byteclass"} + + {:else if carouselSelection === "Magnitude"} + + {/if} + +
diff --git a/frontend/src/hex/stores.js b/frontend/src/hex/stores.js new file mode 100644 index 000000000..c47596e02 --- /dev/null +++ b/frontend/src/hex/stores.js @@ -0,0 +1,3 @@ +import { writable } from "svelte/store"; + +export const screenHeight = writable(0); diff --git a/frontend/src/ofrak/remote_resource.js b/frontend/src/ofrak/remote_resource.js index 035b94b28..77cad8187 100644 --- a/frontend/src/ofrak/remote_resource.js +++ b/frontend/src/ofrak/remote_resource.js @@ -170,10 +170,9 @@ export class RemoteResource extends Resource { if (this.data_id === null) { return null; } - let result = await fetch(`${this.uri}/get_data_length`).then((r) => - r.json() - ); - return result; + return await fetch(`${this.uri}/get_data_length`).then(async (r) => { + return await r.json(); + }); } async get_data_range_within_parent() { @@ -236,6 +235,25 @@ export class RemoteResource extends Resource { await this.update_script(); } + async identify_recursively() { + const identify_recursively_results = await fetch( + `${this.uri}/identify_recursively`, + { + method: "POST", + } + ).then(async (r) => { + if (!r.ok) { + throw Error(JSON.stringify(await r.json(), undefined, 2)); + } + return r.json(); + }); + ingest_component_results(identify_recursively_results, this.resource_list); + this.flush_cache(); + this.update(); + + await this.update_script(); + } + async unpack_recursively() { const unpack_recursively_results = await fetch( `${this.uri}/unpack_recursively`, diff --git a/frontend/src/ofrak/resource.js b/frontend/src/ofrak/resource.js index 8502e0c21..c9241de6e 100644 --- a/frontend/src/ofrak/resource.js +++ b/frontend/src/ofrak/resource.js @@ -134,6 +134,10 @@ export class Resource { throw new NotImplementedError("identify"); } + async identify_recursively() { + throw new NotImplementedError("identify_recursively"); + } + async pack() { throw new NotImplementedError("pack"); } diff --git a/frontend/src/resource/ResourceTreeNode.svelte b/frontend/src/resource/ResourceTreeNode.svelte index 5e7cd363e..ce502b83a 100644 --- a/frontend/src/resource/ResourceTreeNode.svelte +++ b/frontend/src/resource/ResourceTreeNode.svelte @@ -112,11 +112,10 @@ import LoadingText from "../utils/LoadingText.svelte"; import { onDestroy } from "svelte"; - import { selected } from "../stores.js"; + import { selected, resourceNodeDataMap } from "../stores.js"; import { shortcuts } from "../keyboard"; export let rootResource, - resourceNodeDataMap, selectNextSibling = () => {}, selectPreviousSibling = () => {}, collapsed = true, @@ -131,31 +130,31 @@ kiddoChunksize = 512; $: { - if (resourceNodeDataMap[self_id] === undefined) { - resourceNodeDataMap[self_id] = {}; + if ($resourceNodeDataMap[self_id] === undefined) { + $resourceNodeDataMap[self_id] = {}; } - if (resourceNodeDataMap[self_id].collapsed === undefined) { - resourceNodeDataMap[self_id].collapsed = collapsed; + if ($resourceNodeDataMap[self_id].collapsed === undefined) { + $resourceNodeDataMap[self_id].collapsed = collapsed; } - if (resourceNodeDataMap[self_id].childrenPromise === undefined) { - resourceNodeDataMap[self_id].childrenPromise = + if ($resourceNodeDataMap[self_id].childrenPromise === undefined) { + $resourceNodeDataMap[self_id].childrenPromise = rootResource.get_children(); } - if (resourceNodeDataMap[self_id].commentsPromise === undefined) { - resourceNodeDataMap[self_id].commentsPromise = + if ($resourceNodeDataMap[self_id].commentsPromise === undefined) { + $resourceNodeDataMap[self_id].commentsPromise = rootResource.get_comments(); } - if (resourceNodeDataMap[self_id].lastModified === undefined) { - resourceNodeDataMap[self_id].lastModified = false; + if ($resourceNodeDataMap[self_id].lastModified === undefined) { + $resourceNodeDataMap[self_id].lastModified = false; } - if (resourceNodeDataMap[self_id].allModified === undefined) { - resourceNodeDataMap[self_id].allModified = false; + if ($resourceNodeDataMap[self_id].allModified === undefined) { + $resourceNodeDataMap[self_id].allModified = false; } - childrenPromise = resourceNodeDataMap[self_id].childrenPromise; - commentsPromise = resourceNodeDataMap[self_id].commentsPromise; - collapsed = resourceNodeDataMap[self_id].collapsed; - lastModified = resourceNodeDataMap[self_id].lastModified; - allModified = resourceNodeDataMap[self_id].allModified; + childrenPromise = $resourceNodeDataMap[self_id].childrenPromise; + commentsPromise = $resourceNodeDataMap[self_id].commentsPromise; + collapsed = $resourceNodeDataMap[self_id].collapsed; + lastModified = $resourceNodeDataMap[self_id].lastModified; + allModified = $resourceNodeDataMap[self_id].allModified; } function updateRootModel() { rootResource.update(); @@ -171,10 +170,10 @@ $: if ($selected === self_id) { shortcuts["h"] = () => { - resourceNodeDataMap[self_id].collapsed = true; + $resourceNodeDataMap[self_id].collapsed = true; }; shortcuts["l"] = () => { - resourceNodeDataMap[self_id].collapsed = false; + $resourceNodeDataMap[self_id].collapsed = false; }; shortcuts["j"] = () => { if (!collapsed && firstChild) { @@ -204,7 +203,7 @@ } function onDoubleClick(e) { - resourceNodeDataMap[self_id].collapsed = !collapsed; + $resourceNodeDataMap[self_id].collapsed = !collapsed; // Expand children recursively on double click if (!collapsed) { childrenCollapsed = false; @@ -217,15 +216,15 @@ // As a side effect, the corresponding resource gets selected. $selected = self_id; await rootResource.delete_comment(optional_range); - resourceNodeDataMap[$selected].commentsPromise = + $resourceNodeDataMap[$selected].commentsPromise = rootResource.get_comments(); } // Swap "just modified" indication to "previously modified" indication onDestroy(() => { - if (resourceNodeDataMap[self_id].lastModified) { - resourceNodeDataMap[self_id].allModified = - resourceNodeDataMap[self_id].lastModified; + if ($resourceNodeDataMap[self_id].lastModified) { + $resourceNodeDataMap[self_id].allModified = + $resourceNodeDataMap[self_id].lastModified; } }); @@ -235,7 +234,7 @@ {#if children?.length > 0}
diff --git a/frontend/src/resource/ResourceTreeToolbar.svelte b/frontend/src/resource/ResourceTreeToolbar.svelte index 4b4439fb0..933e39ce3 100644 --- a/frontend/src/resource/ResourceTreeToolbar.svelte +++ b/frontend/src/resource/ResourceTreeToolbar.svelte @@ -15,13 +15,10 @@ selected, settings, selectedProject, + resourceNodeDataMap, } from "../stores.js"; - export let resourceNodeDataMap, - modifierView, - bottomLeftPane, - showProjectManager, - showRootResource; + export let modifierView, bottomLeftPane, showProjectManager, showRootResource; $: rootResource = $selectedResource; function refreshResource() { @@ -80,12 +77,12 @@ shortcut: "i", onclick: async (e) => { await rootResource.identify(); - if (!resourceNodeDataMap[$selected]) { - resourceNodeDataMap[$selected] = {}; + if (!$resourceNodeDataMap[$selected]) { + $resourceNodeDataMap[$selected] = {}; } - resourceNodeDataMap[$selected].collapsed = - !!resourceNodeDataMap[$selected]?.collapsed; - resourceNodeDataMap[$selected].childrenPromise = + $resourceNodeDataMap[$selected].collapsed = + !!$resourceNodeDataMap[$selected]?.collapsed; + $resourceNodeDataMap[$selected].childrenPromise = rootResource.get_children(); refreshResource(); }, @@ -97,11 +94,11 @@ shortcut: "u", onclick: async (e) => { await rootResource.unpack(); - if (!resourceNodeDataMap[$selected]) { - resourceNodeDataMap[$selected] = {}; + if (!$resourceNodeDataMap[$selected]) { + $resourceNodeDataMap[$selected] = {}; } - resourceNodeDataMap[$selected].collapsed = false; - resourceNodeDataMap[$selected].childrenPromise = + $resourceNodeDataMap[$selected].collapsed = false; + $resourceNodeDataMap[$selected].childrenPromise = rootResource.get_children(); refreshResource(); }, @@ -121,12 +118,12 @@ shortcut: "a", onclick: async (e) => { await rootResource.analyze(); - if (!resourceNodeDataMap[$selected]) { - resourceNodeDataMap[$selected] = {}; + if (!$resourceNodeDataMap[$selected]) { + $resourceNodeDataMap[$selected] = {}; } - resourceNodeDataMap[$selected].collapsed = - !!resourceNodeDataMap[$selected]?.collapsed; - resourceNodeDataMap[$selected].childrenPromise = + $resourceNodeDataMap[$selected].collapsed = + !!$resourceNodeDataMap[$selected]?.collapsed; + $resourceNodeDataMap[$selected].childrenPromise = rootResource.get_children(); refreshResource(); }, @@ -148,11 +145,11 @@ const descendants = await $selectedResource.get_descendants(); clearModified(descendants); await rootResource.pack(); - if (!resourceNodeDataMap[$selected]) { - resourceNodeDataMap[$selected] = {}; + if (!$resourceNodeDataMap[$selected]) { + $resourceNodeDataMap[$selected] = {}; } - resourceNodeDataMap[$selected].collapsed = false; - resourceNodeDataMap[$selected].childrenPromise = + $resourceNodeDataMap[$selected].collapsed = false; + $resourceNodeDataMap[$selected].childrenPromise = rootResource.get_children(); refreshResource(); }, @@ -238,17 +235,32 @@ }, }, + { + text: "Identify Recursively", + iconUrl: "/icons/identify.svg", + shortcut: "i+Shift", + onclick: async (e) => { + await rootResource.identify_recursively(); + if (!resourceNodeDataMap[$selected]) { + resourceNodeDataMap[$selected] = {}; + } + resourceNodeDataMap[$selected].childrenPromise = + rootResource.get_children(); + refreshResource(); + }, + }, + { text: "Unpack Recursively", iconUrl: "/icons/unpack_r.svg", shortcut: "u+Shift", onclick: async (e) => { await rootResource.unpack_recursively(); - if (!resourceNodeDataMap[$selected]) { - resourceNodeDataMap[$selected] = {}; + if (!$resourceNodeDataMap[$selected]) { + $resourceNodeDataMap[$selected] = {}; } - resourceNodeDataMap[$selected].collapsed = false; - resourceNodeDataMap[$selected].childrenPromise = + $resourceNodeDataMap[$selected].collapsed = false; + $resourceNodeDataMap[$selected].childrenPromise = rootResource.get_children(); refreshResource(); }, @@ -262,11 +274,11 @@ const descendants = await $selectedResource.get_descendants(); clearModified(descendants); await rootResource.pack_recursively(); - if (!resourceNodeDataMap[$selected]) { - resourceNodeDataMap[$selected] = {}; + if (!$resourceNodeDataMap[$selected]) { + $resourceNodeDataMap[$selected] = {}; } - resourceNodeDataMap[$selected].collapsed = false; - resourceNodeDataMap[$selected].childrenPromise = + $resourceNodeDataMap[$selected].collapsed = false; + $resourceNodeDataMap[$selected].childrenPromise = rootResource.get_children(); refreshResource(); }, @@ -316,11 +328,11 @@ function clearModified(descendants) { for (const descendant of descendants) { - if (!resourceNodeDataMap[descendant["resource_id"]]) { - resourceNodeDataMap[descendant["resource_id"]] = {}; + if (!$resourceNodeDataMap[descendant["resource_id"]]) { + $resourceNodeDataMap[descendant["resource_id"]] = {}; } - resourceNodeDataMap[descendant["resource_id"]].lastModified = undefined; - resourceNodeDataMap[descendant["resource_id"]].allModified = undefined; + $resourceNodeDataMap[descendant["resource_id"]].lastModified = undefined; + $resourceNodeDataMap[descendant["resource_id"]].allModified = undefined; } } diff --git a/frontend/src/resource/ResourceTreeView.svelte b/frontend/src/resource/ResourceTreeView.svelte index 50eb12ab7..8c3416777 100644 --- a/frontend/src/resource/ResourceTreeView.svelte +++ b/frontend/src/resource/ResourceTreeView.svelte @@ -28,12 +28,12 @@ .resources { flex-grow: 1; + overflow: auto; } .treebox { flex-grow: 1; padding-left: 1em; - overflow-x: auto; white-space: nowrap; text-align: left; } @@ -41,7 +41,12 @@ .searchbar { flex-grow: 1; padding-left: 1em; + padding-right: 1em; padding-bottom: 0.5em; + position: sticky; + top: 0; + background-color: var(--main-bg-color); + z-index: 10; } @@ -53,7 +58,6 @@ export let rootResource, modifierView, bottomLeftPane, - resourceNodeDataMap = {}, showProjectManager, showRootResource; @@ -76,7 +80,6 @@
diff --git a/frontend/src/stores.js b/frontend/src/stores.js index dd6973e44..0cd75bc04 100644 --- a/frontend/src/stores.js +++ b/frontend/src/stores.js @@ -49,3 +49,7 @@ export function loadSettings(forceReset) { } export let settings = writable(loadSettings()); + +export let resourceNodeDataMap = writable({}); + +export let dataLength = writable(undefined); diff --git a/frontend/src/utils/Pane.svelte b/frontend/src/utils/Pane.svelte index ca56fdf04..2a37d0c43 100644 --- a/frontend/src/utils/Pane.svelte +++ b/frontend/src/utils/Pane.svelte @@ -10,117 +10,31 @@ flex-flow: row; justify-content: space-between; align-items: stretch; + overflow: hidden; } .inner { - overflow: auto; + overflow: hidden; flex-grow: 1; } - - .minimap-container { - background: var(--main-bg-color); - display: flex; - z-index: 1; - } - - .minimap { - width: 64px; - max-width: 64px; - display: flex; - flex-flow: column; - justify-content: space-between; - align-items: center; - } - -
- {#if scrollY !== undefined} -
- -
- {:else} -
- -
- {/if} - - {#if displayMinimap} -
-
- -
-
- {/if} +
+ +
diff --git a/frontend/src/utils/Script.svelte b/frontend/src/utils/Script.svelte index a618c2afa..a51914121 100644 --- a/frontend/src/utils/Script.svelte +++ b/frontend/src/utils/Script.svelte @@ -7,6 +7,9 @@ align-items: stretch; line-height: var(--line-height); font-size: var(--font-size, medium); + overflow: auto; + max-height: 100%; + min-height: 100%; } .spacer { diff --git a/frontend/src/utils/SearchBar.svelte b/frontend/src/utils/SearchBar.svelte index da674b2fb..69d3880cf 100644 --- a/frontend/src/utils/SearchBar.svelte +++ b/frontend/src/utils/SearchBar.svelte @@ -41,6 +41,7 @@ width: 100%; padding-bottom: 1em; min-height: 2.25em; + background-color: var(--main-bg-color); } .resultwidgets { @@ -93,6 +94,9 @@ prevOptions = {}; function nextMatch() { + if (searchResults.matches === undefined) { + return searchResults; + } let nextIndex = searchResults.index + 1; if (nextIndex >= searchResults.matches.length) { nextIndex = 0; @@ -113,7 +117,8 @@ searchQuery == prevQuery && searchOptions.searchType == prevOptions.searchType && searchOptions.regex == prevOptions.regex && - searchOptions.caseIgnore == prevOptions.caseIgnore + searchOptions.caseIgnore == prevOptions.caseIgnore && + searchResults.matches != undefined // Search results are the only attribute of the search we have control of from other components, so we use it to clear the search when changing selected resources. ); } @@ -163,6 +168,7 @@ {/each} +
+ button { + margin-bottom: 0; + border: 1px solid var(--main-fg-color); + } + + .tabs button:focus { + border-bottom: 2px solid var(--main-bg-color); + outline: 0; + } + + .tabs button { + margin-right: 0.5em; + border-bottom: 0px; + } + + hr { + display: block; + height: 1px; + border: 0; + border-top: 1px solid var(--main-fg-color); + margin-top: -1px; + padding: 0; + } + + + + +
+ {#each tabs as tab} + {#if tabId == tab.id} + + {:else} + + {/if} + {/each} +
+ +
diff --git a/frontend/src/views/AddTagView.svelte b/frontend/src/views/AddTagView.svelte index 9ec564cbd..51461472a 100644 --- a/frontend/src/views/AddTagView.svelte +++ b/frontend/src/views/AddTagView.svelte @@ -68,21 +68,26 @@ - - {#await Promise.all([blocksPromise, dataWordsPromise])} {:then [blocks, dataWords]} @@ -126,7 +116,7 @@
- {#each blocks as block} + {#each blocks as block, i} {#each block as instruction}
{instruction.get_attributes()[ @@ -137,6 +127,10 @@ "ofrak.model._auto_attributes.AttributesType[Instruction]" ].operands}
+ {:else} + {#if i == 0} +

I said "Unpack Recursively"

+ {/if} {/each}
{:else} diff --git a/frontend/src/views/AttributesView.svelte b/frontend/src/views/AttributesView.svelte index db6e6be49..c7a69567b 100644 --- a/frontend/src/views/AttributesView.svelte +++ b/frontend/src/views/AttributesView.svelte @@ -3,6 +3,12 @@ font-size: 1em; } + .attributes { + max-height: calc(100% - 3em); + min-height: calc(100% - 3em); + overflow: auto; + } + a { color: var(--main-fg-color); } @@ -35,19 +41,20 @@ } -{#if resource !== undefined} -

Tags:

- {#each resource.get_tags() as tag, i} - {cleanOfrakType(tag)}{i !== resource.get_tags().length - 1 ? ", " : ""} - {/each} - -

Attributes:

- -{/if} +
+ {#if resource !== undefined} +

Tags:

+ {#each resource.get_tags() as tag, i} + {cleanOfrakType(tag)}{i !== resource.get_tags().length - 1 ? ", " : ""} + {/each} +

Attributes:

+ + {/if} +
diff --git a/frontend/src/views/BinaryModifyView.svelte b/frontend/src/views/BinaryModifyView.svelte index 04cd9cd8f..328a8210c 100644 --- a/frontend/src/views/BinaryModifyView.svelte +++ b/frontend/src/views/BinaryModifyView.svelte @@ -84,23 +84,15 @@ } from "../helpers.js"; import { selected, + resourceNodeDataMap, + dataLength, selectedResource as _selectedResource, } from "../stores.js"; import Button from "../utils/Button.svelte"; const selectedResource = $_selectedResource; - export let modifierView, dataLenPromise, resourceNodeDataMap; - let startInput, - endInput, - startOffset, - endOffset, - dataLength, - errorMessage, - userData; - - $: dataLenPromise.then((r) => { - dataLength = r; - }); + export let modifierView; + let startInput, endInput, startOffset, endOffset, errorMessage, userData; function refreshResource() { // Force hex view refresh with colors @@ -167,10 +159,10 @@ if (selectedResource) { await selectedResource.queue_patch(patchData, startOffset, endOffset); } - if (!resourceNodeDataMap[$selected]) { - resourceNodeDataMap[$selected] = {}; + if (!$resourceNodeDataMap[$selected]) { + $resourceNodeDataMap[$selected] = {}; } - resourceNodeDataMap[$selected].lastModified = true; + $resourceNodeDataMap[$selected].lastModified = true; modifierView = undefined; refreshResource(); } catch (err) { @@ -226,9 +218,7 @@ {#if errorMessage} diff --git a/frontend/src/views/CarveView.svelte b/frontend/src/views/CarveView.svelte index 5ed8a4bc6..175b602a6 100644 --- a/frontend/src/views/CarveView.svelte +++ b/frontend/src/views/CarveView.svelte @@ -63,20 +63,21 @@ + + +
+ + {#each tabs as tab} + {#if tabId == tab.id} + + {/if} + {/each} +
diff --git a/frontend/src/views/DecompilationView.svelte b/frontend/src/views/DecompilationView.svelte new file mode 100644 index 000000000..26c897b6f --- /dev/null +++ b/frontend/src/views/DecompilationView.svelte @@ -0,0 +1,45 @@ + + + + + +
+ {@html decompilation} +
+
diff --git a/frontend/src/views/FindReplaceView.svelte b/frontend/src/views/FindReplaceView.svelte index a7b747861..7e7ea0c0f 100644 --- a/frontend/src/views/FindReplaceView.svelte +++ b/frontend/src/views/FindReplaceView.svelte @@ -69,10 +69,14 @@ - - {#await dataPromise.then(bufferToString)} {:then data} diff --git a/install.py b/install.py new file mode 100755 index 000000000..af143d572 --- /dev/null +++ b/install.py @@ -0,0 +1,264 @@ +#!/usr/bin/env python3 +from dataclasses import dataclass +from enum import Enum +from typing import List, Optional + +import argparse +import os +import subprocess +import sys +import yaml +import shutil +import logging + +from build_image import InstallTarget + +LOGGER = logging.getLogger(__name__) +LOGGER.setLevel(logging.INFO) + + +class DependencyMechanism(Enum): + NONE = "none" + SHOW = "show" + APT = "apt" + BREW = "brew" + + +@dataclass +class OfrakInstallConfig: + packages_paths: List[str] + python_command: str + install_target: InstallTarget + dependency_mechanism: DependencyMechanism + dep_install: List[str] + quiet: bool + run_tests: bool + + +def main(): + handler = logging.StreamHandler(sys.stdout) + handler.setLevel(logging.INFO) + formatter = logging.Formatter("*** %(msg)s") + handler.setFormatter(formatter) + LOGGER.addHandler(handler) + + config = parse_args() + + for package_path in config.packages_paths: + check_package_contents(package_path) + + LOGGER.info(f"Checking whether npm is installed") + check_executable(config, "npm") + + install_type = ( + "development environment " if config.install_target == InstallTarget.DEVELOP else "" + ) + LOGGER.info( + f"Installing OFRAK {install_type}for {config.python_command} from: " + f"{', '.join(config.packages_paths)}." + ) + for package_path in config.packages_paths: + install_package(config, package_path) + + if config.dependency_mechanism == DependencyMechanism.NONE: + pass + elif config.dependency_mechanism == DependencyMechanism.SHOW: + LOGGER.info("Checking for missing OFRAK dependencies") + show_dependencies(config) + show_install(config, "apt", "sudo apt install -y") + show_install(config, "brew", "brew install") + else: + install_deps(config) + LOGGER.info("Checking OFRAK dependencies that may need to be installed manually") + if not config.quiet: + show_dependencies(config) + + +def parse_args() -> OfrakInstallConfig: + parser = argparse.ArgumentParser() + parser.add_argument( + "--config", + help="Path to a .yml configuration file specifying which OFRAK packages to install", + required=True, + ) + parser.add_argument( + "--target", + choices=[InstallTarget.DEVELOP.value, InstallTarget.INSTALL.value], + default=InstallTarget.DEVELOP.value, + help='Installation type. Use "install" for regular installation, and "develop" to install in ' + 'editable mode (i.e. setuptools "develop mode") from the source tree paths, and include ' + 'development (test, build documentation, etc) dependencies. Defaults to "develop"', + ) + parser.add_argument( + "--python", + default=os.getenv("OFRAK_INSTALL_PYTHON", "python3"), + help="Path to, or name of the python executable to install OFRAK for. Defaults to the value of" + 'the "OFRAK_INSTALL_PYTHON" environment variable if set, and "python3", if not', + ) + parser.add_argument( + "--install_deps", + choices=[ + DependencyMechanism.NONE.value, + DependencyMechanism.SHOW.value, + DependencyMechanism.APT.value, + DependencyMechanism.BREW.value, + ], + default=os.getenv("OFRAK_INSTALL_DEPS", DependencyMechanism.SHOW.value), + help='Method for installing non-pip dependencies. One of: "none" - do not install, "show" - ' + 'show how to install them, but do not install automatically, "apt" - install using APT ' + '(requires sudo), "brew" - install using brew. Defaults to the value of the ' + '"OFRAK_INSTALL_DEPS" environment variable if set, and "show", if not', + ) + parser.add_argument("--quiet", "-q", action="store_true", help="Reduce verbosity") + parser.add_argument( + "--test", + action="store_true", + help="Run OFRAK tests after install. Can also be enabled by setting the OFRAK_TEST_AFTER_INSTALL environment valiable to a non-empty value", + ) + args = parser.parse_args() + if args.quiet: + LOGGER.setLevel(logging.ERROR) + python = shutil.which(args.python) + if python is None: + LOGGER.critical( + "Specify correct name or path of python binary to use, using either the " + '"--python" command line argument, or the "OFRAK_INSTALL_PYTHON" environment variable.', + ) + raise ValueError(f"{args.python} not found") + with open(args.config) as file_handle: + config_dict = yaml.safe_load(file_handle) + if args.install_deps == "apt": + install_command = ["sudo", "apt", "install", "-y"] + elif args.install_deps == "brew": + install_command = ["brew", "install"] + else: + install_command = [] + install_config = OfrakInstallConfig( + packages_paths=config_dict["packages_paths"], + python_command=python, + install_target=InstallTarget(args.target), + dependency_mechanism=DependencyMechanism(args.install_deps), + quiet=args.quiet, + dep_install=install_command, + run_tests=args.test or bool(os.getenv("OFRAK_TEST_AFTER_INSTALL", "")), + ) + return install_config + + +def check_package_contents(package_path: str): + for content in [package_path, os.path.join(package_path, "Makefile")]: + if not os.path.exists(content): + raise ValueError(f"Required path {content} do not exist") + return + + +def check_executable(config: OfrakInstallConfig, executable: str) -> None: + if shutil.which(executable) is None: + if config.dependency_mechanism in [DependencyMechanism.APT, DependencyMechanism.BREW]: + LOGGER.warning(f"{executable} not found, attempting to install") + run_command(config, config.dep_install + [executable]) + elif config.dependency_mechanism in [DependencyMechanism.NONE, DependencyMechanism.SHOW]: + if config.dependency_mechanism == DependencyMechanism.SHOW: + LOGGER.critical( + f"{executable} not found, please install manually, or use" + ' "--install_deps" / "OFRAK_INSTALL_DEPS" to have it be installed automatically' + f' for you: with apt: "sudo apt install -y {executable}";' + f' with brew: "brew install {executable}"' + ) + raise FileNotFoundError(2, f"{executable} not found", executable) + + +def install_package(config: OfrakInstallConfig, package_path: str) -> None: + LOGGER.info(f"Installing from {package_path}") + if os.path.exists(os.path.join(package_path, "package.json")): + run_command(config, ["make", "-C", package_path, "npm_install_build"]) + run_command( + config, + [ + "make", + f"PYTHON={config.python_command}", + f"PIP={config.python_command} -m pip", + "-C", + package_path, + config.install_target.value, + ], + ) + if config.run_tests: + run_command(config, [config.python_command, "-m", "pip", "check"]) + run_command( + config, + [ + "make", + f"PYTHON={config.python_command}", + "-C", + package_path, + "test", + ], + ) + + +def show_dependencies(config: OfrakInstallConfig) -> None: + missing_deps = run_ofrak_command(config, ["deps", "--missing-only"], capture_out=True) + if missing_deps: + print("\n*** Some optional OFRAK dependencies are missing. ***") + print( + "To get full mileage out of OFRAK, you may want to also install some of the following:" + ) + print(missing_deps.rstrip()) + + +def show_install(config: OfrakInstallConfig, dep: str, prefix: str) -> None: + deps = run_ofrak_command( + config, + ["deps", "--missing-only", f"--packages-for={dep}"], + True, + ) + if deps: + deps = deps.strip().replace("\n", " ") + print( + f"** If your system has {dep}, you can install some of the above missing dependencies using:" + ) + print(f"** {prefix} {deps}") + + +def install_deps(config: OfrakInstallConfig) -> None: + LOGGER.info( + "Installing those OFRAK dependencies that can be installed with " + + config.dependency_mechanism.value + ) + deps = run_ofrak_command( + config, + ["deps", "--missing-only", f"--packages-for={config.dependency_mechanism.value}"], + True, + ) + assert deps is not None + run_command(config, config.dep_install + deps.split()) + + +def run_ofrak_command( + config: OfrakInstallConfig, args: List[str], capture_out=False +) -> Optional[str]: + return run_command(config, [config.python_command, "-m", "ofrak"] + args, capture_out) + + +def run_command(config: OfrakInstallConfig, args: List[str], capture_out=False) -> Optional[str]: + (LOGGER.debug if capture_out else LOGGER.info)("% " + " ".join(args)) + result = subprocess.run(args=args, capture_output=capture_out, check=True) + return result.stdout.decode("ascii") if capture_out else None + + +if __name__ == "__main__": + try: + main() + except subprocess.CalledProcessError as error: + LOGGER.critical(f"Error running shell command, exit status: {error.returncode}") + sys.exit(error.returncode) + except ValueError as error: + LOGGER.critical(f"Error: {error}") + sys.exit(1) + except FileNotFoundError as error: + LOGGER.critical(f"Error: No such file or directory: {error.filename}") + sys.exit(1) + except Exception as error: + LOGGER.critical(f"Unexpected exception: {error}") + sys.exit(1) diff --git a/ofrak-all.yml b/ofrak-all.yml new file mode 100644 index 000000000..14e6b8c58 --- /dev/null +++ b/ofrak-all.yml @@ -0,0 +1,24 @@ +registry: "redballoonsecurity/ofrak" +base_image_name: "all-base" +image_name: "all" +packages_paths: + [ + "ofrak_type", + "ofrak_io", + "ofrak_patch_maker", + "ofrak_core", + "disassemblers/ofrak_ghidra", + "disassemblers/ofrak_binary_ninja", + "disassemblers/ofrak_capstone", + "disassemblers/ofrak_angr", + "examples", + "frontend", + "ofrak_tutorial", + ] +extra_build_args: + ["--secret", + "id=serial,src=serial.txt", + "--secret", + "id=license.dat,src=license.dat" + ] +entrypoint: python3 -m ofrak_ghidra.server start diff --git a/ofrak_core/CHANGELOG.md b/ofrak_core/CHANGELOG.md index 044532b50..71a472a7e 100644 --- a/ofrak_core/CHANGELOG.md +++ b/ofrak_core/CHANGELOG.md @@ -5,8 +5,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) ## [Unreleased](https://github.com/redballoonsecurity/ofrak/tree/master) ### Added +- Add modifier to add and remove sections using lief. ([#443](https://github.com/redballoonsecurity/ofrak/pull/443)) +- Add tabbed content views and a decompilation view to the OFRAK GUI. ([#436](https://github.com/redballoonsecurity/ofrak/pull/436/)) +- Refactor HexView and related components to use mousewheel instead of scroll and compartmentalize all comonents to src/hex. ([#427](https://github.com/redballoonsecurity/ofrak/pull/427)) - Add an improved ISO9660 packer that leverages `mkisofs` instead of PyCdLib. ([#393](https://github.com/redballoonsecurity/ofrak/pull/393)) - Add UEFI binary unpacker. ([#399](https://github.com/redballoonsecurity/ofrak/pull/399)) +- Add recursive identify functionality in the GUI. ([#435](https://github.com/redballoonsecurity/ofrak/pull/435)) ### Fixed - Improved flushing of filesystem entries (including symbolic links and other types) to disk. ([#373](https://github.com/redballoonsecurity/ofrak/pull/373)) @@ -18,10 +22,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) - Fix dragging and dropping in the GUI. ([#407](https://github.com/redballoonsecurity/ofrak/pull/407)) - Fix running scripts without a project selected, and without a config selected. ([#407](https://github.com/redballoonsecurity/ofrak/pull/407)) - Fix bug in OFRAK GUI server which causes an error when parsing a default config value of bytes. ([#409](https://github.com/redballoonsecurity/ofrak/pull/409)) +- Set default fallback font to system default monospace, instead of variable-width sans-serif. ([#422](https://github.com/redballoonsecurity/ofrak/pull/422)) +- View resource attribute string values containing only digits primarily as strings, alternatively as hex numbers. ([#423](https://github.com/redballoonsecurity/ofrak/pull/423)) ### Changed - Change `FreeSpaceModifier` & `PartialFreeSpaceModifier` behavior: an optional stub that isn't free space can be provided and fill-bytes for free space can be specified. ([#409](https://github.com/redballoonsecurity/ofrak/pull/409)) - `Resource.flush_to_disk` method renamed to `Resource.flush_data_to_disk`. ([#373](https://github.com/redballoonsecurity/ofrak/pull/373)) +- `build_image.py` supports building Docker images with OFRAK packages from any ancestor directory. ([#425](https://github.com/redballoonsecurity/ofrak/pull/425)) ## [3.2.0](https://github.com/redballoonsecurity/ofrak/compare/ofrak-v3.1.0...ofrak-v3.2.0) ### Added diff --git a/ofrak_core/Dockerstub b/ofrak_core/Dockerstub index f4725a6be..f41711480 100644 --- a/ofrak_core/Dockerstub +++ b/ofrak_core/Dockerstub @@ -20,9 +20,6 @@ RUN apt-get -y update && \ unar \ zstd -# python-lzo needed by ubireader -RUN python3 -m pip install python-lzo - # Install apktool and uber-apk-signer RUN apt-get -y update && apt-get -y install openjdk-11-jdk RUN wget https://raw.githubusercontent.com/iBotPeaches/Apktool/v2.3.3/scripts/linux/apktool -O /usr/local/bin/apktool && \ @@ -61,7 +58,7 @@ RUN cd /tmp && \ # Install Jefferson WORKDIR /tmp -RUN wget https://bootstrap.pypa.io/pip/get-pip.py && python3.9 get-pip.py && python3.7 get-pip.py && rm get-pip.py +RUN wget https://bootstrap.pypa.io/pip/get-pip.py && python3.9 get-pip.py && python3.8 get-pip.py && rm get-pip.py RUN python3.9 -m pip install jefferson WORKDIR / diff --git a/ofrak_core/Makefile b/ofrak_core/Makefile index 6488bcf86..76e4b35c7 100644 --- a/ofrak_core/Makefile +++ b/ofrak_core/Makefile @@ -3,15 +3,15 @@ PIP=pip3 .PHONY: install install: ofrak/gui/public - $(PIP) install . + $(PIP) install .[non-pypi] .PHONY: develop develop: ofrak/gui/public - $(PIP) install -e .[docs,test] + $(PIP) install -e .[docs,test,non-pypi] .PHONY: inspect inspect: - mypy + $(PYTHON) -m mypy .PHONY: test test: inspect @@ -23,6 +23,7 @@ ofrak/gui/public: cp -r /ofrak_gui ofrak/gui/public ; \ elif [ -d ../frontend ]; then \ cd ../frontend && \ + npm install && \ npm run build && \ cd ../ofrak_core && \ cp -r ../frontend/dist ofrak/gui/public ; \ diff --git a/ofrak_core/ofrak/core/binwalk.py b/ofrak_core/ofrak/core/binwalk.py index 6a87d3723..b633ff0ac 100644 --- a/ofrak_core/ofrak/core/binwalk.py +++ b/ofrak_core/ofrak/core/binwalk.py @@ -30,7 +30,9 @@ def __init__(self): super().__init__( "binwalk", "https://github.com/ReFirmLabs/binwalk", - install_check_arg="", + install_check_arg="-q", + apt_package="binwalk", + brew_package="binwalk", ) async def is_tool_installed(self) -> bool: diff --git a/ofrak_core/ofrak/core/elf/lief_modifier.py b/ofrak_core/ofrak/core/elf/lief_modifier.py index b15c40e64..a6774eed3 100644 --- a/ofrak_core/ofrak/core/elf/lief_modifier.py +++ b/ofrak_core/ofrak/core/elf/lief_modifier.py @@ -73,3 +73,54 @@ async def modify(self, resource: Resource, config: LiefAddSegmentConfig) -> None new_data = f_handle.read() # replace all old content (old range) with new content from Lief resource.queue_patch(Range(0, await resource.get_data_length()), new_data) + + +@dataclass +class LiefAddSectionModifierConfig(ComponentConfig): + name: str + content: bytes + flags: int + + +class LiefAddSectionModifer(Modifier[LiefAddSectionModifierConfig]): + targets = (Elf,) + + async def modify(self, resource: Resource, config: LiefAddSectionModifierConfig): + binary: lief.ELF.Binary = lief.parse(await resource.get_data()) + section: lief.ELF.Section = lief.ELF.Section() + section.name = config.name + section.content = list(config.content) + section.flags = config.flags + binary.add(section) + + with tempfile.NamedTemporaryFile() as temp_file: + binary.write(temp_file.name) + temp_file.flush() + with open(temp_file.name, "rb") as f_handle: + new_data = f_handle.read() + # replace all old content (old range) with new content from Lief + resource.queue_patch(Range(0, await resource.get_data_length()), new_data) + + +@dataclass +class LiefRemoveSectionModifierConfig(ComponentConfig): + name: str + + +class LiefRemoveSectionModifier(Modifier[LiefRemoveSectionModifierConfig]): + targets = (Elf,) + + async def modify(self, resource: Resource, config: LiefRemoveSectionModifierConfig): + binary: lief.ELF.Binary = lief.parse(await resource.get_data()) + section: lief.ELF.Section = binary.get_section(config.name) + if section is None: + raise AttributeError(f"No section with name {config.name}") + binary.remove(section) + + with tempfile.NamedTemporaryFile() as temp_file: + binary.write(temp_file.name) + temp_file.flush() + with open(temp_file.name, "rb") as f_handle: + new_data = f_handle.read() + # replace all old content (old range) with new content from Lief + resource.queue_patch(Range(0, await resource.get_data_length()), new_data) diff --git a/ofrak_core/ofrak/core/squashfs.py b/ofrak_core/ofrak/core/squashfs.py index 10bdf645a..832029d04 100644 --- a/ofrak_core/ofrak/core/squashfs.py +++ b/ofrak_core/ofrak/core/squashfs.py @@ -18,13 +18,23 @@ LOGGER = logging.getLogger(__name__) MKSQUASHFS = ComponentExternalTool( - "mksquashfs", "https://github.com/plougher/squashfs-tools", "-help" + "mksquashfs", + "https://github.com/plougher/squashfs-tools", + "-help", + apt_package="squashfs-tools", + brew_package="squashfs", ) class _UnsquashfsV45Tool(ComponentExternalTool): def __init__(self): - super().__init__("unsquashfs", "https://github.com/plougher/squashfs-tools", "") + super().__init__( + "unsquashfs", + "https://github.com/plougher/squashfs-tools", + "", + apt_package="squashfs-tools", + brew_package="squashfs", + ) async def is_tool_installed(self) -> bool: try: diff --git a/ofrak_core/ofrak/core/strings.py b/ofrak_core/ofrak/core/strings.py index 5b6af0da6..807205683 100644 --- a/ofrak_core/ofrak/core/strings.py +++ b/ofrak_core/ofrak/core/strings.py @@ -8,7 +8,6 @@ from ofrak.core.binary import BinaryPatchConfig, BinaryPatchModifier, GenericText, GenericBinary from ofrak.core.code_region import CodeRegion from ofrak.core.filesystem import File -from ofrak.core.program_section import ProgramSection from ofrak.model.component_model import ComponentConfig from ofrak.model.resource_model import index from ofrak.model.viewable_tag_model import AttributesType @@ -126,7 +125,7 @@ class StringsUnpacker(Unpacker[None]): Unpack NULL-terminated strings of printable ASCII characters. """ - targets = (ProgramSection,) # TODO: Other reasonable targets? + targets = () # Strings unpacker is slow, don't run by default. children = (AsciiString,) # match sequences of at least 2 (or 8 in CodeRegions) printable characters ending with NULL diff --git a/ofrak_core/ofrak/gui/server.py b/ofrak_core/ofrak/gui/server.py index af51594f9..125e5bfe3 100644 --- a/ofrak_core/ofrak/gui/server.py +++ b/ofrak_core/ofrak/gui/server.py @@ -175,6 +175,7 @@ def __init__( web.post("/{resource_id}/pack_recursively", self.pack_recursively), web.post("/{resource_id}/analyze", self.analyze), web.post("/{resource_id}/identify", self.identify), + web.post("/{resource_id}/identify_recursively", self.identify_recursively), web.post("/{resource_id}/data_summary", self.data_summary), web.get("/{resource_id}/get_parent", self.get_parent), web.get("/{resource_id}/get_ancestors", self.get_ancestors), @@ -538,6 +539,20 @@ async def identify(self, request: Request) -> Response: raise e return json_response(await self._serialize_component_result(result)) + @exceptions_to_http(SerializedError) + async def identify_recursively(self, request: Request) -> Response: + resource = await self._get_resource_for_request(request) + script_str = """ + await {resource}.identify_recursively()""" + await self.script_builder.add_action(resource, script_str, ActionType.MOD) + try: + result = await resource.auto_run_recursively(all_identifiers=True) + await self.script_builder.commit_to_script(resource) + except Exception as e: + await self.script_builder.clear_script_queue(resource) + raise e + return json_response(await self._serialize_component_result(result)) + @exceptions_to_http(SerializedError) async def data_summary(self, request: Request) -> Response: resource = cast(Resource, await self._get_resource_for_request(request)) @@ -1178,8 +1193,11 @@ async def get_project_script(self, request: Request) -> Response: script_name_query = request.query.get("script") if script_name_query is not None: script_name = script_name_query - project = self._get_project_by_id(project_id) - script_body = project.get_script_body(script_name) + if script_name == "undefined": + script_body = "" + else: + project = self._get_project_by_id(project_id) + script_body = project.get_script_body(script_name) return Response(text=script_body) diff --git a/ofrak_core/pytest_ofrak/patterns/basic_block_unpacker.py b/ofrak_core/pytest_ofrak/patterns/basic_block_unpacker.py index 5c0e0f012..e25858c39 100644 --- a/ofrak_core/pytest_ofrak/patterns/basic_block_unpacker.py +++ b/ofrak_core/pytest_ofrak/patterns/basic_block_unpacker.py @@ -756,6 +756,14 @@ class BasicBlockUnpackerTestCase( operands="", mode=InstructionSetMode.NONE, ), + Instruction( + virtual_address=0x4004E0, + size=2, + disassembly="repz ret ", + mnemonic="repz ret", + operands="", + mode=InstructionSetMode.NONE, + ), ), ], 0x4004F0: [ diff --git a/ofrak_core/pytest_ofrak/patterns/complex_block_unpacker.py b/ofrak_core/pytest_ofrak/patterns/complex_block_unpacker.py index c632017d1..198e8391a 100644 --- a/ofrak_core/pytest_ofrak/patterns/complex_block_unpacker.py +++ b/ofrak_core/pytest_ofrak/patterns/complex_block_unpacker.py @@ -231,7 +231,7 @@ class ComplexBlockUnpackerTestCase(UnpackAndVerifyTestCase[int, List[Union[Basic is_exit_point=True, exit_vaddr=None, ), - DataWord(virtual_address=32816, size=4, format_string="=4.13 @@ -9,9 +10,10 @@ intervaltree==3.1.0 keystone-engine==0.9.2 jefferson==0.4.5;python_version>="3.8" lief==0.12.3 -orjson~=3.8.7 +orjson~=3.9.15 pefile==2023.2.7 pycdlib==1.12.0 +python-lzo python-magic;platform_system!="Windows" python-magic-bin;platform_system=="Windows" reedsolo==1.7.0 diff --git a/ofrak_core/test_ofrak/components/test_comments.py b/ofrak_core/test_ofrak/components/test_comments.py index 4e8fee044..085b11c1b 100644 --- a/ofrak_core/test_ofrak/components/test_comments.py +++ b/ofrak_core/test_ofrak/components/test_comments.py @@ -1,3 +1,4 @@ +from datetime import timedelta import pytest from hypothesis import given, HealthCheck, settings from hypothesis.strategies import text @@ -38,7 +39,10 @@ async def test_adding_comments(executable_resource: Resource): # We suppress the function_scoped_fixture health check because the executable_resource fixture # doesn't need to be reset between individual runs of hypothesis (since the comment overrides # the previous one every time). -@settings(suppress_health_check=[HealthCheck.function_scoped_fixture]) +@settings( + suppress_health_check=[HealthCheck.function_scoped_fixture], + deadline=timedelta(seconds=5), +) @given(comment_str=text()) async def test_comment_content(executable_resource: Resource, comment_str: str): """Test comments with all kinds of string contents.""" diff --git a/ofrak_core/test_ofrak/components/test_elf_modifiers.py b/ofrak_core/test_ofrak/components/test_elf_modifiers.py index d3714fae9..b302e45cc 100644 --- a/ofrak_core/test_ofrak/components/test_elf_modifiers.py +++ b/ofrak_core/test_ofrak/components/test_elf_modifiers.py @@ -1,11 +1,19 @@ import os import subprocess +from typing import Optional import pytest from elftools.elf.elffile import ELFFile from test_ofrak.components.hello_world_elf import hello_elf -from ofrak.core import LiefAddSegmentConfig, LiefAddSegmentModifier +from ofrak.core import ( + LiefAddSegmentConfig, + LiefAddSegmentModifier, + LiefAddSectionModifer, + LiefAddSectionModifierConfig, + LiefRemoveSectionModifier, + LiefRemoveSectionModifierConfig, +) from ofrak.service.resource_service_i import ResourceFilter from ofrak.core.elf.model import ( Elf, @@ -254,3 +262,35 @@ def assert_segment_exists(filepath: str, vaddr: int, length: int): if segment.header.p_vaddr == vaddr and segment.header.p_memsz == length: return raise ValueError("Could not find segment in binary") + + +async def test_lief_add_section_modifier(hello_out: Resource, tmp_path): + config = LiefAddSectionModifierConfig(name=".test", content=b"test", flags=0) + await hello_out.run(LiefAddSectionModifer, config=config) + elf_path = tmp_path / "test.elf" + await hello_out.flush_data_to_disk(elf_path) + assert segment_exists(elf_path, ".test", content=b"test") + + +async def test_lief_remove_section_modifier(hello_out: Resource, tmp_path): + original = tmp_path / "original.elf" + await hello_out.flush_data_to_disk(original) + assert segment_exists(original, ".text") + config = LiefRemoveSectionModifierConfig(name=".text") + await hello_out.run(LiefRemoveSectionModifier, config=config) + modified = tmp_path / "modified.elf" + await hello_out.flush_data_to_disk(modified) + assert not segment_exists(modified, ".text") + + +def segment_exists(filepath: str, name: str, content: Optional[bytes] = None): + with open(filepath, "rb") as f: + elffile = ELFFile(f) + sections = list(elffile.iter_sections()) + for section in sections: + if section.name == name: + if content is not None and content in section.data(): + return True + if content is None: + return True + return False diff --git a/ofrak_core/test_ofrak/components/test_string.py b/ofrak_core/test_ofrak/components/test_string.py index 5e2e3b0c9..df5f249fc 100644 --- a/ofrak_core/test_ofrak/components/test_string.py +++ b/ofrak_core/test_ofrak/components/test_string.py @@ -6,11 +6,13 @@ from ofrak import OFRAKContext from ofrak.component.modifier import ModifierError +from ofrak.core import ProgramSection from ofrak.core.binary import GenericBinary from ofrak.resource import Resource from ofrak.service.resource_service_i import ResourceFilter from ofrak.core.strings import ( AsciiString, + StringsUnpacker, StringPatchingConfig, StringPatchingModifier, StringFindReplaceConfig, @@ -93,12 +95,16 @@ def executable_file(string_test_directory): async def executable_strings(ofrak_context: OFRAKContext, executable_file) -> List[str]: root_resource = await ofrak_context.create_root_resource_from_file(executable_file) await root_resource.unpack_recursively() + for d in await root_resource.get_descendants(r_filter=ResourceFilter.with_tags(ProgramSection)): + await d.run(StringsUnpacker) descendants = list( await root_resource.get_descendants_as_view( AsciiString, r_filter=ResourceFilter.with_tags(AsciiString), ) ) + for d in descendants: + assert d.text[:8] in d.resource.get_caption() return [string.Text for string in descendants] diff --git a/ofrak_core/test_ofrak/unit/test_ofrak_context.py b/ofrak_core/test_ofrak/unit/test_ofrak_context.py index ed50f2bb7..93eb23ca9 100644 --- a/ofrak_core/test_ofrak/unit/test_ofrak_context.py +++ b/ofrak_core/test_ofrak/unit/test_ofrak_context.py @@ -64,6 +64,9 @@ async def run_component_with_installed_dependency(ofrak_context: OFRAKContext): def test_get_ofrak_context_over_time(): + loop = asyncio.new_event_loop() + asyncio.set_event_loop(loop) + # No active context before running OFRAK with pytest.raises(InvalidStateError): get_current_ofrak_context() diff --git a/ofrak_core/test_ofrak/unit/test_ofrak_server.py b/ofrak_core/test_ofrak/unit/test_ofrak_server.py index 5305752ad..3c4f46bc2 100644 --- a/ofrak_core/test_ofrak/unit/test_ofrak_server.py +++ b/ofrak_core/test_ofrak/unit/test_ofrak_server.py @@ -349,6 +349,17 @@ async def test_identify(ofrak_client: TestClient, hello_world_elf): assert resp_body["modified"][0]["id"] == create_body["id"] +async def test_identify_recursively(ofrak_client: TestClient, hello_world_elf): + create_resp = await ofrak_client.post( + "/create_root_resource", params={"name": "hello_world_elf"}, data=hello_world_elf + ) + create_body = await create_resp.json() + resp = await ofrak_client.post(f"/{create_body['id']}/identify_recursively") + assert resp.status == 200 + resp_body = await resp.json() + assert resp_body["modified"][0]["id"] == create_body["id"] + + async def test_data_summary(ofrak_client: TestClient, ofrak_server, hello_world_elf, test_resource): create_resp = await ofrak_client.post( "/create_root_resource", params={"name": "hello_world_elf"}, data=hello_world_elf diff --git a/ofrak_io/Makefile b/ofrak_io/Makefile index 0f5724824..4ae28cc73 100644 --- a/ofrak_io/Makefile +++ b/ofrak_io/Makefile @@ -11,7 +11,7 @@ develop: .PHONY: inspect inspect: - mypy + $(PYTHON) -m mypy .PHONY: test test: inspect diff --git a/ofrak_patch_maker/CHANGELOG.md b/ofrak_patch_maker/CHANGELOG.md index 17f7a66c7..fe2f9b5ce 100644 --- a/ofrak_patch_maker/CHANGELOG.md +++ b/ofrak_patch_maker/CHANGELOG.md @@ -12,6 +12,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) ### Fixed - X86_64 toolchain now installs on Docker image builds for AARCH64 hosts. ([#405](https://github.com/redballoonsecurity/ofrak/pull/405)) +- Toolchain now drops the .altinstrs_replacement as well as the .altinstructions section in our generated linker scripts ([#414](https://github.com/redballoonsecurity/ofrak/pull/414)) + +### Changed +- Removed `SUBALIGN(0)` for `.bss` sections ## [4.0.2](https://github.com/redballoonsecurity/ofrak/compare/ofrak-patch-maker-v.4.0.1...ofrak-patch-maker-v.4.0.2) ### Fixed diff --git a/ofrak_patch_maker/Makefile b/ofrak_patch_maker/Makefile index 8c311007f..12799dd04 100644 --- a/ofrak_patch_maker/Makefile +++ b/ofrak_patch_maker/Makefile @@ -12,7 +12,7 @@ develop: .PHONY: inspect inspect: - mypy + $(PYTHON) -m mypy .PHONY: test test: inspect diff --git a/ofrak_patch_maker/ofrak_patch_maker/toolchain/abstract.py b/ofrak_patch_maker/ofrak_patch_maker/toolchain/abstract.py index 61553bb32..9f437a482 100644 --- a/ofrak_patch_maker/ofrak_patch_maker/toolchain/abstract.py +++ b/ofrak_patch_maker/ofrak_patch_maker/toolchain/abstract.py @@ -95,6 +95,7 @@ def __init__( ".dynstr", ".eh_frame", ".altinstructions", + ".altinstr_replacement", ] self._assembler_target = self._get_assembler_target(processor) diff --git a/ofrak_patch_maker/ofrak_patch_maker/toolchain/gnu.py b/ofrak_patch_maker/ofrak_patch_maker/toolchain/gnu.py index 51ca0b2fd..93120b515 100644 --- a/ofrak_patch_maker/ofrak_patch_maker/toolchain/gnu.py +++ b/ofrak_patch_maker/ofrak_patch_maker/toolchain/gnu.py @@ -185,7 +185,7 @@ def ld_generate_bss_section( ) -> str: bss_section_name = ".bss" return ( - f" {bss_section_name} : SUBALIGN(0) {{\n" + f" {bss_section_name} : {{\n" f" *.o({bss_section_name}, {bss_section_name}.*)\n" f" }} > {memory_region_name}" ) diff --git a/ofrak_tutorial/Dockerstub b/ofrak_tutorial/Dockerstub index cd504da1a..deaec2896 100644 --- a/ofrak_tutorial/Dockerstub +++ b/ofrak_tutorial/Dockerstub @@ -1,4 +1,3 @@ -ARG OFRAK_DIR=. -COPY $OFRAK_DIR/mkdocs.yml /mkdocs.yml -COPY $OFRAK_DIR/docs /docs -COPY $OFRAK_DIR/examples /examples +COPY $PACKAGE_PATH/../mkdocs.yml /mkdocs.yml +COPY $PACKAGE_PATH/../docs /docs +COPY $PACKAGE_PATH/../examples /examples diff --git a/ofrak_tutorial/Makefile b/ofrak_tutorial/Makefile index f52592550..0249e0e33 100644 --- a/ofrak_tutorial/Makefile +++ b/ofrak_tutorial/Makefile @@ -39,7 +39,7 @@ install: .PHONY: inspect inspect: - mypy + $(PYTHON) -m mypy .PHONY: test test: inspect diff --git a/ofrak_tutorial/notebooks_with_outputs/2_ofrak_internals.ipynb b/ofrak_tutorial/notebooks_with_outputs/2_ofrak_internals.ipynb index 1ca30ab6d..5cf92e314 100644 --- a/ofrak_tutorial/notebooks_with_outputs/2_ofrak_internals.ipynb +++ b/ofrak_tutorial/notebooks_with_outputs/2_ofrak_internals.ipynb @@ -85,8 +85,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "240 resources created\n", - "241 resources modified\n" + "170 resources created\n", + "171 resources modified\n" ] } ], @@ -113,7 +113,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "components run: [b'ApkIdentifier', b'DeviceTreeBlobIdentifier', b'ElfDynamicSectionUnpacker', b'ElfPointerArraySectionUnpacker', b'ElfRelaUnpacker', b'ElfSymbolUnpacker', b'ElfUnpacker', b'MagicDescriptionIdentifier', b'MagicMimeIdentifier', b'OpenWrtIdentifier', b'StringsUnpacker', b'UbiIdentifier', b'UbifsIdentifier', b'Uf2FileIdentifier']\n" + "components run: [b'ApkIdentifier', b'DeviceTreeBlobIdentifier', b'ElfDynamicSectionUnpacker', b'ElfPointerArraySectionUnpacker', b'ElfRelaUnpacker', b'ElfSymbolUnpacker', b'ElfUnpacker', b'MagicDescriptionIdentifier', b'MagicMimeIdentifier', b'OpenWrtIdentifier', b'UbiIdentifier', b'UbifsIdentifier', b'Uf2FileIdentifier']\n" ] } ], @@ -159,247 +159,177 @@ "name": "stdout", "output_type": "stream", "text": [ - "┌a5c49dd26f224bb78a5ad6ff10ab80c1: [caption=(Elf, File: hello_world), attributes=(AttributesType[FilesystemEntry], Magic), global_offset=(0x0-0x4020), parent_offset=(0x0-0x0), data_hash=f5cd0893]\n", - "├────931a90f06a554e55bfb445c68d44aeb6: [caption=(ElfBasicHeader), attributes=(Data, AttributesType[ElfBasicHeader]), global_offset=(0x0-0x10), parent_offset=(0x0-0x10), data_hex=7f454c46020101000000000000000000]\n", - "├────99d957fbc0ae4c658dd27d2e916cd3c4: [caption=(ElfHeader), attributes=(Data, AttributesType[ElfHeader]), global_offset=(0x10-0x40), parent_offset=(0x10-0x40), data_hex=02003e000100000040104000000000004000000000000000e03800000000000000000000400038000b0040001d001c00]\n", - "├────671177d59166495380997a3bfda764f0: [caption=(ElfSectionHeader), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[ElfSectionHeader]), global_offset=(0x38e0-0x3920), parent_offset=(0x38e0-0x3920), data_hex=00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000]\n", - "├────dda2ead0461643c9b7db86e03e183083: [caption=(ElfSection), attributes=(AttributesType[ElfSectionStructure])]\n", - "├────72a9a50018f048b7b6fdf86e66517767: [caption=(ElfSectionHeader), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[ElfSectionHeader]), global_offset=(0x3920-0x3960), parent_offset=(0x3920-0x3960), data_hex=1b000000010000000200000000000000a802400000000000a8020000000000001c00000000000000000000000000000001000000000000000000000000000000]\n", - "├───┬32bb4025ec51480f99dcf9d77aa9dadf: [caption=(ElfSection), attributes=(Data, AttributesType[ElfSectionStructure]), global_offset=(0x2a8-0x2c4), parent_offset=(0x2a8-0x2c4), data_hex=2f6c696236342f6c642d6c696e75782d7838362d36342e736f2e3200]\n", - "│ └────3450290c7ead4745835ea85afe0d5e84: [caption=(string: '/lib64/ld-linux-x86-64.so.2'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x2a8-0x2c4), parent_offset=(0x0-0x1c), data_hex=2f6c696236342f6c642d6c696e75782d7838362d36342e736f2e3200]\n", - "├────f7ebd872a39c4aa69095d18c1fa6356d: [caption=(ElfSectionHeader), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[ElfSectionHeader]), global_offset=(0x3960-0x39a0), parent_offset=(0x3960-0x39a0), data_hex=23000000070000000200000000000000c402400000000000c4020000000000002400000000000000000000000000000004000000000000000000000000000000]\n", - "├───┬696f353d58b04cbcb973af537018f2e2: [caption=(ElfSection), attributes=(Data, AttributesType[ElfSectionStructure]), global_offset=(0x2c4-0x2e8), parent_offset=(0x2c4-0x2e8), data_hex=040000001400000003000000474e550017fb4e8bc7504a89fa3603690cb745adfd747237]\n", - "│ └────f01388b0c68040f3b29882b376793887: [caption=(string: 'GNU'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x2d0-0x2d4), parent_offset=(0xc-0x10), data_hex=474e5500]\n", - "├────db27e6857442424d9aa42bf00272c902: [caption=(ElfSectionHeader), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[ElfSectionHeader]), global_offset=(0x39a0-0x39e0), parent_offset=(0x39a0-0x39e0), data_hex=36000000070000000200000000000000e802400000000000e8020000000000002000000000000000000000000000000004000000000000000000000000000000]\n", - "├───┬7a19c35462d14ac697cdd66910d4a990: [caption=(ElfSection), attributes=(Data, AttributesType[ElfSectionStructure]), global_offset=(0x2e8-0x308), parent_offset=(0x2e8-0x308), data_hex=040000001000000001000000474e550000000000030000000200000000000000]\n", - "│ └────8d6ace47e17d4adf80a7aaa098005bb0: [caption=(string: 'GNU'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x2f4-0x2f8), parent_offset=(0xc-0x10), data_hex=474e5500]\n", - "├────9461425a866f442a839d28371d1e23fb: [caption=(ElfSectionHeader), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[ElfSectionHeader]), global_offset=(0x39e0-0x3a20), parent_offset=(0x39e0-0x3a20), data_hex=44000000f6ffff6f0200000000000000080340000000000008030000000000001c00000000000000050000000000000008000000000000000000000000000000]\n", - "├────53a4aadfeae542b480c37fd1133314ff: [caption=(ElfSection), attributes=(Data, AttributesType[ElfSectionStructure]), global_offset=(0x308-0x324), parent_offset=(0x308-0x324), data_hex=01000000010000000100000000000000000000000000000000000000]\n", - "├────faf10ed697ce461f9d82c1be4221927f: [caption=(ElfSectionHeader), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[ElfSectionHeader]), global_offset=(0x3a20-0x3a60), parent_offset=(0x3a20-0x3a60), data_hex=4e0000000b0000000200000000000000280340000000000028030000000000006000000000000000060000000100000008000000000000001800000000000000]\n", - "├───┬858bf2a78ca247bb82d8cce186888285: [caption=(ElfDynSymbolSection: .dynsym), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[NamedProgramSection], AttributesType[MemoryRegion], AttributesType[Addressable]), global_offset=(0x328-0x388), parent_offset=(0x328-0x388), data_hex=0000000000000000000000000000000000000000000000000100000012000000000000000000000000000000000000000600000012000000000000000000000000000000000000002e0000002000000000000000000000000000000000000000]\n", - "│ ├────c1d2714cd40a4585b5f993f1be6d77b6: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x328-0x340), parent_offset=(0x0-0x18), data_hex=000000000000000000000000000000000000000000000000]\n", - "│ ├────1eb5c61adafc49c6b417ecd0a2b11276: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x340-0x358), parent_offset=(0x18-0x30), data_hex=010000001200000000000000000000000000000000000000]\n", - "│ ├────f3cd6398f7964fe2bd6139ba4aa49505: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x358-0x370), parent_offset=(0x30-0x48), data_hex=060000001200000000000000000000000000000000000000]\n", - "│ └────40c329c571da4040a651e977b7b4fad6: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x370-0x388), parent_offset=(0x48-0x60), data_hex=2e0000002000000000000000000000000000000000000000]\n", - "├────f740d0d72348421fb549c7de6fe7de1c: [caption=(ElfSectionHeader), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[ElfSectionHeader]), global_offset=(0x3a60-0x3aa0), parent_offset=(0x3a60-0x3aa0), data_hex=56000000030000000200000000000000880340000000000088030000000000003d00000000000000000000000000000001000000000000000000000000000000]\n", - "├───┬a6146a8edd1e44aca9030d95a209ba71: [caption=(ElfSection, ElfStringSection), attributes=(Data, AttributesType[ElfSectionStructure]), global_offset=(0x388-0x3c5), parent_offset=(0x388-0x3c5), data_hex=0070757473005f5f6c6962635f73746172745f6d61696e006c6962632e736f2e3600474c4942435f322e322e35005f5f676d6f6e5f73746172745f5f00]\n", - "│ ├────37884d72a15d4d668182721a7709eb27: [caption=(string: 'puts'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x389-0x38e), parent_offset=(0x1-0x6), data_hex=7075747300]\n", - "│ ├────c18792e9bba7418a8eaf844757e9a1e1: [caption=(string: '__libc_start_main'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x38e-0x3a0), parent_offset=(0x6-0x18), data_hex=5f5f6c6962635f73746172745f6d61696e00]\n", - "│ ├────76e942414f4449989898b851f865479e: [caption=(string: 'libc.so.6'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x3a0-0x3aa), parent_offset=(0x18-0x22), data_hex=6c6962632e736f2e3600]\n", - "│ ├────610f5e3ce42f4f8596b2327ba22b89ce: [caption=(string: 'GLIBC_2.2.5'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x3aa-0x3b6), parent_offset=(0x22-0x2e), data_hex=474c4942435f322e322e3500]\n", - "│ └────068336e239464429a78744a64f94796d: [caption=(string: '__gmon_start__'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x3b6-0x3c5), parent_offset=(0x2e-0x3d), data_hex=5f5f676d6f6e5f73746172745f5f00]\n", - "├────7dec697a3f7f4807b2f5c8a1628f98f5: [caption=(ElfSectionHeader), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[ElfSectionHeader]), global_offset=(0x3aa0-0x3ae0), parent_offset=(0x3aa0-0x3ae0), data_hex=5e000000ffffff6f0200000000000000c603400000000000c6030000000000000800000000000000050000000000000002000000000000000200000000000000]\n", - "├────38324503e0bf4526a5fc803a6ca5341f: [caption=(ElfSection), attributes=(Data, AttributesType[ElfSectionStructure]), global_offset=(0x3c6-0x3ce), parent_offset=(0x3c6-0x3ce), data_hex=0000020002000000]\n", - "├────e872db918d67416f86fa82bd7365910a: [caption=(ElfSectionHeader), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[ElfSectionHeader]), global_offset=(0x3ae0-0x3b20), parent_offset=(0x3ae0-0x3b20), data_hex=6b000000feffff6f0200000000000000d003400000000000d0030000000000002000000000000000060000000100000008000000000000000000000000000000]\n", - "├───┬389b7b99e4ee4e37b2afaa5bc863062e: [caption=(ElfSection), attributes=(Data, AttributesType[ElfSectionStructure]), global_offset=(0x3d0-0x3f0), parent_offset=(0x3d0-0x3f0), data_hex=01000100180000001000000000000000751a6909000002002200000000000000]\n", - "│ └────fba047efeac14aceb8258e0fa9c6b996: [caption=(string: 'i\t'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x3e2-0x3e5), parent_offset=(0x12-0x15), data_hex=690900]\n", - "├────8351601478e74e3e9a439b75b806cde1: [caption=(ElfSectionHeader), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[ElfSectionHeader]), global_offset=(0x3b20-0x3b60), parent_offset=(0x3b20-0x3b60), data_hex=7a000000040000000200000000000000f003400000000000f0030000000000003000000000000000050000000000000008000000000000001800000000000000]\n", - "├───┬f37e3ab202d6424b96ed64849f3af863: [caption=(ElfRelaSection: .rela.dyn), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[NamedProgramSection], AttributesType[MemoryRegion], AttributesType[Addressable]), global_offset=(0x3f0-0x420), parent_offset=(0x3f0-0x420), data_hex=f03f40000000000006000000020000000000000000000000f83f40000000000006000000030000000000000000000000]\n", - "│ ├────79d91f4e9d5a4c86af83751bf625740c: [caption=(ElfRelaEntry), attributes=(Data), global_offset=(0x3f0-0x408), parent_offset=(0x0-0x18), data_hex=f03f40000000000006000000020000000000000000000000]\n", - "│ └────877837cdbfba40b7b6162badaae1ba41: [caption=(ElfRelaEntry), attributes=(Data), global_offset=(0x408-0x420), parent_offset=(0x18-0x30), data_hex=f83f40000000000006000000030000000000000000000000]\n", - "├────39d9ad9747cc4f64a90d48af8cbb9580: [caption=(ElfSectionHeader), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[ElfSectionHeader]), global_offset=(0x3b60-0x3ba0), parent_offset=(0x3b60-0x3ba0), data_hex=84000000040000004200000000000000200440000000000020040000000000001800000000000000050000001600000008000000000000001800000000000000]\n", - "├───┬337d596e83c041de8a89f226136681e2: [caption=(ElfRelaSection: .rela.plt), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[NamedProgramSection], AttributesType[MemoryRegion], AttributesType[Addressable]), global_offset=(0x420-0x438), parent_offset=(0x420-0x438), data_hex=184040000000000007000000010000000000000000000000]\n", - "│ └────ff3dd5e68beb4e1f8f7bbb25c41dba98: [caption=(ElfRelaEntry), attributes=(Data), global_offset=(0x420-0x438), parent_offset=(0x0-0x18), data_hex=184040000000000007000000010000000000000000000000]\n", - "├────bab9240c0b7e4ae9950b35392d1fba9c: [caption=(ElfSectionHeader), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[ElfSectionHeader]), global_offset=(0x3ba0-0x3be0), parent_offset=(0x3ba0-0x3be0), data_hex=8e000000010000000600000000000000001040000000000000100000000000001700000000000000000000000000000004000000000000000000000000000000]\n", - "├────d53f13b1d70c486397c25938311aeeab: [caption=(CodeRegion, ElfSection), attributes=(Data, AttributesType[ElfSectionStructure]), global_offset=(0x1000-0x1017), parent_offset=(0x1000-0x1017), data_hex=4883ec08488b05ed2f00004885c07402ffd04883c408c3]\n", - "├────851274651d3a4ed7a659d5e86c74def5: [caption=(ElfSectionHeader), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[ElfSectionHeader]), global_offset=(0x3be0-0x3c20), parent_offset=(0x3be0-0x3c20), data_hex=89000000010000000600000000000000201040000000000020100000000000002000000000000000000000000000000010000000000000001000000000000000]\n", - "├────565fc63a77494276bafea235ae00344e: [caption=(CodeRegion, ElfSection), attributes=(Data, AttributesType[ElfSectionStructure]), global_offset=(0x1020-0x1040), parent_offset=(0x1020-0x1040), data_hex=ff35e22f0000ff25e42f00000f1f4000ff25e22f00006800000000e9e0ffffff]\n", - "├────2298029fa70846288abbbdb6d70dba5f: [caption=(ElfSectionHeader), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[ElfSectionHeader]), global_offset=(0x3c20-0x3c60), parent_offset=(0x3c20-0x3c60), data_hex=94000000010000000600000000000000401040000000000040100000000000006101000000000000000000000000000010000000000000000000000000000000]\n", - "├────1200d9c6b7ba4406bd97d44ef17fea4b: [caption=(CodeRegion, ElfSection), attributes=(Data, AttributesType[ElfSectionStructure]), global_offset=(0x1040-0x11a1), parent_offset=(0x1040-0x11a1), data_hash=1eeedffe]\n", - "├────d144e1261ccb444a8159bf767a973c20: [caption=(ElfSectionHeader), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[ElfSectionHeader]), global_offset=(0x3c60-0x3ca0), parent_offset=(0x3c60-0x3ca0), data_hex=9a000000010000000600000000000000a411400000000000a4110000000000000900000000000000000000000000000004000000000000000000000000000000]\n", - "├────9fb3213d0af14510828108089c1d521b: [caption=(CodeRegion, ElfSection), attributes=(Data, AttributesType[ElfSectionStructure]), global_offset=(0x11a4-0x11ad), parent_offset=(0x11a4-0x11ad), data_hex=4883ec084883c408c3]\n", - "├────0848476f439c4aa2b9809063a2c8081a: [caption=(ElfSectionHeader), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[ElfSectionHeader]), global_offset=(0x3ca0-0x3ce0), parent_offset=(0x3ca0-0x3ce0), data_hex=a0000000010000000200000000000000002040000000000000200000000000001200000000000000000000000000000004000000000000000000000000000000]\n", - "├───┬b473b26106ac441b9e54171d47cdfa40: [caption=(ElfSection), attributes=(Data, AttributesType[ElfSectionStructure]), global_offset=(0x2000-0x2012), parent_offset=(0x2000-0x2012), data_hex=0100020048656c6c6f2c20576f726c642100]\n", - "│ └────4d904e2d99da484d8ebc635c82b3f1fe: [caption=(string: 'Hello, World!'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x2004-0x2012), parent_offset=(0x4-0x12), data_hex=48656c6c6f2c20576f726c642100]\n", - "├────a9a19b9c5cba4366913b338778f377eb: [caption=(ElfSectionHeader), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[ElfSectionHeader]), global_offset=(0x3ce0-0x3d20), parent_offset=(0x3ce0-0x3d20), data_hex=a8000000010000000200000000000000142040000000000014200000000000003c00000000000000000000000000000004000000000000000000000000000000]\n", - "├───┬1ab4bcc3d1314e34b56bf0798000b712: [caption=(ElfSection), attributes=(Data, AttributesType[ElfSectionStructure]), global_offset=(0x2014-0x2050), parent_offset=(0x2014-0x2050), data_hex=011b033b38000000060000000cf0ffff940000002cf0ffff540000005cf0ffff800000000ef1ffffbc0000002cf1ffffdc0000008cf1ffff24010000]\n", - "│ └────0bf1f6f2187b453fbf0cf595d5a68731: [caption=(string: ';8'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x2017-0x201a), parent_offset=(0x3-0x6), data_hex=3b3800]\n", - "├────101b8c782dd54141811ea3e807988b73: [caption=(ElfSectionHeader), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[ElfSectionHeader]), global_offset=(0x3d20-0x3d60), parent_offset=(0x3d20-0x3d60), data_hex=b6000000010000000200000000000000502040000000000050200000000000000001000000000000000000000000000008000000000000000000000000000000]\n", - "├───┬3350874dceb54bf79a0ac41cc2a7c25a: [caption=(ElfSection), attributes=(Data, AttributesType[ElfSectionStructure]), global_offset=(0x2050-0x2150), parent_offset=(0x2050-0x2150), data_hash=ef716b33]\n", - "│ ├────595f99fdb3fc4e6a9d695070e61b9bb3: [caption=(string: 'zR'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x2059-0x205c), parent_offset=(0x9-0xc), data_hex=7a5200]\n", - "│ ├────7e9fb6357ff0494ab81188da589fdb0e: [caption=(string: 'zR'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x2085-0x2088), parent_offset=(0x35-0x38), data_hex=7a5200]\n", - "│ └────52e4dd2b6e2f4f4da3f4f2d3e95cc223: [caption=(string: ';*3$\"'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x20c7-0x20cd), parent_offset=(0x77-0x7d), data_hex=3b2a33242200]\n", - "├────2e207290286544f2aeb6cc686e0c48e0: [caption=(ElfSectionHeader), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[ElfSectionHeader]), global_offset=(0x3d60-0x3da0), parent_offset=(0x3d60-0x3da0), data_hex=c00000000e0000000300000000000000103e400000000000102e0000000000000800000000000000000000000000000008000000000000000800000000000000]\n", - "├───┬df1e9c44ed28444f9a2856e643a92a0c: [caption=(ElfSection, ElfInitArraySection), attributes=(Data, AttributesType[ElfSectionStructure]), global_offset=(0x2e10-0x2e18), parent_offset=(0x2e10-0x2e18), data_hex=2011400000000000]\n", - "│ └────bc9f1bdd9684408dbea4b0ef5addbbfc: [caption=(ElfVirtualAddress), attributes=(Data), global_offset=(0x2e10-0x2e18), parent_offset=(0x0-0x8), data_hex=2011400000000000]\n", - "├────f07749153fbd47a5903be326c4da7174: [caption=(ElfSectionHeader), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[ElfSectionHeader]), global_offset=(0x3da0-0x3de0), parent_offset=(0x3da0-0x3de0), data_hex=cc0000000f0000000300000000000000183e400000000000182e0000000000000800000000000000000000000000000008000000000000000800000000000000]\n", - "├───┬23266aa9e76444ce86b97ba64491c29a: [caption=(ElfFiniArraySection, ElfSection), attributes=(Data, AttributesType[ElfSectionStructure]), global_offset=(0x2e18-0x2e20), parent_offset=(0x2e18-0x2e20), data_hex=f010400000000000]\n", - "│ └────2f229a15b7e84ca798f342f2778d6e7d: [caption=(ElfVirtualAddress), attributes=(Data), global_offset=(0x2e18-0x2e20), parent_offset=(0x0-0x8), data_hex=f010400000000000]\n", - "├────e21bd25cf9534e38afe44a13cdf9394b: [caption=(ElfSectionHeader), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[ElfSectionHeader]), global_offset=(0x3de0-0x3e20), parent_offset=(0x3de0-0x3e20), data_hex=d8000000060000000300000000000000203e400000000000202e000000000000d001000000000000060000000000000008000000000000001000000000000000]\n", - "├───┬b3a8ea72360b466cb742ce187d393cd8: [caption=(ElfDynamicSection: .dynamic), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[NamedProgramSection], AttributesType[MemoryRegion], AttributesType[Addressable]), global_offset=(0x2e20-0x2ff0), parent_offset=(0x2e20-0x2ff0), data_hash=4438de54]\n", - "│ ├────902fe84ed9614a2192c76f9248d9e176: [caption=(ElfDynamicEntry), attributes=(Data), global_offset=(0x2e20-0x2e30), parent_offset=(0x0-0x10), data_hex=01000000000000001800000000000000]\n", - "│ ├────c7715e03d69547a9a1d45cb1e68799df: [caption=(ElfDynamicEntry), attributes=(Data), global_offset=(0x2e30-0x2e40), parent_offset=(0x10-0x20), data_hex=0c000000000000000010400000000000]\n", - "│ ├────599a7b820fa24b34b0f229e29bb999d6: [caption=(ElfDynamicEntry), attributes=(Data), global_offset=(0x2e40-0x2e50), parent_offset=(0x20-0x30), data_hex=0d00000000000000a411400000000000]\n", - "│ ├────9578e852c8424cddbe1b5c5e774b2be2: [caption=(ElfDynamicEntry), attributes=(Data), global_offset=(0x2e50-0x2e60), parent_offset=(0x30-0x40), data_hex=1900000000000000103e400000000000]\n", - "│ ├────34f2e461333a43fe9f6fbf260a1e3fe1: [caption=(ElfDynamicEntry), attributes=(Data), global_offset=(0x2e60-0x2e70), parent_offset=(0x40-0x50), data_hex=1b000000000000000800000000000000]\n", - "│ ├────9cdacdf7eea640a2ba32f3e98a9d264a: [caption=(ElfDynamicEntry), attributes=(Data), global_offset=(0x2e70-0x2e80), parent_offset=(0x50-0x60), data_hex=1a00000000000000183e400000000000]\n", - "│ ├────ee67b77dd99a434293fb9b942a6d562c: [caption=(ElfDynamicEntry), attributes=(Data), global_offset=(0x2e80-0x2e90), parent_offset=(0x60-0x70), data_hex=1c000000000000000800000000000000]\n", - "│ ├────471d4598dbb74dec8c9657944cfbd847: [caption=(ElfDynamicEntry), attributes=(Data), global_offset=(0x2e90-0x2ea0), parent_offset=(0x70-0x80), data_hex=f5feff6f000000000803400000000000]\n", - "│ ├────6bb19c21cc5a4dfc99e9e324b0f949dd: [caption=(ElfDynamicEntry), attributes=(Data), global_offset=(0x2ea0-0x2eb0), parent_offset=(0x80-0x90), data_hex=05000000000000008803400000000000]\n", - "│ ├────e9edeb23fd66451fb5793ed446579575: [caption=(ElfDynamicEntry), attributes=(Data), global_offset=(0x2eb0-0x2ec0), parent_offset=(0x90-0xa0), data_hex=06000000000000002803400000000000]\n", - "│ ├────a0968874e2b94bb1a11f4609edcc74e5: [caption=(ElfDynamicEntry), attributes=(Data), global_offset=(0x2ec0-0x2ed0), parent_offset=(0xa0-0xb0), data_hex=0a000000000000003d00000000000000]\n", - "│ ├────8b77f44ed03046c0a62e208e13996625: [caption=(ElfDynamicEntry), attributes=(Data), global_offset=(0x2ed0-0x2ee0), parent_offset=(0xb0-0xc0), data_hex=0b000000000000001800000000000000]\n", - "│ ├────c3891a7097de4163bb8fccf69e0392b3: [caption=(ElfDynamicEntry), attributes=(Data), global_offset=(0x2ee0-0x2ef0), parent_offset=(0xc0-0xd0), data_hex=15000000000000000000000000000000]\n", - "│ ├────a7e962655c3a483ba9420e51e5ad43ba: [caption=(ElfDynamicEntry), attributes=(Data), global_offset=(0x2ef0-0x2f00), parent_offset=(0xd0-0xe0), data_hex=03000000000000000040400000000000]\n", - "│ ├────c3e747cea5854bffb2425446983c7c2b: [caption=(ElfDynamicEntry), attributes=(Data), global_offset=(0x2f00-0x2f10), parent_offset=(0xe0-0xf0), data_hex=02000000000000001800000000000000]\n", - "│ ├────51fba726e59544789b8ec161af952aef: [caption=(ElfDynamicEntry), attributes=(Data), global_offset=(0x2f10-0x2f20), parent_offset=(0xf0-0x100), data_hex=14000000000000000700000000000000]\n", - "│ ├────31bfea7b52e64f44a99514aa286a72c1: [caption=(ElfDynamicEntry), attributes=(Data), global_offset=(0x2f20-0x2f30), parent_offset=(0x100-0x110), data_hex=17000000000000002004400000000000]\n", - "│ ├────5daca21e8eed4d57ae8b315fdce77f07: [caption=(ElfDynamicEntry), attributes=(Data), global_offset=(0x2f30-0x2f40), parent_offset=(0x110-0x120), data_hex=0700000000000000f003400000000000]\n", - "│ ├────c3f9a978dac34c629f88946c9f580e0c: [caption=(ElfDynamicEntry), attributes=(Data), global_offset=(0x2f40-0x2f50), parent_offset=(0x120-0x130), data_hex=08000000000000003000000000000000]\n", - "│ ├────d60c904bf7124361b14c54dcd7b71e9d: [caption=(ElfDynamicEntry), attributes=(Data), global_offset=(0x2f50-0x2f60), parent_offset=(0x130-0x140), data_hex=09000000000000001800000000000000]\n", - "│ ├────dc9464d5f93b4bb5998d728b51b64d1e: [caption=(ElfDynamicEntry), attributes=(Data), global_offset=(0x2f60-0x2f70), parent_offset=(0x140-0x150), data_hex=feffff6f00000000d003400000000000]\n", - "│ ├────23ad5d4b433447e3bcba200673dd6cdd: [caption=(ElfDynamicEntry), attributes=(Data), global_offset=(0x2f70-0x2f80), parent_offset=(0x150-0x160), data_hex=ffffff6f000000000100000000000000]\n", - "│ ├────d4d1f7feb3274478baec7d31c61fd719: [caption=(ElfDynamicEntry), attributes=(Data), global_offset=(0x2f80-0x2f90), parent_offset=(0x160-0x170), data_hex=f0ffff6f00000000c603400000000000]\n", - "│ ├────a0c1c7b9ec784620b773a2912189974b: [caption=(ElfDynamicEntry), attributes=(Data), global_offset=(0x2f90-0x2fa0), parent_offset=(0x170-0x180), data_hex=00000000000000000000000000000000]\n", - "│ ├────4323221e99b241adbc70767fbd2ebdc3: [caption=(ElfDynamicEntry), attributes=(Data), global_offset=(0x2fa0-0x2fb0), parent_offset=(0x180-0x190), data_hex=00000000000000000000000000000000]\n", - "│ ├────a24230492cf242aaa153c78cc553a561: [caption=(ElfDynamicEntry), attributes=(Data), global_offset=(0x2fb0-0x2fc0), parent_offset=(0x190-0x1a0), data_hex=00000000000000000000000000000000]\n", - "│ ├────f700dee25fbc448499f59f65d8d1d3c0: [caption=(ElfDynamicEntry), attributes=(Data), global_offset=(0x2fc0-0x2fd0), parent_offset=(0x1a0-0x1b0), data_hex=00000000000000000000000000000000]\n", - "│ ├────b8342275bba5488285f75700a6300fd3: [caption=(ElfDynamicEntry), attributes=(Data), global_offset=(0x2fd0-0x2fe0), parent_offset=(0x1b0-0x1c0), data_hex=00000000000000000000000000000000]\n", - "│ └────a0129024378649c792ab07f1f6e2dfa4: [caption=(ElfDynamicEntry), attributes=(Data), global_offset=(0x2fe0-0x2ff0), parent_offset=(0x1c0-0x1d0), data_hex=00000000000000000000000000000000]\n", - "├────20f1b6b8e51242208f8eb6de7b6a0369: [caption=(ElfSectionHeader), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[ElfSectionHeader]), global_offset=(0x3e20-0x3e60), parent_offset=(0x3e20-0x3e60), data_hex=e1000000010000000300000000000000f03f400000000000f02f0000000000001000000000000000000000000000000008000000000000000800000000000000]\n", - "├────3ac284dee3bf46b0b60822d6259867ca: [caption=(ElfSection), attributes=(Data, AttributesType[ElfSectionStructure]), global_offset=(0x2ff0-0x3000), parent_offset=(0x2ff0-0x3000), data_hex=00000000000000000000000000000000]\n", - "├────3deecb4c83954845a615b66733fa3bdb: [caption=(ElfSectionHeader), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[ElfSectionHeader]), global_offset=(0x3e60-0x3ea0), parent_offset=(0x3e60-0x3ea0), data_hex=e6000000010000000300000000000000004040000000000000300000000000002000000000000000000000000000000008000000000000000800000000000000]\n", - "├───┬7af61b3a63014461b864c1c9e0d9c4a3: [caption=(ElfSection), attributes=(Data, AttributesType[ElfSectionStructure]), global_offset=(0x3000-0x3020), parent_offset=(0x3000-0x3020), data_hex=203e400000000000000000000000000000000000000000003610400000000000]\n", - "│ └────89add08014f24faa8f2b69bfc87f16af: [caption=(string: ' >@'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x3000-0x3004), parent_offset=(0x0-0x4), data_hex=203e4000]\n", - "├────fdad13db5cd84ace818229cf9d3b88c5: [caption=(ElfSectionHeader), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[ElfSectionHeader]), global_offset=(0x3ea0-0x3ee0), parent_offset=(0x3ea0-0x3ee0), data_hex=ef000000010000000300000000000000204040000000000020300000000000001000000000000000000000000000000008000000000000000000000000000000]\n", - "├────ec6a44ecf3ed4926bd4872ef17abace2: [caption=(ElfSection), attributes=(Data, AttributesType[ElfSectionStructure]), global_offset=(0x3020-0x3030), parent_offset=(0x3020-0x3030), data_hex=00000000000000000000000000000000]\n", - "├────f6257bc654ec4a738d8ff6a60c516922: [caption=(ElfSectionHeader), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[ElfSectionHeader]), global_offset=(0x3ee0-0x3f20), parent_offset=(0x3ee0-0x3f20), data_hex=f5000000080000000300000000000000304040000000000030300000000000000800000000000000000000000000000001000000000000000000000000000000]\n", - "├────63c686482df44897a02205731c19347c: [caption=(ElfSection), attributes=(AttributesType[ElfSectionStructure])]\n", - "├────e391d59b7d3441caafe60036655fb650: [caption=(ElfSectionHeader), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[ElfSectionHeader]), global_offset=(0x3f20-0x3f60), parent_offset=(0x3f20-0x3f60), data_hex=fa000000010000003000000000000000000000000000000030300000000000002700000000000000000000000000000001000000000000000100000000000000]\n", - "├───┬ae47c11b4e6948f0aee6806ed2d8e14d: [caption=(ElfSection), attributes=(Data, AttributesType[ElfSectionStructure]), global_offset=(0x3030-0x3057), parent_offset=(0x3030-0x3057), data_hex=4743433a202844656269616e2031302e322e312d36292031302e322e3120323032313031313000]\n", - "│ └────4c860a33917e4179beb7046fd6b7373d: [caption=(string: 'GCC: (Debian 10.2.1-6) 10.2.1 20210110'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x3030-0x3057), parent_offset=(0x0-0x27), data_hex=4743433a202844656269616e2031302e322e312d36292031302e322e3120323032313031313000]\n", - "├────8cef7ecc21be4140bb2429dbe94c3b30: [caption=(ElfSectionHeader), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[ElfSectionHeader]), global_offset=(0x3f60-0x3fa0), parent_offset=(0x3f60-0x3fa0), data_hex=0100000002000000000000000000000000000000000000005830000000000000b8050000000000001b0000002b00000008000000000000001800000000000000]\n", - "├───┬09bd05d14c20490b8cfd6986f935e847: [caption=(ElfSymbolSection: .symtab), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[NamedProgramSection], AttributesType[MemoryRegion], AttributesType[Addressable]), global_offset=(0x3058-0x3610), parent_offset=(0x3058-0x3610), data_hash=f6bc0737]\n", - "│ ├────70ffe7ed42144806ab0e85fda9922050: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3058-0x3070), parent_offset=(0x0-0x18), data_hex=000000000000000000000000000000000000000000000000]\n", - "│ ├────5a4283deb3214380ad283d3b6d075690: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3070-0x3088), parent_offset=(0x18-0x30), data_hex=0000000003000100a8024000000000000000000000000000]\n", - "│ ├────3828457875064f44ab194f177c8eabef: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3088-0x30a0), parent_offset=(0x30-0x48), data_hex=0000000003000200c4024000000000000000000000000000]\n", - "│ ├────42f268db029647a18382a25cd07a7812: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x30a0-0x30b8), parent_offset=(0x48-0x60), data_hex=0000000003000300e8024000000000000000000000000000]\n", - "│ ├────ae0880ea05c749a5b4fcd0039703a693: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x30b8-0x30d0), parent_offset=(0x60-0x78), data_hex=000000000300040008034000000000000000000000000000]\n", - "│ ├────3ae56bdc06e1462d87e85ad3c3102094: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x30d0-0x30e8), parent_offset=(0x78-0x90), data_hex=000000000300050028034000000000000000000000000000]\n", - "│ ├────d06f891b3e3647339e05b5c53a5ff679: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x30e8-0x3100), parent_offset=(0x90-0xa8), data_hex=000000000300060088034000000000000000000000000000]\n", - "│ ├────0d9d9f6013514a5fb80bd9ffbdb60204: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3100-0x3118), parent_offset=(0xa8-0xc0), data_hex=0000000003000700c6034000000000000000000000000000]\n", - "│ ├────c5dedee3a6704afd919f244a0182ffc7: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3118-0x3130), parent_offset=(0xc0-0xd8), data_hex=0000000003000800d0034000000000000000000000000000]\n", - "│ ├────40c2038848d84741924f4917ae030a73: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3130-0x3148), parent_offset=(0xd8-0xf0), data_hex=0000000003000900f0034000000000000000000000000000]\n", - "│ ├────08f8be694b88475bb4f4ec2db5f2cb8e: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3148-0x3160), parent_offset=(0xf0-0x108), data_hex=0000000003000a0020044000000000000000000000000000]\n", - "│ ├────f43547d90c254ba3a9f5a7b0917b089f: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3160-0x3178), parent_offset=(0x108-0x120), data_hex=0000000003000b0000104000000000000000000000000000]\n", - "│ ├────d4546221abdc416f8f9e639f7894ce88: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3178-0x3190), parent_offset=(0x120-0x138), data_hex=0000000003000c0020104000000000000000000000000000]\n", - "│ ├────174b8c300ee640a097e7ed3f1ea76ee5: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3190-0x31a8), parent_offset=(0x138-0x150), data_hex=0000000003000d0040104000000000000000000000000000]\n", - "│ ├────954068f2e07042958ae86a177fe6f1fe: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x31a8-0x31c0), parent_offset=(0x150-0x168), data_hex=0000000003000e00a4114000000000000000000000000000]\n", - "│ ├────3c49e28946874f2cabe55c3307a2aca8: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x31c0-0x31d8), parent_offset=(0x168-0x180), data_hex=0000000003000f0000204000000000000000000000000000]\n", - "│ ├────6ed286b0c79f4f639ab444ad80a36ec2: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x31d8-0x31f0), parent_offset=(0x180-0x198), data_hex=000000000300100014204000000000000000000000000000]\n", - "│ ├────1c54b888e13c44f58741e227ef391e5a: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x31f0-0x3208), parent_offset=(0x198-0x1b0), data_hex=000000000300110050204000000000000000000000000000]\n", - "│ ├────0db848b9346e496d853efd15dee04dec: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3208-0x3220), parent_offset=(0x1b0-0x1c8), data_hex=0000000003001200103e4000000000000000000000000000]\n", - "│ ├────54fb7008647749828ac7c36b45d83f6e: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3220-0x3238), parent_offset=(0x1c8-0x1e0), data_hex=0000000003001300183e4000000000000000000000000000]\n", - "│ ├────d9b3fddddbca43acb96c24bc53ff3070: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3238-0x3250), parent_offset=(0x1e0-0x1f8), data_hex=0000000003001400203e4000000000000000000000000000]\n", - "│ ├────4627991aaa6d464486b4e71670e08fad: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3250-0x3268), parent_offset=(0x1f8-0x210), data_hex=0000000003001500f03f4000000000000000000000000000]\n", - "│ ├────8b1f77cf159d4e87b97bf1a3b772c9a4: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3268-0x3280), parent_offset=(0x210-0x228), data_hex=000000000300160000404000000000000000000000000000]\n", - "│ ├────7871c261ff304feda07bd5b181283e7d: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3280-0x3298), parent_offset=(0x228-0x240), data_hex=000000000300170020404000000000000000000000000000]\n", - "│ ├────b1fc756051154947a7c31ec525d03a48: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3298-0x32b0), parent_offset=(0x240-0x258), data_hex=000000000300180030404000000000000000000000000000]\n", - "│ ├────174971ebaf02408fac50a388bda1b051: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x32b0-0x32c8), parent_offset=(0x258-0x270), data_hex=000000000300190000000000000000000000000000000000]\n", - "│ ├────0ae729f046984e01bc49672eb95ada6c: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x32c8-0x32e0), parent_offset=(0x270-0x288), data_hex=010000000400f1ff00000000000000000000000000000000]\n", - "│ ├────11c5de72ec394e8f8cbf1df1617a9341: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x32e0-0x32f8), parent_offset=(0x288-0x2a0), data_hex=0c00000002000d0080104000000000000000000000000000]\n", - "│ ├────51bd7abb93c44b39b16d15637040dbbd: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x32f8-0x3310), parent_offset=(0x2a0-0x2b8), data_hex=0e00000002000d00b0104000000000000000000000000000]\n", - "│ ├────cbbacf603c2f42cfaeab612c538c0128: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3310-0x3328), parent_offset=(0x2b8-0x2d0), data_hex=2100000002000d00f0104000000000000000000000000000]\n", - "│ ├────17f590a81278409c9b1ea04c7b3d7773: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3328-0x3340), parent_offset=(0x2d0-0x2e8), data_hex=370000000100180030404000000000000100000000000000]\n", - "│ ├────3be81857142a4f65b032d4dd42548475: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3340-0x3358), parent_offset=(0x2e8-0x300), data_hex=4300000001001300183e4000000000000000000000000000]\n", - "│ ├────08ab00f4dfb6413cb6279d45f614a8ee: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3358-0x3370), parent_offset=(0x300-0x318), data_hex=6a00000002000d0020114000000000000000000000000000]\n", - "│ ├────d133ba23eca54f709c894a9b7773b2e9: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3370-0x3388), parent_offset=(0x318-0x330), data_hex=7600000001001200103e4000000000000000000000000000]\n", - "│ ├────0bd13550566c48cab24e9b63572d9770: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3388-0x33a0), parent_offset=(0x330-0x348), data_hex=950000000400f1ff00000000000000000000000000000000]\n", - "│ ├────911526d9da3849de8a08c44ee8d41b6f: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x33a0-0x33b8), parent_offset=(0x348-0x360), data_hex=010000000400f1ff00000000000000000000000000000000]\n", - "│ ├────d4da18d132724372b28af2b0e624042e: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x33b8-0x33d0), parent_offset=(0x360-0x378), data_hex=a3000000010011004c214000000000000000000000000000]\n", - "│ ├────f8e27e0325894c96b9416cec965de823: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x33d0-0x33e8), parent_offset=(0x378-0x390), data_hex=000000000400f1ff00000000000000000000000000000000]\n", - "│ ├────10680b7e4deb4cd9aac028ba7a3d3991: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x33e8-0x3400), parent_offset=(0x390-0x3a8), data_hex=b100000000001200183e4000000000000000000000000000]\n", - "│ ├────b538b6d569984838ab427e7e8b10c16e: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3400-0x3418), parent_offset=(0x3a8-0x3c0), data_hex=c200000001001400203e4000000000000000000000000000]\n", - "│ ├────cbc4dd9ab4874ab5b6591baf8453532d: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3418-0x3430), parent_offset=(0x3c0-0x3d8), data_hex=cb00000000001200103e4000000000000000000000000000]\n", - "│ ├────b612b611693e48f48b322517e8fe69d6: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3430-0x3448), parent_offset=(0x3d8-0x3f0), data_hex=de0000000000100014204000000000000000000000000000]\n", - "│ ├────ea4f85d17b5b405cadf3f2103babe060: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3448-0x3460), parent_offset=(0x3f0-0x408), data_hex=f10000000100160000404000000000000000000000000000]\n", - "│ ├────491c4eccf2484e8ea85c9af3a3449d56: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3460-0x3478), parent_offset=(0x408-0x420), data_hex=0701000012000d00a0114000000000000100000000000000]\n", - "│ ├────bcbceb34b4a14fcc833625cc1342ac4d: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3478-0x3490), parent_offset=(0x420-0x438), data_hex=4f0100002000170020404000000000000000000000000000]\n", - "│ ├────74e2d636d55149ad92899fadf334ed59: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3490-0x34a8), parent_offset=(0x438-0x450), data_hex=170100001200000000000000000000000000000000000000]\n", - "│ ├────db33935445e54b5ba13a27778f04583c: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x34a8-0x34c0), parent_offset=(0x450-0x468), data_hex=280100001000170030404000000000000000000000000000]\n", - "│ ├────1b740623121649d39448a0fa30352282: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x34c0-0x34d8), parent_offset=(0x468-0x480), data_hex=1101000012020e00a4114000000000000000000000000000]\n", - "│ ├────2ec1b84c01e64bf5a78cd63daaff8e30: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x34d8-0x34f0), parent_offset=(0x480-0x498), data_hex=2f0100001200000000000000000000000000000000000000]\n", - "│ ├────c01be39339ea47cc87d38e2d3ec79e64: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x34f0-0x3508), parent_offset=(0x498-0x4b0), data_hex=4d0100001000170020404000000000000000000000000000]\n", - "│ ├────13b66c18afe44db99e075137356d6c9c: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3508-0x3520), parent_offset=(0x4b0-0x4c8), data_hex=5a0100002000000000000000000000000000000000000000]\n", - "│ ├────be378c6262a94b19a9eacc11b4e055e1: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3520-0x3538), parent_offset=(0x4c8-0x4e0), data_hex=690100001102170028404000000000000000000000000000]\n", - "│ ├────3c762ac4c1f74354b210bd7da6e5099d: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3538-0x3550), parent_offset=(0x4e0-0x4f8), data_hex=7601000011000f0000204000000000000400000000000000]\n", - "│ ├────60137a93dd6c4f9cabc9040437d072d3: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3550-0x3568), parent_offset=(0x4f8-0x510), data_hex=8501000012000d0040114000000000005d00000000000000]\n", - "│ ├────3df613989f744938b966a48bafad2c6c: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3568-0x3580), parent_offset=(0x510-0x528), data_hex=bd0000001000180038404000000000000000000000000000]\n", - "│ ├────45a5d5557b5541fa864d97e80b9380b4: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3580-0x3598), parent_offset=(0x528-0x540), data_hex=9501000012020d0070104000000000000100000000000000]\n", - "│ ├────7303a996849f4c51bdac179cdf7b9071: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3598-0x35b0), parent_offset=(0x540-0x558), data_hex=5301000012000d0040104000000000002b00000000000000]\n", - "│ ├────1171a93500ef4f96bc82d8dcf3c6cb9a: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x35b0-0x35c8), parent_offset=(0x558-0x570), data_hex=ad0100001000180030404000000000000000000000000000]\n", - "│ ├────fb5b870eb480416dbef6f8f000f84c63: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x35c8-0x35e0), parent_offset=(0x570-0x588), data_hex=b901000012000d0022114000000000001700000000000000]\n", - "│ ├────6af60fe9811f4aa9b3125c433e623c8a: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x35e0-0x35f8), parent_offset=(0x588-0x5a0), data_hex=be0100001102170030404000000000000000000000000000]\n", - "│ └────48a8c170fab44043ad71657da1adb96c: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x35f8-0x3610), parent_offset=(0x5a0-0x5b8), data_hex=8f01000012020b0000104000000000000000000000000000]\n", - "├────e11db891a522445eb9a64df6568b65cd: [caption=(ElfSectionHeader), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[ElfSectionHeader]), global_offset=(0x3fa0-0x3fe0), parent_offset=(0x3fa0-0x3fe0), data_hex=0900000003000000000000000000000000000000000000001036000000000000ca01000000000000000000000000000001000000000000000000000000000000]\n", - "├───┬a1b055329b054cbba19cfc3a39117f58: [caption=(ElfSection, ElfStringSection), attributes=(Data, AttributesType[ElfSectionStructure]), global_offset=(0x3610-0x37da), parent_offset=(0x3610-0x37da), data_hash=800e56e9]\n", - "│ ├────4c74c967f29d46759cb91573500f3399: [caption=(string: 'crtstuff.c'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x3611-0x361c), parent_offset=(0x1-0xc), data_hex=63727473747566662e6300]\n", - "│ ├────17adfad0ba3348208e893835c41dcb94: [caption=(string: 'deregister_tm_clones'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x361c-0x3631), parent_offset=(0xc-0x21), data_hex=646572656769737465725f746d5f636c6f6e657300]\n", - "│ ├────d27714e318d7431e88c539ecd37c2988: [caption=(string: '__do_global_dtors_aux'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x3631-0x3647), parent_offset=(0x21-0x37), data_hex=5f5f646f5f676c6f62616c5f64746f72735f61757800]\n", - "│ ├────e9eaf9d9fb07460894a4086ad4aff81b: [caption=(string: 'completed.0'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x3647-0x3653), parent_offset=(0x37-0x43), data_hex=636f6d706c657465642e3000]\n", - "│ ├────df052a031ef6463db6fec9c4f793ec53: [caption=(string: '__do_global_dtors_aux_fini_array_entry'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x3653-0x367a), parent_offset=(0x43-0x6a), data_hex=5f5f646f5f676c6f62616c5f64746f72735f6175785f66696e695f61727261795f656e74727900]\n", - "│ ├────509a2909d9844cbd8a3b42f73465a5a0: [caption=(string: 'frame_dummy'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x367a-0x3686), parent_offset=(0x6a-0x76), data_hex=6672616d655f64756d6d7900]\n", - "│ ├────2ae49b03fed04937b63f8dcdcad955f6: [caption=(string: '__frame_dummy_init_array_entry'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x3686-0x36a5), parent_offset=(0x76-0x95), data_hex=5f5f6672616d655f64756d6d795f696e69745f61727261795f656e74727900]\n", - "│ ├────b092269e0a834e9898efb6c32d61fe61: [caption=(string: 'hello_world.c'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x36a5-0x36b3), parent_offset=(0x95-0xa3), data_hex=68656c6c6f5f776f726c642e6300]\n", - "│ ├────d05cc2f307434db8b44e99ccc7ae101c: [caption=(string: '__FRAME_END__'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x36b3-0x36c1), parent_offset=(0xa3-0xb1), data_hex=5f5f4652414d455f454e445f5f00]\n", - "│ ├────aee51853031e407aaa722190245f90ec: [caption=(string: '__init_array_end'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x36c1-0x36d2), parent_offset=(0xb1-0xc2), data_hex=5f5f696e69745f61727261795f656e6400]\n", - "│ ├────726c0c756daf4751b2710e7971c10832: [caption=(string: '_DYNAMIC'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x36d2-0x36db), parent_offset=(0xc2-0xcb), data_hex=5f44594e414d494300]\n", - "│ ├────1c7e116bb973459e8dd1cd1a2845bdf3: [caption=(string: '__init_array_start'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x36db-0x36ee), parent_offset=(0xcb-0xde), data_hex=5f5f696e69745f61727261795f737461727400]\n", - "│ ├────1acb2d8e5ae0427eaaadb3bacafcc254: [caption=(string: '__GNU_EH_FRAME_HDR'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x36ee-0x3701), parent_offset=(0xde-0xf1), data_hex=5f5f474e555f45485f4652414d455f48445200]\n", - "│ ├────694a89c8c9af466ba882f32acf8612b6: [caption=(string: '_GLOBAL_OFFSET_TABLE_'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x3701-0x3717), parent_offset=(0xf1-0x107), data_hex=5f474c4f42414c5f4f46465345545f5441424c455f00]\n", - "│ ├────1b3380e97880492682a7c6d2cf5b6c1c: [caption=(string: '__libc_csu_fini'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x3717-0x3727), parent_offset=(0x107-0x117), data_hex=5f5f6c6962635f6373755f66696e6900]\n", - "│ ├────86112bfa46924c65afe2a49b34d92b7c: [caption=(string: 'puts@GLIBC_2.2.5'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x3727-0x3738), parent_offset=(0x117-0x128), data_hex=7075747340474c4942435f322e322e3500]\n", - "│ ├────d2d456a2d6ce4054b02d2653ab142bab: [caption=(string: '_edata'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x3738-0x373f), parent_offset=(0x128-0x12f), data_hex=5f656461746100]\n", - "│ ├────16060343c23b4d33bef2d10019e99467: [caption=(string: '__libc_start_main@GLIBC_2.2.5'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x373f-0x375d), parent_offset=(0x12f-0x14d), data_hex=5f5f6c6962635f73746172745f6d61696e40474c4942435f322e322e3500]\n", - "│ ├────f8373bd606f2404db9b24ed6fc311aeb: [caption=(string: '__data_start'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x375d-0x376a), parent_offset=(0x14d-0x15a), data_hex=5f5f646174615f737461727400]\n", - "│ ├────0f1967784664493c8394f6e5bb5bead0: [caption=(string: '__gmon_start__'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x376a-0x3779), parent_offset=(0x15a-0x169), data_hex=5f5f676d6f6e5f73746172745f5f00]\n", - "│ ├────bc5a744b700b41aa9622fb36d0583ba1: [caption=(string: '__dso_handle'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x3779-0x3786), parent_offset=(0x169-0x176), data_hex=5f5f64736f5f68616e646c6500]\n", - "│ ├────494bfb7d3f264761a2f2e5772f0b0a3d: [caption=(string: '_IO_stdin_used'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x3786-0x3795), parent_offset=(0x176-0x185), data_hex=5f494f5f737464696e5f7573656400]\n", - "│ ├────be1c947b8b444397883e99ebf10c143a: [caption=(string: '__libc_csu_init'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x3795-0x37a5), parent_offset=(0x185-0x195), data_hex=5f5f6c6962635f6373755f696e697400]\n", - "│ ├────db81f67baba946cdb18bec31380a86f7: [caption=(string: '_dl_relocate_static_pie'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x37a5-0x37bd), parent_offset=(0x195-0x1ad), data_hex=5f646c5f72656c6f636174655f7374617469635f70696500]\n", - "│ ├────30fdc17d91674032b2d1edff3db6a950: [caption=(string: '__bss_start'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x37bd-0x37c9), parent_offset=(0x1ad-0x1b9), data_hex=5f5f6273735f737461727400]\n", - "│ ├────c87b5c97c8024f40924912429ed48774: [caption=(string: 'main'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x37c9-0x37ce), parent_offset=(0x1b9-0x1be), data_hex=6d61696e00]\n", - "│ └────20867fffcfbe442abce21251040bec1a: [caption=(string: '__TMC_END__'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x37ce-0x37da), parent_offset=(0x1be-0x1ca), data_hex=5f5f544d435f454e445f5f00]\n", - "├────3364f3c6fcbd489f8ea7a61c522ab86e: [caption=(ElfSectionHeader), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[ElfSectionHeader]), global_offset=(0x3fe0-0x4020), parent_offset=(0x3fe0-0x4020), data_hex=110000000300000000000000000000000000000000000000da370000000000000301000000000000000000000000000001000000000000000000000000000000]\n", - "├───┬df9ebfb75d594b158e2faa33d69765fc: [caption=(ElfSectionNameStringSection, ElfSection), attributes=(Data, AttributesType[ElfSectionStructure]), global_offset=(0x37da-0x38dd), parent_offset=(0x37da-0x38dd), data_hash=6db41dea]\n", - "│ ├────85f937f2862e4923a28bd29761bb5093: [caption=(string: '.symtab'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x37db-0x37e3), parent_offset=(0x1-0x9), data_hex=2e73796d74616200]\n", - "│ ├────061acc50ee7b4f4aa1bf383acf2e93aa: [caption=(string: '.strtab'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x37e3-0x37eb), parent_offset=(0x9-0x11), data_hex=2e73747274616200]\n", - "│ ├────fe45a1f298b2493085d0b345b48381d7: [caption=(string: '.shstrtab'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x37eb-0x37f5), parent_offset=(0x11-0x1b), data_hex=2e736873747274616200]\n", - "│ ├────47aaa70bc63643058f35e92ad9e44c83: [caption=(string: '.interp'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x37f5-0x37fd), parent_offset=(0x1b-0x23), data_hex=2e696e7465727000]\n", - "│ ├────8bc5263a0dd044ec8c7d40456004cae5: [caption=(string: '.note.gnu.build-id'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x37fd-0x3810), parent_offset=(0x23-0x36), data_hex=2e6e6f74652e676e752e6275696c642d696400]\n", - "│ ├────5e786333e8a84a26ab3d118ff6a843ca: [caption=(string: '.note.ABI-tag'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x3810-0x381e), parent_offset=(0x36-0x44), data_hex=2e6e6f74652e4142492d74616700]\n", - "│ ├────993ab2dbaf08405bbfab821d79a9d9d8: [caption=(string: '.gnu.hash'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x381e-0x3828), parent_offset=(0x44-0x4e), data_hex=2e676e752e6861736800]\n", - "│ ├────3f8395bb1f984dfc8c46b9939461bcee: [caption=(string: '.dynsym'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x3828-0x3830), parent_offset=(0x4e-0x56), data_hex=2e64796e73796d00]\n", - "│ ├────738c235e76ca4637aa6a9cc63baeca6d: [caption=(string: '.dynstr'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x3830-0x3838), parent_offset=(0x56-0x5e), data_hex=2e64796e73747200]\n", - "│ ├────d1baed753e694912add6296f15bb40c7: [caption=(string: '.gnu.version'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x3838-0x3845), parent_offset=(0x5e-0x6b), data_hex=2e676e752e76657273696f6e00]\n", - "│ ├────9a8ff2e58b154cbe93cd45dc2a44f257: [caption=(string: '.gnu.version_r'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x3845-0x3854), parent_offset=(0x6b-0x7a), data_hex=2e676e752e76657273696f6e5f7200]\n", - "│ ├────b417e4404146415388689164d4ea3136: [caption=(string: '.rela.dyn'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x3854-0x385e), parent_offset=(0x7a-0x84), data_hex=2e72656c612e64796e00]\n", - "│ ├────2818fa565bec4655810e0f3ccab17e05: [caption=(string: '.rela.plt'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x385e-0x3868), parent_offset=(0x84-0x8e), data_hex=2e72656c612e706c7400]\n", - "│ ├────ccbd553487fc4557895ad8344ff7fa76: [caption=(string: '.init'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x3868-0x386e), parent_offset=(0x8e-0x94), data_hex=2e696e697400]\n", - "│ ├────eb60704920754756830b923f6b262b76: [caption=(string: '.text'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x386e-0x3874), parent_offset=(0x94-0x9a), data_hex=2e7465787400]\n", - "│ ├────7ca3ae66f1224b928402b7af207167be: [caption=(string: '.fini'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x3874-0x387a), parent_offset=(0x9a-0xa0), data_hex=2e66696e6900]\n", - "│ ├────be2413a80f0640b8862297e4d7a1a05a: [caption=(string: '.rodata'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x387a-0x3882), parent_offset=(0xa0-0xa8), data_hex=2e726f6461746100]\n", - "│ ├────8fa957066b9847f8b9d61d911020a531: [caption=(string: '.eh_frame_hdr'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x3882-0x3890), parent_offset=(0xa8-0xb6), data_hex=2e65685f6672616d655f68647200]\n", - "│ ├────a49f789c7829401686f261c4c66eccd4: [caption=(string: '.eh_frame'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x3890-0x389a), parent_offset=(0xb6-0xc0), data_hex=2e65685f6672616d6500]\n", - "│ ├────8e2d42821ca8460a911415c687d0b157: [caption=(string: '.init_array'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x389a-0x38a6), parent_offset=(0xc0-0xcc), data_hex=2e696e69745f617272617900]\n", - "│ ├────f1941f23561f4ba8a502cf09909d7044: [caption=(string: '.fini_array'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x38a6-0x38b2), parent_offset=(0xcc-0xd8), data_hex=2e66696e695f617272617900]\n", - "│ ├────56321f4318bc4ca8939940c50dcce90c: [caption=(string: '.dynamic'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x38b2-0x38bb), parent_offset=(0xd8-0xe1), data_hex=2e64796e616d696300]\n", - "│ ├────133b4b11d00a496fb7b80b42fe1906ba: [caption=(string: '.got'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x38bb-0x38c0), parent_offset=(0xe1-0xe6), data_hex=2e676f7400]\n", - "│ ├────2016eef6125049b680ead829ec50d5e8: [caption=(string: '.got.plt'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x38c0-0x38c9), parent_offset=(0xe6-0xef), data_hex=2e676f742e706c7400]\n", - "│ ├────681905520d864482b4ceca54dd531f29: [caption=(string: '.data'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x38c9-0x38cf), parent_offset=(0xef-0xf5), data_hex=2e6461746100]\n", - "│ ├────8198eb48946143a7a37489583cc300af: [caption=(string: '.bss'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x38cf-0x38d4), parent_offset=(0xf5-0xfa), data_hex=2e62737300]\n", - "│ └────76835b7e13054571b92a16bb2e81490d: [caption=(string: '.comment'), attributes=(Data, AttributesType[AsciiString]), global_offset=(0x38d4-0x38dd), parent_offset=(0xfa-0x103), data_hex=2e636f6d6d656e7400]\n", - "├────2d63dd76ca4e471a903a66582388498b: [caption=(ElfProgramHeader: PHDR, R), attributes=(Data, AttributesType[ElfSegmentStructure], AttributesType[ElfProgramHeader]), global_offset=(0x40-0x78), parent_offset=(0x40-0x78), data_hex=0600000004000000400000000000000040004000000000004000400000000000680200000000000068020000000000000800000000000000]\n", - "├────e34fedd1529a44a5988cabedafb94b76: [caption=(ElfProgramHeader: INTERP, R), attributes=(Data, AttributesType[ElfSegmentStructure], AttributesType[ElfProgramHeader]), global_offset=(0x78-0xb0), parent_offset=(0x78-0xb0), data_hex=0300000004000000a802000000000000a802400000000000a8024000000000001c000000000000001c000000000000000100000000000000]\n", - "├────9bfeee745bce409ab813a462aba4084c: [caption=(ElfProgramHeader: LOAD, R), attributes=(Data, AttributesType[ElfSegmentStructure], AttributesType[ElfProgramHeader]), global_offset=(0xb0-0xe8), parent_offset=(0xb0-0xe8), data_hex=0100000004000000000000000000000000004000000000000000400000000000380400000000000038040000000000000010000000000000]\n", - "├────94357b43e492426aaae0f9bccd05c5ae: [caption=(ElfProgramHeader: LOAD, RX), attributes=(Data, AttributesType[ElfSegmentStructure], AttributesType[ElfProgramHeader]), global_offset=(0xe8-0x120), parent_offset=(0xe8-0x120), data_hex=0100000005000000001000000000000000104000000000000010400000000000ad01000000000000ad010000000000000010000000000000]\n", - "├────f1d1d22ef0e645bb9e77f1c5797baa3f: [caption=(ElfProgramHeader: LOAD, R), attributes=(Data, AttributesType[ElfSegmentStructure], AttributesType[ElfProgramHeader]), global_offset=(0x120-0x158), parent_offset=(0x120-0x158), data_hex=0100000004000000002000000000000000204000000000000020400000000000500100000000000050010000000000000010000000000000]\n", - "├────ac188e20f9ac496f9b871717f55b7e17: [caption=(ElfProgramHeader: LOAD, RW), attributes=(Data, AttributesType[ElfSegmentStructure], AttributesType[ElfProgramHeader]), global_offset=(0x158-0x190), parent_offset=(0x158-0x190), data_hex=0100000006000000102e000000000000103e400000000000103e400000000000200200000000000028020000000000000010000000000000]\n", - "├────a480a2bc7a904b78a683854aabffcd22: [caption=(ElfProgramHeader: DYNAMIC, RW), attributes=(Data, AttributesType[ElfSegmentStructure], AttributesType[ElfProgramHeader]), global_offset=(0x190-0x1c8), parent_offset=(0x190-0x1c8), data_hex=0200000006000000202e000000000000203e400000000000203e400000000000d001000000000000d0010000000000000800000000000000]\n", - "├────d563d1373b3d45b98699e1d5ff669f33: [caption=(ElfProgramHeader: NOTE, R), attributes=(Data, AttributesType[ElfSegmentStructure], AttributesType[ElfProgramHeader]), global_offset=(0x1c8-0x200), parent_offset=(0x1c8-0x200), data_hex=0400000004000000c402000000000000c402400000000000c402400000000000440000000000000044000000000000000400000000000000]\n", - "├────f62bc0a7b2344b84bc06c2d848898e35: [caption=(ElfProgramHeader: GNU_EH_FRAME, R), attributes=(Data, AttributesType[ElfSegmentStructure], AttributesType[ElfProgramHeader]), global_offset=(0x200-0x238), parent_offset=(0x200-0x238), data_hex=50e57464040000001420000000000000142040000000000014204000000000003c000000000000003c000000000000000400000000000000]\n", - "├────dcfb5573e6544725a15bb91d9204f2d3: [caption=(ElfProgramHeader: GNU_STACK, RW), attributes=(Data, AttributesType[ElfSegmentStructure], AttributesType[ElfProgramHeader]), global_offset=(0x238-0x270), parent_offset=(0x238-0x270), data_hex=51e5746406000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000]\n", - "└────df5c4193c1e64f1ea195f1b9896607a1: [caption=(ElfProgramHeader: GNU_RELRO, R), attributes=(Data, AttributesType[ElfSegmentStructure], AttributesType[ElfProgramHeader]), global_offset=(0x270-0x2a8), parent_offset=(0x270-0x2a8), data_hex=52e5746404000000102e000000000000103e400000000000103e400000000000f001000000000000f0010000000000000100000000000000]\n", + "┌7ec3ae1b09aa4a7dbc0fd3125646bbdb: [caption=(File: hello_world, Elf), attributes=(AttributesType[FilesystemEntry], Magic), global_offset=(0x0-0x4020), parent_offset=(0x0-0x0), data_hash=f5cd0893]\n", + "├────1555fee0a9054dbbaacdf8b2543e937e: [caption=(ElfBasicHeader), attributes=(Data, AttributesType[ElfBasicHeader]), global_offset=(0x0-0x10), parent_offset=(0x0-0x10), data_hex=7f454c46020101000000000000000000]\n", + "├────7920a68209a34f76bfa5a1d1e0b58706: [caption=(ElfHeader), attributes=(Data, AttributesType[ElfHeader]), global_offset=(0x10-0x40), parent_offset=(0x10-0x40), data_hex=02003e000100000040104000000000004000000000000000e03800000000000000000000400038000b0040001d001c00]\n", + "├────889c9ce9a69a4b118fdc82d87b0e051e: [caption=(ElfSectionHeader), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[ElfSectionHeader]), global_offset=(0x38e0-0x3920), parent_offset=(0x38e0-0x3920), data_hex=00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000]\n", + "├────227806fb68884cc29f562e583e3844c2: [caption=(ElfSection), attributes=(AttributesType[ElfSectionStructure])]\n", + "├────4aab9d471bbe4ece8023d34d1b3349a6: [caption=(ElfSectionHeader), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[ElfSectionHeader]), global_offset=(0x3920-0x3960), parent_offset=(0x3920-0x3960), data_hex=1b000000010000000200000000000000a802400000000000a8020000000000001c00000000000000000000000000000001000000000000000000000000000000]\n", + "├────5525a41d8d96415fa5aef778f6b7d7fc: [caption=(ElfSection), attributes=(Data, AttributesType[ElfSectionStructure]), global_offset=(0x2a8-0x2c4), parent_offset=(0x2a8-0x2c4), data_hex=2f6c696236342f6c642d6c696e75782d7838362d36342e736f2e3200]\n", + "├────764757192d374f909f4f9bb5e9d43c71: [caption=(ElfSectionHeader), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[ElfSectionHeader]), global_offset=(0x3960-0x39a0), parent_offset=(0x3960-0x39a0), data_hex=23000000070000000200000000000000c402400000000000c4020000000000002400000000000000000000000000000004000000000000000000000000000000]\n", + "├────77cff397e5804c3d94c00093c030f7c4: [caption=(ElfSection), attributes=(Data, AttributesType[ElfSectionStructure]), global_offset=(0x2c4-0x2e8), parent_offset=(0x2c4-0x2e8), data_hex=040000001400000003000000474e550017fb4e8bc7504a89fa3603690cb745adfd747237]\n", + "├────349c4e6f37e841cda4f83c0c68d18e6c: [caption=(ElfSectionHeader), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[ElfSectionHeader]), global_offset=(0x39a0-0x39e0), parent_offset=(0x39a0-0x39e0), data_hex=36000000070000000200000000000000e802400000000000e8020000000000002000000000000000000000000000000004000000000000000000000000000000]\n", + "├────93a034e8d1b9457d930e889a4aad1b55: [caption=(ElfSection), attributes=(Data, AttributesType[ElfSectionStructure]), global_offset=(0x2e8-0x308), parent_offset=(0x2e8-0x308), data_hex=040000001000000001000000474e550000000000030000000200000000000000]\n", + "├────91b63e364b2c4926af8519f09fff05f4: [caption=(ElfSectionHeader), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[ElfSectionHeader]), global_offset=(0x39e0-0x3a20), parent_offset=(0x39e0-0x3a20), data_hex=44000000f6ffff6f0200000000000000080340000000000008030000000000001c00000000000000050000000000000008000000000000000000000000000000]\n", + "├────b9efefb1a9b74ca5afe476c5d30ba2bb: [caption=(ElfSection), attributes=(Data, AttributesType[ElfSectionStructure]), global_offset=(0x308-0x324), parent_offset=(0x308-0x324), data_hex=01000000010000000100000000000000000000000000000000000000]\n", + "├────989b3273a42741328cf8c6f86c0a7296: [caption=(ElfSectionHeader), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[ElfSectionHeader]), global_offset=(0x3a20-0x3a60), parent_offset=(0x3a20-0x3a60), data_hex=4e0000000b0000000200000000000000280340000000000028030000000000006000000000000000060000000100000008000000000000001800000000000000]\n", + "├───┬bc46ab37c0764cdf8bd8dbfde40537c1: [caption=(ElfDynSymbolSection: .dynsym), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[Addressable], AttributesType[MemoryRegion], AttributesType[NamedProgramSection]), global_offset=(0x328-0x388), parent_offset=(0x328-0x388), data_hex=0000000000000000000000000000000000000000000000000100000012000000000000000000000000000000000000000600000012000000000000000000000000000000000000002e0000002000000000000000000000000000000000000000]\n", + "│ ├────008aca663fac46c29b5c462476871b5e: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x328-0x340), parent_offset=(0x0-0x18), data_hex=000000000000000000000000000000000000000000000000]\n", + "│ ├────50d89a7f07b8402c870d4fe10d51e8c4: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x340-0x358), parent_offset=(0x18-0x30), data_hex=010000001200000000000000000000000000000000000000]\n", + "│ ├────7eec0db4d92e423abfb2de4647316f25: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x358-0x370), parent_offset=(0x30-0x48), data_hex=060000001200000000000000000000000000000000000000]\n", + "│ └────d51544794fd94d1f8075a6836f73047d: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x370-0x388), parent_offset=(0x48-0x60), data_hex=2e0000002000000000000000000000000000000000000000]\n", + "├────b3e52741dd2347cfa95607048884ce85: [caption=(ElfSectionHeader), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[ElfSectionHeader]), global_offset=(0x3a60-0x3aa0), parent_offset=(0x3a60-0x3aa0), data_hex=56000000030000000200000000000000880340000000000088030000000000003d00000000000000000000000000000001000000000000000000000000000000]\n", + "├────fff8b3acf48d410bbdc03120092da112: [caption=(ElfSection, ElfStringSection), attributes=(Data, AttributesType[ElfSectionStructure]), global_offset=(0x388-0x3c5), parent_offset=(0x388-0x3c5), data_hex=0070757473005f5f6c6962635f73746172745f6d61696e006c6962632e736f2e3600474c4942435f322e322e35005f5f676d6f6e5f73746172745f5f00]\n", + "├────5656e4d3e4af45afb271e2eb01bf7862: [caption=(ElfSectionHeader), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[ElfSectionHeader]), global_offset=(0x3aa0-0x3ae0), parent_offset=(0x3aa0-0x3ae0), data_hex=5e000000ffffff6f0200000000000000c603400000000000c6030000000000000800000000000000050000000000000002000000000000000200000000000000]\n", + "├────893b708882404d6a99f86825180d8e2a: [caption=(ElfSection), attributes=(Data, AttributesType[ElfSectionStructure]), global_offset=(0x3c6-0x3ce), parent_offset=(0x3c6-0x3ce), data_hex=0000020002000000]\n", + "├────784dbbc2c0c6464588db9f537954c000: [caption=(ElfSectionHeader), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[ElfSectionHeader]), global_offset=(0x3ae0-0x3b20), parent_offset=(0x3ae0-0x3b20), data_hex=6b000000feffff6f0200000000000000d003400000000000d0030000000000002000000000000000060000000100000008000000000000000000000000000000]\n", + "├────4c401d7d42394d8bb1f68b680768f241: [caption=(ElfSection), attributes=(Data, AttributesType[ElfSectionStructure]), global_offset=(0x3d0-0x3f0), parent_offset=(0x3d0-0x3f0), data_hex=01000100180000001000000000000000751a6909000002002200000000000000]\n", + "├────ae7c270dba3a4a9597b3ae8d84b7f424: [caption=(ElfSectionHeader), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[ElfSectionHeader]), global_offset=(0x3b20-0x3b60), parent_offset=(0x3b20-0x3b60), data_hex=7a000000040000000200000000000000f003400000000000f0030000000000003000000000000000050000000000000008000000000000001800000000000000]\n", + "├───┬6b64fccb4aa74bd99c5c573666e67059: [caption=(ElfRelaSection: .rela.dyn), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[Addressable], AttributesType[MemoryRegion], AttributesType[NamedProgramSection]), global_offset=(0x3f0-0x420), parent_offset=(0x3f0-0x420), data_hex=f03f40000000000006000000020000000000000000000000f83f40000000000006000000030000000000000000000000]\n", + "│ ├────7a55cc8e3f054d8aa597d4de4a502922: [caption=(ElfRelaEntry), attributes=(Data), global_offset=(0x3f0-0x408), parent_offset=(0x0-0x18), data_hex=f03f40000000000006000000020000000000000000000000]\n", + "│ └────d6a8cb8a7d084a088ebe9b6c6c5f260e: [caption=(ElfRelaEntry), attributes=(Data), global_offset=(0x408-0x420), parent_offset=(0x18-0x30), data_hex=f83f40000000000006000000030000000000000000000000]\n", + "├────89e54a843ab44f1ca3b96cebb7a48cb4: [caption=(ElfSectionHeader), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[ElfSectionHeader]), global_offset=(0x3b60-0x3ba0), parent_offset=(0x3b60-0x3ba0), data_hex=84000000040000004200000000000000200440000000000020040000000000001800000000000000050000001600000008000000000000001800000000000000]\n", + "├───┬197fade116be4971aa2d3ccf9fda5e9f: [caption=(ElfRelaSection: .rela.plt), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[Addressable], AttributesType[MemoryRegion], AttributesType[NamedProgramSection]), global_offset=(0x420-0x438), parent_offset=(0x420-0x438), data_hex=184040000000000007000000010000000000000000000000]\n", + "│ └────1d87a47fda1542c6af0bb0560cb069ea: [caption=(ElfRelaEntry), attributes=(Data), global_offset=(0x420-0x438), parent_offset=(0x0-0x18), data_hex=184040000000000007000000010000000000000000000000]\n", + "├────1c68566fd848425fa831210133f3a0ae: [caption=(ElfSectionHeader), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[ElfSectionHeader]), global_offset=(0x3ba0-0x3be0), parent_offset=(0x3ba0-0x3be0), data_hex=8e000000010000000600000000000000001040000000000000100000000000001700000000000000000000000000000004000000000000000000000000000000]\n", + "├────64983f9ba7204ed494b99944ab3d0ff3: [caption=(ElfSection, CodeRegion), attributes=(Data, AttributesType[ElfSectionStructure]), global_offset=(0x1000-0x1017), parent_offset=(0x1000-0x1017), data_hex=4883ec08488b05ed2f00004885c07402ffd04883c408c3]\n", + "├────333e6e6581c94728978450427ec9b63a: [caption=(ElfSectionHeader), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[ElfSectionHeader]), global_offset=(0x3be0-0x3c20), parent_offset=(0x3be0-0x3c20), data_hex=89000000010000000600000000000000201040000000000020100000000000002000000000000000000000000000000010000000000000001000000000000000]\n", + "├────72ed80a0f46c4b5ab2cddb3c5eea86b0: [caption=(ElfSection, CodeRegion), attributes=(Data, AttributesType[ElfSectionStructure]), global_offset=(0x1020-0x1040), parent_offset=(0x1020-0x1040), data_hex=ff35e22f0000ff25e42f00000f1f4000ff25e22f00006800000000e9e0ffffff]\n", + "├────de7bd641c27c4bdd84df7f31c2ec8b2d: [caption=(ElfSectionHeader), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[ElfSectionHeader]), global_offset=(0x3c20-0x3c60), parent_offset=(0x3c20-0x3c60), data_hex=94000000010000000600000000000000401040000000000040100000000000006101000000000000000000000000000010000000000000000000000000000000]\n", + "├────59f70c17c0a742ec90206013dea49773: [caption=(ElfSection, CodeRegion), attributes=(Data, AttributesType[ElfSectionStructure]), global_offset=(0x1040-0x11a1), parent_offset=(0x1040-0x11a1), data_hash=1eeedffe]\n", + "├────12aaf5e20fd1407b93323a74c8329241: [caption=(ElfSectionHeader), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[ElfSectionHeader]), global_offset=(0x3c60-0x3ca0), parent_offset=(0x3c60-0x3ca0), data_hex=9a000000010000000600000000000000a411400000000000a4110000000000000900000000000000000000000000000004000000000000000000000000000000]\n", + "├────c0753d43a8e84b8d85dc13fd217f7a88: [caption=(ElfSection, CodeRegion), attributes=(Data, AttributesType[ElfSectionStructure]), global_offset=(0x11a4-0x11ad), parent_offset=(0x11a4-0x11ad), data_hex=4883ec084883c408c3]\n", + "├────dc5c5ebae79d498da647c1ba6c83ea21: [caption=(ElfSectionHeader), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[ElfSectionHeader]), global_offset=(0x3ca0-0x3ce0), parent_offset=(0x3ca0-0x3ce0), data_hex=a0000000010000000200000000000000002040000000000000200000000000001200000000000000000000000000000004000000000000000000000000000000]\n", + "├────82d0c5584c7a446bbbca77ef89f916da: [caption=(ElfSection), attributes=(Data, AttributesType[ElfSectionStructure]), global_offset=(0x2000-0x2012), parent_offset=(0x2000-0x2012), data_hex=0100020048656c6c6f2c20576f726c642100]\n", + "├────8295be99c79a4e3b92b07ebf962d7e05: [caption=(ElfSectionHeader), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[ElfSectionHeader]), global_offset=(0x3ce0-0x3d20), parent_offset=(0x3ce0-0x3d20), data_hex=a8000000010000000200000000000000142040000000000014200000000000003c00000000000000000000000000000004000000000000000000000000000000]\n", + "├────a40437099c894f5598cb03747ca82769: [caption=(ElfSection), attributes=(Data, AttributesType[ElfSectionStructure]), global_offset=(0x2014-0x2050), parent_offset=(0x2014-0x2050), data_hex=011b033b38000000060000000cf0ffff940000002cf0ffff540000005cf0ffff800000000ef1ffffbc0000002cf1ffffdc0000008cf1ffff24010000]\n", + "├────dc9fa3e9eeb248a3ba42742c61eb0e24: [caption=(ElfSectionHeader), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[ElfSectionHeader]), global_offset=(0x3d20-0x3d60), parent_offset=(0x3d20-0x3d60), data_hex=b6000000010000000200000000000000502040000000000050200000000000000001000000000000000000000000000008000000000000000000000000000000]\n", + "├────044434721476420e85bdf7470d9cead5: [caption=(ElfSection), attributes=(Data, AttributesType[ElfSectionStructure]), global_offset=(0x2050-0x2150), parent_offset=(0x2050-0x2150), data_hash=ef716b33]\n", + "├────9f6142f8b7ca4a7ea1bfa667c2a60606: [caption=(ElfSectionHeader), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[ElfSectionHeader]), global_offset=(0x3d60-0x3da0), parent_offset=(0x3d60-0x3da0), data_hex=c00000000e0000000300000000000000103e400000000000102e0000000000000800000000000000000000000000000008000000000000000800000000000000]\n", + "├───┬81d2e7cf2c5c44c89bd793b16ce9aa33: [caption=(ElfInitArraySection), attributes=(Data, AttributesType[ElfSectionStructure]), global_offset=(0x2e10-0x2e18), parent_offset=(0x2e10-0x2e18), data_hex=2011400000000000]\n", + "│ └────3aed4544bef44063af6a4df79d8289e2: [caption=(ElfVirtualAddress), attributes=(Data), global_offset=(0x2e10-0x2e18), parent_offset=(0x0-0x8), data_hex=2011400000000000]\n", + "├────35839cfc301e43bfb19d68d7fdfeeb25: [caption=(ElfSectionHeader), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[ElfSectionHeader]), global_offset=(0x3da0-0x3de0), parent_offset=(0x3da0-0x3de0), data_hex=cc0000000f0000000300000000000000183e400000000000182e0000000000000800000000000000000000000000000008000000000000000800000000000000]\n", + "├───┬39d2332886044a27ba6c822d219f636e: [caption=(ElfFiniArraySection), attributes=(Data, AttributesType[ElfSectionStructure]), global_offset=(0x2e18-0x2e20), parent_offset=(0x2e18-0x2e20), data_hex=f010400000000000]\n", + "│ └────e6342b244fd94acb96a28b8fff9fc254: [caption=(ElfVirtualAddress), attributes=(Data), global_offset=(0x2e18-0x2e20), parent_offset=(0x0-0x8), data_hex=f010400000000000]\n", + "├────5a381742faa64e479aa06f42876383f5: [caption=(ElfSectionHeader), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[ElfSectionHeader]), global_offset=(0x3de0-0x3e20), parent_offset=(0x3de0-0x3e20), data_hex=d8000000060000000300000000000000203e400000000000202e000000000000d001000000000000060000000000000008000000000000001000000000000000]\n", + "├───┬2c68fc7e09a9465fae9b257c6f5baddb: [caption=(ElfDynamicSection: .dynamic), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[Addressable], AttributesType[MemoryRegion], AttributesType[NamedProgramSection]), global_offset=(0x2e20-0x2ff0), parent_offset=(0x2e20-0x2ff0), data_hash=4438de54]\n", + "│ ├────b6eb90d01b204dc987fd81b160005b8c: [caption=(ElfDynamicEntry), attributes=(Data), global_offset=(0x2e20-0x2e30), parent_offset=(0x0-0x10), data_hex=01000000000000001800000000000000]\n", + "│ ├────f705825a5cba43388934ad4a4d0bdf9c: [caption=(ElfDynamicEntry), attributes=(Data), global_offset=(0x2e30-0x2e40), parent_offset=(0x10-0x20), data_hex=0c000000000000000010400000000000]\n", + "│ ├────99d4463b4d794414addaccfa0fd6d28d: [caption=(ElfDynamicEntry), attributes=(Data), global_offset=(0x2e40-0x2e50), parent_offset=(0x20-0x30), data_hex=0d00000000000000a411400000000000]\n", + "│ ├────7ed8e4e561d44564946682ab125be13d: [caption=(ElfDynamicEntry), attributes=(Data), global_offset=(0x2e50-0x2e60), parent_offset=(0x30-0x40), data_hex=1900000000000000103e400000000000]\n", + "│ ├────44461189539644e8b5b6f32e1a11d5cc: [caption=(ElfDynamicEntry), attributes=(Data), global_offset=(0x2e60-0x2e70), parent_offset=(0x40-0x50), data_hex=1b000000000000000800000000000000]\n", + "│ ├────5ae22b77dc984cf6ae0d214e72495ee5: [caption=(ElfDynamicEntry), attributes=(Data), global_offset=(0x2e70-0x2e80), parent_offset=(0x50-0x60), data_hex=1a00000000000000183e400000000000]\n", + "│ ├────0eb9eb88ebfd4a6598d5cf71d84b89b7: [caption=(ElfDynamicEntry), attributes=(Data), global_offset=(0x2e80-0x2e90), parent_offset=(0x60-0x70), data_hex=1c000000000000000800000000000000]\n", + "│ ├────4f20a4cac7f4419eb9689f8790e281c1: [caption=(ElfDynamicEntry), attributes=(Data), global_offset=(0x2e90-0x2ea0), parent_offset=(0x70-0x80), data_hex=f5feff6f000000000803400000000000]\n", + "│ ├────130c4f4e7b1447299b2cfb93f74ef8f0: [caption=(ElfDynamicEntry), attributes=(Data), global_offset=(0x2ea0-0x2eb0), parent_offset=(0x80-0x90), data_hex=05000000000000008803400000000000]\n", + "│ ├────70c4b90b30dc4703b772b56ac8b9623f: [caption=(ElfDynamicEntry), attributes=(Data), global_offset=(0x2eb0-0x2ec0), parent_offset=(0x90-0xa0), data_hex=06000000000000002803400000000000]\n", + "│ ├────62b1aae2cb854c9d8dd67285f5ed420c: [caption=(ElfDynamicEntry), attributes=(Data), global_offset=(0x2ec0-0x2ed0), parent_offset=(0xa0-0xb0), data_hex=0a000000000000003d00000000000000]\n", + "│ ├────6ca482b0921c4438b213c8d0e29fec35: [caption=(ElfDynamicEntry), attributes=(Data), global_offset=(0x2ed0-0x2ee0), parent_offset=(0xb0-0xc0), data_hex=0b000000000000001800000000000000]\n", + "│ ├────3b70d9de54cf47beb3e411bd443108e0: [caption=(ElfDynamicEntry), attributes=(Data), global_offset=(0x2ee0-0x2ef0), parent_offset=(0xc0-0xd0), data_hex=15000000000000000000000000000000]\n", + "│ ├────b00fa84d21c4448aa7b979c68176f5a5: [caption=(ElfDynamicEntry), attributes=(Data), global_offset=(0x2ef0-0x2f00), parent_offset=(0xd0-0xe0), data_hex=03000000000000000040400000000000]\n", + "│ ├────9b6cea1ede9442329ede9c9a6762dc42: [caption=(ElfDynamicEntry), attributes=(Data), global_offset=(0x2f00-0x2f10), parent_offset=(0xe0-0xf0), data_hex=02000000000000001800000000000000]\n", + "│ ├────909779148bd4427a93151b6f3489517a: [caption=(ElfDynamicEntry), attributes=(Data), global_offset=(0x2f10-0x2f20), parent_offset=(0xf0-0x100), data_hex=14000000000000000700000000000000]\n", + "│ ├────58ff0e4abd1e44708203908d40717c7b: [caption=(ElfDynamicEntry), attributes=(Data), global_offset=(0x2f20-0x2f30), parent_offset=(0x100-0x110), data_hex=17000000000000002004400000000000]\n", + "│ ├────8954a9c269d449c2bb71a4c50c0ef2c0: [caption=(ElfDynamicEntry), attributes=(Data), global_offset=(0x2f30-0x2f40), parent_offset=(0x110-0x120), data_hex=0700000000000000f003400000000000]\n", + "│ ├────353446007ece42cd9c3884f7206336aa: [caption=(ElfDynamicEntry), attributes=(Data), global_offset=(0x2f40-0x2f50), parent_offset=(0x120-0x130), data_hex=08000000000000003000000000000000]\n", + "│ ├────bc23b1bb841b430e9d3dfb412f333de0: [caption=(ElfDynamicEntry), attributes=(Data), global_offset=(0x2f50-0x2f60), parent_offset=(0x130-0x140), data_hex=09000000000000001800000000000000]\n", + "│ ├────46cf5f5e656242a8a02fa58f20bd45f1: [caption=(ElfDynamicEntry), attributes=(Data), global_offset=(0x2f60-0x2f70), parent_offset=(0x140-0x150), data_hex=feffff6f00000000d003400000000000]\n", + "│ ├────fb0c015c2ebd458b8e38a6fa25baf728: [caption=(ElfDynamicEntry), attributes=(Data), global_offset=(0x2f70-0x2f80), parent_offset=(0x150-0x160), data_hex=ffffff6f000000000100000000000000]\n", + "│ ├────c00c0a9b085e4d179110559d4679a773: [caption=(ElfDynamicEntry), attributes=(Data), global_offset=(0x2f80-0x2f90), parent_offset=(0x160-0x170), data_hex=f0ffff6f00000000c603400000000000]\n", + "│ ├────73f324b882ac499c97bbfd341f335afc: [caption=(ElfDynamicEntry), attributes=(Data), global_offset=(0x2f90-0x2fa0), parent_offset=(0x170-0x180), data_hex=00000000000000000000000000000000]\n", + "│ ├────203419b4dd4a48678a7e6f1ce991119a: [caption=(ElfDynamicEntry), attributes=(Data), global_offset=(0x2fa0-0x2fb0), parent_offset=(0x180-0x190), data_hex=00000000000000000000000000000000]\n", + "│ ├────1931d0cf7eb74618aa39d15a4487a4d5: [caption=(ElfDynamicEntry), attributes=(Data), global_offset=(0x2fb0-0x2fc0), parent_offset=(0x190-0x1a0), data_hex=00000000000000000000000000000000]\n", + "│ ├────e3c4d316a6c8421096900cc5b511a231: [caption=(ElfDynamicEntry), attributes=(Data), global_offset=(0x2fc0-0x2fd0), parent_offset=(0x1a0-0x1b0), data_hex=00000000000000000000000000000000]\n", + "│ ├────4c5e21867ebf4e218409f92bfd19beb6: [caption=(ElfDynamicEntry), attributes=(Data), global_offset=(0x2fd0-0x2fe0), parent_offset=(0x1b0-0x1c0), data_hex=00000000000000000000000000000000]\n", + "│ └────921d775d20c04511b918f82b54a01ba3: [caption=(ElfDynamicEntry), attributes=(Data), global_offset=(0x2fe0-0x2ff0), parent_offset=(0x1c0-0x1d0), data_hex=00000000000000000000000000000000]\n", + "├────3be0bda2f05f4b0a9b0e335a68c39649: [caption=(ElfSectionHeader), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[ElfSectionHeader]), global_offset=(0x3e20-0x3e60), parent_offset=(0x3e20-0x3e60), data_hex=e1000000010000000300000000000000f03f400000000000f02f0000000000001000000000000000000000000000000008000000000000000800000000000000]\n", + "├────568c1adc329847119834457d4fdab065: [caption=(ElfSection), attributes=(Data, AttributesType[ElfSectionStructure]), global_offset=(0x2ff0-0x3000), parent_offset=(0x2ff0-0x3000), data_hex=00000000000000000000000000000000]\n", + "├────002309662ba04030a2065fc449807d9b: [caption=(ElfSectionHeader), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[ElfSectionHeader]), global_offset=(0x3e60-0x3ea0), parent_offset=(0x3e60-0x3ea0), data_hex=e6000000010000000300000000000000004040000000000000300000000000002000000000000000000000000000000008000000000000000800000000000000]\n", + "├────7cdae41335344d71b9101d176455995e: [caption=(ElfSection), attributes=(Data, AttributesType[ElfSectionStructure]), global_offset=(0x3000-0x3020), parent_offset=(0x3000-0x3020), data_hex=203e400000000000000000000000000000000000000000003610400000000000]\n", + "├────17ae988daefa4a319bcf73b2d6972851: [caption=(ElfSectionHeader), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[ElfSectionHeader]), global_offset=(0x3ea0-0x3ee0), parent_offset=(0x3ea0-0x3ee0), data_hex=ef000000010000000300000000000000204040000000000020300000000000001000000000000000000000000000000008000000000000000000000000000000]\n", + "├────168f6a7572d04cc09a5a655215439b76: [caption=(ElfSection), attributes=(Data, AttributesType[ElfSectionStructure]), global_offset=(0x3020-0x3030), parent_offset=(0x3020-0x3030), data_hex=00000000000000000000000000000000]\n", + "├────39a76ddf9af14535842581a1981317f3: [caption=(ElfSectionHeader), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[ElfSectionHeader]), global_offset=(0x3ee0-0x3f20), parent_offset=(0x3ee0-0x3f20), data_hex=f5000000080000000300000000000000304040000000000030300000000000000800000000000000000000000000000001000000000000000000000000000000]\n", + "├────496b4d122a4b4839b031f33e32591231: [caption=(ElfSection), attributes=(AttributesType[ElfSectionStructure])]\n", + "├────f436ed40956847cda90489eb9232f215: [caption=(ElfSectionHeader), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[ElfSectionHeader]), global_offset=(0x3f20-0x3f60), parent_offset=(0x3f20-0x3f60), data_hex=fa000000010000003000000000000000000000000000000030300000000000002700000000000000000000000000000001000000000000000100000000000000]\n", + "├────aedff0584009432ea8fe7ed5ce71be20: [caption=(ElfSection), attributes=(Data, AttributesType[ElfSectionStructure]), global_offset=(0x3030-0x3057), parent_offset=(0x3030-0x3057), data_hex=4743433a202844656269616e2031302e322e312d36292031302e322e3120323032313031313000]\n", + "├────936847ba855a4363ba0ed9442cf7d3b6: [caption=(ElfSectionHeader), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[ElfSectionHeader]), global_offset=(0x3f60-0x3fa0), parent_offset=(0x3f60-0x3fa0), data_hex=0100000002000000000000000000000000000000000000005830000000000000b8050000000000001b0000002b00000008000000000000001800000000000000]\n", + "├───┬7f4df427959e4e899b9bbba56830b6cb: [caption=(ElfSymbolSection: .symtab), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[Addressable], AttributesType[MemoryRegion], AttributesType[NamedProgramSection]), global_offset=(0x3058-0x3610), parent_offset=(0x3058-0x3610), data_hash=f6bc0737]\n", + "│ ├────d6fd3402287f4fc0924e09166817d462: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3058-0x3070), parent_offset=(0x0-0x18), data_hex=000000000000000000000000000000000000000000000000]\n", + "│ ├────8acccc15acf44297891c05a3263f9abd: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3070-0x3088), parent_offset=(0x18-0x30), data_hex=0000000003000100a8024000000000000000000000000000]\n", + "│ ├────d505c1b03f3840e18dfb2f97191ad4dc: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3088-0x30a0), parent_offset=(0x30-0x48), data_hex=0000000003000200c4024000000000000000000000000000]\n", + "│ ├────076faae384194fa18daf13b26dd456e6: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x30a0-0x30b8), parent_offset=(0x48-0x60), data_hex=0000000003000300e8024000000000000000000000000000]\n", + "│ ├────710d8bf589d048cd873f1571e2676ff3: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x30b8-0x30d0), parent_offset=(0x60-0x78), data_hex=000000000300040008034000000000000000000000000000]\n", + "│ ├────723c1e879c804e76b8e116f1f75ada36: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x30d0-0x30e8), parent_offset=(0x78-0x90), data_hex=000000000300050028034000000000000000000000000000]\n", + "│ ├────ec6ae347714b4d39b0399bb95aeacf5f: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x30e8-0x3100), parent_offset=(0x90-0xa8), data_hex=000000000300060088034000000000000000000000000000]\n", + "│ ├────17c0bfe47fae415e9a658a18cb63bbe4: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3100-0x3118), parent_offset=(0xa8-0xc0), data_hex=0000000003000700c6034000000000000000000000000000]\n", + "│ ├────5f07c8158b7a443ca6953eb89c49eaf0: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3118-0x3130), parent_offset=(0xc0-0xd8), data_hex=0000000003000800d0034000000000000000000000000000]\n", + "│ ├────ec1ff8ae15fc45e48303b8bd2e3bf03b: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3130-0x3148), parent_offset=(0xd8-0xf0), data_hex=0000000003000900f0034000000000000000000000000000]\n", + "│ ├────563a84cfa3b141f4a61fc735037074da: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3148-0x3160), parent_offset=(0xf0-0x108), data_hex=0000000003000a0020044000000000000000000000000000]\n", + "│ ├────ab5954c90fe3479e9722f4c46c304168: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3160-0x3178), parent_offset=(0x108-0x120), data_hex=0000000003000b0000104000000000000000000000000000]\n", + "│ ├────4cb70182d7684f099fafb1f5280fc594: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3178-0x3190), parent_offset=(0x120-0x138), data_hex=0000000003000c0020104000000000000000000000000000]\n", + "│ ├────973236522d4347a1bc98ff268fd3a188: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3190-0x31a8), parent_offset=(0x138-0x150), data_hex=0000000003000d0040104000000000000000000000000000]\n", + "│ ├────13e4a55999a44863973398d90847865d: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x31a8-0x31c0), parent_offset=(0x150-0x168), data_hex=0000000003000e00a4114000000000000000000000000000]\n", + "│ ├────bbd1f4e42bc84157ae2b319fd65e7bd5: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x31c0-0x31d8), parent_offset=(0x168-0x180), data_hex=0000000003000f0000204000000000000000000000000000]\n", + "│ ├────3944be07ff4b4be9b4b7756384de2fe3: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x31d8-0x31f0), parent_offset=(0x180-0x198), data_hex=000000000300100014204000000000000000000000000000]\n", + "│ ├────09c4a1d945a84eab8069c075fa974227: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x31f0-0x3208), parent_offset=(0x198-0x1b0), data_hex=000000000300110050204000000000000000000000000000]\n", + "│ ├────a7f5604a59144cf2ace51d1719af84e2: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3208-0x3220), parent_offset=(0x1b0-0x1c8), data_hex=0000000003001200103e4000000000000000000000000000]\n", + "│ ├────16b5d8ed376f4b758e4fdd64a5193ffc: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3220-0x3238), parent_offset=(0x1c8-0x1e0), data_hex=0000000003001300183e4000000000000000000000000000]\n", + "│ ├────c05804bde68d4dba8f2421ef6580198e: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3238-0x3250), parent_offset=(0x1e0-0x1f8), data_hex=0000000003001400203e4000000000000000000000000000]\n", + "│ ├────f5d86700f16a423f8d92cf47ff443e78: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3250-0x3268), parent_offset=(0x1f8-0x210), data_hex=0000000003001500f03f4000000000000000000000000000]\n", + "│ ├────9bf427fbf2524691a6ec046158a949e1: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3268-0x3280), parent_offset=(0x210-0x228), data_hex=000000000300160000404000000000000000000000000000]\n", + "│ ├────b195d126b2a648278eebdc4f71f6e4dc: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3280-0x3298), parent_offset=(0x228-0x240), data_hex=000000000300170020404000000000000000000000000000]\n", + "│ ├────23e2ca30cdc348538007a7db3e79ccd1: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3298-0x32b0), parent_offset=(0x240-0x258), data_hex=000000000300180030404000000000000000000000000000]\n", + "│ ├────fffa25ec4fb74374a7e69b7ef361e032: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x32b0-0x32c8), parent_offset=(0x258-0x270), data_hex=000000000300190000000000000000000000000000000000]\n", + "│ ├────eaa17981b430447db640a47c707145c4: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x32c8-0x32e0), parent_offset=(0x270-0x288), data_hex=010000000400f1ff00000000000000000000000000000000]\n", + "│ ├────92a1313d1ed048f2851b2679e6815848: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x32e0-0x32f8), parent_offset=(0x288-0x2a0), data_hex=0c00000002000d0080104000000000000000000000000000]\n", + "│ ├────f089c856fa494d4eb898987f7e59867a: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x32f8-0x3310), parent_offset=(0x2a0-0x2b8), data_hex=0e00000002000d00b0104000000000000000000000000000]\n", + "│ ├────b2253507cc324d14a3080345593abad9: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3310-0x3328), parent_offset=(0x2b8-0x2d0), data_hex=2100000002000d00f0104000000000000000000000000000]\n", + "│ ├────d47c18ff2f364253ac700e0345e18bc3: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3328-0x3340), parent_offset=(0x2d0-0x2e8), data_hex=370000000100180030404000000000000100000000000000]\n", + "│ ├────0d9bd08ae41d4c9aa66917b3f5448c69: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3340-0x3358), parent_offset=(0x2e8-0x300), data_hex=4300000001001300183e4000000000000000000000000000]\n", + "│ ├────23a22c769556448da6519900d53509da: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3358-0x3370), parent_offset=(0x300-0x318), data_hex=6a00000002000d0020114000000000000000000000000000]\n", + "│ ├────794fc4b7cfbb46509764f29920aefe19: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3370-0x3388), parent_offset=(0x318-0x330), data_hex=7600000001001200103e4000000000000000000000000000]\n", + "│ ├────344464d733cc4f2f999a85954d5bb9d2: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3388-0x33a0), parent_offset=(0x330-0x348), data_hex=950000000400f1ff00000000000000000000000000000000]\n", + "│ ├────71f73ff2fb434294a6d2c6aa0f911e2a: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x33a0-0x33b8), parent_offset=(0x348-0x360), data_hex=010000000400f1ff00000000000000000000000000000000]\n", + "│ ├────eb5efda26ef84017bc612ef14587ad38: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x33b8-0x33d0), parent_offset=(0x360-0x378), data_hex=a3000000010011004c214000000000000000000000000000]\n", + "│ ├────a54dcf89bf2648d9bae34a6afc29f537: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x33d0-0x33e8), parent_offset=(0x378-0x390), data_hex=000000000400f1ff00000000000000000000000000000000]\n", + "│ ├────fd2c96e5c82840d48e8ad9d2ac00fe8c: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x33e8-0x3400), parent_offset=(0x390-0x3a8), data_hex=b100000000001200183e4000000000000000000000000000]\n", + "│ ├────804264991b7a45caa33c367d698893b9: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3400-0x3418), parent_offset=(0x3a8-0x3c0), data_hex=c200000001001400203e4000000000000000000000000000]\n", + "│ ├────f8c69edfad8e4eacbdb67acf98359e85: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3418-0x3430), parent_offset=(0x3c0-0x3d8), data_hex=cb00000000001200103e4000000000000000000000000000]\n", + "│ ├────acd517a8db4c4353a996164095732c1e: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3430-0x3448), parent_offset=(0x3d8-0x3f0), data_hex=de0000000000100014204000000000000000000000000000]\n", + "│ ├────5a06c5d52da64ab2abb3607e7c687247: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3448-0x3460), parent_offset=(0x3f0-0x408), data_hex=f10000000100160000404000000000000000000000000000]\n", + "│ ├────7130d0386d01459f8bcbf59e53f5855f: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3460-0x3478), parent_offset=(0x408-0x420), data_hex=0701000012000d00a0114000000000000100000000000000]\n", + "│ ├────156b9bc2b9e34e12a606da4bebfd978a: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3478-0x3490), parent_offset=(0x420-0x438), data_hex=4f0100002000170020404000000000000000000000000000]\n", + "│ ├────f2a348fc941f42f6b53ba1856a4d4d72: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3490-0x34a8), parent_offset=(0x438-0x450), data_hex=170100001200000000000000000000000000000000000000]\n", + "│ ├────10eaae4b85eb4b53aad265a8901b91c8: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x34a8-0x34c0), parent_offset=(0x450-0x468), data_hex=280100001000170030404000000000000000000000000000]\n", + "│ ├────dd21956da645496e816036cbeb0ce48c: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x34c0-0x34d8), parent_offset=(0x468-0x480), data_hex=1101000012020e00a4114000000000000000000000000000]\n", + "│ ├────6821c90624374a0caf68fb506e689f01: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x34d8-0x34f0), parent_offset=(0x480-0x498), data_hex=2f0100001200000000000000000000000000000000000000]\n", + "│ ├────517ce3c57958456bbfadb5c57958dc46: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x34f0-0x3508), parent_offset=(0x498-0x4b0), data_hex=4d0100001000170020404000000000000000000000000000]\n", + "│ ├────6a3dcfdce1d342608ccb7f9eacde3362: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3508-0x3520), parent_offset=(0x4b0-0x4c8), data_hex=5a0100002000000000000000000000000000000000000000]\n", + "│ ├────f09b418dc51a483892a6042b1ed87634: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3520-0x3538), parent_offset=(0x4c8-0x4e0), data_hex=690100001102170028404000000000000000000000000000]\n", + "│ ├────6d57c22dbce2493f9fdd9218e255479b: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3538-0x3550), parent_offset=(0x4e0-0x4f8), data_hex=7601000011000f0000204000000000000400000000000000]\n", + "│ ├────5c341f74bc2d43f5aaab7076caca2c03: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3550-0x3568), parent_offset=(0x4f8-0x510), data_hex=8501000012000d0040114000000000005d00000000000000]\n", + "│ ├────96284ebc1c2e4f5b83200bcc750a4fef: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3568-0x3580), parent_offset=(0x510-0x528), data_hex=bd0000001000180038404000000000000000000000000000]\n", + "│ ├────14151cbe5a144134a69a078622ce8e2c: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3580-0x3598), parent_offset=(0x528-0x540), data_hex=9501000012020d0070104000000000000100000000000000]\n", + "│ ├────5f547cfdff45493380ca584b27bf44c3: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x3598-0x35b0), parent_offset=(0x540-0x558), data_hex=5301000012000d0040104000000000002b00000000000000]\n", + "│ ├────d2b8b0cd7c5a4ad89310951553d2d3c2: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x35b0-0x35c8), parent_offset=(0x558-0x570), data_hex=ad0100001000180030404000000000000000000000000000]\n", + "│ ├────65dbe06d408b4a5181ff6c26dced6a8d: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x35c8-0x35e0), parent_offset=(0x570-0x588), data_hex=b901000012000d0022114000000000001700000000000000]\n", + "│ ├────5bafab18e55446e3bac55140c5f1da80: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x35e0-0x35f8), parent_offset=(0x588-0x5a0), data_hex=be0100001102170030404000000000000000000000000000]\n", + "│ └────99c652c5c468492ca145b951a87f899c: [caption=(ElfSymbol), attributes=(Data, AttributesType[ElfSymbolStructure]), global_offset=(0x35f8-0x3610), parent_offset=(0x5a0-0x5b8), data_hex=8f01000012020b0000104000000000000000000000000000]\n", + "├────fbadd51624154144830b32a2a57828d2: [caption=(ElfSectionHeader), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[ElfSectionHeader]), global_offset=(0x3fa0-0x3fe0), parent_offset=(0x3fa0-0x3fe0), data_hex=0900000003000000000000000000000000000000000000001036000000000000ca01000000000000000000000000000001000000000000000000000000000000]\n", + "├────e801f3a5dbb34975a79c8d662fd8e14c: [caption=(ElfSection, ElfStringSection), attributes=(Data, AttributesType[ElfSectionStructure]), global_offset=(0x3610-0x37da), parent_offset=(0x3610-0x37da), data_hash=800e56e9]\n", + "├────7c0d17f39c8f4ae5b43e050b80ffea4b: [caption=(ElfSectionHeader), attributes=(Data, AttributesType[ElfSectionStructure], AttributesType[ElfSectionHeader]), global_offset=(0x3fe0-0x4020), parent_offset=(0x3fe0-0x4020), data_hex=110000000300000000000000000000000000000000000000da370000000000000301000000000000000000000000000001000000000000000000000000000000]\n", + "├────bce8fdcd97d0493885df4bf2257cb603: [caption=(ElfSection, ElfSectionNameStringSection), attributes=(Data, AttributesType[ElfSectionStructure]), global_offset=(0x37da-0x38dd), parent_offset=(0x37da-0x38dd), data_hash=6db41dea]\n", + "├────d2a4b9cd389349a7a3b6fadc842dc4d9: [caption=(ElfProgramHeader: PHDR, R), attributes=(Data, AttributesType[ElfSegmentStructure], AttributesType[ElfProgramHeader]), global_offset=(0x40-0x78), parent_offset=(0x40-0x78), data_hex=0600000004000000400000000000000040004000000000004000400000000000680200000000000068020000000000000800000000000000]\n", + "├────6774abc4d43e4341ba0229176a6f6cb0: [caption=(ElfProgramHeader: INTERP, R), attributes=(Data, AttributesType[ElfSegmentStructure], AttributesType[ElfProgramHeader]), global_offset=(0x78-0xb0), parent_offset=(0x78-0xb0), data_hex=0300000004000000a802000000000000a802400000000000a8024000000000001c000000000000001c000000000000000100000000000000]\n", + "├────4016bcc472e04feaab48b887131db1d4: [caption=(ElfProgramHeader: LOAD, R), attributes=(Data, AttributesType[ElfSegmentStructure], AttributesType[ElfProgramHeader]), global_offset=(0xb0-0xe8), parent_offset=(0xb0-0xe8), data_hex=0100000004000000000000000000000000004000000000000000400000000000380400000000000038040000000000000010000000000000]\n", + "├────2dbf367e00344888ae2db96d5e2eddd0: [caption=(ElfProgramHeader: LOAD, RX), attributes=(Data, AttributesType[ElfSegmentStructure], AttributesType[ElfProgramHeader]), global_offset=(0xe8-0x120), parent_offset=(0xe8-0x120), data_hex=0100000005000000001000000000000000104000000000000010400000000000ad01000000000000ad010000000000000010000000000000]\n", + "├────935e9bf7dc764b7fa7f7eb36fa3cbd52: [caption=(ElfProgramHeader: LOAD, R), attributes=(Data, AttributesType[ElfSegmentStructure], AttributesType[ElfProgramHeader]), global_offset=(0x120-0x158), parent_offset=(0x120-0x158), data_hex=0100000004000000002000000000000000204000000000000020400000000000500100000000000050010000000000000010000000000000]\n", + "├────76ded1a82fb646a692f381d3e66e9ae4: [caption=(ElfProgramHeader: LOAD, RW), attributes=(Data, AttributesType[ElfSegmentStructure], AttributesType[ElfProgramHeader]), global_offset=(0x158-0x190), parent_offset=(0x158-0x190), data_hex=0100000006000000102e000000000000103e400000000000103e400000000000200200000000000028020000000000000010000000000000]\n", + "├────76f6effa81564daa9f491783e826075e: [caption=(ElfProgramHeader: DYNAMIC, RW), attributes=(Data, AttributesType[ElfSegmentStructure], AttributesType[ElfProgramHeader]), global_offset=(0x190-0x1c8), parent_offset=(0x190-0x1c8), data_hex=0200000006000000202e000000000000203e400000000000203e400000000000d001000000000000d0010000000000000800000000000000]\n", + "├────eb69f5aed9244eedaf92057e28880ba5: [caption=(ElfProgramHeader: NOTE, R), attributes=(Data, AttributesType[ElfSegmentStructure], AttributesType[ElfProgramHeader]), global_offset=(0x1c8-0x200), parent_offset=(0x1c8-0x200), data_hex=0400000004000000c402000000000000c402400000000000c402400000000000440000000000000044000000000000000400000000000000]\n", + "├────70c7363eb6de481c9be32353d1032c5a: [caption=(ElfProgramHeader: GNU_EH_FRAME, R), attributes=(Data, AttributesType[ElfSegmentStructure], AttributesType[ElfProgramHeader]), global_offset=(0x200-0x238), parent_offset=(0x200-0x238), data_hex=50e57464040000001420000000000000142040000000000014204000000000003c000000000000003c000000000000000400000000000000]\n", + "├────0978e1b79bf542859e5b0452c7bd5a7e: [caption=(ElfProgramHeader: GNU_STACK, RW), attributes=(Data, AttributesType[ElfSegmentStructure], AttributesType[ElfProgramHeader]), global_offset=(0x238-0x270), parent_offset=(0x238-0x270), data_hex=51e5746406000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000]\n", + "└────85d9284be41443f797d0800d5d721315: [caption=(ElfProgramHeader: GNU_RELRO, R), attributes=(Data, AttributesType[ElfSegmentStructure], AttributesType[ElfProgramHeader]), global_offset=(0x270-0x2a8), parent_offset=(0x270-0x2a8), data_hex=52e5746404000000102e000000000000103e400000000000103e400000000000f001000000000000f0010000000000000100000000000000]\n", "\n" ] } @@ -428,7 +358,6 @@ "output_type": "stream", "text": [ "Addressable\n", - "AsciiString\n", "CodeRegion\n", "ElfBasicHeader\n", "ElfDynSymbolSection\n", @@ -499,10 +428,10 @@ { "data": { "text/plain": [ - "[Resource(resource_id=565fc63a77494276bafea235ae00344e, tag=[Addressable,CodeRegion,ElfSection,MemoryRegion,ProgramSection,NamedProgramSection,ElfSectionStructure], data=565fc63a77494276bafea235ae00344e),\n", - " Resource(resource_id=d53f13b1d70c486397c25938311aeeab, tag=[Addressable,CodeRegion,ElfSection,MemoryRegion,ProgramSection,NamedProgramSection,ElfSectionStructure], data=d53f13b1d70c486397c25938311aeeab),\n", - " Resource(resource_id=9fb3213d0af14510828108089c1d521b, tag=[Addressable,CodeRegion,ElfSection,MemoryRegion,ProgramSection,NamedProgramSection,ElfSectionStructure], data=9fb3213d0af14510828108089c1d521b),\n", - " Resource(resource_id=1200d9c6b7ba4406bd97d44ef17fea4b, tag=[Addressable,CodeRegion,ElfSection,MemoryRegion,ProgramSection,NamedProgramSection,ElfSectionStructure], data=1200d9c6b7ba4406bd97d44ef17fea4b)]" + "[Resource(resource_id=59f70c17c0a742ec90206013dea49773, tag=[ElfSection,NamedProgramSection,CodeRegion,ElfSectionStructure,ProgramSection,Addressable,MemoryRegion], data=59f70c17c0a742ec90206013dea49773),\n", + " Resource(resource_id=72ed80a0f46c4b5ab2cddb3c5eea86b0, tag=[ElfSection,NamedProgramSection,CodeRegion,ElfSectionStructure,ProgramSection,Addressable,MemoryRegion], data=72ed80a0f46c4b5ab2cddb3c5eea86b0),\n", + " Resource(resource_id=64983f9ba7204ed494b99944ab3d0ff3, tag=[ElfSection,NamedProgramSection,CodeRegion,ElfSectionStructure,ProgramSection,Addressable,MemoryRegion], data=64983f9ba7204ed494b99944ab3d0ff3),\n", + " Resource(resource_id=c0753d43a8e84b8d85dc13fd217f7a88, tag=[ElfSection,NamedProgramSection,CodeRegion,ElfSectionStructure,ProgramSection,Addressable,MemoryRegion], data=c0753d43a8e84b8d85dc13fd217f7a88)]" ] }, "execution_count": 7, diff --git a/ofrak_type/Makefile b/ofrak_type/Makefile index 2272aa437..54cef6b96 100644 --- a/ofrak_type/Makefile +++ b/ofrak_type/Makefile @@ -11,7 +11,7 @@ develop: .PHONY: inspect inspect: - mypy + $(PYTHON) -m mypy .PHONY: test test: inspect diff --git a/ofrak_type/setup.py b/ofrak_type/setup.py index c74f530b4..5be7ab912 100644 --- a/ofrak_type/setup.py +++ b/ofrak_type/setup.py @@ -32,8 +32,9 @@ def run(self): "fun-coverage==0.2.0", "hypothesis~=6.39.3", "mypy==0.942", - "pytest", + "pytest<8.0", "pytest-cov", + "pytest-xdist", ] }, packages=setuptools.find_packages(), diff --git a/test_all_versions.sh b/test_all_versions.sh new file mode 100755 index 000000000..dcf674d9b --- /dev/null +++ b/test_all_versions.sh @@ -0,0 +1,36 @@ +#!/bin/bash +set -e +# Needed to allow mypy to find packages. See https://github.com/python/mypy/issues/13392 +export SETUPTOOLS_ENABLE_FEATURES="legacy-editable" +if [ -z "${PYTHON_VERSIONS}" ]; then + PYTHON_VERSIONS="3.7 3.8 3.9 3.10 3.11 3.12" +fi +if [ -z "${PYENV_ROOT}" ]; then + export PYENV_ROOT=/usr/local/pyenv +fi +export PATH="${PYENV_ROOT}/bin:$PATH" +if [ -z "${BINJA_DIR}" ]; then + BINJA_DIR=/opt/rbs +fi +if [ ! -e "${BINJA_DIR}"/binaryninja/scripts/install_api.py ]; then + echo "Expected ${BINJA_DIR}/binaryninja/scripts/install_api.py to be there, but it's not." + echo "Is binary ninja installed? Do you have BINJA_DIR defined correctly (defaults to /opt/rbs)?" + exit 1 +fi +if [ ! -e "${PYENV_ROOT}" ]; then + curl https://pyenv.run | bash +fi +eval "$(pyenv init -)" +for v in ${PYTHON_VERSIONS}; do + pyenv install -s $v + pyenv global $v + python$v -m pip --no-input install --upgrade pip + python$v -m pip --no-input install requests + python$v "${BINJA_DIR}"/binaryninja/scripts/install_api.py + if make OFRAK_INSTALL_PYTHON=python$v install_test_all; then : + else + echo "Failed to make and test with Python v $v" + exit 1 + fi +done +echo "Success!"