diff --git a/fact_extractor/plugins/unpacking/broadcom/__init__.py b/fact_extractor/plugins/unpacking/broadcom/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/fact_extractor/plugins/unpacking/broadcom/code/__init__.py b/fact_extractor/plugins/unpacking/broadcom/code/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/fact_extractor/plugins/unpacking/broadcom/code/broadcom-sao.py b/fact_extractor/plugins/unpacking/broadcom/code/broadcom-sao.py new file mode 100644 index 00000000..8ec5259a --- /dev/null +++ b/fact_extractor/plugins/unpacking/broadcom/code/broadcom-sao.py @@ -0,0 +1,45 @@ +''' +This plugin unpacks Broadcom SAO images. +''' + +import os +from pathlib import Path +from common_helper_files import write_binary_to_file + +NAME = "Broadcom SAO" +MIME_PATTERNS = ['firmware/broadcom-sao'] +VERSION = '0.1' + +def unpack_function(file_path, tmp_dir): + ''' + file_path specifies the input file. + tmp_dir must be used to store the extracted files. + Optional: Return a dict with meta information + ''' + + FILE_SIZE = os.stat(file_path).st_size + + try: + with open(file_path, 'rb') as f: + while (f.tell() < FILE_SIZE): + f.read(8) # skip 8 bytes to part name offset + name = f.read(4).decode('utf-8') + f.read(4) # skip 4 more bytes to size offset + size = int.from_bytes(f.read(4), 'big') + f.read(44) # skip rest of header + data = f.read(size) + outfile = Path(tmp_dir) / name + write_binary_to_file(data, outfile) + + except IOError as io_error: + return {'output': 'failed to read file: {}'.format(str(io_error))} + + + return { + 'output': 'successfully unpacked Broadcom SAO image' + } + +# ----> 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/broadcom/test/__init__.py b/fact_extractor/plugins/unpacking/broadcom/test/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/fact_extractor/plugins/unpacking/broadcom/test/data/broadcom-sao.bin b/fact_extractor/plugins/unpacking/broadcom/test/data/broadcom-sao.bin new file mode 100644 index 00000000..36a1c8b8 Binary files /dev/null and b/fact_extractor/plugins/unpacking/broadcom/test/data/broadcom-sao.bin differ diff --git a/fact_extractor/plugins/unpacking/broadcom/test/test_plugin_broadcom_sao.py b/fact_extractor/plugins/unpacking/broadcom/test/test_plugin_broadcom_sao.py new file mode 100644 index 00000000..5ca73c19 --- /dev/null +++ b/fact_extractor/plugins/unpacking/broadcom/test/test_plugin_broadcom_sao.py @@ -0,0 +1,21 @@ +from pathlib import Path + +from test.unit.unpacker.test_unpacker import TestUnpackerBase + +TEST_DATA_DIR = Path(__file__).parent / 'data' + +class TestBroadcomSAOUnpacker(TestUnpackerBase): + + def test_unpacker_selection_generic(self): + self.check_unpacker_selection('firmware/broadcom-sao', 'Broadcom SAO') + + def test_extraction(self): + test_file_path = Path(TEST_DATA_DIR) / 'broadcom-sao.bin' + extracted_files, meta_data = self.unpacker.extract_files_from_file(str(test_file_path), self.tmp_dir.name) + + assert meta_data['plugin_used'] == 'Broadcom SAO', 'wrong plugin applied' + + assert len(extracted_files) == 4, 'not all files extracted' + assert all( + Path(element).name in ['META', 'DTBB', 'KRNL', 'RTFS'] for element in extracted_files + ), 'not all files extracted'