0

我正在阅读“灰帽蟒蛇”。

有一个示例,我们获取进程的线程并转储所有寄存器值。

我把书上的源码抄下来了,还是不行。

这是我认为有问题的部分来源。

def run(self):
    # Now we have to poll the debuggee for debugging events

    while self.debugger_active == True:
        self.get_debug_event()

def get_debug_event(self):

    debug_event     = DEBUG_EVENT()
    continue_status = DBG_CONTINUE

    if kernel32.WaitForDebugEvent(byref(debug_event), INFINITE):

        # We aren't going to build any event handlers
        # just yet. Let's just resume the process for now.
        # raw_input("Press a key to continue...")
        # self.debugger_active = False
        kernel32.ContinueDebugEvent(debug_event.dwProcessId, debug_event.dwThreadId, continue_status)

这两行用于前面的示例,并在这一行中被注释掉。

# raw_input("Press a key to continue...")
# self.debugger_active = False

这两行被注释掉了问题是当self.debugger_active为True时,它会运行WaitForDebugEvent和ContinueDebugEvent。

但不要打开线程或任何东西。它只运行了 39 次,我不知道为什么。

这是完整的来源。

from ctypes import *
from my_debugger_defines import *

kernel32 = windll.kernel32

class debugger():

    def __init__(self):
        self.h_process          = None
        self.pid                = None
        self.debugger_active    = False

    def load(self, path_to_exe):


        # dwCreation flag determines how to create the process
        # set creation_flags = CREATE_NEW_CONSOLE if you want
        # to see the calculator GUI
        creation_flags = DEBUG_PROCESS

        # instantiate the structs
        startupinfo         = STARTUPINFO()
        process_information = PROCESS_INFORMATION()

        # The following two options allow the started process
        # to be shown as a separate window. This also illustrates
        # how different settings in the STARTUPINFO struct can affect the debuggee
        startupinfo.dwFlags     = 0x1
        startupinfo.wShowWindow = 0x0

        # We then initialize the cb variable in the STARTUPINFO struct
        # which is just the size of the struct itself
        startupinfo.cb = sizeof(startupinfo)

        if kernel32.CreateProcessA(path_to_exe,
                                   None,
                                   None,
                                   None,
                                   None,
                                   creation_flags,
                                   None,
                                   None,
                                   byref(startupinfo),
                                   byref(process_information)):

            print "[*] We have successfully launched the process!"
            print "[*] PID: %d" % process_information.dwProcessId

            # Obtain a valid handle to the newly created process
            # and store it for future access

            self.h_process = self.open_process(process_information.dwProcessId)

        else:
            print "[*] Error: 0x%08x." % kernel32.GetLastError()

    def open_process(self, pid):

        h_process = kernel32.OpenProcess(PROCESS_ALL_ACCESS, pid, False)
        return h_process

    def attach(self, pid):

        self.h_process = self.open_process(pid)

        # We attempt to attach to the process
        # if this fails we exit the call
        if kernel32.DebugActiveProcess(pid):
            self.debugger_active    = True
            self.pid                = int(pid)
            self.run()

        else:
            print "[*] Unable to attach to the process. Error: 0x%08x." % kernel32.GetLastError()

    def run(self):
        # Now we have to poll the debuggee for debugging events

        self.count = 1;
        while self.debugger_active == True:
            self.get_debug_event()

    def get_debug_event(self):

        debug_event     = DEBUG_EVENT()
        continue_status = DBG_CONTINUE

        if kernel32.WaitForDebugEvent(byref(debug_event), INFINITE):

            # We aren't going to build any event handlers
            # just yet. Let's just resume the process for now.
            # raw_input("Press a key to continue...")
            # self.debugger_active = False
            kernel32.ContinueDebugEvent(debug_event.dwProcessId, debug_event.dwThreadId, continue_status)
            print "Just finished ContinueDebugEvent %d" % self.count
            self.count += 1

    def detach(self):

        if kernel32.DebugActiveProcessStop(self.pid):
            print "[*] Finished debugging. Exiting..."
            return True
        else:
            print "There was an error finishing debugging"
            return False

    def open_thread(self, thread_id):

        print "open_thread"
        h_thread = kernel32.OpenThread(THREAD_ALL_ACCESS, None, thread_id)

        if h_thread is not None:
            return h_thread

        else:
            print "[*] Could not obtain a valid thread handle."
            return False

    def enumerate_threads(self):

        print "enumerate_threads"
        thread_entry    = THREADENTRY32()
        thread_list     = []
        snapshot        = kernel32.CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, self.pid)

        if snapshot is not None:
            # You have to set the size of the struct
            # or the call will fail
            thread_entry.dwSize = sizeof(thread_entry)
            success             = kernel32.Thread32First(snapshot, byref(thread_entry))

            while success:
                if thread_entry.th32OwnerProcessID == self.pid:
                    thread_list.append(thread_entry.th32ThreadID)
                success = kernel32.Thread32Next(snapshot, byref(thread_entry))

            kernel32.CloseHandle(snapshot)
            return thread_list

        else:
            return False

    def get_thread_context(self, thread_id):

        print "get_thread_context"
        context                 = CONTEXT()
        context.ContextFlags    = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS

        # Obtain a handle to the thread
        h_thread = self.open_thread(thread_id)

        if kernel32.GetThreadContext(h_thread, byref(context)):
            kernel32.CloseHandle(h_thread)
            return context

        else:
            return False 

