1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 """
29 Instrumentation module.
30
31 @group Instrumentation:
32 System, Process, Thread, Module, Window
33
34 @group Capabilities (private):
35 ModuleContainer, ThreadContainer, ProcessContainer, SymbolContainer,
36 ThreadDebugOperations, ProcessDebugOperations,
37 MemoryOperations, SymbolOperations, SymbolEnumerator
38 """
39
40
41
42
43
44
45
46 __revision__ = "$Id: system.py 764 2010-07-20 10:59:45Z qvasimodo $"
47
48 __all__ = [
49
50 'System',
51 'Process',
52 'Thread',
53 'Module',
54 'Window',
55 ]
56
57 import win32
58 import win32.version
59 from textio import HexInput, HexDump
60 from util import Regenerator, PathOperations, MemoryAddresses, DebugRegister
61
62 import re
63 import os
64 import sys
65 import ctypes
66 import struct
67
68
69 try:
70 from distorm3 import Decode, Decode16Bits, Decode32Bits, Decode64Bits
71 except ImportError:
72 try:
73 from distorm import Decode, Decode16Bits, Decode32Bits, Decode64Bits
74 except ImportError:
75 Decode16Bits = None
76 Decode32Bits = None
77 Decode64Bits = None
79 "PLEASE INSTALL DISTORM BEFORE GENERATING THE DOCUMENTATION"
80 msg = ("diStorm is not installed or can't be found. Download it from: "
81 "http://code.google.com/p/distorm3")
82 raise NotImplementedError, msg
83
87 """
88 Encapsulates the capability to contain Module objects.
89
90 @group Modules snapshot:
91 scan_modules,
92 get_module, get_module_bases, get_module_count,
93 get_module_at_address, get_module_by_name,
94 has_module, iter_modules, iter_module_addresses,
95 clear_modules
96
97 @group Event notifications (private):
98 notify_load_dll,
99 notify_unload_dll
100 """
101
105
107 """
108 Private method to automatically initialize the snapshot
109 when you try to use it without calling any of the scan_*
110 methods first. You don't need to call this yourself.
111 """
112 if not self.__moduleDict:
113 self.scan_modules()
114
116 """
117 @type anObject: L{Module}, int
118 @param anObject:
119 - C{Module}: Module object to look for.
120 - C{int}: Base address of the DLL to look for.
121
122 @rtype: bool
123 @return: C{True} if the snapshot contains
124 a L{Module} object with the same base address.
125 """
126 if isinstance(anObject, Module):
127 anObject = anObject.lpBaseOfDll
128 return self.has_module(anObject)
129
131 """
132 @see: L{iter_modules}
133 @rtype: dictionary-valueiterator
134 @return: Iterator of L{Module} objects in this snapshot.
135 """
136 return self.iter_modules()
137
139 """
140 @see: L{get_module_count}
141 @rtype: int
142 @return: Count of L{Module} objects in this snapshot.
143 """
144 return self.get_module_count()
145
147 """
148 @type lpBaseOfDll: int
149 @param lpBaseOfDll: Base address of the DLL to look for.
150
151 @rtype: bool
152 @return: C{True} if the snapshot contains a
153 L{Module} object with the given base address.
154 """
155 self.__initialize_snapshot()
156 return lpBaseOfDll in self.__moduleDict
157
159 """
160 @type lpBaseOfDll: int
161 @param lpBaseOfDll: Base address of the DLL to look for.
162
163 @rtype: L{Module}
164 @return: Module object with the given base address.
165 """
166 self.__initialize_snapshot()
167 if lpBaseOfDll not in self.__moduleDict:
168 msg = "Unknown DLL base address %s"
169 msg = msg % HexDump.address(lpBaseOfDll)
170 raise KeyError, msg
171 return self.__moduleDict[lpBaseOfDll]
172
174 """
175 @see: L{iter_modules}
176 @rtype: dictionary-keyiterator
177 @return: Iterator of DLL base addresses in this snapshot.
178 """
179 self.__initialize_snapshot()
180 return self.__moduleDict.iterkeys()
181
183 """
184 @see: L{iter_module_addresses}
185 @rtype: dictionary-valueiterator
186 @return: Iterator of L{Module} objects in this snapshot.
187 """
188 self.__initialize_snapshot()
189 return self.__moduleDict.itervalues()
190
192 """
193 @see: L{iter_module_addresses}
194 @rtype: list( int... )
195 @return: List of DLL base addresses in this snapshot.
196 """
197 self.__initialize_snapshot()
198 return self.__moduleDict.keys()
199
201 """
202 @rtype: int
203 @return: Count of L{Module} objects in this snapshot.
204 """
205 self.__initialize_snapshot()
206 return len(self.__moduleDict)
207
208
209
211 """
212 @type modName: int
213 @param modName:
214 Name of the module to look for, as returned by L{Module.get_name}.
215 If two or more modules with the same name are loaded, only one
216 of the matching modules is returned.
217
218 You can also pass a full pathname to the DLL file.
219 This works correctly even if two modules with the same name
220 are loaded from different paths.
221
222 @rtype: L{Module}
223 @return: C{Module} object that best matches the given name.
224 Returns C{None} if no C{Module} can be found.
225 """
226
227
228
229 modName = modName.lower()
230
231
232 if PathOperations.path_is_absolute(modName):
233 for lib in self.iter_modules():
234 if modName == lib.get_filename().lower():
235 return lib
236 return None
237
238
239
240
241 modDict = [ ( lib.get_name(), lib ) for lib in self.iter_modules() ]
242 modDict = dict(modDict)
243
244
245 if modName in modDict:
246 return modDict[modName]
247
248
249 filepart, extpart = PathOperations.split_extension(modName)
250 if filepart and extpart:
251 if filepart in modDict:
252 return modDict[filepart]
253
254
255 try:
256 baseAddress = HexInput.integer(modName)
257 except ValueError:
258 return None
259 if self.has_module(baseAddress):
260 return self.get_module(baseAddress)
261
262
263 return None
264
266 """
267 @type address: int
268 @param address: Memory address to query.
269
270 @rtype: L{Module}
271 @return: C{Module} object that best matches the given address.
272 Returns C{None} if no C{Module} can be found.
273 """
274 bases = self.get_module_bases()
275 bases.sort()
276
277 bases.append(0x1000000000000000)
278 if address >= bases[0]:
279 i = 0
280 max_i = len(bases) - 1
281 while i < max_i:
282 begin, end = bases[i:i+2]
283 if begin <= address <= end:
284 module = self.get_module(begin)
285 here = module.is_address_here(address)
286 if here is False:
287 break
288 else:
289 return module
290 i = i + 1
291 return None
292
293
354
356 """
357 Clears the modules snapshot.
358 """
359 self.__moduleDict = dict()
360
361
362
363
364
366 """
367 Private method to add a module object to the snapshot.
368
369 @type aModule: L{Module}
370 @param aModule: Module object.
371 """
372
373
374
375
376
377
378
379 lpBaseOfDll = aModule.get_base()
380
381
382
383 self.__moduleDict[lpBaseOfDll] = aModule
384
386 """
387 Private method to remove a module object from the snapshot.
388
389 @type lpBaseOfDll: int
390 @param lpBaseOfDll: Module base address.
391 """
392
393
394
395 self.__moduleDict[lpBaseOfDll].hFile = None
396 self.__moduleDict[lpBaseOfDll].process = None
397 del self.__moduleDict[lpBaseOfDll]
398
434
436 """
437 Notify the load of the main module.
438
439 This is done automatically by the L{Debug} class, you shouldn't need
440 to call it yourself.
441
442 @type event: L{CreateProcessEvent}
443 @param event: Create process event.
444
445 @rtype: bool
446 @return: C{True} to call the user-defined handle, C{False} otherwise.
447 """
448 self.__add_loaded_module(event)
449 return True
450
452 """
453 Notify the load of a new module.
454
455 This is done automatically by the L{Debug} class, you shouldn't need
456 to call it yourself.
457
458 @type event: L{LoadDLLEvent}
459 @param event: Load DLL event.
460
461 @rtype: bool
462 @return: C{True} to call the user-defined handle, C{False} otherwise.
463 """
464 self.__add_loaded_module(event)
465 return True
466
468 """
469 Notify the release of a loaded module.
470
471 This is done automatically by the L{Debug} class, you shouldn't need
472 to call it yourself.
473
474 @type event: L{UnloadDLLEvent}
475 @param event: Unload DLL event.
476
477 @rtype: bool
478 @return: C{True} to call the user-defined handle, C{False} otherwise.
479 """
480 lpBaseOfDll = event.get_module_base()
481
482 if self.__moduleDict.has_key(lpBaseOfDll):
483 self.__del_module(lpBaseOfDll)
484 return True
485
489 """
490 Encapsulates the capability to contain Thread objects.
491
492 @group Instrumentation:
493 start_thread
494
495 @group Threads snapshot:
496 scan_threads,
497 get_thread, get_thread_count, get_thread_ids,
498 has_thread, iter_threads, iter_thread_ids,
499 find_threads_by_name, get_windows,
500 clear_threads, clear_dead_threads, close_thread_handles
501
502 @group Event notifications (private):
503 notify_create_process,
504 notify_create_thread,
505 notify_exit_thread
506 """
507
511
513 """
514 Private method to automatically initialize the snapshot
515 when you try to use it without calling any of the scan_*
516 methods first. You don't need to call this yourself.
517 """
518 if not self.__threadDict:
519 self.scan_threads()
520
522 """
523 @type anObject: L{Thread}, int
524 @param anObject:
525 - C{int}: Global ID of the thread to look for.
526 - C{Thread}: Thread object to look for.
527
528 @rtype: bool
529 @return: C{True} if the snapshot contains
530 a L{Thread} object with the same ID.
531 """
532 if isinstance(anObject, Thread):
533 anObject = anObject.dwThreadId
534 return self.has_thread(anObject)
535
537 """
538 @see: L{iter_threads}
539 @rtype: dictionary-valueiterator
540 @return: Iterator of L{Thread} objects in this snapshot.
541 """
542 return self.iter_threads()
543
545 """
546 @see: L{get_thread_count}
547 @rtype: int
548 @return: Count of L{Thread} objects in this snapshot.
549 """
550 return self.get_thread_count()
551
553 """
554 @type dwThreadId: int
555 @param dwThreadId: Global ID of the thread to look for.
556
557 @rtype: bool
558 @return: C{True} if the snapshot contains a
559 L{Thread} object with the given global ID.
560 """
561 self.__initialize_snapshot()
562 return dwThreadId in self.__threadDict
563
565 """
566 @type dwThreadId: int
567 @param dwThreadId: Global ID of the thread to look for.
568
569 @rtype: L{Thread}
570 @return: Thread object with the given global ID.
571 """
572 self.__initialize_snapshot()
573 if dwThreadId not in self.__threadDict:
574 msg = "Unknown thread ID: %d" % dwThreadId
575 raise KeyError, msg
576 return self.__threadDict[dwThreadId]
577
579 """
580 @see: L{iter_threads}
581 @rtype: dictionary-keyiterator
582 @return: Iterator of global thread IDs in this snapshot.
583 """
584 self.__initialize_snapshot()
585 return self.__threadDict.iterkeys()
586
588 """
589 @see: L{iter_thread_ids}
590 @rtype: dictionary-valueiterator
591 @return: Iterator of L{Thread} objects in this snapshot.
592 """
593 self.__initialize_snapshot()
594 return self.__threadDict.itervalues()
595
597 """
598 @rtype: list( int )
599 @return: List of global thread IDs in this snapshot.
600 """
601 self.__initialize_snapshot()
602 return self.__threadDict.keys()
603
605 """
606 @rtype: int
607 @return: Count of L{Thread} objects in this snapshot.
608 """
609 self.__initialize_snapshot()
610 return len(self.__threadDict)
611
612
613
615 """
616 Find threads by name, using different search methods.
617
618 @type name: str, None
619 @param name: Name to look for. Use C{None} to find nameless threads.
620
621 @type bExactMatch: bool
622 @param bExactMatch: C{True} if the name must be
623 B{exactly} as given, C{False} if the name can be
624 loosely matched.
625
626 This parameter is ignored when C{name} is C{None}.
627
628 @rtype: list( L{Thread} )
629 @return: All threads matching the given name.
630 """
631 found_threads = list()
632
633
634 if name is None:
635 for aThread in self.iter_threads():
636 if aThread.get_name() is None:
637 found_threads.append(aThread)
638
639
640 elif bExactMatch:
641 for aThread in self.iter_threads():
642 if aThread.get_name() == name:
643 found_threads.append(aThread)
644
645
646 else:
647 for aThread in self.iter_threads():
648 t_name = aThread.get_name()
649 if t_name is not None and name in t_name:
650 found_threads.append(aThread)
651
652 return found_threads
653
654
655
656
657
658
660 """
661 @rtype: list of L{Window}
662 @return: Returns a list of windows handled by this process.
663 """
664 window_list = list()
665 for thread in self.iter_threads():
666 window_list.extend( thread.get_windows() )
667 return window_list
668
669
670
671 - def start_thread(self, lpStartAddress, lpParameter=0, bSuspended = False):
672 """
673 Remotely creates a new thread in the process.
674
675 @type lpStartAddress: int
676 @param lpStartAddress: Start address for the new thread.
677
678 @type lpParameter: int
679 @param lpParameter: Optional argument for the new thread.
680
681 @type bSuspended: bool
682 @param bSuspended: C{True} if the new thread should be suspended.
683 In that case use L{Thread.resume} to start execution.
684 """
685 if bSuspended:
686 dwCreationFlags = win32.CREATE_SUSPENDED
687 else:
688 dwCreationFlags = 0
689 hThread, dwThreadId = win32.CreateRemoteThread(self.get_handle(), 0, 0,
690 lpStartAddress, lpParameter, dwCreationFlags)
691 aThread = Thread(dwThreadId, hThread, self)
692 self.__add_thread(aThread)
693 return aThread
694
695
696
697
698
699
700
740
742 """
743 Remove Thread objects from the snapshot
744 referring to threads no longer running.
745 """
746 for tid in self.get_thread_ids():
747 aThread = self.get_thread(tid)
748 if not aThread.is_alive():
749 self.__del_thread(aThread)
750
752 """
753 Clears the threads snapshot.
754 """
755 self.__threadDict = dict()
756
758 """
759 Closes all open handles to threads in the snapshot.
760 """
761 for aThread in self.iter_threads():
762 try:
763 aThread.close_handle()
764 except Exception, e:
765 pass
766
767
768
769
770
772 """
773 Private method to add a thread object to the snapshot.
774
775 @type aThread: L{Thread}
776 @param aThread: Thread object.
777 """
778
779
780
781
782
783
784
785 dwThreadId = aThread.dwThreadId
786
787
788
789 aThread.dwProcessId = self.get_pid()
790 self.__threadDict[dwThreadId] = aThread
791
793 """
794 Private method to remove a thread object from the snapshot.
795
796 @type dwThreadId: int
797 @param dwThreadId: Global thread ID.
798 """
799
800
801
802 self.__threadDict[dwThreadId].hThread = None
803 self.__threadDict[dwThreadId].process = None
804 del self.__threadDict[dwThreadId]
805
823
825 """
826 Notify the creation of the main thread of this process.
827
828 This is done automatically by the L{Debug} class, you shouldn't need
829 to call it yourself.
830
831 @type event: L{CreateProcessEvent}
832 @param event: Create process event.
833
834 @rtype: bool
835 @return: C{True} to call the user-defined handle, C{False} otherwise.
836 """
837 self.__add_created_thread(event)
838 return True
839
841 """
842 Notify the creation of a new thread in this process.
843
844 This is done automatically by the L{Debug} class, you shouldn't need
845 to call it yourself.
846
847 @type event: L{CreateThreadEvent}
848 @param event: Create thread event.
849
850 @rtype: bool
851 @return: C{True} to call the user-defined handle, C{False} otherwise.
852 """
853 self.__add_created_thread(event)
854 return True
855
857 """
858 Notify the termination of a thread.
859
860 This is done automatically by the L{Debug} class, you shouldn't need
861 to call it yourself.
862
863 @type event: L{ExitThreadEvent}
864 @param event: Exit thread event.
865
866 @rtype: bool
867 @return: C{True} to call the user-defined handle, C{False} otherwise.
868 """
869 dwThreadId = event.get_tid()
870
871 if self.__threadDict.has_key(dwThreadId):
872 self.__del_thread(dwThreadId)
873 return True
874
878 """
879 Encapsulates the capability to contain Process objects.
880
881 @group Instrumentation:
882 start_process, argv_to_cmdline, cmdline_to_argv
883
884 @group Processes snapshot:
885 scan, scan_processes, scan_processes_fast,
886 get_process, get_process_count, get_process_ids,
887 has_process, iter_processes, iter_process_ids,
888 find_processes_by_filename, get_pid_from_tid,
889 get_windows,
890 clear, clear_processes, clear_dead_processes,
891 clear_unattached_processes,
892 close_process_handles,
893 close_process_and_thread_handles
894
895 @group Threads snapshots:
896 scan_processes_and_threads,
897 get_thread, get_thread_count, get_thread_ids,
898 has_thread
899
900 @group Modules snapshots:
901 scan_modules, find_modules_by_address,
902 find_modules_by_base, find_modules_by_name,
903 get_module_count
904
905 @group Event notifications (private):
906 notify_create_process,
907 notify_exit_process
908 """
909
913
915 """
916 Private method to automatically initialize the snapshot
917 when you try to use it without calling any of the scan_*
918 methods first. You don't need to call this yourself.
919 """
920 if not self.__processDict:
921
922 try:
923 self.scan_processes()
924 except Exception:
925 self.scan_processes_fast()
926
928 """
929 @type anObject: L{Process}, L{Thread}, int
930 @param anObject:
931 - C{int}: Global ID of the process to look for.
932 - C{int}: Global ID of the thread to look for.
933 - C{Process}: Process object to look for.
934 - C{Thread}: Thread object to look for.
935
936 @rtype: bool
937 @return: C{True} if the snapshot contains
938 a L{Process} or L{Thread} object with the same ID.
939 """
940 if isinstance(anObject, Process):
941 anObject = anObject.dwProcessId
942 if self.has_process(anObject):
943 return True
944 for aProcess in self.iter_processes():
945 if anObject in aProcess:
946 return True
947 return False
948
950 """
951 @see: L{iter_processes}
952 @rtype: dictionary-valueiterator
953 @return: Iterator of L{Process} objects in this snapshot.
954 """
955 return self.iter_processes()
956
958 """
959 @see: L{get_process_count}
960 @rtype: int
961 @return: Count of L{Process} objects in this snapshot.
962 """
963 return self.get_process_count()
964
966 """
967 @type dwProcessId: int
968 @param dwProcessId: Global ID of the process to look for.
969
970 @rtype: bool
971 @return: C{True} if the snapshot contains a
972 L{Process} object with the given global ID.
973 """
974 self.__initialize_snapshot()
975 return dwProcessId in self.__processDict
976
978 """
979 @type dwProcessId: int
980 @param dwProcessId: Global ID of the process to look for.
981
982 @rtype: L{Process}
983 @return: Process object with the given global ID.
984 """
985 self.__initialize_snapshot()
986 if dwProcessId not in self.__processDict:
987 msg = "Unknown process ID %d" % dwProcessId
988 raise KeyError, msg
989 return self.__processDict[dwProcessId]
990
992 """
993 @see: L{iter_processes}
994 @rtype: dictionary-keyiterator
995 @return: Iterator of global process IDs in this snapshot.
996 """
997 self.__initialize_snapshot()
998 return self.__processDict.iterkeys()
999
1001 """
1002 @see: L{iter_process_ids}
1003 @rtype: dictionary-valueiterator
1004 @return: Iterator of L{Process} objects in this snapshot.
1005 """
1006 self.__initialize_snapshot()
1007 return self.__processDict.itervalues()
1008
1010 """
1011 @see: L{iter_process_ids}
1012 @rtype: list( int )
1013 @return: List of global process IDs in this snapshot.
1014 """
1015 self.__initialize_snapshot()
1016 return self.__processDict.keys()
1017
1019 """
1020 @rtype: int
1021 @return: Count of L{Process} objects in this snapshot.
1022 """
1023 self.__initialize_snapshot()
1024 return len(self.__processDict)
1025
1026
1027
1028
1029
1030
1032 """
1033 @rtype: list of L{Window}
1034 @return: Returns a list of windows
1035 handled by all processes in this snapshot.
1036 """
1037 window_list = list()
1038 for process in self.iter_processes():
1039 window_list.extend( process.get_windows() )
1040 return window_list
1041
1086
1087
1088
1089 @staticmethod
1091 """
1092 Convert a list of arguments to a single command line string.
1093
1094 @type argv: list( str )
1095 @param argv: List of argument strings.
1096 The first element is the program to execute.
1097
1098 @rtype: str
1099 @return: Command line string.
1100 """
1101 cmdline = list()
1102 for token in argv:
1103 if not token:
1104 token = '""'
1105 else:
1106 if '"' in token:
1107 token = token.replace('"', '\\"')
1108 if ' ' in token or \
1109 '\t' in token or \
1110 '\n' in token or \
1111 '\r' in token:
1112 token = '"%s"' % token
1113 cmdline.append(token)
1114 return ' '.join(cmdline)
1115
1116 @staticmethod
1118 """
1119 Convert a single command line string to a list of arguments.
1120
1121 @type lpCmdLine: str
1122 @param lpCmdLine: Command line string.
1123 The first token is the program to execute.
1124
1125 @rtype: list( str )
1126 @return: List of argument strings.
1127 """
1128 if not lpCmdLine:
1129 return []
1130 return win32.CommandLineToArgv(lpCmdLine)
1131
1132 - def start_process(self, lpCmdLine,
1133 bConsole = False,
1134 bDebug = False,
1135 bFollow = False,
1136 bSuspended = False,
1137 bInheritHandles = False,
1138 dwParentProcessId = None
1139 ):
1140 """
1141 Starts a new process for instrumenting (or debugging).
1142
1143 @type lpCmdLine: str
1144 @param lpCmdLine: Command line to execute. Can't be an empty string.
1145
1146 @type bConsole: bool
1147 @param bConsole: C{True} if the new process should inherit the console.
1148 Defaults to C{False}.
1149
1150 @type bDebug: bool
1151 @param bDebug: C{True} to attach to the new process.
1152 To debug a process it's best to use the L{Debug} class instead.
1153 Defaults to C{False}.
1154
1155 @type bFollow: bool
1156 @param bFollow: C{True} to automatically attach to the child processes
1157 of the newly created process. Ignored unless C{bDebug} is C{True}.
1158 Defaults to C{False}.
1159
1160 @type bSuspended: bool
1161 @param bSuspended: C{True} if the new process should be suspended.
1162 Defaults to C{False}.
1163
1164 @type bInheritHandles: bool
1165 @param bInheritHandles: C{True} if the new process should inherit it's
1166 parent process' handles. Defaults to C{False}.
1167
1168 @type dwParentProcessId: int or None
1169 @param dwParentProcessId: C{None} if the debugger process should be the
1170 parent process (default), or a process ID to forcefully set as the
1171 debugee's parent (only available for Windows Vista and above).
1172
1173 @rtype: L{Process}
1174 @return: Process object.
1175 """
1176 if not lpCmdLine:
1177 raise ValueError, "Missing command line to execute!"
1178 dwCreationFlags = 0
1179 dwCreationFlags |= win32.CREATE_DEFAULT_ERROR_MODE
1180 dwCreationFlags |= win32.CREATE_BREAKAWAY_FROM_JOB
1181 if not bConsole:
1182 dwCreationFlags |= win32.DETACHED_PROCESS
1183 if bSuspended:
1184 dwCreationFlags |= win32.CREATE_SUSPENDED
1185 if bDebug:
1186 dwCreationFlags |= win32.DEBUG_PROCESS
1187 if bDebug and not bFollow:
1188 dwCreationFlags |= win32.DEBUG_ONLY_THIS_PROCESS
1189 lpStartupInfo = None
1190 if dwParentProcessId is not None:
1191 myPID = win32.GetCurrentProcessId()
1192 if dwParentProcessId != myPID:
1193 if self.has_process(dwParentProcessId):
1194 ParentProcess = self.get_process(dwParentProcessId)
1195 else:
1196 ParentProcess = Process(dwParentProcessId)
1197 ParentProcessHandle = ParentProcess.get_handle()._as_parameter_
1198 AttributeList = (
1199 (
1200 win32.PROC_THREAD_ATTRIBUTE_PARENT_PROCESS,
1201 ParentProcessHandle
1202 ),
1203 )
1204 AttributeList = win32.ProcThreadAttributeList(AttributeList)
1205 StartupInfoEx = win32.STARTUPINFOEX()
1206 StartupInfo = StartupInfoEx.StartupInfo
1207 StartupInfo.cb = win32.sizeof(win32.STARTUPINFOEX)
1208 StartupInfo.lpReserved = 0
1209 StartupInfo.lpDesktop = 0
1210 StartupInfo.lpTitle = 0
1211 StartupInfo.dwFlags = 0
1212 StartupInfo.cbReserved2 = 0
1213 StartupInfo.lpReserved2 = 0
1214 StartupInfoEx.lpAttributeList = AttributeList.value
1215 lpStartupInfo = StartupInfoEx
1216 dwCreationFlags |= win32.EXTENDED_STARTUPINFO_PRESENT
1217 pi = win32.CreateProcess(win32.NULL, lpCmdLine,
1218 bInheritHandles = bInheritHandles,
1219 dwCreationFlags = dwCreationFlags,
1220 lpStartupInfo = lpStartupInfo)
1221 aProcess = Process(pi.dwProcessId, pi.hProcess)
1222 aThread = Thread (pi.dwThreadId, pi.hThread)
1223 aProcess._ThreadContainer__add_thread(aThread)
1224 self.__add_process(aProcess)
1225 return aProcess
1226
1227
1228
1229
1230
1242
1321
1322
1324 """
1325 Populates the snapshot with loaded modules.
1326 """
1327
1328 for aProcess in self.__processDict.itervalues():
1329 aProcess.scan_modules()
1330
1366
1368 """
1369 Populates the snapshot with running processes.
1370 Only the PID is retrieved for each process.
1371
1372 Dead processes are removed.
1373 Threads and modules of living processes are ignored.
1374
1375 @note: This method may be faster for scanning, but some information
1376 may be missing, outdated or slower to obtain. This could be a good
1377 tradeoff under some circumstances.
1378 """
1379
1380
1381 new_pids = set( win32.EnumProcesses() )
1382
1383 old_pids = set( self.__processDict.keys() )
1384
1385
1386 our_pid = win32.GetCurrentProcessId()
1387 if our_pid in new_pids:
1388 new_pids.remove(our_pid)
1389 if our_pid in old_pids:
1390 old_pids.remove(our_pid)
1391
1392
1393 for pid in new_pids.difference(old_pids):
1394 self.__add_process( Process(pid) )
1395
1396
1397 for pid in old_pids.difference(new_pids):
1398 self.__del_process(pid)
1399
1401 """
1402 Removes Process objects from the snapshot
1403 referring to processes no longer running.
1404 """
1405 for pid in self.get_process_ids():
1406 aProcess = self.get_process(pid)
1407 if not aProcess.is_alive():
1408 self.__del_process(aProcess)
1409
1411 """
1412 Removes Process objects from the snapshot
1413 referring to processes not being debugged.
1414 """
1415 for pid in self.get_process_ids():
1416 aProcess = self.get_process(pid)
1417 if not aProcess.is_being_debugged():
1418 self.__del_process(aProcess)
1419
1430
1442
1444 """
1445 Removes all L{Process}, L{Thread} and L{Module} objects in this snapshot.
1446 """
1447 self.__processDict = dict()
1448
1450 """
1451 Clears this snapshot.
1452
1453 @see: L{clear_processes}
1454 """
1455 self.clear_processes()
1456
1457
1458
1459
1460
1466
1473
1479
1485
1486 has_thread.__doc__ = ThreadContainer.has_thread.__doc__
1487 get_thread.__doc__ = ThreadContainer.get_thread.__doc__
1488 get_thread_ids.__doc__ = ThreadContainer.get_thread_ids.__doc__
1489 get_thread_count.__doc__ = ThreadContainer.get_thread_count.__doc__
1490
1491
1492
1493
1494
1500
1501 get_module_count.__doc__ = ModuleContainer.get_module_count.__doc__
1502
1503
1504
1506 """
1507 @rtype: list( L{Module}... )
1508 @return: List of Module objects with the given base address.
1509 """
1510 found = list()
1511 for aProcess in self.iter_processes():
1512 if aProcess.has_module(lpBaseOfDll):
1513 aModule = aProcess.get_module(lpBaseOfDll)
1514 found.append( (aProcess, aModule) )
1515 return found
1516
1518 """
1519 @rtype: list( L{Module}... )
1520 @return: List of Module objects found.
1521 """
1522 found = list()
1523 for aProcess in self.iter_processes():
1524 aModule = aProcess.get_module_by_name(fileName)
1525 if aModule is not None:
1526 found.append( (aProcess, aModule) )
1527 return found
1528
1530 """
1531 @rtype: list( L{Module}... )
1532 @return: List of Module objects that best match the given address.
1533 """
1534 found = list()
1535 for aProcess in self.iter_processes():
1536 aModule = aProcess.get_module_at_address(address)
1537 if aModule is not None:
1538 found.append( (aProcess, aModule) )
1539 return found
1540
1542 """
1543 Internally used by L{find_processes_by_filename}.
1544 """
1545 found = list()
1546 filename = filename.lower()
1547 if PathOperations.path_is_absolute(filename):
1548 for aProcess in self.iter_processes():
1549 imagename = aProcess.get_filename()
1550 if imagename and imagename.lower() == filename:
1551 found.append( (aProcess, imagename) )
1552 else:
1553 for aProcess in self.iter_processes():
1554 imagename = aProcess.get_filename()
1555 if imagename:
1556 imagename = PathOperations.pathname_to_filename(imagename)
1557 if imagename.lower() == filename:
1558 found.append( (aProcess, imagename) )
1559 return found
1560
1562 """
1563 @type fileName: str
1564 @param fileName: Filename to search for.
1565 If it's a full pathname, the match must be exact.
1566 If it's a base filename only, the file part is matched,
1567 regardless of the directory where it's located.
1568
1569 @note: If the process is not found and the file extension is not
1570 given, this method will search again assuming a default
1571 extension (.exe).
1572
1573 @rtype: list of tuple( L{Process}, str )
1574 @return: List of processes matching the given main module filename.
1575 Each tuple contains a Process object and it's filename.
1576 """
1577 found = self.__find_processes_by_filename(fileName)
1578 if not found:
1579 fn, ext = PathOperations.split_extension(fileName)
1580 if not ext:
1581 fileName = '%s.exe' % fn
1582 found = self.__find_processes_by_filename(fileName)
1583 return found
1584
1585
1586
1587
1588
1590 """
1591 Private method to add a process object to the snapshot.
1592
1593 @type aProcess: L{Process}
1594 @param aProcess: Process object.
1595 """
1596
1597
1598
1599
1600
1601
1602
1603 dwProcessId = aProcess.dwProcessId
1604
1605
1606
1607 self.__processDict[dwProcessId] = aProcess
1608
1610 """
1611 Private method to remove a process object from the snapshot.
1612
1613 @type dwProcessId: int
1614 @param dwProcessId: Global process ID.
1615 """
1616
1617
1618
1619 self.__processDict[dwProcessId].hProcess = None
1620 self.__processDict[dwProcessId].clear()
1621 del self.__processDict[dwProcessId]
1622
1623
1654
1656 """
1657 Notify the termination of a process.
1658
1659 This is done automatically by the L{Debug} class, you shouldn't need
1660 to call it yourself.
1661
1662 @type event: L{ExitProcessEvent}
1663 @param event: Exit process event.
1664
1665 @rtype: bool
1666 @return: C{True} to call the user-defined handle, C{False} otherwise.
1667 """
1668 dwProcessId = event.get_pid()
1669
1670 if self.__processDict.has_key(dwProcessId):
1671 self.__del_process(dwProcessId)
1672 return True
1673
1682 """
1683 Encapsulates the capabilities to manipulate the memory of a process.
1684
1685 @group Instrumentation:
1686 malloc, free, mprotect, mquery,
1687 take_memory_snapshot, generate_memory_snapshot, restore_memory_snapshot
1688
1689 @group Memory mapping:
1690 get_memory_map, get_mapped_filenames,
1691 is_pointer, is_address_valid, is_address_free, is_address_reserved,
1692 is_address_commited, is_address_guard, is_address_readable,
1693 is_address_writeable, is_address_copy_on_write, is_address_executable,
1694 is_address_executable_and_writeable,
1695 is_buffer,
1696 is_buffer_readable, is_buffer_writeable, is_buffer_executable,
1697 is_buffer_executable_and_writeable
1698
1699 @group Memory read:
1700 read, read_char, read_uint, read_pointer, read_string, read_structure,
1701 peek, peek_char, peek_uint, peek_pointer, peek_string
1702
1703 @group Memory write:
1704 write, write_char, write_uint, write_pointer,
1705 poke, poke_char, poke_uint, poke_pointer
1706 """
1707
1708 - def read(self, lpBaseAddress, nSize):
1709 """
1710 Reads from the memory of the process.
1711
1712 @see: L{peek}
1713
1714 @type lpBaseAddress: int
1715 @param lpBaseAddress: Memory address to begin reading.
1716
1717 @type nSize: int
1718 @param nSize: Number of bytes to read.
1719
1720 @rtype: str
1721 @return: Bytes read from the process memory.
1722
1723 @raise WindowsError: On error an exception is raised.
1724 """
1725
1726
1727 if not self.is_buffer(lpBaseAddress, nSize):
1728 raise ctypes.WinError(win32.ERROR_INVALID_ADDRESS)
1729 data = win32.ReadProcessMemory(self.get_handle(), lpBaseAddress, nSize)
1730 if len(data) != nSize:
1731 raise ctypes.WinError()
1732 return data
1733
1734 - def write(self, lpBaseAddress, lpBuffer):
1735 """
1736 Writes to the memory of the process.
1737
1738 @note: Page permissions may be changed temporarily while writing.
1739
1740 @see: L{poke}
1741
1742 @type lpBaseAddress: int
1743 @param lpBaseAddress: Memory address to begin writing.
1744
1745 @type lpBuffer: str
1746 @param lpBuffer: Bytes to write.
1747
1748 @raise WindowsError: On error an exception is raised.
1749 """
1750 r = self.poke(lpBaseAddress, lpBuffer)
1751 if r != len(lpBuffer):
1752 raise ctypes.WinError()
1753
1755 """
1756 Reads a single unsigned integer from the memory of the process.
1757
1758 @see: L{peek}
1759
1760 @type lpBaseAddress: int
1761 @param lpBaseAddress: Memory address to begin reading.
1762
1763 @rtype: int
1764 @return: Integer value read from the process memory.
1765
1766 @raise WindowsError: On error an exception is raised.
1767 """
1768 packedDword = self.read(lpBaseAddress, 4)
1769 if len(packedDword) != 4:
1770 raise ctypes.WinError()
1771 unpackedDword = struct.unpack('<L', packedDword)[0]
1772 return unpackedDword
1773
1774 - def write_uint(self, lpBaseAddress, unpackedDword):
1775 """
1776 Writes a single unsigned integer to the memory of the process.
1777
1778 @note: Page permissions may be changed temporarily while writing.
1779
1780 @see: L{poke_uint}
1781
1782 @type lpBaseAddress: int
1783 @param lpBaseAddress: Memory address to begin writing.
1784
1785 @type unpackedDword: int, long
1786 @param unpackedDword: Value to write.
1787
1788 @raise WindowsError: On error an exception is raised.
1789 """
1790 packedDword = struct.pack('<L', unpackedDword)
1791 self.write(lpBaseAddress, packedDword)
1792
1794 """
1795 Reads a single pointer value from the memory of the process.
1796
1797 @see: L{peek_pointer}
1798
1799 @type lpBaseAddress: int
1800 @param lpBaseAddress: Memory address to begin reading.
1801
1802 @rtype: int
1803 @return: Pointer value read from the process memory.
1804
1805 @raise WindowsError: On error an exception is raised.
1806 """
1807 lpvoidLength = win32.sizeof(win32.LPVOID)
1808 packedValue = self.read(lpBaseAddress, lpvoidLength)
1809 if lpvoidLength == 4:
1810 lpvoidFmt = '<L'
1811 else:
1812 lpvoidFmt = '<Q'
1813 unpackedValue = struct.unpack(lpvoidFmt, packedValue)[0]
1814 return unpackedValue
1815
1817 """
1818 Writes a single pointer value to the memory of the process.
1819
1820 @note: Page permissions may be changed temporarily while writing.
1821
1822 @see: L{poke_pointer}
1823
1824 @type lpBaseAddress: int
1825 @param lpBaseAddress: Memory address to begin writing.
1826
1827 @type unpackedValue: int, long
1828 @param unpackedValue: Value to write.
1829
1830 @raise WindowsError: On error an exception is raised.
1831 """
1832 lpvoidLength = win32.sizeof(win32.LPVOID)
1833 if lpvoidLength == 4:
1834 lpvoidFmt = '<L'
1835 else:
1836 lpvoidFmt = '<Q'
1837 packedValue = struct.pack(lpvoidFmt, unpackedValue)
1838 self.write(lpBaseAddress, packedValue)
1839
1841 """
1842 Reads a single character to the memory of the process.
1843
1844 @see: L{write_char}
1845
1846 @type lpBaseAddress: int
1847 @param lpBaseAddress: Memory address to begin writing.
1848
1849 @rtype: int
1850 @return: Character value read from the process memory.
1851
1852 @raise WindowsError: On error an exception is raised.
1853 """
1854 return ord( self.read(lpBaseAddress, 1) )
1855
1857 """
1858 Writes a single character to the memory of the process.
1859
1860 @note: Page permissions may be changed temporarily while writing.
1861
1862 @see: L{write_char}
1863
1864 @type lpBaseAddress: int
1865 @param lpBaseAddress: Memory address to begin writing.
1866
1867 @type char: int
1868 @param char: Character to write.
1869
1870 @raise WindowsError: On error an exception is raised.
1871 """
1872 self.write(lpBaseAddress, chr(char))
1873
1875 """
1876 Reads a ctypes structure from the memory of the process.
1877
1878 @see: L{read}
1879
1880 @type lpBaseAddress: int
1881 @param lpBaseAddress: Memory address to begin reading.
1882
1883 @type stype: class ctypes.Structure or a subclass.
1884 @param stype: Structure definition.
1885
1886 @rtype: int
1887 @return: Structure instance filled in with data
1888 read from the process memory.
1889
1890 @raise WindowsError: On error an exception is raised.
1891 """
1892 if type(lpBaseAddress) not in (type(0), type(0L)):
1893 lpBaseAddress = ctypes.cast(lpBaseAddress, ctypes.c_void_p)
1894 data = self.read(lpBaseAddress, ctypes.sizeof(stype))
1895 buff = ctypes.create_string_buffer(data)
1896 ptr = ctypes.cast(ctypes.pointer(buff), ctypes.POINTER(stype))
1897 return ptr.contents
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925 - def read_string(self, lpBaseAddress, nChars, fUnicode = False):
1926 """
1927 Reads an ASCII or Unicode string
1928 from the address space of the process.
1929
1930 @see: L{read}
1931
1932 @type lpBaseAddress: int
1933 @param lpBaseAddress: Memory address to begin reading.
1934
1935 @type nChars: int
1936 @param nChars: String length to read, in characters.
1937 Remember that Unicode strings have two byte characters.
1938
1939 @type fUnicode: bool
1940 @param fUnicode: C{True} is the string is expected to be Unicode,
1941 C{False} if it's expected to be ANSI.
1942
1943 @rtype: str, unicode
1944 @return: String read from the process memory space.
1945
1946 @raise WindowsError: On error an exception is raised.
1947 """
1948 if fUnicode:
1949 nChars = nChars * 2
1950 szString = self.read(lpBaseAddress, nChars)
1951 if fUnicode:
1952 szString = unicode(szString, 'U16', 'ignore')
1953 return szString
1954
1955
1956
1957 - def peek(self, lpBaseAddress, nSize):
1958 """
1959 Reads the memory of the process.
1960
1961 @see: L{read}
1962
1963 @type lpBaseAddress: int
1964 @param lpBaseAddress: Memory address to begin reading.
1965
1966 @type nSize: int
1967 @param nSize: Number of bytes to read.
1968
1969 @rtype: str
1970 @return: Bytes read from the process memory.
1971 Returns an empty string on error.
1972 """
1973
1974
1975
1976
1977 data = ''
1978 if nSize > 0:
1979 try:
1980 for mbi in self.get_memory_map(lpBaseAddress,
1981 lpBaseAddress + nSize):
1982 if not mbi.is_readable():
1983 nSize = mbi.BaseAddress - lpBaseAddress
1984 break
1985 if nSize > 0:
1986 data = win32.ReadProcessMemory(self.get_handle(),
1987 lpBaseAddress, nSize)
1988 except WindowsError:
1989 pass
1990 return data
1991
1992 - def poke(self, lpBaseAddress, lpBuffer):
1993 """
1994 Writes to the memory of the process.
1995
1996 @note: Page permissions may be changed temporarily while writing.
1997
1998 @see: L{write}
1999
2000 @type lpBaseAddress: int
2001 @param lpBaseAddress: Memory address to begin writing.
2002
2003 @type lpBuffer: str
2004 @param lpBuffer: Bytes to write.
2005
2006 @rtype: int
2007 @return: Number of bytes written.
2008 May be less than the number of bytes to write.
2009 """
2010 hProcess = self.get_handle()
2011 mbi = self.mquery(lpBaseAddress)
2012 if not mbi.has_content():
2013 raise ctypes.WinError(win32.ERROR_INVALID_ADDRESS)
2014 if mbi.is_image() or mbi.is_mapped():
2015 prot = win32.PAGE_WRITECOPY
2016 elif mbi.is_writeable():
2017 prot = None
2018 elif mbi.is_executable():
2019 prot = win32.PAGE_EXECUTE_READWRITE
2020 else:
2021 prot = win32.PAGE_READWRITE
2022 if prot is not None:
2023 self.mprotect(lpBaseAddress, len(lpBuffer), prot)
2024 try:
2025 r = win32.WriteProcessMemory(hProcess, lpBaseAddress, lpBuffer)
2026 finally:
2027 if prot is not None:
2028 self.mprotect(lpBaseAddress, len(lpBuffer), mbi.Protect)
2029 return r
2030
2032 """
2033 Reads a single unsigned integer from the memory of the process.
2034
2035 @see: L{read_uint}
2036
2037 @type lpBaseAddress: int
2038 @param lpBaseAddress: Memory address to begin reading.
2039
2040 @rtype: int
2041 @return: Integer value read from the process memory.
2042 Returns zero on error.
2043 """
2044 dwordLength = win32.sizeof(win32.UINT)
2045 packedDword = self.peek(lpBaseAddress, dwordLength)
2046 if len(packedDword) < dwordLength:
2047 packedDword += '\x00' * (dwordLength - len(packedDword))
2048 unpackedDword = struct.unpack('<L', packedDword)[0]
2049 return unpackedDword
2050
2051 - def poke_uint(self, lpBaseAddress, unpackedDword):
2052 """
2053 Writes a single unsigned integer to the memory of the process.
2054
2055 @note: Page permissions may be changed temporarily while writing.
2056
2057 @see: L{write_uint}
2058
2059 @type lpBaseAddress: int
2060 @param lpBaseAddress: Memory address to begin writing.
2061
2062 @type unpackedDword: int, long
2063 @param unpackedDword: Value to write.
2064
2065 @rtype: int
2066 @return: Number of bytes written.
2067 May be less than the number of bytes to write.
2068 """
2069 packedDword = struct.pack('<L', unpackedDword)
2070 dwBytesWritten = self.poke(lpBaseAddress, packedDword)
2071 return dwBytesWritten
2072
2074 """
2075 Reads a single pointer value from the memory of the process.
2076
2077 @see: L{read_pointer}
2078
2079 @type lpBaseAddress: int
2080 @param lpBaseAddress: Memory address to begin reading.
2081
2082 @rtype: int
2083 @return: Pointer value read from the process memory.
2084 Returns zero on error.
2085 """
2086 lpvoidLength = win32.sizeof(win32.LPVOID)
2087 packedValue = self.read(lpBaseAddress, lpvoidLength)
2088 if len(packedValue) < lpvoidLength:
2089 packedValue += '\x00' * (lpvoidLength - len(packedValue))
2090 if lpvoidLength == 4:
2091 lpvoidFmt = '<L'
2092 else:
2093 lpvoidFmt = '<Q'
2094 unpackedValue = struct.unpack(lpvoidFmt, packedValue)[0]
2095 return unpackedValue
2096
2098 """
2099 Writes a single pointer value to the memory of the process.
2100
2101 @note: Page permissions may be changed temporarily while writing.
2102
2103 @see: L{write_pointer}
2104
2105 @type lpBaseAddress: int
2106 @param lpBaseAddress: Memory address to begin writing.
2107
2108 @type unpackedValue: int, long
2109 @param unpackedValue: Value to write.
2110
2111 @rtype: int
2112 @return: Number of bytes written.
2113 May be less than the number of bytes to write.
2114 """
2115 lpvoidLength = win32.sizeof(win32.LPVOID)
2116 if lpvoidLength == 4:
2117 lpvoidFmt = '<L'
2118 else:
2119 lpvoidFmt = '<Q'
2120 packedValue = struct.pack(lpvoidFmt, unpackedValue)
2121 dwBytesWritten = self.poke(lpBaseAddress, packedValue)
2122 return dwBytesWritten
2123
2125 """
2126 Reads a single character from the memory of the process.
2127
2128 @see: L{read_char}
2129
2130 @type lpBaseAddress: int
2131 @param lpBaseAddress: Memory address to begin reading.
2132
2133 @rtype: int
2134 @return: Character read from the process memory.
2135 Returns zero on error.
2136 """
2137 char = self.peek(lpBaseAddress, 1)
2138 if char:
2139 return ord(char)
2140 return 0
2141
2143 """
2144 Writes a single character to the memory of the process.
2145
2146 @note: Page permissions may be changed temporarily while writing.
2147
2148 @see: L{write_char}
2149
2150 @type lpBaseAddress: int
2151 @param lpBaseAddress: Memory address to begin writing.
2152
2153 @type char: str
2154 @param char: Character to write.
2155
2156 @rtype: int
2157 @return: Number of bytes written.
2158 May be less than the number of bytes to write.
2159 """
2160 return self.poke(lpBaseAddress, chr(char))
2161
2162 - def peek_string(self, lpBaseAddress, fUnicode = False, dwMaxSize = 0x1000):
2163 """
2164 Tries to read an ASCII or Unicode string
2165 from the address space of the process.
2166
2167 @see: L{peek}
2168
2169 @type lpBaseAddress: int
2170 @param lpBaseAddress: Memory address to begin reading.
2171
2172 @type fUnicode: bool
2173 @param fUnicode: C{True} is the string is expected to be Unicode,
2174 C{False} if it's expected to be ANSI.
2175
2176 @type dwMaxSize: int
2177 @param dwMaxSize: Maximum allowed string length to read, in bytes.
2178
2179 @rtype: str, unicode
2180 @return: String read from the process memory space.
2181 It B{doesn't} include the terminating null character.
2182 Returns an empty string on failure.
2183 """
2184
2185
2186 if not lpBaseAddress or dwMaxSize == 0:
2187 if fUnicode:
2188 return u''
2189 return ''
2190 if not dwMaxSize:
2191 dwMaxSize = 0x1000
2192
2193
2194 szString = self.peek(lpBaseAddress, dwMaxSize)
2195
2196
2197 if fUnicode:
2198
2199
2200 szString = unicode(szString, 'U16', 'replace')
2201
2202
2203
2204
2205
2206
2207
2208
2209 szString = szString[ : szString.find(u'\0') ]
2210
2211
2212 else:
2213
2214
2215 szString = szString[ : szString.find('\0') ]
2216
2217
2218 return szString
2219
2220
2221
2222 - def malloc(self, dwSize, lpAddress = None):
2223 """
2224 Allocates memory into the address space of the process.
2225
2226 @see: L{free}
2227
2228 @type dwSize: int
2229 @param dwSize: Number of bytes to allocate.
2230
2231 @type lpAddress: int
2232 @param lpAddress: (Optional)
2233 Desired address for the newly allocated memory.
2234 This is only a hint, the memory could still be allocated somewhere
2235 else.
2236
2237 @rtype: int
2238 @return: Address of the newly allocated memory.
2239
2240 @raise WindowsError: On error an exception is raised.
2241 """
2242 return win32.VirtualAllocEx(self.get_handle(), lpAddress, dwSize)
2243
2244 - def mprotect(self, lpAddress, dwSize, flNewProtect):
2245 """
2246 Set memory protection in the address space of the process.
2247
2248 @see: U{http://msdn.microsoft.com/en-us/library/aa366899.aspx}
2249
2250 @type lpAddress: int
2251 @param lpAddress: Address of memory to protect.
2252
2253 @type dwSize: int
2254 @param dwSize: Number of bytes to protect.
2255
2256 @type flNewProtect: int
2257 @param flNewProtect: New protect flags.
2258
2259 @rtype: int
2260 @return: Old protect flags.
2261
2262 @raise WindowsError: On error an exception is raised.
2263 """
2264 return win32.VirtualProtectEx(self.get_handle(), lpAddress, dwSize,
2265 flNewProtect)
2266
2267 - def mquery(self, lpAddress):
2268 """
2269 Query memory information from the address space of the process.
2270 Returns a L{win32.MemoryBasicInformation} object.
2271
2272 @see: U{http://msdn.microsoft.com/en-us/library/aa366907(VS.85).aspx}
2273
2274 @type lpAddress: int
2275 @param lpAddress: Address of memory to query.
2276
2277 @rtype: L{win32.MemoryBasicInformation}
2278 @return: Memory region information.
2279
2280 @raise WindowsError: On error an exception is raised.
2281 """
2282 return win32.VirtualQueryEx(self.get_handle(), lpAddress)
2283
2284 - def free(self, lpAddress, dwSize = 0):
2285 """
2286 Frees memory from the address space of the process.
2287
2288 @see: L{malloc}
2289
2290 @type lpAddress: int
2291 @param lpAddress: Address of memory to free.
2292
2293 @type dwSize: int
2294 @param dwSize: (Optional) Number of bytes to free.
2295
2296 @raise WindowsError: On error an exception is raised.
2297 """
2298 win32.VirtualFreeEx(self.get_handle(), lpAddress, dwSize)
2299
2300
2301
2303 """
2304 Determines if an address is a valid code or data pointer.
2305
2306 That is, the address must be valid and must point to code or data in
2307 the target process.
2308
2309 @type address: int
2310 @param address: Memory address to query.
2311
2312 @rtype: bool
2313 @return: C{True} if the address is a valid code or data pointer.
2314
2315 @raise WindowsError: An exception is raised on error.
2316 """
2317 try:
2318 mbi = self.mquery(address)
2319 except WindowsError, e:
2320 if win32.winerror(e) == win32.ERROR_INVALID_PARAMETER:
2321 return False
2322 raise
2323 return mbi.has_content()
2324
2326 """
2327 Determines if an address is a valid user mode address.
2328
2329 @type address: int
2330 @param address: Memory address to query.
2331
2332 @rtype: bool
2333 @return: C{True} if the address is a valid user mode address.
2334
2335 @raise WindowsError: An exception is raised on error.
2336 """
2337 try:
2338 mbi = self.mquery(address)
2339 except WindowsError, e:
2340 if win32.winerror(e) == win32.ERROR_INVALID_PARAMETER:
2341 return False
2342 raise
2343 return True
2344
2346 """
2347 Determines if an address belongs to a free page.
2348
2349 @note: Returns always C{False} for kernel mode addresses.
2350
2351 @type address: int
2352 @param address: Memory address to query.
2353
2354 @rtype: bool
2355 @return: C{True} if the address belongs to a free page.
2356
2357 @raise WindowsError: An exception is raised on error.
2358 """
2359 try:
2360 mbi = self.mquery(address)
2361 except WindowsError, e:
2362 if win32.winerror(e) == win32.ERROR_INVALID_PARAMETER:
2363 return False
2364 raise
2365 return mbi.is_free()
2366
2368 """
2369 Determines if an address belongs to a reserved page.
2370
2371 @note: Returns always C{False} for kernel mode addresses.
2372
2373 @type address: int
2374 @param address: Memory address to query.
2375
2376 @rtype: bool
2377 @return: C{True} if the address belongs to a reserved page.
2378
2379 @raise WindowsError: An exception is raised on error.
2380 """
2381 try:
2382 mbi = self.mquery(address)
2383 except WindowsError, e:
2384 if win32.winerror(e) == win32.ERROR_INVALID_PARAMETER:
2385 return False
2386 raise
2387 return mbi.is_reserved()
2388
2390 """
2391 Determines if an address belongs to a commited page.
2392
2393 @note: Returns always C{False} for kernel mode addresses.
2394
2395 @type address: int
2396 @param address: Memory address to query.
2397
2398 @rtype: bool
2399 @return: C{True} if the address belongs to a commited page.
2400
2401 @raise WindowsError: An exception is raised on error.
2402 """
2403 try:
2404 mbi = self.mquery(address)
2405 except WindowsError, e:
2406 if win32.winerror(e) == win32.ERROR_INVALID_PARAMETER:
2407 return False
2408 raise
2409 return mbi.is_commited()
2410
2412 """
2413 Determines if an address belongs to a guard page.
2414
2415 @note: Returns always C{False} for kernel mode addresses.
2416
2417 @type address: int
2418 @param address: Memory address to query.
2419
2420 @rtype: bool
2421 @return: C{True} if the address belongs to a guard page.
2422
2423 @raise WindowsError: An exception is raised on error.
2424 """
2425 try:
2426 mbi = self.mquery(address)
2427 except WindowsError, e:
2428 if win32.winerror(e) == win32.ERROR_INVALID_PARAMETER:
2429 return False
2430 raise
2431 return mbi.is_guard()
2432
2434 """
2435 Determines if an address belongs to a commited and readable page.
2436 The page may or may not have additional permissions.
2437
2438 @note: Returns always C{False} for kernel mode addresses.
2439
2440 @type address: int
2441 @param address: Memory address to query.
2442
2443 @rtype: bool
2444 @return:
2445 C{True} if the address belongs to a commited and readable page.
2446
2447 @raise WindowsError: An exception is raised on error.
2448 """
2449 try:
2450 mbi = self.mquery(address)
2451 except WindowsError, e:
2452 if win32.winerror(e) == win32.ERROR_INVALID_PARAMETER:
2453 return False
2454 raise
2455 return mbi.is_readable()
2456
2458 """
2459 Determines if an address belongs to a commited and writeable page.
2460 The page may or may not have additional permissions.
2461
2462 @note: Returns always C{False} for kernel mode addresses.
2463
2464 @type address: int
2465 @param address: Memory address to query.
2466
2467 @rtype: bool
2468 @return:
2469 C{True} if the address belongs to a commited and writeable page.
2470
2471 @raise WindowsError: An exception is raised on error.
2472 """
2473 try:
2474 mbi = self.mquery(address)
2475 except WindowsError, e:
2476 if win32.winerror(e) == win32.ERROR_INVALID_PARAMETER:
2477 return False
2478 raise
2479 return mbi.is_writeable()
2480
2482 """
2483 Determines if an address belongs to a commited, copy-on-write page.
2484 The page may or may not have additional permissions.
2485
2486 @note: Returns always C{False} for kernel mode addresses.
2487
2488 @type address: int
2489 @param address: Memory address to query.
2490
2491 @rtype: bool
2492 @return:
2493 C{True} if the address belongs to a commited, copy-on-write page.
2494
2495 @raise WindowsError: An exception is raised on error.
2496 """
2497 try:
2498 mbi = self.mquery(address)
2499 except WindowsError, e:
2500 if win32.winerror(e) == win32.ERROR_INVALID_PARAMETER:
2501 return False
2502 raise
2503 return mbi.is_copy_on_write()
2504
2506 """
2507 Determines if an address belongs to a commited and executable page.
2508 The page may or may not have additional permissions.
2509
2510 @note: Returns always C{False} for kernel mode addresses.
2511
2512 @type address: int
2513 @param address: Memory address to query.
2514
2515 @rtype: bool
2516 @return:
2517 C{True} if the address belongs to a commited and executable page.
2518
2519 @raise WindowsError: An exception is raised on error.
2520 """
2521 try:
2522 mbi = self.mquery(address)
2523 except WindowsError, e:
2524 if win32.winerror(e) == win32.ERROR_INVALID_PARAMETER:
2525 return False
2526 raise
2527 return mbi.is_executable()
2528
2530 """
2531 Determines if an address belongs to a commited, writeable and
2532 executable page. The page may or may not have additional permissions.
2533
2534 Looking for writeable and executable pages is important when
2535 exploiting a software vulnerability.
2536
2537 @note: Returns always C{False} for kernel mode addresses.
2538
2539 @type address: int
2540 @param address: Memory address to query.
2541
2542 @rtype: bool
2543 @return:
2544 C{True} if the address belongs to a commited, writeable and
2545 executable page.
2546
2547 @raise WindowsError: An exception is raised on error.
2548 """
2549 try:
2550 mbi = self.mquery(address)
2551 except WindowsError, e:
2552 if win32.winerror(e) == win32.ERROR_INVALID_PARAMETER:
2553 return False
2554 raise
2555 return mbi.is_executable_and_writeable()
2556
2558 """
2559 Determines if the given memory area is a valid code or data buffer.
2560
2561 @note: Returns always C{False} for kernel mode addresses.
2562
2563 @see: L{mquery}
2564
2565 @type address: int
2566 @param address: Memory address.
2567
2568 @type size: int
2569 @param size: Number of bytes. Must be greater than zero.
2570
2571 @rtype: bool
2572 @return: C{True} if the memory area is a valid code or data buffer,
2573 C{False} otherwise.
2574
2575 @raise ValueError: The size argument must be greater than zero.
2576 @raise WindowsError: On error an exception is raised.
2577 """
2578 if size <= 0:
2579 raise ValueError, "the size argument must be greater than zero"
2580 while size > 0:
2581 try:
2582 mbi = self.mquery(address)
2583 except WindowsError, e:
2584 if win32.winerror(e) == win32.ERROR_INVALID_PARAMETER:
2585 return False
2586 raise
2587 if not mbi.has_content():
2588 return False
2589 size = size - mbi.RegionSize
2590 return True
2591
2593 """
2594 Determines if the given memory area is readable.
2595
2596 @note: Returns always C{False} for kernel mode addresses.
2597
2598 @see: L{mquery}
2599
2600 @type address: int
2601 @param address: Memory address.
2602
2603 @type size: int
2604 @param size: Number of bytes. Must be greater than zero.
2605
2606 @rtype: bool
2607 @return: C{True} if the memory area is readable, C{False} otherwise.
2608
2609 @raise ValueError: The size argument must be greater than zero.
2610 @raise WindowsError: On error an exception is raised.
2611 """
2612 if size <= 0:
2613 raise ValueError, "the size argument must be greater than zero"
2614 while size > 0:
2615 try:
2616 mbi = self.mquery(address)
2617 except WindowsError, e:
2618 if win32.winerror(e) == win32.ERROR_INVALID_PARAMETER:
2619 return False
2620 raise
2621 if not mbi.is_readable():
2622 return False
2623 size = size - mbi.RegionSize
2624 return True
2625
2627 """
2628 Determines if the given memory area is writeable.
2629
2630 @note: Returns always C{False} for kernel mode addresses.
2631
2632 @see: L{mquery}
2633
2634 @type address: int
2635 @param address: Memory address.
2636
2637 @type size: int
2638 @param size: Number of bytes. Must be greater than zero.
2639
2640 @rtype: bool
2641 @return: C{True} if the memory area is writeable, C{False} otherwise.
2642
2643 @raise ValueError: The size argument must be greater than zero.
2644 @raise WindowsError: On error an exception is raised.
2645 """
2646 if size <= 0:
2647 raise ValueError, "the size argument must be greater than zero"
2648 while size > 0:
2649 try:
2650 mbi = self.mquery(address)
2651 except WindowsError, e:
2652 if win32.winerror(e) == win32.ERROR_INVALID_PARAMETER:
2653 return False
2654 raise
2655 if not mbi.is_writeable():
2656 return False
2657 size = size - mbi.RegionSize
2658 return True
2659
2661 """
2662 Determines if the given memory area is marked as copy-on-write.
2663
2664 @note: Returns always C{False} for kernel mode addresses.
2665
2666 @see: L{mquery}
2667
2668 @type address: int
2669 @param address: Memory address.
2670
2671 @type size: int
2672 @param size: Number of bytes. Must be greater than zero.
2673
2674 @rtype: bool
2675 @return: C{True} if the memory area is marked as copy-on-write,
2676 C{False} otherwise.
2677
2678 @raise ValueError: The size argument must be greater than zero.
2679 @raise WindowsError: On error an exception is raised.
2680 """
2681 if size <= 0:
2682 raise ValueError, "the size argument must be greater than zero"
2683 while size > 0:
2684 try:
2685 mbi = self.mquery(address)
2686 except WindowsError, e:
2687 if win32.winerror(e) == win32.ERROR_INVALID_PARAMETER:
2688 return False
2689 raise
2690 if not mbi.is_copy_on_write():
2691 return False
2692 size = size - mbi.RegionSize
2693 return True
2694
2696 """
2697 Determines if the given memory area is executable.
2698
2699 @note: Returns always C{False} for kernel mode addresses.
2700
2701 @see: L{mquery}
2702
2703 @type address: int
2704 @param address: Memory address.
2705
2706 @type size: int
2707 @param size: Number of bytes. Must be greater than zero.
2708
2709 @rtype: bool
2710 @return: C{True} if the memory area is executable, C{False} otherwise.
2711
2712 @raise ValueError: The size argument must be greater than zero.
2713 @raise WindowsError: On error an exception is raised.
2714 """
2715 if size <= 0:
2716 raise ValueError, "the size argument must be greater than zero"
2717 while size > 0:
2718 try:
2719 mbi = self.mquery(address)
2720 except WindowsError, e:
2721 if win32.winerror(e) == win32.ERROR_INVALID_PARAMETER:
2722 return False
2723 raise
2724 if not mbi.is_executable():
2725 return False
2726 size = size - mbi.RegionSize
2727 return True
2728
2730 """
2731 Determines if the given memory area is writeable and executable.
2732
2733 Looking for writeable and executable pages is important when
2734 exploiting a software vulnerability.
2735
2736 @note: Returns always C{False} for kernel mode addresses.
2737
2738 @see: L{mquery}
2739
2740 @type address: int
2741 @param address: Memory address.
2742
2743 @type size: int
2744 @param size: Number of bytes. Must be greater than zero.
2745
2746 @rtype: bool
2747 @return: C{True} if the memory area is writeable and executable,
2748 C{False} otherwise.
2749
2750 @raise ValueError: The size argument must be greater than zero.
2751 @raise WindowsError: On error an exception is raised.
2752 """
2753 if size <= 0:
2754 raise ValueError, "the size argument must be greater than zero"
2755 while size > 0:
2756 try:
2757 mbi = self.mquery(address)
2758 except WindowsError, e:
2759 if win32.winerror(e) == win32.ERROR_INVALID_PARAMETER:
2760 return False
2761 raise
2762 if not mbi.is_executable():
2763 return False
2764 size = size - mbi.RegionSize
2765 return True
2766
2768 """
2769 Produces a memory map to the process address space.
2770 Optionally restrict the map to the given address range.
2771
2772 @see: L{mquery}
2773
2774 @type minAddr: int
2775 @param minAddr: (Optional) Starting address in address range to query.
2776
2777 @type maxAddr: int
2778 @param maxAddr: (Optional) Ending address in address range to query.
2779
2780 @rtype: list( L{win32.MemoryBasicInformation} )
2781 @return: List of memory region information objects.
2782 """
2783 if minAddr is None:
2784 minAddr = 0
2785 if maxAddr is None:
2786 maxAddr = win32.LPVOID(-1).value
2787 if minAddr > maxAddr:
2788 minAddr, maxAddr = maxAddr, minAddr
2789 minAddr = MemoryAddresses.align_address_to_page_start(minAddr)
2790 if maxAddr != MemoryAddresses.align_address_to_page_start(maxAddr):
2791 maxAddr = MemoryAddresses.align_address_to_page_end(maxAddr)
2792 prevAddr = minAddr - 1
2793 currentAddr = minAddr
2794 memoryMap = list()
2795 while currentAddr < maxAddr and currentAddr > prevAddr:
2796 try:
2797 mbi = self.mquery(currentAddr)
2798 except WindowsError, e:
2799 if win32.winerror(e) == win32.ERROR_INVALID_PARAMETER:
2800 break
2801 raise
2802 memoryMap.append(mbi)
2803 prevAddr = currentAddr
2804 currentAddr = mbi.BaseAddress + mbi.RegionSize
2805 return memoryMap
2806
2808 """
2809 Retrieves the filenames for memory mapped files in the debugee.
2810
2811 @type memoryMap: list( L{win32.MemoryBasicInformation} )
2812 @param memoryMap: (Optional) Memory map returned by L{get_memory_map}.
2813 If not given, the current memory map is used.
2814
2815 @rtype: dict( int S{->} str )
2816 @return: Dictionary mapping memory addresses to file names.
2817 Native filenames are converted to Win32 filenames when possible.
2818 """
2819 hProcess = self.get_handle()
2820 if not memoryMap:
2821 memoryMap = self.get_memory_map()
2822 mappedFilenames = dict()
2823 for mbi in memoryMap:
2824
2825
2826
2827 if mbi.Type not in (win32.MEM_IMAGE, win32.MEM_MAPPED):
2828 continue
2829
2830 baseAddress = mbi.BaseAddress
2831 fileName = ""
2832 try:
2833 fileName = win32.GetMappedFileName(hProcess, baseAddress)
2834 fileName = PathOperations.native_to_win32_pathname(fileName)
2835 except WindowsError, e:
2836
2837 pass
2838 mappedFilenames[baseAddress] = fileName
2839 return mappedFilenames
2840
2842 """
2843 Returns a generator that allows you to iterate through the memory
2844 contents of a process.
2845
2846 It's basically the same as the L{take_memory_snapshot} method, but it
2847 takes the snapshot of each memory region as it goes, as opposed to
2848 taking the whole snapshot at once. This allows you to work with very
2849 large snapshots without a significant performance penalty.
2850
2851 Example::
2852 # Print the memory contents of a process.
2853 process.suspend()
2854 try:
2855 snapshot = process.generate_memory_snapshot()
2856 for mbi in snapshot:
2857 print HexDump.hexblock(mbi.content, mbi.BaseAddress)
2858 finally:
2859 process.resume()
2860
2861 The downside of this is the process must remain suspended while
2862 iterating the snapshot, otherwise strange things may happen.
2863
2864 The snapshot can be iterated more than once. Each time it's iterated
2865 the memory contents of the process will be fetched again.
2866
2867 You can also iterate the memory of a dead process, just as long as the
2868 last open handle to it hasn't been closed.
2869
2870 @see: L{take_memory_snapshot}
2871
2872 @type minAddr: int
2873 @param minAddr: (Optional) Starting address in address range to query.
2874
2875 @type maxAddr: int
2876 @param maxAddr: (Optional) Ending address in address range to query.
2877
2878 @rtype: generator of L{win32.MemoryBasicInformation}
2879 @return: Generator that when iterated returns memory region information
2880 objects. Two extra properties are added to these objects:
2881 - C{filename}: Mapped filename, or C{None}.
2882 - C{content}: Memory contents, or C{None}.
2883 """
2884 return Regenerator(self.__generate_memory_snapshot, minAddr, maxAddr)
2885
2932
2934 """
2935 Takes a snapshot of the memory contents of the process.
2936
2937 It's best if the process is suspended when taking the snapshot.
2938 Execution can be resumed afterwards.
2939
2940 You can also iterate the memory of a dead process, just as long as the
2941 last open handle to it hasn't been closed.
2942
2943 @warning: If the target process has a very big memory footprint, the
2944 resulting snapshot will be equally big. This may result in a severe
2945 performance penalty.
2946
2947 @see: L{generate_memory_snapshot}
2948
2949 @type minAddr: int
2950 @param minAddr: (Optional) Starting address in address range to query.
2951
2952 @type maxAddr: int
2953 @param maxAddr: (Optional) Ending address in address range to query.
2954
2955 @rtype: list( L{win32.MemoryBasicInformation} )
2956 @return: List of memory region information objects.
2957 Two extra properties are added to these objects:
2958 - C{filename}: Mapped filename, or C{None}.
2959 - C{content}: Memory contents, or C{None}.
2960 """
2961 return list( self.generate_memory_snapshot(minAddr, maxAddr) )
2962
2964 """
2965 Attempts to restore the memory state as it was when the given snapshot
2966 was taken.
2967
2968 @warning: Currently only the memory contents, state and protect bits
2969 are restored. Under some circumstances this method may fail (for
2970 example if memory was freed and then reused by a mapped file).
2971
2972 @type snapshot: list( L{win32.MemoryBasicInformation} )
2973 @param snapshot: Memory snapshot returned by L{take_memory_snapshot}.
2974 Snapshots returned by L{generate_memory_snapshot} don't work here.
2975
2976 @type bSkipMappedFiles: bool
2977 @param bSkipMappedFiles: C{True} to avoid restoring the contents of
2978 memory mapped files, C{False} otherwise. Use with care! Setting
2979 this to C{False} can cause undesired side effects - changes to
2980 memory mapped files may be written to disk by the OS. Also note
2981 that most mapped files are typically executables and don't change,
2982 so trying to restore their contents is usually a waste of time.
2983
2984 @raise WindowsError: An error occured while restoring the snapshot.
2985 @raise RuntimeError: An error occured while restoring the snapshot.
2986 @raise TypeError: A snapshot of the wrong type was passed.
2987 """
2988 if not isinstance(snapshot, list):
2989 raise TypeError, "Only snapshots returned by " \
2990 "take_memory_snapshots() can be used here."
2991
2992
2993 hProcess = self.get_handle()
2994
2995
2996 self.suspend()
2997 try:
2998
2999
3000 for old_mbi in snapshot:
3001
3002
3003 new_mbi = self.mquery(old_mbi.BaseAddress)
3004 if new_mbi.BaseAddress == old_mbi.BaseAddress and new_mbi.RegionSize == old_mbi.RegionSize:
3005 self.__restore_mbi(hProcess, new_mbi, old_mbi)
3006
3007
3008 else:
3009
3010 old_mbi = win32.MemoryBasicInformation(old_mbi)
3011
3012
3013 old_start = old_mbi.BaseAddress
3014 old_end = old_start + old_mbi.RegionSize
3015 new_start = new_mbi.BaseAddress
3016 new_end = new_start + new_mbi.RegionSize
3017 if old_start > new_start:
3018 start = old_start
3019 else:
3020 start = new_start
3021 if old_end < new_end:
3022 end = old_end
3023 else:
3024 end = new_end
3025
3026
3027 step = System.pageSize
3028 old_mbi.RegionSize = step
3029 new_mbi.RegionSize = step
3030 address = start
3031 while address < end:
3032 old_mbi.BaseAddress = address
3033 new_mbi.BaseAddress = address
3034 self.__restore_mbi(hProcess, new_mbi, old_mbi)
3035 address = address + step
3036
3037
3038 finally:
3039 self.resume()
3040
3042 """
3043 Used internally by L{restore_memory_snapshot}.
3044 """
3045
3046
3047
3048
3049 if new_mbi.State != old_mbi.State:
3050 if new_mbi.is_free():
3051 if old_mbi.is_reserved():
3052
3053
3054 address = win32.VirtualAllocEx(hProcess, old_mbi.BaseAddress, old_mbi.RegionSize, win32.MEM_RESERVE, old_mbi.Protect)
3055 if address != old_mbi.BaseAddress:
3056 self.free(address)
3057 msg = "Error restoring region at address %s"
3058 msg = msg % HexDump(old_mbi.BaseAddress)
3059 raise RuntimeError, msg
3060 new_mbi.Protect = old_mbi.Protect
3061
3062 else:
3063
3064
3065 address = win32.VirtualAllocEx(hProcess, old_mbi.BaseAddress, old_mbi.RegionSize, win32.MEM_RESERVE | win32.MEM_COMMIT, old_mbi.Protect)
3066 if address != old_mbi.BaseAddress:
3067 self.free(address)
3068 msg = "Error restoring region at address %s"
3069 msg = msg % HexDump(old_mbi.BaseAddress)
3070 raise RuntimeError, msg
3071 new_mbi.Protect = old_mbi.Protect
3072
3073 elif new_mbi.is_reserved():
3074 if old_mbi.is_commited():
3075
3076
3077 address = win32.VirtualAllocEx(hProcess, old_mbi.BaseAddress, old_mbi.RegionSize, win32.MEM_COMMIT, old_mbi.Protect)
3078 if address != old_mbi.BaseAddress:
3079 self.free(address)
3080 msg = "Error restoring region at address %s"
3081 msg = msg % HexDump(old_mbi.BaseAddress)
3082 raise RuntimeError, msg
3083 new_mbi.Protect = old_mbi.Protect
3084
3085 else:
3086
3087
3088 win32.VirtualFreeEx(hProcess, old_mbi.BaseAddress, old_mbi.RegionSize, win32.MEM_RELEASE)
3089
3090 else:
3091 if old_mbi.is_reserved():
3092
3093
3094 win32.VirtualFreeEx(hProcess, old_mbi.BaseAddress, old_mbi.RegionSize, win32.MEM_DECOMMIT)
3095
3096 else:
3097
3098
3099 win32.VirtualFreeEx(hProcess, old_mbi.BaseAddress, old_mbi.RegionSize, win32.MEM_DECOMMIT | win32.MEM_RELEASE)
3100
3101 new_mbi.State = old_mbi.State
3102
3103
3104 if old_mbi.is_commited() and old_mbi.Protect != new_mbi.Protect:
3105 win32.VirtualProtectEx(hProcess, old_mbi.BaseAddress,
3106 old_mbi.RegionSize, old_mbi.Protect)
3107 new_mbi.Protect = old_mbi.Protect
3108
3109
3110
3111 if old_mbi.has_content():
3112 if old_mbi.Type != 0:
3113 if not bSkipMappedFiles:
3114 self.poke(old_mbi.BaseAddress, old_mbi.content)
3115 else:
3116 self.write(old_mbi.BaseAddress, old_mbi.content)
3117 new_mbi.content = old_mbi.content
3118
3122 """
3123 Internally used by L{SymbolContainer} to enumerate symbols in a module.
3124 """
3125
3127 self.symbols = list()
3128
3129 - def __call__(self, SymbolName, SymbolAddress, SymbolSize, UserContext):
3130 """
3131 Callback that receives symbols and stores them in a Python list.
3132 """
3133
3134
3135
3136
3137 self.symbols.append( (SymbolName, SymbolAddress, SymbolSize) )
3138 return win32.TRUE
3139
3141 """
3142 Capability to contain symbols. Used by L{Module}.
3143
3144 @group Symbols:
3145 load_symbols, unload_symbols, get_symbols, iter_symbols,
3146 resolve_symbol, get_symbol_at_address
3147 """
3148
3150 self.__symbols = list()
3151
3152
3153
3154
3155
3157 """
3158 Loads the debugging symbols for a module.
3159 Automatically called by L{get_symbols}.
3160 """
3161 hProcess = self.get_process().get_handle()
3162 hFile = self.hFile
3163 BaseOfDll = self.get_base()
3164 SizeOfDll = self.get_size()
3165 Enumerator = SymbolEnumerator()
3166 try:
3167 win32.SymInitialize(hProcess)
3168 SymOptions = win32.SymGetOptions()
3169 win32.SymSetOptions(SymOptions | \
3170 win32.SYMOPT_ALLOW_ZERO_ADDRESS | \
3171 win32.SYMOPT_CASE_INSENSITIVE | \
3172 win32.SYMOPT_FAVOR_COMPRESSED | \
3173 win32.SYMOPT_INCLUDE_32BIT_MODULES | \
3174 win32.SYMOPT_UNDNAME)
3175 try:
3176 win32.SymSetOptions(SymOptions | win32.SYMOPT_ALLOW_ABSOLUTE_SYMBOLS)
3177 except WindowsError:
3178 pass
3179 try:
3180 try:
3181 win32.SymLoadModule64(hProcess, hFile, None, None, BaseOfDll, SizeOfDll)
3182 except WindowsError:
3183 ImageName = self.get_filename()
3184 win32.SymLoadModule64(hProcess, None, ImageName, None, BaseOfDll, SizeOfDll)
3185 try:
3186 win32.SymEnumerateSymbols64(hProcess, BaseOfDll, Enumerator)
3187 finally:
3188 win32.SymUnloadModule64(hProcess, BaseOfDll)
3189 finally:
3190 win32.SymCleanup(hProcess)
3191 except WindowsError, e:
3192
3193
3194 pass
3195 self.__symbols = Enumerator.symbols
3196
3198 """
3199 Unloads the debugging symbols for a module.
3200 """
3201 self.__symbols = list()
3202
3204 """
3205 Returns the debugging symbols for a module.
3206 The symbols are automatically loaded when needed.
3207
3208 @rtype: list of tuple( str, int, int )
3209 @return: List of symbols.
3210 Each symbol is represented by a tuple that contains:
3211 - Symbol name
3212 - Symbol memory address
3213 - Symbol size in bytes
3214 """
3215 if not self.__symbols:
3216 self.load_symbols()
3217 return list(self.__symbols)
3218
3220 """
3221 Returns an iterator for the debugging symbols in a module,
3222 in no particular order.
3223 The symbols are automatically loaded when needed.
3224
3225 @rtype: iterator of tuple( str, int, int )
3226 @return: Iterator of symbols.
3227 Each symbol is represented by a tuple that contains:
3228 - Symbol name
3229 - Symbol memory address
3230 - Symbol size in bytes
3231 """
3232 if not self.__symbols:
3233 self.load_symbols()
3234 return self.__symbols.__iter__()
3235
3237 """
3238 Resolves a debugging symbol's address.
3239
3240 @type symbol: str
3241 @param symbol: Name of the symbol to resolve.
3242
3243 @type bCaseSensitive: bool
3244 @param bCaseSensitive: C{True} for case sensitive matches,
3245 C{False} for case insensitive.
3246
3247 @rtype: int or None
3248 @return: Memory address of symbol. C{None} if not found.
3249 """
3250 if bCaseSensitive:
3251 for (SymbolName, SymbolAddress, SymbolSize) in self.iter_symbols():
3252 if symbol == SymbolName:
3253 return SymbolAddress
3254 else:
3255 symbol = symbol.lower()
3256 for (SymbolName, SymbolAddress, SymbolSize) in self.iter_symbols():
3257 if symbol == SymbolName.lower():
3258 return SymbolAddress
3259
3261 """
3262 Tries to find the closest matching symbol for the given address.
3263
3264 @type address: int
3265 @param address: Memory address to query.
3266
3267 @rtype: None or tuple( str, int, int )
3268 @return: Returns a tuple consisting of:
3269 - Name
3270 - Address
3271 - Size (in bytes)
3272 Returns C{None} if no symbol could be matched.
3273 """
3274 found = None
3275 for (SymbolName, SymbolAddress, SymbolSize) in self.iter_symbols():
3276 if SymbolAddress > address:
3277 continue
3278 if SymbolAddress + SymbolSize > address:
3279 if not found or found[1] < SymbolAddress:
3280 found = (SymbolName, SymbolAddress, SymbolSize)
3281 return found
3282
3286 """
3287 Encapsulates symbol operations capabilities.
3288
3289 Requires a L{ModuleContainer}.
3290
3291 @note: Labels are an approximated way of referencing memory locations
3292 across different executions of the same process, or different processes
3293 with common modules. They are not meant to be perfectly unique, and
3294 some errors may occur when multiple modules with the same name are
3295 loaded, or when module filenames can't be retrieved.
3296
3297 @group Labels:
3298 parse_label,
3299 split_label,
3300 sanitize_label,
3301 resolve_label,
3302 get_label_at_address,
3303 split_label_strict,
3304 split_label_fuzzy
3305
3306 @group Symbols:
3307 load_symbols, unload_symbols, get_symbols, iter_symbols,
3308 resolve_symbol, get_symbol_at_address
3309
3310 @group Debugging:
3311 is_system_defined_breakpoint, get_system_breakpoint,
3312 get_user_breakpoint, get_breakin_breakpoint,
3313 get_wow64_system_breakpoint, get_wow64_user_breakpoint,
3314 get_wow64_breakin_breakpoint
3315 """
3316
3322
3323 @staticmethod
3324 - def parse_label(module = None, function = None, offset = None):
3325 """
3326 Creates a label from a module and a function name, plus an offset.
3327
3328 @warning: This method only parses the label, it doesn't make sure the
3329 label actually points to a valid memory location.
3330
3331 @type module: None or str
3332 @param module: (Optional) Module name.
3333
3334 @type function: None, str or int
3335 @param function: (Optional) Function name or ordinal.
3336
3337 @type offset: None or int
3338 @param offset: (Optional) Offset value.
3339
3340 If C{function} is specified, offset from the function.
3341
3342 If C{function} is C{None}, offset from the module.
3343
3344 @rtype: str
3345 @return:
3346 Label representing the given function in the given module.
3347
3348 @raise ValueError:
3349 The module or function name contain invalid characters.
3350 """
3351
3352
3353
3354
3355
3356 try:
3357 function = "#0x%x" % function
3358 except TypeError:
3359 pass
3360
3361
3362 if module is not None and ('!' in module or '+' in module):
3363 raise ValueError, "Invalid module name: %s" % module
3364 if function is not None and ('!' in function or '+' in function):
3365 raise ValueError, "Invalid function name: %s" % function
3366
3367
3368 if module:
3369 if function:
3370 if offset:
3371 label = "%s!%s+0x%x" % (module, function, offset)
3372 else:
3373 label = "%s!%s" % (module, function)
3374 else:
3375 if offset:
3376
3377 label = "%s!0x%x" % (module, offset)
3378 else:
3379 label = "%s!" % module
3380 else:
3381 if function:
3382 if offset:
3383 label = "!%s+0x%x" % (function, offset)
3384 else:
3385 label = "!%s" % function
3386 else:
3387 if offset:
3388 label = "0x%x" % offset
3389 else:
3390 label = "0x0"
3391
3392 return label
3393
3394 @staticmethod
3396 """
3397 Splits a label created with L{parse_label}.
3398
3399 To parse labels with a less strict syntax, use the L{split_label_fuzzy}
3400 method instead.
3401
3402 @warning: This method only parses the label, it doesn't make sure the
3403 label actually points to a valid memory location.
3404
3405 @type label: str
3406 @param label: Label to split.
3407
3408 @rtype: tuple( str or None, str or int or None, int or None )
3409 @return: Tuple containing the C{module} name,
3410 the C{function} name or ordinal, and the C{offset} value.
3411
3412 If the label doesn't specify a module,
3413 then C{module} is C{None}.
3414
3415 If the label doesn't specify a function,
3416 then C{function} is C{None}.
3417
3418 If the label doesn't specify an offset,
3419 then C{offset} is C{0}.
3420
3421 @raise ValueError: The label is malformed.
3422 """
3423 module = function = None
3424 offset = 0
3425
3426
3427 if not label:
3428 label = "0x0"
3429 else:
3430
3431
3432 label = label.replace(' ', '')
3433 label = label.replace('\t', '')
3434 label = label.replace('\r', '')
3435 label = label.replace('\n', '')
3436
3437
3438 if not label:
3439 label = "0x0"
3440
3441
3442 if '!' in label:
3443 try:
3444 module, function = label.split('!')
3445 except ValueError:
3446 raise ValueError, "Malformed label: %s" % label
3447
3448
3449 if function:
3450 if '+' in module:
3451 raise ValueError, "Malformed label: %s" % label
3452
3453
3454 if '+' in function:
3455 try:
3456 function, offset = function.split('+')
3457 except ValueError:
3458 raise ValueError, "Malformed label: %s" % label
3459 try:
3460 offset = HexInput.integer(offset)
3461 except ValueError:
3462 raise ValueError, "Malformed label: %s" % label
3463 else:
3464
3465
3466 try:
3467 offset = HexInput.integer(function)
3468 function = None
3469 except ValueError:
3470 pass
3471 else:
3472
3473
3474 if '+' in module:
3475 try:
3476 module, offset = module.split('+')
3477 except ValueError:
3478 raise ValueError, "Malformed label: %s" % label
3479 try:
3480 offset = HexInput.integer(offset)
3481 except ValueError:
3482 raise ValueError, "Malformed label: %s" % label
3483
3484 else:
3485
3486
3487 try:
3488 offset = HexInput.integer(module)
3489 module = None
3490
3491
3492 except ValueError:
3493 pass
3494
3495 if not module:
3496 module = None
3497 if not function:
3498 function = None
3499
3500
3501 else:
3502
3503
3504 try:
3505 offset = HexInput.integer(label)
3506
3507
3508 except ValueError:
3509 if label.startswith('#'):
3510 function = label
3511 try:
3512 HexInput.integer(function[1:])
3513
3514
3515
3516 except ValueError:
3517 raise ValueError, "Ambiguous label: %s" % label
3518
3519
3520
3521 else:
3522 raise ValueError, "Ambiguous label: %s" % label
3523
3524
3525 if function and function.startswith('#'):
3526 try:
3527 function = HexInput.integer(function[1:])
3528 except ValueError:
3529 pass
3530
3531
3532 if not offset:
3533 offset = None
3534
3535 return (module, function, offset)
3536
3538 """
3539 Splits a label entered as user input.
3540
3541 It's more flexible in it's syntax parsing than the L{split_label_strict}
3542 method, as it allows the exclamation mark (B{C{!}}) to be omitted. The
3543 ambiguity is resolved by searching the modules in the snapshot to guess
3544 if a label refers to a module or a function. It also tries to rebuild
3545 labels when they contain hardcoded addresses.
3546
3547 @warning: This method only parses the label, it doesn't make sure the
3548 label actually points to a valid memory location.
3549
3550 @type label: str
3551 @param label: Label to split.
3552
3553 @rtype: tuple( str or None, str or int or None, int or None )
3554 @return: Tuple containing the C{module} name,
3555 the C{function} name or ordinal, and the C{offset} value.
3556
3557 If the label doesn't specify a module,
3558 then C{module} is C{None}.
3559
3560 If the label doesn't specify a function,
3561 then C{function} is C{None}.
3562
3563 If the label doesn't specify an offset,
3564 then C{offset} is C{0}.
3565
3566 @raise ValueError: The label is malformed.
3567 """
3568 module = function = None
3569 offset = 0
3570
3571
3572 if not label:
3573 label = "0x0"
3574 else:
3575
3576
3577 label = label.replace(' ', '')
3578 label = label.replace('\t', '')
3579 label = label.replace('\r', '')
3580 label = label.replace('\n', '')
3581
3582
3583 if not label:
3584 label = "0x0"
3585
3586
3587 if '!' in label:
3588 return self.split_label_strict(label)
3589
3590
3591
3592
3593
3594
3595
3596
3597 if '+' in label:
3598 try:
3599 prefix, offset = label.split('+')
3600 except ValueError:
3601 raise ValueError, "Malformed label: %s" % label
3602 try:
3603 offset = HexInput.integer(offset)
3604 except ValueError:
3605 raise ValueError, "Malformed label: %s" % label
3606 label = prefix
3607
3608
3609 modobj = self.get_module_by_name(label)
3610 if modobj:
3611
3612
3613
3614 module = modobj.get_name()
3615
3616 else:
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627 try:
3628 address = HexInput.integer(label)
3629
3630 if offset:
3631
3632
3633
3634
3635
3636
3637 offset = address + offset
3638 else:
3639
3640 offset = address
3641
3642
3643
3644
3645
3646
3647 try:
3648 new_label = self.get_label_at_address(offset)
3649 module, function, offset = \
3650 self.split_label_strict(new_label)
3651 except ValueError:
3652 pass
3653
3654
3655
3656 except ValueError:
3657 function = label
3658
3659
3660 if function and function.startswith('#'):
3661 try:
3662 function = HexInput.integer(function[1:])
3663 except ValueError:
3664 pass
3665
3666
3667 if not offset:
3668 offset = None
3669
3670 return (module, function, offset)
3671
3672 @classmethod
3674 """
3675 Splits a label into it's C{module}, C{function} and C{offset}
3676 components, as used in L{parse_label}.
3677
3678 When called as a static method, the strict syntax mode is used::
3679
3680 winappdbg.Process.split_label( "kernel32!CreateFileA" )
3681
3682 When called as an instance method, the fuzzy syntax mode is used::
3683
3684 aProcessInstance.split_label( "CreateFileA" )
3685
3686 @see: L{split_label_strict}, L{split_label_fuzzy}
3687
3688 @type label: str
3689 @param label: Label to split.
3690
3691 @rtype: tuple( str or None, str or int or None, int or None )
3692 @return:
3693 Tuple containing the C{module} name,
3694 the C{function} name or ordinal, and the C{offset} value.
3695
3696 If the label doesn't specify a module,
3697 then C{module} is C{None}.
3698
3699 If the label doesn't specify a function,
3700 then C{function} is C{None}.
3701
3702 If the label doesn't specify an offset,
3703 then C{offset} is C{0}.
3704
3705 @raise ValueError: The label is malformed.
3706 """
3707
3708
3709
3710
3711
3712
3713
3714 return cls.split_label_strict(label)
3715
3716
3720
3721
3723 """
3724 Converts a label taken from user input into a well-formed label.
3725
3726 @type label: str
3727 @param label: Label taken from user input.
3728
3729 @rtype: str
3730 @return: Sanitized label.
3731 """
3732 (module, function, offset) = self.split_label_fuzzy(label)
3733 label = self.parse_label(module, function, offset)
3734 return label
3735
3737 """
3738 Resolve the memory address of the given label.
3739
3740 @note:
3741 If multiple modules with the same name are loaded,
3742 the label may be resolved at any of them. For a more precise
3743 way to resolve functions use the base address to get the L{Module}
3744 object (see L{Process.get_module}) and then call L{Module.resolve}.
3745
3746 If no module name is specified in the label, the function may be
3747 resolved in any loaded module. If you want to resolve all functions
3748 with that name in all processes, call L{Process.iter_modules} to
3749 iterate through all loaded modules, and then try to resolve the
3750 function in each one of them using L{Module.resolve}.
3751
3752 @type label: str
3753 @param label: Label to resolve.
3754
3755 @rtype: int
3756 @return: Memory address pointed to by the label.
3757
3758 @raise ValueError: The label is malformed or impossible to resolve.
3759 @raise RuntimeError: Cannot resolve the module or function.
3760 """
3761
3762
3763 address = 0
3764
3765
3766 module, function, offset = self.split_label_fuzzy(label)
3767
3768
3769 if module:
3770 modobj = self.get_module_by_name(module)
3771 if not modobj:
3772 msg = "Module %r not found" % module
3773 raise RuntimeError, msg
3774
3775
3776
3777 if function:
3778 address = modobj.resolve(function)
3779 if address is None:
3780 address = modobj.resolve_symbol(function)
3781 if address is None:
3782 if function == "start":
3783 address = modobj.get_entry_point()
3784 if address is None:
3785 msg = "Symbol %r not found in module %s"
3786 msg = msg % (function, module)
3787 raise RuntimeError, msg
3788
3789
3790 else:
3791 address = modobj.get_base()
3792
3793
3794 elif function:
3795 for modobj in self.iter_modules():
3796 address = modobj.resolve(function)
3797 if address is not None:
3798 break
3799 if address is None:
3800 msg = "Function %r not found in any module" % function
3801 raise RuntimeError, msg
3802
3803
3804 if offset:
3805 address = address + offset
3806 return address
3807
3809 """
3810 Creates a label from the given memory address.
3811
3812 @warning: This method uses the name of the nearest currently loaded
3813 module. If that module is unloaded later, the label becomes
3814 impossible to resolve.
3815
3816 @type address: int
3817 @param address: Memory address.
3818
3819 @type offset: None or int
3820 @param offset: (Optional) Offset value.
3821
3822 @rtype: str
3823 @return: Label pointing to the given address.
3824 """
3825 if offset:
3826 address = address + offset
3827 modobj = self.get_module_at_address(address)
3828 if modobj:
3829 label = modobj.get_label_at_address(address)
3830 else:
3831 label = self.parse_label(None, None, address)
3832 return label
3833
3834
3835
3836
3853
3854
3855
3856
3858 """
3859 @rtype: int or None
3860 @return: Memory address of the system breakpoint
3861 within the process address space.
3862 Returns C{None} on error.
3863 """
3864 try:
3865 return self.resolve_label("ntdll!DbgBreakPoint")
3866 except Exception:
3867 return None
3868
3869
3871 """
3872 @rtype: int or None
3873 @return: Memory address of the Wow64 system breakpoint
3874 within the process address space.
3875 Returns C{None} on error.
3876 """
3877 try:
3878 return self.resolve_label("ntdll32!DbgBreakPoint")
3879 except Exception:
3880 return None
3881
3882
3884 """
3885 @rtype: int or None
3886 @return: Memory address of the user breakpoint
3887 within the process address space.
3888 Returns C{None} on error.
3889 """
3890 try:
3891 return self.resolve_label("ntdll!DbgUserBreakPoint")
3892 except Exception:
3893 return None
3894
3895
3897 """
3898 @rtype: int or None
3899 @return: Memory address of the Wow64 user breakpoint
3900 within the process address space.
3901 Returns C{None} on error.
3902 """
3903 try:
3904 return self.resolve_label("ntdll32!DbgUserBreakPoint")
3905 except Exception:
3906 return None
3907
3908
3909
3911 """
3912 @rtype: int or None
3913 @return: Memory address of the remote breakin breakpoint
3914 within the process address space.
3915 Returns C{None} on error.
3916 """
3917 try:
3918 return self.resolve_label("ntdll!DbgUiRemoteBreakin")
3919 except Exception:
3920 return None
3921
3922
3924 """
3925 @rtype: int or None
3926 @return: Memory address of the Wow64 remote breakin breakpoint
3927 within the process address space.
3928 Returns C{None} on error.
3929 """
3930 try:
3931 return self.resolve_label("ntdll32!DbgUiRemoteBreakin")
3932 except Exception:
3933 return None
3934
3936 """
3937 Loads the debugging symbols for all modules in this snapshot.
3938 Automatically called by L{get_symbols}.
3939 """
3940 for aModule in self.iter_modules():
3941 aModule.load_symbols()
3942
3944 """
3945 Unloads the debugging symbols for all modules in this snapshot.
3946 """
3947 for aModule in self.iter_modules():
3948 aModule.unload_symbols()
3949
3951 """
3952 Returns the debugging symbols for all modules in this snapshot.
3953 The symbols are automatically loaded when needed.
3954
3955 @rtype: list of tuple( str, int, int )
3956 @return: List of symbols.
3957 Each symbol is represented by a tuple that contains:
3958 - Symbol name
3959 - Symbol memory address
3960 - Symbol size in bytes
3961 """
3962 symbols = list()
3963 for aModule in self.iter_modules():
3964 for symbol in aModule.iter_symbols():
3965 symbols.append(symbol)
3966 return symbols
3967
3969 """
3970 Returns an iterator for the debugging symbols in all modules in this
3971 snapshot, in no particular order.
3972 The symbols are automatically loaded when needed.
3973
3974 @rtype: iterator of tuple( str, int, int )
3975 @return: Iterator of symbols.
3976 Each symbol is represented by a tuple that contains:
3977 - Symbol name
3978 - Symbol memory address
3979 - Symbol size in bytes
3980 """
3981 for aModule in self.iter_modules():
3982 for symbol in aModule.iter_symbols():
3983 yield symbol
3984
3986 """
3987 Resolves a debugging symbol's address.
3988
3989 @type symbol: str
3990 @param symbol: Name of the symbol to resolve.
3991
3992 @type bCaseSensitive: bool
3993 @param bCaseSensitive: C{True} for case sensitive matches,
3994 C{False} for case insensitive.
3995
3996 @rtype: int or None
3997 @return: Memory address of symbol. C{None} if not found.
3998 """
3999 if bCaseSensitive:
4000 for (SymbolName, SymbolAddress, SymbolSize) in self.iter_symbols():
4001 if symbol == SymbolName:
4002 return SymbolAddress
4003 else:
4004 symbol = symbol.lower()
4005 for (SymbolName, SymbolAddress, SymbolSize) in self.iter_symbols():
4006 if symbol == SymbolName.lower():
4007 return SymbolAddress
4008
4010 """
4011 Tries to find the closest matching symbol for the given address.
4012
4013 @type address: int
4014 @param address: Memory address to query.
4015
4016 @rtype: None or tuple( str, int, int )
4017 @return: Returns a tuple consisting of:
4018 - Name
4019 - Address
4020 - Size (in bytes)
4021 Returns C{None} if no symbol could be matched.
4022 """
4023
4024
4025 found = None
4026 for (SymbolName, SymbolAddress, SymbolSize) in self.iter_symbols():
4027 if SymbolAddress <= address:
4028 if SymbolAddress + SymbolSize > address:
4029 if not found or found[1] < SymbolAddress:
4030 found = (SymbolName, SymbolAddress, SymbolSize)
4031 return found
4032
4039 """
4040 Encapsulates several useful debugging routines for threads.
4041
4042 @group Properties:
4043 get_teb, get_teb_address, is_wow64
4044
4045 @group Debugging:
4046 get_seh_chain_pointer, set_seh_chain_pointer,
4047 get_seh_chain, get_wait_chain
4048
4049 @group Disassembly:
4050 disassemble, disassemble_around, disassemble_around_pc,
4051 disassemble_string, disassemble_instruction, disassemble_current
4052
4053 @group Stack:
4054 get_stack_frame, get_stack_frame_range, get_stack_range,
4055 get_stack_trace, get_stack_trace_with_labels,
4056 read_stack_data, read_stack_dwords, read_stack_qwords,
4057 peek_stack_data, peek_stack_dwords, peek_stack_qwords
4058
4059 @group Miscellaneous:
4060 read_code_bytes, peek_code_bytes,
4061 peek_pointers_in_data, peek_pointers_in_registers,
4062 get_linear_address, get_label_at_pc
4063 """
4064
4066 """
4067 Determines if the thread is running under WOW64.
4068
4069 @rtype: bool
4070 @return:
4071 C{True} if the thread is running under WOW64. That is, it belongs
4072 to a 32-bit application running in a 64-bit Windows.
4073
4074 C{False} if the thread belongs to either a 32-bit application
4075 running in a 32-bit Windows, or a 64-bit application running in a
4076 64-bit Windows.
4077
4078 @raise WindowsError: On error an exception is raised.
4079
4080 @see: U{http://msdn.microsoft.com/en-us/library/aa384249(VS.85).aspx}
4081 """
4082 return self.get_process().is_wow64()
4083
4084
4085
4086
4087
4089 """
4090 Returns a copy of the TEB.
4091 To dereference pointers in it call L{Process.read_structure}.
4092
4093 @rtype: L{TEB}
4094 @return: TEB structure.
4095 @raise WindowsError: An exception is raised on error.
4096 """
4097 return self.get_process().read_structure( self.get_teb_address(),
4098 win32.TEB )
4099
4117
4119 """
4120 Translates segment-relative addresses to linear addresses.
4121
4122 Linear addresses can be used to access a process memory,
4123 calling L{Process.read} and L{Process.write}.
4124
4125 @type segment: str
4126 @param segment: Segment register name.
4127
4128 @type address: int
4129 @param address: Segment relative memory address.
4130
4131 @rtype: int
4132 @return: Linear memory address.
4133
4134 @raise ValueError: Address is too large for selector.
4135
4136 @raise WindowsError:
4137 The current architecture does not support selectors.
4138 Selectors only exist in x86-based systems.
4139 """
4140 selector = self.get_register(segment)
4141 ldt = win32.GetThreadSelectorEntry(self.get_handle(), selector)
4142 BaseLow = ldt.BaseLow
4143 BaseMid = ldt.HighWord.Bytes.BaseMid << 16
4144 BaseHi = ldt.HighWord.Bytes.BaseHi << 24
4145 Base = BaseLow | BaseMid | BaseHi
4146 LimitLow = ldt.LimitLow
4147 LimitHi = ldt.HighWord.Bits.LimitHi << 16
4148 Limit = LimitLow | LimitHi
4149 if address > Limit:
4150 msg = "Address %s too large for segment %s (selector %d)"
4151 msg = msg % (HexDump.address(address), segment, selector)
4152 raise ValueError, msg
4153 return Base + address
4154
4161
4163 """
4164 Get the pointer to the first structured exception handler block.
4165
4166 @rtype: int
4167 @return: Remote pointer to the first block of the structured exception
4168 handlers linked list. If the list is empty, the returned value is
4169 C{0xFFFFFFFF}.
4170
4171 @raise NotImplementedError:
4172 This method is only supported in 32 bits versions of Windows.
4173 """
4174 if System.arch != 'i386':
4175 raise NotImplementedError, \
4176 "SEH chain parsing is only supported in 32-bit Windows."
4177
4178 process = self.get_process()
4179 address = self.get_linear_address( 'SegFs', 0 )
4180 return process.read_pointer( address )
4181
4183 """
4184 Change the pointer to the first structured exception handler block.
4185
4186 @type value: int
4187 @param value: Value of the remote pointer to the first block of the
4188 structured exception handlers linked list. To disable SEH set the
4189 value C{0xFFFFFFFF}.
4190
4191 @raise NotImplementedError:
4192 This method is only supported in 32 bits versions of Windows.
4193 """
4194 if System.arch != 'i386':
4195 raise NotImplementedError, \
4196 "SEH chain parsing is only supported in 32-bit Windows."
4197
4198 process = self.get_process()
4199 address = self.get_linear_address( 'SegFs', 0 )
4200 process.write_pointer( address, value )
4201
4203 """
4204 @rtype: list of tuple( int, int )
4205 @return: List of structured exception handlers.
4206 Each SEH is represented as a tuple of two addresses:
4207 - Address of this SEH block
4208 - Address of the SEH callback function
4209 Do not confuse this with the contents of the SEH block itself,
4210 where the first member is a pointer to the B{next} block instead.
4211
4212 @raise NotImplementedError:
4213 This method is only supported in 32 bits versions of Windows.
4214 """
4215 seh_chain = list()
4216 try:
4217 process = self.get_process()
4218 seh = self.get_seh_chain_pointer()
4219 while seh != 0xFFFFFFFF:
4220 seh_func = process.read_pointer( seh + 4 )
4221 seh_chain.append( (seh, seh_func) )
4222 seh = process.read_pointer( seh )
4223 except WindowsError, e:
4224 seh_chain.append( (seh, None) )
4225 return seh_chain
4226
4228 """
4229 @rtype:
4230 tuple of (
4231 list of L{win32.WAITCHAIN_NODE_INFO} structures,
4232 bool)
4233 @return:
4234 Wait chain for the thread.
4235 The boolean indicates if there's a cycle in the chain.
4236 @raise AttributeError:
4237 This method is only suppported in Windows Vista and above.
4238 @see:
4239 U{http://msdn.microsoft.com/en-us/library/ms681622%28VS.85%29.aspx}
4240 """
4241 hWct = win32.OpenThreadWaitChainSession()
4242 try:
4243 return win32.GetThreadWaitChain(hWct, None, 0, self.get_tid())
4244 finally:
4245 win32.CloseThreadWaitChainSession(hWct)
4246
4248 """
4249 @rtype: tuple( int, int )
4250 @return: Stack beginning and end pointers, in memory addresses order.
4251 That is, the first pointer is the stack top, and the second pointer
4252 is the stack bottom, since the stack grows towards lower memory
4253 addresses.
4254 @raise WindowsError: Raises an exception on error.
4255 """
4256 teb = self.get_teb()
4257 tib = teb.NtTib
4258 return ( tib.StackLimit, tib.StackBase )
4259
4260 - def __get_stack_trace(self, depth = 16, bUseLabels = True,
4261 bMakePretty = True):
4262 """
4263 Tries to get a stack trace for the current function.
4264 Only works for functions with standard prologue and epilogue.
4265
4266 @type depth: int
4267 @param depth: Maximum depth of stack trace.
4268
4269 @type bUseLabels: bool
4270 @param bUseLabels: C{True} to use labels, C{False} to use addresses.
4271
4272 @rtype: tuple of tuple( int, int, str )
4273 @return: Stack trace of the thread as a tuple of
4274 ( return address, frame pointer address, module filename )
4275 when C{bUseLabels} is C{True}, or a tuple of
4276 ( return address, frame pointer label )
4277 when C{bUseLabels} is C{False}.
4278
4279 @raise WindowsError: Raises an exception on error.
4280 """
4281 aProcess = self.get_process()
4282 st, sb = self.get_stack_range()
4283 fp = self.get_fp()
4284 trace = list()
4285 if aProcess.get_module_count() == 0:
4286 aProcess.scan_modules()
4287 while depth > 0:
4288 if fp == 0:
4289 break
4290 if not st <= fp < sb:
4291 break
4292 ra = aProcess.peek_pointer(fp + 4)
4293 if ra == 0:
4294 break
4295 lib = aProcess.get_module_at_address(ra)
4296 if lib is None:
4297 lib = ""
4298 else:
4299 if lib.fileName:
4300 lib = lib.fileName
4301 else:
4302 lib = "%s" % HexDump.address(lib.lpBaseOfDll)
4303 if bUseLabels:
4304 label = aProcess.get_label_at_address(ra)
4305 if bMakePretty:
4306 label = '%s (%s)' % (HexDump.address(ra), label)
4307 trace.append( (fp, label) )
4308 else:
4309 trace.append( (fp, ra, lib) )
4310 fp = aProcess.peek_pointer(fp)
4311 return tuple(trace)
4312
4314 """
4315 Tries to get a stack trace for the current function.
4316 Only works for functions with standard prologue and epilogue.
4317
4318 @type depth: int
4319 @param depth: Maximum depth of stack trace.
4320
4321 @rtype: tuple of tuple( int, int, str )
4322 @return: Stack trace of the thread as a tuple of
4323 ( return address, frame pointer address, module filename ).
4324
4325 @raise WindowsError: Raises an exception on error.
4326 """
4327 return self.__get_stack_trace(depth, False)
4328
4330 """
4331 Tries to get a stack trace for the current function.
4332 Only works for functions with standard prologue and epilogue.
4333
4334 @type depth: int
4335 @param depth: Maximum depth of stack trace.
4336
4337 @type bMakePretty: bool
4338 @param bMakePretty:
4339 C{True} for user readable labels,
4340 C{False} for labels that can be passed to L{Process.resolve_label}.
4341
4342 "Pretty" labels look better when producing output for the user to
4343 read, while pure labels are more useful programatically.
4344
4345 @rtype: tuple of tuple( int, int, str )
4346 @return: Stack trace of the thread as a tuple of
4347 ( return address, frame pointer label ).
4348
4349 @raise WindowsError: Raises an exception on error.
4350 """
4351 return self.__get_stack_trace(depth, True)
4352
4354 """
4355 Returns the starting and ending addresses of the stack frame.
4356 Only works for functions with standard prologue and epilogue.
4357
4358 @rtype: tuple( int, int )
4359 @return: Stack frame range.
4360 May not be accurate, depending on the compiler used.
4361
4362 @raise RuntimeError: The stack frame is invalid,
4363 or the function doesn't have a standard prologue
4364 and epilogue.
4365
4366 @raise WindowsError: An error occured when getting the thread context.
4367 """
4368 st, sb = self.get_stack_range()
4369 sp = self.get_sp()
4370 fp = self.get_fp()
4371 size = fp - sp
4372 if not st <= sp < sb:
4373 raise RuntimeError, 'Stack pointer lies outside the stack'
4374 if not st <= fp < sb:
4375 raise RuntimeError, 'Frame pointer lies outside the stack'
4376 if sp > fp:
4377 raise RuntimeError, 'No valid stack frame found'
4378 return (sp, fp)
4379
4381 """
4382 Reads the contents of the current stack frame.
4383 Only works for functions with standard prologue and epilogue.
4384
4385 @type max_size: int
4386 @param max_size: (Optional) Maximum amount of bytes to read.
4387
4388 @rtype: str
4389 @return: Stack frame data.
4390 May not be accurate, depending on the compiler used.
4391 May return an empty string.
4392
4393 @raise RuntimeError: The stack frame is invalid,
4394 or the function doesn't have a standard prologue
4395 and epilogue.
4396
4397 @raise WindowsError: An error occured when getting the thread context
4398 or reading data from the process memory.
4399 """
4400 sp, fp = self.get_stack_frame_range()
4401 size = fp - sp
4402 if max_size and size > max_size:
4403 size = max_size
4404 return self.get_process().peek(sp, size)
4405
4407 """
4408 Reads the contents of the top of the stack.
4409
4410 @type size: int
4411 @param size: Number of bytes to read.
4412
4413 @type offset: int
4414 @param offset: Offset from the stack pointer to begin reading.
4415
4416 @rtype: str
4417 @return: Stack data.
4418
4419 @raise WindowsError: Could not read the requested data.
4420 """
4421 aProcess = self.get_process()
4422 return aProcess.read(self.get_sp() + offset, size)
4423
4425 """
4426 Tries to read the contents of the top of the stack.
4427
4428 @type size: int
4429 @param size: Number of bytes to read.
4430
4431 @type offset: int
4432 @param offset: Offset from the stack pointer to begin reading.
4433
4434 @rtype: str
4435 @return: Stack data.
4436 Returned data may be less than the requested size.
4437 """
4438 aProcess = self.get_process()
4439 return aProcess.peek(self.get_sp() + offset, size)
4440
4442 """
4443 Reads DWORDs from the top of the stack.
4444
4445 @type count: int
4446 @param count: Number of DWORDs to read.
4447
4448 @type offset: int
4449 @param offset: Offset from the stack pointer to begin reading.
4450
4451 @rtype: tuple( int... )
4452 @return: Tuple of integers read from the stack.
4453
4454 @raise WindowsError: Could not read the requested data.
4455 """
4456 stackData = self.read_stack_data(count * 4, offset)
4457 return struct.unpack('<'+('L'*count), stackData)
4458
4460 """
4461 Tries to read DWORDs from the top of the stack.
4462
4463 @type count: int
4464 @param count: Number of DWORDs to read.
4465
4466 @type offset: int
4467 @param offset: Offset from the stack pointer to begin reading.
4468
4469 @rtype: tuple( int... )
4470 @return: Tuple of integers read from the stack.
4471 May be less than the requested number of DWORDs.
4472 """
4473 stackData = self.peek_stack_data(count * 4, offset)
4474 if len(stackData) & 3:
4475 stackData = stackData[:-len(stackData) & 3]
4476 if not stackData:
4477 return ()
4478 return struct.unpack('<'+('L'*count), stackData)
4479
4481 """
4482 Reads QWORDs from the top of the stack.
4483
4484 @type count: int
4485 @param count: Number of QWORDs to read.
4486
4487 @type offset: int
4488 @param offset: Offset from the stack pointer to begin reading.
4489
4490 @rtype: tuple( int... )
4491 @return: Tuple of integers read from the stack.
4492
4493 @raise WindowsError: Could not read the requested data.
4494 """
4495 stackData = self.read_stack_data(count * 8, offset)
4496 return struct.unpack('<'+('Q'*count), stackData)
4497
4499 """
4500 Tries to read QWORDs from the top of the stack.
4501
4502 @type count: int
4503 @param count: Number of QWORDs to read.
4504
4505 @type offset: int
4506 @param offset: Offset from the stack pointer to begin reading.
4507
4508 @rtype: tuple( int... )
4509 @return: Tuple of integers read from the stack.
4510 May be less than the requested number of QWORDs.
4511 """
4512 stackData = self.peek_stack_data(count * 8, offset)
4513 if len(stackData) & 7:
4514 stackData = stackData[:-len(stackData) & 7]
4515 if not stackData:
4516 return ()
4517 return struct.unpack('<'+('Q'*count), stackData)
4518
4520 """
4521 Tries to read some bytes of the code currently being executed.
4522
4523 @type size: int
4524 @param size: Number of bytes to read.
4525
4526 @type offset: int
4527 @param offset: Offset from the program counter to begin reading.
4528
4529 @rtype: str
4530 @return: Bytes read from the process memory.
4531
4532 @raise WindowsError: Could not read the requested data.
4533 """
4534 return self.get_process().read(self.get_pc() + offset, size)
4535
4537 """
4538 Tries to read some bytes of the code currently being executed.
4539
4540 @type size: int
4541 @param size: Number of bytes to read.
4542
4543 @type offset: int
4544 @param offset: Offset from the program counter to begin reading.
4545
4546 @rtype: str
4547 @return: Bytes read from the process memory.
4548 May be less than the requested number of bytes.
4549 """
4550 return self.get_process().peek(self.get_pc() + offset, size)
4551
4553 """
4554 Tries to guess which values in the registers are valid pointers,
4555 and reads some data from them.
4556
4557 @type peekSize: int
4558 @param peekSize: Number of bytes to read from each pointer found.
4559
4560 @type context: dict( str S{->} int )
4561 @param context: (Optional)
4562 Dictionary mapping register names to their values.
4563 If not given, the current thread context will be used.
4564
4565 @rtype: dict( str S{->} str )
4566 @return: Dictionary mapping register names to the data they point to.
4567 """
4568 peekable_registers = (
4569 'Eax', 'Ebx', 'Ecx', 'Edx', 'Esi', 'Edi', 'Ebp'
4570 )
4571 if not context:
4572 context = self.get_context(win32.CONTEXT_CONTROL | \
4573 win32.CONTEXT_INTEGER)
4574 aProcess = self.get_process()
4575 data = dict()
4576 for (reg_name, reg_value) in context.iteritems():
4577 if reg_name not in peekable_registers:
4578 continue
4579
4580
4581
4582
4583
4584
4585 reg_data = aProcess.peek(reg_value, peekSize)
4586 if reg_data:
4587 data[reg_name] = reg_data
4588 return data
4589
4590
4591
4593 """
4594 Tries to guess which values in the given data are valid pointers,
4595 and reads some data from them.
4596
4597 @type data: str
4598 @param data: Binary data to find pointers in.
4599
4600 @type peekSize: int
4601 @param peekSize: Number of bytes to read from each pointer found.
4602
4603 @type peekStep: int
4604 @param peekStep: Expected data alignment.
4605 Tipically you specify 1 when data alignment is unknown,
4606 or 4 when you expect data to be DWORD aligned.
4607 Any other value may be specified.
4608
4609 @rtype: dict( str S{->} str )
4610 @return: Dictionary mapping stack offsets to the data they point to.
4611 """
4612 aProcess = self.get_process()
4613 return aProcess.peek_pointers_in_data(data, peekSize, peekStep)
4614
4615
4616
4617
4618
4619
4620
4622 """
4623 Disassemble instructions from a block of binary code.
4624
4625 @type lpAddress: int
4626 @param lpAddress: Memory address where the code was read from.
4627
4628 @type code: str
4629 @param code: Binary code to disassemble.
4630
4631 @rtype: list of tuple( long, int, str, str )
4632 @return: List of tuples. Each tuple represents an assembly instruction
4633 and contains:
4634 - Memory address of instruction.
4635 - Size of instruction in bytes.
4636 - Disassembly line of instruction.
4637 - Hexadecimal dump of instruction.
4638 """
4639 aProcess = self.get_process()
4640 return aProcess.disassemble_string(lpAddress, code)
4641
4643 """
4644 Disassemble instructions from the address space of the process.
4645
4646 @type lpAddress: int
4647 @param lpAddress: Memory address where to read the code from.
4648
4649 @type dwSize: int
4650 @param dwSize: Size of binary code to disassemble.
4651
4652 @rtype: list of tuple( long, int, str, str )
4653 @return: List of tuples. Each tuple represents an assembly instruction
4654 and contains:
4655 - Memory address of instruction.
4656 - Size of instruction in bytes.
4657 - Disassembly line of instruction.
4658 - Hexadecimal dump of instruction.
4659 """
4660 aProcess = self.get_process()
4661 return aProcess.disassemble(lpAddress, dwSize)
4662
4664 """
4665 Disassemble around the given address.
4666
4667 @type lpAddress: int
4668 @param lpAddress: Memory address where to read the code from.
4669
4670 @type dwSize: int
4671 @param dwSize: Delta offset.
4672 Code will be read from lpAddress - dwSize to lpAddress + dwSize.
4673
4674 @rtype: list of tuple( long, int, str, str )
4675 @return: List of tuples. Each tuple represents an assembly instruction
4676 and contains:
4677 - Memory address of instruction.
4678 - Size of instruction in bytes.
4679 - Disassembly line of instruction.
4680 - Hexadecimal dump of instruction.
4681 """
4682 aProcess = self.get_process()
4683 return aProcess.disassemble_around(lpAddress, dwSize)
4684
4686 """
4687 Disassemble around the program counter of the given thread.
4688
4689 @type dwSize: int
4690 @param dwSize: Delta offset.
4691 Code will be read from pc - dwSize to pc + dwSize.
4692
4693 @rtype: list of tuple( long, int, str, str )
4694 @return: List of tuples. Each tuple represents an assembly instruction
4695 and contains:
4696 - Memory address of instruction.
4697 - Size of instruction in bytes.
4698 - Disassembly line of instruction.
4699 - Hexadecimal dump of instruction.
4700 """
4701 aProcess = self.get_process()
4702 return aProcess.disassemble_around(self.get_pc(), dwSize)
4703
4705 """
4706 Disassemble the instruction at the given memory address.
4707
4708 @type lpAddress: int
4709 @param lpAddress: Memory address where to read the code from.
4710
4711 @rtype: tuple( long, int, str, str )
4712 @return: The tuple represents an assembly instruction
4713 and contains:
4714 - Memory address of instruction.
4715 - Size of instruction in bytes.
4716 - Disassembly line of instruction.
4717 - Hexadecimal dump of instruction.
4718 """
4719 aProcess = self.get_process()
4720 return aProcess.disassemble(lpAddress, 15)[0]
4721
4723 """
4724 Disassemble the instruction at the program counter of the given thread.
4725
4726 @rtype: tuple( long, int, str, str )
4727 @return: The tuple represents an assembly instruction
4728 and contains:
4729 - Memory address of instruction.
4730 - Size of instruction in bytes.
4731 - Disassembly line of instruction.
4732 - Hexadecimal dump of instruction.
4733 """
4734 return self.disassemble_instruction(self.get_pc())
4735
4742 """
4743 Encapsulates several useful debugging routines for processes.
4744
4745 @group Properties:
4746 is_wow64, get_peb, get_peb_address,
4747 get_main_module, get_image_base, get_image_name,
4748 get_command_line, get_environment,
4749 get_command_line_block,
4750 get_environment_block, get_environment_data, parse_environment_data
4751
4752 @group Disassembly:
4753 disassemble, disassemble_around, disassemble_around_pc,
4754 disassemble_string, disassemble_instruction, disassemble_current
4755
4756 @group Debugging:
4757 flush_instruction_cache, debug_break, peek_pointers_in_data
4758 """
4759
4760
4761 __hexa_parameter = re.compile('0x[0-9A-Za-z]+')
4762
4764 """
4765 Private method used when disassembling from process memory.
4766
4767 It has no return value because the list is modified in place. On return
4768 all raw memory addresses are replaced by labels when possible.
4769
4770 @type disasm: list of tuple(int, int, str, str)
4771 @param disasm: Output of one of the dissassembly functions.
4772 """
4773 for index in xrange(len(disasm)):
4774 (address, size, text, dump) = disasm[index]
4775 m = self.__hexa_parameter.search(text)
4776 while m:
4777 s, e = m.span()
4778 value = text[s:e]
4779 try:
4780 label = self.get_label_at_address( int(value, 0x10) )
4781 except Exception, e:
4782 label = None
4783 if label:
4784 text = text[:s] + label + text[e:]
4785 e = s + len(value)
4786 m = self.__hexa_parameter.search(text, e)
4787 disasm[index] = (address, size, text, dump)
4788
4790 """
4791 Disassemble instructions from a block of binary code.
4792
4793 @type lpAddress: int
4794 @param lpAddress: Memory address where the code was read from.
4795
4796 @type code: str
4797 @param code: Binary code to disassemble.
4798
4799 @rtype: list of tuple( long, int, str, str )
4800 @return: List of tuples. Each tuple represents an assembly instruction
4801 and contains:
4802 - Memory address of instruction.
4803 - Size of instruction in bytes.
4804 - Disassembly line of instruction.
4805 - Hexadecimal dump of instruction.
4806
4807 @raise NotImplementedError:
4808 No compatible disassembler was found for the current platform.
4809 """
4810 if System.arch not in ('i386', 'amd64'):
4811 raise NotImplementedError
4812 if (not System.wow64 and System.bits == 32) or self.is_wow64():
4813 return Decode(lpAddress, code, Decode32Bits)
4814 return Decode(lpAddress, code, Decode64Bits)
4815
4817 """
4818 Disassemble instructions from the address space of the process.
4819
4820 @type lpAddress: int
4821 @param lpAddress: Memory address where to read the code from.
4822
4823 @type dwSize: int
4824 @param dwSize: Size of binary code to disassemble.
4825
4826 @rtype: list of tuple( long, int, str, str )
4827 @return: List of tuples. Each tuple represents an assembly instruction
4828 and contains:
4829 - Memory address of instruction.
4830 - Size of instruction in bytes.
4831 - Disassembly line of instruction.
4832 - Hexadecimal dump of instruction.
4833 """
4834 data = self.read(lpAddress, dwSize)
4835 disasm = self.disassemble_string(lpAddress, data)
4836 self.__fixup_labels(disasm)
4837 return disasm
4838
4839
4840
4842 """
4843 Disassemble around the given address.
4844
4845 @type lpAddress: int
4846 @param lpAddress: Memory address where to read the code from.
4847
4848 @type dwSize: int
4849 @param dwSize: Delta offset.
4850 Code will be read from lpAddress - dwSize to lpAddress + dwSize.
4851
4852 @rtype: list of tuple( long, int, str, str )
4853 @return: List of tuples. Each tuple represents an assembly instruction
4854 and contains:
4855 - Memory address of instruction.
4856 - Size of instruction in bytes.
4857 - Disassembly line of instruction.
4858 - Hexadecimal dump of instruction.
4859 """
4860 dwDelta = int(float(dwSize) / 2.0)
4861 addr_1 = lpAddress - dwDelta
4862 addr_2 = lpAddress
4863 size_1 = dwDelta
4864 size_2 = dwSize - dwDelta
4865 data = self.read(addr_1, dwSize)
4866 data_1 = data[:size_1]
4867 data_2 = data[size_1:]
4868 disasm_1 = self.disassemble_string(addr_1, data_1)
4869 disasm_2 = self.disassemble_string(addr_2, data_2)
4870 disasm = disasm_1 + disasm_2
4871 self.__fixup_labels(disasm)
4872 return disasm
4873
4875 """
4876 Disassemble around the program counter of the given thread.
4877
4878 @type dwThreadId: int
4879 @param dwThreadId: Global thread ID.
4880 The program counter for this thread will be used as the disassembly
4881 address.
4882
4883 @type dwSize: int
4884 @param dwSize: Delta offset.
4885 Code will be read from pc - dwSize to pc + dwSize.
4886
4887 @rtype: list of tuple( long, int, str, str )
4888 @return: List of tuples. Each tuple represents an assembly instruction
4889 and contains:
4890 - Memory address of instruction.
4891 - Size of instruction in bytes.
4892 - Disassembly line of instruction.
4893 - Hexadecimal dump of instruction.
4894 """
4895 aThread = self.get_thread(dwThreadId)
4896 return self.disassemble_around(aThread.get_pc(), dwSize)
4897
4899 """
4900 Disassemble the instruction at the given memory address.
4901
4902 @type lpAddress: int
4903 @param lpAddress: Memory address where to read the code from.
4904
4905 @rtype: tuple( long, int, str, str )
4906 @return: The tuple represents an assembly instruction
4907 and contains:
4908 - Memory address of instruction.
4909 - Size of instruction in bytes.
4910 - Disassembly line of instruction.
4911 - Hexadecimal dump of instruction.
4912 """
4913 return self.disassemble(lpAddress, 15)[0]
4914
4916 """
4917 Disassemble the instruction at the program counter of the given thread.
4918
4919 @type dwThreadId: int
4920 @param dwThreadId: Global thread ID.
4921 The program counter for this thread will be used as the disassembly
4922 address.
4923
4924 @rtype: tuple( long, int, str, str )
4925 @return: The tuple represents an assembly instruction
4926 and contains:
4927 - Memory address of instruction.
4928 - Size of instruction in bytes.
4929 - Disassembly line of instruction.
4930 - Hexadecimal dump of instruction.
4931 """
4932 aThread = self.get_thread(dwThreadId)
4933 return self.disassemble_instruction(aThread.get_pc())
4934
4935
4936
4938 """
4939 Flush the instruction cache. This is required if the process memory is
4940 modified and one or more threads are executing nearby the modified
4941 memory region.
4942
4943 @see: U{http://blogs.msdn.com/oldnewthing/archive/2003/12/08/55954.aspx#55958}
4944
4945 @raise WindowsError: Raises exception on error.
4946 """
4947 win32.FlushInstructionCache( self.get_handle() )
4948
4950 """
4951 Triggers the system breakpoint in the process.
4952
4953 @raise WindowsError: On error an exception is raised.
4954 """
4955
4956
4957
4958 win32.DebugBreakProcess( self.get_handle() )
4959
4961 """
4962 Determines if the process is running under WOW64.
4963
4964 @rtype: bool
4965 @return:
4966 C{True} if the process is running under WOW64. That is, a 32-bit
4967 application running in a 64-bit Windows.
4968
4969 C{False} if the process is either a 32-bit application running in
4970 a 32-bit Windows, or a 64-bit application running in a 64-bit
4971 Windows.
4972
4973 @raise WindowsError: On error an exception is raised.
4974
4975 @see: U{http://msdn.microsoft.com/en-us/library/aa384249(VS.85).aspx}
4976 """
4977 hProcess = self.get_handle()
4978 try:
4979 return win32.IsWow64Process(hProcess)
4980 except AttributeError:
4981 return False
4982
4983
4984
4986 """
4987 Returns a copy of the PEB.
4988 To dereference pointers in it call L{Process.read_structure}.
4989
4990 @rtype: L{win32.PEB}
4991 @return: PEB structure.
4992 @raise WindowsError: An exception is raised on error.
4993 """
4994 return self.read_structure(self.get_peb_address(), win32.PEB)
4995
5007
5008 - def get_main_module(self):
5009 """
5010 @rtype: L{Module}
5011 @return: Module object for the process main module.
5012 """
5013 return self.get_module(self.get_image_base())
5014
5016 """
5017 @rtype: int
5018 @return: Image base address for the process main module.
5019 """
5020 return self.get_peb().ImageBaseAddress
5021
5023 """
5024 @rtype: int
5025 @return: Filename of the process main module.
5026
5027 This method does it's best to retrieve the filename.
5028 However sometimes this is not possible, so C{None} may
5029 be returned instead.
5030 """
5031
5032
5033
5034
5035
5036 try:
5037 mainModule = self.get_main_module()
5038 name = mainModule.fileName
5039 if not name:
5040 name = None
5041 except (KeyError, AttributeError, WindowsError):
5042 name = None
5043
5044
5045
5046 if not name:
5047 try:
5048 name = win32.QueryFullProcessImageName(self.get_handle())
5049 except (AttributeError, WindowsError):
5050 name = None
5051
5052
5053
5054
5055
5056 if not name:
5057 try:
5058 name = win32.GetProcessImageFileName(self.get_handle())
5059 if name:
5060 name = PathOperations.native_to_win32_pathname(name)
5061 else:
5062 name = None
5063 except (AttributeError, WindowsError):
5064 if not name:
5065 name = None
5066
5067
5068
5069
5070
5071
5072 if not name:
5073 try:
5074 try:
5075 name = win32.GetModuleFileNameEx(self.get_handle())
5076 except WindowsError:
5077 name = win32.GetModuleFileNameEx(self.get_handle(),
5078 self.get_image_base())
5079 if name:
5080 name = PathOperations.native_to_win32_pathname(name)
5081 else:
5082 name = None
5083 except (AttributeError, WindowsError):
5084 if not name:
5085 name = None
5086
5087
5088
5089
5090
5091
5092
5093 if not name:
5094 try:
5095 peb = self.get_peb()
5096 pp = self.read_structure(peb.ProcessParameters,
5097 win32.RTL_USER_PROCESS_PARAMETERS)
5098 s = pp.ImagePathName
5099 name = self.peek_string(s.Buffer,
5100 dwMaxSize=s.MaximumLength, fUnicode=True)
5101 if name:
5102 name = PathOperations.native_to_win32_pathname(name)
5103 else:
5104 name = None
5105 except (AttributeError, WindowsError):
5106 name = None
5107
5108
5109
5110
5111
5112
5113
5114 if not name:
5115 if vars().has_key('mainModule'):
5116 try:
5117 name = mainModule.get_filename()
5118 if not name:
5119 name = None
5120 except (AttributeError, WindowsError):
5121 name = None
5122
5123
5124 if name:
5125 try:
5126 mainModule.fileName = name
5127 except UnboundLocalError:
5128 pass
5129
5130
5131 return name
5132
5148
5150 """
5151 Retrieves the environment block memory address for the process.
5152
5153 @note: The size is always C{None} on Windows XP and below.
5154
5155 @rtype: tuple(int, int)
5156 @return: Tuple with the memory address of the environment block
5157 and it's size.
5158
5159 @raise WindowsError: On error an exception is raised.
5160 """
5161 peb = self.get_peb()
5162 pp = self.read_structure(peb.ProcessParameters,
5163 win32.RTL_USER_PROCESS_PARAMETERS)
5164 Environment = pp.Environment
5165 try:
5166 EnvironmentSize = pp.EnvironmentSize
5167 except AttributeError:
5168 EnvironmentSize = None
5169
5170 return (Environment, EnvironmentSize)
5171
5188
5190 """
5191 Retrieves the environment block data with wich the program is running.
5192
5193 @rtype: list of str
5194 @return: Environment keys and values separated by a C{=} character,
5195 as found in the process memory.
5196
5197 @raise WindowsError: On error an exception is raised.
5198 """
5199 block = list()
5200 address, size = self.get_environment_block()
5201 char_size = ctypes.sizeof(win32.WCHAR)
5202
5203
5204 if size:
5205 data = self.peek(address, size)
5206 while data:
5207 chunk = ctypes.create_unicode_string(data).value
5208 if not chunk:
5209 break
5210 block.append(chunk)
5211 data = data[ (len(chunk) + 1) * char_size : ]
5212
5213
5214
5215
5216 else:
5217 while 1:
5218 chunk = self.peek_string(address, dwMaxSize = System.pageSize,
5219 fUnicode = True)
5220 print "Chunk: ",
5221 print chunk
5222 if not chunk:
5223 break
5224 block.append(chunk)
5225 address += (len(chunk) + 1) * char_size
5226
5227
5228 return block
5229
5230 @staticmethod
5232 """
5233 Parse the environment block into a Python dictionary.
5234
5235 @note: Duplicated keys are joined using null characters.
5236
5237 @type block: list of str
5238 @param block: List of Unicode strings as returned by
5239 L{get_environment_data}.
5240
5241 @rtype: dict(str S{->} str)
5242 @return: Dictionary of environment keys and values.
5243 """
5244 environment = dict()
5245
5246
5247 for chunk in block:
5248 sep = chunk.find(u'=')
5249 if sep >= 0:
5250 key, value = chunk[:sep], chunk[sep:]
5251 else:
5252 key, value = chunk, u''
5253 if not environment.has_key(key):
5254 environment[key] = value
5255 else:
5256 environment[key] += u'\0' + value
5257
5258
5259 gst = win32.GuessStringType
5260 if gst.t_default == gst.t_ansi:
5261 environment = dict( [ (str(key), str(value)) \
5262 for (key, value) in environment.iteritems() ] )
5263
5264
5265 return environment
5266
5268 """
5269 Retrieves the environment with wich the program is running.
5270
5271 @note: Duplicated keys are joined using null characters.
5272
5273 @rtype: dict(str S{->} str)
5274 @return: Dictionary of environment keys and values.
5275
5276 @raise WindowsError: On error an exception is raised.
5277 """
5278 return self.parse_environment_block( self.get_environment_data() )
5279
5280
5281
5282
5283
5285 """
5286 Tries to guess which values in the given data are valid pointers,
5287 and reads some data from them.
5288
5289 @type data: str
5290 @param data: Binary data to find pointers in.
5291
5292 @type peekSize: int
5293 @param peekSize: Number of bytes to read from each pointer found.
5294
5295 @type peekStep: int
5296 @param peekStep: Expected data alignment.
5297 Tipically you specify 1 when data alignment is unknown,
5298 or 4 when you expect data to be DWORD aligned.
5299 Any other value may be specified.
5300
5301 @rtype: dict( str S{->} str )
5302 @return: Dictionary mapping stack offsets to the data they point to.
5303 """
5304 result = dict()
5305 ptrSize = win32.sizeof(win32.LPVOID)
5306 if ptrSize == 4:
5307 ptrFmt = '<L'
5308 else:
5309 ptrFmt = '<Q'
5310 if len(data) > 0:
5311 for i in xrange(0, len(data), peekStep):
5312 packed = data[i:i+ptrSize]
5313 if len(packed) == ptrSize:
5314 address = struct.unpack(ptrFmt, packed)[0]
5315
5316 peek_data = self.peek(address, peekSize)
5317 if peek_data:
5318 result[i] = peek_data
5319 return result
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341 -class Window (object):
5342 """
5343 Interface to an open window in the current desktop.
5344
5345 @group Properties:
5346 hWnd, dwProcessId, dwThreadId,
5347 get_handle, get_pid, get_tid,
5348 get_process, get_thread,
5349 set_process, set_thread,
5350 get_classname, get_text, set_text, get_placement, set_placement,
5351 screen_to_client, client_to_screen
5352
5353 @group State:
5354 is_valid, is_visible, is_enabled, is_maximized, is_minimized, is_child,
5355 is_zoomed, is_iconic
5356
5357 @group Navigation:
5358 get_parent, get_children, get_root, get_tree,
5359 get_child_at
5360
5361 @group Instrumentation:
5362 enable, disable, show, hide, maximize, minimize, restore, move, kill
5363
5364 @group Low-level access:
5365 send, post
5366
5367 @type hWnd: int
5368 @ivar hWnd: Window handle.
5369
5370 @type dwProcessId: int
5371 @ivar dwProcessId: Global ID of the process that owns this window.
5372
5373 @type dwThreadId: int
5374 @ivar dwThreadId: Global ID of the thread that owns this window.
5375
5376 @type process: L{Process}
5377 @ivar process: Process that owns this window.
5378 Use the L{get_process} method instead.
5379
5380 @type thread: L{Thread}
5381 @ivar thread: Thread that owns this window.
5382 Use the L{get_thread} method instead.
5383 """
5384
5385 - def __init__(self, hWnd = None, process = None, thread = None):
5386 """
5387 @type hWnd: int or L{win32.HWND}
5388 @param hWnd: Window handle.
5389
5390 @type process: L{Process}
5391 @param process: (Optional) Process that owns this window.
5392
5393 @type thread: L{Thread}
5394 @param thread: (Optional) Thread that owns this window.
5395 """
5396 self.hWnd = hWnd
5397 self.dwProcessId = None
5398 self.dwThreadId = None
5399 self.set_process(process)
5400 self.set_thread(thread)
5401
5402 @property
5404 """
5405 Compatibility with ctypes.
5406 Allows passing transparently a Window object to an API call.
5407 """
5408 return self.get_handle()
5409
5411 """
5412 @rtype: int
5413 @return: Window handle.
5414 @raise ValueError: No window handle set.
5415 """
5416 if self.hWnd is None:
5417 raise ValueError, "No window handle set!"
5418 return self.hWnd
5419
5429
5439
5444
5446 """
5447 @rtype: L{Process}
5448 @return: Parent Process object.
5449 Returns C{None} if unknown.
5450 """
5451 if self.__process is not None:
5452
5453
5454
5455
5456
5457
5458
5459 return self.__process
5460
5461 self.__process = Process(self.get_pid())
5462 return self.__process
5463
5465 """
5466 Manually set the parent process. Use with care!
5467
5468 @type process: L{Process}
5469 @param process: (Optional) Process object. Use C{None} for no process.
5470 """
5471 if process is None:
5472 self.__process = None
5473 else:
5474 if not isinstance(process, Process):
5475 msg = "Parent process must be a Process instance, "
5476 msg += "got %s instead" % type(process)
5477 raise TypeError, msg
5478 self.dwProcessId = process.get_pid()
5479
5480 self.__process = process
5481
5482
5483
5484 tmp = get_process.__doc__, set_process.__doc__
5485 del get_process.__doc__
5486 del set_process.__doc__
5487 process = property(get_process, set_process)
5488 get_process.__doc__, set_process.__doc__ = tmp
5489 del tmp
5490
5492 """
5493 @rtype: L{Thread}
5494 @return: Parent Thread object.
5495 Returns C{None} if unknown.
5496 """
5497 if self.__thread is not None:
5498
5499
5500
5501
5502
5503
5504
5505 return self.__thread
5506
5507 self.__thread = Thread(self.get_pid())
5508 return self.__thread
5509
5511 """
5512 Manually set the thread process. Use with care!
5513
5514 @type thread: L{Thread}
5515 @param thread: (Optional) Thread object. Use C{None} for no thread.
5516 """
5517 if thread is None:
5518 self.__thread = None
5519 else:
5520 if not isinstance(thread, Thread):
5521 msg = "Parent thread must be a Thread instance, "
5522 msg += "got %s instead" % type(thread)
5523 raise TypeError, msg
5524 self.dwThreadId = thread.get_tid()
5525
5526 self.__thread = thread
5527
5528
5529
5530 tmp = get_thread.__doc__, set_thread.__doc__
5531 del get_thread.__doc__
5532 del set_thread.__doc__
5533 thread = property(get_thread, set_thread)
5534 get_thread.__doc__, set_thread.__doc__ = tmp
5535 del tmp
5536
5548
5549
5550
5552 """
5553 @rtype: str
5554 @return: Window class name.
5555 @raise WindowsError: An error occured while processing this request.
5556 """
5557 return win32.GetClassName( self.get_handle() )
5558
5559 - def get_text(self):
5560 """
5561 @see: L{set_text}
5562 @rtype: str
5563 @return: Window text (caption).
5564 """
5565 length = self.send(win32.WM_GETTEXTLENGTH)
5566 if not length:
5567 raise ctypes.WinError()
5568 length = length + 1
5569 c_buffer = ctypes.create_string_buffer("", length)
5570 success = self.send(win32.WM_GETTEXT, length, c_buffer)
5571 if success == 0:
5572 return ""
5573 return c_buffer.value
5574
5575 - def set_text(self, text):
5576 """
5577 Set the window text (caption).
5578
5579 @see: L{get_text}
5580
5581 @type text: str
5582 @param text: New window text.
5583 """
5584 return self.send(win32.WM_SETTEXT, len(text), text)
5585
5587 """
5588 Retrieve the window placement in the desktop.
5589
5590 @see: L{set_placement}
5591
5592 @rtype: L{win32.WindowPlacement}
5593 @return: Window placement in the desktop.
5594 """
5595 return win32.GetWindowPlacement( self.get_handle() )
5596
5598 """
5599 Set the window placement in the desktop.
5600
5601 @see: L{get_placement}
5602
5603 @type placement: L{win32.WindowPlacement}
5604 @param placement: Window placement in the desktop.
5605
5606 @raise WindowsError: An error occured while processing this request.
5607 """
5608 win32.SetWindowPlacement( self.get_handle(), placement )
5609
5610
5611
5612
5613
5614
5615
5616
5618 """
5619 Translates window client coordinates to screen coordinates.
5620
5621 @note: This is a simplified interface to some of the functionality of
5622 the L{win32.Point} class.
5623
5624 @see: {win32.Point.client_to_screen}
5625
5626 @type x: int
5627 @param x: Horizontal coordinate.
5628 @type y: int
5629 @param y: Vertical coordinate.
5630
5631 @rtype: tuple( int, int )
5632 @return: Translated coordinates in a tuple (x, y).
5633
5634 @raise WindowsError: An error occured while processing this request.
5635 """
5636 return tuple( ClientToScreen( self.get_handle(), (x, y) ) )
5637
5639 """
5640 Translates window screen coordinates to client coordinates.
5641
5642 @note: This is a simplified interface to some of the functionality of
5643 the L{win32.Point} class.
5644
5645 @see: {win32.Point.screen_to_client}
5646
5647 @type x: int
5648 @param x: Horizontal coordinate.
5649 @type y: int
5650 @param y: Vertical coordinate.
5651
5652 @rtype: tuple( int, int )
5653 @return: Translated coordinates in a tuple (x, y).
5654
5655 @raise WindowsError: An error occured while processing this request.
5656 """
5657 return tuple( ScreenToClient( self.get_handle(), (x, y) ) )
5658
5659
5660
5662 """
5663 @see: L{get_children}
5664 @rtype: L{Window} or None
5665 @return: Parent window. Returns C{None} if the window has no parent.
5666 @raise WindowsError: An error occured while processing this request.
5667 """
5668 hWnd = win32.GetParent( self.get_handle() )
5669 if hWnd:
5670 return self.__get_window(hWnd)
5671
5673 """
5674 @see: L{get_parent}
5675 @rtype: list( L{Window} )
5676 @return: List of child windows.
5677 @raise WindowsError: An error occured while processing this request.
5678 """
5679 return [
5680 self.__get_window(hWnd) \
5681 for hWnd in win32.EnumChildWindows( self.get_handle() )
5682 ]
5683
5685 """
5686 @see: L{get_root}
5687 @rtype: dict( L{Window} S{->} dict( ... ) )
5688 @return: Dictionary of dictionaries forming a tree of child windows.
5689 @raise WindowsError: An error occured while processing this request.
5690 """
5691 subtree = dict()
5692 for aWindow in self.get_children():
5693 subtree[ aWindow ] = aWindow.get_tree()
5694 return subtree
5695
5697 """
5698 @see: L{get_tree}
5699 @rtype: L{Window}
5700 @return: Root window for this tree.
5701 @raise RuntimeError: Can't find the root window for this tree.
5702 @raise WindowsError: An error occured while processing this request.
5703 """
5704 hWnd = self.get_handle()
5705 history = set()
5706 hPrevWnd = hWnd
5707 while hWnd and hWnd not in history:
5708 history.add(hWnd)
5709 hPrevWnd = hWnd
5710 hWnd = win32.GetParent(hWnd)
5711 if hWnd in history:
5712
5713 raise RuntimeError, "Can't find the root window for this tree"
5714 if hPrevWnd != self.hWnd:
5715 return self.__get_window(hPrevWnd)
5716 return self
5717
5719 """
5720 Get the child window located at the given coordinates. If no such
5721 window exists an exception is raised.
5722
5723 @see: L{get_children}
5724
5725 @type x: int
5726 @param x: Horizontal coordinate.
5727 @type y: int
5728 @param y: Vertical coordinate.
5729
5730 @rtype: L{Window}
5731 @return: Child window at the requested position. If no such window
5732 exists a C{WindowsError} exception is raised.
5733
5734 @raise WindowsError: An error occured while processing this request.
5735 """
5736 win32.ChildWindowFromPoint( self.get_handle(), (x, y) )
5737
5738
5739
5740
5742 """
5743 @rtype: bool
5744 @return: C{True} if the window handle is still valid.
5745 """
5746 return win32.IsWindow( self.get_handle() )
5747
5749 """
5750 @see: {show}, {hide}
5751 @rtype: bool
5752 @return: C{True} if the window is in a visible state.
5753 """
5754 return win32.IsWindowVisible( self.get_handle() )
5755
5757 """
5758 @see: {enable}, {disable}
5759 @rtype: bool
5760 @return: C{True} if the window is in an enabled state.
5761 """
5762 return win32.IsWindowEnabled( self.get_handle() )
5763
5765 """
5766 @see: L{maximize}
5767 @rtype: bool
5768 @return: C{True} if the window is maximized.
5769 """
5770 return win32.IsZoomed( self.get_handle() )
5771
5773 """
5774 @see: L{minimize}
5775 @rtype: bool
5776 @return: C{True} if the window is minimized.
5777 """
5778 return win32.IsIconic( self.get_handle() )
5779
5781 """
5782 @see: L{get_parent}
5783 @rtype: bool
5784 @return: C{True} if the window is a child window.
5785 """
5786 return win32.IsChild( self.get_handle() )
5787
5788 is_zoomed = is_maximized
5789 is_iconic = is_minimized
5790
5791
5792
5794 """
5795 Enable the user input for the window.
5796
5797 @see: L{disable}
5798
5799 @raise WindowsError: An error occured while processing this request.
5800 """
5801 win32.EnableWindow( self.get_handle(), True )
5802
5804 """
5805 Disable the user input for the window.
5806
5807 @see: L{enable}
5808
5809 @raise WindowsError: An error occured while processing this request.
5810 """
5811 win32.EnableWindow( self.get_handle(), False )
5812
5813 - def show(self, bAsync = True):
5828
5829 - def hide(self, bAsync = True):
5844
5860
5876
5877 - def restore(self, bAsync = True):
5892
5893 - def move(self, x, y, width, height, bRepaint = True):
5894 """
5895 Moves and/or resizes the window.
5896
5897 @note: This is request is performed syncronously.
5898
5899 @type x: int
5900 @param x: New horizontal coordinate.
5901
5902 @type y: int
5903 @param y: New vertical coordinate.
5904
5905 @type width: int
5906 @param width: Desired window width.
5907
5908 @type height: int
5909 @param height: Desired window height.
5910
5911 @type bRepaint: bool
5912 @param bRepaint: C{True} if the window should be redrawn afterwards.
5913
5914 @raise WindowsError: An error occured while processing this request.
5915 """
5916
5917
5918 win32.MoveWindow(self.get_handle(), x, y, width, height, bRepaint)
5919
5921 """
5922 Signals the program to quit.
5923
5924 @note: This is an asyncronous request.
5925
5926 @raise WindowsError: An error occured while processing this request.
5927 """
5928 self.post(win32.WM_QUIT)
5929
5930 - def send(self, uMsg, wParam = None, lParam = None):
5931 """
5932 Send a low-level window message syncronically.
5933
5934 @type uMsg: int
5935 @param uMsg: Message code.
5936
5937 @param wParam:
5938 The type and meaning of this parameter depends on the message.
5939
5940 @param lParam:
5941 The type and meaning of this parameter depends on the message.
5942
5943 @rtype: int
5944 @return: The meaning of the return value depends on the window message.
5945 Typically a value of C{0} means an error occured. You can get the
5946 error code by calling L{win32.GetLastError}.
5947 """
5948 return win32.SendMessage(self.get_handle(), uMsg, wParam, lParam)
5949
5950 - def post(self, uMsg, wParam = None, lParam = None):
5951 """
5952 Post a low-level window message asyncronically.
5953
5954 @type uMsg: int
5955 @param uMsg: Message code.
5956
5957 @param wParam:
5958 The type and meaning of this parameter depends on the message.
5959
5960 @param lParam:
5961 The type and meaning of this parameter depends on the message.
5962
5963 @raise WindowsError: An error occured while sending the message.
5964 """
5965 win32.PostMessage(self.get_handle(), uMsg, wParam, lParam)
5966
5967
5968
5969 -class Module (SymbolContainer):
5970 """
5971 Interface to a DLL library loaded in the context of another process.
5972
5973 @group Properties:
5974 get_base, get_filename, get_name, get_size, get_entry_point,
5975 get_process, set_process, get_pid
5976
5977 @group Labels:
5978 get_label, get_label_at_address, is_address_here,
5979 resolve, resolve_label, match_name
5980
5981 @group Handle:
5982 get_handle, open_handle, close_handle
5983
5984 @type unknown: str
5985 @cvar unknown: Suggested tag for unknown modules.
5986
5987 @type lpBaseOfDll: int
5988 @ivar lpBaseOfDll: Base of DLL module.
5989 Use L{get_base} instead.
5990
5991 @type hFile: L{FileHandle}
5992 @ivar hFile: Handle to the module file.
5993 Use L{get_handle} instead.
5994
5995 @type fileName: str
5996 @ivar fileName: Module filename.
5997 Use L{get_filename} instead.
5998
5999 @type SizeOfImage: int
6000 @ivar SizeOfImage: Size of the module.
6001 Use L{get_size} instead.
6002
6003 @type EntryPoint: int
6004 @ivar EntryPoint: Entry point of the module.
6005 Use L{get_entry_point} instead.
6006
6007 @type process: L{Process}
6008 @ivar process: Process where the module is loaded.
6009 Use the L{get_process} method instead.
6010 """
6011
6012 unknown = '<unknown>'
6013
6014 - def __init__(self, lpBaseOfDll, hFile = None, fileName = None,
6015 SizeOfImage = None,
6016 EntryPoint = None,
6017 process = None):
6018 """
6019 @type lpBaseOfDll: str
6020 @param lpBaseOfDll: Base address of the module.
6021
6022 @type hFile: L{FileHandle}
6023 @param hFile: (Optional) Handle to the module file.
6024
6025 @type fileName: str
6026 @param fileName: (Optional) Module filename.
6027
6028 @type SizeOfImage: int
6029 @param SizeOfImage: (Optional) Size of the module.
6030
6031 @type EntryPoint: int
6032 @param EntryPoint: (Optional) Entry point of the module.
6033
6034 @type process: L{Process}
6035 @param process: (Optional) Process where the module is loaded.
6036 """
6037 super(Module, self).__init__()
6038 self.lpBaseOfDll = lpBaseOfDll
6039 self.hFile = hFile
6040 self.fileName = fileName
6041 self.SizeOfImage = SizeOfImage
6042 self.EntryPoint = EntryPoint
6043 self.set_process(process)
6044
6045
6046
6047
6048
6049
6050
6051
6052
6053
6054
6055
6056
6057
6058
6059
6060
6061
6063 """
6064 @rtype: L{Process}
6065 @return: Parent Process object.
6066 Returns C{None} if unknown.
6067 """
6068 if self.__process is not None:
6069
6070
6071
6072
6073
6074
6075
6076 return self.__process
6077
6078 return None
6079
6081 """
6082 Manually set the parent process. Use with care!
6083
6084 @type process: L{Process}
6085 @param process: (Optional) Process object. Use C{None} for no process.
6086 """
6087 if process is None:
6088 self.__process = None
6089 else:
6090 if not isinstance(process, Process):
6091 msg = "Parent process must be a Process instance, "
6092 msg += "got %s instead" % type(process)
6093 raise TypeError, msg
6094
6095 self.__process = process
6096
6097
6098
6099 tmp = get_process.__doc__, set_process.__doc__
6100 del get_process.__doc__
6101 del set_process.__doc__
6102 process = property(get_process, set_process)
6103 get_process.__doc__, set_process.__doc__ = tmp
6104 del tmp
6105
6107 """
6108 @rtype: int or None
6109 @return: Parent process global ID.
6110 Returns C{None} on error.
6111 """
6112 process = self.get_process()
6113 if process is not None:
6114 return process.get_pid()
6115
6117 """
6118 @rtype: int or None
6119 @return: Base address of the module.
6120 Returns C{None} if unknown.
6121 """
6122 return self.lpBaseOfDll
6123
6133
6134 - def get_entry_point(self):
6135 """
6136 @rtype: int or None
6137 @return: Entry point of the module.
6138 Returns C{None} if unknown.
6139 """
6140 if not self.EntryPoint:
6141 self.__get_size_and_entry_point()
6142 return self.EntryPoint
6143
6145 "Get the size and entry point of the module using the Win32 API."
6146 process = self.get_process()
6147 if process:
6148 try:
6149 handle = process.get_handle()
6150 base = self.get_base()
6151 mi = win32.GetModuleInformation(handle, base)
6152 self.SizeOfImage = mi.SizeOfImage
6153 self.EntryPoint = mi.EntryPoint
6154 except WindowsError:
6155
6156 pass
6157
6171
6173 """
6174 @type pathname: str
6175 @param pathname: Pathname to a module.
6176
6177 @rtype: str
6178 @return: Module name.
6179 """
6180 filename = PathOperations.pathname_to_filename(pathname)
6181 if filename:
6182 filename = filename.lower()
6183 filepart, extpart = PathOperations.split_extension(filename)
6184 if filepart and extpart:
6185 modName = filepart
6186 else:
6187 modName = filename
6188 else:
6189 modName = pathname
6190 return modName
6191
6193 """
6194 @rtype: str
6195 @return: Module name, as used in labels.
6196
6197 @warning: Names are B{NOT} guaranteed to be unique.
6198
6199 If you need unique identification for a loaded module,
6200 use the base address instead.
6201
6202 @see: L{get_label}
6203 """
6204 pathname = self.get_filename()
6205 if pathname:
6206 modName = self.__filename_to_modname(pathname)
6207 else:
6208 modName = "0x%x" % self.get_base()
6209 return modName
6210
6212 """
6213 @rtype: bool
6214 @return:
6215 C{True} if the given name could refer to this module.
6216 It may not be exactly the same returned by L{get_name}.
6217 """
6218
6219
6220
6221 my_name = self.get_name().lower()
6222 if name.lower() == my_name:
6223 return True
6224
6225
6226 try:
6227 base = HexInput.integer(name)
6228 except ValueError:
6229 base = None
6230 if base is not None and base == self.get_base():
6231 return True
6232
6233
6234
6235 modName = self.__filename_to_modname(name)
6236 if modName.lower() == my_name:
6237 return True
6238
6239
6240 return False
6241
6242
6243
6266
6268 """
6269 Closes the handle to the module.
6270
6271 @note: Normally you don't need to call this method. All handles
6272 created by I{WinAppDbg} are automatically closed when the garbage
6273 collector claims them. So unless you've been tinkering with it,
6274 setting L{hFile} to C{None} should be enough.
6275 """
6276 try:
6277 if hasattr(self.hFile, 'close'):
6278 self.hFile.close()
6279 elif self.hFile not in (None, win32.INVALID_HANDLE_VALUE):
6280 win32.CloseHandle(self.hFile)
6281 finally:
6282 self.hFile = None
6283
6292
6293
6294
6295 - def get_label(self, function = None, offset = None):
6296 """
6297 Retrieves the label for the given function of this module or the module
6298 base address if no function name is given.
6299
6300 @type function: str
6301 @param function: (Optional) Exported function name.
6302
6303 @type offset: int
6304 @param offset: (Optional) Offset from the module base address.
6305
6306 @rtype: str
6307 @return: Label for the module base address, plus the offset if given.
6308 """
6309 return SymbolOperations.parse_label(self.get_name(), function, offset)
6310
6312 """
6313 Creates a label from the given memory address.
6314
6315 If the address belongs to the module, the label is made relative to
6316 it's base address.
6317
6318 @type address: int
6319 @param address: Memory address.
6320
6321 @type offset: None or int
6322 @param offset: (Optional) Offset value.
6323
6324 @rtype: str
6325 @return: Label pointing to the given address.
6326 """
6327
6328
6329 if offset:
6330 address = address + offset
6331
6332
6333 module = self.get_name()
6334 function = None
6335 offset = address - self.get_base()
6336
6337
6338
6339 start = self.get_entry_point()
6340 if start and start <= address:
6341 function = "start"
6342 offset = address - start
6343
6344
6345
6346 try:
6347 symbol = self.get_symbol_at_address(address)
6348 if symbol:
6349 (SymbolName, SymbolAddress, SymbolSize) = symbol
6350 new_offset = address - SymbolAddress
6351 if new_offset <= offset:
6352 function = SymbolName
6353 offset = new_offset
6354 except WindowsError, e:
6355 pass
6356
6357
6358 return SymbolOperations.parse_label(module, function, offset)
6359
6361 """
6362 Tries to determine if the given address belongs to this module.
6363
6364 @type address: int
6365 @param address: Memory address.
6366
6367 @rtype: bool or None
6368 @return: C{True} if the address belongs to the module,
6369 C{False} if it doesn't,
6370 and C{None} if it can't be determined.
6371 """
6372 base = self.get_base()
6373 size = self.get_size()
6374 if base and size:
6375 return base <= address < (base + size)
6376 return None
6377
6379 """
6380 Resolves a function exported by this module.
6381
6382 @type function: str or int
6383 @param function:
6384 str: Name of the function.
6385 int: Ordinal of the function.
6386
6387 @rtype: int
6388 @return: Memory address of the exported function in the process.
6389 Returns None on error.
6390 """
6391
6392
6393 filename = self.get_filename()
6394 if not filename:
6395 return None
6396
6397
6398 try:
6399 hlib = win32.GetModuleHandle(filename)
6400 address = win32.GetProcAddress(hlib, function)
6401 except WindowsError, e:
6402
6403
6404 try:
6405 hlib = win32.LoadLibraryEx(filename,
6406 win32.DONT_RESOLVE_DLL_REFERENCES)
6407 try:
6408 address = win32.GetProcAddress(hlib, function)
6409 finally:
6410 win32.FreeLibrary(hlib)
6411 except WindowsError, e:
6412 return None
6413
6414
6415 if address in (None, 0):
6416 return None
6417
6418
6419 return address - hlib + self.lpBaseOfDll
6420
6422 """
6423 Resolves a label for this module only. If the label refers to another
6424 module, an exception is raised.
6425
6426 @type label: str
6427 @param label: Label to resolve.
6428
6429 @rtype: int
6430 @return: Memory address pointed to by the label.
6431
6432 @raise ValueError: The label is malformed or impossible to resolve.
6433 @raise RuntimeError: Cannot resolve the module or function.
6434 """
6435
6436
6437
6438 aProcess = self.get_process()
6439 if aProcess is not None:
6440 (module, procedure, offset) = aProcess.split_label(label)
6441 else:
6442 (module, procedure, offset) = Process.split_label(label)
6443
6444
6445
6446 if module and not self.match_name(module):
6447 raise RuntimeError, "Label does not belong to this module"
6448
6449
6450 if procedure:
6451 address = self.resolve(procedure)
6452 if address is None:
6453
6454
6455 address = self.resolve_symbol(procedure)
6456
6457
6458 if address is None and procedure == "start":
6459 address = self.get_entry_point()
6460
6461
6462 if address is None:
6463 if not module:
6464 module = self.get_name()
6465 msg = "Can't find procedure %s in module %s"
6466 msg = msg % (procedure, module)
6467 raise RuntimeError, msg
6468
6469
6470 else:
6471 address = self.get_base()
6472
6473
6474 if offset:
6475 address = address + offset
6476 return address
6477
6478
6479
6480 -class Thread (ThreadDebugOperations):
6481 """
6482 Interface to a thread in another process.
6483
6484 @group Properties:
6485 get_tid, get_pid, get_process, set_process, get_exit_code, is_alive,
6486 get_name, set_name, get_windows
6487 @group Instrumentation:
6488 suspend, resume, kill, wait
6489 @group Registers:
6490 get_context,
6491 get_register,
6492 get_flags, get_flag_value,
6493 get_pc, get_sp, get_fp,
6494 get_gp, get_rp,
6495 get_cf, get_df, get_sf, get_tf, get_zf,
6496 set_context,
6497 set_register,
6498 set_flags, set_flag_value,
6499 set_pc, set_sp, set_fp,
6500 set_gp, set_rp,
6501 set_cf, set_df, set_sf, set_tf, set_zf,
6502 clear_cf, clear_df, clear_sf, clear_tf, clear_zf,
6503 Flags
6504 @group Handle:
6505 get_handle, open_handle, close_handle
6506
6507 @type dwThreadId: int
6508 @ivar dwThreadId: Global thread ID. Use L{get_tid} instead.
6509
6510 @type hThread: L{ThreadHandle}
6511 @ivar hThread: Handle to the thread. Use L{get_handle} instead.
6512
6513 @type process: L{Process}
6514 @ivar process: Parent process object. Use L{get_process} instead.
6515
6516 @type pInjectedMemory: int
6517 @ivar pInjectedMemory: If the thread was created by L{Process.inject_code},
6518 this member contains a pointer to the memory buffer for the injected
6519 code. Otherwise it's C{None}.
6520
6521 The L{kill} method uses this member to free the buffer
6522 when the injected thread is killed.
6523 """
6524
6525 - def __init__(self, dwThreadId, hThread = None, process = None):
6526 """
6527 @type dwThreadId: int
6528 @param dwThreadId: Global thread ID.
6529
6530 @type hThread: L{ThreadHandle}
6531 @param hThread: (Optional) Handle to the thread.
6532
6533 @type process: L{Process}
6534 @param process: (Optional) Parent Process object.
6535 """
6536 super(Thread, self).__init__()
6537 self.dwProcessId = None
6538 self.dwThreadId = dwThreadId
6539 self.hThread = hThread
6540 self.pInjectedMemory = None
6541 self.set_name()
6542 self.set_process(process)
6543
6544
6545
6546
6547
6548
6549
6550
6551
6552
6553
6554
6555
6556
6557
6558
6559
6560
6561
6562
6564 """
6565 @rtype: L{Process}
6566 @return: Parent Process object.
6567 Returns C{None} if unknown.
6568 """
6569 if self.__process is not None:
6570
6571
6572
6573
6574
6575
6576
6577 return self.__process
6578
6579 self.__process = Process(self.get_pid())
6580 return self.__process
6581
6583 """
6584 Manually set the parent Process object. Use with care!
6585
6586 @type process: L{Process}
6587 @param process: (Optional) Process object. Use C{None} for no process.
6588 """
6589 if process is None:
6590 self.__process = None
6591 else:
6592 if not isinstance(process, Process):
6593 msg = "Parent process must be a Process instance, "
6594 msg += "got %s instead" % type(process)
6595 raise TypeError, msg
6596 self.dwProcessId = process.get_pid()
6597
6598 self.__process = process
6599
6600
6601
6602 tmp = get_process.__doc__, set_process.__doc__
6603 del get_process.__doc__
6604 del set_process.__doc__
6605 process = property(get_process, set_process)
6606 get_process.__doc__, set_process.__doc__ = tmp
6607 del tmp
6608
6631
6650
6652 """
6653 @rtype: int
6654 @return: Thread global ID.
6655 """
6656 return self.dwThreadId
6657
6659 """
6660 @rtype: str
6661 @return: Thread name, or C{None} if the thread is nameless.
6662 """
6663 return self.name
6664
6666 """
6667 Sets the thread's name.
6668
6669 @type name: str
6670 @param name: Thread name, or C{None} if the thread is nameless.
6671 """
6672 self.name = name
6673
6674
6675
6690
6692 """
6693 Closes the handle to the thread.
6694
6695 @note: Normally you don't need to call this method. All handles
6696 created by I{WinAppDbg} are automatically closed when the garbage
6697 collector claims them. So unless you've been tinkering with it,
6698 setting L{hThread} to C{None} should be enough.
6699 """
6700 try:
6701 if hasattr(self.hThread, 'close'):
6702 self.hThread.close()
6703 elif self.hThread not in (None, win32.INVALID_HANDLE_VALUE):
6704 win32.CloseHandle(self.hThread)
6705 finally:
6706 self.hThread = None
6707
6716
6717
6718
6719 - def wait(self, dwTimeout = None):
6720 """
6721 Waits for the thread to finish executing.
6722
6723 @type dwTimeout: int
6724 @param dwTimeout: (Optional) Timeout value in milliseconds.
6725 Use C{INFINITE} or C{None} for no timeout.
6726 """
6727 self.get_handle().wait(dwTimeout)
6728
6729 - def kill(self, dwExitCode = 0):
6730 """
6731 Terminates the thread execution.
6732
6733 @note: If the C{lpInjectedMemory} member contains a valid pointer,
6734 the memory is freed.
6735
6736 @type dwExitCode: int
6737 @param dwExitCode: (Optional) Thread exit code.
6738 """
6739 win32.TerminateThread(self.get_handle(), dwExitCode)
6740 if self.pInjectedMemory is not None:
6741 try:
6742 self.get_process().free(self.pInjectedMemory)
6743 self.pInjectedMemory = None
6744 except Exception:
6745
6746 pass
6747
6748
6749
6750
6751
6753 """
6754 Suspends the thread execution.
6755
6756 @rtype: int
6757 @return: Suspend count. If zero, the thread is running.
6758 """
6759 return win32.SuspendThread(self.get_handle())
6760
6762 """
6763 Resumes the thread execution.
6764
6765 @rtype: int
6766 @return: Suspend count. If zero, the thread is running.
6767 """
6768 return win32.ResumeThread(self.get_handle())
6769
6771 """
6772 @rtype: bool
6773 @return: C{True} if the thread if currently running.
6774 """
6775 try:
6776 hProcess = self.get_handle()
6777 except WindowsError:
6778 return False
6779 try:
6780 hProcess.wait(0)
6781 except WindowsError:
6782 return False
6783 return True
6784
6786 """
6787 @rtype: int
6788 @return: Thread exit code, or C{STILL_ACTIVE} if it's still alive.
6789 """
6790 return win32.GetExitCodeThread(self.get_handle())
6791
6792
6793
6794
6795
6796
6810
6811
6812
6813
6814
6815 - def get_context(self, ContextFlags = None):
6816 """
6817 @type ContextFlags: int
6818 @param ContextFlags: Optional, specify which registers to retrieve.
6819 Defaults to C{win32.CONTEXT_ALL} which retrieves all registes
6820 for the current platform.
6821
6822 @rtype: dict( str S{->} int )
6823 @return: Dictionary mapping register names to their values.
6824
6825 @see: L{set_context}
6826 """
6827
6828
6829 hThread = self.get_handle()
6830
6831
6832
6833 try:
6834 self.suspend()
6835 bSuspended = True
6836 except WindowsError:
6837 bSuspended = False
6838
6839
6840 try:
6841
6842
6843 if not System.wow64:
6844
6845
6846
6847
6848
6849
6850
6851 ctx = win32.GetThreadContext(hThread,
6852 ContextFlags = ContextFlags)
6853
6854
6855 else:
6856 if self.is_wow64():
6857 ctx = win32.GetThreadContext(hThread,
6858 ContextFlags = ContextFlags)
6859 else:
6860
6861 if System.arch != 'i386':
6862 raise NotImplementedError
6863 if ContextFlags is not None:
6864 ContextFlags = ContextFlags & (~win32.ContextArchMask)
6865 ContextFlags = ContextFlags | win32.context_amd64.CONTEXT_AMD64
6866 ctx = win32.context_amd64.GetThreadContext(hThread,
6867 ContextFlags = ContextFlags)
6868 finally:
6869 if bSuspended:
6870 self.resume()
6871 return ctx
6872
6873 - def set_context(self, context):
6874 """
6875 Sets the values of the registers.
6876
6877 @see: L{get_context}
6878
6879 @type context: dict( str S{->} int )
6880 @param context: Dictionary mapping register names to their values.
6881 """
6882
6883
6884 self.suspend()
6885 try:
6886 if System.bits == 64 and self.is_wow64():
6887 win32.Wow64SetThreadContext(self.get_handle(), context)
6888 else:
6889 win32.SetThreadContext(self.get_handle(), context)
6890 finally:
6891 self.resume()
6892
6894 """
6895 @type register: str
6896 @param register: Register name.
6897
6898 @rtype: int
6899 @return: Value of the requested register.
6900 """
6901 'Returns the value of a specific register.'
6902 context = self.get_context()
6903 return context[register]
6904
6906 """
6907 Sets the value of a specific register.
6908
6909 @type register: str
6910 @param register: Register name.
6911
6912 @rtype: int
6913 @return: Register value.
6914 """
6915 context = self.get_context()
6916 context[register] = value
6917 self.set_context(context)
6918
6919
6920
6921 if win32.CONTEXT.arch in ('i386', 'amd64'):
6922
6924 """
6925 @rtype: int
6926 @return: Value of the program counter register.
6927 """
6928 context = self.get_context(win32.CONTEXT_CONTROL)
6929 return context.pc
6930
6932 """
6933 Sets the value of the program counter register.
6934
6935 @type pc: int
6936 @param pc: Value of the program counter register.
6937 """
6938 context = self.get_context(win32.CONTEXT_CONTROL)
6939 context.pc = pc
6940 self.set_context(context)
6941
6949
6951 """
6952 Sets the value of the stack pointer register.
6953
6954 @type sp: int
6955 @param sp: Value of the stack pointer register.
6956 """
6957 context = self.get_context(win32.CONTEXT_CONTROL)
6958 context.sp = sp
6959 self.set_context(context)
6960
6968
6970 """
6971 Sets the value of the frame pointer register.
6972
6973 @type fp: int
6974 @param fp: Value of the frame pointer register.
6975 """
6976 context = self.get_context(win32.CONTEXT_CONTROL)
6977 context.fp = fp
6978 self.set_context(context)
6979
6980 elif win32.CONTEXT.arch == 'ia64':
6981
6989
6991 """
6992 Sets the value of the frame pointer register.
6993
6994 @type gp: int
6995 @param gp: Value of the GP register.
6996 """
6997 context = self.get_context(win32.CONTEXT_CONTROL)
6998 context.gp = gp
6999 self.set_context(context)
7000
7008
7010 """
7011 Sets the value of the SP register.
7012
7013 @type sp: int
7014 @param sp: Value of the SP register.
7015 """
7016 context = self.get_context(win32.CONTEXT_CONTROL)
7017 context.sp = sp
7018 self.set_context(context)
7019
7027
7029 """
7030 Sets the value of the RP register.
7031
7032 @type rp: int
7033 @param rp: Value of the RP register.
7034 """
7035 context = self.get_context(win32.CONTEXT_CONTROL)
7036 context.rp = rp
7037 self.set_context(context)
7038
7039
7040
7041 if win32.CONTEXT.arch in ('i386', 'amd64'):
7042
7057
7058 - def get_flags(self, FlagMask = 0xFFFFFFFF):
7059 """
7060 @type FlagMask: int
7061 @param FlagMask: (Optional) Bitwise-AND mask.
7062
7063 @rtype: int
7064 @return: Flags register contents, optionally masking out some bits.
7065 """
7066 context = self.get_context(win32.CONTEXT_CONTROL)
7067 return context['EFlags'] & FlagMask
7068
7069 - def set_flags(self, eflags, FlagMask = 0xFFFFFFFF):
7070 """
7071 Sets the flags register, optionally masking some bits.
7072
7073 @type eflags: int
7074 @param eflags: Flags register contents.
7075
7076 @type FlagMask: int
7077 @param FlagMask: (Optional) Bitwise-AND mask.
7078 """
7079 context = self.get_context(win32.CONTEXT_CONTROL)
7080 context['EFlags'] = (context['EFlags'] & FlagMask) | eflags
7081 self.set_context(context)
7082
7084 """
7085 @type FlagBit: int
7086 @param FlagBit: One of the L{Flags}.
7087
7088 @rtype: bool
7089 @return: Boolean value of the requested flag.
7090 """
7091 return bool( self.get_flags(FlagBit) )
7092
7094 """
7095 Sets a single flag, leaving the others intact.
7096
7097 @type FlagBit: int
7098 @param FlagBit: One of the L{Flags}.
7099
7100 @type FlagValue: bool
7101 @param FlagValue: Boolean value of the flag.
7102 """
7103 if FlagValue:
7104 eflags = FlagBit
7105 else:
7106 eflags = 0
7107 FlagMask = 0xFFFFFFFF ^ FlagBit
7108 self.set_flags(eflags, FlagMask)
7109
7111 """
7112 @rtype: bool
7113 @return: Boolean value of the Zero flag.
7114 """
7115 return self.get_flag_value(self.Flags.Zero)
7116
7118 """
7119 @rtype: bool
7120 @return: Boolean value of the Carry flag.
7121 """
7122 return self.get_flag_value(self.Flags.Carry)
7123
7125 """
7126 @rtype: bool
7127 @return: Boolean value of the Sign flag.
7128 """
7129 return self.get_flag_value(self.Flags.Sign)
7130
7132 """
7133 @rtype: bool
7134 @return: Boolean value of the Direction flag.
7135 """
7136 return self.get_flag_value(self.Flags.Direction)
7137
7139 """
7140 @rtype: bool
7141 @return: Boolean value of the Trap flag.
7142 """
7143 return self.get_flag_value(self.Flags.Trap)
7144
7148
7152
7156
7160
7164
7168
7172
7176
7180
7184
7185
7186
7187 -class Process (MemoryOperations, ProcessDebugOperations, SymbolOperations, \
7188 ThreadContainer, ModuleContainer):
7189 """
7190 Interface to a process. Contains threads and modules snapshots.
7191
7192 @group Properties:
7193 get_pid, get_filename, get_exit_code,
7194 is_alive, is_debugged
7195
7196 @group Instrumentation:
7197 kill, wait, suspend, resume, inject_code, inject_dll, clean_exit
7198
7199 @group Processes snapshot:
7200 scan, clear, __contains__, __iter__, __len__
7201
7202 @group Handle:
7203 get_handle, open_handle, close_handle
7204
7205 @type dwProcessId: int
7206 @ivar dwProcessId: Global process ID. Use L{get_pid} instead.
7207
7208 @type hProcess: L{ProcessHandle}
7209 @ivar hProcess: Handle to the process. Use L{get_handle} instead.
7210
7211 @type fileName: str
7212 @ivar fileName: Filename of the main module. Use L{get_filename} instead.
7213 """
7214
7215 - def __init__(self, dwProcessId, hProcess = None, fileName = None):
7235
7237 """
7238 @rtype: int
7239 @return: Process global ID.
7240 """
7241 return self.dwProcessId
7242
7244 """
7245 @rtype: str
7246 @return: Filename of the main module of the process.
7247 """
7248 if not self.fileName:
7249 self.fileName = self.get_image_name()
7250 return self.fileName
7251
7267
7269 """
7270 Closes the handle to the process.
7271
7272 @note: Normally you don't need to call this method. All handles
7273 created by I{WinAppDbg} are automatically closed when the garbage
7274 collector claims them. So unless you've been tinkering with it,
7275 setting L{hProcess} to C{None} should be enough.
7276 """
7277 try:
7278 if hasattr(self.hProcess, 'close'):
7279 self.hProcess.close()
7280 elif self.hProcess not in (None, win32.INVALID_HANDLE_VALUE):
7281 win32.CloseHandle(self.hProcess)
7282 finally:
7283 self.hProcess = None
7284
7293
7294
7295
7296
7297
7298
7299
7300
7301
7302
7303
7304
7305
7306
7307
7308
7309
7310
7311
7312
7313
7314
7316 """
7317 The same as: C{self.has_thread(anObject) or self.has_module(anObject)}
7318
7319 @type anObject: L{Thread}, L{Module} or int
7320 @param anObject: Object to look for.
7321 Can be a Thread, Module, thread global ID or module base address.
7322
7323 @rtype: bool
7324 @return: C{True} if the requested object was found in the snapshot.
7325 """
7326 return ThreadContainer.__contains__(self, anObject) or \
7327 ModuleContainer.__contains__(self, anObject)
7328
7330 """
7331 @see: L{get_thread_count}, L{get_module_count}
7332 @rtype: int
7333 @return: Count of L{Thread} and L{Module} objects in this snapshot.
7334 """
7335 return ThreadContainer.__len__(self) + \
7336 ModuleContainer.__len__(self)
7337
7339 """
7340 Iterator object for L{Process} objects.
7341 Iterates through L{Thread} objects first, L{Module} objects next.
7342 """
7343
7345 """
7346 @type container: L{Process}
7347 @param container: L{Thread} and L{Module} container.
7348 """
7349 self.__container = container
7350 self.__iterator = None
7351 self.__state = 0
7352
7354 'x.__iter__() <==> iter(x)'
7355 return self
7356
7358 'x.next() -> the next value, or raise StopIteration'
7359 if self.__state == 0:
7360 self.__iterator = self.__container.iter_threads()
7361 self.__state = 1
7362 if self.__state == 1:
7363 try:
7364 return self.__iterator.next()
7365 except StopIteration:
7366 self.__iterator = self.__container.iter_modules()
7367 self.__state = 2
7368 if self.__state == 2:
7369 try:
7370 return self.__iterator.next()
7371 except StopIteration:
7372 self.__iterator = None
7373 self.__state = 3
7374 raise StopIteration
7375
7377 """
7378 @see: L{iter_threads}, L{iter_modules}
7379 @rtype: iterator
7380 @return: Iterator of L{Thread} and L{Module} objects in this snapshot.
7381 All threads are iterated first, then all modules.
7382 """
7383 return self.__ThreadsAndModulesIterator(self)
7384
7385
7386
7387 - def wait(self, dwTimeout = None):
7388 """
7389 Waits for the process to finish executing.
7390
7391 @raise WindowsError: On error an exception is raised.
7392 """
7393 self.get_handle().wait(dwTimeout)
7394
7395 - def kill(self, dwExitCode = 0):
7402
7404 """
7405 Suspends execution on all threads of the process.
7406
7407 @raise WindowsError: On error an exception is raised.
7408 """
7409 if self.get_thread_count() == 0:
7410 self.scan_threads()
7411 suspended = list()
7412 try:
7413 for aThread in self.iter_threads():
7414 aThread.suspend()
7415 suspended.append(aThread)
7416 except Exception:
7417 for aThread in suspended:
7418 try:
7419 aThread.resume()
7420 except Exception:
7421 pass
7422 raise
7423
7425 """
7426 Resumes execution on all threads of the process.
7427
7428 @raise WindowsError: On error an exception is raised.
7429 """
7430 if self.get_thread_count() == 0:
7431 self.scan_threads()
7432 resumed = list()
7433 try:
7434 for aThread in self.iter_threads():
7435 aThread.resume()
7436 resumed.append(aThread)
7437 except Exception:
7438 for aThread in resumed:
7439 try:
7440 aThread.suspend()
7441 except Exception:
7442 pass
7443 raise
7444
7446 """
7447 Tries to determine if the process is being debugged by another process.
7448 It may detect other debuggers besides WinAppDbg.
7449
7450 @rtype: bool
7451 @return: C{True} if the process has a debugger attached.
7452
7453 @warning:
7454 May return inaccurate results when some anti-debug techniques are
7455 used by the target process.
7456
7457 @note: To know if a process currently being debugged by a L{Debug}
7458 object, call L{Debug.is_debugee} instead.
7459 """
7460 return win32.CheckRemoteDebuggerPresent(self.get_handle())
7461
7463 """
7464 @rtype: bool
7465 @return: C{True} if the process is currently running.
7466 """
7467 try:
7468 self.wait(0)
7469 except WindowsError, e:
7470 return win32.winerror(e) == win32.WAIT_TIMEOUT
7471 return False
7472
7474 """
7475 @rtype: int
7476 @return: Process exit code, or C{STILL_ACTIVE} if it's still alive.
7477
7478 @warning: If a process returns C{STILL_ACTIVE} as it's exit code,
7479 you may not be able to determine if it's active or not with this
7480 method. Use L{is_alive} to check if the process is still active.
7481 Alternatively you can call L{get_handle} to get the handle object
7482 and then L{ProcessHandle.wait} on it to wait until the process
7483 finishes running.
7484 """
7485 return win32.GetExitCodeProcess(self.get_handle())
7486
7487
7488
7495
7502
7503
7504
7506 """
7507 Injects relocatable code into the process memory and executes it.
7508
7509 @see: L{inject_dll}
7510
7511 @type payload: str
7512 @param payload: Relocatable code to run in a new thread.
7513
7514 @type lpParameter: int
7515 @param lpParameter: (Optional) Parameter to be pushed in the stack.
7516
7517 @rtype: tuple( L{Thread}, int )
7518 @return: The injected Thread object
7519 and the memory address where the code was written.
7520
7521 @raise WindowsError: An exception is raised on error.
7522 """
7523
7524
7525
7526
7527
7528 lpStartAddress = self.malloc(len(payload))
7529
7530
7531 try:
7532
7533
7534 self.write(lpStartAddress, payload)
7535
7536
7537 aThread = self.start_thread(lpStartAddress, lpParameter,
7538 bSuspended = False)
7539
7540
7541
7542
7543
7544
7545 aThread.pInjectedMemory = lpStartAddress
7546
7547
7548 except Exception, e:
7549 self.free(lpStartAddress)
7550 raise
7551
7552
7553 return aThread, lpStartAddress
7554
7555
7556
7557
7558
7559 - def inject_dll(self, dllname, procname = None, lpParameter = 0,
7560 bWait = True, dwTimeout = None):
7561 """
7562 Injects a DLL into the process memory.
7563
7564 @warning: Setting C{bWait} to C{True} when the process is frozen by a
7565 debug event will cause a deadlock in your debugger.
7566
7567 @see: L{inject_code}
7568
7569 @type dllname: str
7570 @param dllname: Name of the DLL module to load.
7571
7572 @type procname: str
7573 @param procname: (Optional) Procedure to call when the DLL is loaded.
7574
7575 @type lpParameter: int
7576 @param lpParameter: (Optional) Parameter to the C{procname} procedure.
7577
7578 @type bWait: bool
7579 @param bWait: C{True} to wait for the process to finish.
7580 C{False} to return immediately.
7581
7582 @type dwTimeout: int
7583 @param dwTimeout: (Optional) Timeout value in milliseconds.
7584 Ignored if C{bWait} is C{False}.
7585
7586 @raise NotImplementedError: The target platform is not supported.
7587 Currently calling a procedure in the library is only supported in
7588 the I{i386} architecture.
7589
7590 @raise WindowsError: An exception is raised on error.
7591 """
7592
7593
7594 aModule = self.get_module_by_name('kernel32.dll')
7595 if aModule is None:
7596 self.scan_modules()
7597 aModule = self.get_module_by_name('kernel32.dll')
7598 if aModule is None:
7599 raise RuntimeError, \
7600 "Cannot resolve kernel32.dll in the remote process"
7601
7602
7603 if procname:
7604 if System.arch != 'i386':
7605 raise NotImplementedError
7606 dllname = str(dllname)
7607
7608
7609 pllib = aModule.resolve('LoadLibraryA')
7610 if not pllib:
7611 raise RuntimeError, \
7612 "Cannot resolve kernel32.dll!LoadLibraryA in the remote process"
7613
7614
7615 pgpad = aModule.resolve('GetProcAddress')
7616 if not pgpad:
7617 raise RuntimeError, \
7618 "Cannot resolve kernel32.dll!GetProcAddress in the remote process"
7619
7620
7621 pvf = aModule.resolve('VirtualFree')
7622 if not pvf:
7623 raise RuntimeError, \
7624 "Cannot resolve kernel32.dll!VirtualFree in the remote process"
7625
7626
7627 code = ''.encode('utf8')
7628
7629
7630 code += '\xe8' + struct.pack('<L', len(dllname) + 1) + dllname + '\0'
7631
7632
7633 code += '\xb8' + struct.pack('<L', pllib)
7634
7635
7636 code += '\xff\xd0'
7637
7638 if procname:
7639
7640
7641 code += '\xe8' + struct.pack('<L', len(procname) + 1)
7642 code += procname + '\0'
7643
7644
7645 code += '\x50'
7646
7647
7648 code += '\xb8' + struct.pack('<L', pgpad)
7649
7650
7651 code += '\xff\xd0'
7652
7653
7654 code += '\x8b\xec'
7655
7656
7657 code += '\x68' + struct.pack('<L', lpParameter)
7658
7659
7660 code += '\xff\xd0'
7661
7662
7663 code += '\x8b\xe5'
7664
7665
7666 code += '\x5a'
7667
7668
7669 code += '\x68' + struct.pack('<L', win32.MEM_RELEASE)
7670
7671
7672 code += '\x68' + struct.pack('<L', 0x1000)
7673
7674
7675 code += '\xe8\x00\x00\x00\x00'
7676
7677
7678 code += '\x81\x24\x24\x00\xf0\xff\xff'
7679
7680
7681 code += '\xb8' + struct.pack('<L', pvf)
7682
7683
7684 code += '\x52'
7685
7686
7687 code += '\xff\xe0'
7688
7689
7690 aThread, lpStartAddress = self.inject_code(code, lpParameter)
7691
7692
7693
7694 aThread.pInjectedMemory = None
7695
7696
7697 else:
7698
7699
7700 if type(dllname) == type(u''):
7701 pllibname = 'LoadLibraryW'
7702 bufferlen = (len(dllname) + 1) * 2
7703 dllname = win32.ctypes.create_unicode_buffer(dllname).raw[:bufferlen + 1]
7704 else:
7705 pllibname = 'LoadLibraryA'
7706 dllname = str(dllname) + '\x00'
7707 bufferlen = len(dllname)
7708 pllib = aModule.resolve(pllibname)
7709 if not pllib:
7710 msg = "Cannot resolve kernel32.dll!%s in the remote process"
7711 raise RuntimeError, msg % pllibname
7712
7713
7714 pbuffer = self.malloc(bufferlen)
7715 try:
7716 self.write(pbuffer, dllname)
7717
7718
7719 aThread = self.start_thread(pllib, pbuffer)
7720
7721
7722
7723
7724
7725 aThread.pInjectedMemory = pbuffer
7726
7727
7728 except Exception:
7729 self.free(pbuffer, bufferlen)
7730 raise
7731
7732
7733 if bWait:
7734 aThread.wait(dwTimeout)
7735
7736 - def clean_exit(self, dwExitCode = 0, bWait = False, dwTimeout = None):
7737 """
7738 Injects a new thread to call ExitProcess().
7739 Optionally waits for the injected thread to finish.
7740
7741 @warning: Setting C{bWait} to C{True} when the process is frozen by a
7742 debug event will cause a deadlock in your debugger.
7743
7744 @type dwExitCode: int
7745 @param dwExitCode: Process exit code.
7746
7747 @type bWait: bool
7748 @param bWait: C{True} to wait for the process to finish.
7749 C{False} to return immediately.
7750
7751 @type dwTimeout: int
7752 @param dwTimeout: (Optional) Timeout value in milliseconds.
7753 Ignored if C{bWait} is C{False}.
7754
7755 @raise WindowsError: An exception is raised on error.
7756 """
7757 if not dwExitCode:
7758 dwExitCode = 0
7759 pExitProcess = self.resolve_label('kernel32!ExitProcess')
7760 aThread = self.start_thread(pExitProcess, dwExitCode)
7761 if bWait:
7762 aThread.wait(dwTimeout)
7763
7764
7765
7767 """
7768 Notify the creation of a new process.
7769
7770 This is done automatically by the L{Debug} class, you shouldn't need
7771 to call it yourself.
7772
7773 @type event: L{CreateProcessEvent}
7774 @param event: Create process event.
7775
7776 @rtype: bool
7777 @return: C{True} to call the user-defined handle, C{False} otherwise.
7778 """
7779
7780 bCallHandler = ThreadContainer.notify_create_process(self, event)
7781 bCallHandler = bCallHandler and \
7782 ModuleContainer.notify_create_process(self, event)
7783 return bCallHandler
7784
7785
7786
7787 -class System (ProcessContainer):
7788 """
7789 Interface to a batch of processes, plus some system wide settings.
7790 Contains a snapshot of processes.
7791
7792 @group Instrumentation:
7793 find_window, get_window_at, get_desktop_window, get_foreground_window
7794
7795 @group Global settings:
7796 arch, bits, os, wow64, pageSize,
7797 set_kill_on_exit_mode, request_debug_privileges, load_dbghelp,
7798 read_msr, write_msr, enable_step_on_branch_mode,
7799 get_last_branch_location
7800
7801 @type arch: str
7802 @cvar arch: Name of the processor architecture we're running on.
7803 For more details see L{win32.version.get_arch}.
7804
7805 @type bits: int
7806 @cvar bits: Size of the machine word in bits for the current architecture.
7807 For more details see L{win32.version.get_bits}.
7808
7809 @type os: str
7810 @cvar os: Name of the Windows version we're runing on.
7811 For more details see L{win32.version.get_os}.
7812
7813 @type wow64: bool
7814 @cvar wow64: C{True} if the debugger is a 32 bits process running in a 64
7815 bits version of Windows, C{False} otherwise.
7816
7817 @type pageSize: int
7818 @cvar pageSize: Page size in bytes. Defaults to 0x1000 but it's
7819 automatically updated on runtime when importing the module.
7820 """
7821
7822 arch = win32.version.arch
7823 bits = win32.version.bits
7824 os = win32.version.os
7825
7826
7827
7828 try:
7829 wow64 = win32.IsWow64Process( win32.GetCurrentProcess() )
7830 except Exception:
7831 wow64 = False
7832
7833 pageSize = MemoryAddresses.pageSize
7834
7835
7836
7837 @staticmethod
7838 - def find_window(className = None, windowName = None):
7839 """
7840 Find the first top-level window in the current desktop to match the
7841 given class name and/or window name. If neither are provided any
7842 top-level window will match.
7843
7844 @see: L{get_window_at}
7845
7846 @type className: str
7847 @param className: (Optional) Class name of the window to find.
7848 If C{None} or not used any class name will match the search.
7849
7850 @type windowName: str
7851 @param windowName: (Optional) Caption text of the window to find.
7852 If C{None} or not used any caption text will match the search.
7853
7854 @rtype: L{Window} or None
7855 @return: A window that matches the request. There may be more matching
7856 windows, but this method only returns one. If no matching window
7857 is found, the return value is C{None}.
7858
7859 @raise WindowsError: An error occured while processing this request.
7860 """
7861
7862
7863 hWnd = win32.FindWindow(className, windowName)
7864 if hWnd:
7865 return Window(hWnd)
7866
7867 @staticmethod
7869 """
7870 Get the window located at the given coordinates in the desktop.
7871 If no such window exists an exception is raised.
7872
7873 @see: L{find_window}
7874
7875 @type x: int
7876 @param x: Horizontal coordinate.
7877 @type y: int
7878 @param y: Vertical coordinate.
7879
7880 @rtype: L{Window}
7881 @return: Window at the requested position. If no such window
7882 exists a C{WindowsError} exception is raised.
7883
7884 @raise WindowsError: An error occured while processing this request.
7885 """
7886 return Window( win32.WindowFromPoint( (x, y) ) )
7887
7888 @staticmethod
7890 """
7891 @rtype: L{Window}
7892 @return: Returns the desktop window.
7893 @raise WindowsError: An error occured while processing this request.
7894 """
7895 return Window( win32.GetDesktopWindow() )
7896
7897 @staticmethod
7899 """
7900 @rtype: L{Window}
7901 @return: Returns the foreground window.
7902 @raise WindowsError: An error occured while processing this request.
7903 """
7904 return Window( win32.GetForegroundWindow() )
7905
7906
7907
7908 @staticmethod
7931
7932 @staticmethod
7934 """
7935 Automatically detach from processes when the current thread dies.
7936
7937 Works on the following platforms:
7938
7939 - Microsoft Windows XP and above.
7940 - Wine (Windows Emulator).
7941
7942 Fails on the following platforms:
7943
7944 - Microsoft Windows 2000 and below.
7945 - ReactOS.
7946
7947 @type bKillOnExit: bool
7948 @param bKillOnExit: C{True} to automatically kill processes when the
7949 debugger thread dies. C{False} to automatically detach from
7950 processes when the debugger thread dies.
7951
7952 @rtype: bool
7953 @return: C{True} on success, C{False} on error.
7954
7955 @note:
7956 This call will fail if a debug port was not created. That is, if
7957 the debugger isn't attached to at least one process. For more info
7958 see: U{http://msdn.microsoft.com/en-us/library/ms679307.aspx}
7959 """
7960 try:
7961
7962
7963 win32.DebugSetProcessKillOnExit(bKillOnExit)
7964 return True
7965 except (AttributeError, WindowsError):
7966 pass
7967 return False
7968
7969 @classmethod
7971 """
7972 Load the C{dbghelp.dll} library shipped with the Debugging Tools for
7973 Windows. Essentially this enables symbol server support, since this
7974 version is newer than the one pre-installed with Windows, and the
7975 symbol server loader library (C{SymSrv.dll}) is present in the same
7976 directory.
7977
7978 For this method to have any effect it MUST be called BEFORE any
7979 function in C{dbghelp.dll}. It's recommended that you call it right
7980 after starting your debug script, or after instancing the L{Debug}
7981 object.
7982
7983 Example::
7984 from winappdbg import Debug
7985
7986 def simple_debugger( argv ):
7987
7988 # Instance a Debug object, passing it the event handler callback
7989 debug = Debug( my_event_handler )
7990 try:
7991
7992 # Enable support for symbol downloading
7993 debug.system.load_dbghelp()
7994
7995 # Start a new process for debugging
7996 debug.execv( argv )
7997
7998 # Wait for the debugee to finish
7999 debug.loop()
8000
8001 # Stop the debugger
8002 finally:
8003 debug.stop()
8004
8005 @see: U{http://msdn.microsoft.com/en-us/library/ms679294(VS.85).aspx}
8006
8007 @type pathname: str
8008 @param pathname:
8009 (Optional) Full pathname to the C{dbghelp.dll} library.
8010
8011 @rtype: ctypes.WinDLL
8012 @return: Loaded instance of C{dbghelp.dll}.
8013
8014 @raise NotImplementedError: This feature was not implemented for the
8015 current architecture.
8016
8017 @raise WindowsError: An error occured while processing this request.
8018 """
8019 if not pathname:
8020 if cls.arch == 'amd64':
8021 if cls.wow64:
8022 pathname = os.path.join(
8023 os.getenv("ProgramFiles(x86)",
8024 os.getenv("ProgramFiles")),
8025 "Debugging Tools for Windows (x86)",
8026 "dbghelp.dll")
8027 else:
8028 pathname = os.path.join(
8029 os.getenv("ProgramFiles"),
8030 "Debugging Tools for Windows (x64)",
8031 "dbghelp.dll")
8032 elif cls.arch == 'i386':
8033 pathname = os.path.join(
8034 os.getenv("ProgramFiles"),
8035 "Debugging Tools for Windows (x86)",
8036 "dbghelp.dll")
8037 else:
8038 msg = "Architecture %s is not currently supported."
8039 raise NotImplementedError, msg % cls.arch
8040 return ctypes.windll.LoadLibrary(pathname)
8041
8042 @classmethod
8044 """
8045 Read the contents of the specified MSR (Machine Specific Register).
8046
8047 @type address: int
8048 @param address: MSR to read.
8049
8050 @rtype: int
8051 @return: Value of the specified MSR.
8052
8053 @raise WindowsError:
8054 Raises an exception on error.
8055
8056 @raise NotImplementedError:
8057 Current architecture is not C{i386} or C{amd64}.
8058
8059 @warning:
8060 It could potentially brick your machine.
8061 It works on my machine, but your mileage may vary.
8062 """
8063 if cls.arch not in ('i386', 'amd64'):
8064 raise NotImplementedError, \
8065 "MSR reading is only supported on i386 or amd64 processors."
8066 msr = win32.SYSDBG_MSR()
8067 msr.Address = address
8068 msr.Data = 0
8069 win32.NtSystemDebugControl(win32.SysDbgReadMsr,
8070 InputBuffer = msr,
8071 OutputBuffer = msr)
8072 return msr.Data
8073
8074 @classmethod
8076 """
8077 Set the contents of the specified MSR (Machine Specific Register).
8078
8079 @type address: int
8080 @param address: MSR to write.
8081
8082 @type value: int
8083 @param value: Contents to write on the MSR.
8084
8085 @raise WindowsError:
8086 Raises an exception on error.
8087
8088 @raise NotImplementedError:
8089 Current architecture is not C{i386} or C{amd64}.
8090
8091 @warning:
8092 It could potentially brick your machine.
8093 It works on my machine, but your mileage may vary.
8094 """
8095 if cls.arch not in ('i386', 'amd64'):
8096 raise NotImplementedError, \
8097 "MSR reading is only supported on i386 or amd64 processors."
8098 msr = win32.SYSDBG_MSR()
8099 msr.Address = address
8100 msr.Data = value
8101 win32.NtSystemDebugControl(win32.SysDbgWriteMsr, InputBuffer = msr)
8102
8103 @classmethod
8105 """
8106 When tracing, call this on every single step event
8107 for step on branch mode.
8108
8109 @raise WindowsError:
8110 Raises C{ERROR_DEBUGGER_INACTIVE} if the debugger is not attached
8111 to least one process.
8112
8113 @raise NotImplementedError:
8114 Current architecture is not C{i386} or C{amd64}.
8115
8116 @warning:
8117 This method uses the processor's machine specific registers (MSR).
8118 It could potentially brick your machine.
8119 It works on my machine, but your mileage may vary.
8120
8121 @note:
8122 It doesn't seem to work in VMWare or VirtualBox machines.
8123 Maybe it fails in other virtualization/emulation environments,
8124 no extensive testing was made so far.
8125 """
8126 cls.write_msr(DebugRegister.DebugCtlMSR,
8127 DebugRegister.BranchTrapFlag | DebugRegister.LastBranchRecord)
8128
8129 @classmethod
8131 """
8132 Returns the source and destination addresses of the last taken branch.
8133
8134 @rtype: tuple( int, int )
8135 @return: Source and destination addresses of the last taken branch.
8136
8137 @raise WindowsError:
8138 Raises an exception on error.
8139
8140 @raise NotImplementedError:
8141 Current architecture is not C{i386} or C{amd64}.
8142
8143 @warning:
8144 This method uses the processor's machine specific registers (MSR).
8145 It could potentially brick your machine.
8146 It works on my machine, but your mileage may vary.
8147
8148 @note:
8149 It doesn't seem to work in VMWare or VirtualBox machines.
8150 Maybe it fails in other virtualization/emulation environments,
8151 no extensive testing was made so far.
8152 """
8153 LastBranchFromIP = cls.read_msr(DebugRegister.LastBranchFromIP)
8154 LastBranchToIP = cls.read_msr(DebugRegister.LastBranchToIP)
8155 return ( LastBranchFromIP, LastBranchToIP )
8156