diff --git a/fact_extractor/plugins/unpacking/bneg/__init__.py b/fact_extractor/plugins/unpacking/bneg/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/fact_extractor/plugins/unpacking/bneg/code/__init__.py b/fact_extractor/plugins/unpacking/bneg/code/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/fact_extractor/plugins/unpacking/bneg/code/bneg.py b/fact_extractor/plugins/unpacking/bneg/code/bneg.py new file mode 100644 index 00000000..2e4ca351 --- /dev/null +++ b/fact_extractor/plugins/unpacking/bneg/code/bneg.py @@ -0,0 +1,39 @@ +import struct +from pathlib import Path + +NAME = 'Instar BNEG' +MIME_PATTERNS = ['firmware/bneg'] +VERSION = '0.1.0' + + +class BnegHeader: + def __init__(self, data: bytes): + ( + self.magic, + self.major_version, + self.minor_version, + *self.partitions, + ) = struct.unpack('<4sIIII', data) + + def to_dict(self): + return self.__dict__ + + +def unpack_function(file_path: str, tmp_dir: str) -> dict: + input_file = Path(file_path) + output_dir = Path(tmp_dir) + with input_file.open('rb') as fp: + header = BnegHeader(fp.read(20)) + output = [f'Found BNEG v{header.major_version}.{header.minor_version}'] + for index, partition in enumerate(header.partitions, start=1): + if partition: + (output_dir / f'partition_{index}.bin').write_bytes(fp.read(partition)) + output.append(f'Unpacked partition {index} to partition_{index}.bin (size {partition})') + + return {'output': '\n'.join(output)} + + +# ----> Do not edit below this line <---- +def setup(unpack_tool): + for item in MIME_PATTERNS: + unpack_tool.register_plugin(item, (unpack_function, NAME, VERSION)) diff --git a/fact_extractor/plugins/unpacking/bneg/test/__init__.py b/fact_extractor/plugins/unpacking/bneg/test/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/fact_extractor/plugins/unpacking/bneg/test/data/test.bneg b/fact_extractor/plugins/unpacking/bneg/test/data/test.bneg new file mode 100644 index 00000000..5907bcb1 Binary files /dev/null and b/fact_extractor/plugins/unpacking/bneg/test/data/test.bneg differ diff --git a/fact_extractor/plugins/unpacking/bneg/test/test_bneg.py b/fact_extractor/plugins/unpacking/bneg/test/test_bneg.py new file mode 100644 index 00000000..8ba83ec1 --- /dev/null +++ b/fact_extractor/plugins/unpacking/bneg/test/test_bneg.py @@ -0,0 +1,27 @@ +from pathlib import Path + +from test.unit.unpacker.test_unpacker import TestUnpackerBase + +TEST_DATA_DIR = Path(__file__).parent / 'data' + + +class TestInstarBnegUnpacker(TestUnpackerBase): + + def test_unpacker_selection_generic(self): + self.check_unpacker_selection('firmware/bneg', 'Instar BNEG') + + def test_extraction_bneg(self): + in_file = TEST_DATA_DIR / 'test.bneg' + assert in_file.is_file(), 'test file is missing' + files, meta = self.unpacker.extract_files_from_file(str(in_file), self.tmp_dir.name) + assert len(files) == 2 # noqa: PLR2004 + assert 'output' in meta + assert 'size 7' in meta['output'] + assert 'size 8' in meta['output'] + + file1 = Path(self.tmp_dir.name) / 'partition_1.bin' + assert file1.is_file() + assert file1.read_bytes() == b'foobar\n' + file2 = Path(self.tmp_dir.name) / 'partition_2.bin' + assert file2.is_file() + assert file2.read_bytes() == b'test123\n'