# -*- coding: cp949 -*-
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
self.h_thread = None
self.context = None
# Here let's determine and store
# the default page size for the system
# determine the system page size.
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
# 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
# 새로 생성한 프로세스의 핸들을 구한 후
# 나중에 접근하기 위해 저장한다.
self.h_process = self.open_process(process_information.dwProcessId)
else:
print "[*] Error : 0x%08x." % kernel32.GetLastError()
def open_process(self,pid):
# PROCESS_ALL_ACCESS = 0x0x001F0FFF
h_process = kernel32.OpenProcess(PROCESS_ALL_ACCESS,False,pid)
return h_process
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):
thread_entry = THREADENTRY32() # Thread32First 실행인자로 전달되는 구조체
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.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS
# 스레드의 핸들을 구한다.
h_thread = self.open_thread(thread_id)
if kernel32.GetThreadContext(h_thread, byref(context)):
# 레지스터 정보를 얻기 위해서 GetThreadContext 함수를 사용한다.
kernel32.CloseHandle(h_thread)
return context
else:
return False
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 run(self):
# 이제 디버기에 대한 디버그 이벤트를 처리해야 한다.
# 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):
# 아직은 디버그 이벤트를 처리할 핸들러를 작성하지 않았다.
# 따라서 여기서는 단순히 프로세스가 실행을 계속하게 만든다.
raw_input("Press a key to continue...")
self.debugger_active = False
kernel32.ContinueDebugEvent(
debug_event.dwProcessId,
debug_event.dwThreadId,
continue_status )
def detach(self):
if kernel32.DebugActiveProcessStop(self.pid):
print "[*] Finished debugging. Exiting..."
return True
else:
print "There was an error"
return False
지식 출처 :
http://scytalezz.tistory.com/21