def testSeek(self): """Tests the seek function.""" file_object = io.BytesIO(self._FILE_DATA) test_range = data_range.DataRange(file_object, data_offset=32, data_size=64) test_range.seek(0, os.SEEK_SET) offset = test_range.get_offset() self.assertEqual(offset, 0) test_range.seek(0, os.SEEK_END) offset = test_range.get_offset() self.assertEqual(offset, 64) test_range.seek(-32, os.SEEK_CUR) offset = test_range.get_offset() self.assertEqual(offset, 32) test_range.seek(128, os.SEEK_SET) offset = test_range.get_offset() self.assertEqual(offset, 128) with self.assertRaises(IOError): test_range.seek(0, -1) with self.assertRaises(IOError): test_range.seek(-256, os.SEEK_CUR) test_range.data_size = -1 with self.assertRaises(IOError): test_range.seek(0, os.SEEK_SET) test_range.data_offset = 64
def testRead(self): """Tests the read function.""" file_object = io.BytesIO(self._FILE_DATA) test_range = data_range.DataRange(file_object, data_offset=32, data_size=64) byte_stream = test_range.read(size=1) self.assertEqual(byte_stream, b'\x20') byte_stream = test_range.read() self.assertEqual(len(byte_stream), 63) byte_stream = test_range.read() self.assertEqual(byte_stream, b'') test_range.data_offset = -1 with self.assertRaises(IOError): test_range.read() test_range.data_offset = 32 test_range.data_size = -1 with self.assertRaises(IOError): test_range.read() test_range.data_offset = 64
def testTell(self): """Tests the tell function.""" file_object = io.BytesIO(self._FILE_DATA) test_range = data_range.DataRange(file_object, data_offset=32, data_size=64) offset = test_range.tell() self.assertEqual(offset, 0)
def testSeekable(self): """Tests the seekable function.""" file_object = io.BytesIO(self._FILE_DATA) test_range = data_range.DataRange(file_object, data_offset=32, data_size=64) result = test_range.seekable() self.assertTrue(result)
def testGetSize(self): """Tests the get_size function.""" file_object = io.BytesIO(self._FILE_DATA) test_range = data_range.DataRange(file_object, data_offset=32, data_size=64) size = test_range.get_size() self.assertEqual(size, 64)
def _ReadLNKFiles(self, file_object): """Reads the LNK files. Args: file_object (file): file-like object. Raises: ParseError: if the LNK files cannot be read. """ file_offset = file_object.tell() remaining_file_size = self._file_size - file_offset data_type_map = self._GetDataTypeMap('custom_entry_header') # The Custom Destination file does not have a unique signature in # the file header that is why we use the first LNK class identifier (GUID) # as a signature. first_guid_checked = False while remaining_file_size > 4: try: entry_header, _ = self._ReadStructureFromFileObject( file_object, file_offset, data_type_map, 'entry header') except errors.ParseError as exception: error_message = ( 'Unable to parse file entry header at offset: 0x{0:08x} ' 'with error: {1:s}').format(file_offset, exception) if not first_guid_checked: raise errors.ParseError(error_message) logging.warning(error_message) break if entry_header.guid != self._LNK_GUID: error_message = 'Invalid entry header at offset: 0x{0:08x}.'.format( file_offset) if not first_guid_checked: raise errors.ParseError(error_message) file_object.seek(-16, os.SEEK_CUR) self._ReadFileFooter(file_object) file_object.seek(-4, os.SEEK_CUR) break first_guid_checked = True file_offset += 16 remaining_file_size -= 16 lnk_file_object = data_range.DataRange( file_object, data_offset=file_offset, data_size=remaining_file_size) lnk_file_entry = self._ReadLNKFile(lnk_file_object) if lnk_file_entry: self.entries.append(lnk_file_entry) file_offset += lnk_file_entry.data_size remaining_file_size -= lnk_file_entry.data_size file_object.seek(file_offset, os.SEEK_SET)
def HashFileEntries(self): """Hashes the file entries stored in the CPIO archive file.""" stat_object = os.stat(self._path) file_object = open(self._path, 'rb') file_offset = 0 file_size = stat_object.st_size # initrd files can consist of an uncompressed and compressed cpio archive. # Keeping the functionality in this script for now, but this likely # needs to be in a separate initrd hashing script. while file_offset < stat_object.st_size: file_object.seek(file_offset, os.SEEK_SET) signature_data = file_object.read(6) file_type = None if len(signature_data) > 2: if (signature_data[:2] in (self._CPIO_SIGNATURE_BINARY_BIG_ENDIAN, self._CPIO_SIGNATURE_BINARY_LITTLE_ENDIAN) or signature_data in (self._CPIO_SIGNATURE_PORTABLE_ASCII, self._CPIO_SIGNATURE_NEW_ASCII, self._CPIO_SIGNATURE_NEW_ASCII_WITH_CHECKSUM)): file_type = 'cpio' elif signature_data[:2] == self._GZIP_SIGNATURE: file_type = 'gzip' elif signature_data[:2] == self._BZIP_SIGNATURE: file_type = 'bzip' elif signature_data == self._XZ_SIGNATURE: file_type = 'xz' if not file_type: self._output_writer.WriteText( 'Unsupported file type at offset: 0x{0:08x}.\n'.format( file_offset)) return if file_type == 'cpio': file_object.seek(file_offset, os.SEEK_SET) cpio_file_object = file_object elif file_type in ('bzip', 'gzip', 'xz'): compressed_data_size = file_size - file_offset compressed_data_file_object = data_range.DataRange( file_object, data_offset=file_offset, data_size=compressed_data_size) if file_type == 'bzip': cpio_file_object = bz2.BZ2File(compressed_data_file_object) elif file_type == 'gzip': cpio_file_object = gzip.GzipFile( fileobj=compressed_data_file_object) # pylint: disable=no-member elif file_type == 'xz' and lzma: cpio_file_object = lzma.LZMAFile( compressed_data_file_object) cpio_archive_file = cpio.CPIOArchiveFile(debug=self._debug) cpio_archive_file.ReadFileObject(cpio_file_object) for file_entry in sorted(cpio_archive_file.GetFileEntries()): if file_entry.data_size == 0: continue sha256_context = hashlib.sha256() file_data = file_entry.read(4096) while file_data: sha256_context.update(file_data) file_data = file_entry.read(4096) self._output_writer.WriteText('{0:s}\t{1:s}\n'.format( sha256_context.hexdigest(), file_entry.path)) file_offset += cpio_archive_file.size padding_size = file_offset % 16 if padding_size > 0: file_offset += 16 - padding_size cpio_archive_file.Close()