188cc0b97SApple OSS Distributionsimport logging 2e7776783SApple OSS Distributionsfrom . import target 388cc0b97SApple OSS Distributionsimport struct 488cc0b97SApple OSS Distributions 588cc0b97SApple OSS Distributionsfrom xnu import * 688cc0b97SApple OSS Distributionsfrom core.operating_system import Armv8_RegisterSet, Armv7_RegisterSet, I386_RegisterSet, X86_64RegisterSet 7bb611c8fSApple OSS Distributionsfrom core import caching 888cc0b97SApple OSS Distributions 976e12aa3SApple OSS Distributions""" these defines should come from an authoritative header file """ 1088cc0b97SApple OSS DistributionsCPU_TYPE_I386 = 0x00000007 1188cc0b97SApple OSS DistributionsCPU_TYPE_X86_64 = 0x01000007 1288cc0b97SApple OSS DistributionsCPU_TYPE_ARM = 0x0000000c 1388cc0b97SApple OSS DistributionsCPU_TYPE_ARM64 = 0x0100000c 14a5e72196SApple OSS DistributionsCPU_TYPE_ARM64_32 = 0x0200000c 1588cc0b97SApple OSS Distributions 1688cc0b97SApple OSS Distributionsdef GetRegisterSetForCPU(cputype, subtype): 1776e12aa3SApple OSS Distributions if cputype == CPU_TYPE_ARM64: 1888cc0b97SApple OSS Distributions retval = Armv8_RegisterSet 19a5e72196SApple OSS Distributions elif cputype == CPU_TYPE_ARM64_32: 20a5e72196SApple OSS Distributions retval = Armv8_RegisterSet 2176e12aa3SApple OSS Distributions elif cputype == CPU_TYPE_ARM: 2288cc0b97SApple OSS Distributions retval = Armv7_RegisterSet 2388cc0b97SApple OSS Distributions elif cputype == CPU_TYPE_I386: 2488cc0b97SApple OSS Distributions retval = I386_RegisterSet 2576e12aa3SApple OSS Distributions elif cputype == CPU_TYPE_X86_64: 2676e12aa3SApple OSS Distributions retval = X86_64RegisterSet 2776e12aa3SApple OSS Distributions 2876e12aa3SApple OSS Distributions """ crash if unknown cputype """ 2988cc0b97SApple OSS Distributions 3088cc0b97SApple OSS Distributions return retval.register_info['registers'] 3188cc0b97SApple OSS Distributions 3288cc0b97SApple OSS Distributions 3388cc0b97SApple OSS Distributionsclass UserThreadObject(object): 3488cc0b97SApple OSS Distributions """representation of userspace thread""" 355c2921b0SApple OSS Distributions def __init__(self, thr_obj, cputype, cpusubtype): 368d741a5dSApple OSS Distributions super().__init__() 3788cc0b97SApple OSS Distributions self.thread = thr_obj 3888cc0b97SApple OSS Distributions self.registerset = GetRegisterSetForCPU(cputype, cpusubtype) 3988cc0b97SApple OSS Distributions self.thread_id = unsigned(self.thread.thread_id) 4088cc0b97SApple OSS Distributions self.is64Bit = bool(cputype & 0x01000000) 4188cc0b97SApple OSS Distributions 4288cc0b97SApple OSS Distributions if self.is64Bit: 4388cc0b97SApple OSS Distributions if cputype == CPU_TYPE_X86_64: 4488cc0b97SApple OSS Distributions self.reg_type = "x86_64" 4588cc0b97SApple OSS Distributions self.saved_state = Cast(self.thread.machine.iss, 'x86_saved_state_t *').uss.ss_64 4688cc0b97SApple OSS Distributions if cputype == CPU_TYPE_ARM64: 4788cc0b97SApple OSS Distributions self.reg_type = "arm64" 4888cc0b97SApple OSS Distributions self.saved_state = self.thread.machine.upcb.uss.ss_64 4988cc0b97SApple OSS Distributions else: 5088cc0b97SApple OSS Distributions if cputype == CPU_TYPE_I386: 5188cc0b97SApple OSS Distributions self.reg_type = "i386" 5288cc0b97SApple OSS Distributions self.saved_state = Cast(self.thread.machine.iss, 'x86_saved_state_t *').uss.ss_32 5388cc0b97SApple OSS Distributions if cputype == CPU_TYPE_ARM: 5488cc0b97SApple OSS Distributions self.reg_type = "arm" 5588cc0b97SApple OSS Distributions self.saved_state = self.thread.machine.contextData.ss.uss.ss_32 56a5e72196SApple OSS Distributions if cputype == CPU_TYPE_ARM64_32: 57a5e72196SApple OSS Distributions self.reg_type = "arm64" 58a5e72196SApple OSS Distributions self.saved_state = self.thread.machine.upcb.uss.ss_64 59cc9a6355SApple OSS Distributions 605c2921b0SApple OSS Distributions logging.debug("created thread id 0x%x of type %s, cputype 0x%x" 615c2921b0SApple OSS Distributions % (self.thread_id, self.reg_type, cputype)) 6288cc0b97SApple OSS Distributions 6388cc0b97SApple OSS Distributions def getRegisterValueByName(self, name): 6488cc0b97SApple OSS Distributions if self.reg_type == 'arm64': 6588cc0b97SApple 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'): 6688cc0b97SApple OSS Distributions return unsigned(getattr(self.saved_state, 'x')[int(name.strip('x'))]) 6788cc0b97SApple OSS Distributions 6888cc0b97SApple OSS Distributions return unsigned(getattr(self.saved_state, name)) 6988cc0b97SApple OSS Distributions 7088cc0b97SApple OSS Distributions if self.reg_type == "x86_64": 7188cc0b97SApple OSS Distributions if name in ('rip', 'rflags', 'cs', 'rsp', 'cpu'): 7288cc0b97SApple OSS Distributions return unsigned(getattr(self.saved_state.isf, name)) 7388cc0b97SApple OSS Distributions return unsigned(getattr(self.saved_state, name)) 7488cc0b97SApple OSS Distributions 7588cc0b97SApple OSS Distributions if self.reg_type == "arm": 7688cc0b97SApple OSS Distributions if name in ('r0', 'r1', 'r2', 'r3', 'r4', 'r5', 'r6', 'r7', 'r8', 'r9', 'r10', 'r11', 'r12'): 7788cc0b97SApple OSS Distributions retval = unsigned(getattr(self.saved_state, 'r')[int(name.strip('r'))]) 7888cc0b97SApple OSS Distributions else: 7988cc0b97SApple OSS Distributions retval = unsigned(getattr(self.saved_state, name)) 8088cc0b97SApple OSS Distributions return retval 8188cc0b97SApple OSS Distributions 8288cc0b97SApple OSS Distributions #TODO for i386 8388cc0b97SApple OSS Distributions 8488cc0b97SApple OSS Distributions def getName(self): 8588cc0b97SApple OSS Distributions return str(self.thread_id) 8688cc0b97SApple OSS Distributions 8788cc0b97SApple OSS Distributions def getRegisterData(self, reg_num): 8888cc0b97SApple OSS Distributions """ returns None if there is error """ 8988cc0b97SApple OSS Distributions if reg_num < 0 or reg_num >= len(self.registerset): 9088cc0b97SApple OSS Distributions logging.warning("regnum %d is not defined for thread_id 0x%x" % (reg_num, self.thread_id)) 9188cc0b97SApple OSS Distributions return None 9288cc0b97SApple OSS Distributions return self.getRegisterValueByName(self.registerset[reg_num]['name']) 9388cc0b97SApple OSS Distributions 9488cc0b97SApple OSS Distributions 9588cc0b97SApple OSS Distributionsclass UserProcess(target.Process): 9688cc0b97SApple OSS Distributions """ Represent a user process and thread states """ 9788cc0b97SApple OSS Distributions def __init__(self, task): 9888cc0b97SApple OSS Distributions self.task = task 995c2921b0SApple OSS Distributions self.proc = GetProcFromTask(task) 100aca3beaaSApple OSS Distributions self.cache = {} 101*33de042dSApple OSS Distributions if self.proc is None: 1025c2921b0SApple OSS Distributions raise ValueError("Task has no associated BSD process.") 10388cc0b97SApple OSS Distributions dataregisters64bit = False 10488cc0b97SApple OSS Distributions ptrsize = 4 10588cc0b97SApple OSS Distributions 10688cc0b97SApple OSS Distributions if task.t_flags & 0x1: 10788cc0b97SApple OSS Distributions ptrsize = 8 10888cc0b97SApple OSS Distributions if task.t_flags & 0x2: 109cc9a6355SApple OSS Distributions dataregisters64bit = True 11088cc0b97SApple OSS Distributions 11188cc0b97SApple OSS Distributions self.cputype = unsigned(self.proc.p_cputype) 11288cc0b97SApple OSS Distributions self.cpusubtype = unsigned(self.proc.p_cpusubtype) 113cc9a6355SApple OSS Distributions 1148d741a5dSApple OSS Distributions super().__init__(self.cputype, self.cpusubtype, ptrsize) 115bb611c8fSApple 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) 116e7776783SApple OSS Distributions self.proc_platform = int(GetProcPlatform(self.proc)) 117bb611c8fSApple OSS Distributions if self.proc_platform == xnudefines.P_PLATFORM_MACOS: 118cc9a6355SApple OSS Distributions self.hinfo['ostype'] = 'macosx' 119bb611c8fSApple OSS Distributions elif self.proc_platform == xnudefines.P_PLATFORM_WATCHOS: 120bb611c8fSApple OSS Distributions self.hinfo['ostype'] = 'watchos' 121bb611c8fSApple OSS Distributions elif self.proc_platform == xnudefines.P_PLATFORM_TVOS: 122bb611c8fSApple OSS Distributions self.hinfo['ostype'] = 'tvos' 123bb611c8fSApple OSS Distributions else: 124cc9a6355SApple OSS Distributions self.hinfo['ostype'] = 'ios' 125bb611c8fSApple OSS Distributions dbg_message += " ostype:%s" % self.hinfo['ostype'] 126bb611c8fSApple OSS Distributions 1275c2921b0SApple OSS Distributions if str(kern.arch).lower().startswith('arm'): 128bb611c8fSApple OSS Distributions addressing_bits = 64 - int(kern.globals.gT1Sz) 129bb611c8fSApple OSS Distributions self.hinfo['addressing_bits'] = addressing_bits 130bb611c8fSApple OSS Distributions dbg_message += " addressing_bits:%d" % addressing_bits 131cc9a6355SApple OSS Distributions 132cc9a6355SApple OSS Distributions self.registerset = GetRegisterSetForCPU(self.cputype, self.cpusubtype) 133bb611c8fSApple OSS Distributions logging.info(dbg_message) 13488cc0b97SApple OSS Distributions self.threads = {} 13588cc0b97SApple OSS Distributions self.threads_ids_list = [] 13688cc0b97SApple OSS Distributions logging.debug("iterating over threads in process") 13788cc0b97SApple OSS Distributions for thval in IterateQueue(task.threads, 'thread *', 'task_threads'): 1385c2921b0SApple OSS Distributions self.threads[unsigned(thval.thread_id)] = UserThreadObject(thval, self.cputype, self.cpusubtype) 13988cc0b97SApple OSS Distributions self.threads_ids_list.append(unsigned(thval.thread_id)) 14088cc0b97SApple OSS Distributions 14188cc0b97SApple OSS Distributions def getRegisterDataForThread(self, th_id, reg_num): 14288cc0b97SApple OSS Distributions if th_id not in self.threads: 14388cc0b97SApple OSS Distributions logging.critical("0x%x thread id is not found in this task") 14488cc0b97SApple OSS Distributions return '' 14588cc0b97SApple OSS Distributions if reg_num < 0 or reg_num >= len(self.registerset): 14688cc0b97SApple OSS Distributions logging.warning("regnum %d is not defined for thread_id 0x%x" % (reg_num, th_id)) 14788cc0b97SApple OSS Distributions return '' 14888cc0b97SApple OSS Distributions value = self.threads[th_id].getRegisterData(reg_num) 149e7776783SApple OSS Distributions return self.encodeRegisterData(value, bytesize=(self.registerset[reg_num]['bitsize'] // 8)) 15088cc0b97SApple OSS Distributions 15188cc0b97SApple OSS Distributions def getRegisterCombinedDataForThread(self, th_id): 15288cc0b97SApple OSS Distributions if th_id not in self.threads: 15388cc0b97SApple OSS Distributions logging.critical("0x%x thread id is not found in this task" % th_id) 15488cc0b97SApple OSS Distributions return '' 15588cc0b97SApple OSS Distributions cur_thread = self.threads[th_id] 15688cc0b97SApple OSS Distributions retval = 'thread:%s;name:%s;' % (self.encodeThreadID(th_id), cur_thread.getName()) 15788cc0b97SApple OSS Distributions pos = 0 15888cc0b97SApple OSS Distributions for rinfo in self.registerset: 15988cc0b97SApple OSS Distributions name = rinfo['name'] 16088cc0b97SApple OSS Distributions format = "%02x:%s;" 16188cc0b97SApple OSS Distributions value = cur_thread.getRegisterValueByName(name) 162e7776783SApple OSS Distributions value_endian_correct_str = self.encodeRegisterData(value, bytesize=(rinfo['bitsize'] // 8)) 16388cc0b97SApple OSS Distributions retval += format % (pos, value_endian_correct_str) 16488cc0b97SApple OSS Distributions pos += 1 16588cc0b97SApple OSS Distributions return retval 16688cc0b97SApple OSS Distributions 16788cc0b97SApple OSS Distributions def getThreadStopInfo(self, th_id): 16888cc0b97SApple OSS Distributions if th_id not in self.threads: 16988cc0b97SApple OSS Distributions logging.critical("0x%x thread id is not found in this task") 17088cc0b97SApple OSS Distributions return '' 17188cc0b97SApple OSS Distributions return 'T02' + self.getRegisterCombinedDataForThread(th_id) + 'threads:' + self.getThreadsInfo()+';' 17288cc0b97SApple OSS Distributions 17388cc0b97SApple OSS Distributions def getRegisterInfo(self, regnum): 17488cc0b97SApple OSS Distributions #something similar to 17588cc0b97SApple OSS Distributions #"name:x1;bitsize:64;offset:8;encoding:uint;format:hex;gcc:1;dwarf:1;set:General Purpose Registers;" 176bb611c8fSApple OSS Distributions if regnum >= len(self.registerset): 17788cc0b97SApple OSS Distributions logging.debug("No register_info for number %d." % regnum) 17888cc0b97SApple OSS Distributions return 'E45' 17988cc0b97SApple OSS Distributions 18088cc0b97SApple OSS Distributions rinfo = self.registerset[regnum] 18188cc0b97SApple OSS Distributions retval = '' 182e7776783SApple OSS Distributions for i in list(rinfo.keys()): 18388cc0b97SApple OSS Distributions i_val = str(rinfo[i]) 18488cc0b97SApple OSS Distributions if i == 'set': 18588cc0b97SApple OSS Distributions i_val = 'General Purpose Registers' 18688cc0b97SApple OSS Distributions retval += '%s:%s;' % (str(i), i_val) 18788cc0b97SApple OSS Distributions 18888cc0b97SApple OSS Distributions return retval 18988cc0b97SApple OSS Distributions 19088cc0b97SApple OSS Distributions def getProcessInfo(self): 19188cc0b97SApple OSS Distributions retval = '' 19288cc0b97SApple OSS Distributions #pid:d22c;parent-pid:d34d;real-uid:ecf;real-gid:b;effective-uid:ecf;effective-gid:b;cputype:1000007;cpusubtype:3; 19388cc0b97SApple OSS Distributions #ostype:macosx;vendor:apple;endian:little;ptrsize:8; 19488cc0b97SApple OSS Distributions pinfo = {'effective-uid': 'ecf', 'effective-gid': 'b', 'endian': 'little', 'vendor': 'apple'} 19588cc0b97SApple OSS Distributions pinfo['pid'] = "%x" % (GetProcPIDForTask(self.task)) 19688cc0b97SApple OSS Distributions pinfo['parent-pid'] = "%x" % (unsigned(self.proc.p_ppid)) 19788cc0b97SApple OSS Distributions pinfo['ptrsize'] = str(self.ptrsize) 19888cc0b97SApple OSS Distributions pinfo['ostype'] = 'macosx' 19988cc0b97SApple OSS Distributions pinfo['cputype'] = "%x" % self.cputype 20088cc0b97SApple OSS Distributions pinfo['cpusubtype'] = "%x" % self.cpusubtype 20188cc0b97SApple OSS Distributions pinfo['real-uid'] = "%x" % (unsigned(self.proc.p_ruid)) 20288cc0b97SApple OSS Distributions pinfo['real-gid'] = "%x" % (unsigned(self.proc.p_rgid)) 20388cc0b97SApple OSS Distributions if str(kern.arch).find('arm') >= 0: 20488cc0b97SApple OSS Distributions pinfo['ostype'] = 'ios' 205e7776783SApple OSS Distributions for i in list(pinfo.keys()): 20688cc0b97SApple OSS Distributions i_val = str(pinfo[i]) 20788cc0b97SApple OSS Distributions retval += '%s:%s;' % (str(i), i_val) 20888cc0b97SApple OSS Distributions return retval 20988cc0b97SApple OSS Distributions 21088cc0b97SApple OSS Distributions def readMemory(self, address, size): 211bb611c8fSApple OSS Distributions cache_key = "{}-{}-{}".format(hex(self.task), hex(address), size) 212aca3beaaSApple OSS Distributions cache_data = self.cache.get(cache_key, None) 213bb611c8fSApple OSS Distributions if cache_data: 214bb611c8fSApple OSS Distributions return self.encodeByteString(cache_data) 21588cc0b97SApple OSS Distributions data = GetUserDataAsString(self.task, address, size) 21688cc0b97SApple OSS Distributions if not data: 21788cc0b97SApple OSS Distributions logging.error("Failed to read memory task:{: <#018x} {: <#018x} {:d}".format(self.task, address, size)) 218bb611c8fSApple OSS Distributions else: 219aca3beaaSApple OSS Distributions self.cache[cache_key] = data 22088cc0b97SApple OSS Distributions return self.encodeByteString(data) 22188cc0b97SApple OSS Distributions 22288cc0b97SApple OSS Distributions def getSharedLibInfoAddress(self): 22388cc0b97SApple OSS Distributions return unsigned(self.task.all_image_info_addr) 224