《python灰帽子》源码三,获取寄存器状态

今天才发现自己的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,表示不支持该请求,用在系统自带的截图工具软件上也是一样,但是使用酷狗这些软件就可以。

猜你喜欢

转载自blog.csdn.net/qq_41738613/article/details/83217186