Pyhtonによるデバッガ (Windows)

リバースエンジニアリング ―Pythonによるバイナリ解析技法 (Art Of Reversing)

リバースエンジニアリング ―Pythonによるバイナリ解析技法 (Art Of Reversing)

最近これを読んでます。 これのメモを以下に書く。

プロセスの起動

if kernel32.CreateProcessA(path_to_exe,
                                   None,
                                   None,
                                   None,
                                   None,
                                   creation_flag,
                                   None,
                                   None,
                                   byref(startupinfo),
                                   byref(process_information)):
            print "[*] We have successfully  lanched the process!"
            print "[*] PID: %d" % process_information.dwProcessId
else:
            print "[*] Error: 0x%08x." % kernel32.GetLastError()

プロセスのハンドルを取得

def open_process(self, pid):
        # プロセスのハンドルを取得
        h_process = kernel32.OpenProcess(PROCESS_ALL_ACCESS, False, pid)
        return h_process

プロセスにアタッチ

    def attach(self, pid):
        self.h_process = self.open_process(pid)

        if kernel32.DebugActiveProcess(pid):
            self.debugger_active = True
            self.pid = int(pid)
        else:
            print "[*] Unable to attach to the process."

プロセスのデタッチ

def detach(self):
        # プロセスの切り離し
        if kernel32.DebugActiveProcessStop(self.pid):
            print "[*} Finished debugging Exiting..."
            return True
        else:
            print "There is an error"
            return False

スレッドのハンドルを取得

def open_thread(self, thread_id):
        # スレッドのハンドルを取得
        h_thread = kernel32.OpenThread(THREAD_ALL_ACCESS, None, thread_id)
        if h_thread is not 0:
            return h_thread
        else:
            print "[*] Could not obtain a valid handle"
            return False

指定したプロセスのスレッドを取得

def enumerate_threads(self):
        thread_entry = THREADENTRY32()
        thread_list = []
        # スレッドの列挙
        snapshot = kernel32.CreateToolhelp32Snapshot(
            TH32CS_SNAPTHREAD, self.pid
        )

        if snapshot is not None:
            # 構造体のサイズを指定しないと呼び出しが失敗する
            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=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.GetThreadContext(h_thread, byref(context)):
            kernel32.CloseHandle(h_thread)
            return context
        else:
            return False

イベントの捕捉

 # イベントの捕捉 (例:レジスタの値の取得)
        if kernel32.WaitForDebugEvent(byref(debug_event), INFINITE):

            self.h_thread = self.open_thread(debug_event.dwThreadId)
            self.context = self.get_thread_context(h_thread=self.h_thread)

            print "Event Code: %d Thread ID: %d" % (debug_event.dwDebugEventCode, debug_event.dwThreadId)

            # 実行の再開
            kernel32.ContinueDebugEvent(
                debug_event.dwProcessId,
                debug_event.dwThreadId,
                continue_status )

以上のコードは本のサンプルコードを用いている。