《python灰帽子》原始碼三,獲取暫存器狀態
阿新 • • 發佈:2018-12-16
今天才發現自己的python3是64位的,一直以為是32位的,所以我後面的程式碼都將使用python 3.5 - 32位
win10系統,python3.5-32位,編碼軟體vscode
因為跟上一章程式碼有重複的就以。。。帶過了,新新增的程式碼都會顯示出來
上程式碼
首先my_debugger_defines.py檔案
from ctypes import * # 為了清晰起見,讓我們將Microsoft型別對映到ctypes BYTE = c_ubyte WORD = c_ushort DWORD = c_ulong LPBYTE = POINTER(c_ubyte) LPTSTR = POINTER(c_char) HANDLE = c_void_p LONG = c_long PVOID = c_void_p ULONG_PTR =c_ulong ULONG = c_ulong DEBUG_PROCESS = 0x00000001 CREATE_NEW_CONSOLE = 0x00000010 # 常量 PROCESS_ALL_ACCESS = 0x001F0FFF INFINITE = 0xFFFFFFFF DBG_CONTINUE = 0x00010002 TH32CS_SNAPTHREAD = 0x00000004 # 包括快照中系統中的所有執行緒。要列舉執行緒 # 執行緒常量 THREAD_ALL_ACCESS = 0x001F03FF # GetThreadContext()的上下文標誌 CONTEXT_FULL = 0x00010007 CONTEXT_DEBUG_REGISTERS = 0x00010010 。。。。。。。。。 class THREADENTRY32(Structure): _fields_ = [ ("dwSize",DWORD), ("cntUsage",DWORD), ("th32ThreadID",DWORD), ("th32OwnerProcessID",DWORD), ("tpBasePri",LONG), ("tpDeltaPri",LONG), ("dwFlags",DWORD), ] # Used by the CONTEXT structure class FLOATING_SAVE_AREA(Structure): _fields_ = [ ("ControlWord", DWORD), ("StatusWord", DWORD), ("TagWord", DWORD), ("ErrorOffset", DWORD), ("ErrorSelector", DWORD), ("DataOffset", DWORD), ("DataSelector", DWORD), ("RegisterArea", BYTE * 80), ("Cr0NpxState", DWORD), ] # The CONTEXT structure which holds all of the # register values after a GetThreadContext() call class CONTEXT(Structure): _fields_ = [ ("ContextFlags", DWORD), ("Dr0", DWORD), ("Dr1", DWORD), ("Dr2", DWORD), ("Dr3", DWORD), ("Dr6", DWORD), ("Dr7", DWORD), ("FloatSave", FLOATING_SAVE_AREA), ("SegGs", DWORD), ("SegFs", DWORD), ("SegEs", DWORD), ("SegDs", DWORD), ("Edi", DWORD), ("Esi", DWORD), ("Ebx", DWORD), ("Edx", DWORD), ("Ecx", DWORD), ("Eax", DWORD), ("Ebp", DWORD), ("Eip", DWORD), ("SegCs", DWORD), ("EFlags", DWORD), ("Esp", DWORD), ("SegSs", DWORD), ("ExtendedRegisters", BYTE * 512), ]
定義的常量,型別,以及新增結構體都貼了出來,但是還有很多結構體可以從上一章中獲取到,就不貼出來。
my_debugger.py檔案
from ctypes import * from my_debugger_defines import * kernel32 = windll.kernel32 class debugger(): def __init__(self): self.h_process = None # 程序控制代碼 self.pid = None # 程序pid self.debugger_active = False # 程序活躍狀態 self.h_thread = None # 執行緒id self.context = None # 暫存器內容 pass def load(self,path_to_exe): def open_process(self,pid): def attach(self,pid): def run(self): def get_debug_event(self): def detach(self): 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) # 通過Thread32First列舉出執行緒 success = kernel32.Thread32First(snapshot,byref((thread_entry))) while success: # 執行緒擁有的程序id必須與我們輸入的pid相同 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): """ 獲取暫存器內容 """ context = CONTEXT() context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS # 獲得一個執行緒控制代碼 h_thread = self.open_thread(thread_id) if kernel32.GetThreadContext(h_thread,byref(context)): kernel32.CloseHandle(h_thread) return context else: return False def open_thread(self,thread_id): """ 開啟執行緒,獲取執行緒控制代碼 :param thread_id 執行緒id類似程序pid :return 執行緒控制代碼 """ h_thread = kernel32.OpenThread(THREAD_ALL_ACCESS,None,thread_id) if h_thread is not None: return h_thread else: print("[*] 無法獲得有效的執行緒控制代碼") return False
新新增的屬性以及方法都貼了出來,有些方法可以從上一章找,不然貼出來就太長了。
最後my_test.py
from my_debugger import debugger debugger = debugger() pid = input("輸入需要依附的程式的pid:") debugger.attach(int(pid)) list = debugger.enumerate_threads() for thread in list: thread_context = debugger.get_thread_context(thread) print("[*] 執行緒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) debugger.detach()
我覺得執行這次程式碼最主要是確定python是32位的,剛開始我是用python3.6的64位執行,一直都有問題出現,後來換成32位就成功了,但是換了之後卻不能用在系統自帶的計算器上了,老是在attach()這個函式報錯,根據kernel32.GetLastError()返回來的值是50,表示不支援該請求,用在系統自帶的截圖工具軟體上也是一樣,但是使用酷狗這些軟體就可以。