2013-05-09 1 views
0

'회색 모자 파이썬'을 읽고 있습니다.파이썬 WaitForDebugEvent 및 ContinueDebugEvent (회색 모자 Python)

프로세스의 스레드를 가져 와서 모든 레지스터 값을 덤프하는 예제가 있습니다.

나는 책에서 근원을 아래로 베낀 것이 작동하지 않을 것이다.

다음은 내가 생각하는 문제의 일부입니다.

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은, 그것은 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을 호출 한 직후에 프로그램을 종료합니다.

이 두 가지가 관련되어 있는지는 확실하지 않지만 업데이트와는 관련이 없습니다.

대단히 감사합니다.

PART 솔루션은

나는 코드에서 하나의 큰 오류를 발견했습니다.

책에 일종의 편집 된 버전이 있는지 여부는 확실하지 않습니다.

어쨌든 내 문제 중 하나는 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의 매개 변수로 사용했습니다. 다시는 그럴 필요가 없습니다.

=============== 여전히 다른 오류에 대한 해결책을 찾지 못했습니다. ContinueDebugEventEXIT_THREAD_DEBUG_EVENT으로 끝나지 않습니다.

+0

나는 문제가 있어요 같은 코드로,하지만 내 경우에는 코드를 잘 컴파일, 문제 : 코드에 의해 인쇄 된 레지스터의 내용은 항상 : 0x00000000 코드가 32 비트 플랫폼에서만 작동하는 것처럼 보입니다 –

+0

x64에서 실행되도록 32 비트 코드를 변경하는 방법은 무엇입니까? win32API 함수 호출과 ctypes 만 업데이트해야합니까? 또는 x64와 호환되지 않는 파이썬 코드입니까? 이 책의 모든 코드를 x64 코드로 다시 파이썬 스킬 향상을위한 부수 프로젝트로 다시 작성하는 데 관심이 있습니다. @ a.u.r – Info5ek

답변

3

이 책의 코드는 32 비트 플랫폼에서만 작동합니다. 또한 출처에는 책 웹 사이트에 기록되어 프로그램 작동을 중지시키는 몇 가지 버그가 있습니다.사이트에서 소스를 다운로드하면이 버그가 제거되었습니다.

컴퓨터에서 코드를 실행하고 x64를 실행하려면 Microsoft에서 무료로 제공하는 가상의 32 비트 Windows XP 환경 인 "Windows XP 모드"를 다운로드 할 수 있습니다. http://www.microsoft.com/en-us/download/details.aspx?id=3702. Python IDE를 거기에 설치하면 코드가 실행됩니다.

+0

32 비트? 머리를 가져 주셔서 감사합니다. 나는 64를 달리고 몇몇 문제가있다. – Vnge

0

64 비트 창에서 64 비트 파이썬 인스턴스에서 디버거를 실행하기위한 솔루션이 있습니다. 하지만 당신은 32 비트 응용 프로그램을 디버깅하거나 64 비트 디버거를 구현해야합니다. 64 비트와 64 비트 사이의 차이점이 있습니다.

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