[3주] 05장 - Immunity Debugger 공격코드에서 사용할 명령찾기

Posted by dw0rdptr
2015. 1. 26. 07:31 Study/파이썬 해킹 프로그래밍

Immunity 디버거의 파이썬 라이브러리를 이용하면 로드된 바이너리에서 원하는 명령을 쉽게 찾을 수 있다.



작성한 코드를 Immunity Debugger\PyCommands 폴더에 넣고 디버거 명령줄에 !findinstruction<찾을 명령>

을 입력하면 된다. jmp esp 명령을 찾아보려면

!findinstruction jmp esp

메뉴의 View->Log(단축키 Alt+L)로 확인 할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 
 
#findinstruction.py
#-*- coding: utf-8 -*-
from immlib import *
 
def main(args):
    imm = Debugger()
    search_code = " ".join(args)
    search_byte = imm.assemble(search_code)
    search_results = imm.search(search_byte)
 
    for hit in search_results:
        #메모리 페이지를 구하고 실행 가능한 것인지 확인
        code_page = imm.getMemoryPageByAddress(hit)
        access = code_page.getAccess(human = True)
 
        if "execute" in access.lower():
            imm.log("[*] Found : %s (0x%08x)" % (search_code, hit), address = hit)
 
    return "[*] Finish searching for instructions, check the Log window."
 
cs



'Study > 파이썬 해킹 프로그래밍' 카테고리의 다른 글

[3주] 05장~06장 후킹  (0) 2015.01.26
[3주] 05장 - 윈도우 DEP우회  (0) 2015.01.26
[3주] 04장 - 종합  (0) 2015.01.26
[3주] 04장 - 프로세스 스냅샷  (0) 2015.01.26
[3주] 04장 - 접근 위반 핸들러  (0) 2015.01.26

[3주] 04장 - 종합

Posted by dw0rdptr
2015. 1. 26. 06:36 Study/파이썬 해킹 프로그래밍

악용될 수 있는 소프트웨어 애플리케이션의 결함을 제거하는데 도움이 되는 유틸리티프로그램을 짜보자


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#danger_track.py
#-*- coding: utf-8 -*-
from pydbg import *
from pydbg.defines import *
 
import utils
 
#접근 위반이 발생한 후에 조사할 명령의 최대 개수
MAX_INSTRUCTIONS = 10
 
 
#다음은 모든 위험한 한수에 포함하는 완벽한 리스트는 아니다.
dangerous_functions = { "strcpy" : "msvcrt.dll""strncpy" : "msvcrt.dll"
                                "sprintf" : "msvcrt.dll""vsprintf" : "msvcrt.dll"}
dangerous_functions_resolved = {}
crash_encountered = False
instruction_count = 0
 
def danger_handler(dbg):
    #스택의 내용을 출력한다.
    #일반적으로 몇 개의 파라미터만을 사용하기 때문에 ESP~ESP+20 내용만 출력해도됨
    esp_offset = 0
    print "[*] Hit %s" % dangerous_functions_resolved[dbg.context.Eip]
    print "============================================================"
 
    while esp_offset <=20:
        parameter = dbg.smart_dereference(dbg.context.Esp + esp_offset)
        print "[ESP + %d] => %s " % (esp_offset, parameter)
        esp_offset += 4
 
    print "============================================================"
 
    dbg.suspend_all_threads()
    dbg.process_snapshot()
    dbg.resume_all_threads()
 
    return DBG_CONTINUE
 
def access_violation_handler(dbg):
    global crash_encountered
 
    #접근 위반을 처리하고 프로세스를 마지막 위험한 함수가 호출된 시점으로 되돌림
    if dbg.dbg.u.Exception.dwFirstChance:
        return DBG_EXCEPTION_NOT_HANDLED
 
 
    crash_bin = utils.crash_binning.crash_binning()
    crash_bin.record_crash(dbg)
    print crash_bin.crash_synopsis()
 
    if crash_encountered == False:
        dbg.suspend_all_threads()
        dbg.process_restore()
        crash_encountered = True
 
        for thread_id in dbg.enumerate_threads():
            print "[*] Setting single step for thread: 0x%08x" % thread_id
            h_thread = dbg.open_thread(thread_id)
            dbg.single_step(True, h_thread)
            dbg.close_handle(h_thread)
 
        #단일 스탭 핸들러에게 제어권을 넘기기위해 프로세스를 다시 실행되게만든다
        dbg.resume_all_threads()
 
        return DBG_CONTINUE
    else:
        dbg.terminate_process()
 
    return DBG_EXCEPTION_NOT_HANDLED
 
