1#!~/.wine/drive_c/Python25/python.exe
2# -*- coding: utf-8 -*-
3
4# Copyright (c) 2009-2014, Mario Vilas
5# All rights reserved.
6#
7# Redistribution and use in source and binary forms, with or without
8# modification, are permitted provided that the following conditions are met:
9#
10#     * Redistributions of source code must retain the above copyright notice,
11#       this list of conditions and the following disclaimer.
12#     * Redistributions in binary form must reproduce the above copyright
13#       notice,this list of conditions and the following disclaimer in the
14#       documentation and/or other materials provided with the distribution.
15#     * Neither the name of the copyright holder nor the names of its
16#       contributors may be used to endorse or promote products derived from
17#       this software without specific prior written permission.
18#
19# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29# POSSIBILITY OF SUCH DAMAGE.
30
31"""
32Process instrumentation.
33
34@group Instrumentation:
35    Process
36"""
37
38from __future__ import with_statement
39
40# FIXME
41# I've been told the host process for the latest versions of VMWare
42# can't be instrumented, because they try to stop code injection into the VMs.
43# The solution appears to be to run the debugger from a user account that
44# belongs to the VMware group. I haven't confirmed this yet.
45
46__revision__ = "$Id$"
47
48__all__ = ['Process']
49
50import sys
51from winappdbg import win32
52from winappdbg import compat
53from winappdbg.textio import HexDump, HexInput
54from winappdbg.util import Regenerator, PathOperations, MemoryAddresses
55from winappdbg.module import Module, _ModuleContainer
56from winappdbg.thread import Thread, _ThreadContainer
57from winappdbg.window import Window
58from winappdbg.search import Search, \
59                   Pattern, BytePattern, TextPattern, RegExpPattern, HexPattern
60from winappdbg.disasm import Disassembler
61
62import re
63import os
64import os.path
65import ctypes
66import struct
67import warnings
68import traceback
69
70# delayed import
71System = None
72
73#==============================================================================
74
75# TODO
76# * Remote GetLastError()
77# * The memory operation methods do not take into account that code breakpoints
78#   change the memory. This object should talk to BreakpointContainer to
79#   retrieve the original memory contents where code breakpoints are enabled.
80# * A memory cache could be implemented here.
81
82class Process (_ThreadContainer, _ModuleContainer):
83    """
84    Interface to a process. Contains threads and modules snapshots.
85
86    @group Properties:
87        get_pid, is_alive, is_debugged, is_wow64, get_arch, get_bits,
88        get_filename, get_exit_code,
89        get_start_time, get_exit_time, get_running_time,
90        get_services, get_dep_policy, get_peb, get_peb_address,
91        get_entry_point, get_main_module, get_image_base, get_image_name,
92        get_command_line, get_environment,
93        get_command_line_block,
94        get_environment_block, get_environment_variables,
95        get_handle, open_handle, close_handle
96
97    @group Instrumentation:
98        kill, wait, suspend, resume, inject_code, inject_dll, clean_exit
99
100    @group Disassembly:
101        disassemble, disassemble_around, disassemble_around_pc,
102        disassemble_string, disassemble_instruction, disassemble_current
103
104    @group Debugging:
105        flush_instruction_cache, debug_break, peek_pointers_in_data
106
107    @group Memory mapping:
108        take_memory_snapshot, generate_memory_snapshot, iter_memory_snapshot,
109        restore_memory_snapshot, get_memory_map, get_mapped_filenames,
110        generate_memory_map, iter_memory_map,
111        is_pointer, is_address_valid, is_address_free, is_address_reserved,
112        is_address_commited, is_address_guard, is_address_readable,
113        is_address_writeable, is_address_copy_on_write, is_address_executable,
114        is_address_executable_and_writeable,
115        is_buffer,
116        is_buffer_readable, is_buffer_writeable, is_buffer_executable,
117        is_buffer_executable_and_writeable, is_buffer_copy_on_write
118
119    @group Memory allocation:
120        malloc, free, mprotect, mquery
121
122    @group Memory read:
123        read, read_char, read_int, read_uint, read_float, read_double,
124        read_dword, read_qword, read_pointer, read_string, read_structure,
125        peek, peek_char, peek_int, peek_uint, peek_float, peek_double,
126        peek_dword, peek_qword, peek_pointer, peek_string
127
128    @group Memory write:
129        write, write_char, write_int, write_uint, write_float, write_double,
130        write_dword, write_qword, write_pointer,
131        poke, poke_char, poke_int, poke_uint, poke_float, poke_double,
132        poke_dword, poke_qword, poke_pointer
133
134    @group Memory search:
135        search, search_bytes, search_hexa, search_text, search_regexp, strings
136
137    @group Processes snapshot:
138        scan, clear, __contains__, __iter__, __len__
139
140    @group Deprecated:
141        get_environment_data, parse_environment_data
142
143    @type dwProcessId: int
144    @ivar dwProcessId: Global process ID. Use L{get_pid} instead.
145
146    @type hProcess: L{ProcessHandle}
147    @ivar hProcess: Handle to the process. Use L{get_handle} instead.
148
149    @type fileName: str
150    @ivar fileName: Filename of the main module. Use L{get_filename} instead.
151    """
152
153    def __init__(self, dwProcessId, hProcess = None, fileName = None):
154        """
155        @type  dwProcessId: int
156        @param dwProcessId: Global process ID.
157
158        @type  hProcess: L{ProcessHandle}
159        @param hProcess: Handle to the process.
160
161        @type  fileName: str
162        @param fileName: (Optional) Filename of the main module.
163        """
164        _ThreadContainer.__init__(self)
165        _ModuleContainer.__init__(self)
166
167        self.dwProcessId = dwProcessId
168        self.hProcess    = hProcess
169        self.fileName    = fileName
170
171    def get_pid(self):
172        """
173        @rtype:  int
174        @return: Process global ID.
175        """
176        return self.dwProcessId
177
178    def get_filename(self):
179        """
180        @rtype:  str
181        @return: Filename of the main module of the process.
182        """
183        if not self.fileName:
184            self.fileName = self.get_image_name()
185        return self.fileName
186
187    def open_handle(self, dwDesiredAccess = win32.PROCESS_ALL_ACCESS):
188        """
189        Opens a new handle to the process.
190
191        The new handle is stored in the L{hProcess} property.
192
193        @warn: Normally you should call L{get_handle} instead, since it's much
194            "smarter" and tries to reuse handles and merge access rights.
195
196        @type  dwDesiredAccess: int
197        @param dwDesiredAccess: Desired access rights.
198            Defaults to L{win32.PROCESS_ALL_ACCESS}.
199            See: U{http://msdn.microsoft.com/en-us/library/windows/desktop/ms684880(v=vs.85).aspx}
200
201        @raise WindowsError: It's not possible to open a handle to the process
202            with the requested access rights. This tipically happens because
203            the target process is a system process and the debugger is not
204            runnning with administrative rights.
205        """
206        hProcess = win32.OpenProcess(dwDesiredAccess, win32.FALSE, self.dwProcessId)
207
208        try:
209            self.close_handle()
210        except Exception:
211            warnings.warn(
212                "Failed to close process handle: %s" % traceback.format_exc())
213
214        self.hProcess = hProcess
215
216    def close_handle(self):
217        """
218        Closes the handle to the process.
219
220        @note: Normally you don't need to call this method. All handles
221            created by I{WinAppDbg} are automatically closed when the garbage
222            collector claims them. So unless you've been tinkering with it,
223            setting L{hProcess} to C{None} should be enough.
224        """
225        try:
226            if hasattr(self.hProcess, 'close'):
227                self.hProcess.close()
228            elif self.hProcess not in (None, win32.INVALID_HANDLE_VALUE):
229                win32.CloseHandle(self.hProcess)
230        finally:
231            self.hProcess = None
232
233    def get_handle(self, dwDesiredAccess = win32.PROCESS_ALL_ACCESS):
234        """
235        Returns a handle to the process with I{at least} the access rights
236        requested.
237
238        @note:
239            If a handle was previously opened and has the required access
240            rights, it's reused. If not, a new handle is opened with the
241            combination of the old and new access rights.
242
243        @type  dwDesiredAccess: int
244        @param dwDesiredAccess: Desired access rights.
245            Defaults to L{win32.PROCESS_ALL_ACCESS}.
246            See: U{http://msdn.microsoft.com/en-us/library/windows/desktop/ms684880(v=vs.85).aspx}
247
248        @rtype:  L{ProcessHandle}
249        @return: Handle to the process.
250
251        @raise WindowsError: It's not possible to open a handle to the process
252            with the requested access rights. This tipically happens because
253            the target process is a system process and the debugger is not
254            runnning with administrative rights.
255        """
256        if self.hProcess in (None, win32.INVALID_HANDLE_VALUE):
257            self.open_handle(dwDesiredAccess)
258        else:
259            dwAccess = self.hProcess.dwAccess
260            if (dwAccess | dwDesiredAccess) != dwAccess:
261                self.open_handle(dwAccess | dwDesiredAccess)
262        return self.hProcess
263
264#------------------------------------------------------------------------------
265
266    # Not really sure if it's a good idea...
267##    def __eq__(self, aProcess):
268##        """
269##        Compare two Process objects. The comparison is made using the IDs.
270##
271##        @warning:
272##            If you have two Process instances with different handles the
273##            equality operator still returns C{True}, so be careful!
274##
275##        @type  aProcess: L{Process}
276##        @param aProcess: Another Process object.
277##
278##        @rtype:  bool
279##        @return: C{True} if the two process IDs are equal,
280##            C{False} otherwise.
281##        """
282##        return isinstance(aProcess, Process)         and \
283##               self.get_pid() == aProcess.get_pid()
284
285    def __contains__(self, anObject):
286        """
287        The same as: C{self.has_thread(anObject) or self.has_module(anObject)}
288
289        @type  anObject: L{Thread}, L{Module} or int
290        @param anObject: Object to look for.
291            Can be a Thread, Module, thread global ID or module base address.
292
293        @rtype:  bool
294        @return: C{True} if the requested object was found in the snapshot.
295        """
296        return _ThreadContainer.__contains__(self, anObject) or \
297               _ModuleContainer.__contains__(self, anObject)
298
299    def __len__(self):
300        """
301        @see:    L{get_thread_count}, L{get_module_count}
302        @rtype:  int
303        @return: Count of L{Thread} and L{Module} objects in this snapshot.
304        """
305        return _ThreadContainer.__len__(self) + \
306               _ModuleContainer.__len__(self)
307
308    class __ThreadsAndModulesIterator (object):
309        """
310        Iterator object for L{Process} objects.
311        Iterates through L{Thread} objects first, L{Module} objects next.
312        """
313
314        def __init__(self, container):
315            """
316            @type  container: L{Process}
317            @param container: L{Thread} and L{Module} container.
318            """
319            self.__container = container
320            self.__iterator  = None
321            self.__state     = 0
322
323        def __iter__(self):
324            'x.__iter__() <==> iter(x)'
325            return self
326
327        def next(self):
328            'x.next() -> the next value, or raise StopIteration'
329            if self.__state == 0:
330                self.__iterator = self.__container.iter_threads()
331                self.__state    = 1
332            if self.__state == 1:
333                try:
334                    return self.__iterator.next()
335                except StopIteration:
336                    self.__iterator = self.__container.iter_modules()
337                    self.__state    = 2
338            if self.__state == 2:
339                try:
340                    return self.__iterator.next()
341                except StopIteration:
342                    self.__iterator = None
343                    self.__state    = 3
344            raise StopIteration
345
346    def __iter__(self):
347        """
348        @see:    L{iter_threads}, L{iter_modules}
349        @rtype:  iterator
350        @return: Iterator of L{Thread} and L{Module} objects in this snapshot.
351            All threads are iterated first, then all modules.
352        """
353        return self.__ThreadsAndModulesIterator(self)
354
355#------------------------------------------------------------------------------
356
357    def wait(self, dwTimeout = None):
358        """
359        Waits for the process to finish executing.
360
361        @raise WindowsError: On error an exception is raised.
362        """
363        self.get_handle(win32.SYNCHRONIZE).wait(dwTimeout)
364
365    def kill(self, dwExitCode = 0):
366        """
367        Terminates the execution of the process.
368
369        @raise WindowsError: On error an exception is raised.
370        """
371        hProcess = self.get_handle(win32.PROCESS_TERMINATE)
372        win32.TerminateProcess(hProcess, dwExitCode)
373
374    def suspend(self):
375        """
376        Suspends execution on all threads of the process.
377
378        @raise WindowsError: On error an exception is raised.
379        """
380        self.scan_threads() # force refresh the snapshot
381        suspended = list()
382        try:
383            for aThread in self.iter_threads():
384                aThread.suspend()
385                suspended.append(aThread)
386        except Exception:
387            for aThread in suspended:
388                try:
389                    aThread.resume()
390                except Exception:
391                    pass
392            raise
393
394    def resume(self):
395        """
396        Resumes execution on all threads of the process.
397
398        @raise WindowsError: On error an exception is raised.
399        """
400        if self.get_thread_count() == 0:
401            self.scan_threads() # only refresh the snapshot if empty
402        resumed = list()
403        try:
404            for aThread in self.iter_threads():
405                aThread.resume()
406                resumed.append(aThread)
407        except Exception:
408            for aThread in resumed:
409                try:
410                    aThread.suspend()
411                except Exception:
412                    pass
413            raise
414
415    def is_debugged(self):
416        """
417        Tries to determine if the process is being debugged by another process.
418        It may detect other debuggers besides WinAppDbg.
419
420        @rtype:  bool
421        @return: C{True} if the process has a debugger attached.
422
423        @warning:
424            May return inaccurate results when some anti-debug techniques are
425            used by the target process.
426
427        @note: To know if a process currently being debugged by a L{Debug}
428            object, call L{Debug.is_debugee} instead.
429        """
430        # FIXME the MSDN docs don't say what access rights are needed here!
431        hProcess = self.get_handle(win32.PROCESS_QUERY_INFORMATION)
432        return win32.CheckRemoteDebuggerPresent(hProcess)
433
434    def is_alive(self):
435        """
436        @rtype:  bool
437        @return: C{True} if the process is currently running.
438        """
439        try:
440            self.wait(0)
441        except WindowsError:
442            e = sys.exc_info()[1]
443            return e.winerror == win32.WAIT_TIMEOUT
444        return False
445
446    def get_exit_code(self):
447        """
448        @rtype:  int
449        @return: Process exit code, or C{STILL_ACTIVE} if it's still alive.
450
451        @warning: If a process returns C{STILL_ACTIVE} as it's exit code,
452            you may not be able to determine if it's active or not with this
453            method. Use L{is_alive} to check if the process is still active.
454            Alternatively you can call L{get_handle} to get the handle object
455            and then L{ProcessHandle.wait} on it to wait until the process
456            finishes running.
457        """
458        if win32.PROCESS_ALL_ACCESS == win32.PROCESS_ALL_ACCESS_VISTA:
459            dwAccess = win32.PROCESS_QUERY_LIMITED_INFORMATION
460        else:
461            dwAccess = win32.PROCESS_QUERY_INFORMATION
462        return win32.GetExitCodeProcess( self.get_handle(dwAccess) )
463
464#------------------------------------------------------------------------------
465
466    def scan(self):
467        """
468        Populates the snapshot of threads and modules.
469        """
470        self.scan_threads()
471        self.scan_modules()
472
473    def clear(self):
474        """
475        Clears the snapshot of threads and modules.
476        """
477        try:
478            try:
479                self.clear_threads()
480            finally:
481                self.clear_modules()
482        finally:
483            self.close_handle()
484
485#------------------------------------------------------------------------------
486
487    # Regular expression to find hexadecimal values of any size.
488    __hexa_parameter = re.compile('0x[0-9A-Fa-f]+')
489
490    def __fixup_labels(self, disasm):
491        """
492        Private method used when disassembling from process memory.
493
494        It has no return value because the list is modified in place. On return
495        all raw memory addresses are replaced by labels when possible.
496
497        @type  disasm: list of tuple(int, int, str, str)
498        @param disasm: Output of one of the dissassembly functions.
499        """
500        for index in compat.xrange(len(disasm)):
501            (address, size, text, dump) = disasm[index]
502            m = self.__hexa_parameter.search(text)
503            while m:
504                s, e = m.span()
505                value = text[s:e]
506                try:
507                    label = self.get_label_at_address( int(value, 0x10) )
508                except Exception:
509                    label = None
510                if label:
511                    text = text[:s] + label + text[e:]
512                    e = s + len(value)
513                m = self.__hexa_parameter.search(text, e)
514            disasm[index] = (address, size, text, dump)
515
516    def disassemble_string(self, lpAddress, code):
517        """
518        Disassemble instructions from a block of binary code.
519
520        @type  lpAddress: int
521        @param lpAddress: Memory address where the code was read from.
522
523        @type  code: str
524        @param code: Binary code to disassemble.
525
526        @rtype:  list of tuple( long, int, str, str )
527        @return: List of tuples. Each tuple represents an assembly instruction
528            and contains:
529             - Memory address of instruction.
530             - Size of instruction in bytes.
531             - Disassembly line of instruction.
532             - Hexadecimal dump of instruction.
533
534        @raise NotImplementedError:
535            No compatible disassembler was found for the current platform.
536        """
537        try:
538            disasm = self.__disasm
539        except AttributeError:
540            disasm = self.__disasm = Disassembler( self.get_arch() )
541        return disasm.decode(lpAddress, code)
542
543    def disassemble(self, lpAddress, dwSize):
544        """
545        Disassemble instructions from the address space of the process.
546
547        @type  lpAddress: int
548        @param lpAddress: Memory address where to read the code from.
549
550        @type  dwSize: int
551        @param dwSize: Size of binary code to disassemble.
552
553        @rtype:  list of tuple( long, int, str, str )
554        @return: List of tuples. Each tuple represents an assembly instruction
555            and contains:
556             - Memory address of instruction.
557             - Size of instruction in bytes.
558             - Disassembly line of instruction.
559             - Hexadecimal dump of instruction.
560        """
561        data   = self.read(lpAddress, dwSize)
562        disasm = self.disassemble_string(lpAddress, data)
563        self.__fixup_labels(disasm)
564        return disasm
565
566    # FIXME
567    # This algorithm really sucks, I've got to write a better one :P
568    def disassemble_around(self, lpAddress, dwSize = 64):
569        """
570        Disassemble around the given address.
571
572        @type  lpAddress: int
573        @param lpAddress: Memory address where to read the code from.
574
575        @type  dwSize: int
576        @param dwSize: Delta offset.
577            Code will be read from lpAddress - dwSize to lpAddress + dwSize.
578
579        @rtype:  list of tuple( long, int, str, str )
580        @return: List of tuples. Each tuple represents an assembly instruction
581            and contains:
582             - Memory address of instruction.
583             - Size of instruction in bytes.
584             - Disassembly line of instruction.
585             - Hexadecimal dump of instruction.
586        """
587        dwDelta  = int(float(dwSize) / 2.0)
588        addr_1   = lpAddress - dwDelta
589        addr_2   = lpAddress
590        size_1   = dwDelta
591        size_2   = dwSize - dwDelta
592        data     = self.read(addr_1, dwSize)
593        data_1   = data[:size_1]
594        data_2   = data[size_1:]
595        disasm_1 = self.disassemble_string(addr_1, data_1)
596        disasm_2 = self.disassemble_string(addr_2, data_2)
597        disasm   = disasm_1 + disasm_2
598        self.__fixup_labels(disasm)
599        return disasm
600
601    def disassemble_around_pc(self, dwThreadId, dwSize = 64):
602        """
603        Disassemble around the program counter of the given thread.
604
605        @type  dwThreadId: int
606        @param dwThreadId: Global thread ID.
607            The program counter for this thread will be used as the disassembly
608            address.
609
610        @type  dwSize: int
611        @param dwSize: Delta offset.
612            Code will be read from pc - dwSize to pc + dwSize.
613
614        @rtype:  list of tuple( long, int, str, str )
615        @return: List of tuples. Each tuple represents an assembly instruction
616            and contains:
617             - Memory address of instruction.
618             - Size of instruction in bytes.
619             - Disassembly line of instruction.
620             - Hexadecimal dump of instruction.
621        """
622        aThread = self.get_thread(dwThreadId)
623        return self.disassemble_around(aThread.get_pc(), dwSize)
624
625    def disassemble_instruction(self, lpAddress):
626        """
627        Disassemble the instruction at the given memory address.
628
629        @type  lpAddress: int
630        @param lpAddress: Memory address where to read the code from.
631
632        @rtype:  tuple( long, int, str, str )
633        @return: The tuple represents an assembly instruction
634            and contains:
635             - Memory address of instruction.
636             - Size of instruction in bytes.
637             - Disassembly line of instruction.
638             - Hexadecimal dump of instruction.
639        """
640        return self.disassemble(lpAddress, 15)[0]
641
642    def disassemble_current(self, dwThreadId):
643        """
644        Disassemble the instruction at the program counter of the given thread.
645
646        @type  dwThreadId: int
647        @param dwThreadId: Global thread ID.
648            The program counter for this thread will be used as the disassembly
649            address.
650
651        @rtype:  tuple( long, int, str, str )
652        @return: The tuple represents an assembly instruction
653            and contains:
654             - Memory address of instruction.
655             - Size of instruction in bytes.
656             - Disassembly line of instruction.
657             - Hexadecimal dump of instruction.
658        """
659        aThread = self.get_thread(dwThreadId)
660        return self.disassemble_instruction(aThread.get_pc())
661
662#------------------------------------------------------------------------------
663
664    def flush_instruction_cache(self):
665        """
666        Flush the instruction cache. This is required if the process memory is
667        modified and one or more threads are executing nearby the modified
668        memory region.
669
670        @see: U{http://blogs.msdn.com/oldnewthing/archive/2003/12/08/55954.aspx#55958}
671
672        @raise WindowsError: Raises exception on error.
673        """
674        # FIXME
675        # No idea what access rights are required here!
676        # Maybe PROCESS_VM_OPERATION ???
677        # In any case we're only calling this from the debugger,
678        # so it should be fine (we already have PROCESS_ALL_ACCESS).
679        win32.FlushInstructionCache( self.get_handle() )
680
681    def debug_break(self):
682        """
683        Triggers the system breakpoint in the process.
684
685        @raise WindowsError: On error an exception is raised.
686        """
687        # The exception is raised by a new thread.
688        # When continuing the exception, the thread dies by itself.
689        # This thread is hidden from the debugger.
690        win32.DebugBreakProcess( self.get_handle() )
691
692    def is_wow64(self):
693        """
694        Determines if the process is running under WOW64.
695
696        @rtype:  bool
697        @return:
698            C{True} if the process is running under WOW64. That is, a 32-bit
699            application running in a 64-bit Windows.
700
701            C{False} if the process is either a 32-bit application running in
702            a 32-bit Windows, or a 64-bit application running in a 64-bit
703            Windows.
704
705        @raise WindowsError: On error an exception is raised.
706
707        @see: U{http://msdn.microsoft.com/en-us/library/aa384249(VS.85).aspx}
708        """
709        try:
710            wow64 = self.__wow64
711        except AttributeError:
712            if (win32.bits == 32 and not win32.wow64):
713                wow64 = False
714            else:
715                if win32.PROCESS_ALL_ACCESS == win32.PROCESS_ALL_ACCESS_VISTA:
716                    dwAccess = win32.PROCESS_QUERY_LIMITED_INFORMATION
717                else:
718                    dwAccess = win32.PROCESS_QUERY_INFORMATION
719                hProcess = self.get_handle(dwAccess)
720                try:
721                    wow64 = win32.IsWow64Process(hProcess)
722                except AttributeError:
723                    wow64 = False
724            self.__wow64 = wow64
725        return wow64
726
727    def get_arch(self):
728        """
729        @rtype:  str
730        @return: The architecture in which this process believes to be running.
731            For example, if running a 32 bit binary in a 64 bit machine, the
732            architecture returned by this method will be L{win32.ARCH_I386},
733            but the value of L{System.arch} will be L{win32.ARCH_AMD64}.
734        """
735
736        # Are we in a 32 bit machine?
737        if win32.bits == 32 and not win32.wow64:
738            return win32.arch
739
740        # Is the process outside of WOW64?
741        if not self.is_wow64():
742            return win32.arch
743
744        # In WOW64, "amd64" becomes "i386".
745        if win32.arch == win32.ARCH_AMD64:
746            return win32.ARCH_I386
747
748        # We don't know the translation for other architectures.
749        raise NotImplementedError()
750
751    def get_bits(self):
752        """
753        @rtype:  str
754        @return: The number of bits in which this process believes to be
755            running. For example, if running a 32 bit binary in a 64 bit
756            machine, the number of bits returned by this method will be C{32},
757            but the value of L{System.arch} will be C{64}.
758        """
759
760        # Are we in a 32 bit machine?
761        if win32.bits == 32 and not win32.wow64:
762
763            # All processes are 32 bits.
764            return 32
765
766        # Is the process inside WOW64?
767        if self.is_wow64():
768
769            # The process is 32 bits.
770            return 32
771
772        # The process is 64 bits.
773        return 64
774
775    # TODO: get_os, to test compatibility run
776    # See: http://msdn.microsoft.com/en-us/library/windows/desktop/ms683224(v=vs.85).aspx
777
778#------------------------------------------------------------------------------
779
780    def get_start_time(self):
781        """
782        Determines when has this process started running.
783
784        @rtype:  win32.SYSTEMTIME
785        @return: Process start time.
786        """
787        if win32.PROCESS_ALL_ACCESS == win32.PROCESS_ALL_ACCESS_VISTA:
788            dwAccess = win32.PROCESS_QUERY_LIMITED_INFORMATION
789        else:
790            dwAccess = win32.PROCESS_QUERY_INFORMATION
791        hProcess = self.get_handle(dwAccess)
792        CreationTime = win32.GetProcessTimes(hProcess)[0]
793        return win32.FileTimeToSystemTime(CreationTime)
794
795    def get_exit_time(self):
796        """
797        Determines when has this process finished running.
798        If the process is still alive, the current time is returned instead.
799
800        @rtype:  win32.SYSTEMTIME
801        @return: Process exit time.
802        """
803        if self.is_alive():
804            ExitTime = win32.GetSystemTimeAsFileTime()
805        else:
806            if win32.PROCESS_ALL_ACCESS == win32.PROCESS_ALL_ACCESS_VISTA:
807                dwAccess = win32.PROCESS_QUERY_LIMITED_INFORMATION
808            else:
809                dwAccess = win32.PROCESS_QUERY_INFORMATION
810            hProcess = self.get_handle(dwAccess)
811            ExitTime = win32.GetProcessTimes(hProcess)[1]
812        return win32.FileTimeToSystemTime(ExitTime)
813
814    def get_running_time(self):
815        """
816        Determines how long has this process been running.
817
818        @rtype:  long
819        @return: Process running time in milliseconds.
820        """
821        if win32.PROCESS_ALL_ACCESS == win32.PROCESS_ALL_ACCESS_VISTA:
822            dwAccess = win32.PROCESS_QUERY_LIMITED_INFORMATION
823        else:
824            dwAccess = win32.PROCESS_QUERY_INFORMATION
825        hProcess = self.get_handle(dwAccess)
826        (CreationTime, ExitTime, _, _) = win32.GetProcessTimes(hProcess)
827        if self.is_alive():
828            ExitTime = win32.GetSystemTimeAsFileTime()
829        CreationTime = CreationTime.dwLowDateTime + (CreationTime.dwHighDateTime << 32)
830        ExitTime     =     ExitTime.dwLowDateTime + (    ExitTime.dwHighDateTime << 32)
831        RunningTime  = ExitTime - CreationTime
832        return RunningTime / 10000 # 100 nanoseconds steps => milliseconds
833
834#------------------------------------------------------------------------------
835
836    def __load_System_class(self):
837        global System      # delayed import
838        if System is None:
839            from system import System
840
841    def get_services(self):
842        """
843        Retrieves the list of system services that are currently running in
844        this process.
845
846        @see: L{System.get_services}
847
848        @rtype:  list( L{win32.ServiceStatusProcessEntry} )
849        @return: List of service status descriptors.
850        """
851        self.__load_System_class()
852        pid = self.get_pid()
853        return [d for d in System.get_active_services() if d.ProcessId == pid]
854
855#------------------------------------------------------------------------------
856
857    def get_dep_policy(self):
858        """
859        Retrieves the DEP (Data Execution Prevention) policy for this process.
860
861        @note: This method is only available in Windows XP SP3 and above, and
862            only for 32 bit processes. It will fail in any other circumstance.
863
864        @see: U{http://msdn.microsoft.com/en-us/library/bb736297(v=vs.85).aspx}
865
866        @rtype:  tuple(int, int)
867        @return:
868            The first member of the tuple is the DEP flags. It can be a
869            combination of the following values:
870             - 0: DEP is disabled for this process.
871             - 1: DEP is enabled for this process. (C{PROCESS_DEP_ENABLE})
872             - 2: DEP-ATL thunk emulation is disabled for this process.
873                  (C{PROCESS_DEP_DISABLE_ATL_THUNK_EMULATION})
874
875            The second member of the tuple is the permanent flag. If C{TRUE}
876            the DEP settings cannot be changed in runtime for this process.
877
878        @raise WindowsError: On error an exception is raised.
879        """
880        hProcess = self.get_handle(win32.PROCESS_QUERY_INFORMATION)
881        try:
882            return win32.kernel32.GetProcessDEPPolicy(hProcess)
883        except AttributeError:
884            msg = "This method is only available in Windows XP SP3 and above."
885            raise NotImplementedError(msg)
886
887#------------------------------------------------------------------------------
888
889    def get_peb(self):
890        """
891        Returns a copy of the PEB.
892        To dereference pointers in it call L{Process.read_structure}.
893
894        @rtype:  L{win32.PEB}
895        @return: PEB structure.
896        @raise WindowsError: An exception is raised on error.
897        """
898        self.get_handle( win32.PROCESS_VM_READ |
899                         win32.PROCESS_QUERY_INFORMATION )
900        return self.read_structure(self.get_peb_address(), win32.PEB)
901
902    def get_peb_address(self):
903        """
904        Returns a remote pointer to the PEB.
905
906        @rtype:  int
907        @return: Remote pointer to the L{win32.PEB} structure.
908            Returns C{None} on error.
909        """
910        try:
911            return self._peb_ptr
912        except AttributeError:
913            hProcess = self.get_handle(win32.PROCESS_QUERY_INFORMATION)
914            pbi = win32.NtQueryInformationProcess(hProcess,
915                                                win32.ProcessBasicInformation)
916            address = pbi.PebBaseAddress
917            self._peb_ptr = address
918            return address
919
920    def get_entry_point(self):
921        """
922        Alias to C{process.get_main_module().get_entry_point()}.
923
924        @rtype:  int
925        @return: Address of the entry point of the main module.
926        """
927        return self.get_main_module().get_entry_point()
928
929    def get_main_module(self):
930        """
931        @rtype:  L{Module}
932        @return: Module object for the process main module.
933        """
934        return self.get_module(self.get_image_base())
935
936    def get_image_base(self):
937        """
938        @rtype:  int
939        @return: Image base address for the process main module.
940        """
941        return self.get_peb().ImageBaseAddress
942
943    def get_image_name(self):
944        """
945        @rtype:  int
946        @return: Filename of the process main module.
947
948            This method does it's best to retrieve the filename.
949            However sometimes this is not possible, so C{None} may
950            be returned instead.
951        """
952
953        # Method 1: Module.fileName
954        # It's cached if the filename was already found by the other methods,
955        # if it came with the corresponding debug event, or it was found by the
956        # toolhelp API.
957        mainModule = None
958        try:
959            mainModule = self.get_main_module()
960            name = mainModule.fileName
961            if not name:
962                name = None
963        except (KeyError, AttributeError, WindowsError):
964##            traceback.print_exc()                               # XXX DEBUG
965            name = None
966
967        # Method 2: QueryFullProcessImageName()
968        # Not implemented until Windows Vista.
969        if not name:
970            try:
971                hProcess = self.get_handle(
972                                    win32.PROCESS_QUERY_LIMITED_INFORMATION)
973                name = win32.QueryFullProcessImageName(hProcess)
974            except (AttributeError, WindowsError):
975##                traceback.print_exc()                           # XXX DEBUG
976                name = None
977
978        # Method 3: GetProcessImageFileName()
979        #
980        # Not implemented until Windows XP.
981        # For more info see:
982        # https://voidnish.wordpress.com/2005/06/20/getprocessimagefilenamequerydosdevice-trivia/
983        if not name:
984            try:
985                hProcess = self.get_handle(win32.PROCESS_QUERY_INFORMATION)
986                name = win32.GetProcessImageFileName(hProcess)
987                if name:
988                    name = PathOperations.native_to_win32_pathname(name)
989                else:
990                    name = None
991            except (AttributeError, WindowsError):
992##                traceback.print_exc()                           # XXX DEBUG
993                if not name:
994                    name = None
995
996        # Method 4: GetModuleFileNameEx()
997        # Not implemented until Windows 2000.
998        #
999        # May be spoofed by malware, since this information resides
1000        # in usermode space (see http://www.ragestorm.net/blogs/?p=163).
1001        if not name:
1002            try:
1003                hProcess = self.get_handle( win32.PROCESS_VM_READ |
1004                                            win32.PROCESS_QUERY_INFORMATION )
1005                try:
1006                    name = win32.GetModuleFileNameEx(hProcess)
1007                except WindowsError:
1008##                    traceback.print_exc()                       # XXX DEBUG
1009                    name = win32.GetModuleFileNameEx(
1010                                            hProcess, self.get_image_base())
1011                if name:
1012                    name = PathOperations.native_to_win32_pathname(name)
1013                else:
1014                    name = None
1015            except (AttributeError, WindowsError):
1016##                traceback.print_exc()                           # XXX DEBUG
1017                if not name:
1018                    name = None
1019
1020        # Method 5: PEB.ProcessParameters->ImagePathName
1021        #
1022        # May fail since it's using an undocumented internal structure.
1023        #
1024        # May be spoofed by malware, since this information resides
1025        # in usermode space (see http://www.ragestorm.net/blogs/?p=163).
1026        if not name:
1027            try:
1028                peb = self.get_peb()
1029                pp = self.read_structure(peb.ProcessParameters,
1030                                             win32.RTL_USER_PROCESS_PARAMETERS)
1031                s = pp.ImagePathName
1032                name = self.peek_string(s.Buffer,
1033                                    dwMaxSize=s.MaximumLength, fUnicode=True)
1034                if name:
1035                    name = PathOperations.native_to_win32_pathname(name)
1036                else:
1037                    name = None
1038            except (AttributeError, WindowsError):
1039##                traceback.print_exc()                           # XXX DEBUG
1040                name = None
1041
1042        # Method 6: Module.get_filename()
1043        # It tries to get the filename from the file handle.
1044        #
1045        # There are currently some problems due to the strange way the API
1046        # works - it returns the pathname without the drive letter, and I
1047        # couldn't figure out a way to fix it.
1048        if not name and mainModule is not None:
1049            try:
1050                name = mainModule.get_filename()
1051                if not name:
1052                    name = None
1053            except (AttributeError, WindowsError):
1054##                traceback.print_exc()                           # XXX DEBUG
1055                name = None
1056
1057        # Remember the filename.
1058        if name and mainModule is not None:
1059            mainModule.fileName = name
1060
1061        # Return the image filename, or None on error.
1062        return name
1063
1064    def get_command_line_block(self):
1065        """
1066        Retrieves the command line block memory address and size.
1067
1068        @rtype:  tuple(int, int)
1069        @return: Tuple with the memory address of the command line block
1070            and it's maximum size in Unicode characters.
1071
1072        @raise WindowsError: On error an exception is raised.
1073        """
1074        peb = self.get_peb()
1075        pp = self.read_structure(peb.ProcessParameters,
1076                                             win32.RTL_USER_PROCESS_PARAMETERS)
1077        s = pp.CommandLine
1078        return (s.Buffer, s.MaximumLength)
1079
1080    def get_environment_block(self):
1081        """
1082        Retrieves the environment block memory address for the process.
1083
1084        @note: The size is always enough to contain the environment data, but
1085            it may not be an exact size. It's best to read the memory and
1086            scan for two null wide chars to find the actual size.
1087
1088        @rtype:  tuple(int, int)
1089        @return: Tuple with the memory address of the environment block
1090            and it's size.
1091
1092        @raise WindowsError: On error an exception is raised.
1093        """
1094        peb = self.get_peb()
1095        pp = self.read_structure(peb.ProcessParameters,
1096                                             win32.RTL_USER_PROCESS_PARAMETERS)
1097        Environment = pp.Environment
1098        try:
1099            EnvironmentSize = pp.EnvironmentSize
1100        except AttributeError:
1101            mbi = self.mquery(Environment)
1102            EnvironmentSize = mbi.RegionSize + mbi.BaseAddress - Environment
1103        return (Environment, EnvironmentSize)
1104
1105    def get_command_line(self):
1106        """
1107        Retrieves the command line with wich the program was started.
1108
1109        @rtype:  str
1110        @return: Command line string.
1111
1112        @raise WindowsError: On error an exception is raised.
1113        """
1114        (Buffer, MaximumLength) = self.get_command_line_block()
1115        CommandLine = self.peek_string(Buffer, dwMaxSize=MaximumLength,
1116                                                            fUnicode=True)
1117        gst = win32.GuessStringType
1118        if gst.t_default == gst.t_ansi:
1119            CommandLine = CommandLine.encode('cp1252')
1120        return CommandLine
1121
1122    def get_environment_variables(self):
1123        """
1124        Retrieves the environment variables with wich the program is running.
1125
1126        @rtype:  list of tuple(compat.unicode, compat.unicode)
1127        @return: Environment keys and values as found in the process memory.
1128
1129        @raise WindowsError: On error an exception is raised.
1130        """
1131
1132        # Note: the first bytes are garbage and must be skipped. Then the first
1133        # two environment entries are the current drive and directory as key
1134        # and value pairs, followed by the ExitCode variable (it's what batch
1135        # files know as "errorlevel"). After that, the real environment vars
1136        # are there in alphabetical order. In theory that's where it stops,
1137        # but I've always seen one more "variable" tucked at the end which
1138        # may be another environment block but in ANSI. I haven't examined it
1139        # yet, I'm just skipping it because if it's parsed as Unicode it just
1140        # renders garbage.
1141
1142        # Read the environment block contents.
1143        data = self.peek( *self.get_environment_block() )
1144
1145        # Put them into a Unicode buffer.
1146        tmp = ctypes.create_string_buffer(data)
1147        buffer = ctypes.create_unicode_buffer(len(data))
1148        ctypes.memmove(buffer, tmp, len(data))
1149        del tmp
1150
1151        # Skip until the first Unicode null char is found.
1152        pos = 0
1153        while buffer[pos] != u'\0':
1154            pos += 1
1155        pos += 1
1156
1157        # Loop for each environment variable...
1158        environment = []
1159        while buffer[pos] != u'\0':
1160
1161            # Until we find a null char...
1162            env_name_pos = pos
1163            env_name = u''
1164            found_name = False
1165            while buffer[pos] != u'\0':
1166
1167                # Get the current char.
1168                char = buffer[pos]
1169
1170                # Is it an equal sign?
1171                if char == u'=':
1172
1173                    # Skip leading equal signs.
1174                    if env_name_pos == pos:
1175                        env_name_pos += 1
1176                        pos += 1
1177                        continue
1178
1179                    # Otherwise we found the separator equal sign.
1180                    pos += 1
1181                    found_name = True
1182                    break
1183
1184                # Add the char to the variable name.
1185                env_name += char
1186
1187                # Next char.
1188                pos += 1
1189
1190            # If the name was not parsed properly, stop.
1191            if not found_name:
1192                break
1193
1194            # Read the variable value until we find a null char.
1195            env_value = u''
1196            while buffer[pos] != u'\0':
1197                env_value += buffer[pos]
1198                pos += 1
1199
1200            # Skip the null char.
1201            pos += 1
1202
1203            # Add to the list of environment variables found.
1204            environment.append( (env_name, env_value) )
1205
1206        # Remove the last entry, it's garbage.
1207        if environment:
1208            environment.pop()
1209
1210        # Return the environment variables.
1211        return environment
1212
1213    def get_environment_data(self, fUnicode = None):
1214        """
1215        Retrieves the environment block data with wich the program is running.
1216
1217        @warn: Deprecated since WinAppDbg 1.5.
1218
1219        @see: L{win32.GuessStringType}
1220
1221        @type  fUnicode: bool or None
1222        @param fUnicode: C{True} to return a list of Unicode strings, C{False}
1223            to return a list of ANSI strings, or C{None} to return whatever
1224            the default is for string types.
1225
1226        @rtype:  list of str
1227        @return: Environment keys and values separated by a (C{=}) character,
1228            as found in the process memory.
1229
1230        @raise WindowsError: On error an exception is raised.
1231        """
1232
1233        # Issue a deprecation warning.
1234        warnings.warn(
1235            "Process.get_environment_data() is deprecated" \
1236            " since WinAppDbg 1.5.",
1237            DeprecationWarning)
1238
1239        # Get the environment variables.
1240        block = [ key + u'=' + value for (key, value) \
1241                                     in self.get_environment_variables() ]
1242
1243        # Convert the data to ANSI if requested.
1244        if fUnicode is None:
1245            gst = win32.GuessStringType
1246            fUnicode = gst.t_default == gst.t_unicode
1247        if not fUnicode:
1248            block = [x.encode('cp1252') for x in block]
1249
1250        # Return the environment data.
1251        return block
1252
1253    @staticmethod
1254    def parse_environment_data(block):
1255        """
1256        Parse the environment block into a Python dictionary.
1257
1258        @warn: Deprecated since WinAppDbg 1.5.
1259
1260        @note: Values of duplicated keys are joined using null characters.
1261
1262        @type  block: list of str
1263        @param block: List of strings as returned by L{get_environment_data}.
1264
1265        @rtype:  dict(str S{->} str)
1266        @return: Dictionary of environment keys and values.
1267        """
1268
1269        # Issue a deprecation warning.
1270        warnings.warn(
1271            "Process.parse_environment_data() is deprecated" \
1272            " since WinAppDbg 1.5.",
1273            DeprecationWarning)
1274
1275        # Create an empty environment dictionary.
1276        environment = dict()
1277
1278        # End here if the environment block is empty.
1279        if not block:
1280            return environment
1281
1282        # Prepare the tokens (ANSI or Unicode).
1283        gst = win32.GuessStringType
1284        if type(block[0]) == gst.t_ansi:
1285            equals = '='
1286            terminator = '\0'
1287        else:
1288            equals = u'='
1289            terminator = u'\0'
1290
1291        # Split the blocks into key/value pairs.
1292        for chunk in block:
1293            sep = chunk.find(equals, 1)
1294            if sep < 0:
1295##                raise Exception()
1296                continue    # corrupted environment block?
1297            key, value = chunk[:sep], chunk[sep+1:]
1298
1299            # For duplicated keys, append the value.
1300            # Values are separated using null terminators.
1301            if key not in environment:
1302                environment[key] = value
1303            else:
1304                environment[key] += terminator + value
1305
1306        # Return the environment dictionary.
1307        return environment
1308
1309    def get_environment(self, fUnicode = None):
1310        """
1311        Retrieves the environment with wich the program is running.
1312
1313        @note: Duplicated keys are joined using null characters.
1314            To avoid this behavior, call L{get_environment_variables} instead
1315            and convert the results to a dictionary directly, like this:
1316            C{dict(process.get_environment_variables())}
1317
1318        @see: L{win32.GuessStringType}
1319
1320        @type  fUnicode: bool or None
1321        @param fUnicode: C{True} to return a list of Unicode strings, C{False}
1322            to return a list of ANSI strings, or C{None} to return whatever
1323            the default is for string types.
1324
1325        @rtype:  dict(str S{->} str)
1326        @return: Dictionary of environment keys and values.
1327
1328        @raise WindowsError: On error an exception is raised.
1329        """
1330
1331        # Get the environment variables.
1332        variables = self.get_environment_variables()
1333
1334        # Convert the strings to ANSI if requested.
1335        if fUnicode is None:
1336            gst = win32.GuessStringType
1337            fUnicode = gst.t_default == gst.t_unicode
1338        if not fUnicode:
1339            variables = [ ( key.encode('cp1252'), value.encode('cp1252') ) \
1340                        for (key, value) in variables ]
1341
1342        # Add the variables to a dictionary, concatenating duplicates.
1343        environment = dict()
1344        for key, value in variables:
1345            if key in environment:
1346                environment[key] = environment[key] + u'\0' + value
1347            else:
1348                environment[key] = value
1349
1350        # Return the dictionary.
1351        return environment
1352
1353#------------------------------------------------------------------------------
1354
1355    def search(self, pattern, minAddr = None, maxAddr = None):
1356        """
1357        Search for the given pattern within the process memory.
1358
1359        @type  pattern: str, compat.unicode or L{Pattern}
1360        @param pattern: Pattern to search for.
1361            It may be a byte string, a Unicode string, or an instance of
1362            L{Pattern}.
1363
1364            The following L{Pattern} subclasses are provided by WinAppDbg:
1365             - L{BytePattern}
1366             - L{TextPattern}
1367             - L{RegExpPattern}
1368             - L{HexPattern}
1369
1370            You can also write your own subclass of L{Pattern} for customized
1371            searches.
1372
1373        @type  minAddr: int
1374        @param minAddr: (Optional) Start the search at this memory address.
1375
1376        @type  maxAddr: int
1377        @param maxAddr: (Optional) Stop the search at this memory address.
1378
1379        @rtype:  iterator of tuple( int, int, str )
1380        @return: An iterator of tuples. Each tuple contains the following:
1381             - The memory address where the pattern was found.
1382             - The size of the data that matches the pattern.
1383             - The data that matches the pattern.
1384
1385        @raise WindowsError: An error occurred when querying or reading the
1386            process memory.
1387        """
1388        if isinstance(pattern, str):
1389            return self.search_bytes(pattern, minAddr, maxAddr)
1390        if isinstance(pattern, compat.unicode):
1391            return self.search_bytes(pattern.encode("utf-16le"),
1392                                     minAddr, maxAddr)
1393        if isinstance(pattern, Pattern):
1394            return Search.search_process(self, pattern, minAddr, maxAddr)
1395        raise TypeError("Unknown pattern type: %r" % type(pattern))
1396
1397    def search_bytes(self, bytes, minAddr = None, maxAddr = None):
1398        """
1399        Search for the given byte pattern within the process memory.
1400
1401        @type  bytes: str
1402        @param bytes: Bytes to search for.
1403
1404        @type  minAddr: int
1405        @param minAddr: (Optional) Start the search at this memory address.
1406
1407        @type  maxAddr: int
1408        @param maxAddr: (Optional) Stop the search at this memory address.
1409
1410        @rtype:  iterator of int
1411        @return: An iterator of memory addresses where the pattern was found.
1412
1413        @raise WindowsError: An error occurred when querying or reading the
1414            process memory.
1415        """
1416        pattern = BytePattern(bytes)
1417        matches = Search.search_process(self, pattern, minAddr, maxAddr)
1418        for addr, size, data in matches:
1419            yield addr
1420
1421    def search_text(self, text, encoding = "utf-16le",
1422                                caseSensitive = False,
1423                                minAddr = None,
1424                                maxAddr = None):
1425        """
1426        Search for the given text within the process memory.
1427
1428        @type  text: str or compat.unicode
1429        @param text: Text to search for.
1430
1431        @type  encoding: str
1432        @param encoding: (Optional) Encoding for the text parameter.
1433            Only used when the text to search for is a Unicode string.
1434            Don't change unless you know what you're doing!
1435
1436        @type  caseSensitive: bool
1437        @param caseSensitive: C{True} of the search is case sensitive,
1438            C{False} otherwise.
1439
1440        @type  minAddr: int
1441        @param minAddr: (Optional) Start the search at this memory address.
1442
1443        @type  maxAddr: int
1444        @param maxAddr: (Optional) Stop the search at this memory address.
1445
1446        @rtype:  iterator of tuple( int, str )
1447        @return: An iterator of tuples. Each tuple contains the following:
1448             - The memory address where the pattern was found.
1449             - The text that matches the pattern.
1450
1451        @raise WindowsError: An error occurred when querying or reading the
1452            process memory.
1453        """
1454        pattern = TextPattern(text, encoding, caseSensitive)
1455        matches = Search.search_process(self, pattern, minAddr, maxAddr)
1456        for addr, size, data in matches:
1457            yield addr, data
1458
1459    def search_regexp(self, regexp, flags = 0,
1460                                    minAddr = None,
1461                                    maxAddr = None,
1462                                    bufferPages = -1):
1463        """
1464        Search for the given regular expression within the process memory.
1465
1466        @type  regexp: str
1467        @param regexp: Regular expression string.
1468
1469        @type  flags: int
1470        @param flags: Regular expression flags.
1471
1472        @type  minAddr: int
1473        @param minAddr: (Optional) Start the search at this memory address.
1474
1475        @type  maxAddr: int
1476        @param maxAddr: (Optional) Stop the search at this memory address.
1477
1478        @type  bufferPages: int
1479        @param bufferPages: (Optional) Number of memory pages to buffer when
1480            performing the search. Valid values are:
1481             - C{0} or C{None}:
1482               Automatically determine the required buffer size. May not give
1483               complete results for regular expressions that match variable
1484               sized strings.
1485             - C{> 0}: Set the buffer size, in memory pages.
1486             - C{< 0}: Disable buffering entirely. This may give you a little
1487               speed gain at the cost of an increased memory usage. If the
1488               target process has very large contiguous memory regions it may
1489               actually be slower or even fail. It's also the only way to
1490               guarantee complete results for regular expressions that match
1491               variable sized strings.
1492
1493        @rtype:  iterator of tuple( int, int, str )
1494        @return: An iterator of tuples. Each tuple contains the following:
1495             - The memory address where the pattern was found.
1496             - The size of the data that matches the pattern.
1497             - The data that matches the pattern.
1498
1499        @raise WindowsError: An error occurred when querying or reading the
1500            process memory.
1501        """
1502        pattern = RegExpPattern(regexp, flags)
1503        return Search.search_process(self, pattern,
1504                                     minAddr, maxAddr,
1505                                     bufferPages)
1506
1507    def search_hexa(self, hexa, minAddr = None, maxAddr = None):
1508        """
1509        Search for the given hexadecimal pattern within the process memory.
1510
1511        Hex patterns must be in this form::
1512            "68 65 6c 6c 6f 20 77 6f 72 6c 64"  # "hello world"
1513
1514        Spaces are optional. Capitalization of hex digits doesn't matter.
1515        This is exactly equivalent to the previous example::
1516            "68656C6C6F20776F726C64"            # "hello world"
1517
1518        Wildcards are allowed, in the form of a C{?} sign in any hex digit::
1519            "5? 5? c3"          # pop register / pop register / ret
1520            "b8 ?? ?? ?? ??"    # mov eax, immediate value
1521
1522        @type  hexa: str
1523        @param hexa: Pattern to search for.
1524
1525        @type  minAddr: int
1526        @param minAddr: (Optional) Start the search at this memory address.
1527
1528        @type  maxAddr: int
1529        @param maxAddr: (Optional) Stop the search at this memory address.
1530
1531        @rtype:  iterator of tuple( int, str )
1532        @return: An iterator of tuples. Each tuple contains the following:
1533             - The memory address where the pattern was found.
1534             - The bytes that match the pattern.
1535
1536        @raise WindowsError: An error occurred when querying or reading the
1537            process memory.
1538        """
1539        pattern = HexPattern(hexa)
1540        matches = Search.search_process(self, pattern, minAddr, maxAddr)
1541        for addr, size, data in matches:
1542            yield addr, data
1543
1544    def strings(self, minSize = 4, maxSize = 1024):
1545        """
1546        Extract ASCII strings from the process memory.
1547
1548        @type  minSize: int
1549        @param minSize: (Optional) Minimum size of the strings to search for.
1550
1551        @type  maxSize: int
1552        @param maxSize: (Optional) Maximum size of the strings to search for.
1553
1554        @rtype:  iterator of tuple(int, int, str)
1555        @return: Iterator of strings extracted from the process memory.
1556            Each tuple contains the following:
1557             - The memory address where the string was found.
1558             - The size of the string.
1559             - The string.
1560        """
1561        return Search.extract_ascii_strings(self, minSize = minSize,
1562                                                  maxSize = maxSize)
1563
1564#------------------------------------------------------------------------------
1565
1566    def __read_c_type(self, address, format, c_type):
1567        size = ctypes.sizeof(c_type)
1568        packed = self.read(address, size)
1569        if len(packed) != size:
1570            raise ctypes.WinError()
1571        return struct.unpack(format, packed)[0]
1572
1573    def __write_c_type(self, address, format, unpacked):
1574        packed = struct.pack('@L', unpacked)
1575        self.write(address, packed)
1576
1577    # XXX TODO
1578    # + Maybe change page permissions before trying to read?
1579    def read(self, lpBaseAddress, nSize):
1580        """
1581        Reads from the memory of the process.
1582
1583        @see: L{peek}
1584
1585        @type  lpBaseAddress: int
1586        @param lpBaseAddress: Memory address to begin reading.
1587
1588        @type  nSize: int
1589        @param nSize: Number of bytes to read.
1590
1591        @rtype:  str
1592        @return: Bytes read from the process memory.
1593
1594        @raise WindowsError: On error an exception is raised.
1595        """
1596        hProcess = self.get_handle( win32.PROCESS_VM_READ |
1597                                    win32.PROCESS_QUERY_INFORMATION )
1598        if not self.is_buffer(lpBaseAddress, nSize):
1599            raise ctypes.WinError(win32.ERROR_INVALID_ADDRESS)
1600        data = win32.ReadProcessMemory(hProcess, lpBaseAddress, nSize)
1601        if len(data) != nSize:
1602            raise ctypes.WinError()
1603        return data
1604
1605    def write(self, lpBaseAddress, lpBuffer):
1606        """
1607        Writes to the memory of the process.
1608
1609        @note: Page permissions may be changed temporarily while writing.
1610
1611        @see: L{poke}
1612
1613        @type  lpBaseAddress: int
1614        @param lpBaseAddress: Memory address to begin writing.
1615
1616        @type  lpBuffer: str
1617        @param lpBuffer: Bytes to write.
1618
1619        @raise WindowsError: On error an exception is raised.
1620        """
1621        r = self.poke(lpBaseAddress, lpBuffer)
1622        if r != len(lpBuffer):
1623            raise ctypes.WinError()
1624
1625    def read_char(self, lpBaseAddress):
1626        """
1627        Reads a single character to the memory of the process.
1628
1629        @see: L{peek_char}
1630
1631        @type  lpBaseAddress: int
1632        @param lpBaseAddress: Memory address to begin writing.
1633
1634        @rtype:  int
1635        @return: Character value read from the process memory.
1636
1637        @raise WindowsError: On error an exception is raised.
1638        """
1639        return ord( self.read(lpBaseAddress, 1) )
1640
1641    def write_char(self, lpBaseAddress, char):
1642        """
1643        Writes a single character to the memory of the process.
1644
1645        @note: Page permissions may be changed temporarily while writing.
1646
1647        @see: L{poke_char}
1648
1649        @type  lpBaseAddress: int
1650        @param lpBaseAddress: Memory address to begin writing.
1651
1652        @type  char: int
1653        @param char: Character to write.
1654
1655        @raise WindowsError: On error an exception is raised.
1656        """
1657        self.write(lpBaseAddress, chr(char))
1658
1659    def read_int(self, lpBaseAddress):
1660        """
1661        Reads a signed integer from the memory of the process.
1662
1663        @see: L{peek_int}
1664
1665        @type  lpBaseAddress: int
1666        @param lpBaseAddress: Memory address to begin reading.
1667
1668        @rtype:  int
1669        @return: Integer value read from the process memory.
1670
1671        @raise WindowsError: On error an exception is raised.
1672        """
1673        return self.__read_c_type(lpBaseAddress, compat.b('@l'), ctypes.c_int)
1674
1675    def write_int(self, lpBaseAddress, unpackedValue):
1676        """
1677        Writes a signed integer to the memory of the process.
1678
1679        @note: Page permissions may be changed temporarily while writing.
1680
1681        @see: L{poke_int}
1682
1683        @type  lpBaseAddress: int
1684        @param lpBaseAddress: Memory address to begin writing.
1685
1686        @type  unpackedValue: int, long
1687        @param unpackedValue: Value to write.
1688
1689        @raise WindowsError: On error an exception is raised.
1690        """
1691        self.__write_c_type(lpBaseAddress, '@l', unpackedValue)
1692
1693    def read_uint(self, lpBaseAddress):
1694        """
1695        Reads an unsigned integer from the memory of the process.
1696
1697        @see: L{peek_uint}
1698
1699        @type  lpBaseAddress: int
1700        @param lpBaseAddress: Memory address to begin reading.
1701
1702        @rtype:  int
1703        @return: Integer value read from the process memory.
1704
1705        @raise WindowsError: On error an exception is raised.
1706        """
1707        return self.__read_c_type(lpBaseAddress, '@L', ctypes.c_uint)
1708
1709    def write_uint(self, lpBaseAddress, unpackedValue):
1710        """
1711        Writes an unsigned integer to the memory of the process.
1712
1713        @note: Page permissions may be changed temporarily while writing.
1714
1715        @see: L{poke_uint}
1716
1717        @type  lpBaseAddress: int
1718        @param lpBaseAddress: Memory address to begin writing.
1719
1720        @type  unpackedValue: int, long
1721        @param unpackedValue: Value to write.
1722
1723        @raise WindowsError: On error an exception is raised.
1724        """
1725        self.__write_c_type(lpBaseAddress, '@L', unpackedValue)
1726
1727    def read_float(self, lpBaseAddress):
1728        """
1729        Reads a float from the memory of the process.
1730
1731        @see: L{peek_float}
1732
1733        @type  lpBaseAddress: int
1734        @param lpBaseAddress: Memory address to begin reading.
1735
1736        @rtype:  int
1737        @return: Floating point value read from the process memory.
1738
1739        @raise WindowsError: On error an exception is raised.
1740        """
1741        return self.__read_c_type(lpBaseAddress, '@f', ctypes.c_float)
1742
1743    def write_float(self, lpBaseAddress, unpackedValue):
1744        """
1745        Writes a float to the memory of the process.
1746
1747        @note: Page permissions may be changed temporarily while writing.
1748
1749        @see: L{poke_float}
1750
1751        @type  lpBaseAddress: int
1752        @param lpBaseAddress: Memory address to begin writing.
1753
1754        @type  unpackedValue: int, long
1755        @param unpackedValue: Floating point value to write.
1756
1757        @raise WindowsError: On error an exception is raised.
1758        """
1759        self.__write_c_type(lpBaseAddress, '@f', unpackedValue)
1760
1761    def read_double(self, lpBaseAddress):
1762        """
1763        Reads a double from the memory of the process.
1764
1765        @see: L{peek_double}
1766
1767        @type  lpBaseAddress: int
1768        @param lpBaseAddress: Memory address to begin reading.
1769
1770        @rtype:  int
1771        @return: Floating point value read from the process memory.
1772
1773        @raise WindowsError: On error an exception is raised.
1774        """
1775        return self.__read_c_type(lpBaseAddress, '@d', ctypes.c_double)
1776
1777    def write_double(self, lpBaseAddress, unpackedValue):
1778        """
1779        Writes a double to the memory of the process.
1780
1781        @note: Page permissions may be changed temporarily while writing.
1782
1783        @see: L{poke_double}
1784
1785        @type  lpBaseAddress: int
1786        @param lpBaseAddress: Memory address to begin writing.
1787
1788        @type  unpackedValue: int, long
1789        @param unpackedValue: Floating point value to write.
1790
1791        @raise WindowsError: On error an exception is raised.
1792        """
1793        self.__write_c_type(lpBaseAddress, '@d', unpackedValue)
1794
1795    def read_pointer(self, lpBaseAddress):
1796        """
1797        Reads a pointer value from the memory of the process.
1798
1799        @see: L{peek_pointer}
1800
1801        @type  lpBaseAddress: int
1802        @param lpBaseAddress: Memory address to begin reading.
1803
1804        @rtype:  int
1805        @return: Pointer value read from the process memory.
1806
1807        @raise WindowsError: On error an exception is raised.
1808        """
1809        return self.__read_c_type(lpBaseAddress, '@P', ctypes.c_void_p)
1810
1811    def write_pointer(self, lpBaseAddress, unpackedValue):
1812        """
1813        Writes a pointer value to the memory of the process.
1814
1815        @note: Page permissions may be changed temporarily while writing.
1816
1817        @see: L{poke_pointer}
1818
1819        @type  lpBaseAddress: int
1820        @param lpBaseAddress: Memory address to begin writing.
1821
1822        @type  unpackedValue: int, long
1823        @param unpackedValue: Value to write.
1824
1825        @raise WindowsError: On error an exception is raised.
1826        """
1827        self.__write_c_type(lpBaseAddress, '@P', unpackedValue)
1828
1829    def read_dword(self, lpBaseAddress):
1830        """
1831        Reads a DWORD from the memory of the process.
1832
1833        @see: L{peek_dword}
1834
1835        @type  lpBaseAddress: int
1836        @param lpBaseAddress: Memory address to begin reading.
1837
1838        @rtype:  int
1839        @return: Integer value read from the process memory.
1840
1841        @raise WindowsError: On error an exception is raised.
1842        """
1843        return self.__read_c_type(lpBaseAddress, '=L', win32.DWORD)
1844
1845    def write_dword(self, lpBaseAddress, unpackedValue):
1846        """
1847        Writes a DWORD to the memory of the process.
1848
1849        @note: Page permissions may be changed temporarily while writing.
1850
1851        @see: L{poke_dword}
1852
1853        @type  lpBaseAddress: int
1854        @param lpBaseAddress: Memory address to begin writing.
1855
1856        @type  unpackedValue: int, long
1857        @param unpackedValue: Value to write.
1858
1859        @raise WindowsError: On error an exception is raised.
1860        """
1861        self.__write_c_type(lpBaseAddress, '=L', unpackedValue)
1862
1863    def read_qword(self, lpBaseAddress):
1864        """
1865        Reads a QWORD from the memory of the process.
1866
1867        @see: L{peek_qword}
1868
1869        @type  lpBaseAddress: int
1870        @param lpBaseAddress: Memory address to begin reading.
1871
1872        @rtype:  int
1873        @return: Integer value read from the process memory.
1874
1875        @raise WindowsError: On error an exception is raised.
1876        """
1877        return self.__read_c_type(lpBaseAddress, '=Q', win32.QWORD)
1878
1879    def write_qword(self, lpBaseAddress, unpackedValue):
1880        """
1881        Writes a QWORD to the memory of the process.
1882
1883        @note: Page permissions may be changed temporarily while writing.
1884
1885        @see: L{poke_qword}
1886
1887        @type  lpBaseAddress: int
1888        @param lpBaseAddress: Memory address to begin writing.
1889
1890        @type  unpackedValue: int, long
1891        @param unpackedValue: Value to write.
1892
1893        @raise WindowsError: On error an exception is raised.
1894        """
1895        self.__write_c_type(lpBaseAddress, '=Q', unpackedValue)
1896
1897    def read_structure(self, lpBaseAddress, stype):
1898        """
1899        Reads a ctypes structure from the memory of the process.
1900
1901        @see: L{read}
1902
1903        @type  lpBaseAddress: int
1904        @param lpBaseAddress: Memory address to begin reading.
1905
1906        @type  stype: class ctypes.Structure or a subclass.
1907        @param stype: Structure definition.
1908
1909        @rtype:  int
1910        @return: Structure instance filled in with data
1911            read from the process memory.
1912
1913        @raise WindowsError: On error an exception is raised.
1914        """
1915        if type(lpBaseAddress) not in (type(0), type(long(0))):
1916            lpBaseAddress = ctypes.cast(lpBaseAddress, ctypes.c_void_p)
1917        data = self.read(lpBaseAddress, ctypes.sizeof(stype))
1918        buff = ctypes.create_string_buffer(data)
1919        ptr  = ctypes.cast(ctypes.pointer(buff), ctypes.POINTER(stype))
1920        return ptr.contents
1921
1922# XXX TODO
1923##    def write_structure(self, lpBaseAddress, sStructure):
1924##        """
1925##        Writes a ctypes structure into the memory of the process.
1926##
1927##        @note: Page permissions may be changed temporarily while writing.
1928##
1929##        @see: L{write}
1930##
1931##        @type  lpBaseAddress: int
1932##        @param lpBaseAddress: Memory address to begin writing.
1933##
1934##        @type  sStructure: ctypes.Structure or a subclass' instance.
1935##        @param sStructure: Structure definition.
1936##
1937##        @rtype:  int
1938##        @return: Structure instance filled in with data
1939##            read from the process memory.
1940##
1941##        @raise WindowsError: On error an exception is raised.
1942##        """
1943##        size = ctypes.sizeof(sStructure)
1944##        data = ctypes.create_string_buffer("", size = size)
1945##        win32.CopyMemory(ctypes.byref(data), ctypes.byref(sStructure), size)
1946##        self.write(lpBaseAddress, data.raw)
1947
1948    def read_string(self, lpBaseAddress, nChars, fUnicode = False):
1949        """
1950        Reads an ASCII or Unicode string
1951        from the address space of the process.
1952
1953        @see: L{peek_string}
1954
1955        @type  lpBaseAddress: int
1956        @param lpBaseAddress: Memory address to begin reading.
1957
1958        @type  nChars: int
1959        @param nChars: String length to read, in characters.
1960            Remember that Unicode strings have two byte characters.
1961
1962        @type  fUnicode: bool
1963        @param fUnicode: C{True} is the string is expected to be Unicode,
1964            C{False} if it's expected to be ANSI.
1965
1966        @rtype:  str, compat.unicode
1967        @return: String read from the process memory space.
1968
1969        @raise WindowsError: On error an exception is raised.
1970        """
1971        if fUnicode:
1972            nChars = nChars * 2
1973        szString = self.read(lpBaseAddress, nChars)
1974        if fUnicode:
1975            szString = compat.unicode(szString, 'U16', 'ignore')
1976        return szString
1977
1978#------------------------------------------------------------------------------
1979
1980    # FIXME this won't work properly with a different endianness!
1981    def __peek_c_type(self, address, format, c_type):
1982        size = ctypes.sizeof(c_type)
1983        packed = self.peek(address, size)
1984        if len(packed) < size:
1985            packed = '\0' * (size - len(packed)) + packed
1986        elif len(packed) > size:
1987            packed = packed[:size]
1988        return struct.unpack(format, packed)[0]
1989
1990    def __poke_c_type(self, address, format, unpacked):
1991        packed = struct.pack('@L', unpacked)
1992        return self.poke(address, packed)
1993
1994    def peek(self, lpBaseAddress, nSize):
1995        """
1996        Reads the memory of the process.
1997
1998        @see: L{read}
1999
2000        @type  lpBaseAddress: int
2001        @param lpBaseAddress: Memory address to begin reading.
2002
2003        @type  nSize: int
2004        @param nSize: Number of bytes to read.
2005
2006        @rtype:  str
2007        @return: Bytes read from the process memory.
2008            Returns an empty string on error.
2009        """
2010        # XXX TODO
2011        # + Maybe change page permissions before trying to read?
2012        # + Maybe use mquery instead of get_memory_map?
2013        #   (less syscalls if we break out of the loop earlier)
2014        data = ''
2015        if nSize > 0:
2016            try:
2017                hProcess = self.get_handle( win32.PROCESS_VM_READ |
2018                                            win32.PROCESS_QUERY_INFORMATION )
2019                for mbi in self.get_memory_map(lpBaseAddress,
2020                                               lpBaseAddress + nSize):
2021                    if not mbi.is_readable():
2022                        nSize = mbi.BaseAddress - lpBaseAddress
2023                        break
2024                if nSize > 0:
2025                    data = win32.ReadProcessMemory(
2026                                    hProcess, lpBaseAddress, nSize)
2027            except WindowsError:
2028                e = sys.exc_info()[1]
2029                msg = "Error reading process %d address %s: %s"
2030                msg %= (self.get_pid(),
2031                        HexDump.address(lpBaseAddress),
2032                        e.strerror)
2033                warnings.warn(msg)
2034        return data
2035
2036    def poke(self, lpBaseAddress, lpBuffer):
2037        """
2038        Writes to the memory of the process.
2039
2040        @note: Page permissions may be changed temporarily while writing.
2041
2042        @see: L{write}
2043
2044        @type  lpBaseAddress: int
2045        @param lpBaseAddress: Memory address to begin writing.
2046
2047        @type  lpBuffer: str
2048        @param lpBuffer: Bytes to write.
2049
2050        @rtype:  int
2051        @return: Number of bytes written.
2052            May be less than the number of bytes to write.
2053        """
2054        assert isinstance(lpBuffer, compat.bytes)
2055        hProcess = self.get_handle( win32.PROCESS_VM_WRITE |
2056                                    win32.PROCESS_VM_OPERATION |
2057                                    win32.PROCESS_QUERY_INFORMATION )
2058        mbi = self.mquery(lpBaseAddress)
2059        if not mbi.has_content():
2060            raise ctypes.WinError(win32.ERROR_INVALID_ADDRESS)
2061        if mbi.is_image() or mbi.is_mapped():
2062            prot = win32.PAGE_WRITECOPY
2063        elif mbi.is_writeable():
2064            prot = None
2065        elif mbi.is_executable():
2066            prot = win32.PAGE_EXECUTE_READWRITE
2067        else:
2068            prot = win32.PAGE_READWRITE
2069        if prot is not None:
2070            try:
2071                self.mprotect(lpBaseAddress, len(lpBuffer), prot)
2072            except Exception:
2073                prot = None
2074                msg = ("Failed to adjust page permissions"
2075                       " for process %s at address %s: %s")
2076                msg = msg % (self.get_pid(),
2077                             HexDump.address(lpBaseAddress, self.get_bits()),
2078                             traceback.format_exc())
2079                warnings.warn(msg, RuntimeWarning)
2080        try:
2081            r = win32.WriteProcessMemory(hProcess, lpBaseAddress, lpBuffer)
2082        finally:
2083            if prot is not None:
2084                self.mprotect(lpBaseAddress, len(lpBuffer), mbi.Protect)
2085        return r
2086
2087    def peek_char(self, lpBaseAddress):
2088        """
2089        Reads a single character from the memory of the process.
2090
2091        @see: L{read_char}
2092
2093        @type  lpBaseAddress: int
2094        @param lpBaseAddress: Memory address to begin reading.
2095
2096        @rtype:  int
2097        @return: Character read from the process memory.
2098            Returns zero on error.
2099        """
2100        char = self.peek(lpBaseAddress, 1)
2101        if char:
2102            return ord(char)
2103        return 0
2104
2105    def poke_char(self, lpBaseAddress, char):
2106        """
2107        Writes a single character to the memory of the process.
2108
2109        @note: Page permissions may be changed temporarily while writing.
2110
2111        @see: L{write_char}
2112
2113        @type  lpBaseAddress: int
2114        @param lpBaseAddress: Memory address to begin writing.
2115
2116        @type  char: str
2117        @param char: Character to write.
2118
2119        @rtype:  int
2120        @return: Number of bytes written.
2121            May be less than the number of bytes to write.
2122        """
2123        return self.poke(lpBaseAddress, chr(char))
2124
2125    def peek_int(self, lpBaseAddress):
2126        """
2127        Reads a signed integer from the memory of the process.
2128
2129        @see: L{read_int}
2130
2131        @type  lpBaseAddress: int
2132        @param lpBaseAddress: Memory address to begin reading.
2133
2134        @rtype:  int
2135        @return: Integer value read from the process memory.
2136            Returns zero on error.
2137        """
2138        return self.__peek_c_type(lpBaseAddress, '@l', ctypes.c_int)
2139
2140    def poke_int(self, lpBaseAddress, unpackedValue):
2141        """
2142        Writes a signed integer to the memory of the process.
2143
2144        @note: Page permissions may be changed temporarily while writing.
2145
2146        @see: L{write_int}
2147
2148        @type  lpBaseAddress: int
2149        @param lpBaseAddress: Memory address to begin writing.
2150
2151        @type  unpackedValue: int, long
2152        @param unpackedValue: Value to write.
2153
2154        @rtype:  int
2155        @return: Number of bytes written.
2156            May be less than the number of bytes to write.
2157        """
2158        return self.__poke_c_type(lpBaseAddress, '@l', unpackedValue)
2159
2160    def peek_uint(self, lpBaseAddress):
2161        """
2162        Reads an unsigned integer from the memory of the process.
2163
2164        @see: L{read_uint}
2165
2166        @type  lpBaseAddress: int
2167        @param lpBaseAddress: Memory address to begin reading.
2168
2169        @rtype:  int
2170        @return: Integer value read from the process memory.
2171            Returns zero on error.
2172        """
2173        return self.__peek_c_type(lpBaseAddress, '@L', ctypes.c_uint)
2174
2175    def poke_uint(self, lpBaseAddress, unpackedValue):
2176        """
2177        Writes an unsigned integer to the memory of the process.
2178
2179        @note: Page permissions may be changed temporarily while writing.
2180
2181        @see: L{write_uint}
2182
2183        @type  lpBaseAddress: int
2184        @param lpBaseAddress: Memory address to begin writing.
2185
2186        @type  unpackedValue: int, long
2187        @param unpackedValue: Value to write.
2188
2189        @rtype:  int
2190        @return: Number of bytes written.
2191            May be less than the number of bytes to write.
2192        """
2193        return self.__poke_c_type(lpBaseAddress, '@L', unpackedValue)
2194
2195    def peek_float(self, lpBaseAddress):
2196        """
2197        Reads a float from the memory of the process.
2198
2199        @see: L{read_float}
2200
2201        @type  lpBaseAddress: int
2202        @param lpBaseAddress: Memory address to begin reading.
2203
2204        @rtype:  int
2205        @return: Integer value read from the process memory.
2206            Returns zero on error.
2207        """
2208        return self.__peek_c_type(lpBaseAddress, '@f', ctypes.c_float)
2209
2210    def poke_float(self, lpBaseAddress, unpackedValue):
2211        """
2212        Writes a float to the memory of the process.
2213
2214        @note: Page permissions may be changed temporarily while writing.
2215
2216        @see: L{write_float}
2217
2218        @type  lpBaseAddress: int
2219        @param lpBaseAddress: Memory address to begin writing.
2220
2221        @type  unpackedValue: int, long
2222        @param unpackedValue: Value to write.
2223
2224        @rtype:  int
2225        @return: Number of bytes written.
2226            May be less than the number of bytes to write.
2227        """
2228        return self.__poke_c_type(lpBaseAddress, '@f', unpackedValue)
2229
2230    def peek_double(self, lpBaseAddress):
2231        """
2232        Reads a double from the memory of the process.
2233
2234        @see: L{read_double}
2235
2236        @type  lpBaseAddress: int
2237        @param lpBaseAddress: Memory address to begin reading.
2238
2239        @rtype:  int
2240        @return: Integer value read from the process memory.
2241            Returns zero on error.
2242        """
2243        return self.__peek_c_type(lpBaseAddress, '@d', ctypes.c_double)
2244
2245    def poke_double(self, lpBaseAddress, unpackedValue):
2246        """
2247        Writes a double to the memory of the process.
2248
2249        @note: Page permissions may be changed temporarily while writing.
2250
2251        @see: L{write_double}
2252
2253        @type  lpBaseAddress: int
2254        @param lpBaseAddress: Memory address to begin writing.
2255
2256        @type  unpackedValue: int, long
2257        @param unpackedValue: Value to write.
2258
2259        @rtype:  int
2260        @return: Number of bytes written.
2261            May be less than the number of bytes to write.
2262        """
2263        return self.__poke_c_type(lpBaseAddress, '@d', unpackedValue)
2264
2265    def peek_dword(self, lpBaseAddress):
2266        """
2267        Reads a DWORD from the memory of the process.
2268
2269        @see: L{read_dword}
2270
2271        @type  lpBaseAddress: int
2272        @param lpBaseAddress: Memory address to begin reading.
2273
2274        @rtype:  int
2275        @return: Integer value read from the process memory.
2276            Returns zero on error.
2277        """
2278        return self.__peek_c_type(lpBaseAddress, '=L', win32.DWORD)
2279
2280    def poke_dword(self, lpBaseAddress, unpackedValue):
2281        """
2282        Writes a DWORD to the memory of the process.
2283
2284        @note: Page permissions may be changed temporarily while writing.
2285
2286        @see: L{write_dword}
2287
2288        @type  lpBaseAddress: int
2289        @param lpBaseAddress: Memory address to begin writing.
2290
2291        @type  unpackedValue: int, long
2292        @param unpackedValue: Value to write.
2293
2294        @rtype:  int
2295        @return: Number of bytes written.
2296            May be less than the number of bytes to write.
2297        """
2298        return self.__poke_c_type(lpBaseAddress, '=L', unpackedValue)
2299
2300    def peek_qword(self, lpBaseAddress):
2301        """
2302        Reads a QWORD from the memory of the process.
2303
2304        @see: L{read_qword}
2305
2306        @type  lpBaseAddress: int
2307        @param lpBaseAddress: Memory address to begin reading.
2308
2309        @rtype:  int
2310        @return: Integer value read from the process memory.
2311            Returns zero on error.
2312        """
2313        return self.__peek_c_type(lpBaseAddress, '=Q', win32.QWORD)
2314
2315    def poke_qword(self, lpBaseAddress, unpackedValue):
2316        """
2317        Writes a QWORD to the memory of the process.
2318
2319        @note: Page permissions may be changed temporarily while writing.
2320
2321        @see: L{write_qword}
2322
2323        @type  lpBaseAddress: int
2324        @param lpBaseAddress: Memory address to begin writing.
2325
2326        @type  unpackedValue: int, long
2327        @param unpackedValue: Value to write.
2328
2329        @rtype:  int
2330        @return: Number of bytes written.
2331            May be less than the number of bytes to write.
2332        """
2333        return self.__poke_c_type(lpBaseAddress, '=Q', unpackedValue)
2334
2335    def peek_pointer(self, lpBaseAddress):
2336        """
2337        Reads a pointer value from the memory of the process.
2338
2339        @see: L{read_pointer}
2340
2341        @type  lpBaseAddress: int
2342        @param lpBaseAddress: Memory address to begin reading.
2343
2344        @rtype:  int
2345        @return: Pointer value read from the process memory.
2346            Returns zero on error.
2347        """
2348        return self.__peek_c_type(lpBaseAddress, '@P', ctypes.c_void_p)
2349
2350    def poke_pointer(self, lpBaseAddress, unpackedValue):
2351        """
2352        Writes a pointer value to the memory of the process.
2353
2354        @note: Page permissions may be changed temporarily while writing.
2355
2356        @see: L{write_pointer}
2357
2358        @type  lpBaseAddress: int
2359        @param lpBaseAddress: Memory address to begin writing.
2360
2361        @type  unpackedValue: int, long
2362        @param unpackedValue: Value to write.
2363
2364        @rtype:  int
2365        @return: Number of bytes written.
2366            May be less than the number of bytes to write.
2367        """
2368        return self.__poke_c_type(lpBaseAddress, '@P', unpackedValue)
2369
2370    def peek_string(self, lpBaseAddress, fUnicode = False, dwMaxSize = 0x1000):
2371        """
2372        Tries to read an ASCII or Unicode string
2373        from the address space of the process.
2374
2375        @see: L{read_string}
2376
2377        @type  lpBaseAddress: int
2378        @param lpBaseAddress: Memory address to begin reading.
2379
2380        @type  fUnicode: bool
2381        @param fUnicode: C{True} is the string is expected to be Unicode,
2382            C{False} if it's expected to be ANSI.
2383
2384        @type  dwMaxSize: int
2385        @param dwMaxSize: Maximum allowed string length to read, in bytes.
2386
2387        @rtype:  str, compat.unicode
2388        @return: String read from the process memory space.
2389            It B{doesn't} include the terminating null character.
2390            Returns an empty string on failure.
2391        """
2392
2393        # Validate the parameters.
2394        if not lpBaseAddress or dwMaxSize == 0:
2395            if fUnicode:
2396                return u''
2397            return ''
2398        if not dwMaxSize:
2399            dwMaxSize = 0x1000
2400
2401        # Read the string.
2402        szString = self.peek(lpBaseAddress, dwMaxSize)
2403
2404        # If the string is Unicode...
2405        if fUnicode:
2406
2407            # Decode the string.
2408            szString = compat.unicode(szString, 'U16', 'replace')
2409##            try:
2410##                szString = compat.unicode(szString, 'U16')
2411##            except UnicodeDecodeError:
2412##                szString = struct.unpack('H' * (len(szString) / 2), szString)
2413##                szString = [ unichr(c) for c in szString ]
2414##                szString = u''.join(szString)
2415
2416            # Truncate the string when the first null char is found.
2417            szString = szString[ : szString.find(u'\0') ]
2418
2419        # If the string is ANSI...
2420        else:
2421
2422            # Truncate the string when the first null char is found.
2423            szString = szString[ : szString.find('\0') ]
2424
2425        # Return the decoded string.
2426        return szString
2427
2428    # TODO
2429    # try to avoid reading the same page twice by caching it
2430    def peek_pointers_in_data(self, data, peekSize = 16, peekStep = 1):
2431        """
2432        Tries to guess which values in the given data are valid pointers,
2433        and reads some data from them.
2434
2435        @see: L{peek}
2436
2437        @type  data: str
2438        @param data: Binary data to find pointers in.
2439
2440        @type  peekSize: int
2441        @param peekSize: Number of bytes to read from each pointer found.
2442
2443        @type  peekStep: int
2444        @param peekStep: Expected data alignment.
2445            Tipically you specify 1 when data alignment is unknown,
2446            or 4 when you expect data to be DWORD aligned.
2447            Any other value may be specified.
2448
2449        @rtype:  dict( str S{->} str )
2450        @return: Dictionary mapping stack offsets to the data they point to.
2451        """
2452        result = dict()
2453        ptrSize = win32.sizeof(win32.LPVOID)
2454        if ptrSize == 4:
2455            ptrFmt = '<L'
2456        else:
2457            ptrFmt = '<Q'
2458        if len(data) > 0:
2459            for i in compat.xrange(0, len(data), peekStep):
2460                packed          = data[i:i+ptrSize]
2461                if len(packed) == ptrSize:
2462                    address     = struct.unpack(ptrFmt, packed)[0]
2463##                    if not address & (~0xFFFF): continue
2464                    peek_data   = self.peek(address, peekSize)
2465                    if peek_data:
2466                        result[i] = peek_data
2467        return result
2468
2469#------------------------------------------------------------------------------
2470
2471    def malloc(self, dwSize, lpAddress = None):
2472        """
2473        Allocates memory into the address space of the process.
2474
2475        @see: L{free}
2476
2477        @type  dwSize: int
2478        @param dwSize: Number of bytes to allocate.
2479
2480        @type  lpAddress: int
2481        @param lpAddress: (Optional)
2482            Desired address for the newly allocated memory.
2483            This is only a hint, the memory could still be allocated somewhere
2484            else.
2485
2486        @rtype:  int
2487        @return: Address of the newly allocated memory.
2488
2489        @raise WindowsError: On error an exception is raised.
2490        """
2491        hProcess = self.get_handle(win32.PROCESS_VM_OPERATION)
2492        return win32.VirtualAllocEx(hProcess, lpAddress, dwSize)
2493
2494    def mprotect(self, lpAddress, dwSize, flNewProtect):
2495        """
2496        Set memory protection in the address space of the process.
2497
2498        @see: U{http://msdn.microsoft.com/en-us/library/aa366899.aspx}
2499
2500        @type  lpAddress: int
2501        @param lpAddress: Address of memory to protect.
2502
2503        @type  dwSize: int
2504        @param dwSize: Number of bytes to protect.
2505
2506        @type  flNewProtect: int
2507        @param flNewProtect: New protect flags.
2508
2509        @rtype:  int
2510        @return: Old protect flags.
2511
2512        @raise WindowsError: On error an exception is raised.
2513        """
2514        hProcess = self.get_handle(win32.PROCESS_VM_OPERATION)
2515        return win32.VirtualProtectEx(hProcess, lpAddress, dwSize, flNewProtect)
2516
2517    def mquery(self, lpAddress):
2518        """
2519        Query memory information from the address space of the process.
2520        Returns a L{win32.MemoryBasicInformation} object.
2521
2522        @see: U{http://msdn.microsoft.com/en-us/library/aa366907(VS.85).aspx}
2523
2524        @type  lpAddress: int
2525        @param lpAddress: Address of memory to query.
2526
2527        @rtype:  L{win32.MemoryBasicInformation}
2528        @return: Memory region information.
2529
2530        @raise WindowsError: On error an exception is raised.
2531        """
2532        hProcess = self.get_handle(win32.PROCESS_QUERY_INFORMATION)
2533        return win32.VirtualQueryEx(hProcess, lpAddress)
2534
2535    def free(self, lpAddress):
2536        """
2537        Frees memory from the address space of the process.
2538
2539        @see: U{http://msdn.microsoft.com/en-us/library/aa366894(v=vs.85).aspx}
2540
2541        @type  lpAddress: int
2542        @param lpAddress: Address of memory to free.
2543            Must be the base address returned by L{malloc}.
2544
2545        @raise WindowsError: On error an exception is raised.
2546        """
2547        hProcess = self.get_handle(win32.PROCESS_VM_OPERATION)
2548        win32.VirtualFreeEx(hProcess, lpAddress)
2549
2550#------------------------------------------------------------------------------
2551
2552    def is_pointer(self, address):
2553        """
2554        Determines if an address is a valid code or data pointer.
2555
2556        That is, the address must be valid and must point to code or data in
2557        the target process.
2558
2559        @type  address: int
2560        @param address: Memory address to query.
2561
2562        @rtype:  bool
2563        @return: C{True} if the address is a valid code or data pointer.
2564
2565        @raise WindowsError: An exception is raised on error.
2566        """
2567        try:
2568            mbi = self.mquery(address)
2569        except WindowsError:
2570            e = sys.exc_info()[1]
2571            if e.winerror == win32.ERROR_INVALID_PARAMETER:
2572                return False
2573            raise
2574        return mbi.has_content()
2575
2576    def is_address_valid(self, address):
2577        """
2578        Determines if an address is a valid user mode address.
2579
2580        @type  address: int
2581        @param address: Memory address to query.
2582
2583        @rtype:  bool
2584        @return: C{True} if the address is a valid user mode address.
2585
2586        @raise WindowsError: An exception is raised on error.
2587        """
2588        try:
2589            mbi = self.mquery(address)
2590        except WindowsError:
2591            e = sys.exc_info()[1]
2592            if e.winerror == win32.ERROR_INVALID_PARAMETER:
2593                return False
2594            raise
2595        return True
2596
2597    def is_address_free(self, address):
2598        """
2599        Determines if an address belongs to a free page.
2600
2601        @note: Returns always C{False} for kernel mode addresses.
2602
2603        @type  address: int
2604        @param address: Memory address to query.
2605
2606        @rtype:  bool
2607        @return: C{True} if the address belongs to a free page.
2608
2609        @raise WindowsError: An exception is raised on error.
2610        """
2611        try:
2612            mbi = self.mquery(address)
2613        except WindowsError:
2614            e = sys.exc_info()[1]
2615            if e.winerror == win32.ERROR_INVALID_PARAMETER:
2616                return False
2617            raise
2618        return mbi.is_free()
2619
2620    def is_address_reserved(self, address):
2621        """
2622        Determines if an address belongs to a reserved page.
2623
2624        @note: Returns always C{False} for kernel mode addresses.
2625
2626        @type  address: int
2627        @param address: Memory address to query.
2628
2629        @rtype:  bool
2630        @return: C{True} if the address belongs to a reserved page.
2631
2632        @raise WindowsError: An exception is raised on error.
2633        """
2634        try:
2635            mbi = self.mquery(address)
2636        except WindowsError:
2637            e = sys.exc_info()[1]
2638            if e.winerror == win32.ERROR_INVALID_PARAMETER:
2639                return False
2640            raise
2641        return mbi.is_reserved()
2642
2643    def is_address_commited(self, address):
2644        """
2645        Determines if an address belongs to a commited page.
2646
2647        @note: Returns always C{False} for kernel mode addresses.
2648
2649        @type  address: int
2650        @param address: Memory address to query.
2651
2652        @rtype:  bool
2653        @return: C{True} if the address belongs to a commited page.
2654
2655        @raise WindowsError: An exception is raised on error.
2656        """
2657        try:
2658            mbi = self.mquery(address)
2659        except WindowsError:
2660            e = sys.exc_info()[1]
2661            if e.winerror == win32.ERROR_INVALID_PARAMETER:
2662                return False
2663            raise
2664        return mbi.is_commited()
2665
2666    def is_address_guard(self, address):
2667        """
2668        Determines if an address belongs to a guard page.
2669
2670        @note: Returns always C{False} for kernel mode addresses.
2671
2672        @type  address: int
2673        @param address: Memory address to query.
2674
2675        @rtype:  bool
2676        @return: C{True} if the address belongs to a guard page.
2677
2678        @raise WindowsError: An exception is raised on error.
2679        """
2680        try:
2681            mbi = self.mquery(address)
2682        except WindowsError:
2683            e = sys.exc_info()[1]
2684            if e.winerror == win32.ERROR_INVALID_PARAMETER:
2685                return False
2686            raise
2687        return mbi.is_guard()
2688
2689    def is_address_readable(self, address):
2690        """
2691        Determines if an address belongs to a commited and readable page.
2692        The page may or may not have additional permissions.
2693
2694        @note: Returns always C{False} for kernel mode addresses.
2695
2696        @type  address: int
2697        @param address: Memory address to query.
2698
2699        @rtype:  bool
2700        @return:
2701            C{True} if the address belongs to a commited and readable page.
2702
2703        @raise WindowsError: An exception is raised on error.
2704        """
2705        try:
2706            mbi = self.mquery(address)
2707        except WindowsError:
2708            e = sys.exc_info()[1]
2709            if e.winerror == win32.ERROR_INVALID_PARAMETER:
2710                return False
2711            raise
2712        return mbi.is_readable()
2713
2714    def is_address_writeable(self, address):
2715        """
2716        Determines if an address belongs to a commited and writeable page.
2717        The page may or may not have additional permissions.
2718
2719        @note: Returns always C{False} for kernel mode addresses.
2720
2721        @type  address: int
2722        @param address: Memory address to query.
2723
2724        @rtype:  bool
2725        @return:
2726            C{True} if the address belongs to a commited and writeable page.
2727
2728        @raise WindowsError: An exception is raised on error.
2729        """
2730        try:
2731            mbi = self.mquery(address)
2732        except WindowsError:
2733            e = sys.exc_info()[1]
2734            if e.winerror == win32.ERROR_INVALID_PARAMETER:
2735                return False
2736            raise
2737        return mbi.is_writeable()
2738
2739    def is_address_copy_on_write(self, address):
2740        """
2741        Determines if an address belongs to a commited, copy-on-write page.
2742        The page may or may not have additional permissions.
2743
2744        @note: Returns always C{False} for kernel mode addresses.
2745
2746        @type  address: int
2747        @param address: Memory address to query.
2748
2749        @rtype:  bool
2750        @return:
2751            C{True} if the address belongs to a commited, copy-on-write page.
2752
2753        @raise WindowsError: An exception is raised on error.
2754        """
2755        try:
2756            mbi = self.mquery(address)
2757        except WindowsError:
2758            e = sys.exc_info()[1]
2759            if e.winerror == win32.ERROR_INVALID_PARAMETER:
2760                return False
2761            raise
2762        return mbi.is_copy_on_write()
2763
2764    def is_address_executable(self, address):
2765        """
2766        Determines if an address belongs to a commited and executable page.
2767        The page may or may not have additional permissions.
2768
2769        @note: Returns always C{False} for kernel mode addresses.
2770
2771        @type  address: int
2772        @param address: Memory address to query.
2773
2774        @rtype:  bool
2775        @return:
2776            C{True} if the address belongs to a commited and executable page.
2777
2778        @raise WindowsError: An exception is raised on error.
2779        """
2780        try:
2781            mbi = self.mquery(address)
2782        except WindowsError:
2783            e = sys.exc_info()[1]
2784            if e.winerror == win32.ERROR_INVALID_PARAMETER:
2785                return False
2786            raise
2787        return mbi.is_executable()
2788
2789    def is_address_executable_and_writeable(self, address):
2790        """
2791        Determines if an address belongs to a commited, writeable and
2792        executable page. The page may or may not have additional permissions.
2793
2794        Looking for writeable and executable pages is important when
2795        exploiting a software vulnerability.
2796
2797        @note: Returns always C{False} for kernel mode addresses.
2798
2799        @type  address: int
2800        @param address: Memory address to query.
2801
2802        @rtype:  bool
2803        @return:
2804            C{True} if the address belongs to a commited, writeable and
2805            executable page.
2806
2807        @raise WindowsError: An exception is raised on error.
2808        """
2809        try:
2810            mbi = self.mquery(address)
2811        except WindowsError:
2812            e = sys.exc_info()[1]
2813            if e.winerror == win32.ERROR_INVALID_PARAMETER:
2814                return False
2815            raise
2816        return mbi.is_executable_and_writeable()
2817
2818    def is_buffer(self, address, size):
2819        """
2820        Determines if the given memory area is a valid code or data buffer.
2821
2822        @note: Returns always C{False} for kernel mode addresses.
2823
2824        @see: L{mquery}
2825
2826        @type  address: int
2827        @param address: Memory address.
2828
2829        @type  size: int
2830        @param size: Number of bytes. Must be greater than zero.
2831
2832        @rtype:  bool
2833        @return: C{True} if the memory area is a valid code or data buffer,
2834            C{False} otherwise.
2835
2836        @raise ValueError: The size argument must be greater than zero.
2837        @raise WindowsError: On error an exception is raised.
2838        """
2839        if size <= 0:
2840            raise ValueError("The size argument must be greater than zero")
2841        while size > 0:
2842            try:
2843                mbi = self.mquery(address)
2844            except WindowsError:
2845                e = sys.exc_info()[1]
2846                if e.winerror == win32.ERROR_INVALID_PARAMETER:
2847                    return False
2848                raise
2849            if not mbi.has_content():
2850                return False
2851            size = size - mbi.RegionSize
2852        return True
2853
2854    def is_buffer_readable(self, address, size):
2855        """
2856        Determines if the given memory area is readable.
2857
2858        @note: Returns always C{False} for kernel mode addresses.
2859
2860        @see: L{mquery}
2861
2862        @type  address: int
2863        @param address: Memory address.
2864
2865        @type  size: int
2866        @param size: Number of bytes. Must be greater than zero.
2867
2868        @rtype:  bool
2869        @return: C{True} if the memory area is readable, C{False} otherwise.
2870
2871        @raise ValueError: The size argument must be greater than zero.
2872        @raise WindowsError: On error an exception is raised.
2873        """
2874        if size <= 0:
2875            raise ValueError("The size argument must be greater than zero")
2876        while size > 0:
2877            try:
2878                mbi = self.mquery(address)
2879            except WindowsError:
2880                e = sys.exc_info()[1]
2881                if e.winerror == win32.ERROR_INVALID_PARAMETER:
2882                    return False
2883                raise
2884            if not mbi.is_readable():
2885                return False
2886            size = size - mbi.RegionSize
2887        return True
2888
2889    def is_buffer_writeable(self, address, size):
2890        """
2891        Determines if the given memory area is writeable.
2892
2893        @note: Returns always C{False} for kernel mode addresses.
2894
2895        @see: L{mquery}
2896
2897        @type  address: int
2898        @param address: Memory address.
2899
2900        @type  size: int
2901        @param size: Number of bytes. Must be greater than zero.
2902
2903        @rtype:  bool
2904        @return: C{True} if the memory area is writeable, C{False} otherwise.
2905
2906        @raise ValueError: The size argument must be greater than zero.
2907        @raise WindowsError: On error an exception is raised.
2908        """
2909        if size <= 0:
2910            raise ValueError("The size argument must be greater than zero")
2911        while size > 0:
2912            try:
2913                mbi = self.mquery(address)
2914            except WindowsError:
2915                e = sys.exc_info()[1]
2916                if e.winerror == win32.ERROR_INVALID_PARAMETER:
2917                    return False
2918                raise
2919            if not mbi.is_writeable():
2920                return False
2921            size = size - mbi.RegionSize
2922        return True
2923
2924    def is_buffer_copy_on_write(self, address, size):
2925        """
2926        Determines if the given memory area is marked as copy-on-write.
2927
2928        @note: Returns always C{False} for kernel mode addresses.
2929
2930        @see: L{mquery}
2931
2932        @type  address: int
2933        @param address: Memory address.
2934
2935        @type  size: int
2936        @param size: Number of bytes. Must be greater than zero.
2937
2938        @rtype:  bool
2939        @return: C{True} if the memory area is marked as copy-on-write,
2940            C{False} otherwise.
2941
2942        @raise ValueError: The size argument must be greater than zero.
2943        @raise WindowsError: On error an exception is raised.
2944        """
2945        if size <= 0:
2946            raise ValueError("The size argument must be greater than zero")
2947        while size > 0:
2948            try:
2949                mbi = self.mquery(address)
2950            except WindowsError:
2951                e = sys.exc_info()[1]
2952                if e.winerror == win32.ERROR_INVALID_PARAMETER:
2953                    return False
2954                raise
2955            if not mbi.is_copy_on_write():
2956                return False
2957            size = size - mbi.RegionSize
2958        return True
2959
2960    def is_buffer_executable(self, address, size):
2961        """
2962        Determines if the given memory area is executable.
2963
2964        @note: Returns always C{False} for kernel mode addresses.
2965
2966        @see: L{mquery}
2967
2968        @type  address: int
2969        @param address: Memory address.
2970
2971        @type  size: int
2972        @param size: Number of bytes. Must be greater than zero.
2973
2974        @rtype:  bool
2975        @return: C{True} if the memory area is executable, C{False} otherwise.
2976
2977        @raise ValueError: The size argument must be greater than zero.
2978        @raise WindowsError: On error an exception is raised.
2979        """
2980        if size <= 0:
2981            raise ValueError("The size argument must be greater than zero")
2982        while size > 0:
2983            try:
2984                mbi = self.mquery(address)
2985            except WindowsError:
2986                e = sys.exc_info()[1]
2987                if e.winerror == win32.ERROR_INVALID_PARAMETER:
2988                    return False
2989                raise
2990            if not mbi.is_executable():
2991                return False
2992            size = size - mbi.RegionSize
2993        return True
2994
2995    def is_buffer_executable_and_writeable(self, address, size):
2996        """
2997        Determines if the given memory area is writeable and executable.
2998
2999        Looking for writeable and executable pages is important when
3000        exploiting a software vulnerability.
3001
3002        @note: Returns always C{False} for kernel mode addresses.
3003
3004        @see: L{mquery}
3005
3006        @type  address: int
3007        @param address: Memory address.
3008
3009        @type  size: int
3010        @param size: Number of bytes. Must be greater than zero.
3011
3012        @rtype:  bool
3013        @return: C{True} if the memory area is writeable and executable,
3014            C{False} otherwise.
3015
3016        @raise ValueError: The size argument must be greater than zero.
3017        @raise WindowsError: On error an exception is raised.
3018        """
3019        if size <= 0:
3020            raise ValueError("The size argument must be greater than zero")
3021        while size > 0:
3022            try:
3023                mbi = self.mquery(address)
3024            except WindowsError:
3025                e = sys.exc_info()[1]
3026                if e.winerror == win32.ERROR_INVALID_PARAMETER:
3027                    return False
3028                raise
3029            if not mbi.is_executable():
3030                return False
3031            size = size - mbi.RegionSize
3032        return True
3033
3034    def get_memory_map(self, minAddr = None, maxAddr = None):
3035        """
3036        Produces a memory map to the process address space.
3037
3038        Optionally restrict the map to the given address range.
3039
3040        @see: L{mquery}
3041
3042        @type  minAddr: int
3043        @param minAddr: (Optional) Starting address in address range to query.
3044
3045        @type  maxAddr: int
3046        @param maxAddr: (Optional) Ending address in address range to query.
3047
3048        @rtype:  list( L{win32.MemoryBasicInformation} )
3049        @return: List of memory region information objects.
3050        """
3051        return list(self.iter_memory_map(minAddr, maxAddr))
3052
3053    def generate_memory_map(self, minAddr = None, maxAddr = None):
3054        """
3055        Returns a L{Regenerator} that can iterate indefinitely over the memory
3056        map to the process address space.
3057
3058        Optionally restrict the map to the given address range.
3059
3060        @see: L{mquery}
3061
3062        @type  minAddr: int
3063        @param minAddr: (Optional) Starting address in address range to query.
3064
3065        @type  maxAddr: int
3066        @param maxAddr: (Optional) Ending address in address range to query.
3067
3068        @rtype:  L{Regenerator} of L{win32.MemoryBasicInformation}
3069        @return: List of memory region information objects.
3070        """
3071        return Regenerator(self.iter_memory_map, minAddr, maxAddr)
3072
3073    def iter_memory_map(self, minAddr = None, maxAddr = None):
3074        """
3075        Produces an iterator over the memory map to the process address space.
3076
3077        Optionally restrict the map to the given address range.
3078
3079        @see: L{mquery}
3080
3081        @type  minAddr: int
3082        @param minAddr: (Optional) Starting address in address range to query.
3083
3084        @type  maxAddr: int
3085        @param maxAddr: (Optional) Ending address in address range to query.
3086
3087        @rtype:  iterator of L{win32.MemoryBasicInformation}
3088        @return: List of memory region information objects.
3089        """
3090        minAddr, maxAddr = MemoryAddresses.align_address_range(minAddr,maxAddr)
3091        prevAddr    = minAddr - 1
3092        currentAddr = minAddr
3093        while prevAddr < currentAddr < maxAddr:
3094            try:
3095                mbi = self.mquery(currentAddr)
3096            except WindowsError:
3097                e = sys.exc_info()[1]
3098                if e.winerror == win32.ERROR_INVALID_PARAMETER:
3099                    break
3100                raise
3101            yield mbi
3102            prevAddr    = currentAddr
3103            currentAddr = mbi.BaseAddress + mbi.RegionSize
3104
3105    def get_mapped_filenames(self, memoryMap = None):
3106        """
3107        Retrieves the filenames for memory mapped files in the debugee.
3108
3109        @type  memoryMap: list( L{win32.MemoryBasicInformation} )
3110        @param memoryMap: (Optional) Memory map returned by L{get_memory_map}.
3111            If not given, the current memory map is used.
3112
3113        @rtype:  dict( int S{->} str )
3114        @return: Dictionary mapping memory addresses to file names.
3115            Native filenames are converted to Win32 filenames when possible.
3116        """
3117        hProcess = self.get_handle( win32.PROCESS_VM_READ |
3118                                    win32.PROCESS_QUERY_INFORMATION )
3119        if not memoryMap:
3120            memoryMap = self.get_memory_map()
3121        mappedFilenames = dict()
3122        for mbi in memoryMap:
3123            if mbi.Type not in (win32.MEM_IMAGE, win32.MEM_MAPPED):
3124                continue
3125            baseAddress = mbi.BaseAddress
3126            fileName    = ""
3127            try:
3128                fileName = win32.GetMappedFileName(hProcess, baseAddress)
3129                fileName = PathOperations.native_to_win32_pathname(fileName)
3130            except WindowsError:
3131                #e = sys.exc_info()[1]
3132                #try:
3133                #    msg = "Can't get mapped file name at address %s in process " \
3134                #          "%d, reason: %s" % (HexDump.address(baseAddress),
3135                #                              self.get_pid(),
3136                #                              e.strerror)
3137                #    warnings.warn(msg, Warning)
3138                #except Exception:
3139                pass
3140            mappedFilenames[baseAddress] = fileName
3141        return mappedFilenames
3142
3143    def generate_memory_snapshot(self, minAddr = None, maxAddr = None):
3144        """
3145        Returns a L{Regenerator} that allows you to iterate through the memory
3146        contents of a process indefinitely.
3147
3148        It's basically the same as the L{take_memory_snapshot} method, but it
3149        takes the snapshot of each memory region as it goes, as opposed to
3150        taking the whole snapshot at once. This allows you to work with very
3151        large snapshots without a significant performance penalty.
3152
3153        Example::
3154            # Print the memory contents of a process.
3155            process.suspend()
3156            try:
3157                snapshot = process.generate_memory_snapshot()
3158                for mbi in snapshot:
3159                    print HexDump.hexblock(mbi.content, mbi.BaseAddress)
3160            finally:
3161                process.resume()
3162
3163        The downside of this is the process must remain suspended while
3164        iterating the snapshot, otherwise strange things may happen.
3165
3166        The snapshot can be iterated more than once. Each time it's iterated
3167        the memory contents of the process will be fetched again.
3168
3169        You can also iterate the memory of a dead process, just as long as the
3170        last open handle to it hasn't been closed.
3171
3172        @see: L{take_memory_snapshot}
3173
3174        @type  minAddr: int
3175        @param minAddr: (Optional) Starting address in address range to query.
3176
3177        @type  maxAddr: int
3178        @param maxAddr: (Optional) Ending address in address range to query.
3179
3180        @rtype:  L{Regenerator} of L{win32.MemoryBasicInformation}
3181        @return: Generator that when iterated returns memory region information
3182            objects. Two extra properties are added to these objects:
3183             - C{filename}: Mapped filename, or C{None}.
3184             - C{content}: Memory contents, or C{None}.
3185        """
3186        return Regenerator(self.iter_memory_snapshot, minAddr, maxAddr)
3187
3188    def iter_memory_snapshot(self, minAddr = None, maxAddr = None):
3189        """
3190        Returns an iterator that allows you to go through the memory contents
3191        of a process.
3192
3193        It's basically the same as the L{take_memory_snapshot} method, but it
3194        takes the snapshot of each memory region as it goes, as opposed to
3195        taking the whole snapshot at once. This allows you to work with very
3196        large snapshots without a significant performance penalty.
3197
3198        Example::
3199            # Print the memory contents of a process.
3200            process.suspend()
3201            try:
3202                snapshot = process.generate_memory_snapshot()
3203                for mbi in snapshot:
3204                    print HexDump.hexblock(mbi.content, mbi.BaseAddress)
3205            finally:
3206                process.resume()
3207
3208        The downside of this is the process must remain suspended while
3209        iterating the snapshot, otherwise strange things may happen.
3210
3211        The snapshot can only iterated once. To be able to iterate indefinitely
3212        call the L{generate_memory_snapshot} method instead.
3213
3214        You can also iterate the memory of a dead process, just as long as the
3215        last open handle to it hasn't been closed.
3216
3217        @see: L{take_memory_snapshot}
3218
3219        @type  minAddr: int
3220        @param minAddr: (Optional) Starting address in address range to query.
3221
3222        @type  maxAddr: int
3223        @param maxAddr: (Optional) Ending address in address range to query.
3224
3225        @rtype:  iterator of L{win32.MemoryBasicInformation}
3226        @return: Iterator of memory region information objects.
3227            Two extra properties are added to these objects:
3228             - C{filename}: Mapped filename, or C{None}.
3229             - C{content}: Memory contents, or C{None}.
3230        """
3231
3232        # One may feel tempted to include calls to self.suspend() and
3233        # self.resume() here, but that wouldn't work on a dead process.
3234        # It also wouldn't be needed when debugging since the process is
3235        # already suspended when the debug event arrives. So it's up to
3236        # the user to suspend the process if needed.
3237
3238        # Get the memory map.
3239        memory = self.get_memory_map(minAddr, maxAddr)
3240
3241        # Abort if the map couldn't be retrieved.
3242        if not memory:
3243            return
3244
3245        # Get the mapped filenames.
3246        # Don't fail on access denied errors.
3247        try:
3248            filenames = self.get_mapped_filenames(memory)
3249        except WindowsError:
3250            e = sys.exc_info()[1]
3251            if e.winerror != win32.ERROR_ACCESS_DENIED:
3252                raise
3253            filenames = dict()
3254
3255        # Trim the first memory information block if needed.
3256        if minAddr is not None:
3257            minAddr = MemoryAddresses.align_address_to_page_start(minAddr)
3258            mbi = memory[0]
3259            if mbi.BaseAddress < minAddr:
3260                mbi.RegionSize  = mbi.BaseAddress + mbi.RegionSize - minAddr
3261                mbi.BaseAddress = minAddr
3262
3263        # Trim the last memory information block if needed.
3264        if maxAddr is not None:
3265            if maxAddr != MemoryAddresses.align_address_to_page_start(maxAddr):
3266                maxAddr = MemoryAddresses.align_address_to_page_end(maxAddr)
3267            mbi = memory[-1]
3268            if mbi.BaseAddress + mbi.RegionSize > maxAddr:
3269                mbi.RegionSize = maxAddr - mbi.BaseAddress
3270
3271        # Read the contents of each block and yield it.
3272        while memory:
3273            mbi = memory.pop(0) # so the garbage collector can take it
3274            mbi.filename = filenames.get(mbi.BaseAddress, None)
3275            if mbi.has_content():
3276                mbi.content = self.read(mbi.BaseAddress, mbi.RegionSize)
3277            else:
3278                mbi.content = None
3279            yield mbi
3280
3281    def take_memory_snapshot(self, minAddr = None, maxAddr = None):
3282        """
3283        Takes a snapshot of the memory contents of the process.
3284
3285        It's best if the process is suspended (if alive) when taking the
3286        snapshot. Execution can be resumed afterwards.
3287
3288        Example::
3289            # Print the memory contents of a process.
3290            process.suspend()
3291            try:
3292                snapshot = process.take_memory_snapshot()
3293                for mbi in snapshot:
3294                    print HexDump.hexblock(mbi.content, mbi.BaseAddress)
3295            finally:
3296                process.resume()
3297
3298        You can also iterate the memory of a dead process, just as long as the
3299        last open handle to it hasn't been closed.
3300
3301        @warning: If the target process has a very big memory footprint, the
3302            resulting snapshot will be equally big. This may result in a severe
3303            performance penalty.
3304
3305        @see: L{generate_memory_snapshot}
3306
3307        @type  minAddr: int
3308        @param minAddr: (Optional) Starting address in address range to query.
3309
3310        @type  maxAddr: int
3311        @param maxAddr: (Optional) Ending address in address range to query.
3312
3313        @rtype:  list( L{win32.MemoryBasicInformation} )
3314        @return: List of memory region information objects.
3315            Two extra properties are added to these objects:
3316             - C{filename}: Mapped filename, or C{None}.
3317             - C{content}: Memory contents, or C{None}.
3318        """
3319        return list( self.iter_memory_snapshot(minAddr, maxAddr) )
3320
3321    def restore_memory_snapshot(self, snapshot,
3322                                bSkipMappedFiles = True,
3323                                bSkipOnError = False):
3324        """
3325        Attempts to restore the memory state as it was when the given snapshot
3326        was taken.
3327
3328        @warning: Currently only the memory contents, state and protect bits
3329            are restored. Under some circumstances this method may fail (for
3330            example if memory was freed and then reused by a mapped file).
3331
3332        @type  snapshot: list( L{win32.MemoryBasicInformation} )
3333        @param snapshot: Memory snapshot returned by L{take_memory_snapshot}.
3334            Snapshots returned by L{generate_memory_snapshot} don't work here.
3335
3336        @type  bSkipMappedFiles: bool
3337        @param bSkipMappedFiles: C{True} to avoid restoring the contents of
3338            memory mapped files, C{False} otherwise. Use with care! Setting
3339            this to C{False} can cause undesired side effects - changes to
3340            memory mapped files may be written to disk by the OS. Also note
3341            that most mapped files are typically executables and don't change,
3342            so trying to restore their contents is usually a waste of time.
3343
3344        @type  bSkipOnError: bool
3345        @param bSkipOnError: C{True} to issue a warning when an error occurs
3346            during the restoration of the snapshot, C{False} to stop and raise
3347            an exception instead. Use with care! Setting this to C{True} will
3348            cause the debugger to falsely believe the memory snapshot has been
3349            correctly restored.
3350
3351        @raise WindowsError: An error occured while restoring the snapshot.
3352        @raise RuntimeError: An error occured while restoring the snapshot.
3353        @raise TypeError: A snapshot of the wrong type was passed.
3354        """
3355        if not snapshot or not isinstance(snapshot, list) \
3356                or not isinstance(snapshot[0], win32.MemoryBasicInformation):
3357            raise TypeError( "Only snapshots returned by " \
3358                             "take_memory_snapshot() can be used here." )
3359
3360        # Get the process handle.
3361        hProcess = self.get_handle( win32.PROCESS_VM_WRITE          |
3362                                    win32.PROCESS_VM_OPERATION      |
3363                                    win32.PROCESS_SUSPEND_RESUME    |
3364                                    win32.PROCESS_QUERY_INFORMATION )
3365
3366        # Freeze the process.
3367        self.suspend()
3368        try:
3369
3370            # For each memory region in the snapshot...
3371            for old_mbi in snapshot:
3372
3373                # If the region matches, restore it directly.
3374                new_mbi = self.mquery(old_mbi.BaseAddress)
3375                if new_mbi.BaseAddress == old_mbi.BaseAddress and \
3376                                    new_mbi.RegionSize == old_mbi.RegionSize:
3377                    self.__restore_mbi(hProcess, new_mbi, old_mbi,
3378                                       bSkipMappedFiles)
3379
3380                # If the region doesn't match, restore it page by page.
3381                else:
3382
3383                    # We need a copy so we don't corrupt the snapshot.
3384                    old_mbi = win32.MemoryBasicInformation(old_mbi)
3385
3386                    # Get the overlapping range of pages.
3387                    old_start = old_mbi.BaseAddress
3388                    old_end   = old_start + old_mbi.RegionSize
3389                    new_start = new_mbi.BaseAddress
3390                    new_end   = new_start + new_mbi.RegionSize
3391                    if old_start > new_start:
3392                        start = old_start
3393                    else:
3394                        start = new_start
3395                    if old_end < new_end:
3396                        end = old_end
3397                    else:
3398                        end = new_end
3399
3400                    # Restore each page in the overlapping range.
3401                    step = MemoryAddresses.pageSize
3402                    old_mbi.RegionSize = step
3403                    new_mbi.RegionSize = step
3404                    address = start
3405                    while address < end:
3406                        old_mbi.BaseAddress = address
3407                        new_mbi.BaseAddress = address
3408                        self.__restore_mbi(hProcess, new_mbi, old_mbi,
3409                                           bSkipMappedFiles, bSkipOnError)
3410                        address = address + step
3411
3412        # Resume execution.
3413        finally:
3414            self.resume()
3415
3416    def __restore_mbi(self, hProcess, new_mbi, old_mbi, bSkipMappedFiles,
3417                      bSkipOnError):
3418        """
3419        Used internally by L{restore_memory_snapshot}.
3420        """
3421
3422##        print "Restoring %s-%s" % (
3423##            HexDump.address(old_mbi.BaseAddress, self.get_bits()),
3424##            HexDump.address(old_mbi.BaseAddress + old_mbi.RegionSize,
3425##                            self.get_bits()))
3426
3427        try:
3428
3429            # Restore the region state.
3430            if new_mbi.State != old_mbi.State:
3431                if new_mbi.is_free():
3432                    if old_mbi.is_reserved():
3433
3434                        # Free -> Reserved
3435                        address = win32.VirtualAllocEx(hProcess,
3436                                                       old_mbi.BaseAddress,
3437                                                       old_mbi.RegionSize,
3438                                                       win32.MEM_RESERVE,
3439                                                       old_mbi.Protect)
3440                        if address != old_mbi.BaseAddress:
3441                            self.free(address)
3442                            msg = "Error restoring region at address %s"
3443                            msg = msg % HexDump(old_mbi.BaseAddress,
3444                                                self.get_bits())
3445                            raise RuntimeError(msg)
3446                        # permissions already restored
3447                        new_mbi.Protect = old_mbi.Protect
3448
3449                    else:   # elif old_mbi.is_commited():
3450
3451                        # Free -> Commited
3452                        address = win32.VirtualAllocEx(hProcess,
3453                                                       old_mbi.BaseAddress,
3454                                                       old_mbi.RegionSize,
3455                                                       win32.MEM_RESERVE | \
3456                                                       win32.MEM_COMMIT,
3457                                                       old_mbi.Protect)
3458                        if address != old_mbi.BaseAddress:
3459                            self.free(address)
3460                            msg = "Error restoring region at address %s"
3461                            msg = msg % HexDump(old_mbi.BaseAddress,
3462                                                self.get_bits())
3463                            raise RuntimeError(msg)
3464                        # permissions already restored
3465                        new_mbi.Protect = old_mbi.Protect
3466
3467                elif new_mbi.is_reserved():
3468                    if old_mbi.is_commited():
3469
3470                        # Reserved -> Commited
3471                        address = win32.VirtualAllocEx(hProcess,
3472                                                       old_mbi.BaseAddress,
3473                                                       old_mbi.RegionSize,
3474                                                       win32.MEM_COMMIT,
3475                                                       old_mbi.Protect)
3476                        if address != old_mbi.BaseAddress:
3477                            self.free(address)
3478                            msg = "Error restoring region at address %s"
3479                            msg = msg % HexDump(old_mbi.BaseAddress,
3480                                                self.get_bits())
3481                            raise RuntimeError(msg)
3482                        # permissions already restored
3483                        new_mbi.Protect = old_mbi.Protect
3484
3485                    else:   # elif old_mbi.is_free():
3486
3487                        # Reserved -> Free
3488                        win32.VirtualFreeEx(hProcess,
3489                                            old_mbi.BaseAddress,
3490                                            old_mbi.RegionSize,
3491                                            win32.MEM_RELEASE)
3492
3493                else:   # elif new_mbi.is_commited():
3494                    if old_mbi.is_reserved():
3495
3496                        # Commited -> Reserved
3497                        win32.VirtualFreeEx(hProcess,
3498                                            old_mbi.BaseAddress,
3499                                            old_mbi.RegionSize,
3500                                            win32.MEM_DECOMMIT)
3501
3502                    else:   # elif old_mbi.is_free():
3503
3504                        # Commited -> Free
3505                        win32.VirtualFreeEx(hProcess,
3506                                            old_mbi.BaseAddress,
3507                                            old_mbi.RegionSize,
3508                                            win32.MEM_DECOMMIT | win32.MEM_RELEASE)
3509
3510            new_mbi.State = old_mbi.State
3511
3512            # Restore the region permissions.
3513            if old_mbi.is_commited() and old_mbi.Protect != new_mbi.Protect:
3514                win32.VirtualProtectEx(hProcess, old_mbi.BaseAddress,
3515                                       old_mbi.RegionSize, old_mbi.Protect)
3516                new_mbi.Protect = old_mbi.Protect
3517
3518            # Restore the region data.
3519            # Ignore write errors when the region belongs to a mapped file.
3520            if old_mbi.has_content():
3521                if old_mbi.Type != 0:
3522                    if not bSkipMappedFiles:
3523                        self.poke(old_mbi.BaseAddress, old_mbi.content)
3524                else:
3525                    self.write(old_mbi.BaseAddress, old_mbi.content)
3526                new_mbi.content = old_mbi.content
3527
3528        # On error, skip this region or raise an exception.
3529        except Exception:
3530            if not bSkipOnError:
3531                raise
3532            msg = "Error restoring region at address %s: %s"
3533            msg = msg % (
3534                HexDump(old_mbi.BaseAddress, self.get_bits()),
3535                traceback.format_exc())
3536            warnings.warn(msg, RuntimeWarning)
3537
3538#------------------------------------------------------------------------------
3539
3540    def inject_code(self, payload, lpParameter = 0):
3541        """
3542        Injects relocatable code into the process memory and executes it.
3543
3544        @warning: Don't forget to free the memory when you're done with it!
3545            Otherwise you'll be leaking memory in the target process.
3546
3547        @see: L{inject_dll}
3548
3549        @type  payload: str
3550        @param payload: Relocatable code to run in a new thread.
3551
3552        @type  lpParameter: int
3553        @param lpParameter: (Optional) Parameter to be pushed in the stack.
3554
3555        @rtype:  tuple( L{Thread}, int )
3556        @return: The injected Thread object
3557            and the memory address where the code was written.
3558
3559        @raise WindowsError: An exception is raised on error.
3560        """
3561
3562        # Uncomment for debugging...
3563##        payload = '\xCC' + payload
3564
3565        # Allocate the memory for the shellcode.
3566        lpStartAddress = self.malloc(len(payload))
3567
3568        # Catch exceptions so we can free the memory on error.
3569        try:
3570
3571            # Write the shellcode to our memory location.
3572            self.write(lpStartAddress, payload)
3573
3574            # Start a new thread for the shellcode to run.
3575            aThread = self.start_thread(lpStartAddress, lpParameter,
3576                                                            bSuspended = False)
3577
3578            # Remember the shellcode address.
3579            #  It will be freed ONLY by the Thread.kill() method
3580            #  and the EventHandler class, otherwise you'll have to
3581            #  free it in your code, or have your shellcode clean up
3582            #  after itself (recommended).
3583            aThread.pInjectedMemory = lpStartAddress
3584
3585        # Free the memory on error.
3586        except Exception:
3587            self.free(lpStartAddress)
3588            raise
3589
3590        # Return the Thread object and the shellcode address.
3591        return aThread, lpStartAddress
3592
3593    # TODO
3594    # The shellcode should check for errors, otherwise it just crashes
3595    # when the DLL can't be loaded or the procedure can't be found.
3596    # On error the shellcode should execute an int3 instruction.
3597    def inject_dll(self, dllname, procname = None, lpParameter = 0,
3598                                               bWait = True, dwTimeout = None):
3599        """
3600        Injects a DLL into the process memory.
3601
3602        @warning: Setting C{bWait} to C{True} when the process is frozen by a
3603            debug event will cause a deadlock in your debugger.
3604
3605        @warning: This involves allocating memory in the target process.
3606            This is how the freeing of this memory is handled:
3607
3608             - If the C{bWait} flag is set to C{True} the memory will be freed
3609               automatically before returning from this method.
3610             - If the C{bWait} flag is set to C{False}, the memory address is
3611               set as the L{Thread.pInjectedMemory} property of the returned
3612               thread object.
3613             - L{Debug} objects free L{Thread.pInjectedMemory} automatically
3614               both when it detaches from a process and when the injected
3615               thread finishes its execution.
3616             - The {Thread.kill} method also frees L{Thread.pInjectedMemory}
3617               automatically, even if you're not attached to the process.
3618
3619            You could still be leaking memory if not careful. For example, if
3620            you inject a dll into a process you're not attached to, you don't
3621            wait for the thread's completion and you don't kill it either, the
3622            memory would be leaked.
3623
3624        @see: L{inject_code}
3625
3626        @type  dllname: str
3627        @param dllname: Name of the DLL module to load.
3628
3629        @type  procname: str
3630        @param procname: (Optional) Procedure to call when the DLL is loaded.
3631
3632        @type  lpParameter: int
3633        @param lpParameter: (Optional) Parameter to the C{procname} procedure.
3634
3635        @type  bWait: bool
3636        @param bWait: C{True} to wait for the process to finish.
3637            C{False} to return immediately.
3638
3639        @type  dwTimeout: int
3640        @param dwTimeout: (Optional) Timeout value in milliseconds.
3641            Ignored if C{bWait} is C{False}.
3642
3643        @rtype: L{Thread}
3644        @return: Newly created thread object. If C{bWait} is set to C{True} the
3645            thread will be dead, otherwise it will be alive.
3646
3647        @raise NotImplementedError: The target platform is not supported.
3648            Currently calling a procedure in the library is only supported in
3649            the I{i386} architecture.
3650
3651        @raise WindowsError: An exception is raised on error.
3652        """
3653
3654        # Resolve kernel32.dll
3655        aModule = self.get_module_by_name(compat.b('kernel32.dll'))
3656        if aModule is None:
3657            self.scan_modules()
3658            aModule = self.get_module_by_name(compat.b('kernel32.dll'))
3659        if aModule is None:
3660            raise RuntimeError(
3661                "Cannot resolve kernel32.dll in the remote process")
3662
3663        # Old method, using shellcode.
3664        if procname:
3665            if self.get_arch() != win32.ARCH_I386:
3666                raise NotImplementedError()
3667            dllname = compat.b(dllname)
3668
3669            # Resolve kernel32.dll!LoadLibraryA
3670            pllib = aModule.resolve(compat.b('LoadLibraryA'))
3671            if not pllib:
3672                raise RuntimeError(
3673                    "Cannot resolve kernel32.dll!LoadLibraryA"
3674                    " in the remote process")
3675
3676            # Resolve kernel32.dll!GetProcAddress
3677            pgpad = aModule.resolve(compat.b('GetProcAddress'))
3678            if not pgpad:
3679                raise RuntimeError(
3680                    "Cannot resolve kernel32.dll!GetProcAddress"
3681                    " in the remote process")
3682
3683            # Resolve kernel32.dll!VirtualFree
3684            pvf = aModule.resolve(compat.b('VirtualFree'))
3685            if not pvf:
3686                raise RuntimeError(
3687                    "Cannot resolve kernel32.dll!VirtualFree"
3688                    " in the remote process")
3689
3690            # Shellcode follows...
3691            code  = compat.b('')
3692
3693            # push dllname
3694            code += compat.b('\xe8') + struct.pack('<L', len(dllname) + 1) + dllname + compat.b('\0')
3695
3696            # mov eax, LoadLibraryA
3697            code += compat.b('\xb8') + struct.pack('<L', pllib)
3698
3699            # call eax
3700            code += compat.b('\xff\xd0')
3701
3702            if procname:
3703
3704                # push procname
3705                code += compat.b('\xe8') + struct.pack('<L', len(procname) + 1)
3706                code += procname + compat.b('\0')
3707
3708                # push eax
3709                code += compat.b('\x50')
3710
3711                # mov eax, GetProcAddress
3712                code += compat.b('\xb8') + struct.pack('<L', pgpad)
3713
3714                # call eax
3715                code += compat.b('\xff\xd0')
3716
3717                # mov ebp, esp      ; preserve stack pointer
3718                code += compat.b('\x8b\xec')
3719
3720                # push lpParameter
3721                code += compat.b('\x68') + struct.pack('<L', lpParameter)
3722
3723                # call eax
3724                code += compat.b('\xff\xd0')
3725
3726                # mov esp, ebp      ; restore stack pointer
3727                code += compat.b('\x8b\xe5')
3728
3729            # pop edx       ; our own return address
3730            code += compat.b('\x5a')
3731
3732            # push MEM_RELEASE  ; dwFreeType
3733            code += compat.b('\x68') + struct.pack('<L', win32.MEM_RELEASE)
3734
3735            # push 0x1000       ; dwSize, shellcode max size 4096 bytes
3736            code += compat.b('\x68') + struct.pack('<L', 0x1000)
3737
3738            # call $+5
3739            code += compat.b('\xe8\x00\x00\x00\x00')
3740
3741            # and dword ptr [esp], 0xFFFFF000   ; align to page boundary
3742            code += compat.b('\x81\x24\x24\x00\xf0\xff\xff')
3743
3744            # mov eax, VirtualFree
3745            code += compat.b('\xb8') + struct.pack('<L', pvf)
3746
3747            # push edx      ; our own return address
3748            code += compat.b('\x52')
3749
3750            # jmp eax   ; VirtualFree will return to our own return address
3751            code += compat.b('\xff\xe0')
3752
3753            # Inject the shellcode.
3754            # There's no need to free the memory,
3755            # because the shellcode will free it itself.
3756            aThread, lpStartAddress = self.inject_code(code, lpParameter)
3757
3758        # New method, not using shellcode.
3759        else:
3760
3761            # Resolve kernel32.dll!LoadLibrary (A/W)
3762            if type(dllname) == type(u''):
3763                pllibname = compat.b('LoadLibraryW')
3764                bufferlen = (len(dllname) + 1) * 2
3765                dllname = win32.ctypes.create_unicode_buffer(dllname).raw[:bufferlen + 1]
3766            else:
3767                pllibname = compat.b('LoadLibraryA')
3768                dllname   = compat.b(dllname) + compat.b('\x00')
3769                bufferlen = len(dllname)
3770            pllib = aModule.resolve(pllibname)
3771            if not pllib:
3772                msg = "Cannot resolve kernel32.dll!%s in the remote process"
3773                raise RuntimeError(msg % pllibname)
3774
3775            # Copy the library name into the process memory space.
3776            pbuffer = self.malloc(bufferlen)
3777            try:
3778                self.write(pbuffer, dllname)
3779
3780                # Create a new thread to load the library.
3781                try:
3782                    aThread = self.start_thread(pllib, pbuffer)
3783                except WindowsError:
3784                    e = sys.exc_info()[1]
3785                    if e.winerror != win32.ERROR_NOT_ENOUGH_MEMORY:
3786                        raise
3787
3788                    # This specific error is caused by trying to spawn a new
3789                    # thread in a process belonging to a different Terminal
3790                    # Services session (for example a service).
3791                    raise NotImplementedError(
3792                        "Target process belongs to a different"
3793                        " Terminal Services session, cannot inject!"
3794                    )
3795
3796                # Remember the buffer address.
3797                #  It will be freed ONLY by the Thread.kill() method
3798                #  and the EventHandler class, otherwise you'll have to
3799                #  free it in your code.
3800                aThread.pInjectedMemory = pbuffer
3801
3802            # Free the memory on error.
3803            except Exception:
3804                self.free(pbuffer)
3805                raise
3806
3807        # Wait for the thread to finish.
3808        if bWait:
3809            aThread.wait(dwTimeout)
3810            self.free(aThread.pInjectedMemory)
3811            del aThread.pInjectedMemory
3812
3813        # Return the thread object.
3814        return aThread
3815
3816    def clean_exit(self, dwExitCode = 0, bWait = False, dwTimeout = None):
3817        """
3818        Injects a new thread to call ExitProcess().
3819        Optionally waits for the injected thread to finish.
3820
3821        @warning: Setting C{bWait} to C{True} when the process is frozen by a
3822            debug event will cause a deadlock in your debugger.
3823
3824        @type  dwExitCode: int
3825        @param dwExitCode: Process exit code.
3826
3827        @type  bWait: bool
3828        @param bWait: C{True} to wait for the process to finish.
3829            C{False} to return immediately.
3830
3831        @type  dwTimeout: int
3832        @param dwTimeout: (Optional) Timeout value in milliseconds.
3833            Ignored if C{bWait} is C{False}.
3834
3835        @raise WindowsError: An exception is raised on error.
3836        """
3837        if not dwExitCode:
3838            dwExitCode = 0
3839        pExitProcess = self.resolve_label('kernel32!ExitProcess')
3840        aThread = self.start_thread(pExitProcess, dwExitCode)
3841        if bWait:
3842            aThread.wait(dwTimeout)
3843
3844#------------------------------------------------------------------------------
3845
3846    def _notify_create_process(self, event):
3847        """
3848        Notify the creation of a new process.
3849
3850        This is done automatically by the L{Debug} class, you shouldn't need
3851        to call it yourself.
3852
3853        @type  event: L{CreateProcessEvent}
3854        @param event: Create process event.
3855
3856        @rtype:  bool
3857        @return: C{True} to call the user-defined handle, C{False} otherwise.
3858        """
3859        # Do not use super() here.
3860        bCallHandler = _ThreadContainer._notify_create_process(self, event)
3861        bCallHandler = bCallHandler and \
3862                           _ModuleContainer._notify_create_process(self, event)
3863        return bCallHandler
3864
3865#==============================================================================
3866
3867class _ProcessContainer (object):
3868    """
3869    Encapsulates the capability to contain Process objects.
3870
3871    @group Instrumentation:
3872        start_process, argv_to_cmdline, cmdline_to_argv, get_explorer_pid
3873
3874    @group Processes snapshot:
3875        scan, scan_processes, scan_processes_fast,
3876        get_process, get_process_count, get_process_ids,
3877        has_process, iter_processes, iter_process_ids,
3878        find_processes_by_filename, get_pid_from_tid,
3879        get_windows,
3880        scan_process_filenames,
3881        clear, clear_processes, clear_dead_processes,
3882        clear_unattached_processes,
3883        close_process_handles,
3884        close_process_and_thread_handles
3885
3886    @group Threads snapshots:
3887        scan_processes_and_threads,
3888        get_thread, get_thread_count, get_thread_ids,
3889        has_thread
3890
3891    @group Modules snapshots:
3892        scan_modules, find_modules_by_address,
3893        find_modules_by_base, find_modules_by_name,
3894        get_module_count
3895    """
3896
3897    def __init__(self):
3898        self.__processDict = dict()
3899
3900    def __initialize_snapshot(self):
3901        """
3902        Private method to automatically initialize the snapshot
3903        when you try to use it without calling any of the scan_*
3904        methods first. You don't need to call this yourself.
3905        """
3906        if not self.__processDict:
3907            try:
3908                self.scan_processes()       # remote desktop api (relative fn)
3909            except Exception:
3910                self.scan_processes_fast()  # psapi (no filenames)
3911            self.scan_process_filenames()   # get the pathnames when possible
3912
3913    def __contains__(self, anObject):
3914        """
3915        @type  anObject: L{Process}, L{Thread}, int
3916        @param anObject:
3917             - C{int}: Global ID of the process to look for.
3918             - C{int}: Global ID of the thread to look for.
3919             - C{Process}: Process object to look for.
3920             - C{Thread}: Thread object to look for.
3921
3922        @rtype:  bool
3923        @return: C{True} if the snapshot contains
3924            a L{Process} or L{Thread} object with the same ID.
3925        """
3926        if isinstance(anObject, Process):
3927            anObject = anObject.dwProcessId
3928        if self.has_process(anObject):
3929            return True
3930        for aProcess in self.iter_processes():
3931            if anObject in aProcess:
3932                return True
3933        return False
3934
3935    def __iter__(self):
3936        """
3937        @see:    L{iter_processes}
3938        @rtype:  dictionary-valueiterator
3939        @return: Iterator of L{Process} objects in this snapshot.
3940        """
3941        return self.iter_processes()
3942
3943    def __len__(self):
3944        """
3945        @see:    L{get_process_count}
3946        @rtype:  int
3947        @return: Count of L{Process} objects in this snapshot.
3948        """
3949        return self.get_process_count()
3950
3951    def has_process(self, dwProcessId):
3952        """
3953        @type  dwProcessId: int
3954        @param dwProcessId: Global ID of the process to look for.
3955
3956        @rtype:  bool
3957        @return: C{True} if the snapshot contains a
3958            L{Process} object with the given global ID.
3959        """
3960        self.__initialize_snapshot()
3961        return dwProcessId in self.__processDict
3962
3963    def get_process(self, dwProcessId):
3964        """
3965        @type  dwProcessId: int
3966        @param dwProcessId: Global ID of the process to look for.
3967
3968        @rtype:  L{Process}
3969        @return: Process object with the given global ID.
3970        """
3971        self.__initialize_snapshot()
3972        if dwProcessId not in self.__processDict:
3973            msg = "Unknown process ID %d" % dwProcessId
3974            raise KeyError(msg)
3975        return self.__processDict[dwProcessId]
3976
3977    def iter_process_ids(self):
3978        """
3979        @see:    L{iter_processes}
3980        @rtype:  dictionary-keyiterator
3981        @return: Iterator of global process IDs in this snapshot.
3982        """
3983        self.__initialize_snapshot()
3984        return compat.iterkeys(self.__processDict)
3985
3986    def iter_processes(self):
3987        """
3988        @see:    L{iter_process_ids}
3989        @rtype:  dictionary-valueiterator
3990        @return: Iterator of L{Process} objects in this snapshot.
3991        """
3992        self.__initialize_snapshot()
3993        return compat.itervalues(self.__processDict)
3994
3995    def get_process_ids(self):
3996        """
3997        @see:    L{iter_process_ids}
3998        @rtype:  list( int )
3999        @return: List of global process IDs in this snapshot.
4000        """
4001        self.__initialize_snapshot()
4002        return compat.keys(self.__processDict)
4003
4004    def get_process_count(self):
4005        """
4006        @rtype:  int
4007        @return: Count of L{Process} objects in this snapshot.
4008        """
4009        self.__initialize_snapshot()
4010        return len(self.__processDict)
4011
4012#------------------------------------------------------------------------------
4013
4014    # XXX TODO
4015    # Support for string searches on the window captions.
4016
4017    def get_windows(self):
4018        """
4019        @rtype:  list of L{Window}
4020        @return: Returns a list of windows
4021            handled by all processes in this snapshot.
4022        """
4023        window_list = list()
4024        for process in self.iter_processes():
4025            window_list.extend( process.get_windows() )
4026        return window_list
4027
4028    def get_pid_from_tid(self, dwThreadId):
4029        """
4030        Retrieves the global ID of the process that owns the thread.
4031
4032        @type  dwThreadId: int
4033        @param dwThreadId: Thread global ID.
4034
4035        @rtype:  int
4036        @return: Process global ID.
4037
4038        @raise KeyError: The thread does not exist.
4039        """
4040        try:
4041
4042            # No good, because in XP and below it tries to get the PID
4043            # through the toolhelp API, and that's slow. We don't want
4044            # to scan for threads over and over for each call.
4045##            dwProcessId = Thread(dwThreadId).get_pid()
4046
4047            # This API only exists in Windows 2003, Vista and above.
4048            try:
4049                hThread = win32.OpenThread(
4050                    win32.THREAD_QUERY_LIMITED_INFORMATION, False, dwThreadId)
4051            except WindowsError:
4052                e = sys.exc_info()[1]
4053                if e.winerror != win32.ERROR_ACCESS_DENIED:
4054                    raise
4055                hThread = win32.OpenThread(
4056                    win32.THREAD_QUERY_INFORMATION, False, dwThreadId)
4057            try:
4058                return win32.GetProcessIdOfThread(hThread)
4059            finally:
4060                hThread.close()
4061
4062        # If all else fails, go through all processes in the snapshot
4063        # looking for the one that owns the thread we're looking for.
4064        # If the snapshot was empty the iteration should trigger an
4065        # automatic scan. Otherwise, it'll look for the thread in what
4066        # could possibly be an outdated snapshot.
4067        except Exception:
4068            for aProcess in self.iter_processes():
4069                if aProcess.has_thread(dwThreadId):
4070                    return aProcess.get_pid()
4071
4072        # The thread wasn't found, so let's refresh the snapshot and retry.
4073        # Normally this shouldn't happen since this function is only useful
4074        # for the debugger, so the thread should already exist in the snapshot.
4075        self.scan_processes_and_threads()
4076        for aProcess in self.iter_processes():
4077            if aProcess.has_thread(dwThreadId):
4078                return aProcess.get_pid()
4079
4080        # No luck! It appears to be the thread doesn't exist after all.
4081        msg = "Unknown thread ID %d" % dwThreadId
4082        raise KeyError(msg)
4083
4084#------------------------------------------------------------------------------
4085
4086    @staticmethod
4087    def argv_to_cmdline(argv):
4088        """
4089        Convert a list of arguments to a single command line string.
4090
4091        @type  argv: list( str )
4092        @param argv: List of argument strings.
4093            The first element is the program to execute.
4094
4095        @rtype:  str
4096        @return: Command line string.
4097        """
4098        cmdline = list()
4099        for token in argv:
4100            if not token:
4101                token = '""'
4102            else:
4103                if '"' in token:
4104                    token = token.replace('"', '\\"')
4105                if  ' ' in token  or \
4106                    '\t' in token or \
4107                    '\n' in token or \
4108                    '\r' in token:
4109                        token = '"%s"' % token
4110            cmdline.append(token)
4111        return ' '.join(cmdline)
4112
4113    @staticmethod
4114    def cmdline_to_argv(lpCmdLine):
4115        """
4116        Convert a single command line string to a list of arguments.
4117
4118        @type  lpCmdLine: str
4119        @param lpCmdLine: Command line string.
4120            The first token is the program to execute.
4121
4122        @rtype:  list( str )
4123        @return: List of argument strings.
4124        """
4125        if not lpCmdLine:
4126            return []
4127        return win32.CommandLineToArgv(lpCmdLine)
4128
4129    def start_process(self, lpCmdLine, **kwargs):
4130        """
4131        Starts a new process for instrumenting (or debugging).
4132
4133        @type  lpCmdLine: str
4134        @param lpCmdLine: Command line to execute. Can't be an empty string.
4135
4136        @type    bConsole: bool
4137        @keyword bConsole: True to inherit the console of the debugger.
4138            Defaults to C{False}.
4139
4140        @type    bDebug: bool
4141        @keyword bDebug: C{True} to attach to the new process.
4142            To debug a process it's best to use the L{Debug} class instead.
4143            Defaults to C{False}.
4144
4145        @type    bFollow: bool
4146        @keyword bFollow: C{True} to automatically attach to the child
4147            processes of the newly created process. Ignored unless C{bDebug} is
4148            C{True}. Defaults to C{False}.
4149
4150        @type    bInheritHandles: bool
4151        @keyword bInheritHandles: C{True} if the new process should inherit
4152            it's parent process' handles. Defaults to C{False}.
4153
4154        @type    bSuspended: bool
4155        @keyword bSuspended: C{True} to suspend the main thread before any code
4156            is executed in the debugee. Defaults to C{False}.
4157
4158        @type    dwParentProcessId: int or None
4159        @keyword dwParentProcessId: C{None} if the debugger process should be
4160            the parent process (default), or a process ID to forcefully set as
4161            the debugee's parent (only available for Windows Vista and above).
4162
4163        @type    iTrustLevel: int
4164        @keyword iTrustLevel: Trust level.
4165            Must be one of the following values:
4166             - 0: B{No trust}. May not access certain resources, such as
4167                  cryptographic keys and credentials. Only available since
4168                  Windows XP and 2003, desktop editions.
4169             - 1: B{Normal trust}. Run with the same privileges as a normal
4170                  user, that is, one that doesn't have the I{Administrator} or
4171                  I{Power User} user rights. Only available since Windows XP
4172                  and 2003, desktop editions.
4173             - 2: B{Full trust}. Run with the exact same privileges as the
4174                  current user. This is the default value.
4175
4176        @type    bAllowElevation: bool
4177        @keyword bAllowElevation: C{True} to allow the child process to keep
4178            UAC elevation, if the debugger itself is running elevated. C{False}
4179            to ensure the child process doesn't run with elevation. Defaults to
4180            C{True}.
4181
4182            This flag is only meaningful on Windows Vista and above, and if the
4183            debugger itself is running with elevation. It can be used to make
4184            sure the child processes don't run elevated as well.
4185
4186            This flag DOES NOT force an elevation prompt when the debugger is
4187            not running with elevation.
4188
4189            Note that running the debugger with elevation (or the Python
4190            interpreter at all for that matter) is not normally required.
4191            You should only need to if the target program requires elevation
4192            to work properly (for example if you try to debug an installer).
4193
4194        @rtype:  L{Process}
4195        @return: Process object.
4196        """
4197
4198        # Get the flags.
4199        bConsole            = kwargs.pop('bConsole', False)
4200        bDebug              = kwargs.pop('bDebug', False)
4201        bFollow             = kwargs.pop('bFollow', False)
4202        bSuspended          = kwargs.pop('bSuspended', False)
4203        bInheritHandles     = kwargs.pop('bInheritHandles', False)
4204        dwParentProcessId   = kwargs.pop('dwParentProcessId', None)
4205        iTrustLevel         = kwargs.pop('iTrustLevel', 2)
4206        bAllowElevation     = kwargs.pop('bAllowElevation', True)
4207        if kwargs:
4208            raise TypeError("Unknown keyword arguments: %s" % compat.keys(kwargs))
4209        if not lpCmdLine:
4210            raise ValueError("Missing command line to execute!")
4211
4212        # Sanitize the trust level flag.
4213        if iTrustLevel is None:
4214            iTrustLevel = 2
4215
4216        # The UAC elevation flag is only meaningful if we're running elevated.
4217        try:
4218            bAllowElevation = bAllowElevation or not self.is_admin()
4219        except AttributeError:
4220            bAllowElevation = True
4221            warnings.warn(
4222                "UAC elevation is only available in Windows Vista and above",
4223                RuntimeWarning)
4224
4225        # Calculate the process creation flags.
4226        dwCreationFlags  = 0
4227        dwCreationFlags |= win32.CREATE_DEFAULT_ERROR_MODE
4228        dwCreationFlags |= win32.CREATE_BREAKAWAY_FROM_JOB
4229        ##dwCreationFlags |= win32.CREATE_UNICODE_ENVIRONMENT
4230        if not bConsole:
4231            dwCreationFlags |= win32.DETACHED_PROCESS
4232            #dwCreationFlags |= win32.CREATE_NO_WINDOW   # weird stuff happens
4233        if bSuspended:
4234            dwCreationFlags |= win32.CREATE_SUSPENDED
4235        if bDebug:
4236            dwCreationFlags |= win32.DEBUG_PROCESS
4237            if not bFollow:
4238                dwCreationFlags |= win32.DEBUG_ONLY_THIS_PROCESS
4239
4240        # Change the parent process if requested.
4241        # May fail on old versions of Windows.
4242        lpStartupInfo = None
4243        if dwParentProcessId is not None:
4244            myPID = win32.GetCurrentProcessId()
4245            if dwParentProcessId != myPID:
4246                if self.has_process(dwParentProcessId):
4247                    ParentProcess = self.get_process(dwParentProcessId)
4248                else:
4249                    ParentProcess = Process(dwParentProcessId)
4250                ParentProcessHandle = ParentProcess.get_handle(
4251                                        win32.PROCESS_CREATE_PROCESS)
4252                AttributeListData = (
4253                    (
4254                        win32.PROC_THREAD_ATTRIBUTE_PARENT_PROCESS,
4255                        ParentProcessHandle._as_parameter_
4256                    ),
4257                )
4258                AttributeList = win32.ProcThreadAttributeList(AttributeListData)
4259                StartupInfoEx           = win32.STARTUPINFOEX()
4260                StartupInfo             = StartupInfoEx.StartupInfo
4261                StartupInfo.cb          = win32.sizeof(win32.STARTUPINFOEX)
4262                StartupInfo.lpReserved  = 0
4263                StartupInfo.lpDesktop   = 0
4264                StartupInfo.lpTitle     = 0
4265                StartupInfo.dwFlags     = 0
4266                StartupInfo.cbReserved2 = 0
4267                StartupInfo.lpReserved2 = 0
4268                StartupInfoEx.lpAttributeList = AttributeList.value
4269                lpStartupInfo = StartupInfoEx
4270                dwCreationFlags |= win32.EXTENDED_STARTUPINFO_PRESENT
4271
4272        pi = None
4273        try:
4274
4275            # Create the process the easy way.
4276            if iTrustLevel >= 2 and bAllowElevation:
4277                pi = win32.CreateProcess(None, lpCmdLine,
4278                                            bInheritHandles = bInheritHandles,
4279                                            dwCreationFlags = dwCreationFlags,
4280                                            lpStartupInfo   = lpStartupInfo)
4281
4282            # Create the process the hard way...
4283            else:
4284
4285                # If we allow elevation, use the current process token.
4286                # If not, get the token from the current shell process.
4287                hToken = None
4288                try:
4289                    if not bAllowElevation:
4290                        if bFollow:
4291                            msg = (
4292                                "Child processes can't be autofollowed"
4293                                " when dropping UAC elevation.")
4294                            raise NotImplementedError(msg)
4295                        if bConsole:
4296                            msg = (
4297                                "Child processes can't inherit the debugger's"
4298                                " console when dropping UAC elevation.")
4299                            raise NotImplementedError(msg)
4300                        if bInheritHandles:
4301                            msg = (
4302                                "Child processes can't inherit the debugger's"
4303                                " handles when dropping UAC elevation.")
4304                            raise NotImplementedError(msg)
4305                        try:
4306                            hWnd = self.get_shell_window()
4307                        except WindowsError:
4308                            hWnd = self.get_desktop_window()
4309                        shell = hWnd.get_process()
4310                        try:
4311                            hShell = shell.get_handle(
4312                                            win32.PROCESS_QUERY_INFORMATION)
4313                            with win32.OpenProcessToken(hShell) as hShellToken:
4314                                hToken = win32.DuplicateTokenEx(hShellToken)
4315                        finally:
4316                            shell.close_handle()
4317
4318                    # Lower trust level if requested.
4319                    if iTrustLevel < 2:
4320                        if iTrustLevel > 0:
4321                            dwLevelId = win32.SAFER_LEVELID_NORMALUSER
4322                        else:
4323                            dwLevelId = win32.SAFER_LEVELID_UNTRUSTED
4324                        with win32.SaferCreateLevel(dwLevelId = dwLevelId) as hSafer:
4325                            hSaferToken = win32.SaferComputeTokenFromLevel(
4326                                                            hSafer, hToken)[0]
4327                            try:
4328                                if hToken is not None:
4329                                    hToken.close()
4330                            except:
4331                                hSaferToken.close()
4332                                raise
4333                            hToken = hSaferToken
4334
4335                    # If we have a computed token, call CreateProcessAsUser().
4336                    if bAllowElevation:
4337                        pi = win32.CreateProcessAsUser(
4338                                    hToken          = hToken,
4339                                    lpCommandLine   = lpCmdLine,
4340                                    bInheritHandles = bInheritHandles,
4341                                    dwCreationFlags = dwCreationFlags,
4342                                    lpStartupInfo   = lpStartupInfo)
4343
4344                    # If we have a primary token call CreateProcessWithToken().
4345                    # The problem is, there are many flags CreateProcess() and
4346                    # CreateProcessAsUser() accept but CreateProcessWithToken()
4347                    # and CreateProcessWithLogonW() don't, so we need to work
4348                    # around them.
4349                    else:
4350
4351                        # Remove the debug flags.
4352                        dwCreationFlags &= ~win32.DEBUG_PROCESS
4353                        dwCreationFlags &= ~win32.DEBUG_ONLY_THIS_PROCESS
4354
4355                        # Remove the console flags.
4356                        dwCreationFlags &= ~win32.DETACHED_PROCESS
4357
4358                        # The process will be created suspended.
4359                        dwCreationFlags |= win32.CREATE_SUSPENDED
4360
4361                        # Create the process using the new primary token.
4362                        pi = win32.CreateProcessWithToken(
4363                                    hToken          = hToken,
4364                                    dwLogonFlags    = win32.LOGON_WITH_PROFILE,
4365                                    lpCommandLine   = lpCmdLine,
4366                                    dwCreationFlags = dwCreationFlags,
4367                                    lpStartupInfo   = lpStartupInfo)
4368
4369                        # Attach as a debugger, if requested.
4370                        if bDebug:
4371                            win32.DebugActiveProcess(pi.dwProcessId)
4372
4373                        # Resume execution, if requested.
4374                        if not bSuspended:
4375                            win32.ResumeThread(pi.hThread)
4376
4377                # Close the token when we're done with it.
4378                finally:
4379                    if hToken is not None:
4380                        hToken.close()
4381
4382            # Wrap the new process and thread in Process and Thread objects,
4383            # and add them to the corresponding snapshots.
4384            aProcess = Process(pi.dwProcessId, pi.hProcess)
4385            aThread  = Thread (pi.dwThreadId,  pi.hThread)
4386            aProcess._add_thread(aThread)
4387            self._add_process(aProcess)
4388
4389        # Clean up on error.
4390        except:
4391            if pi is not None:
4392                try:
4393                    win32.TerminateProcess(pi.hProcess)
4394                except WindowsError:
4395                    pass
4396                pi.hThread.close()
4397                pi.hProcess.close()
4398            raise
4399
4400        # Return the new Process object.
4401        return aProcess
4402
4403    def get_explorer_pid(self):
4404        """
4405        Tries to find the process ID for "explorer.exe".
4406
4407        @rtype:  int or None
4408        @return: Returns the process ID, or C{None} on error.
4409        """
4410        try:
4411            exp = win32.SHGetFolderPath(win32.CSIDL_WINDOWS)
4412        except Exception:
4413            exp = None
4414        if not exp:
4415            exp = os.getenv('SystemRoot')
4416        if exp:
4417            exp = os.path.join(exp, 'explorer.exe')
4418            exp_list = self.find_processes_by_filename(exp)
4419            if exp_list:
4420                return exp_list[0][0].get_pid()
4421        return None
4422
4423#------------------------------------------------------------------------------
4424
4425    # XXX this methods musn't end up calling __initialize_snapshot by accident!
4426
4427    def scan(self):
4428        """
4429        Populates the snapshot with running processes and threads,
4430        and loaded modules.
4431
4432        Tipically this is the first method called after instantiating a
4433        L{System} object, as it makes a best effort approach to gathering
4434        information on running processes.
4435
4436        @rtype: bool
4437        @return: C{True} if the snapshot is complete, C{False} if the debugger
4438            doesn't have permission to scan some processes. In either case, the
4439            snapshot is complete for all processes the debugger has access to.
4440        """
4441        has_threads = True
4442        try:
4443            try:
4444
4445                # Try using the Toolhelp API
4446                # to scan for processes and threads.
4447                self.scan_processes_and_threads()
4448
4449            except Exception:
4450
4451                # On error, try using the PSAPI to scan for process IDs only.
4452                self.scan_processes_fast()
4453
4454                # Now try using the Toolhelp again to get the threads.
4455                for aProcess in self.__processDict.values():
4456                    if aProcess._get_thread_ids():
4457                        try:
4458                            aProcess.scan_threads()
4459                        except WindowsError:
4460                            has_threads = False
4461
4462        finally:
4463
4464            # Try using the Remote Desktop API to scan for processes only.
4465            # This will update the filenames when it's not possible
4466            # to obtain them from the Toolhelp API.
4467            self.scan_processes()
4468
4469        # When finished scanning for processes, try modules too.
4470        has_modules = self.scan_modules()
4471
4472        # Try updating the process filenames when possible.
4473        has_full_names = self.scan_process_filenames()
4474
4475        # Return the completion status.
4476        return has_threads and has_modules and has_full_names
4477
4478    def scan_processes_and_threads(self):
4479        """
4480        Populates the snapshot with running processes and threads.
4481
4482        Tipically you don't need to call this method directly, if unsure use
4483        L{scan} instead.
4484
4485        @note: This method uses the Toolhelp API.
4486
4487        @see: L{scan_modules}
4488
4489        @raise WindowsError: An error occured while updating the snapshot.
4490            The snapshot was not modified.
4491        """
4492
4493        # The main module filename may be spoofed by malware,
4494        # since this information resides in usermode space.
4495        # See: http://www.ragestorm.net/blogs/?p=163
4496
4497        our_pid    = win32.GetCurrentProcessId()
4498        dead_pids  = set( compat.iterkeys(self.__processDict) )
4499        found_tids = set()
4500
4501        # Ignore our own process if it's in the snapshot for some reason
4502        if our_pid in dead_pids:
4503            dead_pids.remove(our_pid)
4504
4505        # Take a snapshot of all processes and threads
4506        dwFlags   = win32.TH32CS_SNAPPROCESS | win32.TH32CS_SNAPTHREAD
4507        with win32.CreateToolhelp32Snapshot(dwFlags) as hSnapshot:
4508
4509            # Add all the processes (excluding our own)
4510            pe = win32.Process32First(hSnapshot)
4511            while pe is not None:
4512                dwProcessId = pe.th32ProcessID
4513                if dwProcessId != our_pid:
4514                    if dwProcessId in dead_pids:
4515                        dead_pids.remove(dwProcessId)
4516                    if dwProcessId not in self.__processDict:
4517                        aProcess = Process(dwProcessId, fileName=pe.szExeFile)
4518                        self._add_process(aProcess)
4519                    elif pe.szExeFile:
4520                        aProcess = self.get_process(dwProcessId)
4521                        if not aProcess.fileName:
4522                            aProcess.fileName = pe.szExeFile
4523                pe = win32.Process32Next(hSnapshot)
4524
4525            # Add all the threads
4526            te = win32.Thread32First(hSnapshot)
4527            while te is not None:
4528                dwProcessId = te.th32OwnerProcessID
4529                if dwProcessId != our_pid:
4530                    if dwProcessId in dead_pids:
4531                        dead_pids.remove(dwProcessId)
4532                    if dwProcessId in self.__processDict:
4533                        aProcess = self.get_process(dwProcessId)
4534                    else:
4535                        aProcess = Process(dwProcessId)
4536                        self._add_process(aProcess)
4537                    dwThreadId = te.th32ThreadID
4538                    found_tids.add(dwThreadId)
4539                    if not aProcess._has_thread_id(dwThreadId):
4540                        aThread = Thread(dwThreadId, process = aProcess)
4541                        aProcess._add_thread(aThread)
4542                te = win32.Thread32Next(hSnapshot)
4543
4544        # Remove dead processes
4545        for pid in dead_pids:
4546            self._del_process(pid)
4547
4548        # Remove dead threads
4549        for aProcess in compat.itervalues(self.__processDict):
4550            dead_tids = set( aProcess._get_thread_ids() )
4551            dead_tids.difference_update(found_tids)
4552            for tid in dead_tids:
4553                aProcess._del_thread(tid)
4554
4555    def scan_modules(self):
4556        """
4557        Populates the snapshot with loaded modules.
4558
4559        Tipically you don't need to call this method directly, if unsure use
4560        L{scan} instead.
4561
4562        @note: This method uses the Toolhelp API.
4563
4564        @see: L{scan_processes_and_threads}
4565
4566        @rtype: bool
4567        @return: C{True} if the snapshot is complete, C{False} if the debugger
4568            doesn't have permission to scan some processes. In either case, the
4569            snapshot is complete for all processes the debugger has access to.
4570        """
4571        complete = True
4572        for aProcess in compat.itervalues(self.__processDict):
4573            try:
4574                aProcess.scan_modules()
4575            except WindowsError:
4576                complete = False
4577        return complete
4578
4579    def scan_processes(self):
4580        """
4581        Populates the snapshot with running processes.
4582
4583        Tipically you don't need to call this method directly, if unsure use
4584        L{scan} instead.
4585
4586        @note: This method uses the Remote Desktop API instead of the Toolhelp
4587            API. It might give slightly different results, especially if the
4588            current process does not have full privileges.
4589
4590        @note: This method will only retrieve process filenames. To get the
4591            process pathnames instead, B{after} this method call
4592            L{scan_process_filenames}.
4593
4594        @raise WindowsError: An error occured while updating the snapshot.
4595            The snapshot was not modified.
4596        """
4597
4598        # Get the previous list of PIDs.
4599        # We'll be removing live PIDs from it as we find them.
4600        our_pid   = win32.GetCurrentProcessId()
4601        dead_pids  = set( compat.iterkeys(self.__processDict) )
4602
4603        # Ignore our own PID.
4604        if our_pid in dead_pids:
4605            dead_pids.remove(our_pid)
4606
4607        # Get the list of processes from the Remote Desktop API.
4608        pProcessInfo = None
4609        try:
4610            pProcessInfo, dwCount = win32.WTSEnumerateProcesses(
4611                                            win32.WTS_CURRENT_SERVER_HANDLE)
4612
4613            # For each process found...
4614            for index in compat.xrange(dwCount):
4615                sProcessInfo = pProcessInfo[index]
4616
4617##                # Ignore processes belonging to other sessions.
4618##                if sProcessInfo.SessionId != win32.WTS_CURRENT_SESSION:
4619##                    continue
4620
4621                # Ignore our own PID.
4622                pid = sProcessInfo.ProcessId
4623                if pid == our_pid:
4624                    continue
4625
4626                # Remove the PID from the dead PIDs list.
4627                if pid in dead_pids:
4628                    dead_pids.remove(pid)
4629
4630                # Get the "process name".
4631                # Empirically, this seems to be the filename without the path.
4632                # (The MSDN docs aren't very clear about this API call).
4633                fileName = sProcessInfo.pProcessName
4634
4635                # If the process is new, add a new Process object.
4636                if pid not in self.__processDict:
4637                    aProcess = Process(pid, fileName = fileName)
4638                    self._add_process(aProcess)
4639
4640                # If the process was already in the snapshot, and the
4641                # filename is missing, update the Process object.
4642                elif fileName:
4643                    aProcess = self.__processDict.get(pid)
4644                    if not aProcess.fileName:
4645                        aProcess.fileName = fileName
4646
4647        # Free the memory allocated by the Remote Desktop API.
4648        finally:
4649            if pProcessInfo is not None:
4650                try:
4651                    win32.WTSFreeMemory(pProcessInfo)
4652                except WindowsError:
4653                    pass
4654
4655        # At this point the only remaining PIDs from the old list are dead.
4656        # Remove them from the snapshot.
4657        for pid in dead_pids:
4658            self._del_process(pid)
4659
4660    def scan_processes_fast(self):
4661        """
4662        Populates the snapshot with running processes.
4663        Only the PID is retrieved for each process.
4664
4665        Dead processes are removed.
4666        Threads and modules of living processes are ignored.
4667
4668        Tipically you don't need to call this method directly, if unsure use
4669        L{scan} instead.
4670
4671        @note: This method uses the PSAPI. It may be faster for scanning,
4672            but some information may be missing, outdated or slower to obtain.
4673            This could be a good tradeoff under some circumstances.
4674        """
4675
4676        # Get the new and old list of pids
4677        new_pids = set( win32.EnumProcesses() )
4678        old_pids = set( compat.iterkeys(self.__processDict) )
4679
4680        # Ignore our own pid
4681        our_pid  = win32.GetCurrentProcessId()
4682        if our_pid in new_pids:
4683            new_pids.remove(our_pid)
4684        if our_pid in old_pids:
4685            old_pids.remove(our_pid)
4686
4687        # Add newly found pids
4688        for pid in new_pids.difference(old_pids):
4689            self._add_process( Process(pid) )
4690
4691        # Remove missing pids
4692        for pid in old_pids.difference(new_pids):
4693            self._del_process(pid)
4694
4695    def scan_process_filenames(self):
4696        """
4697        Update the filename for each process in the snapshot when possible.
4698
4699        @note: Tipically you don't need to call this method. It's called
4700            automatically by L{scan} to get the full pathname for each process
4701            when possible, since some scan methods only get filenames without
4702            the path component.
4703
4704            If unsure, use L{scan} instead.
4705
4706        @see: L{scan}, L{Process.get_filename}
4707
4708        @rtype: bool
4709        @return: C{True} if all the pathnames were retrieved, C{False} if the
4710            debugger doesn't have permission to scan some processes. In either
4711            case, all processes the debugger has access to have a full pathname
4712            instead of just a filename.
4713        """
4714        complete = True
4715        for aProcess in self.__processDict.values():
4716            try:
4717                new_name = None
4718                old_name = aProcess.fileName
4719                try:
4720                    aProcess.fileName = None
4721                    new_name = aProcess.get_filename()
4722                finally:
4723                    if not new_name:
4724                        aProcess.fileName = old_name
4725                        complete = False
4726            except Exception:
4727                complete = False
4728        return complete
4729
4730#------------------------------------------------------------------------------
4731
4732    def clear_dead_processes(self):
4733        """
4734        Removes Process objects from the snapshot
4735        referring to processes no longer running.
4736        """
4737        for pid in self.get_process_ids():
4738            aProcess = self.get_process(pid)
4739            if not aProcess.is_alive():
4740                self._del_process(aProcess)
4741
4742    def clear_unattached_processes(self):
4743        """
4744        Removes Process objects from the snapshot
4745        referring to processes not being debugged.
4746        """
4747        for pid in self.get_process_ids():
4748            aProcess = self.get_process(pid)
4749            if not aProcess.is_being_debugged():
4750                self._del_process(aProcess)
4751
4752    def close_process_handles(self):
4753        """
4754        Closes all open handles to processes in this snapshot.
4755        """
4756        for pid in self.get_process_ids():
4757            aProcess = self.get_process(pid)
4758            try:
4759                aProcess.close_handle()
4760            except Exception:
4761                e = sys.exc_info()[1]
4762                try:
4763                    msg = "Cannot close process handle %s, reason: %s"
4764                    msg %= (aProcess.hProcess.value, str(e))
4765                    warnings.warn(msg)
4766                except Exception:
4767                    pass
4768
4769    def close_process_and_thread_handles(self):
4770        """
4771        Closes all open handles to processes and threads in this snapshot.
4772        """
4773        for aProcess in self.iter_processes():
4774            aProcess.close_thread_handles()
4775            try:
4776                aProcess.close_handle()
4777            except Exception:
4778                e = sys.exc_info()[1]
4779                try:
4780                    msg = "Cannot close process handle %s, reason: %s"
4781                    msg %= (aProcess.hProcess.value, str(e))
4782                    warnings.warn(msg)
4783                except Exception:
4784                    pass
4785
4786    def clear_processes(self):
4787        """
4788        Removes all L{Process}, L{Thread} and L{Module} objects in this snapshot.
4789        """
4790        #self.close_process_and_thread_handles()
4791        for aProcess in self.iter_processes():
4792            aProcess.clear()
4793        self.__processDict = dict()
4794
4795    def clear(self):
4796        """
4797        Clears this snapshot.
4798
4799        @see: L{clear_processes}
4800        """
4801        self.clear_processes()
4802
4803#------------------------------------------------------------------------------
4804
4805    # Docs for these methods are taken from the _ThreadContainer class.
4806
4807    def has_thread(self, dwThreadId):
4808        dwProcessId = self.get_pid_from_tid(dwThreadId)
4809        if dwProcessId is None:
4810            return False
4811        return self.has_process(dwProcessId)
4812
4813    def get_thread(self, dwThreadId):
4814        dwProcessId = self.get_pid_from_tid(dwThreadId)
4815        if dwProcessId is None:
4816            msg = "Unknown thread ID %d" % dwThreadId
4817            raise KeyError(msg)
4818        return self.get_process(dwProcessId).get_thread(dwThreadId)
4819
4820    def get_thread_ids(self):
4821        ids = list()
4822        for aProcess in self.iter_processes():
4823            ids += aProcess.get_thread_ids()
4824        return ids
4825
4826    def get_thread_count(self):
4827        count = 0
4828        for aProcess in self.iter_processes():
4829            count += aProcess.get_thread_count()
4830        return count
4831
4832    has_thread.__doc__       = _ThreadContainer.has_thread.__doc__
4833    get_thread.__doc__       = _ThreadContainer.get_thread.__doc__
4834    get_thread_ids.__doc__   = _ThreadContainer.get_thread_ids.__doc__
4835    get_thread_count.__doc__ = _ThreadContainer.get_thread_count.__doc__
4836
4837#------------------------------------------------------------------------------
4838
4839    # Docs for these methods are taken from the _ModuleContainer class.
4840
4841    def get_module_count(self):
4842        count = 0
4843        for aProcess in self.iter_processes():
4844            count += aProcess.get_module_count()
4845        return count
4846
4847    get_module_count.__doc__ = _ModuleContainer.get_module_count.__doc__
4848
4849#------------------------------------------------------------------------------
4850
4851    def find_modules_by_base(self, lpBaseOfDll):
4852        """
4853        @rtype:  list( L{Module}... )
4854        @return: List of Module objects with the given base address.
4855        """
4856        found = list()
4857        for aProcess in self.iter_processes():
4858            if aProcess.has_module(lpBaseOfDll):
4859                aModule = aProcess.get_module(lpBaseOfDll)
4860                found.append( (aProcess, aModule) )
4861        return found
4862
4863    def find_modules_by_name(self, fileName):
4864        """
4865        @rtype:  list( L{Module}... )
4866        @return: List of Module objects found.
4867        """
4868        found = list()
4869        for aProcess in self.iter_processes():
4870            aModule = aProcess.get_module_by_name(fileName)
4871            if aModule is not None:
4872                found.append( (aProcess, aModule) )
4873        return found
4874
4875    def find_modules_by_address(self, address):
4876        """
4877        @rtype:  list( L{Module}... )
4878        @return: List of Module objects that best match the given address.
4879        """
4880        found = list()
4881        for aProcess in self.iter_processes():
4882            aModule = aProcess.get_module_at_address(address)
4883            if aModule is not None:
4884                found.append( (aProcess, aModule) )
4885        return found
4886
4887    def __find_processes_by_filename(self, filename):
4888        """
4889        Internally used by L{find_processes_by_filename}.
4890        """
4891        found    = list()
4892        filename = filename.lower()
4893        if PathOperations.path_is_absolute(filename):
4894            for aProcess in self.iter_processes():
4895                imagename = aProcess.get_filename()
4896                if imagename and imagename.lower() == filename:
4897                    found.append( (aProcess, imagename) )
4898        else:
4899            for aProcess in self.iter_processes():
4900                imagename = aProcess.get_filename()
4901                if imagename:
4902                    imagename = PathOperations.pathname_to_filename(imagename)
4903                    if imagename.lower() == filename:
4904                        found.append( (aProcess, imagename) )
4905        return found
4906
4907    def find_processes_by_filename(self, fileName):
4908        """
4909        @type  fileName: str
4910        @param fileName: Filename to search for.
4911            If it's a full pathname, the match must be exact.
4912            If it's a base filename only, the file part is matched,
4913            regardless of the directory where it's located.
4914
4915        @note: If the process is not found and the file extension is not
4916            given, this method will search again assuming a default
4917            extension (.exe).
4918
4919        @rtype:  list of tuple( L{Process}, str )
4920        @return: List of processes matching the given main module filename.
4921            Each tuple contains a Process object and it's filename.
4922        """
4923        found = self.__find_processes_by_filename(fileName)
4924        if not found:
4925            fn, ext = PathOperations.split_extension(fileName)
4926            if not ext:
4927                fileName = '%s.exe' % fn
4928                found    = self.__find_processes_by_filename(fileName)
4929        return found
4930
4931#------------------------------------------------------------------------------
4932
4933    # XXX _notify_* methods should not trigger a scan
4934
4935    def _add_process(self, aProcess):
4936        """
4937        Private method to add a process object to the snapshot.
4938
4939        @type  aProcess: L{Process}
4940        @param aProcess: Process object.
4941        """
4942##        if not isinstance(aProcess, Process):
4943##            if hasattr(aProcess, '__class__'):
4944##                typename = aProcess.__class__.__name__
4945##            else:
4946##                typename = str(type(aProcess))
4947##            msg = "Expected Process, got %s instead" % typename
4948##            raise TypeError(msg)
4949        dwProcessId = aProcess.dwProcessId
4950##        if dwProcessId in self.__processDict:
4951##            msg = "Process already exists: %d" % dwProcessId
4952##            raise KeyError(msg)
4953        self.__processDict[dwProcessId] = aProcess
4954
4955    def _del_process(self, dwProcessId):
4956        """
4957        Private method to remove a process object from the snapshot.
4958
4959        @type  dwProcessId: int
4960        @param dwProcessId: Global process ID.
4961        """
4962        try:
4963            aProcess = self.__processDict[dwProcessId]
4964            del self.__processDict[dwProcessId]
4965        except KeyError:
4966            aProcess = None
4967            msg = "Unknown process ID %d" % dwProcessId
4968            warnings.warn(msg, RuntimeWarning)
4969        if aProcess:
4970            aProcess.clear()    # remove circular references
4971
4972    # Notify the creation of a new process.
4973    def _notify_create_process(self, event):
4974        """
4975        Notify the creation of a new process.
4976
4977        This is done automatically by the L{Debug} class, you shouldn't need
4978        to call it yourself.
4979
4980        @type  event: L{CreateProcessEvent}
4981        @param event: Create process event.
4982
4983        @rtype:  bool
4984        @return: C{True} to call the user-defined handle, C{False} otherwise.
4985        """
4986        dwProcessId = event.get_pid()
4987        dwThreadId  = event.get_tid()
4988        hProcess    = event.get_process_handle()
4989##        if not self.has_process(dwProcessId): # XXX this would trigger a scan
4990        if dwProcessId not in self.__processDict:
4991            aProcess = Process(dwProcessId, hProcess)
4992            self._add_process(aProcess)
4993            aProcess.fileName = event.get_filename()
4994        else:
4995            aProcess = self.get_process(dwProcessId)
4996            #if hProcess != win32.INVALID_HANDLE_VALUE:
4997            #    aProcess.hProcess = hProcess    # may have more privileges
4998            if not aProcess.fileName:
4999                fileName = event.get_filename()
5000                if fileName:
5001                    aProcess.fileName = fileName
5002        return aProcess._notify_create_process(event)  # pass it to the process
5003
5004    def _notify_exit_process(self, event):
5005        """
5006        Notify the termination of a process.
5007
5008        This is done automatically by the L{Debug} class, you shouldn't need
5009        to call it yourself.
5010
5011        @type  event: L{ExitProcessEvent}
5012        @param event: Exit process event.
5013
5014        @rtype:  bool
5015        @return: C{True} to call the user-defined handle, C{False} otherwise.
5016        """
5017        dwProcessId = event.get_pid()
5018##        if self.has_process(dwProcessId): # XXX this would trigger a scan
5019        if dwProcessId in self.__processDict:
5020            self._del_process(dwProcessId)
5021        return True
5022