Package winappdbg :: Module thread
[hide private]
[frames] | no frames]

Source Code for Module winappdbg.thread

   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  """ 
  32  Thread instrumentation. 
  33   
  34  @group Instrumentation: 
  35      Thread 
  36  """ 
  37   
  38  from __future__ import with_statement 
  39   
  40  __revision__ = "$Id: thread.py 1299 2013-12-20 09:30:55Z qvasimodo $" 
  41   
  42  __all__ = ['Thread'] 
  43   
  44  import win32 
  45  from textio import HexDump 
  46  from util import DebugRegister 
  47  from window import Window 
  48   
  49  import struct 
  50  import warnings 
  51   
  52  # delayed imports 
  53  Process = None 
  54   
  55  #============================================================================== 
  56   
  57  # TODO 
  58  # + fetch special registers (MMX, XMM, 3DNow!, etc) 
  59   
60 -class Thread (object):
61 """ 62 Interface to a thread in another process. 63 64 @group Properties: 65 get_tid, get_pid, get_process, set_process, get_exit_code, is_alive, 66 get_name, set_name, get_windows, get_teb, get_teb_address, is_wow64, 67 get_arch, get_bits, get_handle, open_handle, close_handle 68 69 @group Instrumentation: 70 suspend, resume, kill, wait 71 72 @group Debugging: 73 get_seh_chain_pointer, set_seh_chain_pointer, 74 get_seh_chain, get_wait_chain, is_hidden 75 76 @group Disassembly: 77 disassemble, disassemble_around, disassemble_around_pc, 78 disassemble_string, disassemble_instruction, disassemble_current 79 80 @group Stack: 81 get_stack_frame, get_stack_frame_range, get_stack_range, 82 get_stack_trace, get_stack_trace_with_labels, 83 read_stack_data, read_stack_dwords, read_stack_qwords, 84 peek_stack_data, peek_stack_dwords, peek_stack_qwords, 85 read_stack_structure, read_stack_frame 86 87 @group Registers: 88 get_context, 89 get_register, 90 get_flags, get_flag_value, 91 get_pc, get_sp, get_fp, 92 get_cf, get_df, get_sf, get_tf, get_zf, 93 set_context, 94 set_register, 95 set_flags, set_flag_value, 96 set_pc, set_sp, set_fp, 97 set_cf, set_df, set_sf, set_tf, set_zf, 98 clear_cf, clear_df, clear_sf, clear_tf, clear_zf, 99 Flags 100 101 @group Threads snapshot: 102 clear 103 104 @group Miscellaneous: 105 read_code_bytes, peek_code_bytes, 106 peek_pointers_in_data, peek_pointers_in_registers, 107 get_linear_address, get_label_at_pc 108 109 @type dwThreadId: int 110 @ivar dwThreadId: Global thread ID. Use L{get_tid} instead. 111 112 @type hThread: L{ThreadHandle} 113 @ivar hThread: Handle to the thread. Use L{get_handle} instead. 114 115 @type process: L{Process} 116 @ivar process: Parent process object. Use L{get_process} instead. 117 118 @type pInjectedMemory: int 119 @ivar pInjectedMemory: If the thread was created by L{Process.inject_code}, 120 this member contains a pointer to the memory buffer for the injected 121 code. Otherwise it's C{None}. 122 123 The L{kill} method uses this member to free the buffer 124 when the injected thread is killed. 125 """ 126
127 - def __init__(self, dwThreadId, hThread = None, process = None):
128 """ 129 @type dwThreadId: int 130 @param dwThreadId: Global thread ID. 131 132 @type hThread: L{ThreadHandle} 133 @param hThread: (Optional) Handle to the thread. 134 135 @type process: L{Process} 136 @param process: (Optional) Parent Process object. 137 """ 138 self.dwProcessId = None 139 self.dwThreadId = dwThreadId 140 self.hThread = hThread 141 self.pInjectedMemory = None 142 self.set_name(None) 143 self.set_process(process)
144 145 # Not really sure if it's a good idea... 146 ## def __eq__(self, aThread): 147 ## """ 148 ## Compare two Thread objects. The comparison is made using the IDs. 149 ## 150 ## @warning: 151 ## If you have two Thread instances with different handles the 152 ## equality operator still returns C{True}, so be careful! 153 ## 154 ## @type aThread: L{Thread} 155 ## @param aThread: Another Thread object. 156 ## 157 ## @rtype: bool 158 ## @return: C{True} if the two thread IDs are equal, 159 ## C{False} otherwise. 160 ## """ 161 ## return isinstance(aThread, Thread) and \ 162 ## self.get_tid() == aThread.get_tid() 163
164 - def __load_Process_class(self):
165 global Process # delayed import 166 if Process is None: 167 from process import Process
168
169 - def get_process(self):
170 """ 171 @rtype: L{Process} 172 @return: Parent Process object. 173 Returns C{None} if unknown. 174 """ 175 if self.__process is not None: 176 return self.__process 177 self.__load_Process_class() 178 self.__process = Process(self.get_pid()) 179 return self.__process
180
181 - def set_process(self, process = None):
182 """ 183 Manually set the parent Process object. Use with care! 184 185 @type process: L{Process} 186 @param process: (Optional) Process object. Use C{None} for no process. 187 """ 188 if process is None: 189 self.dwProcessId = None 190 self.__process = None 191 else: 192 self.__load_Process_class() 193 if not isinstance(process, Process): 194 msg = "Parent process must be a Process instance, " 195 msg += "got %s instead" % type(process) 196 raise TypeError(msg) 197 self.dwProcessId = process.get_pid() 198 self.__process = process
199 200 process = property(get_process, set_process, doc="") 201
202 - def get_pid(self):
203 """ 204 @rtype: int 205 @return: Parent process global ID. 206 207 @raise WindowsError: An error occured when calling a Win32 API function. 208 @raise RuntimeError: The parent process ID can't be found. 209 """ 210 if self.dwProcessId is None: 211 if self.__process is not None: 212 # Infinite loop if self.__process is None 213 self.dwProcessId = self.get_process().get_pid() 214 else: 215 try: 216 # I wish this had been implemented before Vista... 217 # XXX TODO find the real ntdll call under this api 218 hThread = self.get_handle( 219 win32.THREAD_QUERY_LIMITED_INFORMATION) 220 self.dwProcessId = win32.GetProcessIdOfThread(hThread) 221 except AttributeError: 222 # This method really sucks :P 223 self.dwProcessId = self.__get_pid_by_scanning() 224 return self.dwProcessId
225
226 - def __get_pid_by_scanning(self):
227 'Internally used by get_pid().' 228 dwProcessId = None 229 dwThreadId = self.get_tid() 230 with win32.CreateToolhelp32Snapshot(win32.TH32CS_SNAPTHREAD) as hSnapshot: 231 te = win32.Thread32First(hSnapshot) 232 while te is not None: 233 if te.th32ThreadID == dwThreadId: 234 dwProcessId = te.th32OwnerProcessID 235 break 236 te = win32.Thread32Next(hSnapshot) 237 if dwProcessId is None: 238 msg = "Cannot find thread ID %d in any process" % dwThreadId 239 raise RuntimeError(msg) 240 return dwProcessId
241
242 - def get_tid(self):
243 """ 244 @rtype: int 245 @return: Thread global ID. 246 """ 247 return self.dwThreadId
248
249 - def get_name(self):
250 """ 251 @rtype: str 252 @return: Thread name, or C{None} if the thread is nameless. 253 """ 254 return self.name
255
256 - def set_name(self, name = None):
257 """ 258 Sets the thread's name. 259 260 @type name: str 261 @param name: Thread name, or C{None} if the thread is nameless. 262 """ 263 self.name = name
264 265 #------------------------------------------------------------------------------ 266
267 - def open_handle(self, dwDesiredAccess = win32.THREAD_ALL_ACCESS):
268 """ 269 Opens a new handle to the thread, closing the previous one. 270 271 The new handle is stored in the L{hThread} property. 272 273 @warn: Normally you should call L{get_handle} instead, since it's much 274 "smarter" and tries to reuse handles and merge access rights. 275 276 @type dwDesiredAccess: int 277 @param dwDesiredAccess: Desired access rights. 278 Defaults to L{win32.THREAD_ALL_ACCESS}. 279 See: U{http://msdn.microsoft.com/en-us/library/windows/desktop/ms686769(v=vs.85).aspx} 280 281 @raise WindowsError: It's not possible to open a handle to the thread 282 with the requested access rights. This tipically happens because 283 the target thread belongs to system process and the debugger is not 284 runnning with administrative rights. 285 """ 286 hThread = win32.OpenThread(dwDesiredAccess, win32.FALSE, self.dwThreadId) 287 288 # In case hThread was set to an actual handle value instead of a Handle 289 # object. This shouldn't happen unless the user tinkered with it. 290 if not hasattr(self.hThread, '__del__'): 291 self.close_handle() 292 293 self.hThread = hThread
294
295 - def close_handle(self):
296 """ 297 Closes the handle to the thread. 298 299 @note: Normally you don't need to call this method. All handles 300 created by I{WinAppDbg} are automatically closed when the garbage 301 collector claims them. 302 """ 303 try: 304 if hasattr(self.hThread, 'close'): 305 self.hThread.close() 306 elif self.hThread not in (None, win32.INVALID_HANDLE_VALUE): 307 win32.CloseHandle(self.hThread) 308 finally: 309 self.hThread = None
310
311 - def get_handle(self, dwDesiredAccess = win32.THREAD_ALL_ACCESS):
312 """ 313 Returns a handle to the thread with I{at least} the access rights 314 requested. 315 316 @note: 317 If a handle was previously opened and has the required access 318 rights, it's reused. If not, a new handle is opened with the 319 combination of the old and new access rights. 320 321 @type dwDesiredAccess: int 322 @param dwDesiredAccess: Desired access rights. 323 See: U{http://msdn.microsoft.com/en-us/library/windows/desktop/ms686769(v=vs.85).aspx} 324 325 @rtype: ThreadHandle 326 @return: Handle to the thread. 327 328 @raise WindowsError: It's not possible to open a handle to the thread 329 with the requested access rights. This tipically happens because 330 the target thread belongs to system process and the debugger is not 331 runnning with administrative rights. 332 """ 333 if self.hThread in (None, win32.INVALID_HANDLE_VALUE): 334 self.open_handle(dwDesiredAccess) 335 else: 336 dwAccess = self.hThread.dwAccess 337 if (dwAccess | dwDesiredAccess) != dwAccess: 338 self.open_handle(dwAccess | dwDesiredAccess) 339 return self.hThread
340
341 - def clear(self):
342 """ 343 Clears the resources held by this object. 344 """ 345 try: 346 self.set_process(None) 347 finally: 348 self.close_handle()
349 350 #------------------------------------------------------------------------------ 351
352 - def wait(self, dwTimeout = None):
353 """ 354 Waits for the thread to finish executing. 355 356 @type dwTimeout: int 357 @param dwTimeout: (Optional) Timeout value in milliseconds. 358 Use C{INFINITE} or C{None} for no timeout. 359 """ 360 self.get_handle(win32.SYNCHRONIZE).wait(dwTimeout)
361
362 - def kill(self, dwExitCode = 0):
363 """ 364 Terminates the thread execution. 365 366 @note: If the C{lpInjectedMemory} member contains a valid pointer, 367 the memory is freed. 368 369 @type dwExitCode: int 370 @param dwExitCode: (Optional) Thread exit code. 371 """ 372 hThread = self.get_handle(win32.THREAD_TERMINATE) 373 win32.TerminateThread(hThread, dwExitCode) 374 375 # Ugliest hack ever, won't work if many pieces of code are injected. 376 # Seriously, what was I thinking? Lame! :( 377 if self.pInjectedMemory is not None: 378 try: 379 self.get_process().free(self.pInjectedMemory) 380 self.pInjectedMemory = None 381 except Exception: 382 ## raise # XXX DEBUG 383 pass
384 385 # XXX TODO 386 # suspend() and resume() should have a counter of how many times a thread 387 # was suspended, so on debugger exit they could (optionally!) be restored 388
389 - def suspend(self):
390 """ 391 Suspends the thread execution. 392 393 @rtype: int 394 @return: Suspend count. If zero, the thread is running. 395 """ 396 hThread = self.get_handle(win32.THREAD_SUSPEND_RESUME) 397 if self.is_wow64(): 398 # FIXME this will be horribly slow on XP 64 399 # since it'll try to resolve a missing API every time 400 try: 401 return win32.Wow64SuspendThread(hThread) 402 except AttributeError: 403 pass 404 return win32.SuspendThread(hThread)
405
406 - def resume(self):
407 """ 408 Resumes the thread execution. 409 410 @rtype: int 411 @return: Suspend count. If zero, the thread is running. 412 """ 413 hThread = self.get_handle(win32.THREAD_SUSPEND_RESUME) 414 return win32.ResumeThread(hThread)
415
416 - def is_alive(self):
417 """ 418 @rtype: bool 419 @return: C{True} if the thread if currently running. 420 @raise WindowsError: 421 The debugger doesn't have enough privileges to perform this action. 422 """ 423 try: 424 self.wait(0) 425 except WindowsError, e: 426 error = e.winerror 427 if error == win32.ERROR_ACCESS_DENIED: 428 raise 429 return error == win32.WAIT_TIMEOUT 430 return True
431
432 - def get_exit_code(self):
433 """ 434 @rtype: int 435 @return: Thread exit code, or C{STILL_ACTIVE} if it's still alive. 436 """ 437 if win32.THREAD_ALL_ACCESS == win32.THREAD_ALL_ACCESS_VISTA: 438 dwAccess = win32.THREAD_QUERY_LIMITED_INFORMATION 439 else: 440 dwAccess = win32.THREAD_QUERY_INFORMATION 441 return win32.GetExitCodeThread( self.get_handle(dwAccess) )
442 443 #------------------------------------------------------------------------------ 444 445 # XXX TODO 446 # Support for string searches on the window captions. 447
448 - def get_windows(self):
449 """ 450 @rtype: list of L{Window} 451 @return: Returns a list of windows handled by this thread. 452 """ 453 try: 454 process = self.get_process() 455 except Exception: 456 process = None 457 return [ 458 Window( hWnd, process, self ) \ 459 for hWnd in win32.EnumThreadWindows( self.get_tid() ) 460 ]
461 462 #------------------------------------------------------------------------------ 463 464 # TODO 465 # A registers cache could be implemented here.
466 - def get_context(self, ContextFlags = None, bSuspend = False):
467 """ 468 Retrieves the execution context (i.e. the registers values) for this 469 thread. 470 471 @type ContextFlags: int 472 @param ContextFlags: Optional, specify which registers to retrieve. 473 Defaults to C{win32.CONTEXT_ALL} which retrieves all registes 474 for the current platform. 475 476 @type bSuspend: bool 477 @param bSuspend: C{True} to automatically suspend the thread before 478 getting its context, C{False} otherwise. 479 480 Defaults to C{False} because suspending the thread during some 481 debug events (like thread creation or destruction) may lead to 482 strange errors. 483 484 Note that WinAppDbg 1.4 used to suspend the thread automatically 485 always. This behavior was changed in version 1.5. 486 487 @rtype: dict( str S{->} int ) 488 @return: Dictionary mapping register names to their values. 489 490 @see: L{set_context} 491 """ 492 493 # Some words on the "strange errors" that lead to the bSuspend 494 # parameter. Peter Van Eeckhoutte and I were working on a fix 495 # for some bugs he found in the 1.5 betas when we stumbled upon 496 # what seemed to be a deadlock in the debug API that caused the 497 # GetThreadContext() call never to return. Since removing the 498 # call to SuspendThread() solved the problem, and a few Google 499 # searches showed a handful of problems related to these two 500 # APIs and Wow64 environments, I decided to break compatibility. 501 # 502 # Here are some pages about the weird behavior of SuspendThread: 503 # http://zachsaw.blogspot.com.es/2010/11/wow64-bug-getthreadcontext-may-return.html 504 # http://stackoverflow.com/questions/3444190/windows-suspendthread-doesnt-getthreadcontext-fails 505 506 # Get the thread handle. 507 dwAccess = win32.THREAD_GET_CONTEXT 508 if bSuspend: 509 dwAccess = dwAccess | win32.THREAD_SUSPEND_RESUME 510 hThread = self.get_handle(dwAccess) 511 512 # Suspend the thread if requested. 513 if bSuspend: 514 try: 515 self.suspend() 516 except WindowsError: 517 # Threads can't be suspended when the exit process event 518 # arrives, but you can still get the context. 519 bSuspend = False 520 521 # If an exception is raised, make sure the thread execution is resumed. 522 try: 523 524 if win32.bits == self.get_bits(): 525 526 # 64 bit debugger attached to 64 bit process, or 527 # 32 bit debugger attached to 32 bit process. 528 ctx = win32.GetThreadContext(hThread, 529 ContextFlags = ContextFlags) 530 531 else: 532 if self.is_wow64(): 533 534 # 64 bit debugger attached to 32 bit process. 535 if ContextFlags is not None: 536 ContextFlags &= ~win32.ContextArchMask 537 ContextFlags |= win32.WOW64_CONTEXT_i386 538 ctx = win32.Wow64GetThreadContext(hThread, ContextFlags) 539 540 else: 541 542 # 32 bit debugger attached to 64 bit process. 543 # XXX only i386/AMD64 is supported in this particular case 544 if win32.arch not in (win32.ARCH_I386, win32.ARCH_AMD64): 545 raise NotImplementedError() 546 if ContextFlags is not None: 547 ContextFlags &= ~win32.ContextArchMask 548 ContextFlags |= win32.context_amd64.CONTEXT_AMD64 549 ctx = win32.context_amd64.GetThreadContext(hThread, 550 ContextFlags = ContextFlags) 551 552 finally: 553 554 # Resume the thread if we suspended it. 555 if bSuspend: 556 self.resume() 557 558 # Return the context. 559 return ctx
560
561 - def set_context(self, context, bSuspend = False):
562 """ 563 Sets the values of the registers. 564 565 @see: L{get_context} 566 567 @type context: dict( str S{->} int ) 568 @param context: Dictionary mapping register names to their values. 569 570 @type bSuspend: bool 571 @param bSuspend: C{True} to automatically suspend the thread before 572 setting its context, C{False} otherwise. 573 574 Defaults to C{False} because suspending the thread during some 575 debug events (like thread creation or destruction) may lead to 576 strange errors. 577 578 Note that WinAppDbg 1.4 used to suspend the thread automatically 579 always. This behavior was changed in version 1.5. 580 """ 581 582 # Get the thread handle. 583 dwAccess = win32.THREAD_SET_CONTEXT 584 if bSuspend: 585 dwAccess = dwAccess | win32.THREAD_SUSPEND_RESUME 586 hThread = self.get_handle(dwAccess) 587 588 # Suspend the thread if requested. 589 if bSuspend: 590 self.suspend() 591 # No fix for the exit process event bug. 592 # Setting the context of a dead thread is pointless anyway. 593 594 # Set the thread context. 595 try: 596 if win32.bits == 64 and self.is_wow64(): 597 win32.Wow64SetThreadContext(hThread, context) 598 else: 599 win32.SetThreadContext(hThread, context) 600 601 # Resume the thread if we suspended it. 602 finally: 603 if bSuspend: 604 self.resume()
605
606 - def get_register(self, register):
607 """ 608 @type register: str 609 @param register: Register name. 610 611 @rtype: int 612 @return: Value of the requested register. 613 """ 614 'Returns the value of a specific register.' 615 context = self.get_context() 616 return context[register]
617
618 - def set_register(self, register, value):
619 """ 620 Sets the value of a specific register. 621 622 @type register: str 623 @param register: Register name. 624 625 @rtype: int 626 @return: Register value. 627 """ 628 context = self.get_context() 629 context[register] = value 630 self.set_context(context)
631 632 #------------------------------------------------------------------------------ 633 634 # TODO: a metaclass would do a better job instead of checking the platform 635 # during module import, also would support mixing 32 and 64 bits 636 637 if win32.arch in (win32.ARCH_I386, win32.ARCH_AMD64): 638
639 - def get_pc(self):
640 """ 641 @rtype: int 642 @return: Value of the program counter register. 643 """ 644 context = self.get_context(win32.CONTEXT_CONTROL) 645 return context.pc
646
647 - def set_pc(self, pc):
648 """ 649 Sets the value of the program counter register. 650 651 @type pc: int 652 @param pc: Value of the program counter register. 653 """ 654 context = self.get_context(win32.CONTEXT_CONTROL) 655 context.pc = pc 656 self.set_context(context)
657
658 - def get_sp(self):
659 """ 660 @rtype: int 661 @return: Value of the stack pointer register. 662 """ 663 context = self.get_context(win32.CONTEXT_CONTROL) 664 return context.sp
665
666 - def set_sp(self, sp):
667 """ 668 Sets the value of the stack pointer register. 669 670 @type sp: int 671 @param sp: Value of the stack pointer register. 672 """ 673 context = self.get_context(win32.CONTEXT_CONTROL) 674 context.sp = sp 675 self.set_context(context)
676
677 - def get_fp(self):
678 """ 679 @rtype: int 680 @return: Value of the frame pointer register. 681 """ 682 flags = win32.CONTEXT_CONTROL | win32.CONTEXT_INTEGER 683 context = self.get_context(flags) 684 return context.fp
685
686 - def set_fp(self, fp):
687 """ 688 Sets the value of the frame pointer register. 689 690 @type fp: int 691 @param fp: Value of the frame pointer register. 692 """ 693 flags = win32.CONTEXT_CONTROL | win32.CONTEXT_INTEGER 694 context = self.get_context(flags) 695 context.fp = fp 696 self.set_context(context)
697 698 #------------------------------------------------------------------------------ 699 700 if win32.arch in (win32.ARCH_I386, win32.ARCH_AMD64): 701
702 - class Flags (object):
703 'Commonly used processor flags' 704 Overflow = 0x800 705 Direction = 0x400 706 Interrupts = 0x200 707 Trap = 0x100 708 Sign = 0x80 709 Zero = 0x40 710 # 0x20 ??? 711 Auxiliary = 0x10 712 # 0x8 ??? 713 Parity = 0x4 714 # 0x2 ??? 715 Carry = 0x1
716
717 - def get_flags(self, FlagMask = 0xFFFFFFFF):
718 """ 719 @type FlagMask: int 720 @param FlagMask: (Optional) Bitwise-AND mask. 721 722 @rtype: int 723 @return: Flags register contents, optionally masking out some bits. 724 """ 725 context = self.get_context(win32.CONTEXT_CONTROL) 726 return context['EFlags'] & FlagMask
727
728 - def set_flags(self, eflags, FlagMask = 0xFFFFFFFF):
729 """ 730 Sets the flags register, optionally masking some bits. 731 732 @type eflags: int 733 @param eflags: Flags register contents. 734 735 @type FlagMask: int 736 @param FlagMask: (Optional) Bitwise-AND mask. 737 """ 738 context = self.get_context(win32.CONTEXT_CONTROL) 739 context['EFlags'] = (context['EFlags'] & FlagMask) | eflags 740 self.set_context(context)
741
742 - def get_flag_value(self, FlagBit):
743 """ 744 @type FlagBit: int 745 @param FlagBit: One of the L{Flags}. 746 747 @rtype: bool 748 @return: Boolean value of the requested flag. 749 """ 750 return bool( self.get_flags(FlagBit) )
751
752 - def set_flag_value(self, FlagBit, FlagValue):
753 """ 754 Sets a single flag, leaving the others intact. 755 756 @type FlagBit: int 757 @param FlagBit: One of the L{Flags}. 758 759 @type FlagValue: bool 760 @param FlagValue: Boolean value of the flag. 761 """ 762 if FlagValue: 763 eflags = FlagBit 764 else: 765 eflags = 0 766 FlagMask = 0xFFFFFFFF ^ FlagBit 767 self.set_flags(eflags, FlagMask)
768
769 - def get_zf(self):
770 """ 771 @rtype: bool 772 @return: Boolean value of the Zero flag. 773 """ 774 return self.get_flag_value(self.Flags.Zero)
775
776 - def get_cf(self):
777 """ 778 @rtype: bool 779 @return: Boolean value of the Carry flag. 780 """ 781 return self.get_flag_value(self.Flags.Carry)
782
783 - def get_sf(self):
784 """ 785 @rtype: bool 786 @return: Boolean value of the Sign flag. 787 """ 788 return self.get_flag_value(self.Flags.Sign)
789
790 - def get_df(self):
791 """ 792 @rtype: bool 793 @return: Boolean value of the Direction flag. 794 """ 795 return self.get_flag_value(self.Flags.Direction)
796
797 - def get_tf(self):
798 """ 799 @rtype: bool 800 @return: Boolean value of the Trap flag. 801 """ 802 return self.get_flag_value(self.Flags.Trap)
803
804 - def clear_zf(self):
805 'Clears the Zero flag.' 806 self.set_flag_value(self.Flags.Zero, False)
807
808 - def clear_cf(self):
809 'Clears the Carry flag.' 810 self.set_flag_value(self.Flags.Carry, False)
811
812 - def clear_sf(self):
813 'Clears the Sign flag.' 814 self.set_flag_value(self.Flags.Sign, False)
815
816 - def clear_df(self):
817 'Clears the Direction flag.' 818 self.set_flag_value(self.Flags.Direction, False)
819
820 - def clear_tf(self):
821 'Clears the Trap flag.' 822 self.set_flag_value(self.Flags.Trap, False)
823
824 - def set_zf(self):
825 'Sets the Zero flag.' 826 self.set_flag_value(self.Flags.Zero, True)
827
828 - def set_cf(self):
829 'Sets the Carry flag.' 830 self.set_flag_value(self.Flags.Carry, True)
831
832 - def set_sf(self):
833 'Sets the Sign flag.' 834 self.set_flag_value(self.Flags.Sign, True)
835
836 - def set_df(self):
837 'Sets the Direction flag.' 838 self.set_flag_value(self.Flags.Direction, True)
839
840 - def set_tf(self):
841 'Sets the Trap flag.' 842 self.set_flag_value(self.Flags.Trap, True)
843 844 #------------------------------------------------------------------------------ 845
846 - def is_wow64(self):
847 """ 848 Determines if the thread is running under WOW64. 849 850 @rtype: bool 851 @return: 852 C{True} if the thread is running under WOW64. That is, it belongs 853 to a 32-bit application running in a 64-bit Windows. 854 855 C{False} if the thread belongs to either a 32-bit application 856 running in a 32-bit Windows, or a 64-bit application running in a 857 64-bit Windows. 858 859 @raise WindowsError: On error an exception is raised. 860 861 @see: U{http://msdn.microsoft.com/en-us/library/aa384249(VS.85).aspx} 862 """ 863 try: 864 wow64 = self.__wow64 865 except AttributeError: 866 if (win32.bits == 32 and not win32.wow64): 867 wow64 = False 868 else: 869 wow64 = self.get_process().is_wow64() 870 self.__wow64 = wow64 871 return wow64
872
873 - def get_arch(self):
874 """ 875 @rtype: str 876 @return: The architecture in which this thread believes to be running. 877 For example, if running a 32 bit binary in a 64 bit machine, the 878 architecture returned by this method will be L{win32.ARCH_I386}, 879 but the value of L{System.arch} will be L{win32.ARCH_AMD64}. 880 """ 881 if win32.bits == 32 and not win32.wow64: 882 return win32.arch 883 return self.get_process().get_arch()
884
885 - def get_bits(self):
886 """ 887 @rtype: str 888 @return: The number of bits in which this thread believes to be 889 running. For example, if running a 32 bit binary in a 64 bit 890 machine, the number of bits returned by this method will be C{32}, 891 but the value of L{System.arch} will be C{64}. 892 """ 893 if win32.bits == 32 and not win32.wow64: 894 return 32 895 return self.get_process().get_bits()
896
897 - def is_hidden(self):
898 """ 899 Determines if the thread has been hidden from debuggers. 900 901 Some binary packers hide their own threads to thwart debugging. 902 903 @rtype: bool 904 @return: C{True} if the thread is hidden from debuggers. 905 This means the thread's execution won't be stopped for debug 906 events, and thus said events won't be sent to the debugger. 907 """ 908 return win32.NtQueryInformationThread( 909 self.get_handle(), # XXX what permissions do I need? 910 win32.ThreadHideFromDebugger)
911
912 - def get_teb(self):
913 """ 914 Returns a copy of the TEB. 915 To dereference pointers in it call L{Process.read_structure}. 916 917 @rtype: L{TEB} 918 @return: TEB structure. 919 @raise WindowsError: An exception is raised on error. 920 """ 921 return self.get_process().read_structure( self.get_teb_address(), 922 win32.TEB )
923
924 - def get_teb_address(self):
925 """ 926 Returns a remote pointer to the TEB. 927 928 @rtype: int 929 @return: Remote pointer to the L{TEB} structure. 930 @raise WindowsError: An exception is raised on error. 931 """ 932 try: 933 return self._teb_ptr 934 except AttributeError: 935 try: 936 hThread = self.get_handle(win32.THREAD_QUERY_INFORMATION) 937 tbi = win32.NtQueryInformationThread( hThread, 938 win32.ThreadBasicInformation) 939 address = tbi.TebBaseAddress 940 except WindowsError: 941 address = self.get_linear_address('SegFs', 0) # fs:[0] 942 if not address: 943 raise 944 self._teb_ptr = address 945 return address
946
947 - def get_linear_address(self, segment, address):
948 """ 949 Translates segment-relative addresses to linear addresses. 950 951 Linear addresses can be used to access a process memory, 952 calling L{Process.read} and L{Process.write}. 953 954 @type segment: str 955 @param segment: Segment register name. 956 957 @type address: int 958 @param address: Segment relative memory address. 959 960 @rtype: int 961 @return: Linear memory address. 962 963 @raise ValueError: Address is too large for selector. 964 965 @raise WindowsError: 966 The current architecture does not support selectors. 967 Selectors only exist in x86-based systems. 968 """ 969 hThread = self.get_handle(win32.THREAD_QUERY_INFORMATION) 970 selector = self.get_register(segment) 971 ldt = win32.GetThreadSelectorEntry(hThread, selector) 972 BaseLow = ldt.BaseLow 973 BaseMid = ldt.HighWord.Bytes.BaseMid << 16 974 BaseHi = ldt.HighWord.Bytes.BaseHi << 24 975 Base = BaseLow | BaseMid | BaseHi 976 LimitLow = ldt.LimitLow 977 LimitHi = ldt.HighWord.Bits.LimitHi << 16 978 Limit = LimitLow | LimitHi 979 if address > Limit: 980 msg = "Address %s too large for segment %s (selector %d)" 981 msg = msg % (HexDump.address(address, self.get_bits()), 982 segment, selector) 983 raise ValueError(msg) 984 return Base + address
985
986 - def get_label_at_pc(self):
987 """ 988 @rtype: str 989 @return: Label that points to the instruction currently being executed. 990 """ 991 return self.get_process().get_label_at_address( self.get_pc() )
992
993 - def get_seh_chain_pointer(self):
994 """ 995 Get the pointer to the first structured exception handler block. 996 997 @rtype: int 998 @return: Remote pointer to the first block of the structured exception 999 handlers linked list. If the list is empty, the returned value is 1000 C{0xFFFFFFFF}. 1001 1002 @raise NotImplementedError: 1003 This method is only supported in 32 bits versions of Windows. 1004 """ 1005 if win32.arch != win32.ARCH_I386: 1006 raise NotImplementedError( 1007 "SEH chain parsing is only supported in 32-bit Windows.") 1008 1009 process = self.get_process() 1010 address = self.get_linear_address( 'SegFs', 0 ) 1011 return process.read_pointer( address )
1012
1013 - def set_seh_chain_pointer(self, value):
1014 """ 1015 Change the pointer to the first structured exception handler block. 1016 1017 @type value: int 1018 @param value: Value of the remote pointer to the first block of the 1019 structured exception handlers linked list. To disable SEH set the 1020 value C{0xFFFFFFFF}. 1021 1022 @raise NotImplementedError: 1023 This method is only supported in 32 bits versions of Windows. 1024 """ 1025 if win32.arch != win32.ARCH_I386: 1026 raise NotImplementedError( 1027 "SEH chain parsing is only supported in 32-bit Windows.") 1028 1029 process = self.get_process() 1030 address = self.get_linear_address( 'SegFs', 0 ) 1031 process.write_pointer( address, value )
1032
1033 - def get_seh_chain(self):
1034 """ 1035 @rtype: list of tuple( int, int ) 1036 @return: List of structured exception handlers. 1037 Each SEH is represented as a tuple of two addresses: 1038 - Address of this SEH block 1039 - Address of the SEH callback function 1040 Do not confuse this with the contents of the SEH block itself, 1041 where the first member is a pointer to the B{next} block instead. 1042 1043 @raise NotImplementedError: 1044 This method is only supported in 32 bits versions of Windows. 1045 """ 1046 seh_chain = list() 1047 try: 1048 process = self.get_process() 1049 seh = self.get_seh_chain_pointer() 1050 while seh != 0xFFFFFFFF: 1051 seh_func = process.read_pointer( seh + 4 ) 1052 seh_chain.append( (seh, seh_func) ) 1053 seh = process.read_pointer( seh ) 1054 except WindowsError, e: 1055 seh_chain.append( (seh, None) ) 1056 return seh_chain
1057
1058 - def get_wait_chain(self):
1059 """ 1060 @rtype: 1061 tuple of ( 1062 list of L{win32.WaitChainNodeInfo} structures, 1063 bool) 1064 @return: 1065 Wait chain for the thread. 1066 The boolean indicates if there's a cycle in the chain (a deadlock). 1067 @raise AttributeError: 1068 This method is only suppported in Windows Vista and above. 1069 @see: 1070 U{http://msdn.microsoft.com/en-us/library/ms681622%28VS.85%29.aspx} 1071 """ 1072 with win32.OpenThreadWaitChainSession() as hWct: 1073 return win32.GetThreadWaitChain(hWct, ThreadId = self.get_tid())
1074
1075 - def get_stack_range(self):
1076 """ 1077 @rtype: tuple( int, int ) 1078 @return: Stack beginning and end pointers, in memory addresses order. 1079 That is, the first pointer is the stack top, and the second pointer 1080 is the stack bottom, since the stack grows towards lower memory 1081 addresses. 1082 @raise WindowsError: Raises an exception on error. 1083 """ 1084 # TODO use teb.DeallocationStack too (max. possible stack size) 1085 teb = self.get_teb() 1086 tib = teb.NtTib 1087 return ( tib.StackLimit, tib.StackBase ) # top, bottom
1088
1089 - def __get_stack_trace(self, depth = 16, bUseLabels = True, 1090 bMakePretty = True):
1091 """ 1092 Tries to get a stack trace for the current function using the debug 1093 helper API (dbghelp.dll). 1094 1095 @type depth: int 1096 @param depth: Maximum depth of stack trace. 1097 1098 @type bUseLabels: bool 1099 @param bUseLabels: C{True} to use labels, C{False} to use addresses. 1100 1101 @type bMakePretty: bool 1102 @param bMakePretty: 1103 C{True} for user readable labels, 1104 C{False} for labels that can be passed to L{Process.resolve_label}. 1105 1106 "Pretty" labels look better when producing output for the user to 1107 read, while pure labels are more useful programatically. 1108 1109 @rtype: tuple of tuple( int, int, str ) 1110 @return: Stack trace of the thread as a tuple of 1111 ( return address, frame pointer address, module filename ) 1112 when C{bUseLabels} is C{True}, or a tuple of 1113 ( return address, frame pointer label ) 1114 when C{bUseLabels} is C{False}. 1115 1116 @raise WindowsError: Raises an exception on error. 1117 """ 1118 1119 aProcess = self.get_process() 1120 arch = aProcess.get_arch() 1121 bits = aProcess.get_bits() 1122 1123 if arch == win32.ARCH_I386: 1124 MachineType = win32.IMAGE_FILE_MACHINE_I386 1125 elif arch == win32.ARCH_AMD64: 1126 MachineType = win32.IMAGE_FILE_MACHINE_AMD64 1127 elif arch == win32.ARCH_IA64: 1128 MachineType = win32.IMAGE_FILE_MACHINE_IA64 1129 else: 1130 msg = "Stack walking is not available for this architecture: %s" 1131 raise NotImplementedError(msg % arch) 1132 1133 hProcess = aProcess.get_handle( win32.PROCESS_VM_READ | 1134 win32.PROCESS_QUERY_INFORMATION ) 1135 hThread = self.get_handle( win32.THREAD_GET_CONTEXT | 1136 win32.THREAD_QUERY_INFORMATION ) 1137 1138 StackFrame = win32.STACKFRAME64() 1139 StackFrame.AddrPC = win32.ADDRESS64( self.get_pc() ) 1140 StackFrame.AddrFrame = win32.ADDRESS64( self.get_fp() ) 1141 StackFrame.AddrStack = win32.ADDRESS64( self.get_sp() ) 1142 1143 trace = list() 1144 while win32.StackWalk64(MachineType, hProcess, hThread, StackFrame): 1145 if depth <= 0: 1146 break 1147 fp = StackFrame.AddrFrame.Offset 1148 ra = aProcess.peek_pointer(fp + 4) 1149 if ra == 0: 1150 break 1151 lib = aProcess.get_module_at_address(ra) 1152 if lib is None: 1153 lib = "" 1154 else: 1155 if lib.fileName: 1156 lib = lib.fileName 1157 else: 1158 lib = "%s" % HexDump.address(lib.lpBaseOfDll, bits) 1159 if bUseLabels: 1160 label = aProcess.get_label_at_address(ra) 1161 if bMakePretty: 1162 label = '%s (%s)' % (HexDump.address(ra, bits), label) 1163 trace.append( (fp, label) ) 1164 else: 1165 trace.append( (fp, ra, lib) ) 1166 fp = aProcess.peek_pointer(fp) 1167 return tuple(trace)
1168
1169 - def __get_stack_trace_manually(self, depth = 16, bUseLabels = True, 1170 bMakePretty = True):
1171 """ 1172 Tries to get a stack trace for the current function. 1173 Only works for functions with standard prologue and epilogue. 1174 1175 @type depth: int 1176 @param depth: Maximum depth of stack trace. 1177 1178 @type bUseLabels: bool 1179 @param bUseLabels: C{True} to use labels, C{False} to use addresses. 1180 1181 @type bMakePretty: bool 1182 @param bMakePretty: 1183 C{True} for user readable labels, 1184 C{False} for labels that can be passed to L{Process.resolve_label}. 1185 1186 "Pretty" labels look better when producing output for the user to 1187 read, while pure labels are more useful programatically. 1188 1189 @rtype: tuple of tuple( int, int, str ) 1190 @return: Stack trace of the thread as a tuple of 1191 ( return address, frame pointer address, module filename ) 1192 when C{bUseLabels} is C{True}, or a tuple of 1193 ( return address, frame pointer label ) 1194 when C{bUseLabels} is C{False}. 1195 1196 @raise WindowsError: Raises an exception on error. 1197 """ 1198 aProcess = self.get_process() 1199 st, sb = self.get_stack_range() # top, bottom 1200 fp = self.get_fp() 1201 trace = list() 1202 if aProcess.get_module_count() == 0: 1203 aProcess.scan_modules() 1204 bits = aProcess.get_bits() 1205 while depth > 0: 1206 if fp == 0: 1207 break 1208 if not st <= fp < sb: 1209 break 1210 ra = aProcess.peek_pointer(fp + 4) 1211 if ra == 0: 1212 break 1213 lib = aProcess.get_module_at_address(ra) 1214 if lib is None: 1215 lib = "" 1216 else: 1217 if lib.fileName: 1218 lib = lib.fileName 1219 else: 1220 lib = "%s" % HexDump.address(lib.lpBaseOfDll, bits) 1221 if bUseLabels: 1222 label = aProcess.get_label_at_address(ra) 1223 if bMakePretty: 1224 label = '%s (%s)' % (HexDump.address(ra, bits), label) 1225 trace.append( (fp, label) ) 1226 else: 1227 trace.append( (fp, ra, lib) ) 1228 fp = aProcess.peek_pointer(fp) 1229 return tuple(trace)
1230
1231 - def get_stack_trace(self, depth = 16):
1232 """ 1233 Tries to get a stack trace for the current function. 1234 Only works for functions with standard prologue and epilogue. 1235 1236 @type depth: int 1237 @param depth: Maximum depth of stack trace. 1238 1239 @rtype: tuple of tuple( int, int, str ) 1240 @return: Stack trace of the thread as a tuple of 1241 ( return address, frame pointer address, module filename ). 1242 1243 @raise WindowsError: Raises an exception on error. 1244 """ 1245 try: 1246 trace = self.__get_stack_trace(depth, False) 1247 except Exception, e: 1248 import traceback 1249 traceback.print_exc(e) 1250 trace = () 1251 if not trace: 1252 trace = self.__get_stack_trace_manually(depth, False) 1253 return trace
1254
1255 - def get_stack_trace_with_labels(self, depth = 16, bMakePretty = True):
1256 """ 1257 Tries to get a stack trace for the current function. 1258 Only works for functions with standard prologue and epilogue. 1259 1260 @type depth: int 1261 @param depth: Maximum depth of stack trace. 1262 1263 @type bMakePretty: bool 1264 @param bMakePretty: 1265 C{True} for user readable labels, 1266 C{False} for labels that can be passed to L{Process.resolve_label}. 1267 1268 "Pretty" labels look better when producing output for the user to 1269 read, while pure labels are more useful programatically. 1270 1271 @rtype: tuple of tuple( int, int, str ) 1272 @return: Stack trace of the thread as a tuple of 1273 ( return address, frame pointer label ). 1274 1275 @raise WindowsError: Raises an exception on error. 1276 """ 1277 try: 1278 trace = self.__get_stack_trace(depth, True, bMakePretty) 1279 except Exception, e: 1280 trace = () 1281 if not trace: 1282 trace = self.__get_stack_trace_manually(depth, True, bMakePretty) 1283 return trace
1284
1285 - def get_stack_frame_range(self):
1286 """ 1287 Returns the starting and ending addresses of the stack frame. 1288 Only works for functions with standard prologue and epilogue. 1289 1290 @rtype: tuple( int, int ) 1291 @return: Stack frame range. 1292 May not be accurate, depending on the compiler used. 1293 1294 @raise RuntimeError: The stack frame is invalid, 1295 or the function doesn't have a standard prologue 1296 and epilogue. 1297 1298 @raise WindowsError: An error occured when getting the thread context. 1299 """ 1300 st, sb = self.get_stack_range() # top, bottom 1301 sp = self.get_sp() 1302 fp = self.get_fp() 1303 size = fp - sp 1304 if not st <= sp < sb: 1305 raise RuntimeError('Stack pointer lies outside the stack') 1306 if not st <= fp < sb: 1307 raise RuntimeError('Frame pointer lies outside the stack') 1308 if sp > fp: 1309 raise RuntimeError('No valid stack frame found') 1310 return (sp, fp)
1311
1312 - def get_stack_frame(self, max_size = None):
1313 """ 1314 Reads the contents of the current stack frame. 1315 Only works for functions with standard prologue and epilogue. 1316 1317 @type max_size: int 1318 @param max_size: (Optional) Maximum amount of bytes to read. 1319 1320 @rtype: str 1321 @return: Stack frame data. 1322 May not be accurate, depending on the compiler used. 1323 May return an empty string. 1324 1325 @raise RuntimeError: The stack frame is invalid, 1326 or the function doesn't have a standard prologue 1327 and epilogue. 1328 1329 @raise WindowsError: An error occured when getting the thread context 1330 or reading data from the process memory. 1331 """ 1332 sp, fp = self.get_stack_frame_range() 1333 size = fp - sp 1334 if max_size and size > max_size: 1335 size = max_size 1336 return self.get_process().peek(sp, size)
1337
1338 - def read_stack_data(self, size = 128, offset = 0):
1339 """ 1340 Reads the contents of the top of the stack. 1341 1342 @type size: int 1343 @param size: Number of bytes to read. 1344 1345 @type offset: int 1346 @param offset: Offset from the stack pointer to begin reading. 1347 1348 @rtype: str 1349 @return: Stack data. 1350 1351 @raise WindowsError: Could not read the requested data. 1352 """ 1353 aProcess = self.get_process() 1354 return aProcess.read(self.get_sp() + offset, size)
1355
1356 - def peek_stack_data(self, size = 128, offset = 0):
1357 """ 1358 Tries to read the contents of the top of the stack. 1359 1360 @type size: int 1361 @param size: Number of bytes to read. 1362 1363 @type offset: int 1364 @param offset: Offset from the stack pointer to begin reading. 1365 1366 @rtype: str 1367 @return: Stack data. 1368 Returned data may be less than the requested size. 1369 """ 1370 aProcess = self.get_process() 1371 return aProcess.peek(self.get_sp() + offset, size)
1372
1373 - def read_stack_dwords(self, count, offset = 0):
1374 """ 1375 Reads DWORDs from the top of the stack. 1376 1377 @type count: int 1378 @param count: Number of DWORDs to read. 1379 1380 @type offset: int 1381 @param offset: Offset from the stack pointer to begin reading. 1382 1383 @rtype: tuple( int... ) 1384 @return: Tuple of integers read from the stack. 1385 1386 @raise WindowsError: Could not read the requested data. 1387 """ 1388 if count > 0: 1389 stackData = self.read_stack_data(count * 4, offset) 1390 return struct.unpack('<'+('L'*count), stackData) 1391 return ()
1392
1393 - def peek_stack_dwords(self, count, offset = 0):
1394 """ 1395 Tries to read DWORDs from the top of the stack. 1396 1397 @type count: int 1398 @param count: Number of DWORDs to read. 1399 1400 @type offset: int 1401 @param offset: Offset from the stack pointer to begin reading. 1402 1403 @rtype: tuple( int... ) 1404 @return: Tuple of integers read from the stack. 1405 May be less than the requested number of DWORDs. 1406 """ 1407 stackData = self.peek_stack_data(count * 4, offset) 1408 if len(stackData) & 3: 1409 stackData = stackData[:-len(stackData) & 3] 1410 if not stackData: 1411 return () 1412 return struct.unpack('<'+('L'*count), stackData)
1413
1414 - def read_stack_qwords(self, count, offset = 0):
1415 """ 1416 Reads QWORDs from the top of the stack. 1417 1418 @type count: int 1419 @param count: Number of QWORDs to read. 1420 1421 @type offset: int 1422 @param offset: Offset from the stack pointer to begin reading. 1423 1424 @rtype: tuple( int... ) 1425 @return: Tuple of integers read from the stack. 1426 1427 @raise WindowsError: Could not read the requested data. 1428 """ 1429 stackData = self.read_stack_data(count * 8, offset) 1430 return struct.unpack('<'+('Q'*count), stackData)
1431
1432 - def peek_stack_qwords(self, count, offset = 0):
1433 """ 1434 Tries to read QWORDs from the top of the stack. 1435 1436 @type count: int 1437 @param count: Number of QWORDs to read. 1438 1439 @type offset: int 1440 @param offset: Offset from the stack pointer to begin reading. 1441 1442 @rtype: tuple( int... ) 1443 @return: Tuple of integers read from the stack. 1444 May be less than the requested number of QWORDs. 1445 """ 1446 stackData = self.peek_stack_data(count * 8, offset) 1447 if len(stackData) & 7: 1448 stackData = stackData[:-len(stackData) & 7] 1449 if not stackData: 1450 return () 1451 return struct.unpack('<'+('Q'*count), stackData)
1452
1453 - def read_stack_structure(self, structure, offset = 0):
1454 """ 1455 Reads the given structure at the top of the stack. 1456 1457 @type structure: ctypes.Structure 1458 @param structure: Structure of the data to read from the stack. 1459 1460 @type offset: int 1461 @param offset: Offset from the stack pointer to begin reading. 1462 The stack pointer is the same returned by the L{get_sp} method. 1463 1464 @rtype: tuple 1465 @return: Tuple of elements read from the stack. The type of each 1466 element matches the types in the stack frame structure. 1467 """ 1468 aProcess = self.get_process() 1469 stackData = aProcess.read_structure(self.get_sp() + offset, structure) 1470 return tuple([ stackData.__getattribute__(name) 1471 for (name, type) in stackData._fields_ ])
1472
1473 - def read_stack_frame(self, structure, offset = 0):
1474 """ 1475 Reads the stack frame of the thread. 1476 1477 @type structure: ctypes.Structure 1478 @param structure: Structure of the stack frame. 1479 1480 @type offset: int 1481 @param offset: Offset from the frame pointer to begin reading. 1482 The frame pointer is the same returned by the L{get_fp} method. 1483 1484 @rtype: tuple 1485 @return: Tuple of elements read from the stack frame. The type of each 1486 element matches the types in the stack frame structure. 1487 """ 1488 aProcess = self.get_process() 1489 stackData = aProcess.read_structure(self.get_fp() + offset, structure) 1490 return tuple([ stackData.__getattribute__(name) 1491 for (name, type) in stackData._fields_ ])
1492
1493 - def read_code_bytes(self, size = 128, offset = 0):
1494 """ 1495 Tries to read some bytes of the code currently being executed. 1496 1497 @type size: int 1498 @param size: Number of bytes to read. 1499 1500 @type offset: int 1501 @param offset: Offset from the program counter to begin reading. 1502 1503 @rtype: str 1504 @return: Bytes read from the process memory. 1505 1506 @raise WindowsError: Could not read the requested data. 1507 """ 1508 return self.get_process().read(self.get_pc() + offset, size)
1509
1510 - def peek_code_bytes(self, size = 128, offset = 0):
1511 """ 1512 Tries to read some bytes of the code currently being executed. 1513 1514 @type size: int 1515 @param size: Number of bytes to read. 1516 1517 @type offset: int 1518 @param offset: Offset from the program counter to begin reading. 1519 1520 @rtype: str 1521 @return: Bytes read from the process memory. 1522 May be less than the requested number of bytes. 1523 """ 1524 return self.get_process().peek(self.get_pc() + offset, size)
1525
1526 - def peek_pointers_in_registers(self, peekSize = 16, context = None):
1527 """ 1528 Tries to guess which values in the registers are valid pointers, 1529 and reads some data from them. 1530 1531 @type peekSize: int 1532 @param peekSize: Number of bytes to read from each pointer found. 1533 1534 @type context: dict( str S{->} int ) 1535 @param context: (Optional) 1536 Dictionary mapping register names to their values. 1537 If not given, the current thread context will be used. 1538 1539 @rtype: dict( str S{->} str ) 1540 @return: Dictionary mapping register names to the data they point to. 1541 """ 1542 peekable_registers = ( 1543 'Eax', 'Ebx', 'Ecx', 'Edx', 'Esi', 'Edi', 'Ebp' 1544 ) 1545 if not context: 1546 context = self.get_context(win32.CONTEXT_CONTROL | \ 1547 win32.CONTEXT_INTEGER) 1548 aProcess = self.get_process() 1549 data = dict() 1550 for (reg_name, reg_value) in context.iteritems(): 1551 if reg_name not in peekable_registers: 1552 continue 1553 ## if reg_name == 'Ebp': 1554 ## stack_begin, stack_end = self.get_stack_range() 1555 ## print hex(stack_end), hex(reg_value), hex(stack_begin) 1556 ## if stack_begin and stack_end and stack_end < stack_begin and \ 1557 ## stack_begin <= reg_value <= stack_end: 1558 ## continue 1559 reg_data = aProcess.peek(reg_value, peekSize) 1560 if reg_data: 1561 data[reg_name] = reg_data 1562 return data
1563 1564 # TODO 1565 # try to avoid reading the same page twice by caching it
1566 - def peek_pointers_in_data(self, data, peekSize = 16, peekStep = 1):
1567 """ 1568 Tries to guess which values in the given data are valid pointers, 1569 and reads some data from them. 1570 1571 @type data: str 1572 @param data: Binary data to find pointers in. 1573 1574 @type peekSize: int 1575 @param peekSize: Number of bytes to read from each pointer found. 1576 1577 @type peekStep: int 1578 @param peekStep: Expected data alignment. 1579 Tipically you specify 1 when data alignment is unknown, 1580 or 4 when you expect data to be DWORD aligned. 1581 Any other value may be specified. 1582 1583 @rtype: dict( str S{->} str ) 1584 @return: Dictionary mapping stack offsets to the data they point to. 1585 """ 1586 aProcess = self.get_process() 1587 return aProcess.peek_pointers_in_data(data, peekSize, peekStep)
1588 1589 #------------------------------------------------------------------------------ 1590 1591 # TODO 1592 # The disassemble_around and disassemble_around_pc methods 1593 # should take as parameter instruction counts rather than sizes 1594
1595 - def disassemble_string(self, lpAddress, code):
1596 """ 1597 Disassemble instructions from a block of binary code. 1598 1599 @type lpAddress: int 1600 @param lpAddress: Memory address where the code was read from. 1601 1602 @type code: str 1603 @param code: Binary code to disassemble. 1604 1605 @rtype: list of tuple( long, int, str, str ) 1606 @return: List of tuples. Each tuple represents an assembly instruction 1607 and contains: 1608 - Memory address of instruction. 1609 - Size of instruction in bytes. 1610 - Disassembly line of instruction. 1611 - Hexadecimal dump of instruction. 1612 """ 1613 aProcess = self.get_process() 1614 return aProcess.disassemble_string(lpAddress, code)
1615
1616 - def disassemble(self, lpAddress, dwSize):
1617 """ 1618 Disassemble instructions from the address space of the process. 1619 1620 @type lpAddress: int 1621 @param lpAddress: Memory address where to read the code from. 1622 1623 @type dwSize: int 1624 @param dwSize: Size of binary code to disassemble. 1625 1626 @rtype: list of tuple( long, int, str, str ) 1627 @return: List of tuples. Each tuple represents an assembly instruction 1628 and contains: 1629 - Memory address of instruction. 1630 - Size of instruction in bytes. 1631 - Disassembly line of instruction. 1632 - Hexadecimal dump of instruction. 1633 """ 1634 aProcess = self.get_process() 1635 return aProcess.disassemble(lpAddress, dwSize)
1636
1637 - def disassemble_around(self, lpAddress, dwSize = 64):
1638 """ 1639 Disassemble around the given address. 1640 1641 @type lpAddress: int 1642 @param lpAddress: Memory address where to read the code from. 1643 1644 @type dwSize: int 1645 @param dwSize: Delta offset. 1646 Code will be read from lpAddress - dwSize to lpAddress + dwSize. 1647 1648 @rtype: list of tuple( long, int, str, str ) 1649 @return: List of tuples. Each tuple represents an assembly instruction 1650 and contains: 1651 - Memory address of instruction. 1652 - Size of instruction in bytes. 1653 - Disassembly line of instruction. 1654 - Hexadecimal dump of instruction. 1655 """ 1656 aProcess = self.get_process() 1657 return aProcess.disassemble_around(lpAddress, dwSize)
1658
1659 - def disassemble_around_pc(self, dwSize = 64):
1660 """ 1661 Disassemble around the program counter of the given thread. 1662 1663 @type dwSize: int 1664 @param dwSize: Delta offset. 1665 Code will be read from pc - dwSize to pc + dwSize. 1666 1667 @rtype: list of tuple( long, int, str, str ) 1668 @return: List of tuples. Each tuple represents an assembly instruction 1669 and contains: 1670 - Memory address of instruction. 1671 - Size of instruction in bytes. 1672 - Disassembly line of instruction. 1673 - Hexadecimal dump of instruction. 1674 """ 1675 aProcess = self.get_process() 1676 return aProcess.disassemble_around(self.get_pc(), dwSize)
1677
1678 - def disassemble_instruction(self, lpAddress):
1679 """ 1680 Disassemble the instruction at the given memory address. 1681 1682 @type lpAddress: int 1683 @param lpAddress: Memory address where to read the code from. 1684 1685 @rtype: tuple( long, int, str, str ) 1686 @return: The tuple represents an assembly instruction 1687 and contains: 1688 - Memory address of instruction. 1689 - Size of instruction in bytes. 1690 - Disassembly line of instruction. 1691 - Hexadecimal dump of instruction. 1692 """ 1693 aProcess = self.get_process() 1694 return aProcess.disassemble(lpAddress, 15)[0]
1695
1696 - def disassemble_current(self):
1697 """ 1698 Disassemble the instruction at the program counter of the given thread. 1699 1700 @rtype: tuple( long, int, str, str ) 1701 @return: The tuple represents an assembly instruction 1702 and contains: 1703 - Memory address of instruction. 1704 - Size of instruction in bytes. 1705 - Disassembly line of instruction. 1706 - Hexadecimal dump of instruction. 1707 """ 1708 return self.disassemble_instruction( self.get_pc() )
1709 1710 #============================================================================== 1711
1712 -class _ThreadContainer (object):
1713 """ 1714 Encapsulates the capability to contain Thread objects. 1715 1716 @group Instrumentation: 1717 start_thread 1718 1719 @group Threads snapshot: 1720 scan_threads, 1721 get_thread, get_thread_count, get_thread_ids, 1722 has_thread, iter_threads, iter_thread_ids, 1723 find_threads_by_name, get_windows, 1724 clear_threads, clear_dead_threads, close_thread_handles 1725 """ 1726
1727 - def __init__(self):
1728 self.__threadDict = dict()
1729
1730 - def __initialize_snapshot(self):
1731 """ 1732 Private method to automatically initialize the snapshot 1733 when you try to use it without calling any of the scan_* 1734 methods first. You don't need to call this yourself. 1735 """ 1736 if not self.__threadDict: 1737 self.scan_threads()
1738
1739 - def __contains__(self, anObject):
1740 """ 1741 @type anObject: L{Thread}, int 1742 @param anObject: 1743 - C{int}: Global ID of the thread to look for. 1744 - C{Thread}: Thread object to look for. 1745 1746 @rtype: bool 1747 @return: C{True} if the snapshot contains 1748 a L{Thread} object with the same ID. 1749 """ 1750 if isinstance(anObject, Thread): 1751 anObject = anObject.dwThreadId 1752 return self.has_thread(anObject)
1753
1754 - def __iter__(self):
1755 """ 1756 @see: L{iter_threads} 1757 @rtype: dictionary-valueiterator 1758 @return: Iterator of L{Thread} objects in this snapshot. 1759 """ 1760 return self.iter_threads()
1761
1762 - def __len__(self):
1763 """ 1764 @see: L{get_thread_count} 1765 @rtype: int 1766 @return: Count of L{Thread} objects in this snapshot. 1767 """ 1768 return self.get_thread_count()
1769
1770 - def has_thread(self, dwThreadId):
1771 """ 1772 @type dwThreadId: int 1773 @param dwThreadId: Global ID of the thread to look for. 1774 1775 @rtype: bool 1776 @return: C{True} if the snapshot contains a 1777 L{Thread} object with the given global ID. 1778 """ 1779 self.__initialize_snapshot() 1780 return dwThreadId in self.__threadDict
1781
1782 - def get_thread(self, dwThreadId):
1783 """ 1784 @type dwThreadId: int 1785 @param dwThreadId: Global ID of the thread to look for. 1786 1787 @rtype: L{Thread} 1788 @return: Thread object with the given global ID. 1789 """ 1790 self.__initialize_snapshot() 1791 if dwThreadId not in self.__threadDict: 1792 msg = "Unknown thread ID: %d" % dwThreadId 1793 raise KeyError(msg) 1794 return self.__threadDict[dwThreadId]
1795
1796 - def iter_thread_ids(self):
1797 """ 1798 @see: L{iter_threads} 1799 @rtype: dictionary-keyiterator 1800 @return: Iterator of global thread IDs in this snapshot. 1801 """ 1802 self.__initialize_snapshot() 1803 return self.__threadDict.iterkeys()
1804
1805 - def iter_threads(self):
1806 """ 1807 @see: L{iter_thread_ids} 1808 @rtype: dictionary-valueiterator 1809 @return: Iterator of L{Thread} objects in this snapshot. 1810 """ 1811 self.__initialize_snapshot() 1812 return self.__threadDict.itervalues()
1813
1814 - def get_thread_ids(self):
1815 """ 1816 @rtype: list( int ) 1817 @return: List of global thread IDs in this snapshot. 1818 """ 1819 self.__initialize_snapshot() 1820 return self.__threadDict.keys()
1821
1822 - def get_thread_count(self):
1823 """ 1824 @rtype: int 1825 @return: Count of L{Thread} objects in this snapshot. 1826 """ 1827 self.__initialize_snapshot() 1828 return len(self.__threadDict)
1829 1830 #------------------------------------------------------------------------------ 1831
1832 - def find_threads_by_name(self, name, bExactMatch = True):
1833 """ 1834 Find threads by name, using different search methods. 1835 1836 @type name: str, None 1837 @param name: Name to look for. Use C{None} to find nameless threads. 1838 1839 @type bExactMatch: bool 1840 @param bExactMatch: C{True} if the name must be 1841 B{exactly} as given, C{False} if the name can be 1842 loosely matched. 1843 1844 This parameter is ignored when C{name} is C{None}. 1845 1846 @rtype: list( L{Thread} ) 1847 @return: All threads matching the given name. 1848 """ 1849 found_threads = list() 1850 1851 # Find threads with no name. 1852 if name is None: 1853 for aThread in self.iter_threads(): 1854 if aThread.get_name() is None: 1855 found_threads.append(aThread) 1856 1857 # Find threads matching the given name exactly. 1858 elif bExactMatch: 1859 for aThread in self.iter_threads(): 1860 if aThread.get_name() == name: 1861 found_threads.append(aThread) 1862 1863 # Find threads whose names match the given substring. 1864 else: 1865 for aThread in self.iter_threads(): 1866 t_name = aThread.get_name() 1867 if t_name is not None and name in t_name: 1868 found_threads.append(aThread) 1869 1870 return found_threads
1871 1872 #------------------------------------------------------------------------------ 1873 1874 # XXX TODO 1875 # Support for string searches on the window captions. 1876
1877 - def get_windows(self):
1878 """ 1879 @rtype: list of L{Window} 1880 @return: Returns a list of windows handled by this process. 1881 """ 1882 window_list = list() 1883 for thread in self.iter_threads(): 1884 window_list.extend( thread.get_windows() ) 1885 return window_list
1886 1887 #------------------------------------------------------------------------------ 1888
1889 - def start_thread(self, lpStartAddress, lpParameter=0, bSuspended = False):
1890 """ 1891 Remotely creates a new thread in the process. 1892 1893 @type lpStartAddress: int 1894 @param lpStartAddress: Start address for the new thread. 1895 1896 @type lpParameter: int 1897 @param lpParameter: Optional argument for the new thread. 1898 1899 @type bSuspended: bool 1900 @param bSuspended: C{True} if the new thread should be suspended. 1901 In that case use L{Thread.resume} to start execution. 1902 """ 1903 if bSuspended: 1904 dwCreationFlags = win32.CREATE_SUSPENDED 1905 else: 1906 dwCreationFlags = 0 1907 hProcess = self.get_handle( win32.PROCESS_CREATE_THREAD | 1908 win32.PROCESS_QUERY_INFORMATION | 1909 win32.PROCESS_VM_OPERATION | 1910 win32.PROCESS_VM_WRITE | 1911 win32.PROCESS_VM_READ ) 1912 hThread, dwThreadId = win32.CreateRemoteThread( 1913 hProcess, 0, 0, lpStartAddress, lpParameter, dwCreationFlags) 1914 aThread = Thread(dwThreadId, hThread, self) 1915 self._add_thread(aThread) 1916 return aThread
1917 1918 #------------------------------------------------------------------------------ 1919 1920 # TODO 1921 # maybe put all the toolhelp code into their own set of classes? 1922 # 1923 # XXX this method musn't end up calling __initialize_snapshot by accident!
1924 - def scan_threads(self):
1925 """ 1926 Populates the snapshot with running threads. 1927 """ 1928 1929 # Ignore special process IDs. 1930 # PID 0: System Idle Process. Also has a special meaning to the 1931 # toolhelp APIs (current process). 1932 # PID 4: System Integrity Group. See this forum post for more info: 1933 # http://tinyurl.com/ycza8jo 1934 # (points to social.technet.microsoft.com) 1935 # Only on XP and above 1936 # PID 8: System (?) only in Windows 2000 and below AFAIK. 1937 # It's probably the same as PID 4 in XP and above. 1938 dwProcessId = self.get_pid() 1939 if dwProcessId in (0, 4, 8): 1940 return 1941 1942 ## dead_tids = set( self.get_thread_ids() ) # XXX triggers a scan 1943 dead_tids = self._get_thread_ids() 1944 dwProcessId = self.get_pid() 1945 hSnapshot = win32.CreateToolhelp32Snapshot(win32.TH32CS_SNAPTHREAD, 1946 dwProcessId) 1947 try: 1948 te = win32.Thread32First(hSnapshot) 1949 while te is not None: 1950 if te.th32OwnerProcessID == dwProcessId: 1951 dwThreadId = te.th32ThreadID 1952 if dwThreadId in dead_tids: 1953 dead_tids.remove(dwThreadId) 1954 ## if not self.has_thread(dwThreadId): # XXX triggers a scan 1955 if not self._has_thread_id(dwThreadId): 1956 aThread = Thread(dwThreadId, process = self) 1957 self._add_thread(aThread) 1958 te = win32.Thread32Next(hSnapshot) 1959 finally: 1960 win32.CloseHandle(hSnapshot) 1961 for tid in dead_tids: 1962 self._del_thread(tid)
1963
1964 - def clear_dead_threads(self):
1965 """ 1966 Remove Thread objects from the snapshot 1967 referring to threads no longer running. 1968 """ 1969 for tid in self.get_thread_ids(): 1970 aThread = self.get_thread(tid) 1971 if not aThread.is_alive(): 1972 self._del_thread(aThread)
1973
1974 - def clear_threads(self):
1975 """ 1976 Clears the threads snapshot. 1977 """ 1978 for aThread in self.__threadDict.itervalues(): 1979 aThread.clear() 1980 self.__threadDict = dict()
1981
1982 - def close_thread_handles(self):
1983 """ 1984 Closes all open handles to threads in the snapshot. 1985 """ 1986 for aThread in self.iter_threads(): 1987 try: 1988 aThread.close_handle() 1989 except Exception, e: 1990 try: 1991 msg = "Cannot close thread handle %s, reason: %s" 1992 msg %= (aThread.hThread.value, str(e)) 1993 warnings.warn(msg) 1994 except Exception: 1995 pass
1996 1997 #------------------------------------------------------------------------------ 1998 1999 # XXX _notify_* methods should not trigger a scan 2000
2001 - def _add_thread(self, aThread):
2002 """ 2003 Private method to add a thread object to the snapshot. 2004 2005 @type aThread: L{Thread} 2006 @param aThread: Thread object. 2007 """ 2008 ## if not isinstance(aThread, Thread): 2009 ## if hasattr(aThread, '__class__'): 2010 ## typename = aThread.__class__.__name__ 2011 ## else: 2012 ## typename = str(type(aThread)) 2013 ## msg = "Expected Thread, got %s instead" % typename 2014 ## raise TypeError(msg) 2015 dwThreadId = aThread.dwThreadId 2016 ## if dwThreadId in self.__threadDict: 2017 ## msg = "Already have a Thread object with ID %d" % dwThreadId 2018 ## raise KeyError(msg) 2019 aThread.set_process(self) 2020 self.__threadDict[dwThreadId] = aThread
2021
2022 - def _del_thread(self, dwThreadId):
2023 """ 2024 Private method to remove a thread object from the snapshot. 2025 2026 @type dwThreadId: int 2027 @param dwThreadId: Global thread ID. 2028 """ 2029 try: 2030 aThread = self.__threadDict[dwThreadId] 2031 del self.__threadDict[dwThreadId] 2032 except KeyError: 2033 aThread = None 2034 msg = "Unknown thread ID %d" % dwThreadId 2035 warnings.warn(msg, RuntimeWarning) 2036 if aThread: 2037 aThread.clear() # remove circular references
2038
2039 - def _has_thread_id(self, dwThreadId):
2040 """ 2041 Private method to test for a thread in the snapshot without triggering 2042 an automatic scan. 2043 """ 2044 return dwThreadId in self.__threadDict
2045
2046 - def _get_thread_ids(self):
2047 """ 2048 Private method to get the list of thread IDs currently in the snapshot 2049 without triggering an automatic scan. 2050 """ 2051 return self.__threadDict.keys()
2052
2053 - def __add_created_thread(self, event):
2054 """ 2055 Private method to automatically add new thread objects from debug events. 2056 2057 @type event: L{Event} 2058 @param event: Event object. 2059 """ 2060 dwThreadId = event.get_tid() 2061 hThread = event.get_thread_handle() 2062 ## if not self.has_thread(dwThreadId): # XXX this would trigger a scan 2063 if not self._has_thread_id(dwThreadId): 2064 aThread = Thread(dwThreadId, hThread, self) 2065 teb_ptr = event.get_teb() # remember the TEB pointer 2066 if teb_ptr: 2067 aThread._teb_ptr = teb_ptr 2068 self._add_thread(aThread)
2069 #else: 2070 # aThread = self.get_thread(dwThreadId) 2071 # if hThread != win32.INVALID_HANDLE_VALUE: 2072 # aThread.hThread = hThread # may have more privileges 2073
2074 - def _notify_create_process(self, event):
2075 """ 2076 Notify the creation of the main thread of this process. 2077 2078 This is done automatically by the L{Debug} class, you shouldn't need 2079 to call it yourself. 2080 2081 @type event: L{CreateProcessEvent} 2082 @param event: Create process event. 2083 2084 @rtype: bool 2085 @return: C{True} to call the user-defined handle, C{False} otherwise. 2086 """ 2087 self.__add_created_thread(event) 2088 return True
2089
2090 - def _notify_create_thread(self, event):
2091 """ 2092 Notify the creation of a new thread in this process. 2093 2094 This is done automatically by the L{Debug} class, you shouldn't need 2095 to call it yourself. 2096 2097 @type event: L{CreateThreadEvent} 2098 @param event: Create thread event. 2099 2100 @rtype: bool 2101 @return: C{True} to call the user-defined handle, C{False} otherwise. 2102 """ 2103 self.__add_created_thread(event) 2104 return True
2105
2106 - def _notify_exit_thread(self, event):
2107 """ 2108 Notify the termination of a thread. 2109 2110 This is done automatically by the L{Debug} class, you shouldn't need 2111 to call it yourself. 2112 2113 @type event: L{ExitThreadEvent} 2114 @param event: Exit thread event. 2115 2116 @rtype: bool 2117 @return: C{True} to call the user-defined handle, C{False} otherwise. 2118 """ 2119 dwThreadId = event.get_tid() 2120 ## if self.has_thread(dwThreadId): # XXX this would trigger a scan 2121 if self._has_thread_id(dwThreadId): 2122 self._del_thread(dwThreadId) 2123 return True
2124