def single_step_handler(dbg):
    global instruction_count
    global crash_encountered
 
    if crash_encountered:
        if instruction_count == MAX_INSTRUCTIONS:
                dbg.single_step(False)
                return DBG_CONTINUE
        else:
            #명령을 디스어셈블.
            instruction = dbg.disasm(dbg.context.Eip)
            print "#%d\t0x%08x : %s" % (instruction_count, dbg.context.Eip, instruction)
            instruction_count +=1
            dbg.single_step(True)
 
    return DBG_CONTINUE
 
dbg = pydbg()
pid = int(raw_input("Enter the PID you wish to monitor :"))
dbg.attach(pid)
 
#리스트의 모든 위험한 함수를 호출하고 브레이크포인트설정
 
for func in dangerous_functions.keys():
 
    func_address = dbg.func_resolve(dangerous_functions[func],func)
    print "[*] Resolved breakpoint: %s -> 0x%08x" % (func,func_address)
    dbg.bp_set(func_address, handler = danger_handler)
    dangerous_functions_resolved[func_address] = func
 
dbg.set_callback( EXCEPTION_ACCESS_VIOLATION, access_violation_handler)
dbg.set_callback(EXCEPTION_SINGLE_STEP, single_step_handler)
dbg.run()
 
 
cs


buffer_overflow.py에 붙인 결과


restore에서 자꾸 매개변수가 틀리다는 에러가뜨는데 왜그런지는 모르겠다


[3주] 04장 - 프로세스 스냅샷

Posted by dw0rdptr
2015. 1. 26. 06:02 Study/파이썬 해킹 프로그래밍

스냅샷은 대상 프로세스의 어떤 특정 시점을 저장한다.

스냅샷을 만든 이후에는 언제든지 프로세스의 상태를 스냅샷 생성 시점으로 되돌릴 수 있다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#snapshot.py
#-*- coding: utf-8 -*-
from pydbg import *
from pydbg.defines import *
 
import threading
import time
import sys
 
class snapshotter(object):
 
    def __init__(self,exe_path):
 
        self.exe_path = exe_path
        self.pid      = None
        self.dbg      = None
        self.running  = True
 
        #디버거 스레드시작, 대상 프로세스의 PID가 설정될 떄까지 루프돔
        pydbg_thread = threading.Thread(target = self.start_debugger)
        pydbg_thread.setDaemon(0)
        pydbg_thread.start()
 
        while self.pid == None:
            time.sleep(1)
 
        #현재 PID가 설정된 상태이고 대상 프로세스가 실행중.
        #스냅샷을 위한 두 번째 스레드 실행
        monitor_thread = threading.Thread(target=self.monitor_debugger)
        monitor_thread.setDaemon(0)
        monitor_thread.start()
 
 
    #스냅샷을 만들것인지 복원할것인지 종료할것인지 명령입력
    def monitor_debugger(self):
        while self.running == True:
            input = raw_input("Enter: 'snap', 'restore' or 'quit' :")
            input = input.lower().strip()
 
            if input == "quit":
                print "[*] Exiting the snapshotter."
                self.running = False
                self.dbg.terminate_process()
 
            elif input == "snap":
                print "[*] Suspending all threads."
                self.dbg.suspend_all_threads()
 
                print "[*] Obtaining snapshot"
                self.dbg.process_snapshot()
 
                print "[*] Resuming operation."
                self.dbg.resume_all_threads()
 
            elif input == "restore":
                print "[*] Suspending all threads."
                self.dbg.suspend_all_threads()
 
                print "[*] Restoring snapshot."
                self.dbg.process_restore()
 
                print "[*] Resuming operation."
                self.dbg.resume_all_threads()
 
    def start_debugger(self):
        self.dbg = pydbg()
        pid = self.dbg.load(self.exe_path)
        self.pid = self.dbg.pid
 
        self.dbg.run()
 
