From 21a935010a80d13642516790f36cfe33e14a4099 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sun, 16 Jul 2023 12:12:34 +0200 Subject: [PATCH] Fixed a problem when a journal bud is not mapped Fixed a problem when a corrupted inode with invalid ino_size field (e.g. ludicrously huge size) is being dumped Fixed a problem caused when decompressing data fails --- .gitignore | 7 ++----- ubift/cli/renderer.py | 2 +- ubift/framework/compression.py | 29 +++++++++++++++++++---------- ubift/framework/ubifs.py | 3 +++ 4 files changed, 25 insertions(+), 16 deletions(-) diff --git a/.gitignore b/.gitignore index c2948b1..d7c8fd3 100644 --- a/.gitignore +++ b/.gitignore @@ -231,8 +231,5 @@ fabric.properties # libreoffice files **/.~lock* -# ocrmypdf docker container -data/ocrmypdf.tar - -# protege tempfiles -data/catalog-v001.xml \ No newline at end of file +# local files +/utils/ diff --git a/ubift/cli/renderer.py b/ubift/cli/renderer.py index 838c592..54e6401 100644 --- a/ubift/cli/renderer.py +++ b/ubift/cli/renderer.py @@ -364,7 +364,7 @@ def write_to_file(inode: UBIFS_INO_NODE, data_nodes: List[UBIFS_DATA_NODE], abs_ accu_size += len(data_node.decompressed_data) - if inode.ino_size > accu_size: + if inode.ino_size > accu_size and accu_size > 0: ubiftlog.warning( f"[!] Size from inode field 'size' ({inode.ino_size}) is more than written bytes {accu_size}. Filling bytes with zeroes.") f.seek(inode.ino_size) diff --git a/ubift/framework/compression.py b/ubift/framework/compression.py index 486c89f..a29a4c5 100644 --- a/ubift/framework/compression.py +++ b/ubift/framework/compression.py @@ -5,6 +5,9 @@ import lzo from ubift import exception +from ubift.framework.structs.ubifs_structs import UBIFS_COMPRESSION_TYPE +from ubift.logging import ubiftlog + def decompress(data: bytes, compr_type: int, size: int = None) -> bytes: """ @@ -14,13 +17,19 @@ def decompress(data: bytes, compr_type: int, size: int = None) -> bytes: :param size: Size of buffer length that will fit output, needed by LZO-compression, for other compression methods this value does not matter. Value for this can be found in UBIFS_DATA_NODE :return: Uncompressed data """ - if compr_type == 0: # UBIFS_COMPRESSION_TYPE.UBIFS_COMPR_NONE - return data - elif compr_type == 1: # UBIFS_COMPRESSION_TYPE.UBIFS_COMPR_LZO - return lzo.decompress(data, False, size) - elif compr_type == 2: # UBIFS_COMPRESSION_TYPE.UBIFS_COMPR_ZLIB - return zlib.decompress(data, -zlib.MAX_WBITS) - elif compr_type == 3: # UBIFS_COMPRESSION_TYPE.UBIFS_COMPR_ZSTD - return zstandard.decompress(data, size) - else: - raise exception.UBIFTException(f"Data is compressed with unknown type. ({compr_type})") + try: + if compr_type == 0: # UBIFS_COMPRESSION_TYPE.UBIFS_COMPR_NONE + return data + elif compr_type == 1: # UBIFS_COMPRESSION_TYPE.UBIFS_COMPR_LZO + return lzo.decompress(data, False, size) + elif compr_type == 2: # UBIFS_COMPRESSION_TYPE.UBIFS_COMPR_ZLIB + return zlib.decompress(data, -zlib.MAX_WBITS) + elif compr_type == 3: # UBIFS_COMPRESSION_TYPE.UBIFS_COMPR_ZSTD + return zstandard.decompress(data, size) + else: + raise exception.UBIFTException(f"Data is compressed with unknown type. ({compr_type})") + except Exception as e: + ubiftlog.warn( + f"[-] Error while decompressing data using {UBIFS_COMPRESSION_TYPE(compr_type).name}: {e}") + return bytes() + diff --git a/ubift/framework/ubifs.py b/ubift/framework/ubifs.py index ae8a20d..74c08c6 100644 --- a/ubift/framework/ubifs.py +++ b/ubift/framework/ubifs.py @@ -66,6 +66,9 @@ def _parse_bud(self, jhead: int) -> list: ubiftlog.info(f"[!] Parsing bud {UBIFS_JOURNAL_HEADS(jhead)}") ref_node = self._jheads[jhead] + if ref_node.lnum not in self._ubifs.ubi_volume.lebs: + ubiftlog.info(f"[-] Cannot parse bud {UBIFS_JOURNAL_HEADS(jhead)} because referenced LEB {ref_node.lnum} is not mapped.") + return [] leb = self._ubifs.ubi_volume.lebs[ref_node.lnum] leb_offs = ref_node.offs