[2주] 03장 - 윈도우 디버거 개발 (3)
디버거는 cpu 레지스터의 상태정보를 캡쳐하고 변경할 수 있어야 한다.
이 글에서는 디버깅 대상 프로세스의 현재 실행중인 스레드 핸들을 얻어 레지스터 값을 출력할 것이다.
#my_debugger.py
#-*- coding: utf-8 -*-
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 플래그를 이용해 프로세스를 어떻게 생성할 것인지 판단.
# 계산기의 GUI를 보고자 한다면 creation_flags를 CREATE_NEW_CONSOLE로 설정
creation_flags = DEBUG_PROCESS
#구조체 인스턴트화
startupinfo = STARTUPINFO()
process_information = PROCESS_INFORMATION()
# 프로세스가 독립적인 창으로 실행되게 해줌
# STARTUPINFO struct 구조체내용에따라 디버기프로세스에 어떤영향을 미치는지 보여줌
startupinfo.dwFlags = 0x1
startupinfo.wShowWindow = 0x0
# STARTUPINFO struct 구조체 자신의 크기를 나타내는 cb 변수값을 초기화
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_infomation.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 run(self):
#디버기에 대한 디버그 이벤트를 처리
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):
#아직 디버그이벤트를 처리한 핸들러 구현x 단순히 프로세스가 실행을 계속하게 함
#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
def open_thread (self,thread_id):
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()
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 not h_thread:
self.open_thread(thread_id)
#스레드의 핸들을 구한다.
h_thread = self.open_thread(thread_id)
if kernel32.GetThreadContext(h_thread, byref(context)):
kernel32.CloseHandle(h_thread)
return context
else:
return False
#-*- coding: utf-8 -*-
import my_debugger
debugger = my_debugger.debugger()
pid = raw_input("Enter the PID of the process to attach to: ")
debugger.attach(int(pid))
list = debugger.enumerate_threads()
#스레드 리스트의 각 스레드에 대한 레지스터 값을 출력
for thread in list:
thread_context = debugger.get_thread_context(thread)
print "[*] Dumping registers for thread ID : 0x%08x" % thread
print "[**] EIP:0x%08x" %thread_context.Eip
print "[**] ESP:0x%08x" %thread_context.Esp
print "[**] EBP:0x%08x" %thread_context.Ebp
print "[**] EAX:0x%08x" %thread_context.Eax
print "[**] EBX:0x%08x" %thread_context.Ebx
print "[**] ECX:0x%08x" %thread_context.Ecx
print "[**] EDX:0x%08x" %thread_context.Edx
print "[*] END DUMP"
debugger.detach()
my_test.py 실행결과
Enter the PID of the process to attach to: 1092 [*] Dumping registers for thread ID : 0x00000ddc [**] EIP:0x77a170b4 [**] ESP:0x0016ed58 [**] EBP:0x0016ed74 [**] EAX:0x002df130 [**] EBX:0x00000000 [**] ECX:0x76f4372c [**] EDX:0x002df130 [*] END DUMP [*] Dumping registers for thread ID : 0x00000fb0 [**] EIP:0x77a170b4 [**] ESP:0x00a2fd28 [**] EBP:0x00a2fdc4 [**] EAX:0x747887f8 [**] EBX:0x00a2fd78 [**] ECX:0x00000300 [**] EDX:0x77a170b4 [*] END DUMP [*] Dumping registers for thread ID : 0x0000080c [**] EIP:0x77a170b4 [**] ESP:0x02cffc2c [**] EBP:0x02cffcd4 [**] EAX:0x00000001 [**] EBX:0x00000000 [**] ECX:0x002ae6d8 [**] EDX:0x77a170b4 [*] END DUMP [*] Dumping registers for thread ID : 0x00000244 [**] EIP:0x77a170b4 [**] ESP:0x02e3fde0 [**] EBP:0x02e3ff74 [**] EAX:0x02e3ff24 [**] EBX:0x779ffe90 [**] ECX:0x00000000 [**] EDX:0x779ffd0f [*] END DUMP [*] Dumping registers for thread ID : 0x0000035c [**] EIP:0x77a17098 [**] ESP:0x01c0fcdc [**] EBP:0x00000000 [**] EAX:0x77a6f125 [**] EBX:0x00000000 [**] ECX:0x00000000 [**] EDX:0x00000000 [*] END DUMP [*] Finished debugging. Exiting...레지스터 상태 캡쳐성공
'Study > 파이썬 해킹 프로그래밍' 카테고리의 다른 글
| [2주] 03장 - 윈도우 디버거 개발 (5) (0) | 2015.01.19 |
|---|---|
| [2주] 03장 - 윈도우 디버거 개발 (4) (1) | 2015.01.19 |
| [2주] 03장 - 윈도우 디버거 개발 (2) (0) | 2015.01.18 |
| [2주] 03장 - 윈도우 디버거 개발 (1) (0) | 2015.01.17 |
| api 기초 (0) | 2015.01.12 |