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

Source Code for Module winappdbg.win32.context_i386

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