예제 #1
0
 def write_memory(self, addr, data):
     """Write `data` at `addr`"""
     if windows.current_process.bitness == 32 and self.bitness == 64:
         if not winproxy.is_implemented(winproxy.NtWow64WriteVirtualMemory64):
             raise ValueError("NtWow64WriteVirtualMemory64 non available in ntdll: cannot write into 64bits processus")
         return winproxy.NtWow64WriteVirtualMemory64(self.handle, addr, data, len(data))
     return winproxy.WriteProcessMemory(self.handle, addr, lpBuffer=data)
예제 #2
0
 def write_memory(self, addr, data):
     """Write `data` at `addr`"""
     if windows.current_process.bitness == 32 and self.bitness == 64:
         if not winproxy.is_implemented(winproxy.NtWow64WriteVirtualMemory64):
             raise ValueError("NtWow64WriteVirtualMemory64 non available in ntdll: cannot write into 64bits processus")
         return winproxy.NtWow64WriteVirtualMemory64(self.handle, addr, data, len(data))
     return winproxy.WriteProcessMemory(self.handle, addr, lpBuffer=data)
예제 #3
0
 def low_read_memory(self, addr, buffer_addr, size):
     if windows.current_process.bitness == 32 and self.bitness == 64:
         # OptionalExport can be None (see winproxy.py)
         if not winproxy.is_implemented(winproxy.NtWow64ReadVirtualMemory64):
             raise ValueError("NtWow64ReadVirtualMemory64 non available in ntdll: cannot read into 64bits processus")
         return winproxy.NtWow64ReadVirtualMemory64(self.handle, addr, buffer_addr, size)
     #if self.is_wow_64 and addr > 0xffffffff:
     #    return winproxy.NtWow64ReadVirtualMemory64(self.handle, addr, buffer_addr, size)
     return winproxy.ReadProcessMemory(self.handle, addr, lpBuffer=buffer_addr, nSize=size)
예제 #4
0
 def low_read_memory(self, addr, buffer_addr, size):
     if windows.current_process.bitness == 32 and self.bitness == 64:
         # OptionalExport can be None (see winproxy.py)
         if not winproxy.is_implemented(winproxy.NtWow64ReadVirtualMemory64):
             raise ValueError("NtWow64ReadVirtualMemory64 non available in ntdll: cannot read into 64bits processus")
         return winproxy.NtWow64ReadVirtualMemory64(self.handle, addr, buffer_addr, size)
     #if self.is_wow_64 and addr > 0xffffffff:
     #    return winproxy.NtWow64ReadVirtualMemory64(self.handle, addr, buffer_addr, size)
     return winproxy.ReadProcessMemory(self.handle, addr, lpBuffer=buffer_addr, nSize=size)
