Package winappdbg :: Package win32 :: Module context_i386
[hide private]
[frames] | no frames]

Source Code for Module winappdbg.win32.context_i386

  1  # Copyright (c) 2009, Mario Vilas 
  2  # All rights reserved. 
  3  # 
  4  # Redistribution and use in source and binary forms, with or without 
  5  # modification, are permitted provided that the following conditions are met: 
  6  # 
  7  #     * Redistributions of source code must retain the above copyright notice, 
  8  #       this list of conditions and the following disclaimer. 
  9  #     * Redistributions in binary form must reproduce the above copyright 
 10  #       notice,this list of conditions and the following disclaimer in the 
 11  #       documentation and/or other materials provided with the distribution. 
 12  #     * Neither the name of the copyright holder nor the names of its 
 13  #       contributors may be used to endorse or promote products derived from 
 14  #       this software without specific prior written permission. 
 15  # 
 16  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
 17  # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
 18  # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
 19  # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
 20  # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
 21  # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
 22  # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
 23  # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
 24  # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
 25  # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
 26  # POSSIBILITY OF SUCH DAMAGE. 
 27   
 28  """ 
 29  Debugging API wrappers in ctypes. 
 30   
 31  @see: U{http://apps.sourceforge.net/trac/winappdbg/wiki/Win32APIWrappers} 
 32  """ 
 33   
 34  __revision__ = "$Id: context_i386.py 382 2009-08-25 21:20:54Z QvasiModo $" 
 35   
 36  from defines import * 
 37   
 38  # The following values specify the type of access in the first parameter 
 39  # of the exception record whan the exception code specifies an access 
 40  # violation. 
 41  EXCEPTION_READ_FAULT        = 0     # exception caused by a read 
 42  EXCEPTION_WRITE_FAULT       = 1     # exception caused by a write 
 43  EXCEPTION_EXECUTE_FAULT     = 8     # exception caused by an instruction fetch 
 44   
 45  CONTEXT_i386                = 0x00010000    # this assumes that i386 and 
 46  CONTEXT_i486                = 0x00010000    # i486 have identical context records 
 47   
 48  CONTEXT_CONTROL             = (CONTEXT_i386 | 0x00000001L) # SS:SP, CS:IP, FLAGS, BP 
 49  CONTEXT_INTEGER             = (CONTEXT_i386 | 0x00000002L) # AX, BX, CX, DX, SI, DI 
 50  CONTEXT_SEGMENTS            = (CONTEXT_i386 | 0x00000004L) # DS, ES, FS, GS 
 51  CONTEXT_FLOATING_POINT      = (CONTEXT_i386 | 0x00000008L) # 387 state 
 52  CONTEXT_DEBUG_REGISTERS     = (CONTEXT_i386 | 0x00000010L) # DB 0-3,6,7 
 53  CONTEXT_EXTENDED_REGISTERS  = (CONTEXT_i386 | 0x00000020L) # cpu specific extensions 
 54   
 55  CONTEXT_FULL = (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS) 
 56   
 57  CONTEXT_ALL = (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS | \ 
 58                  CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS | \ 
 59                  CONTEXT_EXTENDED_REGISTERS) 
 60   
 61  SIZE_OF_80387_REGISTERS     = 80 
 62  MAXIMUM_SUPPORTED_EXTENSION = 512 
