'회색 모자 파이썬'을 읽고 있습니다.파이썬 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
의 매개 변수로 사용했습니다. 다시는 그럴 필요가 없습니다.
=============== 여전히 다른 오류에 대한 해결책을 찾지 못했습니다. ContinueDebugEvent
은 EXIT_THREAD_DEBUG_EVENT
으로 끝나지 않습니다.
나는 문제가 있어요 같은 코드로,하지만 내 경우에는 코드를 잘 컴파일, 문제 : 코드에 의해 인쇄 된 레지스터의 내용은 항상 : 0x00000000 코드가 32 비트 플랫폼에서만 작동하는 것처럼 보입니다 –
x64에서 실행되도록 32 비트 코드를 변경하는 방법은 무엇입니까? win32API 함수 호출과 ctypes 만 업데이트해야합니까? 또는 x64와 호환되지 않는 파이썬 코드입니까? 이 책의 모든 코드를 x64 코드로 다시 파이썬 스킬 향상을위한 부수 프로젝트로 다시 작성하는 데 관심이 있습니다. @ a.u.r – Info5ek