I'm working on a Windows 7 64 bit machine (I have admin privs).
I'm using Python 2.7 (64-bit) with PyDev ctypes for Eclipse to try and read the values of registers in all threads associated with a particular PID (tried both PIDs of processes running in 64 and 32 bit modes), but when I do this, the values for the registers are all zeroe'd out. When I use Wow64GetThreadContext
, the call fails with GetLastError
returning 0x00000057 ('invalid parameters' according to MSDN)
I attach to the process successfully, enumerate the threads (via CreateToolhelp32Snapshot
), find the threads that are owned by the process with the appropriate PID, and attempt to get the thread context. Here is my code for opening the thread and getting the thread context:
Opening a thread:
def open_thread(self, thread_id):
h_thread = kernel32.OpenThread(THREAD_ALL_ACCESS, None, thread_id)
Getting context:
def get_thread_context(self, thread_id = None, h_thread = None):
context = CONTEXT()
context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS
#alternatively, for 64
context64 = WOW64_CONTEXT()
context64.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS
#Obtain a handle to the thread
if h_thread is None:
self.h_thread = self.open_thread(thread_id)
kernel32.SuspendThread(self.h_thread)
if kernel32.GetThreadContext(self.h_thread, byref(context)):
kernel32.ResumeThread(self.h_thread)
return context
else:
kernel32.ResumeThread(self.h_thread)
return False
I call this code using:
debugger.attach(int(pid))
#debugger.run()
list = debugger.enumerate_threads()
for thread in list:
thread_context = debugger.get_thread_context(thread)
if thread_context == False:
print "[*] Thread context is false..."
else:
print "[*] Dumping registers for thread ID: 0x%08x" % thread
print "[**] Eip: 0x%016x" % thread_context.Eip
print "[**] Esp: 0x%016x" % thread_context.Esp
print "[**] Ebp: 0x%016x" % thread_context.Ebp
print "[**] Eax: 0x%016x" % thread_context.Eax
print "[**] Ebx: 0x%016x" % thread_context.Ebx
print "[**] Ecx: 0x%016x" % thread_context.Ecx
print "[**] Edx: 0x%016x" % thread_context.Edx
print "[*] End DUMP"
debugger.detach()
When I run this code using GetThreadContext
with the CONTEXT structure, I get the context object back for each thread, but the register values are all zero.
I have tried replacing GetThreadContext
with Wow64GetThreadContext
(and respectively, SuspendThread
with Wow64SuspendThread
), but when I do this, the call fails with error 'invalid parameters'. The arguments I give to Wow64GetThreadContext
are the same as those I give to GetThreadContext
, other than the name of the variables in the code I provided (this is because when I looked at their definitions in WinNT.h, they were equivalent (unless I missed something). I've defined these structures the following way:
class WOW64_CONTEXT(Structure):
_fields_ = [
("ContextFlags", DWORD),
("Dr0", DWORD),
("Dr1", DWORD),
("Dr2", DWORD),
("Dr3", DWORD),
("Dr6", DWORD),
("Dr7", DWORD),
("FloatSave", WOW64_FLOATING_SAVE_AREA),
("SegGs", DWORD),
("SegFs", DWORD),
("SegEs", DWORD),
("SegDs", DWORD),
("Edi", DWORD),
("Esi", DWORD),
("Ebx", DWORD),
("Edx", DWORD),
("Ecx", DWORD),
("Eax", DWORD),
("Ebp", DWORD),
("Eip", DWORD),
("SegCs", DWORD),
("EFlags", DWORD),
("Esp", DWORD),
("SegSs", DWORD),
("ExtendedRegisters", BYTE * 512),
]
class WOW64_FLOATING_SAVE_AREA(Structure):
_fields_ = [
("ControlWord", DWORD),
("StatusWord", DWORD),
("TagWord", DWORD),
("ErrorOffset", DWORD),
("ErrorSelector", DWORD),
("DataOffset", DWORD),
("DataSelector", DWORD),
("RegisterArea", BYTE * 80),
("Cr0NpxState", DWORD),
]
class CONTEXT(Structure):
_fields_ = [
("ContextFlags", DWORD),
("Dr0", DWORD),
("Dr1", DWORD),
("Dr2", DWORD),
("Dr3", DWORD),
("Dr6", DWORD),
("Dr7", DWORD),
("FloatSave", FLOATING_SAVE_AREA),
("SegGs", DWORD),
("SegFs", DWORD),
("SegEs", DWORD),
("SegDs", DWORD),
("Edi", DWORD),
("Esi", DWORD),
("Ebx", DWORD),
("Edx", DWORD),
("Ecx", DWORD),
("Eax", DWORD),
("Ebp", DWORD),
("Eip", DWORD),
("SegCs", DWORD),
("EFlags", DWORD),
("Esp", DWORD),
("SegSs", DWORD),
("ExtendedRegisters", BYTE * 512),
]
class FLOATING_SAVE_AREA(Structure):
_fields_ = [
("ControlWord", DWORD),
("StatusWord", DWORD),
("TagWord", DWORD),
("ErrorOffset", DWORD),
("ErrorSelector", DWORD),
("DataOffset", DWORD),
("DataSelector", DWORD),
("RegisterArea", BYTE * 80),
("Cr0NpxState", DWORD),
]
I've done a fair amount of googling on this issue, and have tried the following to no avail:
According to a comment on the MSDN:
CONTEXT_FULL
should beCONTEXT_AMD64 | CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT
to be used with Win64 properly.I've tried renaming the registers inside my CONTEXT and WOW_64CONTEXT structures by replacing the 'E' in the register names with 'R' (Eax -> Rax, etc.)
Has anyone else used Python with ctypes to successfully get the context of a 64-bit thread on Windows?