1 2""" Please make sure you read the README COMPLETELY BEFORE reading anything below. 3 It is very critical that you read coding guidelines in Section E in README file. 4""" 5 6from cvalue import * 7from lazytarget import * 8from configuration import * 9from utils import * 10import caching 11import lldb 12 13def IterateTAILQ_HEAD(headval, element_name, list_prefix=''): 14 """ iterate over a TAILQ_HEAD in kernel. refer to bsd/sys/queue.h 15 params: 16 headval - value : value object representing the head of the list 17 element_name - str : string name of the field which holds the list links. 18 list_prefix - str : use 's' here to iterate STAILQ_HEAD instead 19 returns: 20 A generator does not return. It is used for iterating. 21 value : an object that is of type as headval->tqh_first. Always a pointer object 22 example usage: 23 list_head = kern.GetGlobalVariable('mountlist') 24 for entryobj in IterateTAILQ_HEAD(list_head, 'mnt_list'): 25 print GetEntrySummary(entryobj) 26 """ 27 iter_val = headval.__getattr__(list_prefix + 'tqh_first') 28 while unsigned(iter_val) != 0 : 29 yield iter_val 30 iter_val = iter_val.__getattr__(element_name).__getattr__(list_prefix + 'tqe_next') 31 #end of yield loop 32 33def IterateLinkedList(element, field_name): 34 """ iterate over a linked list. 35 This is equivalent to elt = element; while(elt) { do_work(elt); elt = elt-><field_name>; } 36 params: 37 element - value : value object representing element in the list. 38 field_name - str : name of field that holds pointer to next element 39 returns: Nothing. This is used as iterable 40 example usage: 41 first_zone = kern.GetGlobalVariable('first_zone') 42 for zone in IterateLinkedList(first_zone, 'next_zone'): 43 print GetZoneSummary(zone) 44 """ 45 elt = element 46 while unsigned(elt) != 0: 47 yield elt 48 elt = elt.__getattr__(field_name) 49 #end of while loop 50 51def IterateListEntry(element, element_type, field_name, list_prefix=''): 52 """ iterate over a list as defined with LIST_HEAD in bsd/sys/queue.h 53 params: 54 element - value : Value object for lh_first 55 element_type - str : Type of the next element 56 field_name - str : Name of the field in next element's structure 57 list_prefix - str : use 's' here to iterate SLIST_HEAD instead 58 returns: 59 A generator does not return. It is used for iterating 60 value : an object thats of type (element_type) head->le_next. Always a pointer object 61 example usage: 62 headp = kern.globals.initproc.p_children 63 for pp in IterateListEntry(headp, 'struct proc *', 'p_sibling'): 64 print GetProcInfo(pp) 65 """ 66 elt = element.__getattr__(list_prefix + 'lh_first') 67 if type(element_type) == str: 68 element_type = gettype(element_type) 69 while unsigned(elt) != 0: 70 yield elt 71 next_el = elt.__getattr__(field_name).__getattr__(list_prefix + 'le_next') 72 elt = cast(next_el, element_type) 73 74def IterateLinkageChain(queue_head, element_type, field_name, field_ofst=0): 75 """ Iterate over a Linkage Chain queue in kernel of type queue_head_t. (osfmk/kern/queue.h method 1) 76 This is equivalent to the qe_foreach_element() macro 77 params: 78 queue_head - value : Value object for queue_head. 79 element_type - lldb.SBType : pointer type of the element which contains the queue_chain_t. Typically its structs like thread, task etc.. 80 - str : OR a string describing the type. ex. 'task *' 81 field_name - str : Name of the field (in element) which holds a queue_chain_t 82 field_ofst - int : offset from the 'field_name' (in element) which holds a queue_chain_t 83 This is mostly useful if a particular element contains an array of queue_chain_t 84 returns: 85 A generator does not return. It is used for iterating. 86 value : An object thats of type (element_type). Always a pointer object 87 example usage: 88 coalq = kern.GetGlobalVariable('coalitions_q') 89 for coal in IterateLinkageChain(coalq, 'struct coalition *', 'coalitions'): 90 print GetCoalitionInfo(coal) 91 """ 92 global kern 93 if type(element_type) == str: 94 element_type = gettype(element_type) 95 96 if unsigned(queue_head) == 0: 97 return 98 99 if element_type.IsPointerType(): 100 elem_ofst = getfieldoffset(element_type.GetPointeeType(), field_name) + field_ofst 101 else: 102 elem_ofst = getfieldoffset(element_type, field_name) + field_ofst 103 104 link = queue_head.next 105 while (unsigned(link) != unsigned(queue_head)): 106 addr = unsigned(link) - elem_ofst; 107 # I can't use the GetValueFromAddress function of the kernel class 108 # because I have no instance of that class! 109 obj = value(link.GetSBValue().CreateValueFromExpression(None,'(void *)'+str(addr))) 110 obj = cast(obj, element_type) 111 yield obj 112 link = link.next 113 114def IterateCircleQueue(queue_head, element_ptr_type, element_field_name): 115 """ iterate over a circle queue in kernel of type circle_queue_head_t. refer to osfmk/kern/circle_queue.h 116 params: 117 queue_head - lldb.SBValue : Value object for queue_head. 118 element_type - lldb.SBType : a pointer type of the element 'next' points to. Typically its structs like thread, task etc.. 119 element_field_name - str : name of the field in target struct. 120 returns: 121 A generator does not return. It is used for iterating. 122 SBValue : an object thats of type (element_type) queue_head->next. Always a pointer object 123 """ 124 head = queue_head.head.GetSBValue() 125 queue_head_addr = 0x0 126 if head.TypeIsPointerType(): 127 queue_head_addr = head.GetValueAsUnsigned() 128 else: 129 queue_head_addr = head.GetAddress().GetLoadAddress(osplugin_target_obj) 130 cur_elt = head 131 while True: 132 if not cur_elt.IsValid() or cur_elt.GetValueAsUnsigned() == 0: 133 break 134 yield containerof(value(cur_elt), element_ptr_type, element_field_name) 135 cur_elt = cur_elt.GetChildMemberWithName('next') 136 if cur_elt.GetValueAsUnsigned() == queue_head_addr: 137 break 138 139def IterateQueue(queue_head, element_ptr_type, element_field_name, backwards=False, unpack_ptr_fn=None): 140 """ Iterate over an Element Chain queue in kernel of type queue_head_t. (osfmk/kern/queue.h method 2) 141 params: 142 queue_head - value : Value object for queue_head. 143 element_ptr_type - lldb.SBType : a pointer type of the element 'next' points to. Typically its structs like thread, task etc.. 144 - str : OR a string describing the type. ex. 'task *' 145 element_field_name - str : name of the field in target struct. 146 backwards - backwards : traverse the queue backwards 147 unpack_ptr_fn - function : a function ptr of signature def unpack_ptr(long v) which returns long. 148 returns: 149 A generator does not return. It is used for iterating. 150 value : an object thats of type (element_type) queue_head->next. Always a pointer object 151 example usage: 152 for page_meta in IterateQueue(kern.globals.first_zone.pages.all_free, 'struct zone_page_metadata *', 'pages'): 153 print page_meta 154 """ 155 if type(element_ptr_type) == str : 156 element_ptr_type = gettype(element_ptr_type) 157 158 queue_head = queue_head.GetSBValue() 159 queue_head_addr = 0x0 160 if queue_head.TypeIsPointerType(): 161 queue_head_addr = queue_head.GetValueAsUnsigned() 162 else: 163 queue_head_addr = queue_head.GetAddress().GetLoadAddress(LazyTarget.GetTarget()) 164 165 def unpack_ptr_and_recast(v): 166 if unpack_ptr_fn is None: 167 return v 168 v_unpacked = unpack_ptr_fn(v.GetValueAsUnsigned()) 169 obj = v.CreateValueFromExpression(None,'(void *)'+str(v_unpacked)) 170 obj.Cast(element_ptr_type) 171 return obj 172 173 if backwards: 174 cur_elt = unpack_ptr_and_recast(queue_head.GetChildMemberWithName('prev')) 175 else: 176 cur_elt = unpack_ptr_and_recast(queue_head.GetChildMemberWithName('next')) 177 178 while True: 179 180 if not cur_elt.IsValid() or cur_elt.GetValueAsUnsigned() == 0 or cur_elt.GetValueAsUnsigned() == queue_head_addr: 181 break 182 elt = cur_elt.Cast(element_ptr_type) 183 yield value(elt) 184 if backwards: 185 cur_elt = unpack_ptr_and_recast(elt.GetChildMemberWithName(element_field_name).GetChildMemberWithName('prev')) 186 else: 187 cur_elt = unpack_ptr_and_recast(elt.GetChildMemberWithName(element_field_name).GetChildMemberWithName('next')) 188 189 190def IterateRBTreeEntry(element, element_type, field_name): 191 """ iterate over a rbtree as defined with RB_HEAD in libkern/tree.h 192 element - value : Value object for rbh_root 193 element_type - str : Type of the link element 194 field_name - str : Name of the field in link element's structure 195 returns: 196 A generator does not return. It is used for iterating 197 value : an object thats of type (element_type) head->sle_next. Always a pointer object 198 """ 199 elt = element.__getattr__('rbh_root') 200 if type(element_type) == str: 201 element_type = gettype(element_type) 202 203 # Walk to find min 204 parent = elt 205 while unsigned(elt) != 0: 206 parent = elt 207 elt = cast(elt.__getattr__(field_name).__getattr__('rbe_left'), element_type) 208 elt = parent 209 210 # Now elt is min 211 while unsigned(elt) != 0: 212 yield elt 213 # implementation cribbed from RB_NEXT in libkern/tree.h 214 right = cast(elt.__getattr__(field_name).__getattr__('rbe_right'), element_type) 215 if unsigned(right) != 0: 216 elt = right 217 left = cast(elt.__getattr__(field_name).__getattr__('rbe_left'), element_type) 218 while unsigned(left) != 0: 219 elt = left 220 left = cast(elt.__getattr__(field_name).__getattr__('rbe_left'), element_type) 221 else: 222 223 # avoid using GetValueFromAddress 224 addr = elt.__getattr__(field_name).__getattr__('rbe_parent')&~1 225 parent = value(elt.GetSBValue().CreateValueFromExpression(None,'(void *)'+str(addr))) 226 parent = cast(parent, element_type) 227 228 if unsigned(parent) != 0: 229 left = cast(parent.__getattr__(field_name).__getattr__('rbe_left'), element_type) 230 if (unsigned(parent) != 0) and (unsigned(elt) == unsigned(left)): 231 elt = parent 232 else: 233 if unsigned(parent) != 0: 234 right = cast(parent.__getattr__(field_name).__getattr__('rbe_right'), element_type) 235 while unsigned(parent) != 0 and (unsigned(elt) == unsigned(right)): 236 elt = parent 237 238 # avoid using GetValueFromAddress 239 addr = elt.__getattr__(field_name).__getattr__('rbe_parent')&~1 240 parent = value(elt.GetSBValue().CreateValueFromExpression(None,'(void *)'+str(addr))) 241 parent = cast(parent, element_type) 242 243 right = cast(parent.__getattr__(field_name).__getattr__('rbe_right'), element_type) 244 245 # avoid using GetValueFromAddress 246 addr = elt.__getattr__(field_name).__getattr__('rbe_parent')&~1 247 elt = value(elt.GetSBValue().CreateValueFromExpression(None,'(void *)'+str(addr))) 248 elt = cast(elt, element_type) 249 250 251def IterateSchedPriorityQueue(root, element_type, field_name): 252 """ iterate over a priority queue as defined with struct priority_queue from osfmk/kern/priority_queue.h 253 root - value : Value object for the priority queue 254 element_type - str : Type of the link element 255 field_name - str : Name of the field in link element's structure 256 returns: 257 A generator does not return. It is used for iterating 258 value : an object thats of type (element_type). Always a pointer object 259 """ 260 def _make_pqe(addr): 261 return value(root.GetSBValue().CreateValueFromExpression(None,'(struct priority_queue_entry_sched *)'+str(addr))) 262 263 queue = [unsigned(root.pq_root)] 264 265 while len(queue): 266 elt = _make_pqe(queue.pop()) 267 268 while elt: 269 yield containerof(elt, element_type, field_name) 270 addr = unsigned(elt.child) 271 if addr: queue.append(addr) 272 elt = elt.next 273 274def SchedPriorityStableQueueRootPri(root, element_type, field_name): 275 """ Return the root level priority of a priority queue as defined with struct priority_queue from osfmk/kern/priority_queue.h 276 root - value : Value object for the priority queue 277 element_type - str : Type of the link element 278 field_name - str : Name of the field in link element's structure 279 returns: 280 The sched pri of the root element. 281 """ 282 def _make_pqe(addr): 283 return value(root.GetSBValue().CreateValueFromExpression(None,'(struct priority_queue_entry_stable *)'+str(addr))) 284 285 elt = _make_pqe(unsigned(root.pq_root)) 286 return (elt.key >> 8); 287 288def IterateMPSCQueue(root, element_type, field_name): 289 """ iterate over an MPSC queue as defined with struct mpsc_queue_head from osfmk/kern/mpsc_queue.h 290 root - value : Value object for the mpsc queue 291 element_type - str : Type of the link element 292 field_name - str : Name of the field in link element's structure 293 returns: 294 A generator does not return. It is used for iterating 295 value : an object thats of type (element_type). Always a pointer object 296 """ 297 elt = root.mpqh_head.mpqc_next 298 while unsigned(elt): 299 yield containerof(elt, element_type, field_name) 300 elt = elt.mpqc_next 301 302class KernelTarget(object): 303 """ A common kernel object that provides access to kernel objects and information. 304 The class holds global lists for task, terminated_tasks, procs, zones, zombroc etc. 305 It also provides a way to symbolicate an address or create a value from an address. 306 """ 307 def __init__(self, debugger): 308 """ Initialize the kernel debugging environment. 309 Target properties like architecture and connectedness are lazy-evaluted. 310 """ 311 self._debugger = debugger # This holds an lldb.SBDebugger object for debugger state 312 self._threads_list = [] 313 self._tasks_list = [] 314 self._coalitions_list = [] 315 self._thread_groups = [] 316 self._allproc = [] 317 self._terminated_tasks_list = [] 318 self._terminated_threads_list = [] 319 self._zones_list = [] 320 self._zombproc_list = [] 321 self._kernel_types_cache = {} #this will cache the Type objects as and when requested. 322 self._version = None 323 self._arch = None 324 self._ptrsize = None # pointer size of kernel, not userspace 325 self.symbolicator = None 326 class _GlobalVariableFind(object): 327 def __init__(self, kern): 328 self._xnu_kernobj_12obscure12 = kern 329 def __getattr__(self, name): 330 v = self._xnu_kernobj_12obscure12.GetGlobalVariable(name) 331 if not v.GetSBValue().IsValid(): 332 raise ValueError('No such global variable by name: %s '%str(name)) 333 return v 334 self.globals = _GlobalVariableFind(self) 335 LazyTarget.Initialize(debugger) 336 337 def _GetSymbolicator(self): 338 """ Internal function: To initialize the symbolication from lldb.utils 339 """ 340 if not self.symbolicator is None: 341 return self.symbolicator 342 343 from lldb.utils import symbolication 344 symbolicator = symbolication.Symbolicator() 345 symbolicator.target = LazyTarget.GetTarget() 346 self.symbolicator = symbolicator 347 return self.symbolicator 348 349 def Symbolicate(self, addr): 350 """ simple method to get name of function/variable from an address. this is equivalent of gdb 'output /a 0xaddress' 351 params: 352 addr - int : typically hex value like 0xffffff80002c0df0 353 returns: 354 str - '' if no symbol found else the symbol name. 355 Note: this function only finds the first symbol. If you expect multiple symbol conflict please use SymbolicateFromAddress() 356 """ 357 ret_str = '' 358 syms = self.SymbolicateFromAddress(addr) 359 if len(syms) > 0: 360 ret_str +=syms[0].GetName() 361 return ret_str 362 363 def SymbolicateFromAddress(self, addr): 364 """ symbolicates any given address based on modules loaded in the target. 365 params: 366 addr - int : typically hex value like 0xffffff80002c0df0 367 returns: 368 [] of SBSymbol: In case we don't find anything than empty array is returned. 369 Note: a type of symbol can be figured out by gettype() function of SBSymbol. 370 example usage: 371 syms = kern.Symbolicate(0xffffff80002c0df0) 372 for s in syms: 373 if s.GetType() == lldb.eSymbolTypeCode: 374 print "Function", s.GetName() 375 if s.GetType() == lldb.eSymbolTypeData: 376 print "Variable", s.GetName() 377 """ 378 if type(int(1)) != type(addr): 379 if str(addr).strip().find("0x") == 0 : 380 addr = int(addr, 16) 381 else: 382 addr = int(addr) 383 addr = self.StripKernelPAC(addr) 384 ret_array = [] 385 symbolicator = self._GetSymbolicator() 386 syms = symbolicator.symbolicate(addr) 387 if not syms: 388 return ret_array 389 for s in syms: 390 ret_array.append(s.get_symbol_context().symbol) 391 return ret_array 392 393 def IsDebuggerConnected(self): 394 proc_state = LazyTarget.GetProcess().state 395 if proc_state == lldb.eStateInvalid : return False 396 if proc_state in [lldb.eStateStopped, lldb.eStateSuspended] : return True 397 398 def GetGlobalVariable(self, name): 399 """ Get the value object representation for a kernel global variable 400 params: 401 name : str - name of the variable. ex. version 402 returns: value - python object representing global variable. 403 raises : Exception in case the variable is not found. 404 """ 405 self._globals_cache_dict = caching.GetDynamicCacheData("kern._globals_cache_dict", {}) 406 if name not in self._globals_cache_dict: 407 self._globals_cache_dict[name] = value(LazyTarget.GetTarget().FindGlobalVariables(name, 1).GetValueAtIndex(0)) 408 return self._globals_cache_dict[name] 409 410 def PERCPU_BASE(self, cpu): 411 """ Get the PERCPU base for the given cpu number 412 params: 413 cpu : int - the cpu# for this variable 414 returns: int - the base for PERCPU for this cpu index 415 """ 416 if self.arch == 'x86_64': 417 return unsigned(self.globals.cpu_data_ptr[cpu].cpu_pcpu_base) 418 elif self.arch.startswith('arm'): 419 data_entries = self.GetGlobalVariable('CpuDataEntries') 420 return unsigned(data_entries[cpu]) - unsigned(data_entries[0]) 421 422 def PERCPU_GET(self, name, cpu): 423 """ Get the value object representation for a kernel percpu global variable 424 params: 425 name : str - name of the variable. ex. version 426 cpu : int - the cpu# for this variable 427 returns: value - python object representing global variable. 428 raises : Exception in case the variable is not found. 429 """ 430 var = addressof(self.GetGlobalVariable('percpu_slot_' + name)) 431 addr = unsigned(var) + self.PERCPU_BASE(cpu) 432 return dereference(self.GetValueFromAddress(addr, var)) 433 434 def GetLoadAddressForSymbol(self, name): 435 """ Get the load address of a symbol in the kernel. 436 params: 437 name : str - name of the symbol to lookup 438 returns: int - the load address as an integer. Use GetValueFromAddress to cast to a value. 439 raises : LookupError - if the symbol is not found. 440 """ 441 name = str(name) 442 target = LazyTarget.GetTarget() 443 syms_arr = target.FindSymbols(name) 444 if syms_arr.IsValid() and len(syms_arr) > 0: 445 symbol = syms_arr[0].GetSymbol() 446 if symbol.IsValid(): 447 return int(symbol.GetStartAddress().GetLoadAddress(target)) 448 449 raise LookupError("Symbol not found: " + name) 450 451 def GetValueFromAddress(self, addr, type_str = 'void *'): 452 """ convert a address to value 453 params: 454 addr - int : typically hex value like 0xffffff80008dc390 455 type_str - str: type to cast to. Default type will be void * 456 returns: 457 value : a value object which has address as addr and type is type_str 458 """ 459 obj = value(self.globals.version.GetSBValue().CreateValueFromExpression(None,'(void *)'+str(addr))) 460 obj = cast(obj, type_str) 461 return obj 462 463 def GetValueAsType(self, v, t): 464 """ Retrieves a global variable 'v' of type 't' wrapped in a vue object. 465 If 'v' is an address, creates a vue object of the appropriate type. 466 If 'v' is a name, looks for the global variable and asserts its type. 467 Throws: 468 NameError - If 'v' cannot be found 469 TypeError - If 'v' is of the wrong type 470 """ 471 if islong(v): 472 return self.GetValueFromAddress(v, t) 473 else: 474 var = LazyTarget.GetTarget().FindGlobalVariables(v, 1)[0] 475 if not var: 476 raise NameError("Failed to find global variable '{0}'".format(v)) 477 if var.GetTypeName() != t: 478 raise TypeError("{0} must be of type '{1}', not '{2}'".format(v, t, var.GetTypeName())) 479 return value(var) 480 481 def _GetIterator(self, iter_head_name, next_element_name='next', iter_head_type=None): 482 """ returns an iterator for a collection in kernel memory. 483 params: 484 iter_head_name - str : name of queue_head or list head variable. 485 next_element_name - str : name of the element that leads to next element. 486 for ex. in struct zone list 'next_zone' is the linking element. 487 returns: 488 iterable : typically used in conjunction with "for varname in iterable:" 489 """ 490 head_element = self.GetGlobalVariable(iter_head_name) 491 return head_element.GetSBValue().linked_list_iter(next_element_name) 492 493 def TruncPage(self, addr): 494 return (addr & ~(unsigned(self.GetGlobalVariable("page_size")) - 1)) 495 496 def RoundPage(self, addr): 497 return trunc_page(addr + unsigned(self.GetGlobalVariable("page_size")) - 1) 498 499 def StraddlesPage(self, addr, size): 500 if size > unsigned(self.GetGlobalVariable("page_size")): 501 return True 502 val = ((addr + size) & (unsigned(self.GetGlobalVariable("page_size"))-1)) 503 return (val < size and val > 0) 504 505 def StripUserPAC(self, addr): 506 if self.arch != 'arm64e': 507 return addr 508 T0Sz = self.GetGlobalVariable('gT0Sz') 509 return StripPAC(addr, T0Sz) 510 511 def StripKernelPAC(self, addr): 512 if self.arch != 'arm64e': 513 return addr 514 T1Sz = self.GetGlobalVariable('gT1Sz') 515 return StripPAC(addr, T1Sz) 516 517 def PhysToKVARM64(self, addr): 518 ptov_table = self.GetGlobalVariable('ptov_table') 519 for i in range(0, self.GetGlobalVariable('ptov_index')): 520 if (addr >= long(unsigned(ptov_table[i].pa))) and (addr < (long(unsigned(ptov_table[i].pa)) + long(unsigned(ptov_table[i].len)))): 521 return (addr - long(unsigned(ptov_table[i].pa)) + long(unsigned(ptov_table[i].va))) 522 return (addr - unsigned(self.GetGlobalVariable("gPhysBase")) + unsigned(self.GetGlobalVariable("gVirtBase"))) 523 524 def PhysToKernelVirt(self, addr): 525 if self.arch == 'x86_64': 526 return (addr + unsigned(self.GetGlobalVariable('physmap_base'))) 527 elif self.arch.startswith('arm64'): 528 return self.PhysToKVARM64(addr) 529 elif self.arch.startswith('arm'): 530 return (addr - unsigned(self.GetGlobalVariable("gPhysBase")) + unsigned(self.GetGlobalVariable("gVirtBase"))) 531 else: 532 raise ValueError("PhysToVirt does not support {0}".format(self.arch)) 533 534 def GetNanotimeFromAbstime(self, abstime): 535 """ convert absolute time (which is in MATUs) to nano seconds. 536 Since based on architecture the conversion may differ. 537 params: 538 abstime - int absolute time as shown by mach_absolute_time 539 returns: 540 int - nanosecs of time 541 """ 542 usec_divisor = caching.GetStaticCacheData("kern.rtc_usec_divisor", None) 543 if not usec_divisor: 544 if self.arch == 'x86_64': 545 usec_divisor = 1000 546 else: 547 rtclockdata_addr = self.GetLoadAddressForSymbol('RTClockData') 548 rtc = self.GetValueFromAddress(rtclockdata_addr, 'struct _rtclock_data_ *') 549 usec_divisor = unsigned(rtc.rtc_usec_divisor) 550 usec_divisor = int(usec_divisor) 551 caching.SaveStaticCacheData('kern.rtc_usec_divisor', usec_divisor) 552 nsecs = (abstime * 1000)/usec_divisor 553 return nsecs 554 555 def __getattribute__(self, name): 556 if name == 'zones' : 557 self._zones_list = caching.GetDynamicCacheData("kern._zones_list", []) 558 if len(self._zones_list) > 0: return self._zones_list 559 zone_array = self.GetGlobalVariable('zone_array') 560 zone_security_array = self.GetGlobalVariable('zone_security_array') 561 for i in range(0, self.GetGlobalVariable('num_zones')): 562 self._zones_list.append([addressof(zone_array[i]), addressof(zone_security_array[i])]) 563 caching.SaveDynamicCacheData("kern._zones_list", self._zones_list) 564 return self._zones_list 565 566 if name == 'threads' : 567 self._threads_list = caching.GetDynamicCacheData("kern._threads_list", []) 568 if len(self._threads_list) > 0 : return self._threads_list 569 thread_queue_head = self.GetGlobalVariable('threads') 570 thread_type = LazyTarget.GetTarget().FindFirstType('thread') 571 thread_ptr_type = thread_type.GetPointerType() 572 for th in IterateQueue(thread_queue_head, thread_ptr_type, 'threads'): 573 self._threads_list.append(th) 574 caching.SaveDynamicCacheData("kern._threads_list", self._threads_list) 575 return self._threads_list 576 577 if name == 'tasks' : 578 self._tasks_list = caching.GetDynamicCacheData("kern._tasks_list", []) 579 if len(self._tasks_list) > 0 : return self._tasks_list 580 task_queue_head = self.GetGlobalVariable('tasks') 581 task_type = LazyTarget.GetTarget().FindFirstType('task') 582 task_ptr_type = task_type.GetPointerType() 583 for tsk in IterateQueue(task_queue_head, task_ptr_type, 'tasks'): 584 self._tasks_list.append(tsk) 585 caching.SaveDynamicCacheData("kern._tasks_list", self._tasks_list) 586 return self._tasks_list 587 588 if name == 'coalitions' : 589 self._coalitions_list = caching.GetDynamicCacheData("kern._coalitions_list", []) 590 if len(self._coalitions_list) > 0 : return self._coalitions_list 591 coalition_queue_head = self.GetGlobalVariable('coalitions_q') 592 coalition_type = LazyTarget.GetTarget().FindFirstType('coalition') 593 coalition_ptr_type = coalition_type.GetPointerType() 594 for coal in IterateLinkageChain(addressof(coalition_queue_head), coalition_ptr_type, 'coalitions'): 595 self._coalitions_list.append(coal) 596 caching.SaveDynamicCacheData("kern._coalitions_list", self._coalitions_list) 597 return self._coalitions_list 598 599 if name == 'thread_groups' : 600 self._thread_groups_list = caching.GetDynamicCacheData("kern._thread_groups_list", []) 601 if len(self._thread_groups_list) > 0 : return self._thread_groups_list 602 thread_groups_queue_head = self.GetGlobalVariable('tg_queue') 603 thread_group_type = LazyTarget.GetTarget().FindFirstType('thread_group') 604 thread_groups_ptr_type = thread_group_type.GetPointerType() 605 for coal in IterateLinkageChain(addressof(thread_groups_queue_head), thread_groups_ptr_type, 'tg_queue_chain'): 606 self._thread_groups_list.append(coal) 607 caching.SaveDynamicCacheData("kern._thread_groups_list", self._thread_groups_list) 608 return self._thread_groups_list 609 610 if name == 'terminated_tasks' : 611 self._terminated_tasks_list = caching.GetDynamicCacheData("kern._terminated_tasks_list", []) 612 if len(self._terminated_tasks_list) > 0 : return self._terminated_tasks_list 613 task_queue_head = self.GetGlobalVariable('terminated_tasks') 614 task_type = LazyTarget.GetTarget().FindFirstType('task') 615 task_ptr_type = task_type.GetPointerType() 616 for tsk in IterateQueue(task_queue_head, task_ptr_type, 'tasks'): 617 self._terminated_tasks_list.append(tsk) 618 caching.SaveDynamicCacheData("kern._terminated_tasks_list", self._terminated_tasks_list) 619 return self._terminated_tasks_list 620 621 if name == 'terminated_threads' : 622 self._terminated_threads_list = caching.GetDynamicCacheData("kern._terminated_threads_list", []) 623 if len(self._terminated_threads_list) > 0 : return self._terminated_threads_list 624 thread_queue_head = self.GetGlobalVariable('terminated_threads') 625 thread_type = LazyTarget.GetTarget().FindFirstType('thread') 626 thread_ptr_type = thread_type.GetPointerType() 627 for trd in IterateQueue(thread_queue_head, thread_ptr_type, 'threads'): 628 self._terminated_threads_list.append(trd) 629 caching.SaveDynamicCacheData("kern._terminated_threads_list", self._terminated_threads_list) 630 return self._terminated_threads_list 631 632 if name == 'procs' : 633 self._allproc = caching.GetDynamicCacheData("kern._allproc", []) 634 if len(self._allproc) > 0 : return self._allproc 635 all_proc_head = self.GetGlobalVariable('allproc') 636 proc_val = cast(all_proc_head.lh_first, 'proc *') 637 while proc_val != 0: 638 self._allproc.append(proc_val) 639 proc_val = cast(proc_val.p_list.le_next, 'proc *') 640 caching.SaveDynamicCacheData("kern._allproc", self._allproc) 641 return self._allproc 642 643 if name == 'interrupt_stats' : 644 self._interrupt_stats_list = caching.GetDynamicCacheData("kern._interrupt_stats_list", []) 645 if len(self._interrupt_stats_list) > 0 : return self._interrupt_stats_list 646 interrupt_stats_head = self.GetGlobalVariable('gInterruptAccountingDataList') 647 interrupt_stats_type = LazyTarget.GetTarget().FindFirstType('IOInterruptAccountingData') 648 interrupt_stats_ptr_type = interrupt_stats_type.GetPointerType() 649 for interrupt_stats_obj in IterateQueue(interrupt_stats_head, interrupt_stats_ptr_type, 'chain'): 650 self._interrupt_stats_list.append(interrupt_stats_obj) 651 caching.SaveDynamicCacheData("kern._interrupt_stats", self._interrupt_stats_list) 652 return self._interrupt_stats_list 653 654 if name == 'zombprocs' : 655 self._zombproc_list = caching.GetDynamicCacheData("kern._zombproc_list", []) 656 if len(self._zombproc_list) > 0 : return self._zombproc_list 657 zproc_head = self.GetGlobalVariable('zombproc') 658 proc_val = cast(zproc_head.lh_first, 'proc *') 659 while proc_val != 0: 660 self._zombproc_list.append(proc_val) 661 proc_val = cast(proc_val.p_list.le_next, 'proc *') 662 caching.SaveDynamicCacheData("kern._zombproc_list", self._zombproc_list) 663 return self._zombproc_list 664 665 if name == 'version' : 666 self._version = caching.GetStaticCacheData("kern.version", None) 667 if self._version != None : return self._version 668 self._version = str(self.GetGlobalVariable('version')) 669 caching.SaveStaticCacheData("kern.version", self._version) 670 return self._version 671 672 if name == 'arch' : 673 self._arch = caching.GetStaticCacheData("kern.arch", None) 674 if self._arch != None : return self._arch 675 arch = LazyTarget.GetTarget().triple.split('-')[0] 676 if arch in ('armv7', 'armv7s', 'armv7k'): 677 self._arch = 'arm' 678 else: 679 self._arch = arch 680 caching.SaveStaticCacheData("kern.arch", self._arch) 681 return self._arch 682 683 if name == 'ptrsize' : 684 self._ptrsize = caching.GetStaticCacheData("kern.ptrsize", None) 685 if self._ptrsize != None : return self._ptrsize 686 arch = LazyTarget.GetTarget().triple.split('-')[0] 687 if arch == 'x86_64' or arch.startswith('arm64'): 688 self._ptrsize = 8 689 else: 690 self._ptrsize = 4 691 caching.SaveStaticCacheData("kern.ptrsize", self._ptrsize) 692 return self._ptrsize 693 694 if name == 'VM_MIN_KERNEL_ADDRESS': 695 if self.arch == 'x86_64': 696 return unsigned(0xFFFFFF8000000000) 697 elif self.arch.startswith('arm64'): 698 return unsigned(0xffffffe000000000) 699 else: 700 return unsigned(0x80000000) 701 702 if name == 'VM_MIN_KERNEL_AND_KEXT_ADDRESS': 703 if self.arch == 'x86_64': 704 return self.VM_MIN_KERNEL_ADDRESS - 0x80000000 705 else: 706 return self.VM_MIN_KERNEL_ADDRESS 707 708 return object.__getattribute__(self, name) 709