添加

我调试了一下,发现当get_thread_context被调用时,它总是返回false。

此外,在结束时ContinueDebugEvent,它不会调用EXIT_THREAD_DEBUG_EVENT. 它只是在调用后立即终止程序EXEPTION_DEBUG_EVENT

我不确定这两个是否相关,但只是作为更新。

非常感谢你。

部分解决方案

我在代码中发现了一个巨大的错误。

我不知道这本书是否有某种编辑版本。

无论如何,我的一个问题是它get_thread_context不起作用。

源应更改为

def get_thread_context(self, h_thread):

    context                 = CONTEXT()
    context.ContextFlags    = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS

    if kernel32.GetThreadContext(h_thread, byref(context)):
        kernel32.CloseHandle(h_thread)
        return context

    else:
        return False 

出于某种原因,书中的来源将线程句柄作为open_thread. 您之前已经获得了线程句柄,并将其作为get_thread_context. 所以没必要再这样了。

=============== 仍然没有找到其他错误的任何解决方案。这ContinueDebugEvent不会以EXIT_THREAD_DEBUG_EVENT.

4

3 回答 3

3

经确认,本书的代码仅适用于 32 位平台。此外,书籍网站上指出的源代码中存在一些错误,这些错误将阻止程序运行。如果您从该站点下载源代码,这些错误已被删除。

如果您想让代码在您的机器上运行并运行 x64,您可以下载“Windows XP 模式”,它是微软免费提供的虚拟 32 位 Windows XP 环境。http://www.microsoft.com/en-us/download/details.aspx?id=3702。在那里安装你的 Python IDE,代码应该会运行。

于 2013-08-04T04:01:10.817 回答
0

有一个解决方案可以在 64 位窗口上从 64 位 python 实例运行调试器。但是你应该坚持调试 32 位应用程序或实现 64 位调试器,64 和 32 位寄存器之间存在差异。

我添加了一些代码在 64 位系统下运行它。1. 如果您想在 64 位窗口上调试/运行 32 位应用程序。Windows 使用 Wow64,因此您必须使用 msdn 上解释的其他一些功能。

要测试进程是否在 wow64 中以 32 位运行:

 i = c_int()
 kernel32.IsWow64Process(self.h_process,byref(i))
 if i:
     print('[*] 32 bit process')

例子:

def wow64_get_thread_context(self,thread_id=None,h_thread=None):
    context = CONTEXT()
    context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS
    if h_thread is None:
        h_thread = self.open_thread(thread_id)
    if kernel32.Wow64SuspendThread(h_thread) != -1:
        if kernel32.Wow64GetThreadContext(h_thread,byref(context)) != 0:
            kernel32.ResumeThread(h_thread) 
            kernel32.CloseHandle(h_thread)
            return context
        else:
            testWinError()
            return False
    else:
        testWinError()
        return False

要测试获胜错误,请使用:

def testWinError():
    if kernel32.GetLastError() != 0:
        raise WinError()
于 2015-04-28T20:07:58.163 回答
0

OpenProcess有另一个签名。

HANDLE OpenProcess(
  DWORD dwDesiredAccess,
  BOOL  bInheritHandle,
  DWORD dwProcessId
);

所以你应该把 openprocess 改成

def open_process(self, pid):

    # h_process = kernel32.OpenProcess(PROCESS_ALL_ACCESS, pid, False)
    h_process = kernel32.OpenProcess(PROCESS_ALL_ACCESS, False, pid)
    return h_process
于 2018-07-22T17:46:32.967 回答