1*fdd8201dSApple OSS Distributionsfrom __future__ import absolute_import, division 2*fdd8201dSApple OSS Distributions 3*fdd8201dSApple OSS Distributionsfrom builtins import hex 4*fdd8201dSApple OSS Distributions 5*fdd8201dSApple OSS Distributionsfrom builtins import object 6*fdd8201dSApple OSS Distributionsimport logging 7*fdd8201dSApple OSS Distributionsfrom . import target 8*fdd8201dSApple OSS Distributionsimport struct 9*fdd8201dSApple OSS Distributions 10*fdd8201dSApple OSS Distributionsfrom xnu import * 11*fdd8201dSApple OSS Distributionsfrom core.operating_system import Armv8_RegisterSet, Armv7_RegisterSet, I386_RegisterSet, X86_64RegisterSet 12*fdd8201dSApple OSS Distributionsfrom core import caching 13*fdd8201dSApple OSS Distributions 14*fdd8201dSApple OSS Distributions""" these defines should come from an authoritative header file """ 15*fdd8201dSApple OSS DistributionsCPU_TYPE_I386 = 0x00000007 16*fdd8201dSApple OSS DistributionsCPU_TYPE_X86_64 = 0x01000007 17*fdd8201dSApple OSS DistributionsCPU_TYPE_ARM = 0x0000000c 18*fdd8201dSApple OSS DistributionsCPU_TYPE_ARM64 = 0x0100000c 19*fdd8201dSApple OSS DistributionsCPU_TYPE_ARM64_32 = 0x0200000c 20*fdd8201dSApple OSS Distributions 21*fdd8201dSApple OSS Distributionsdef GetRegisterSetForCPU(cputype, subtype): 22*fdd8201dSApple OSS Distributions if cputype == CPU_TYPE_ARM64: 23*fdd8201dSApple OSS Distributions retval = Armv8_RegisterSet 24*fdd8201dSApple OSS Distributions elif cputype == CPU_TYPE_ARM64_32: 25*fdd8201dSApple OSS Distributions retval = Armv8_RegisterSet 26*fdd8201dSApple OSS Distributions elif cputype == CPU_TYPE_ARM: 27*fdd8201dSApple OSS Distributions retval = Armv7_RegisterSet 28*fdd8201dSApple OSS Distributions elif cputype == CPU_TYPE_I386: 29*fdd8201dSApple OSS Distributions retval = I386_RegisterSet 30*fdd8201dSApple OSS Distributions elif cputype == CPU_TYPE_X86_64: 31*fdd8201dSApple OSS Distributions retval = X86_64RegisterSet 32*fdd8201dSApple OSS Distributions 33*fdd8201dSApple OSS Distributions """ crash if unknown cputype """ 34*fdd8201dSApple OSS Distributions 35*fdd8201dSApple OSS Distributions return retval.register_info['registers'] 36*fdd8201dSApple OSS Distributions 37*fdd8201dSApple OSS Distributions 38*fdd8201dSApple OSS Distributionsclass UserThreadObject(object): 39*fdd8201dSApple OSS Distributions """representation of userspace thread""" 40*fdd8201dSApple OSS Distributions def __init__(self, thr_obj, cputype, cpusubtype, is_kern_64bit): 41*fdd8201dSApple OSS Distributions super(UserThreadObject, self).__init__() 42*fdd8201dSApple OSS Distributions self.thread = thr_obj 43*fdd8201dSApple OSS Distributions self.registerset = GetRegisterSetForCPU(cputype, cpusubtype) 44*fdd8201dSApple OSS Distributions self.thread_id = unsigned(self.thread.thread_id) 45*fdd8201dSApple OSS Distributions self.is64Bit = bool(cputype & 0x01000000) 46*fdd8201dSApple OSS Distributions 47*fdd8201dSApple OSS Distributions if self.is64Bit: 48*fdd8201dSApple OSS Distributions if cputype == CPU_TYPE_X86_64: 49*fdd8201dSApple OSS Distributions self.reg_type = "x86_64" 50*fdd8201dSApple OSS Distributions self.saved_state = Cast(self.thread.machine.iss, 'x86_saved_state_t *').uss.ss_64 51*fdd8201dSApple OSS Distributions if cputype == CPU_TYPE_ARM64: 52*fdd8201dSApple OSS Distributions self.reg_type = "arm64" 53*fdd8201dSApple OSS Distributions self.saved_state = self.thread.machine.upcb.uss.ss_64 54*fdd8201dSApple OSS Distributions else: 55*fdd8201dSApple OSS Distributions if cputype == CPU_TYPE_I386: 56*fdd8201dSApple OSS Distributions self.reg_type = "i386" 57*fdd8201dSApple OSS Distributions self.saved_state = Cast(self.thread.machine.iss, 'x86_saved_state_t *').uss.ss_32 58*fdd8201dSApple OSS Distributions if cputype == CPU_TYPE_ARM: 59*fdd8201dSApple OSS Distributions self.reg_type = "arm" 60*fdd8201dSApple OSS Distributions if not is_kern_64bit: 61*fdd8201dSApple OSS Distributions self.saved_state = self.thread.machine.PcbData 62*fdd8201dSApple OSS Distributions else: 63*fdd8201dSApple OSS Distributions self.saved_state = self.thread.machine.contextData.ss.uss.ss_32 64*fdd8201dSApple OSS Distributions if cputype == CPU_TYPE_ARM64_32: 65*fdd8201dSApple OSS Distributions self.reg_type = "arm64" 66*fdd8201dSApple OSS Distributions self.saved_state = self.thread.machine.upcb.uss.ss_64 67*fdd8201dSApple OSS Distributions 68*fdd8201dSApple OSS Distributions logging.debug("created thread id 0x%x of type %s, is_kern_64bit 0x%x cputype 0x%x" 69*fdd8201dSApple OSS Distributions % (self.thread_id, self.reg_type, is_kern_64bit, cputype)) 70*fdd8201dSApple OSS Distributions 71*fdd8201dSApple OSS Distributions def getRegisterValueByName(self, name): 72*fdd8201dSApple OSS Distributions if self.reg_type == 'arm64': 73*fdd8201dSApple OSS Distributions if name in ('x0', 'x1', 'x2', 'x3', 'x4', 'x5', 'x6', 'x7', 'x8', 'x9', 'x10', 'x11', 'x12', 'x13', 'x14', 'x15', 'x16', 'x17', 'x18', 'x19', 'x20', 'x21', 'x22', 'x23', 'x24', 'x25', 'x26', 'x27', 'x28'): 74*fdd8201dSApple OSS Distributions return unsigned(getattr(self.saved_state, 'x')[int(name.strip('x'))]) 75*fdd8201dSApple OSS Distributions 76*fdd8201dSApple OSS Distributions return unsigned(getattr(self.saved_state, name)) 77*fdd8201dSApple OSS Distributions 78*fdd8201dSApple OSS Distributions if self.reg_type == "x86_64": 79*fdd8201dSApple OSS Distributions if name in ('rip', 'rflags', 'cs', 'rsp', 'cpu'): 80*fdd8201dSApple OSS Distributions return unsigned(getattr(self.saved_state.isf, name)) 81*fdd8201dSApple OSS Distributions return unsigned(getattr(self.saved_state, name)) 82*fdd8201dSApple OSS Distributions 83*fdd8201dSApple OSS Distributions if self.reg_type == "arm": 84*fdd8201dSApple OSS Distributions if name in ('r0', 'r1', 'r2', 'r3', 'r4', 'r5', 'r6', 'r7', 'r8', 'r9', 'r10', 'r11', 'r12'): 85*fdd8201dSApple OSS Distributions retval = unsigned(getattr(self.saved_state, 'r')[int(name.strip('r'))]) 86*fdd8201dSApple OSS Distributions else: 87*fdd8201dSApple OSS Distributions retval = unsigned(getattr(self.saved_state, name)) 88*fdd8201dSApple OSS Distributions return retval 89*fdd8201dSApple OSS Distributions 90*fdd8201dSApple OSS Distributions #TODO for i386 91*fdd8201dSApple OSS Distributions 92*fdd8201dSApple OSS Distributions def getName(self): 93*fdd8201dSApple OSS Distributions return str(self.thread_id) 94*fdd8201dSApple OSS Distributions 95*fdd8201dSApple OSS Distributions def getRegisterData(self, reg_num): 96*fdd8201dSApple OSS Distributions """ returns None if there is error """ 97*fdd8201dSApple OSS Distributions if reg_num < 0 or reg_num >= len(self.registerset): 98*fdd8201dSApple OSS Distributions logging.warning("regnum %d is not defined for thread_id 0x%x" % (reg_num, self.thread_id)) 99*fdd8201dSApple OSS Distributions return None 100*fdd8201dSApple OSS Distributions return self.getRegisterValueByName(self.registerset[reg_num]['name']) 101*fdd8201dSApple OSS Distributions 102*fdd8201dSApple OSS Distributions 103*fdd8201dSApple OSS Distributionsclass UserProcess(target.Process): 104*fdd8201dSApple OSS Distributions """ Represent a user process and thread states """ 105*fdd8201dSApple OSS Distributions def __init__(self, task): 106*fdd8201dSApple OSS Distributions self.task = task 107*fdd8201dSApple OSS Distributions self.proc = Cast(task.bsd_info, 'proc_t') 108*fdd8201dSApple OSS Distributions dataregisters64bit = False 109*fdd8201dSApple OSS Distributions ptrsize = 4 110*fdd8201dSApple OSS Distributions 111*fdd8201dSApple OSS Distributions if task.t_flags & 0x1: 112*fdd8201dSApple OSS Distributions ptrsize = 8 113*fdd8201dSApple OSS Distributions if task.t_flags & 0x2: 114*fdd8201dSApple OSS Distributions dataregisters64bit = True 115*fdd8201dSApple OSS Distributions 116*fdd8201dSApple OSS Distributions is_kern_64bit = kern.arch in ['x86_64', 'x86_64h', 'arm64', 'arm64e'] 117*fdd8201dSApple OSS Distributions 118*fdd8201dSApple OSS Distributions self.cputype = unsigned(self.proc.p_cputype) 119*fdd8201dSApple OSS Distributions self.cpusubtype = unsigned(self.proc.p_cpusubtype) 120*fdd8201dSApple OSS Distributions 121*fdd8201dSApple OSS Distributions super(UserProcess, self).__init__(self.cputype, self.cpusubtype, ptrsize) 122*fdd8201dSApple OSS Distributions dbg_message = "process:%s is64bit:%d ptrsize:%d cputype:0x%x cpusubtype:0x%x" % (hex(self.proc), int(dataregisters64bit), ptrsize, self.cputype, self.cpusubtype) 123*fdd8201dSApple OSS Distributions self.proc_platform = int(GetProcPlatform(self.proc)) 124*fdd8201dSApple OSS Distributions if self.proc_platform == xnudefines.P_PLATFORM_MACOS: 125*fdd8201dSApple OSS Distributions self.hinfo['ostype'] = 'macosx' 126*fdd8201dSApple OSS Distributions elif self.proc_platform == xnudefines.P_PLATFORM_WATCHOS: 127*fdd8201dSApple OSS Distributions self.hinfo['ostype'] = 'watchos' 128*fdd8201dSApple OSS Distributions elif self.proc_platform == xnudefines.P_PLATFORM_TVOS: 129*fdd8201dSApple OSS Distributions self.hinfo['ostype'] = 'tvos' 130*fdd8201dSApple OSS Distributions else: 131*fdd8201dSApple OSS Distributions self.hinfo['ostype'] = 'ios' 132*fdd8201dSApple OSS Distributions dbg_message += " ostype:%s" % self.hinfo['ostype'] 133*fdd8201dSApple OSS Distributions 134*fdd8201dSApple OSS Distributions if is_kern_64bit and str(kern.arch).lower().startswith('arm'): 135*fdd8201dSApple OSS Distributions addressing_bits = 64 - int(kern.globals.gT1Sz) 136*fdd8201dSApple OSS Distributions self.hinfo['addressing_bits'] = addressing_bits 137*fdd8201dSApple OSS Distributions dbg_message += " addressing_bits:%d" % addressing_bits 138*fdd8201dSApple OSS Distributions 139*fdd8201dSApple OSS Distributions self.registerset = GetRegisterSetForCPU(self.cputype, self.cpusubtype) 140*fdd8201dSApple OSS Distributions logging.info(dbg_message) 141*fdd8201dSApple OSS Distributions self.threads = {} 142*fdd8201dSApple OSS Distributions self.threads_ids_list = [] 143*fdd8201dSApple OSS Distributions logging.debug("iterating over threads in process") 144*fdd8201dSApple OSS Distributions for thval in IterateQueue(task.threads, 'thread *', 'task_threads'): 145*fdd8201dSApple OSS Distributions self.threads[unsigned(thval.thread_id)] = UserThreadObject(thval, self.cputype, self.cpusubtype, is_kern_64bit) 146*fdd8201dSApple OSS Distributions self.threads_ids_list.append(unsigned(thval.thread_id)) 147*fdd8201dSApple OSS Distributions 148*fdd8201dSApple OSS Distributions def getRegisterDataForThread(self, th_id, reg_num): 149*fdd8201dSApple OSS Distributions if th_id not in self.threads: 150*fdd8201dSApple OSS Distributions logging.critical("0x%x thread id is not found in this task") 151*fdd8201dSApple OSS Distributions return '' 152*fdd8201dSApple OSS Distributions if reg_num < 0 or reg_num >= len(self.registerset): 153*fdd8201dSApple OSS Distributions logging.warning("regnum %d is not defined for thread_id 0x%x" % (reg_num, th_id)) 154*fdd8201dSApple OSS Distributions return '' 155*fdd8201dSApple OSS Distributions value = self.threads[th_id].getRegisterData(reg_num) 156*fdd8201dSApple OSS Distributions return self.encodeRegisterData(value, bytesize=(self.registerset[reg_num]['bitsize'] // 8)) 157*fdd8201dSApple OSS Distributions 158*fdd8201dSApple OSS Distributions def getRegisterCombinedDataForThread(self, th_id): 159*fdd8201dSApple OSS Distributions if th_id not in self.threads: 160*fdd8201dSApple OSS Distributions logging.critical("0x%x thread id is not found in this task" % th_id) 161*fdd8201dSApple OSS Distributions return '' 162*fdd8201dSApple OSS Distributions cur_thread = self.threads[th_id] 163*fdd8201dSApple OSS Distributions retval = 'thread:%s;name:%s;' % (self.encodeThreadID(th_id), cur_thread.getName()) 164*fdd8201dSApple OSS Distributions pos = 0 165*fdd8201dSApple OSS Distributions for rinfo in self.registerset: 166*fdd8201dSApple OSS Distributions name = rinfo['name'] 167*fdd8201dSApple OSS Distributions format = "%02x:%s;" 168*fdd8201dSApple OSS Distributions value = cur_thread.getRegisterValueByName(name) 169*fdd8201dSApple OSS Distributions value_endian_correct_str = self.encodeRegisterData(value, bytesize=(rinfo['bitsize'] // 8)) 170*fdd8201dSApple OSS Distributions retval += format % (pos, value_endian_correct_str) 171*fdd8201dSApple OSS Distributions pos += 1 172*fdd8201dSApple OSS Distributions return retval 173*fdd8201dSApple OSS Distributions 174*fdd8201dSApple OSS Distributions def getThreadStopInfo(self, th_id): 175*fdd8201dSApple OSS Distributions if th_id not in self.threads: 176*fdd8201dSApple OSS Distributions logging.critical("0x%x thread id is not found in this task") 177*fdd8201dSApple OSS Distributions return '' 178*fdd8201dSApple OSS Distributions return 'T02' + self.getRegisterCombinedDataForThread(th_id) + 'threads:' + self.getThreadsInfo()+';' 179*fdd8201dSApple OSS Distributions 180*fdd8201dSApple OSS Distributions def getRegisterInfo(self, regnum): 181*fdd8201dSApple OSS Distributions #something similar to 182*fdd8201dSApple OSS Distributions #"name:x1;bitsize:64;offset:8;encoding:uint;format:hex;gcc:1;dwarf:1;set:General Purpose Registers;" 183*fdd8201dSApple OSS Distributions if regnum >= len(self.registerset): 184*fdd8201dSApple OSS Distributions logging.debug("No register_info for number %d." % regnum) 185*fdd8201dSApple OSS Distributions return 'E45' 186*fdd8201dSApple OSS Distributions 187*fdd8201dSApple OSS Distributions rinfo = self.registerset[regnum] 188*fdd8201dSApple OSS Distributions retval = '' 189*fdd8201dSApple OSS Distributions for i in list(rinfo.keys()): 190*fdd8201dSApple OSS Distributions i_val = str(rinfo[i]) 191*fdd8201dSApple OSS Distributions if i == 'set': 192*fdd8201dSApple OSS Distributions i_val = 'General Purpose Registers' 193*fdd8201dSApple OSS Distributions retval += '%s:%s;' % (str(i), i_val) 194*fdd8201dSApple OSS Distributions 195*fdd8201dSApple OSS Distributions return retval 196*fdd8201dSApple OSS Distributions 197*fdd8201dSApple OSS Distributions def getProcessInfo(self): 198*fdd8201dSApple OSS Distributions retval = '' 199*fdd8201dSApple OSS Distributions #pid:d22c;parent-pid:d34d;real-uid:ecf;real-gid:b;effective-uid:ecf;effective-gid:b;cputype:1000007;cpusubtype:3; 200*fdd8201dSApple OSS Distributions #ostype:macosx;vendor:apple;endian:little;ptrsize:8; 201*fdd8201dSApple OSS Distributions pinfo = {'effective-uid': 'ecf', 'effective-gid': 'b', 'endian': 'little', 'vendor': 'apple'} 202*fdd8201dSApple OSS Distributions pinfo['pid'] = "%x" % (GetProcPIDForTask(self.task)) 203*fdd8201dSApple OSS Distributions pinfo['parent-pid'] = "%x" % (unsigned(self.proc.p_ppid)) 204*fdd8201dSApple OSS Distributions pinfo['ptrsize'] = str(self.ptrsize) 205*fdd8201dSApple OSS Distributions pinfo['ostype'] = 'macosx' 206*fdd8201dSApple OSS Distributions pinfo['cputype'] = "%x" % self.cputype 207*fdd8201dSApple OSS Distributions pinfo['cpusubtype'] = "%x" % self.cpusubtype 208*fdd8201dSApple OSS Distributions pinfo['real-uid'] = "%x" % (unsigned(self.proc.p_ruid)) 209*fdd8201dSApple OSS Distributions pinfo['real-gid'] = "%x" % (unsigned(self.proc.p_rgid)) 210*fdd8201dSApple OSS Distributions if str(kern.arch).find('arm') >= 0: 211*fdd8201dSApple OSS Distributions pinfo['ostype'] = 'ios' 212*fdd8201dSApple OSS Distributions for i in list(pinfo.keys()): 213*fdd8201dSApple OSS Distributions i_val = str(pinfo[i]) 214*fdd8201dSApple OSS Distributions retval += '%s:%s;' % (str(i), i_val) 215*fdd8201dSApple OSS Distributions return retval 216*fdd8201dSApple OSS Distributions 217*fdd8201dSApple OSS Distributions def readMemory(self, address, size): 218*fdd8201dSApple OSS Distributions cache_key = "{}-{}-{}".format(hex(self.task), hex(address), size) 219*fdd8201dSApple OSS Distributions cache_data = caching.GetDynamicCacheData(cache_key) 220*fdd8201dSApple OSS Distributions if cache_data: 221*fdd8201dSApple OSS Distributions return self.encodeByteString(cache_data) 222*fdd8201dSApple OSS Distributions data = GetUserDataAsString(self.task, address, size) 223*fdd8201dSApple OSS Distributions if not data: 224*fdd8201dSApple OSS Distributions logging.error("Failed to read memory task:{: <#018x} {: <#018x} {:d}".format(self.task, address, size)) 225*fdd8201dSApple OSS Distributions else: 226*fdd8201dSApple OSS Distributions caching.SaveDynamicCacheData(cache_key, data) 227*fdd8201dSApple OSS Distributions return self.encodeByteString(data) 228*fdd8201dSApple OSS Distributions 229*fdd8201dSApple OSS Distributions def getSharedLibInfoAddress(self): 230*fdd8201dSApple OSS Distributions return unsigned(self.task.all_image_info_addr) 231