63 64 # typedef struct _FLOATING_SAVE_AREA { 65 # DWORD ControlWord; 66 # DWORD StatusWord; 67 # DWORD TagWord; 68 # DWORD ErrorOffset; 69 # DWORD ErrorSelector; 70 # DWORD DataOffset; 71 # DWORD DataSelector; 72 # BYTE RegisterArea[SIZE_OF_80387_REGISTERS]; 73 # DWORD Cr0NpxState; 74 # } FLOATING_SAVE_AREA; 75 -class FLOATING_SAVE_AREA(Structure):
76 _pack_ = 1 77 _fields_ = [ 78 ('ControlWord', DWORD), 79 ('StatusWord', DWORD), 80 ('TagWord', DWORD), 81 ('ErrorOffset', DWORD), 82 ('ErrorSelector', DWORD), 83 ('DataOffset', DWORD), 84 ('DataSelector', DWORD), 85 ('RegisterArea', BYTE * SIZE_OF_80387_REGISTERS), 86 ('Cr0NpxState', DWORD), 87 ] 88 89 _integer_members = ('ControlWord', 'StatusWord', 'TagWord', 'ErrorOffset', 'ErrorSelector', 'DataOffset', 'DataSelector', 'Cr0NpxState') 90 91 @classmethod
92 - def from_dict(cls, fsa):
93 'Instance a new structure from a Python dictionary.' 94 fsa = dict(fsa) 95 s = cls() 96 for key in cls._integer_members: 97 setattr(s, key, fsa.get(key)) 98 ra = fsa.get('RegisterArea', None) 99 if ra is not None: 100 for index in xrange(0, SIZE_OF_80387_REGISTERS): 101 s.RegisterArea[index] = ra[index] 102 return s
103
104 - def to_dict(self):
105 'Convert a structure into a Python dictionary.' 106 fsa = dict() 107 for key in self._integer_members: 108 fsa[key] = getattr(self, key) 109 ra = [ self.RegisterArea[index] for index in xrange(0, SIZE_OF_80387_REGISTERS) ] 110 ra = tuple(ra) 111 fsa['RegisterArea'] = ra 112 return fsa
113 114 PFLOATING_SAVE_AREA = POINTER(FLOATING_SAVE_AREA) 115 LPFLOATING_SAVE_AREA = PFLOATING_SAVE_AREA
116 117 # typedef struct _CONTEXT { 118 # DWORD ContextFlags; 119 # DWORD Dr0; 120 # DWORD Dr1; 121 # DWORD Dr2; 122 # DWORD Dr3; 123 # DWORD Dr6; 124 # DWORD Dr7; 125 # FLOATING_SAVE_AREA FloatSave; 126 # DWORD SegGs; 127 # DWORD SegFs; 128 # DWORD SegEs; 129 # DWORD SegDs; 130 # DWORD Edi; 131 # DWORD Esi; 132 # DWORD Ebx; 133 # DWORD Edx; 134 # DWORD Ecx; 135 # DWORD Eax; 136 # DWORD Ebp; 137 # DWORD Eip; 138 # DWORD SegCs; 139 # DWORD EFlags; 140 # DWORD Esp; 141 # DWORD SegSs; 142 # BYTE ExtendedRegisters[MAXIMUM_SUPPORTED_EXTENSION]; 143 # } CONTEXT; 144 -class CONTEXT(Structure):
145 arch = 'i386' 146 147 _pack_ = 1 148 149 # Context Frame 150 # 151 # This frame has a several purposes: 1) it is used as an argument to 152 # NtContinue, 2) is is used to constuct a call frame for APC delivery, 153 # and 3) it is used in the user level thread creation routines. 154 # 155 # The layout of the record conforms to a standard call frame. 156 157 _fields_ = [ 158 159 # The flags values within this flag control the contents of 160 # a CONTEXT record. 161 # 162 # If the context record is used as an input parameter, then 163 # for each portion of the context record controlled by a flag 164 # whose value is set, it is assumed that that portion of the 165 # context record contains valid context. If the context record 166 # is being used to modify a threads context, then only that 167 # portion of the threads context will be modified. 168 # 169 # If the context record is used as an IN OUT parameter to capture 170 # the context of a thread, then only those portions of the thread's 171 # context corresponding to set flags will be returned. 172 # 173 # The context record is never used as an OUT only parameter. 174 175 ('ContextFlags', DWORD), 176 177 # This section is specified/returned if CONTEXT_DEBUG_REGISTERS is 178 # set in ContextFlags. Note that CONTEXT_DEBUG_REGISTERS is NOT 179 # included in CONTEXT_FULL. 180 181 ('Dr0', DWORD), 182 ('Dr1', DWORD), 183 ('Dr2', DWORD), 184 ('Dr3', DWORD), 185 ('Dr6', DWORD), 186 ('Dr7', DWORD), 187 188 # This section is specified/returned if the 189 # ContextFlags word contains the flag CONTEXT_FLOATING_POINT. 190 191 ('FloatSave', FLOATING_SAVE_AREA), 192 193 # This section is specified/returned if the 194 # ContextFlags word contains the flag CONTEXT_SEGMENTS. 195 196 ('SegGs', DWORD), 197 ('SegFs', DWORD), 198 ('SegEs', DWORD), 199 ('SegDs', DWORD), 200 201 # This section is specified/returned if the 202 # ContextFlags word contains the flag CONTEXT_INTEGER. 203 204 ('Edi', DWORD), 205 ('Esi', DWORD), 206 ('Ebx', DWORD), 207 ('Edx', DWORD), 208 ('Ecx', DWORD), 209 ('Eax', DWORD), 210 211 # This section is specified/returned if the 212 # ContextFlags word contains the flag CONTEXT_CONTROL. 213 214 ('Ebp', DWORD), 215 ('Eip', DWORD), 216 ('SegCs', DWORD), # MUST BE SANITIZED 217 ('EFlags', DWORD), # MUST BE SANITIZED 218 ('Esp', DWORD), 219 ('SegSs', DWORD), 220 221 # This section is specified/returned if the ContextFlags word 222 # contains the flag CONTEXT_EXTENDED_REGISTERS. 223 # The format and contexts are processor specific. 224 225 ('ExtendedRegisters', BYTE * MAXIMUM_SUPPORTED_EXTENSION), 226 ] 227 228 _ctx_debug = ('Dr0', 'Dr1', 'Dr2', 'Dr3', 'Dr6', 'Dr7') 229 _ctx_segs = ('SegGs', 'SegFs', 'SegEs', 'SegDs', ) 230 _ctx_int = ('Edi', 'Esi', 'Ebx', 'Edx', 'Ecx', 'Eax') 231 _ctx_ctrl = ('Ebp', 'Eip', 'SegCs', 'EFlags', 'Esp', 'SegSs') 232 233 @classmethod
234 - def from_dict(cls, ctx):
235 'Instance a new structure from a Python dictionary.' 236 ctx = Context(ctx) 237 s = cls() 238 ContextFlags = ctx['ContextFlags'] 239 setattr(s, 'ContextFlags', ContextFlags) 240 if (ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS: 241 for key in s._ctx_debug: 242 setattr(s, key, ctx[key]) 243 if (ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT: 244 fsa = ctx['FloatSave'] 245 s.FloatSave = FLOATING_SAVE_AREA.from_dict(fsa) 246 if (ContextFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS: 247 for key in s._ctx_segs: 248 setattr(s, key, ctx[key]) 249 if (ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER: 250 for key in s._ctx_int: 251 setattr(s, key, ctx[key]) 252 if (ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL: 253 for key in s._ctx_ctrl: 254 setattr(s, key, ctx[key]) 255 if (ContextFlags & CONTEXT_EXTENDED_REGISTERS) == CONTEXT_EXTENDED_REGISTERS: 256 er = ctx['ExtendedRegisters'] 257 for index in xrange(0, MAXIMUM_SUPPORTED_EXTENSION): 258 s.ExtendedRegisters[index] = er[index] 259 return s
260
261 - def to_dict(self):
262 'Convert a structure into a Python dictionary.' 263 ctx = Context() 264 ContextFlags = self.ContextFlags 265 ctx['ContextFlags'] = ContextFlags 266 if (ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS: 267 for key in self._ctx_debug: 268 ctx[key] = getattr(self, key) 269 if (ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT: 270 ctx['FloatSave'] = self.FloatSave.to_dict() 271 if (ContextFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS: 272 for key in self._ctx_segs: 273 ctx[key] = getattr(self, key) 274 if (ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER: 275 for key in self._ctx_int: 276 ctx[key] = getattr(self, key) 277 if (ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL: 278 for key in self._ctx_ctrl: 279 ctx[key] = getattr(self, key) 280 if (ContextFlags & CONTEXT_EXTENDED_REGISTERS) == CONTEXT_EXTENDED_REGISTERS: 281 er = [ self.ExtendedRegisters[index] for index in xrange(0, MAXIMUM_SUPPORTED_EXTENSION) ] 282 er = tuple(er) 283 ctx['ExtendedRegisters'] = er 284 return ctx
285 286 PCONTEXT = POINTER(CONTEXT) 287 LPCONTEXT = PCONTEXT
288 289 -class Context(dict):
290 """ 291 Register context dictionary for the %s architecture. 292 """ % CONTEXT.arch 293 arch = CONTEXT.arch 294
295 - def __get_pc(self):
296 return self['Eip']
297 - def __set_pc(self, value):
298 self['Eip'] = value
299 pc = property(__get_pc, __set_pc) 300
301 - def __get_sp(self):
302 return self['Esp']
303 - def __set_sp(self, value):
304 self['Esp'] = value
305 sp = property(__get_sp, __set_sp) 306
307 - def __get_fp(self):
308 return self['Ebp']
309 - def __set_fp(self, value):
310 self['Ebp'] = value
311 fp = property(__get_fp, __set_fp)
312
313 #--- LDT_ENTRY structure ------------------------------------------------------ 314 315 # typedef struct _LDT_ENTRY { 316 # WORD LimitLow; 317 # WORD BaseLow; 318 # union { 319 # struct { 320 # BYTE BaseMid; 321 # BYTE Flags1; 322 # BYTE Flags2; 323 # BYTE BaseHi; 324 # } Bytes; 325 # struct { 326 # DWORD BaseMid :8; 327 # DWORD Type :5; 328 # DWORD Dpl :2; 329 # DWORD Pres :1; 330 # DWORD LimitHi :4; 331 # DWORD Sys :1; 332 # DWORD Reserved_0 :1; 333 # DWORD Default_Big :1; 334 # DWORD Granularity :1; 335 # DWORD BaseHi :8; 336 # } Bits; 337 # } HighWord; 338 # } LDT_ENTRY, 339 # *PLDT_ENTRY; 340 341 -class _LDT_ENTRY_BYTES_(Structure):
342 _pack_ = 1 343 _fields_ = [ 344 ('BaseMid', BYTE), 345 ('Flags1', BYTE), 346 ('Flags2', BYTE), 347 ('BaseHi', BYTE), 348 ]
349
350 -class _LDT_ENTRY_BITS_(Structure):
351 _pack_ = 1 352 _fields_ = [ 353 ('BaseMid', DWORD, 8), 354 ('Type', DWORD, 5), 355 ('Dpl', DWORD, 2), 356 ('Pres', DWORD, 1), 357 ('LimitHi', DWORD, 4), 358 ('Sys', DWORD, 1), 359 ('Reserved_0', DWORD, 1), 360 ('Default_Big', DWORD, 1), 361 ('Granularity', DWORD, 1), 362 ('BaseHi', DWORD, 8), 363 ]
364
365 -class _LDT_ENTRY_HIGHWORD_(Union):
366 _pack_ = 1 367 _fields_ = [ 368 ('Bytes', _LDT_ENTRY_BYTES_), 369 ('Bits', _LDT_ENTRY_BITS_), 370 ]
371
372 -class LDT_ENTRY(Structure):
373 _pack_ = 1 374 _fields_ = [ 375 ('LimitLow', WORD), 376 ('BaseLow', WORD), 377 ('HighWord', _LDT_ENTRY_HIGHWORD_), 378 ]
379 380 PLDT_ENTRY = POINTER(LDT_ENTRY) 381 LPLDT_ENTRY = PLDT_ENTRY
382 383 ############################################################################### 384 385 # BOOL WINAPI GetThreadSelectorEntry( 386 # __in HANDLE hThread, 387 # __in DWORD dwSelector, 388 # __out LPLDT_ENTRY lpSelectorEntry 389 # ); 390 -def GetThreadSelectorEntry(hThread, dwSelector):
391 _GetThreadSelectorEntry = windll.kernel32.GetThreadSelectorEntry 392 _GetThreadSelectorEntry.argtypes = [HANDLE, DWORD, LPLDT_ENTRY] 393 _GetThreadSelectorEntry.restype = bool 394 _GetThreadSelectorEntry.errcheck = RaiseIfZero 395 396 ldt = LDT_ENTRY() 397 _GetThreadSelectorEntry(hThread, dwSelector, ctypes.byref(ldt)) 398 return ldt
399
400 # BOOL WINAPI GetThreadContext( 401 # __in HANDLE hThread, 402 # __inout LPCONTEXT lpContext 403 # ); 404 -def GetThreadContext(hThread, ContextFlags = None):
405 _GetThreadContext = windll.kernel32.GetThreadContext 406 _GetThreadContext.argtypes = [HANDLE, LPCONTEXT] 407 _GetThreadContext.restype = bool 408 _GetThreadContext.errcheck = RaiseIfZero 409 410 if ContextFlags is None: 411 ContextFlags = CONTEXT_ALL 412 lpContext = CONTEXT() 413 lpContext.ContextFlags = ContextFlags 414 _GetThreadContext(hThread, ctypes.byref(lpContext)) 415 return lpContext.to_dict()
416
417 # BOOL WINAPI SetThreadContext( 418 # __in HANDLE hThread, 419 # __in const CONTEXT* lpContext 420 # ); 421 -def SetThreadContext(hThread, lpContext):
422 _SetThreadContext = windll.kernel32.SetThreadContext 423 _SetThreadContext.argtypes = [HANDLE, LPCONTEXT] 424 _SetThreadContext.restype = bool 425 _SetThreadContext.errcheck = RaiseIfZero 426 427 if isinstance(lpContext, dict): 428 lpContext = CONTEXT.from_dict(lpContext) 429 _SetThreadContext(hThread, ctypes.byref(lpContext))
430