예제 #5
0
class WinThread(THREADENTRY32, AutoHandle):
    """Represent a thread """
    @utils.fixedpropety
    def tid(self):
        """Thread ID

        :type: :class:`int`"""
        return self.th32ThreadID

    @utils.fixedpropety
    def owner(self):
        """The Process owning the thread

        :type: :class:`WinProcess`
		"""
        if hasattr(self, "_owner"):
            return self._owner
        try:
            self._owner = [process for process in windows.system.processes if process.pid == self.th32OwnerProcessID][0]
        except IndexError:
            return None
        return self._owner

    @property
    def context(self):
        """The context of the thread, type depend of the target process.

        :type: :class:`windows.exception.ECONTEXT32` or  :class:`windows.exception.ECONTEXT64` or :class:`windows.exception.ECONTEXTWOW64`
		"""
        if self.owner.bitness == 32 and windows.current_process.bitness == 64:
            # Wow64
            x = exception.ECONTEXTWOW64()
            x.ContextFlags = CONTEXT_ALL
            winproxy.Wow64GetThreadContext(self.handle, x)
            return x

        if self.owner.bitness == 64 and windows.current_process.bitness == 32:
            x = exception.ECONTEXT64.new_aligned()
            x.ContextFlags = CONTEXT_ALL
            windows.syswow64.NtGetContextThread_32_to_64(self.handle, x)
            return x

        if self.owner.bitness == 32:
            x = exception.ECONTEXT32()
        else:
            x = exception.ECONTEXT64.new_aligned()
        x.ContextFlags = CONTEXT_ALL
        winproxy.GetThreadContext(self.handle, x)
        return x

    @property
    def context_syswow(self):
        """The 64 bits context of a syswow thread.

        :type:  :class:`windows.exception.ECONTEXT64`
		"""
        if not self.owner.is_wow_64:
            raise ValueError("Not a syswow process")
        x = exception.ECONTEXT64.new_aligned()
        x.ContextFlags = CONTEXT_ALL
        if windows.current_process.bitness == 64:
            winproxy.GetThreadContext(self.handle, x)
        else:
            windows.syswow64.NtGetContextThread_32_to_64(self.handle, x)
        return x


    def set_context(self, context):
        """Set the thread's context to ``context``"""
        if self.owner.bitness == windows.current_process.bitness:
            return winproxy.SetThreadContext(self.handle, context)
        if windows.current_process.bitness == 64 and self.owner.bitness == 32:
            return winproxy.Wow64SetThreadContext(self.handle, context)
        return windows.syswow64.NtSetContextThread_32_to_64(self.handle, ctypes.byref(context))


    def set_syswow_context(self, context):
        """Set a syswow thread's 64 context to ``context``"""
        if not self.owner.is_wow_64:
            raise ValueError("Not a syswow process")
        if windows.current_process.bitness == 64:
            return winproxy.SetThreadContext(self.handle, context)
        return windows.syswow64.NtSetContextThread_32_to_64(self.handle, ctypes.byref(context))


    @property
    def start_address(self):
        """The start address of the thread

            :type: :class:`int`
		"""
        if windows.current_process.bitness == 32 and self.owner.bitness == 64:
            res = ULONGLONG()
            windows.syswow64.NtQueryInformationThread_32_to_64(self.handle, ThreadQuerySetWin32StartAddress, byref(res), ctypes.sizeof(res))
            return res.value
        res_size = max(self.owner.bitness, windows.current_process.bitness)
        if res_size == 32:
            res = ULONG()
        else:
            res = ULONGLONG()
        winproxy.NtQueryInformationThread(self.handle, ThreadQuerySetWin32StartAddress, byref(res), ctypes.sizeof(res))
        return res.value

    @property
    def teb_base(self):
        """The address of the thread's TEB

            :type: :class:`int`
		"""
        if windows.current_process.bitness == 32 and self.owner.bitness == 64:
            restype = rctypes.transform_type_to_remote64bits(THREAD_BASIC_INFORMATION)
            ressize = (ctypes.sizeof(restype))
            # Manual aligned allocation :DDDD
            nb_qword = (ressize + 8) / ctypes.sizeof(ULONGLONG)
            buffer = (nb_qword * ULONGLONG)()
            struct_address = ctypes.addressof(buffer)
            if (struct_address & 0xf) not in [0, 8]:
                raise ValueError("ULONGLONG array not aligned on 8")
            windows.syswow64.NtQueryInformationThread_32_to_64(self.handle, ThreadBasicInformation, struct_address, ressize)
            return restype(struct_address, windows.current_process).TebBaseAddress

        res = THREAD_BASIC_INFORMATION()
        windows.winproxy.NtQueryInformationThread(self.handle, ThreadBasicInformation, byref(res), ctypes.sizeof(res))
        return res.TebBaseAddress

    def exit(self, code=0):
        """Exit the thread"""
        return winproxy.TerminateThread(self.handle, code)

    def resume(self):
        """Resume the thread"""
        return winproxy.ResumeThread(self.handle)

    def suspend(self):
        """Suspend the thread"""
        return winproxy.SuspendThread(self.handle)

    def _get_handle(self):
        return winproxy.OpenThread(dwThreadId=self.tid)

    @property
    def is_exit(self):
        """``True`` if the thread is terminated

        :type: :class:`bool`
		"""
        return self.exit_code != STILL_ACTIVE

    @property
    def exit_code(self):
        """The exit code of the thread : ``STILL_ACTIVE`` means the process is not dead

        :type: :class:`int`
		"""
        res = DWORD()
        winproxy.GetExitCodeThread(self.handle, byref(res))
        return res.value

    def __repr__(self):
        owner = self.owner
        if owner is None:
            owner_name = "<Dead process with pid {0}>".format(hex(self.th32OwnerProcessID))
        else:
            owner_name = owner.name
        return '<{0} {1} owner "{2}" at {3}>'.format(self.__class__.__name__, self.tid, owner_name, hex(id(self)))

    @staticmethod
    def _from_handle(handle):
        tid = WinThread._get_thread_id(handle)
        try:
            # Really useful ?
            thread = [t for t in windows.winobject.system.System().threads if t.tid == tid][0]
            # set AutoHandle _handle
            thread._handle = handle
            dbgprint("Thread {0} from handle {1}".format(thread, hex(handle)), "HANDLE")
            return thread
        except IndexError:
            dbgprint("DeadThread from handle {0}".format(hex(handle)), "HANDLE")
            return DeadThread(handle, tid)

    @staticmethod
    def _get_thread_id_by_api(handle):
        return winproxy.GetThreadId(handle)

    @staticmethod
    def _get_thread_id_manual(handle):
        if windows.current_process.bitness == 32 and self.owner.bitness == 64:
            raise NotImplementedError("[_get_thread_id_manual] 32 -> 64 (XP64 bits + Syswow process ?)")
        res = THREAD_BASIC_INFORMATION()
        windows.winproxy.NtQueryInformationThread(hand, ThreadBasicInformation, byref(res), ctypes.sizeof(res))
        id2 = res.ClientId.UniqueThread
        return id2

    if winproxy.is_implemented(winproxy.GetThreadId):
        _get_thread_id = _get_thread_id_by_api
    else:
        _get_thread_id = _get_thread_id_manual