def test_read(): f = BlobIO(b'test' * 1000) assert f.read(6) == b'testte' assert f.tell() == 6 assert f.read(6) == b'sttest' assert f.tell() == 12
def test_read_all(): f = BlobIO(b'test' * 3) assert f.read() == b'testtesttest' assert f.tell() == 12 assert f.read() == b'' f.seek(6) assert f.read() == b'sttest'
def test_out_of_bounds_read(): f = BlobIO(b'test' * 1000) f.seek(3998) assert f.read(10) == b'st' assert f.tell() == 4000 assert f.read(10) == b'' assert f.tell() == 4000 f.seek(5000) assert f.read(10) == b''
def __init__(self, blob, verify_checksum=False): pe_offs, = _read(blob[0x3c:], '<H') fin = BlobIO(blob[pe_offs:]) sig = fin.read(4) if sig != b'PE\0\0': raise RuntimeError('Not a PE file: PE signature is missing.') hdr = _IMAGE_FILE_HEADER.unpack_from_io(fin) opt_sig, = struct.unpack('<H', fin.read(2)) if opt_sig == IMAGE_NT_OPTIONAL_HDR32_MAGIC: opt = _IMAGE_OPTIONAL_HEADER32.unpack_from_io(fin) opt.sig = opt_sig elif opt_sig == IMAGE_NT_OPTIONAL_HDR64_MAGIC: opt = _IMAGE_OPTIONAL_HEADER64.unpack_from_io(fin) opt.sig = opt_sig else: raise RuntimeError('Unknown optional header type.') self._checksum_offs = pe_offs + 4 + _IMAGE_FILE_HEADER.size + 4 * 16 if verify_checksum: if opt.CheckSum == 0: self.checksum_correct = False else: real_checksum = pe_checksum( rope(blob[:self._checksum_offs], b'\0\0\0\0', blob[self._checksum_offs + 4:])) self.checksum_correct = real_checksum == opt.CheckSum if opt.FileAlignment == 0: raise RuntimeError( 'IMAGE_OPTIONAL_HEADER.FileAlignment must be nonzero') dds = [ _IMAGE_DATA_DIRECTORY.unpack_from_io(fin) for dd_idx in range(opt.NumberOfRvaAndSizes) ] def make_pe_section(idx, hdr): name = hdr.Name.rstrip(b'\0') if hdr.PointerToRawData % opt.FileAlignment != 0: raise RuntimeError('Section {}@{} is misaligned ({})'.format( name, idx, hdr.PointerToRawData)) if hdr.SizeOfRawData % opt.FileAlignment != 0: raise RuntimeError( 'Size of section {}@{} is misaligned ({})'.format( name, idx, hdr.SizeOfRawData)) if hdr.PointerToRawData == 0: data = None else: data = blob[hdr.PointerToRawData:hdr.PointerToRawData + hdr.SizeOfRawData] return _PeSection(hdr, data) sections = [ make_pe_section(sec_idx, _IMAGE_SECTION_HEADER.unpack_from_io(fin)) for sec_idx in range(hdr.NumberOfSections) ] present_secs = sorted( (sec for sec in sections if sec.hdr.SizeOfRawData != 0), key=lambda sec: sec.hdr.PointerToRawData) if not present_secs: raise RuntimeError('no present sections') i = 1 while i < len(present_secs): if present_secs[i - 1].hdr.PointerToRawData + present_secs[ i - 1].hdr.SizeOfRawData != present_secs[ i].hdr.PointerToRawData: raise RuntimeError('there are holes between sections') i += 1 last_sec = present_secs[-1] end_of_image = last_sec.hdr.PointerToRawData + last_sec.hdr.SizeOfRawData self._blob = blob self._dos_stub = blob[:pe_offs] self._file_header = hdr self._opt_header = opt self._data_directories = dds self._sections = sections self._trailer_offset = end_of_image self._trailer = blob[end_of_image:] self._check_vm_overlaps()