exe_path = "C:\\Windows\\System32\\calc.exe"
snapshotter(exe_path)
 
 
 
cs

#계산기로 프로세스 스냅샷 기능이 동작하는 것을 확인 가능


[3주] 04장 - 접근 위반 핸들러

Posted by dw0rdptr
2015. 1. 26. 05:48 Study/파이썬 해킹 프로그래밍

접근 위반은 접근할 권한이 없는 메모리에 접근하려고 하거나 허용되지 않은 방법으로 메모리에 접근하려고 할 때

프로세스 내부에서 발생한다.

PyDbg로 예외와 관련된 정보를 얻을 수 있는 함수들을 사용할 수 있다.


strcpy()함수를 이용해 버퍼오버플로우를 발생시키는 프로그램의 접근 위반을 처리하는 PyDbg 스크립트를 짜보자.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
#buffer_overflow.py
from ctypes import *
 
msvcrt = cdll.msvcrt
 
raw_input("Once the debugger is attached, press any key.")
 
buffer = c_char_p("AAAAA")
 
overflow = "A" * 100
 
msvcrt.strcpy(buffer, overflow)
 
 
cs



이제 접근위반을 처리하는 스크립트를 짠다
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#access_violation_handler.py
from pydbg import *
from pydbg.defines import *
 
# Utility libraries included with pydbg
import utils
 
def check_accessv(dbg):
 
    if dbg.dbg.u.Exception.dwFirstChance:
        return DBG_EXCEPTION_NOT_HANDLED
 
    crash_bin = utils.crash_binning.crash_binning()
    crash_bin.record_crash(dbg)
    print crash_bin.crash_synopsis()
 
    dbg.terminate_process()
 
    return DBG_EXCEPTION_NOT_HANDLED
 
pid = raw_input("Enter the Process ID : ")
 
dbg = pydbg()
dbg.attach(int(pid))
dbg.set_callback(EXCEPTION_ACCESS_VIOLATION, check_accessv)
dbg.run()
 
 
 
cs


1. buffer_overflow.py 실행
2. PID 확인
3. access_violation_handler.py 실행하고 PID 입력
4. buffer_overflow.py 프로세스가 계속 실행할 수 있도록 엔터키를 누름

결과

1. 접근위반예외를 발생시킨 명령과 그 명령이 속한 모듈을 알려줌

2. 모든 레지스터의 컨텍스트 정보를 보여줌

3. 예외를 발생시킨 명령어 주위에 잇는 명령을 디스어셈블해 보여줌

4. 예외가 발생했을 때 등록되는 SEH(structured exception handling) 핸들러 리스트를 보여줌


[3주] 04장 - 브레이크포인트 확장

Posted by dw0rdptr
2015. 1. 26. 05:17 Study/파이썬 해킹 프로그래밍

PyDbg를 이용하면 사용자 정의 콜백 함수를 구현함으로써

기본적인 이벤트 핸들러를 쉽게 확장시킬 수 있다.


디버깅 대상 프로세스 내부의 이벤트를 실제로 관찰하고 교체해보자


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#-*- coding: utf-8 -*-
from pydbg import *
from pydbg.defines import *
 
import struct
import random
 
#사용자 정의 콜백 함수
def printf_randomizer(dbg):
 
    # ESP + 0x8 위치에 있는 counter DWORD 값을 읽어들인다.
    parameter_addr = dbg.context.Esp + 0x4
    counter = dbg.read_process_memory(parameter_addr,4)
 
    #read_process_memory는 패킹된 바이너리 문자열 리턴
    #언어 언팩먼저 수행
    string_addr = struct.unpack("L",counter)[0]
 
    #"Loop iteration %d!\n" 문자열의 길이는 20바이트
    str_len = 20
 
    #문자열의 주소를 알았고, 해당 문자열의 주소에 문자열 사이즈만큼 얻어옴
    counter_string = dbg.read_process_memory(string_addr,int(str_len))
    counter_string = struct.unpack(str(str_len)+"s",counter_string)[0]
 
    #!\n은 필요가 없으므로 뺌
    counter_string = counter_string.split("!\n")[0]
 
    #앞에있는 문자열 버리고 숫자만 가져옴
    counter = counter_string[15:]
    print "Counter : %d" % int(counter)
 
    #랜덤한 숫자 생성, "Loop iteration" 뒤에 넣어줌
    random_counter = str(random.randint(1,100))
 
    #디버깅 대상 프로세스에 임의의 수를 써넣고 프로세스가 계속 실행되게만듬
    dbg.write_process_memory(string_addr + 0x0F, random_counter)
    return DBG_CONTINUE
 
