Exemple #1
0
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
Exemple #2
0
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'
Exemple #3
0
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''
Exemple #4
0
    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()