221 lines · python
1# DExTer : Debugging Experience Tester2# ~~~~~~ ~ ~~ ~ ~~3#4# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.5# See https://llvm.org/LICENSE.txt for license information.6# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception7 8from ctypes import *9from functools import partial10 11from .utils import *12 13# UUID For SystemObjects4 interface.14DebugSystemObjects4IID = IID(15 0x489468E6,16 0x7D0F,17 0x4AF5,18 IID_Data4_Type(0x87, 0xAB, 0x25, 0x20, 0x74, 0x54, 0xD5, 0x53),19)20 21 22class IDebugSystemObjects4(Structure):23 pass24 25 26class IDebugSystemObjects4Vtbl(Structure):27 wrp = partial(WINFUNCTYPE, c_long, POINTER(IDebugSystemObjects4))28 ids_getnumberprocesses = wrp(POINTER(c_ulong))29 ids_getprocessidsbyindex = wrp(c_ulong, c_ulong, c_ulong_p, c_ulong_p)30 ids_setcurrentprocessid = wrp(c_ulong)31 ids_getnumberthreads = wrp(c_ulong_p)32 ids_getthreadidsbyindex = wrp(c_ulong, c_ulong, c_ulong_p, c_ulong_p)33 ids_setcurrentthreadid = wrp(c_ulong)34 _fields_ = [35 ("QueryInterface", c_void_p),36 ("AddRef", c_void_p),37 ("Release", c_void_p),38 ("GetEventThread", c_void_p),39 ("GetEventProcess", c_void_p),40 ("GetCurrentThreadId", c_void_p),41 ("SetCurrentThreadId", ids_setcurrentthreadid),42 ("GetCurrentProcessId", c_void_p),43 ("SetCurrentProcessId", ids_setcurrentprocessid),44 ("GetNumberThreads", ids_getnumberthreads),45 ("GetTotalNumberThreads", c_void_p),46 ("GetThreadIdsByIndex", ids_getthreadidsbyindex),47 ("GetThreadIdByProcessor", c_void_p),48 ("GetCurrentThreadDataOffset", c_void_p),49 ("GetThreadIdByDataOffset", c_void_p),50 ("GetCurrentThreadTeb", c_void_p),51 ("GetThreadIdByTeb", c_void_p),52 ("GetCurrentThreadSystemId", c_void_p),53 ("GetThreadIdBySystemId", c_void_p),54 ("GetCurrentThreadHandle", c_void_p),55 ("GetThreadIdByHandle", c_void_p),56 ("GetNumberProcesses", ids_getnumberprocesses),57 ("GetProcessIdsByIndex", ids_getprocessidsbyindex),58 ("GetCurrentProcessDataOffset", c_void_p),59 ("GetProcessIdByDataOffset", c_void_p),60 ("GetCurrentProcessPeb", c_void_p),61 ("GetProcessIdByPeb", c_void_p),62 ("GetCurrentProcessSystemId", c_void_p),63 ("GetProcessIdBySystemId", c_void_p),64 ("GetCurrentProcessHandle", c_void_p),65 ("GetProcessIdByHandle", c_void_p),66 ("GetCurrentProcessExecutableName", c_void_p),67 ("GetCurrentProcessUpTime", c_void_p),68 ("GetImplicitThreadDataOffset", c_void_p),69 ("SetImplicitThreadDataOffset", c_void_p),70 ("GetImplicitProcessDataOffset", c_void_p),71 ("SetImplicitProcessDataOffset", c_void_p),72 ("GetEventSystem", c_void_p),73 ("GetCurrentSystemId", c_void_p),74 ("SetCurrentSystemId", c_void_p),75 ("GetNumberSystems", c_void_p),76 ("GetSystemIdsByIndex", c_void_p),77 ("GetTotalNumberThreadsAndProcesses", c_void_p),78 ("GetCurrentSystemServer", c_void_p),79 ("GetSystemByServer", c_void_p),80 ("GetCurrentSystemServerName", c_void_p),81 ("GetCurrentProcessExecutableNameWide", c_void_p),82 ("GetCurrentSystemServerNameWide", c_void_p),83 ]84 85 86IDebugSystemObjects4._fields_ = [("lpVtbl", POINTER(IDebugSystemObjects4Vtbl))]87 88 89class SysObjects(object):90 def __init__(self, sysobjects):91 self.ptr = sysobjects92 self.sysobjects = sysobjects.contents93 self.vt = self.sysobjects.lpVtbl.contents94 # Keep a handy ulong for passing into C methods.95 self.ulong = c_ulong()96 97 def GetNumberSystems(self):98 res = self.vt.GetNumberSystems(self.sysobjects, byref(self.ulong))99 aborter(res, "GetNumberSystems")100 return self.ulong.value101 102 def GetNumberProcesses(self):103 res = self.vt.GetNumberProcesses(self.sysobjects, byref(self.ulong))104 aborter(res, "GetNumberProcesses")105 return self.ulong.value106 107 def GetNumberThreads(self):108 res = self.vt.GetNumberThreads(self.sysobjects, byref(self.ulong))109 aborter(res, "GetNumberThreads")110 return self.ulong.value111 112 def GetTotalNumberThreadsAndProcesses(self):113 tthreads = c_ulong()114 tprocs = c_ulong()115 pulong3 = c_ulong()116 res = self.vt.GetTotalNumberThreadsAndProcesses(117 self.sysobjects,118 byref(tthreads),119 byref(tprocs),120 byref(pulong3),121 byref(pulong3),122 byref(pulong3),123 )124 aborter(res, "GettotalNumberThreadsAndProcesses")125 return tthreads.value, tprocs.value126 127 def GetCurrentProcessId(self):128 res = self.vt.GetCurrentProcessId(self.sysobjects, byref(self.ulong))129 aborter(res, "GetCurrentProcessId")130 return self.ulong.value131 132 def SetCurrentProcessId(self, sysid):133 res = self.vt.SetCurrentProcessId(self.sysobjects, sysid)134 aborter(res, "SetCurrentProcessId")135 return136 137 def GetCurrentThreadId(self):138 res = self.vt.GetCurrentThreadId(self.sysobjects, byref(self.ulong))139 aborter(res, "GetCurrentThreadId")140 return self.ulong.value141 142 def SetCurrentThreadId(self, sysid):143 res = self.vt.SetCurrentThreadId(self.sysobjects, sysid)144 aborter(res, "SetCurrentThreadId")145 return146 147 def GetProcessIdsByIndex(self):148 num_processes = self.GetNumberProcesses()149 if num_processes == 0:150 return []151 engineids = (c_ulong * num_processes)()152 pids = (c_ulong * num_processes)()153 for x in range(num_processes):154 engineids[x] = DEBUG_ANY_ID155 pids[x] = DEBUG_ANY_ID156 res = self.vt.GetProcessIdsByIndex(157 self.sysobjects, 0, num_processes, engineids, pids158 )159 aborter(res, "GetProcessIdsByIndex")160 return list(zip(engineids, pids))161 162 def GetThreadIdsByIndex(self):163 num_threads = self.GetNumberThreads()164 if num_threads == 0:165 return []166 engineids = (c_ulong * num_threads)()167 tids = (c_ulong * num_threads)()168 for x in range(num_threads):169 engineids[x] = DEBUG_ANY_ID170 tids[x] = DEBUG_ANY_ID171 # Zero -> start index172 res = self.vt.GetThreadIdsByIndex(173 self.sysobjects, 0, num_threads, engineids, tids174 )175 aborter(res, "GetThreadIdsByIndex")176 return list(zip(engineids, tids))177 178 def GetCurThreadHandle(self):179 pulong64 = c_ulonglong()180 res = self.vt.GetCurrentThreadHandle(self.sysobjects, byref(pulong64))181 aborter(res, "GetCurrentThreadHandle")182 return pulong64.value183 184 def set_current_thread(self, pid, tid):185 proc_sys_id = -1186 for x in self.GetProcessIdsByIndex():187 sysid, procid = x188 if procid == pid:189 proc_sys_id = sysid190 191 if proc_sys_id == -1:192 raise Exception("Couldn't find designated PID {}".format(pid))193 194 self.SetCurrentProcessId(proc_sys_id)195 196 thread_sys_id = -1197 for x in self.GetThreadIdsByIndex():198 sysid, threadid = x199 if threadid == tid:200 thread_sys_id = sysid201 202 if thread_sys_id == -1:203 raise Exception("Couldn't find designated TID {}".format(tid))204 205 self.SetCurrentThreadId(thread_sys_id)206 return207 208 def print_current_procs_threads(self):209 procs = []210 for x in self.GetProcessIdsByIndex():211 sysid, procid = x212 procs.append(procid)213 214 threads = []215 for x in self.GetThreadIdsByIndex():216 sysid, threadid = x217 threads.append(threadid)218 219 print("Current processes: {}".format(procs))220 print("Current threads: {}".format(threads))221