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