6 from core
.operating_system 
import Armv8_RegisterSet
, Armv7_RegisterSet
, I386_RegisterSet
, X86_64RegisterSet
 
   8 CPU_TYPE_I386 
= 0x00000007 
   9 CPU_TYPE_X86_64 
= 0x01000007 
  10 CPU_TYPE_ARM 
= 0x0000000c 
  11 CPU_TYPE_ARM64 
= 0x0100000c 
  14 CPU_SUBTYPE_X86_64_ALL 
= 3 
  15 CPU_SUBTYPE_X86_64_H 
= 8 
  16 CPU_SUBTYPE_ARMV8 
= 13 
  17 CPU_SUBTYPE_ARM_V7 
= 9 
  18 CPU_SUBTYPE_ARM_V7S 
= 11 
  19 CPU_SUBTYPE_ARM_V7K 
= 12 
  22 def GetRegisterSetForCPU(cputype
, subtype
): 
  23     retval 
= X86_64RegisterSet
 
  24     if cputype 
in (CPU_TYPE_ARM
, CPU_TYPE_ARM64
): 
  25         if subtype 
== CPU_SUBTYPE_ARMV8
: 
  26             retval 
= Armv8_RegisterSet
 
  28             retval 
= Armv7_RegisterSet
 
  29     elif cputype 
== CPU_TYPE_I386
: 
  30         retval 
= I386_RegisterSet
 
  32     return retval
.register_info
['registers'] 
  35 class UserThreadObject(object): 
  36     """representation of userspace thread""" 
  37     def __init__(self
, thr_obj
, cputype
, cpusubtype
, kern_cputype
): 
  38         super(UserThreadObject
, self
).__init
__() 
  40         self
.registerset 
= GetRegisterSetForCPU(cputype
, cpusubtype
) 
  41         self
.thread_id 
= unsigned(self
.thread
.thread_id
) 
  42         self
.is64Bit 
= bool(cputype 
& 0x01000000) 
  43         isKern64Bit 
= bool(kern_cputype 
& 0x01000000) 
  46             if cputype 
== CPU_TYPE_X86_64
: 
  47                 self
.reg_type 
= "x86_64" 
  48                 self
.saved_state 
= Cast(self
.thread
.machine
.iss
, 'x86_saved_state_t *').uss
.ss_64
 
  49             if cputype 
== CPU_TYPE_ARM64
: 
  50                 self
.reg_type 
= "arm64" 
  51                 self
.saved_state 
= self
.thread
.machine
.upcb
.uss
.ss_64
 
  53             if cputype 
== CPU_TYPE_I386
: 
  54                 self
.reg_type 
= "i386" 
  55                 self
.saved_state 
= Cast(self
.thread
.machine
.iss
, 'x86_saved_state_t *').uss
.ss_32
 
  56             if cputype 
== CPU_TYPE_ARM
: 
  59                     self
.saved_state 
= self
.thread
.machine
.PcbData
 
  61                     self
.saved_state 
= self
.thread
.machine
.contextData
.ss
.uss
.ss_32
 
  62         logging
.debug("created thread id 0x%x of type %s, kern_cputype 0x%x cputype 0x%x" 
  63                       % (self
.thread_id
, self
.reg_type
, kern_cputype
, cputype
)) 
  65     def getRegisterValueByName(self
, name
): 
  66         if self
.reg_type 
== 'arm64': 
  67             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'): 
  68                 return unsigned(getattr(self
.saved_state
, 'x')[int(name
.strip('x'))]) 
  70             return unsigned(getattr(self
.saved_state
, name
)) 
  72         if self
.reg_type 
== "x86_64": 
  73             if name 
in ('rip', 'rflags', 'cs', 'rsp', 'cpu'): 
  74                 return unsigned(getattr(self
.saved_state
.isf
, name
)) 
  75             return unsigned(getattr(self
.saved_state
, name
)) 
  77         if self
.reg_type 
== "arm": 
  78             if name 
in ('r0', 'r1', 'r2', 'r3', 'r4', 'r5', 'r6', 'r7', 'r8', 'r9', 'r10', 'r11', 'r12'): 
  79                 retval 
= unsigned(getattr(self
.saved_state
, 'r')[int(name
.strip('r'))]) 
  81                 retval 
= unsigned(getattr(self
.saved_state
, name
)) 
  87         return str(self
.thread_id
) 
  89     def getRegisterData(self
, reg_num
): 
  90         """ returns None if there is error """ 
  91         if reg_num 
< 0 or reg_num 
>= len(self
.registerset
): 
  92             logging
.warning("regnum %d is not defined for thread_id 0x%x" % (reg_num
, self
.thread_id
)) 
  94         return self
.getRegisterValueByName(self
.registerset
[reg_num
]['name']) 
  97 class UserProcess(target
.Process
): 
  98     """ Represent a user process and thread states """ 
  99     def __init__(self
, task
): 
 101         self
.proc 
= Cast(task
.bsd_info
, 'proc_t') 
 102         dataregisters64bit 
= False 
 105         if task
.t_flags 
& 0x1: 
 107         if task
.t_flags 
& 0x2: 
 108             dataregisters64bit 
= 8 
 110         cputype 
= CPU_TYPE_X86_64
 
 111         cpusubtype 
= CPU_SUBTYPE_X86_64_ALL
 
 113         if kern
.arch 
in ('arm'): 
 114             cputype 
= CPU_TYPE_ARM
 
 115             cpusubtype 
= CPU_SUBTYPE_ARM_V7
 
 116         elif kern
.arch 
in ('armv8', 'arm64'): 
 117             cputype 
= CPU_TYPE_ARM64
 
 118             cpusubtype 