#pydbg 클래스의 인스턴스
dbg = pydbg()
pid = raw_input("Enter the printf_loop.py PID:")
 
#해당 프로세스에 디버거 붙임
dbg.attach(int(pid))
 
 
#printf_randomizer 함수를 콜백함수로 등록하면서 브레이크포인트를 설정
printf_address = dbg.func_resolve("msvcrt","printf")
dbg.bp_set(printf_address, description = "printf_address", handler = printf_randomizer)
 
dbg.run()
 
 
cs


그리고 앞에서 짜놓은 printf_loop.py를 실행하고 printf_random.py에 PID를 써넣자
결과


counter 2까지는 정상적으로 루프를 수행하다가  3~부터 printf_loop의 값이 랜덤하게 나오는 것을 알 수 있다. 


[2주] 03장 - 윈도우 디버거 개발 (5)

Posted by dw0rdptr
2015. 1. 19. 19:14 Study/파이썬 해킹 프로그래밍

브레이크포인트 부분을 my_debugger에 확장


#-*- 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
		self.h_thread			= None
		self.context  			= None
		self.exception 			= None
		self.exception_address  = None
		self.breakpoints		= {}
		self.first_breakpoint 	= True

	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):
		resultMap = {
            1:"EXCEPTION_DEBUG_EVENT",
            2:"CREATE_THREAD_DEBUG_EVENT",
            3:"CREATE_PROCESS_DEBUG_EVENT",
            4:"EXIT_THREAD_DEBUG_EVENT",
            5:"EXIT_PROCESS_DEBUG_EVENT",
            6:"LOAD_DLL_DEBUG_EVENT",
            7:"UNLOAD_DLL_DEBUG_EVENT",
            8:"OUTPUT_DEBUG_STRING_EVENT",
            9:"RIP_EVENT"
        }

		debug_event = DEBUG_EVENT()
		continue_status = DBG_CONTINUE

		if kernel32.WaitForDebugEvent(byref(debug_event), INFINITE):

			#스레드의 컨텍스트 정보를 구한다.
			self.h_thread = self.open_thread(debug_event.dwThreadId)
			self.context = self.get_thread_context(h_thread=self.h_thread)
			self.debug_event = debug_event

			print "Event Code: %d Thread Id :%d"%(debug_event.dwDebugEventCode,
					debug_event.dwThreadId)

			#발생한 이벤트의 종류가 예외 이벤트이면 그것을 좀 더 자세히 조사한다.
			if debug_event.dwDebugEventCode == EXCEPTION_DEBUG_EVENT:

				#예외 코드를 구한다.
				self.exception = debug_event.u.Exception.ExceptionRecord.ExceptionCode
				self.exception_address = debug_event.u.Exception.ExceptionRecord.ExceptionAddress

				if self.exception == EXCEPTION_ACCESS_VIOLATION:
					print "Access Violation Detected"
				elif self.exception == EXCEPTION_BREAKPOINT:
					continue_status = self.exception_handler_breakpoint()
				elif self.exception == EXCEPTION_GUARD_PAGE:
					print "Guard Page Access Detected"
				elif self.exception == EXCEPTION_SINGLE_STEP:
					print "Single Stepping"

			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 h_thread is None:
			self.h_thread = self.open_thread(thread_id)

		if kernel32.GetThreadContext(self.h_thread, byref(context)):
			return context
		else:
			return False


	def exception_handler_breakpoint(self):
		 #print "[+] Inside the breakpoint handler."
		print "Exception Address: 0x%08x" % self.exception_address

		if not self.breakpoints.has_key(self.exception_address):
			if self.first_breakpoint == True:
				self.first_breakpoint = False
				print "[+] Hit the first breakpoint."
				return DBG_CONTINUE
		else:
			print "[+] Hit user defined breakpoint."
			self.write_process_memory(self.exception_address,self.breakpoints[self.exception_address])
			self.context = self.get_thread_context(h_thread=self.h_thread)
			self.context.Eip -= 0x01 # Error!
			kernel32.SetThreadContext(self.h_thread,byref(self.context))
			continue_status = DBG_CONTINUE

		return continue_status

	def read_process_memory(self,address,length):
		data		= ""
		read_buf	= create_string_buffer(length)
		count  		= c_ulong(0)

		if not kernel32.ReadProcessMemory(self.h_process,
										  address,
										  read_buf,
										  length,
										  byref(count)):
			return False

		else:

			data += read_buf.raw
			return data

	def write_process_memory(self,address,data):

		count = c_ulong(0)
		length = len(data)

		c_data = c_char_p(data[count.value:])

		kernel32.VirtualProtect(self.h_process, address, 0x40, dwSi)

		if not kernel32.WriteProcessMemory(self.h_process,
										   address,
										   c_data,
										   length,
										   byref(count)):
			return False
		else:
			return True

	def bp_set(self,address):

		if not self.breakpoints.has_key(address):
			try:
				#원래의 바이트값을 저장.
				original_byte = self.read_process_memory(address,1)
				
				#INT3 opcode를 써넣음
				self.write_process_memory(address, "\xCC")
				
				#내부 리스트에 브레이크보인트 등록
				self.breakpoints[address] = (original_byte)
				print self.breakpoints[address]
			except:
				return False

		return True

	def func_resolve(self,dll,function):
		handle = kernel32.GetModuleHandleA(dll)
		address = kernel32.GetProcAddress(handle, function)

		kernel32.CloseHandle(handle)

		return address


