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)

これらの 2 行は前の例で使用され、この例ではコメント化されています。

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

これらの 2 行はコメントアウトされています。問題は、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です。

これら2つが関連しているかどうかはわかりませんが、更新として。

どうもありがとうございました。

パーツソリューション

コードに 1 つの大きなエラーが見つかりました。

本に何らかの編集版があるかどうかはわかりません。

とにかく、私の問題の 1 つは、それ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 ビット プラットフォームでのみ動作することが確認されています。また、書籍の Web サイトに記載されているソースには、プログラムが動作しなくなるバグがいくつかあります。サイトからソースをダウンロードすると、これらのバグは削除されています。

コードを取得して x64 を実行しているマシンで実行する場合は、Microsoft が無料で提供している仮想 32 ビット Windows XP 環境である「Windows XP モード」をダウンロードできます。http://www.microsoft.com/en-us/download/details.aspx?id=3702 . そこに Python IDE をインストールすると、コードが実行されます。

于 2013-08-04T04:01:10.817 に答える
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 に答える