目前绝大多数的IDE都包含断点调试的功能,缺少这个,用print来调试代码,简直就是个灾难,下面我们来实现一个简陋版的“断点调试”;
环境:WIN7 x86_64 Python2.7
///了解///
调试类别:白盒调试:源码在手 黑盒调试:软件包
黑盒调试 -> 用户态(ring3);内核态(ring0)
ring3 -> WinDbg;OllyDbg; GNU(gdb):Linux ...
八个通用寄存器(习惯了32位,64位请自己查询):EAX,EDX.ECX.ESI.EDI.EBP.ESP.EBX
EAX:累加器,常用的运算操作和传递函数调用的返回值
EDX:数据寄存器,可理解为EAX的延伸
ECX:计数器
counter = 0
while counter<5#ECX = 5 每执行一次ECX -= 1 : SUB ECX 1H
print counter
counter+=1
ESI:源变址寄存器,可简单理解为存储输入数据流位置的信息,用于“读”
EDI:用于“写”
ESP:栈指针 指向栈顶(低位)
EBP:栈基指 指向栈底(高位)
EIP*:始终指向cpu当前执行的指令,缓冲区溢出原理就是利用EIP被覆盖,来执行自己构建的代码
断点:软断点 ,硬件断点,内存断点
ctypes 库
kernel32.dll
///开始///
#代码参考
THREADENTRY32结构体为
class THREADENTRY32(Structure): _fields_ = [ ("dwSize", DWORD), ("cntUsage", DWORD), ("th32ThreadID", DWORD), ("th32OwnerProcessID", DWORD), ("tpBasePri", DWORD), ("tpDeltaPri", DWORD), ("dwFlags", DWORD), ] 这个结构体中包含着枚举到的首个线程的相关信息,在调用kernel32.Thread32First()之前要确保成员变量dwSize被正确的初始化, th32ThreadID为当前枚举到线程的TID值,th32OwnerProcessID可以获取当前线程对应的进程PID,通过比对th32OwnerProcessID与 目标进程的PID值,筛选出标识符与之相匹配的线程,由此断定这个线程为我们的目标线程,然后通过Thread32Next()从快照中获取 下一个线程,CreateToolhelp32Snapshot函数为指定的进程、进程使用的堆[HEAP]、模块[MODULE]、线程[THREAD])建立一个快照[snapshot]。 CONTEXT线程数据结构体为: 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), ] 我们所有关心的数据通过这个结构体返回 #放开调试 def detach(self): if kernel32.DebugActiveProcessStop(self.pid): print "[*] Finished debugging. Exiting..." else: print "There was an error" return False 这个结构体中包含着枚举到的首个线程的相关信息,在调用kernel32.Thread32First()之前要确保成员变量dwSize被正确的初始化, th32ThreadID为当前枚举到线程的TID值,th32OwnerProcessID可以获取当前线程对应的进程PID,通过比对th32OwnerProcessID与 目标进程的PID值,筛选出标识符与之相匹配的线程,由此断定这个线程为我们的目标线程,然后通过Thread32Next()从快照中获取 下一个线程,CreateToolhelp32Snapshot函数为指定的进程、进程使用的堆[HEAP]、模块[MODULE]、线程[THREAD])建立一个快照[snapshot]。 调用 if __name__ == "__main__": pid = raw_input("Enter the PID of the process to attach to:") attach(int(pid)) threadList = enumerate_threads() for thread in threadList: thread_context = get_thread_context(thread) print "[*] Dumping registers for thread ID:0xx" % thread print "[**] EIP:0xx" % thread_context.Eip print "[**] ESP:0xx" % thread_context.Esp print "[**] EBP:0xx" % thread_context.Ebp print "[**] EAX:0xx" % thread_context.Eax print "[**] EBX:0xx" % thread_context.Ebx print "[**] ECX:0xx" % thread_context.Ecx print "[**] EDX:0xx" % thread_context.Edx print "[*] END DUMP" detach()