루프를 돌면서 printf()함수를 호출하는 테스트 프로그램
#printf_loop.py
from ctypes import *
import time

msvcrt = cdll.msvcrt
counter = 0

while 1:
	msvcrt.printf("Loop iteration %d!\n" % counter)
	time.sleep(2)
	counter +=1


printf() 함수에 브레이크포인트를 테스트 할 수 있게 변경한 테스트프로그램
#my_test.py
#-*- 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))

printf_address = debugger.func_resolve("msvcrt.dll","printf")

print "[*] Address of printf : 0x%08x" % printf_address

debugger.bp_set(printf_address)

debugger.run()

print_loop.py를 실행시키고 작업관리자로 python.exe 프로세스의 PID를 구한다.
그 후 my_test.py 스크립트를 실행시켜 python.exe의 PID를 입력한다 



결과

Enter the PID of the process to attach to: 3104
[*] Address of printf : 0x7720c5b9
Event Code: 3 Thread Id :1924
Event Code: 6 Thread Id :1924
Event Code: 6 Thread Id :1924
Event Code: 6 Thread Id :1924
Event Code: 6 Thread Id :1924
Event Code: 6 Thread Id :1924
Event Code: 6 Thread Id :1924
Event Code: 6 Thread Id :1924
Event Code: 6 Thread Id :1924
Event Code: 6 Thread Id :1924
Event Code: 6 Thread Id :1924
Event Code: 6 Thread Id :1924
Event Code: 6 Thread Id :1924
Event Code: 6 Thread Id :1924
Event Code: 6 Thread Id :1924
Event Code: 6 Thread Id :1924
Event Code: 6 Thread Id :1924
Event Code: 6 Thread Id :1924
Event Code: 6 Thread Id :1924
Event Code: 6 Thread Id :1924
Event Code: 6 Thread Id :1924
Event Code: 2 Thread Id :3852
Event Code: 1 Thread Id :3852
Exception Address: 0x77a040f0
[+] Hit the first breakpoint.
Event Code: 4 Thread Id :3852


[2주] 03장 - 윈도우 디버거 개발 (4)

Posted by dw0rdptr
2015. 1. 19. 07:40 Study/파이썬 해킹 프로그래밍

이벤트가 발생했을 때,디버거가 그 이벤트에 반응하기 위해서는 각 디버깅 이벤트에 대한 핸들러를 구현해야 한다.


WaitForDebugEvent() 함수가 이벤트가 발생할때마다 반환하는 

DEBUG_EVENT 구조체 내부의 정보를 이용해 디버깅이벤트를 어떻게 처리할 것인지 판단할 것이다.


