Пример #1
0
    def read_bytes(self, address, bytes = 4, use_NtWow64ReadVirtualMemory64=False):
        #print "reading %s bytes from addr %s"%(bytes, address)
        if use_NtWow64ReadVirtualMemory64:
            if NtWow64ReadVirtualMemory64 is None:
                raise WindowsError("NtWow64ReadVirtualMemory64 is not available from a 64bit process")
            RpM = NtWow64ReadVirtualMemory64
        else:
            RpM = ReadProcessMemory

        address = int(address)
        buffer = create_string_buffer(bytes)
        bytesread = c_size_t(0)
        data = ''
        length = bytes
        while length:
            if RpM(self.h_process, address, buffer, bytes, byref(bytesread)) or (use_NtWow64ReadVirtualMemory64 and GetLastError() == 0):
                if bytesread.value:
                    data += buffer.raw[:bytesread.value]
                    length -= bytesread.value
                    address += bytesread.value
                if not len(data):
                    raise ProcessException('Error %s in ReadProcessMemory(%08x, %d, read=%d)' % (GetLastError(),
                     address,
                     length,
                     bytesread.value))
                return data
            else:
                if GetLastError()==299: #only part of ReadProcessMemory has been done, let's return it
                    data += buffer.raw[:bytesread.value]
                    return data
                raise WinError()
            # data += buffer.raw[:bytesread.value]
            # length -= bytesread.value
            # address += bytesread.value
        return data
Пример #2
0
 def _open(self):
     self.isProcessOpen = True
     self.task = ctypes.c_uint32()
     self.mytask = libc.mach_task_self()
     ret = libc.task_for_pid(self.mytask, ctypes.c_int(self.pid),
                             ctypes.pointer(self.task))
     if ret != 0:
         raise ProcessException("task_for_pid failed with error code : %s" %
                                ret)
Пример #3
0
    def iter_region(self,
                    start_offset=None,
                    end_offset=None,
                    protec=None,
                    optimizations=None):
        """
            optimizations :
                i for inode==0 (no file mapping)
                s to avoid scanning shared regions
                x to avoid scanning x regions
                r don't scan ronly regions
        """
        maps = []
        address = ctypes.c_ulong(0)
        mapsize = ctypes.c_ulong(0)
        name = ctypes.c_uint32(0)
        count = ctypes.c_uint32(VM_REGION_BASIC_INFO_COUNT_64)
        info = vm_region_basic_info_64()

        while True:
            r = libc.mach_vm_region(self.task, ctypes.pointer(address),
                                    ctypes.pointer(mapsize),
                                    VM_REGION_BASIC_INFO_64,
                                    ctypes.pointer(info),
                                    ctypes.pointer(count),
                                    ctypes.pointer(name))
            # If we get told "invalid address", we have crossed into kernel land...
            if r == 1:
                break

            if r != 0:
                raise ProcessException(
                    'mach_vm_region failed with error code %s' % r)
            if start_offset is not None:
                if address.value < start_offset:
                    address.value += mapsize.value
                    continue
            if end_offset is not None:
                if address.value > end_offset:
                    break
            p = info.protection
            if p & VM_PROT_EXECUTE:
                if optimizations and 'x' in optimizations:
                    address.value += mapsize.value
                    continue
            if info.shared:
                if optimizations and 's' in optimizations:
                    address.value += mapsize.value
                    continue
            if p & VM_PROT_READ:
                if not (p & VM_PROT_WRITE):
                    if optimizations and 'r' in optimizations:
                        address.value += mapsize.value
                        continue
                yield address.value, mapsize.value

            address.value += mapsize.value
Пример #4
0
 def _open_from_name(self, processName, debug=False):
     processes = self.processes_from_name(processName)
     if not processes:
         raise ProcessException("can't get pid from name %s" % processName)
     elif len(processes)>1:
         raise ValueError("There is multiple processes with name %s. Please select a process from its pid instead"%processName)
     if debug:
         self._open(processes[0]["pid"], debug=True)
     else:
         self._open(processes[0]["pid"], debug=False)
Пример #5
0
 def pid_from_name(name):
     #quick and dirty, works with all linux not depending on ps output
     for pid in os.listdir("/proc"):
         try:
             int(pid)
         except:
             continue
         pname = ""
         with open("/proc/%s/cmdline" % pid, 'r') as f:
             pname = f.read()
         if name in pname:
             return int(pid)
     raise ProcessException("No process with such name: %s" % name)
Пример #6
0
    def pid_from_name(name):
        processes = []
        for pid in os.listdir('/proc'):
            try:
                pid = int(pid)
                pname, cmdline = SunProcess._name_args(pid)
                if name in pname:
                    return pid
                if name in cmdline.split(' ', 1)[0]:
                    return pid
            except:
                pass

        raise ProcessException('No process with such name: %s' % name)
