一、開發內容介紹
為了對一個進程進行調試,你首先必須用一些方法把調試器和進程連接起來。所以, 我
們的調試器要不然就是裝載一個可執行程序然后運行它, 要不然就是動態的附加到一個運行
的進程。Windows 的調試接口(Windows debugging API)提供了一個非常簡單的方法完成
這兩點。
運行一個程序和附加到一個程序有細微的差別。 打開一個程序的優點在於他能在程序運
行任何代碼之前完全的控制程序。 這在分析病毒或者惡意代碼的時候非常有用。 附加到一個
進程,僅僅是強行的進入一個已經運行了的進程內部,它允許你跳過啟動部分的代碼,分析
你感興趣的代碼。你正在分析的地方也就是程序目前正在執行的地方。
第一種方法,其實就是從調試器本身調用這個程序(調試器就是父進程,對被調試進程
的控制權限更大) 。在 Windows 上創建一個進程用 CreateProcessA()函數。將特定的標志傳
進這個函數,使得目標進程能夠被調試。
目標:使用CreateProcess打開一個進程
二、需要用到的winAPI函數
函數原型:
創建兩個 Python 文件 my_debugger.py 和 my_debugger_defines.py。 我們將創建一個父類
debugger() 接着逐漸的增加各種調試函數。另外,把所有的結構,聯合,常量放 到
my_debugger_defines.py 方便以后維護。
# my_debugger_defines.py
from ctypes import *
# Let's map the Microsoft types to ctypes for clarity
WORD = c_ushort
DWORD = c_ulong
LPBYTE = POINTER(c_ubyte)
LPTSTR = POINTER(c_char)
HANDLE = c_void_p
# Constants
DEBUG_PROCESS = 0x00000001
CREATE_NEW_CONSOLE = 0x00000010
# Structures for CreateProcessA() function
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),
("hThread", HANDLE),
("dwProcessId", DWORD),
("dwThreadId", DWORD),
]
# my_debugger.py
from ctypes import *
from my_debugger_defines import *
kernel32 = windll.kernel32
class debugger():
def __init__(self):
pass
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
else:
print "[*] Error: 0x%08x." % kernel32.GetLastError()
#my_test.py
import my_debugger
debugger = my_debugger.debugger()
debugger.load("C:\\WINDOWS\\system32\\calc.exe")
運行結果:
Connected to pydev debugger (build 145.844)
[*] We have successfully launched the process!
[*] PID: 4720