#DEBUG_EVENT 구조체 정의
typedef struct DEBUG_EVENT {
    DWORD  dwDebugEventCode;
    DWORD dwProcessId;
    DWORD dwThreadId;
    union {
        EXCEPTION_DEBUG_INFO Exception;
        CREATE_THREAD_DEBUG_INFO CreateThread;
        CREATE_PROCESS_DEBUG_INFO CreateProcessInfo;
        EXIT_THREAD_DEBUG_INFO ExitThread;
        EXIT_PROCESS_DEBUG_INFO ExitProcess;
        LOAD_DLL_DEBUG_INFO LoadDll;
        UNLOAD_DLL_DEBUG_INFO UnloadDll;
        OUTPUT_DEBUG_STRING_INFO DebugString;
        RIP_inFo RipInfo;
       }u;
};

dwDebugEventCode를 통해 발생한 이벤트가 어떤 종류의 이벤트인지 판단한다.



이벤트코드   이벤트 코드 값                                 유니언u의 값      

Ox1         EXCEPTION DEBUG EVENT              u.Exception

Ox2         CREATE THREAD DEBUG EVENT     u.Create Thread

Ox3         CREATE PROCESS DEBUG EVENT    u.CreateProcesslnfo

Ox4         EXIT THREAD DEBUG EVENT     u.ExitThread

Ox5         EXIT PROCESS DEBUG EVENT     u.ExilProcess

Ox6         LOAD DLL DEBUG EVENT     u.LoadDII

Ox7         UNLOAD DLL DEBUG EVENT     u.UnloadDII

Ox8         OUPUT DEBUG STRING EVENT     u.DebugString

Ox9         RIP EVENT                                     u.RipInfo


위 표는 각 이벤트에 어떤 구조체를 사용해야 하는지 보여준다.



현재까지의 소스코드
#-*- 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
		self.h_thread			= None
		self.context  			= None

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

			#스레드의 컨텍스트 정보를 구한다.
			self.h_thread = self.open_thread(debug_event.dwThreadId)
			self.context = self.get_thread_context(self.h_thread)

			print "Event Code: %d Thread Id :%d"%(debug_event.dwDebugEventCode,
					debug_event.dwThreadId)
			
			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

my_test.py
#-*- 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))
debugger.run()
debugger.detach()
실행결과

CREATE_PROCESS_EVENT(0x3)이 가장 먼저 발생되었고 바로 

LOAD_DLL_DEBUG_EVENT(0x6)이 여러번 발생된 것을 알 수 있다. 

그 이후에는 CREATE_THREAD_DEBUG_EVENT(0x2)와 EXCEPTION_DEBUG_EVENT(0x1)이 발생되었다.

EXCEPTION_DEBUG_EVENT(0x1)은 윈도우가 처리하는 이벤트로서 디버거가 해당프로세스를 계속 실행되게 만들기 전에 프로세스의 상태정보를 조사할 수 있게 한다. 마지막으로 발생한 EXIT_THREAD_DEBUG_EVENT(0x4)가 발생되어 THREAD가 종료되었다는 것을 알 수 있다.





[2주] 03장 - 윈도우 디버거 개발 (3)

Posted by dw0rdptr
2015. 1. 19. 04:11 Study/파이썬 해킹 프로그래밍

디버거는 cpu 레지스터의 상태정보를 캡쳐하고 변경할 수 있어야 한다.

이 글에서는 디버깅 대상 프로세스의 현재 실행중인 스레드 핸들을 얻어 레지스터 값을 출력할 것이다.




스레드 핸들을 구해 레지스터값을 알아내는 것 까지 구현한 my_debugger 소스코드
#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...
레지스터 상태 캡쳐성공

[2주] 03장 - 윈도우 디버거 개발 (2)

Posted by dw0rdptr
2015. 1. 18. 21:53 Study/파이썬 해킹 프로그래밍

앞서 CreateProcessA 함수를 이용해 디버거로 직접 프로세스를 실행시켜 보았다. 

이번엔 두번째 방법인 디버거를 실행중인 프로세스에 붙이는(attach) 방법이다.


*-------------------------------------------------

my_debugger_defines .py

이 책에서는 앞에서 짠 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를 확인해보면 현재 프로세스가 일시정지되어 있는 상태이기 때문에

버튼이나 메뉴를 눌러도 반응이 없는것을 알 수 있다. 엔터를 누르면 종료된다.