Пример #7
0
    def read_bytes(self, address, bytes=4):
        pdata = ctypes.c_void_p(0)
        data_cnt = ctypes.c_uint32(0)

        ret = libc.mach_vm_read(self.task, ctypes.c_ulonglong(address),
                                ctypes.c_longlong(bytes),
                                ctypes.pointer(pdata),
                                ctypes.pointer(data_cnt))
        #if ret==1:
        #    return ""
        if ret != 0:
            raise ProcessException("mach_vm_read returned : %s" % ret)
        buf = ctypes.string_at(pdata.value, data_cnt.value)
        libc.vm_deallocate(self.mytask, pdata, data_cnt)
        return buf
Пример #8
0
    def write_bytes(self, address, data):
        address = int(address)
        if not self.isProcessOpen:
            raise ProcessException("Can't write_bytes(%s, %s), process %s is not open" % (address, data, self.pid))
        buffer = create_string_buffer(data)
        sizeWriten = c_size_t(0)
        bufferSize = sizeof(buffer) - 1
        _address = address
        _length = bufferSize + 1
        try:
            old_protect = self.VirtualProtectEx(_address, _length, PAGE_EXECUTE_READWRITE)
        except:
            pass

        res = kernel32.WriteProcessMemory(self.h_process, address, buffer, bufferSize, byref(sizeWriten))
        try:
            self.VirtualProtectEx(_address, _length, old_protect)
        except:
            pass

        return res
Пример #9
0
 def VirtualProtectEx(self, base_address, size, protection):
     old_protect = c_ulong(0)
     if not kernel32.VirtualProtectEx(self.h_process, base_address, size, protection, byref(old_protect)):
         raise ProcessException('Error: VirtualProtectEx(%08X, %d, %08X)' % (base_address, size, protection))
     return old_protect.value
Пример #10
0
 def VirtualQueryEx64(self, lpAddress):
     mbi = MEMORY_BASIC_INFORMATION64()
     if not VirtualQueryEx64(self.h_process, lpAddress, byref(mbi), sizeof(mbi)):
         raise ProcessException('Error VirtualQueryEx: 0x%08X' % lpAddress)
     return mbi
Пример #11
0
    def mem_search(self,
                   value,
                   ftype='match',
                   protec=PAGE_READWRITE | PAGE_READONLY,
                   optimizations=None,
                   start_offset=None,
                   end_offset=None):
        """ 
                iterator returning all indexes where the pattern has been found
        """

        # pre-compile regex to run faster
        if ftype == 're' or ftype == 'groups' or ftype == 'ngroups':

            # value should be an array of regex
            if type(value) is not list:
                value = [value]

            tmp = []
            for reg in value:
                if type(reg) is tuple:
                    name = reg[0]
                    if type(reg[1]) != REGEX_TYPE:
                        regex = re.compile(reg[1], re.IGNORECASE)
                    else:
                        regex = reg[1]
                elif type(reg) == REGEX_TYPE:
                    name = ''
                    regex = reg
                else:
                    name = ''
                    regex = re.compile(reg, re.IGNORECASE)

                tmp.append((name, regex))
            value = tmp

        elif ftype != 'match' and ftype != 'group' and ftype != 're' and ftype != 'groups' and ftype != 'ngroups' and ftype != 'lambda':
            structtype, structlen = utils.type_unpack(ftype)
            value = struct.pack(structtype, value)

        # different functions avoid if statement before parsing the buffer
        if ftype == 're':
            func = self.parse_re_function

        elif ftype == 'groups':
            func = self.parse_groups_function

        elif ftype == 'ngroups':
            func = self.parse_named_groups_function

        elif ftype == 'float':
            func = self.parse_float_function
        elif ftype == 'lambda':  # use a custm function
            func = value
        else:
            func = self.parse_any_function

        if not self.process.isProcessOpen:
            raise ProcessException("Can't read_bytes, process %s is not open" %
                                   (self.process.pid))

        for offset, chunk_size in self.process.iter_region(
                start_offset=start_offset,
                end_offset=end_offset,
                protec=protec,
                optimizations=optimizations):
            b = ''
            current_offset = offset
            chunk_read = 0
            chunk_exc = False
            while chunk_read < chunk_size:
                try:
                    b += self.process.read_bytes(current_offset, chunk_size)
                except IOError as e:
                    print traceback.format_exc()
                    if e.errno == 13:
                        raise
                    else:
                        logger.warning(e)
                    chunk_exc = True
                    break
                except Exception as e:
                    logger.warning(e)
                    chunk_exc = True
                    break
                finally:
                    current_offset += chunk_size
                    chunk_read += chunk_size

            if chunk_exc:
                continue

            if b:
                if ftype == "lambda":
                    for res in func(b, offset):
                        yield res
                else:
                    for res in func(b, value, offset):
                        yield res