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

Source Code for Module winappdbg.win32.context_i386

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