[2주] 03장 - 윈도우 디버거 개발 (1)

Posted by dw0rdptr
2015. 1. 17. 22:12 Study/파이썬 해킹 프로그래밍

프로세스를 디버깅하려면 해당 프로세스를 연결해야하는데, 두가지 방법이 있다.


첫번째는 디버거가 직접 바이너리를 실행시키는 것이다. 이 경우에는 해당 프로세스의 코드가 실행되기 전에 제어 할 수 있다는 장점이 있으므로 악성코드나 기타 다른 형태의 악의적인 코드를 분석할 때 편리하다.

두번째 방법은 디버거를 이미 실행중인 프로세스에 attach(붙이는) 하는 방법이다. 이는 프로세스가 시작되면서 실행되는 코드를 건너뛸 수 있으며 특정 영역의 코드만을 분석할 수 있다.

윈도우에서는 이 두가지 작업을 쉽게 수행할 수 있게 하는 디버깅 api를 제공한다.

* 구동환경은 윈도우7 32bit


CreateProcessA함수로 계산기(calc.exe)를 열어보자



#my_debugger_defines.py
#-*- coding: utf-8 -*-
from ctypes import *

# ctypes 형태의 타입을 마이크로소프트의 타입으로 매핑
WORD	= c_ushort
DWORD	= c_ulong
LPBYTE	= POINTER(c_ubyte)
LPTSTR	= POINTER(c_char)
HANDLE	= c_void_p

#상수
DEBUG_PROCESS = 0x00000001
CREATE_NEW_CONSOLE = 0x00000010

#CreateProcesssA() 함수를 위한 구조체
class STARTUPINFO(Structure):
	_fields_= [
		("cb",				DWORD),
		("lpReserved",		LPTSTR),
		("lpDesktop",		LPTSTR),
		("lpTitle",			LPTSTR),
		("dwX",				DWORD),
		("dwY",				DWORD),
		("dwXSize",			DWORD),
		("dwYSize",			DWORD),
		("dwXCountChars",	DWORD),
		("dwYCountChars",	DWORD),
		("dwFillAttribute",	DWORD),
		("dwFlags",			DWORD),
		("wShowWindow",		WORD),
		("cbReserved2",		WORD),
		("lpReserved2",		LPBYTE),
		("hStdInput",		HANDLE),
		("hStdOutput",		HANDLE),
		("hStdError",		HANDLE),
	]


class PROCESS_INFORMATION(Structure):
	_fields_ = [
		("hProcess",		HANDLE),
		("hThrea",			HANDLE),
		("dwProcessId",		DWORD),
		("dwThreadId",		DWORD),
	]
구조체,유니온,상수를 미리 정의해놓는다.
#my_debugger.py
#-*- coding: utf-8 -*-
from ctypes import *
from my_debugger_defines import *


kernel32 = windll.kernel32

class debugger():
	def __init__(self):
		pass

	def load(self,path_to_exe):
		#dwCreation 플래그를 이용해 프로세스를 어떻게 생성할 것인지 판단.
		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

		else:
			print "[*] Error : 0x%08x." % kernel32.GetLastError()
#my_test.py
import my_debugger

debugger = my_debugger.debugger()

debugger.load("C:\\Windows\\System32\\calc.exe")

raw_input("")
세 파일을 같은 디렉토리에 두고 my_test.py를 실행하면  
[*] We have successfully launched the process! 
[*] PID : 1588 

calc.exe 프로세스를 열었다. PID는 1588 
하지만 디버거로부터 실행을 계속하게 하는 명령을 받지 못해서 계산기 프로그램의 GUI를 볼수는 없다. 
이부분은 나중에 하자.


두번째 방법인 디버거를 프로세스에 attach하는 방법은 다음 글에서 정리하겠다.




'Study > 파이썬 해킹 프로그래밍' 카테고리의 다른 글

[2주] 03장 - 윈도우 디버거 개발 (3)  (0) 2015.01.19
[2주] 03장 - 윈도우 디버거 개발 (2)  (0) 2015.01.18
api 기초  (0) 2015.01.12
[1주] 02장-디버거  (0) 2015.01.12
[1주] 01장 - 개발환경 구축  (0) 2015.01.12