= CPU_SUBTYPE_ARMV8
 
 120         super(UserProcess
, self
).__init
__(cputype
, cpusubtype
, ptrsize
) 
 122         self
.hinfo
['ostype'] = 'macosx' 
 123         if cputype 
!= CPU_TYPE_X86_64
: 
 124             self
.hinfo
['ostype'] = 'ios' 
 126         self
.cputype 
= unsigned(self
.proc
.p_cputype
) 
 127         self
.cpusubtype 
= unsigned(self
.proc
.p_cpusubtype
) 
 128         self
.registerset 
= GetRegisterSetForCPU(cputype
, cpusubtype
) 
 129         logging
.debug("process %s is64bit: %d ptrsize: %d cputype: %d  cpusubtype:%d", 
 130                       hex(self
.proc
), int(dataregisters64bit
), ptrsize
, 
 131                       self
.cputype
, self
.cpusubtype
 
 134         self
.threads_ids_list 
= [] 
 135         logging
.debug("iterating over threads in process") 
 136         for thval 
in IterateQueue(task
.threads
, 'thread *', 'task_threads'): 
 137             self
.threads
[unsigned(thval
.thread_id
)] = UserThreadObject(thval
, self
.cputype
, self
.cpusubtype
, cputype
) 
 138             self
.threads_ids_list
.append(unsigned(thval
.thread_id
)) 
 140     def getRegisterDataForThread(self
, th_id
, reg_num
): 
 141         if th_id 
not in self
.threads
: 
 142             logging
.critical("0x%x thread id is not found in this task") 
 144         if reg_num 
< 0 or reg_num 
>= len(self
.registerset
): 
 145             logging
.warning("regnum %d is not defined for thread_id 0x%x" % (reg_num
, th_id
)) 
 147         value 
= self
.threads
[th_id
].getRegisterData(reg_num
) 
 148         return self
.encodeRegisterData(value
, bytesize
=self
.registerset
[reg_num
]['bitsize']/8) 
 150     def getRegisterCombinedDataForThread(self
, th_id
): 
 151         if th_id 
not in self
.threads
: 
 152             logging
.critical("0x%x thread id is not found in this task" % th_id
) 
 154         cur_thread 
= self
.threads
[th_id
] 
 155         retval 
= 'thread:%s;name:%s;' % (self
.encodeThreadID(th_id
), cur_thread
.getName()) 
 157         for rinfo 
in self
.registerset
: 
 160             value 
= cur_thread
.getRegisterValueByName(name
) 
 161             value_endian_correct_str 
= self
.encodeRegisterData(value
, bytesize
=(rinfo
['bitsize']/8)) 
 162             retval 
+= format 
% (pos
, value_endian_correct_str
) 
 166     def getThreadStopInfo(self
, th_id
): 
 167         if th_id 
not in self
.threads
: 
 168             logging
.critical("0x%x thread id is not found in this task") 
 170         return 'T02' + self
.getRegisterCombinedDataForThread(th_id
) + 'threads:' + self
.getThreadsInfo()+';' 
 172     def getRegisterInfo(self
, regnum
): 
 173         #something similar to 
 174         #"name:x1;bitsize:64;offset:8;encoding:uint;format:hex;gcc:1;dwarf:1;set:General Purpose Registers;" 
 175         if regnum 
> len(self
.registerset
): 
 176             logging
.debug("No register_info for number %d." % regnum
) 
 179         rinfo 
= self
.registerset
[regnum
] 
 181         for i 
in rinfo
.keys(): 
 182             i_val 
= str(rinfo
[i
]) 
 184                 i_val 
= 'General Purpose Registers' 
 185             retval 
+= '%s:%s;' % (str(i
), i_val
) 
 189     def getProcessInfo(self
): 
 191         #pid:d22c;parent-pid:d34d;real-uid:ecf;real-gid:b;effective-uid:ecf;effective-gid:b;cputype:1000007;cpusubtype:3; 
 192         #ostype:macosx;vendor:apple;endian:little;ptrsize:8; 
 193         pinfo 
= {'effective-uid': 'ecf', 'effective-gid': 'b', 'endian': 'little', 'vendor': 'apple'}
 
 194         pinfo
['pid'] = "%x" % (GetProcPIDForTask(self
.task
)) 
 195         pinfo
['parent-pid'] = "%x" % (unsigned(self
.proc
.p_ppid
)) 
 196         pinfo
['ptrsize'] = str(self
.ptrsize
) 
 197         pinfo
['ostype'] = 'macosx' 
 198         pinfo
['cputype'] = "%x" % self
.cputype
 
 199         pinfo
['cpusubtype'] = "%x" % self
.cpusubtype
 
 200         pinfo
['real-uid'] = "%x" % (unsigned(self
.proc
.p_ruid
)) 
 201         pinfo
['real-gid'] = "%x" % (unsigned(self
.proc
.p_rgid
)) 
 202         if str(kern
.arch
).find('arm') >= 0: 
 203             pinfo
['ostype'] = 'ios' 
 204         for i 
in pinfo
.keys(): 
 205             i_val 
= str(pinfo
[i
]) 
 206             retval 
+= '%s:%s;' % (str(i
), i_val
) 
 209     def readMemory(self
, address
, size
): 
 210         data 
= GetUserDataAsString(self
.task
, address
, size
) 
 212             logging
.error("Failed to read memory task:{: <#018x} {: <#018x} {:d}".format(self
.task
, address
, size
)) 
 213         return self
.encodeByteString(data
) 
 215     def getSharedLibInfoAddress(self
): 
 216         return unsigned(self
.task
.all_image_info_addr
)