Esempio n. 1
0
class MemWorker(object):
    def __init__(self, process_name, end_offset=None, start_offset=None):
        logger.info('opening process %s ...' % process_name)
        self.process = Process()
        self.process.open_debug_from_name(process_name)
        si = self.process.GetSystemInfo()
        if end_offset:
            self.end_offset = end_offset
        else:
            self.end_offset = si.lpMaximumApplicationAddress
        if start_offset:
            self.start_offset = start_offset
        else:
            self.start_offset = si.lpMinimumApplicationAddress

    def Address(self, value, default_type='uint'):
        """ wrapper to instanciate an Address class for the memworker.process"""
        return Address(value, process=self.process, default_type=default_type)

    def get_process(self):
        return self.process

    def search_address(self, address):
        address = int(address)
        for m in self.process.list_modules():
            for addr in self.mem_search(address,
                                        ftype='ulong',
                                        start_offset=m.modBaseAddr,
                                        end_offset=m.modBaseSize):
                logger.debug('found module %s => addr %s' % (m.szModule, addr))

    def umem_replace(self, regex, replace):
        """ like search_replace_mem but works with unicode strings """
        regex = utils.re_to_unicode(regex)
        replace = replace.encode('utf-16-le')
        return self.mem_replace(re.compile(regex, re.UNICODE), replace)

    def mem_replace(self, regex, replace):
        """ search memory for a pattern and replace all found occurrences """
        allWritesSucceed = True
        for start_offset in self.mem_search(regex, ftype='re'):
            if self.process.write_bytes(start_offset, replace) == 1:
                logger.debug('Write at offset %s succeeded !' % start_offset)
            else:
                allWritesSucceed = False
                logger.debug('Write at offset %s failed !' % start_offset)

        return allWritesSucceed

    def umem_search(self, regex):
        """ like mem_search but works with unicode strings """
        regex = utils.re_to_unicode(regex)
        for i in self.mem_search(str(regex), ftype='re'):
            yield i

    def group_search(self, group, start_offset=None, end_offset=None):
        regex = ''
        for value, type in group:
            if type == 'f' or type == 'float':
                f = struct.pack('<f', float(value))
                regex += '..' + f[2:4]
            else:
                raise NotImplementedError('unknown type %s' % type)

        return self.mem_search(regex,
                               ftype='re',
                               start_offset=start_offset,
                               end_offset=end_offset)

    def search_address(self, addr):
        a = '%08X' % addr
        logger.debug('searching address %s' % a)
        regex = ''
        for i in range(len(a) - 2, -1, -2):
            regex += binascii.unhexlify(a[i:i + 2])

        return self.mem_search(re.escape(regex), ftype='re')

    def mem_search(self,
                   value,
                   ftype='match',
                   protec=PAGE_READWRITE | PAGE_READONLY,
                   start_offset=None,
                   end_offset=None):
        """ 
                iterator returning all indexes where the pattern has been found
        """
        ftype = ftype.lower().strip()
        if type(value) is list:
            ftype = 'group'
        if ftype == 're':
            if type(value) is str:
                regex = re.compile(value)
            else:
                regex = value
        if start_offset is None:
            offset = self.start_offset
        else:
            offset = start_offset
        if end_offset is None:
            end_offset = self.end_offset
        if ftype == 'float':
            structtype, structlen = utils.type_unpack(ftype)
        elif ftype != 'match' and ftype != 'group' and ftype != 're':
            structtype, structlen = utils.type_unpack(ftype)
            value = struct.pack(structtype, value)
        while True:
            if offset >= end_offset:
                break
            totalread = 0
            mbi = self.process.VirtualQueryEx(offset)
            offset = mbi.BaseAddress
            chunk = mbi.RegionSize
            protect = mbi.Protect
            state = mbi.State
            if state & MEM_FREE or state & MEM_RESERVE:
                offset += chunk
                continue
            if protec:
                if not protect & protec or protect & PAGE_NOCACHE or protect & PAGE_WRITECOMBINE or protect & PAGE_GUARD:
                    offset += chunk
                    continue
            b = ''
            #b = self.process.read_bytes(offset, chunk)

            try:
                b = self.process.read_bytes(offset, chunk)
                totalread = len(b)
            except Exception as e:
                #print(e)
                offset += chunk
                continue

            if b:
                if ftype == 're':
                    duplicates_cache = set()
                    for res in regex.findall(b):
                        index = b.find(res)
                        while index != -1:
                            soffset = offset + index
                            if soffset not in duplicates_cache:
                                duplicates_cache.add(soffset)
                                yield self.Address(soffset, 'bytes')
                            index = b.find(res, index + len(res))

                elif ftype == 'float':
                    for index in range(0, len(b)):
                        try:
                            tmpval = struct.unpack(structtype,
                                                   b[index:index + 4])[0]
                            if int(value) == int(tmpval):
                                soffset = offset + index
                                yield self.Address(soffset, 'float')
                        except Exception as e:
                            print(e)

                else:
                    index = b.find(value)
                    while index != -1:
                        soffset = offset + index
                        yield self.Address(soffset, 'bytes')
                        index = b.find(value, index + 1)

            offset += totalread