def __determine_file_extension(parsed_pe_file: pefile.PE) -> str: if parsed_pe_file.is_dll(): return 'dll' if parsed_pe_file.is_driver(): return 'sys' if parsed_pe_file.is_exe(): return 'exe' else: return 'bin'
def unpack(self, data): cursor = 0 mv = memoryview(data) while True: offset = data.find(B'MZ', cursor) if offset < cursor: break cursor = offset + 2 ntoffset = mv[offset + 0x3C:offset + 0x3E] if len(ntoffset) < 2: return ntoffset, = unpack('H', ntoffset) if mv[offset + ntoffset:offset + ntoffset + 2] != B'PE': self.log_debug( F'invalid NT header signature for candidate at 0x{offset:08X}' ) continue try: pe = PE(data=data[offset:], fast_load=True) except PEFormatError as err: self.log_debug( F'parsing of PE header at 0x{offset:08X} failed:', err) continue pesize = get_pe_size(pe, memdump=self.args.memdump) pedata = mv[offset:offset + pesize] info = {} if self.args.fileinfo: try: info = pemeta().parse_version(pe) or {} except Exception as error: self.log_warn( F'Unable to obtain file information: {error!s}') try: path = info['OriginalFilename'] except KeyError: extension = 'exe' if pe.is_exe() else 'dll' if pe.is_dll( ) else 'sys' path = F'carve-0x{offset:08X}.{extension}' if offset > 0 or self.args.keep_root: yield UnpackResult(path, pedata, offset=offset) self.log_info( F'extracted PE file of size 0x{pesize:08X} from 0x{offset:08X}' ) else: self.log_info( F'ignored root file of size 0x{pesize:08X} from 0x{offset:08X}' ) continue if not offset or self.args.recursive: cursor += pe.OPTIONAL_HEADER.SizeOfHeaders else: cursor += pesize