[2주] 03장 - 윈도우 디버거 개발 (2)
앞서 CreateProcessA 함수를 이용해 디버거로 직접 프로세스를 실행시켜 보았다.
이번엔 두번째 방법인 디버거를 실행중인 프로세스에 붙이는(attach) 방법이다.
*-------------------------------------------------
이 책에서는 앞에서 짠 my_debugger_defines.py 외 추가적인 구조체,유니온,상수의 정의를 설명하지 않기 때문에
앞으로는 필요한 모든 정의가 되어있는 위의 파일을 쓴다.
*-------------------------------------------------
프로세스에 붙이기 위에선 먼저 해당 프로세스의 핸들을 구하여야 한다. 이 글에서 쓰일 함수들은 대부분
핸들을 필요로 한다.
프로세스 핸들을 얻기 위해 사용하는 함수는 OpenProcess()이다.
#OpenProcess() 프로토타입
#kernel32.dll에서 익스포트
HANDLE WINAPI OpenProcess(
DWORD dwDesiredAccess, #어떤 종류의 접근 권한을 가진 프로세스 핸들을 원하는지 입력
BOOL bInheritHandle #항상 False 값으로 설정
DWORD dwProcessId #핸들을 얻고자 하는 프로세스의 PID 입력
);
프로세스에 붙일 때는 DebugActiveProcess() 함수 이용
#DebugActiveProcess() 프로토타입
BOOL WINAPI DebugActiveProcess(
DWORD dwProcessId #attach할 프로세스이 PID
);
디버거는 WaitForDebugEvent() 함수를 이용해 디버그 이벤트를 처리한다.
#WaitForDebugEvent() 프로토타입
BOOL WINAPI WaitForDebugEvent(
LPDEBUG_EVENT lpDebugEvent, #DEBUG_EVENT 구조체에 대한 포인터
DWORD dwMilliseconds #INFINITE로 설정하면 디버그이벤트가 발생할 때까지 리턴x
);
ContinueDebugEvent()는 각 이벤트 핸들러의 작업이 완료되면 프로세스가 실행을 계속하게 만들어준다.
#ContinueDebugEvent() 프로토타입
BOOL WINAPI ContinueDebugEvent(
DWORD dwProcessId,
DWORD dwThreadId,
DWORD dwContinueStatus
);
아래는 위 함수들을 이용해 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
아래는 테스트를 위한 코드
#my_test.py
import my_debugger
debugger = my_debugger.debugger()
pid = raw_input("Enter the PID of the process to attach to: ")
debugger.attach(int(pid))
debugger.run()
계산기를 실행시킨 후 작업관리자를 열어 PID를 확인한다. 현재 PID는 536.
이제 python으로 my_test.py를 실행시켜보자
Enter the PID of the process to attach to: 536
Press a key to continue...
위처럼 떴을 때 계산기의 GUI를 확인해보면 현재 프로세스가 일시정지되어 있는 상태이기 때문에
버튼이나 메뉴를 눌러도 반응이 없는것을 알 수 있다. 엔터를 누르면 종료된다.
'Study > 파이썬 해킹 프로그래밍' 카테고리의 다른 글
| [2주] 03장 - 윈도우 디버거 개발 (4) (1) | 2015.01.19 |
|---|---|
| [2주] 03장 - 윈도우 디버거 개발 (3) (0) | 2015.01.19 |
| [2주] 03장 - 윈도우 디버거 개발 (1) (0) | 2015.01.17 |
| api 기초 (0) | 2015.01.12 |
| [1주] 02장-디버거 (0) | 2015.01.12 |
my_debugger_defines .py