python – Win 64bit GetThreadContext返回zeroe’d寄存器,或0x57错误代码

我正在使用Windows 7 64位计算机(我有管理员权限).

我正在使用Python 2.7(64位)和PyDev ctypes for Eclipse来尝试读取与特定PID相关的所有线程中的寄存器值(尝试在64位和32位模式下运行的两个进程的PID),但是当我这样做,寄存器的值都是零.当我使用Wow64GetThreadContext时,调用失败,GetLastError返回0x00000057(根据MSDN,’无效参数’)

我成功附加到进程,枚举线程(通过CreateToolhelp32Snapshot),找到具有适当PID的进程拥有的线程,并尝试获取线程上下文.这是我打开线程和获取线程上下文的代码:

打开一个帖子:

def open_thread(self, thread_id):
    h_thread = kernel32.OpenThread(THREAD_ALL_ACCESS, None, thread_id)

获取背景:

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

我用以下方法调用此代码:

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()

当我使用带有CONTEXT结构的GetThreadContext运行此代码时,我会为每个线程返回上下文对象,但寄存器值都为零.

我已经尝试用Wow64GetThreadContext替换GetThreadContext(分别使用Wow64SuspendThread替换SuspendThread),但是当我这样做时,调用失败并出现错误’invalid parameters’.我给Wow64GetThreadContext的参数与我给GetThreadContext的参数相同,除了我提供的代码中的变量名称(这是因为当我在WinNT.h中查看它们的定义时,它们是等价的(除非我错过了)我已经按照以下方式定义了这些结构:

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),
]

我已经在这个问题上做了相当多的谷歌搜索,并尝试了以下无济于事:

>根据MSDN上的评论:CONTEXT_FULL应该是
CONTEXT_AMD64 | CONTEXT_CONTROL | CONTEXT_INTEGER |
正确使用Win64的CONTEXT_FLOATING_POINT.
>我已经尝试重命名我的CONTEXT和WOW_64CONTEXT中的寄存器
通过用’R’替换寄存器名称中的’E'(Eax
– &GT Rax等)

有没有其他人使用Python与ctypes成功获取Windows上的64位线程的上下文?

解决方法:

你的主要问题是WOW64实际上是32位上下文,而不是64位.您需要实现64位结构,类似于:

class CONTEXT64(Structure):
_pack_ = 16
_fields_ = [
    ("P1Home", DWORD64),
    ("P2Home", DWORD64),
    ("P3Home", DWORD64),
    ("P4Home", DWORD64),
    ("P5Home", DWORD64),
    ("P6Home", DWORD64),

    ("ContextFlags", DWORD),
    ("MxCsr", DWORD),

    ("SegCs", WORD),
    ("SegDs", WORD),
    ("SegEs", WORD),
    ("SegFs", WORD),
    ("SegGs", WORD),
    ("SegSs", WORD),
    ("EFlags", DWORD),

    ("Dr0", DWORD64),
    ("Dr1", DWORD64),
    ("Dr2", DWORD64),
    ("Dr3", DWORD64),
    ("Dr6", DWORD64),
    ("Dr7", DWORD64),

    ("Rax", DWORD64),
    ("Rcx", DWORD64),
    ("Rdx", DWORD64),
    ("Rbx", DWORD64),
    ("Rsp", DWORD64),
    ("Rbp", DWORD64),
    ("Rsi", DWORD64),
    ("Rdi", DWORD64),
    ("R8", DWORD64),
    ("R9", DWORD64),
    ("R10", DWORD64),
    ("R11", DWORD64),
    ("R12", DWORD64),
    ("R13", DWORD64),
    ("R14", DWORD64),
    ("R15", DWORD64),
    ("Rip", DWORD64),

    ("DebugControl", DWORD64),
    ("LastBranchToRip", DWORD64),
    ("LastBranchFromRip", DWORD64),
    ("LastExceptionToRip", DWORD64),
    ("LastExceptionFromRip", DWORD64),

    ("DUMMYUNIONNAME", DUMMYUNIONNAME),

    ("VectorRegister", M128A * 26),
    ("VectorControl", DWORD64)
]

注意:此定义位于WinNT.h中 – 如果安装了VC,它将位于安装它的/ include目录中.

一旦建立了这个结构,你就可以使用它而不是你构建的CONTEXT / WOW64语境.您还必须明显将寄存器更改为RAX等.

(注意:你还需要在Python ctypes中实现4个其他的东西:DWORD64,M128A,DUMMYUNIONNAME,DUMMYSTRUCTNAME和XMM_SAVE_AREA32.为简洁起见,我已将它们排除在外,但您可以在以下位置找到它们的定义来构建他们自己:

DWORD64:只是一个c_ulonglong

DUMMYUNIONNAME,DUMMYSTRUCTNAME:在_CONTEXT结构中的WinNT.h中

M128A:http://winappdbg.sourceforge.net/doc/v1.3/winappdbg.win32.defines.M128A-class.html

XMM_SAVE_AREA32:http://winappdbg.sourceforge.net/doc/v1.3/winappdbg.win32.context_amd64.XMM_SAVE_AREA32-class.html

上一篇:python – 在eclipse中导入matplotlib


下一篇:Hadoop遇到的问题