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