1   
   2   
   3   
   4   
   5   
   6   
   7   
   8   
   9   
  10   
  11   
  12   
  13   
  14   
  15   
  16   
  17   
  18   
  19  __author__ = "Michael Cohen <scudette@gmail.com>" 
  20   
  21  from rekall import obj 
  22   
  23  from rekall.plugins.addrspaces import amd64 
  24  from rekall.plugins.overlays import basic 
  25  from rekall_lib import utils 
  26   
  27   
  28  darwin_overlay = { 
  29      "proc": [None, { 
  30           
  31          "name": lambda x: x.p_comm, 
  32          "pid": lambda x: x.p_pid.v(), 
  33          "dtb": lambda x: x.task.map.pmap.pm_cr3.v(), 
  34   
  35          "p_list": [None, ["LIST_ENTRY"]], 
  36          "p_sibling": [None, ["LIST_ENTRY"]], 
  37   
  38          "p_comm": [None, ["UnicodeString", dict(length=17)]], 
  39          "task": [None, ["Pointer", dict( 
  40              target="task" 
  41          )]], 
  42      }], 
  43   
  44      "task": [None, { 
  45          "bsd_info": [None, ["Pointer", dict(target="proc")]], 
  46      }], 
  47   
  48      "rtentry": [None, { 
  49          "base_calendartime": [None, ["UnixTimeStamp"]], 
  50   
  51          "source_ip": lambda x: x.rt_nodes[0].rn_u.rn_leaf.m( 
  52              "rn_Key").dereference_as("sockaddr"), 
  53   
  54          "dest_ip": lambda x: x.rt_gateway.deref(), 
  55   
  56          "name": lambda x: x.rt_ifp.name, 
  57   
  58          "sent": lambda x: x.m("rt_stats").nstat_txpackets, 
  59   
  60          "rx": lambda x: x.rt_expire if x.m("rt_stats") else None, 
  61   
  62          "delta": lambda x: (x.rt_expire - x.base_uptime 
  63                              if x.rt_expire else 0), 
  64   
  65      }], 
  66   
  67      "kmod_info": [None, { 
  68          "name": lambda x: utils.SmartUnicode(x.m("name").cast("UnicodeString")), 
  69          "base": lambda x: x.address.v(), 
  70          "end": lambda x: x.base + x.size, 
  71          "version": [None, ["String"]], 
  72   
  73           
  74          "address": [None, ["Pointer"]], 
  75      }], 
  76   
  77      "sockaddr": [None, { 
  78           
  79          "sa_family": [None, ["Enumeration", dict( 
  80              enum_name="sa_family_t", 
  81              target="unsigned char", 
  82          )]], 
  83      }], 
  84   
  85      "sysctl_oid": [None, { 
  86           
  87           
  88           
  89          "oid_kind_type": lambda x: x.m("oid_kind").cast( 
  90              "Enumeration", choices={ 
  91                  1: "CTLTYPE_NODE", 
  92                  2: "CTLTYPE_INT", 
  93                  3: "CTLTYPE_STRING", 
  94                  4: "CTLTYPE_QUAD", 
  95                  5: "CTLTYPE_OPAQUE", 
  96              }, 
  97              target="BitField", 
  98              target_args=dict(start_bit=0, end_bit=8), 
  99          ), 
 100   
 101          "oid_perms": lambda x: x.m("oid_kind").cast( 
 102              "Flags", maskmap={ 
 103                  "CTLFLAG_RD": 0x80000000,   
 104                  "CTLFLAG_WR": 0x40000000,   
 105                   
 106                  "CTLFLAG_LOCKED": 0x00800000, 
 107              }, 
 108          ), 
 109   
 110          "oid_name": [None, ["Pointer", dict(target="String")]], 
 111   
 112      }], 
 113   
 114      "zone": [None, { 
 115          "zone_name": [None, ["Pointer", dict(target="String")]], 
 116          "free_elements": [None, ["Pointer", dict( 
 117              target="zone_free_element" 
 118          )]], 
 119      }], 
 120   
 121      "vm_map_entry": [None, { 
 122           
 123          "protection": [None, ["Flags", dict( 
 124              maskmap={ 
 125                  "VM_PROT_READ": 1, 
 126                  "VM_PROT_WRITE": 2, 
 127                  "VM_PROT_EXECUTE": 4, 
 128              }, 
 129              target="BitField", 
 130              target_args=dict( 
 131                  start_bit=7, 
 132                  end_bit=10 
 133              ) 
 134          )]], 
 135          "max_protection": [None, ["Flags", dict( 
 136              maskmap={ 
 137                  "VM_PROT_READ": 1, 
 138                  "VM_PROT_WRITE": 2, 
 139                  "VM_PROT_EXECUTE": 4, 
 140              }, 
 141              target="BitField", 
 142              target_args=dict( 
 143                  start_bit=10, 
 144                  end_bit=13 
 145              ) 
 146          )]], 
 147      }], 
 148   
 149      "vnode": [None, { 
 150          "v_name": [None, ["Pointer", dict(target="String")]], 
 151   
 152          "path": lambda self: "/".join(reversed( 
 153              [unicode(y.v_name.deref()) for y in self.walk_list("v_parent")])), 
 154   
 155           
 156          "v_flag": [None, ["Flags", dict( 
 157              maskmap={ 
 158                  "VROOT": 0x000001, 
 159                  "VTEXT": 0x000002, 
 160                  "VSYSTEM": 0x000004, 
 161                  "VISTTY": 0x000008, 
 162                  "VRAGE": 0x000010, 
 163              } 
 164          )]], 
 165      }], 
 166   
 167      "cat_attr": [None, { 
 168          "ca_atime": [None, ["UnixTimeStamp"]], 
 169          "ca_atimeondisk": [None, ["UnixTimeStamp"]], 
 170          "ca_mtime": [None, ["UnixTimeStamp"]], 
 171          "ca_ctime": [None, ["UnixTimeStamp"]], 
 172          "ca_itime": [None, ["UnixTimeStamp"]], 
 173          "ca_btime": [None, ["UnixTimeStamp"]], 
 174      }], 
 175   
 176      "ifnet": [None, { 
 177          "if_name": [None, ["Pointer", dict(target="String")]], 
 178      }], 
 179   
 180      "session": [None, { 
 181          "s_login": [None, ["String"]], 
 182      }], 
 183   
 184      "filedesc": [None, { 
 185           
 186           
 187          "fd_ofileflags": [None, ["Pointer", dict( 
 188              target="Array", 
 189              target_args=dict( 
 190                  target="Flags", 
 191                  target_args=dict( 
 192                      target="unsigned char", 
 193                      maskmap=utils.MaskMapFromDefines(""" 
 194  /* 
 195   * Per-process open flags. 
 196   */ 
 197  #define UF_EXCLOSE      0x01            /* auto-close on exec */ 
 198  #define UF_FORKCLOSE    0x02            /* auto-close on fork */ 
 199  #define UF_RESERVED     0x04            /* open pending / in progress */ 
 200  #define UF_CLOSING      0x08            /* close in progress */ 
 201   
 202  #define UF_RESVWAIT     0x10            /* close in progress */ 
 203  #define UF_INHERIT      0x20            /* "inherit-on-exec" */ 
 204  """))))]], 
 205   
 206          "fd_ofiles": [None, ["Pointer", dict( 
 207              target="Array", 
 208              target_args=dict( 
 209                  target="Pointer", 
 210                  count=lambda x: x.fd_lastfile, 
 211                  target_args=dict( 
 212                      target="fileproc" 
 213                  ) 
 214              ) 
 215          )]], 
 216      }], 
 217   
 218      "mount": [None, { 
 219           
 220          "mnt_flag": [None, ["Flags", dict( 
 221              maskmap={ 
 222                  "MNT_LOCAL": 0x00001000, 
 223                  "MNT_QUOTA": 0x00002000, 
 224                  "MNT_ROOTFS": 0x00004000, 
 225              } 
 226          )]], 
 227      }], 
 228   
 229      "vfsstatfs": [None, { 
 230          "f_mntonname": [None, ["String"]], 
 231          "f_mntfromname": [None, ["String"]], 
 232          "f_fstypename": [None, ["String"]], 
 233      }], 
 234   
 235      "sockaddr_un": [None, { 
 236           
 237           
 238           
 239           
 240           
 241           
 242           
 243          "sun_path": [None, ["String", dict( 
 244              length=lambda x: ( 
 245                  x.sun_len 
 246                  - x.obj_profile.get_obj_offset("sockaddr_un", "sun_path") 
 247              ), 
 248          )]], 
 249      }], 
 250   
 251      "domain": [None, { 
 252           
 253          "dom_family": [None, ["Enumeration", dict( 
 254              enum_name="sa_family_t", 
 255              target="unsigned char", 
 256          )]], 
 257      }], 
 258   
 259      "tcpcb": [None, { 
 260          "t_state": [None, ["Enumeration", dict( 
 261               
 262              choices={ 
 263                  0: "TCPS_CLOSED", 
 264                  1: "TCPS_LISTEN", 
 265                  2: "TCPS_SYN_SENT", 
 266                  3: "TCPS_SYN_RECEIVED", 
 267                  4: "TCPS_ESTABLISHED", 
 268                  5: "TCPS_CLOSE_WAIT", 
 269                  6: "TCPS_FIN_WAIT_1", 
 270                  7: "TCPS_CLOSING", 
 271                  8: "TCPS_LAST_ACK", 
 272                  9: "TCPS_FIN_WAIT_2", 
 273                  10: "TCPS_TIME_WAIT", 
 274              }, 
 275              target="int", 
 276          )]], 
 277      }], 
 278   
 279      "protosw": [None, { 
 280          "pr_protocol": [None, ["Enumeration", dict( 
 281               
 282              choices={ 
 283                  0: "IPPROTO_IP", 
 284                  1: "IPPROTO_ICMP", 
 285                  2: "IPPROTO_IGMP", 
 286                  4: "IPPROTO_IPV4", 
 287                  6: "IPPROTO_TCP", 
 288                  17: "IPPROTO_UDP", 
 289                  41: "IPPROTO_IPV6", 
 290                  50: "IPPROTO_ESP", 
 291                  51: "IPPROTO_AH", 
 292                  58: "IPPROTO_ICMPV6", 
 293                  255: "IPPROTO_RAW", 
 294              }, 
 295              target="short", 
 296          )]], 
 297          "pr_type": [None, ["Enumeration", dict( 
 298              enum_name="pr_type", 
 299              target="short", 
 300          )]], 
 301      }], 
 302   
 303      "OSDictionary": [None, { 
 304          "dictionary": [None, ["Pointer", dict( 
 305              target="Array", 
 306              target_args=dict( 
 307                  target="dictEntry", 
 308                  count=lambda x: x.count, 
 309              ) 
 310          )]], 
 311      }], 
 312   
 313      "OSString": [None, { 
 314          "value": lambda x: x.obj_profile.UnicodeString( 
 315              offset=x.string, 
 316              length=x.length 
 317          ), 
 318      }], 
 319   
 320      "OSOrderedSet": [None, { 
 321          "array": [None, ["Pointer", dict( 
 322              target="Array", 
 323              target_args=dict( 
 324                  target="_Element", 
 325                  count=lambda x: x.count 
 326              ) 
 327          )]], 
 328      }], 
 329   
 330      "_Element": [8, { 
 331          "obj": [0, ["pointer", ["OSMetaClassBase"]]] 
 332      }], 
 333   
 334      "PE_state": [None, { 
 335          "bootArgs": [None, ["Pointer", dict(target="boot_args")]], 
 336      }], 
 337   
 338      "boot_args": [None, { 
 339          "CommandLine": [None, ["String"]] 
 340      }], 
 341   
 342      "EfiMemoryRange": [None, { 
 343           
 344          "Type": [None, ["Enumeration", dict( 
 345              choices={ 
 346                  0: "kEfiReservedMemoryType", 
 347                  1: "kEfiLoaderCode", 
 348                  2: "kEfiLoaderData", 
 349                  3: "kEfiBootServicesCode", 
 350                  4: "kEfiBootServicesData", 
 351                  5: "kEfiRuntimeServicesCode", 
 352                  6: "kEfiRuntimeServicesData", 
 353                  7: "kEfiConventionalMemory", 
 354                  8: "kEfiUnusableMemory", 
 355                  9: "kEfiACPIReclaimMemory", 
 356                  10: "kEfiACPIMemoryNVS", 
 357                  11: "kEfiMemoryMappedIO", 
 358                  12: "kEfiMemoryMappedIOPortSpace", 
 359                  13: "kEfiPalCode", 
 360                  14: "kEfiMaxMemoryType", 
 361              }, 
 362              target="unsigned int" 
 363          )]], 
 364      }] 
 365  } 
 366   
 367   
 368  darwin_enums = { 
 369       
 370       
 371       
 372       
 373       
 374       
 375       
 376       
 377       
 378       
 379       
 380       
 381       
 382       
 383       
 384       
 385       
 386      "sa_family_t": utils.EnumerationFromDefines(""" 
 387  /* 
 388   * Address families. 
 389   */ 
 390  #define AF_UNSPEC       0               /* unspecified */ 
 391  #define AF_UNIX         1               /* local to host (pipes) */ 
 392  #define AF_INET         2               /* internetwork: UDP, TCP, etc. */ 
 393  #define AF_IMPLINK      3               /* arpanet imp addresses */ 
 394  #define AF_PUP          4               /* pup protocols: e.g. BSP */ 
 395  #define AF_CHAOS        5               /* mit CHAOS protocols */ 
 396  #define AF_NS           6               /* XEROX NS protocols */ 
 397  #define AF_ISO          7               /* ISO protocols */ 
 398  #define AF_ECMA         8               /* European computer manufacturers */ 
 399  #define AF_DATAKIT      9               /* datakit protocols */ 
 400  #define AF_CCITT        10              /* CCITT protocols, X.25 etc */ 
 401  #define AF_SNA          11              /* IBM SNA */ 
 402  #define AF_DECnet       12              /* DECnet */ 
 403  #define AF_DLI          13              /* DEC Direct data link interface */ 
 404  #define AF_LAT          14              /* LAT */ 
 405  #define AF_HYLINK       15              /* NSC Hyperchannel */ 
 406  #define AF_APPLETALK    16              /* Apple Talk */ 
 407  #define AF_ROUTE        17              /* Internal Routing Protocol */ 
 408  #define AF_LINK         18              /* Link layer interface */ 
 409  #define pseudo_AF_XTP   19              /* eXpress Transfer Protocol (no AF) */ 
 410  #define AF_COIP         20              /* connection-oriented IP, aka ST II */ 
 411  #define AF_CNT          21              /* Computer Network Technology */ 
 412  #define pseudo_AF_RTIP  22              /* Help Identify RTIP packets */ 
 413  #define AF_IPX          23              /* Novell Internet Protocol */ 
 414  #define AF_SIP          24              /* Simple Internet Protocol */ 
 415  #define pseudo_AF_PIP   25              /* Help Identify PIP packets */ 
 416  #define AF_NDRV         27              /* Network Driver 'raw' access */ 
 417  #define AF_ISDN         28              /* Integrated Services Digital Network*/ 
 418  #define pseudo_AF_KEY   29              /* Internal key-management function */ 
 419  #define AF_INET6        30              /* IPv6 */ 
 420  #define AF_NATM         31              /* native ATM access */ 
 421  #define AF_SYSTEM       32              /* Kernel event messages */ 
 422  #define AF_NETBIOS      33              /* NetBIOS */ 
 423  #define AF_PPP          34              /* PPP communication protocol */ 
 424  #define pseudo_AF_HDRCMPLT 35           /* Used by BPF to not rewrite headers 
 425                                           * in interface output routine */ 
 426  #define AF_AFP          36              /* Used by AFP */ 
 427  #define AF_IEEE80211    37              /* IEEE 802.11 protocol */ 
 428  #define AF_UTUN         38 
 429  #define AF_MULTIPATH    39 
 430  #define AF_MAX          40 
 431  """), 
 432   
 433       
 434       
 435      "pr_type": utils.EnumerationFromDefines(""" 
 436  /* 
 437   * Types 
 438   */ 
 439  #define SOCK_STREAM     1               /* stream socket */ 
 440  #define SOCK_DGRAM      2               /* datagram socket */ 
 441  #define SOCK_RAW        3               /* raw-protocol interface */ 
 442  #define SOCK_RDM        4               /* reliably-delivered message */ 
 443  #define SOCK_SEQPACKET  5               /* sequenced packet stream */ 
 444  """), 
 445  } 
 446   
 447  darwin64_types = { 
 448      "LIST_ENTRY": [16, { 
 449          "le_next": [0, ["Pointer"]], 
 450          "le_prev": [8, ["Pointer", dict(target="Pointer")]], 
 451      }], 
 452  } 
 453   
 454   
 455 -class LIST_ENTRY(obj.Struct): 
  456      """XNU defines lists inline using an annonymous struct. This makes it hard 
 457      for us to automatically support lists because the debugging symbols dont 
 458      indicate this inner struct is of any particular type (since its annonymous). 
 459   
 460      We therefore depend on the overlays to redefine each list memeber as a 
 461      LIST_ENTRY member. For example we see code like: 
 462   
 463      struct proc { 
 464         LIST_ENTRY(proc) p_list; 
 465         ... 
 466   
 467      Where: 
 468   
 469      #define  LIST_ENTRY(type)                                       \ 
 470        struct {                                                      \ 
 471        struct type *le_next;  /* next element */                     \ 
 472        struct type **le_prev; /* address of previous next element */ \ 
 473      } 
 474      """ 
 475      _forward = "le_next" 
 476      _backward = "le_prev" 
 477   
 478 -    def is_valid(self): 
  479          """Must have both valid next and prev pointers.""" 
 480          return (self.m(self._forward).is_valid() and 
 481                  self.m(self._backward).is_valid()) 
  482   
 483 -    def _GetNextEntry(self, type, member): 
  484          return self.m(self._forward).dereference_as(type).m(member) 
  485   
 487          return self.m(self._backward).dereference_as(self.obj_type) 
  488   
 489 -    def dereference_as(self, type, member, vm=None): 
  490          """Recasts the list entry as a member in a type, and return the type. 
 491   
 492          Args: 
 493          type: The name of this Struct type. 
 494          member: The name of the member of this Struct. 
 495          address_space: An optional address space to switch during 
 496          deferencing. 
 497          """ 
 498          offset = self.obj_profile.get_obj_offset(type, member) 
 499   
 500          item = self.obj_profile.Object( 
 501              type_name=type, offset=self.obj_offset - offset, 
 502              vm=vm or self.obj_vm, parent=self.obj_parent, 
 503              name=type, context=self.obj_context) 
 504   
 505          return item 
  506   
 507 -    def find_all_lists(self, type, member, seen=None): 
  508          """Follows all the list entries starting from lst. 
 509   
 510          We basically convert the list to a tree and recursively search it for 
 511          new nodes. From each node we follow the Flink and then the Blink. When 
 512          we see a node we already have, we backtrack. 
 513          """ 
 514          if seen is None: 
 515              seen = set() 
 516   
 517          if not self.is_valid(): 
 518              return seen 
 519   
 520          elif self in seen: 
 521              return seen 
 522   
 523          seen.add(self) 
 524   
 525          flink = self._GetNextEntry(type, member) 
 526          flink.find_all_lists(type, member, seen=seen) 
 527   
 528          blink = self._GetPreviousEntry() 
 529          blink.find_all_lists(type, member, seen=seen) 
 530   
 531          return seen 
  532   
 533 -    def list_of_type(self, type, member=None, include_current=True): 
  534           
 535           
 536          result = sorted(self.find_all_lists(type, member), 
 537                          key=lambda x: x.obj_offset) 
 538   
 539          if member is None: 
 540              member = self.obj_name 
 541   
 542           
 543          if include_current: 
 544              yield self.dereference_as(type, member) 
 545   
 546           
 547           
 548          for lst in result: 
 549               
 550               
 551              if lst.obj_offset == self.obj_offset: 
 552                  continue 
 553   
 554              task = lst.dereference_as(type, member) 
 555              if task: 
 556                   
 557                  yield task 
  558   
 559 -    def reflect(self, vm=None): 
  560          """Reflect this list element by following its Flink and Blink. 
 561   
 562          This is basically the same as Flink.Blink except that it also checks 
 563          Blink.Flink. It also ensures that Flink and Blink are dereferences to 
 564          the correct type in case the vtypes do not specify them as pointers. 
 565   
 566          Returns: 
 567          the result of Flink.Blink. 
 568          """ 
 569          result1 = self.m(self._forward).dereference_as( 
 570              self.obj_type, vm=vm).m(self._backward).deref().cast( 
 571                  self.obj_type) 
 572   
 573          if not result1: 
 574              return obj.NoneObject("Flink not valid.") 
 575   
 576          result2 = self.Blink.deref().dereference_as( 
 577              self.obj_type, vm=vm).m( 
 578                  self._forward).dereference_as(self.obj_type) 
 579   
 580          if result1 != result2: 
 581              return obj.NoneObject("Flink and Blink not consistent.") 
 582   
 583          return result1 
  584   
 585 -    def __nonzero__(self): 
  586           
 587          return bool(self.m(self._forward)) or bool(self.m(self._backward)) 
  588   
 589 -    def __iter__(self): 
  590          return self.list_of_type(self.obj_parent.obj_type, self.obj_name) 
   591   
 594      @utils.safe_property 
 596          try: 
 597              return self.la_rt.rt_llinfo.v() == self.obj_offset 
 598          except AttributeError: 
 599              return False 
   600   
 601   
 602 -class queue_entry(basic.ListMixIn, obj.Struct): 
  603      """A queue_entry is an externalized linked list. 
 604   
 605      Although the queue_entry is defined as: 
 606   
 607      struct queue_entry { 
 608          struct queue_entry      *next;          /* next element */ 
 609          struct queue_entry      *prev;          /* previous element */ 
 610      }; 
 611   
 612      This is in fact not correct since the next, and prev pointers 
 613      point to the start of the next struct. A queue_entry has a queue 
 614      head which is also a queue entry and this can eb iterated over 
 615      using the list_of_type method. 
 616   
 617      NOTE: list_of_type should only be called on the head queue_entry. 
 618      """ 
 619      _forward = "next" 
 620      _backward = "prev" 
 621   
 622 -    def list_of_type(self, type, member): 
  623          seen = set() 
 624          seen.add(self.prev.v()) 
 625   
 626          item = self.next.dereference_as(type) 
 627          while item != None: 
 628              yield item 
 629              if item.obj_offset in seen: 
 630                  return 
 631              seen.add(item.obj_offset) 
 632              item = item.m(member).next.dereference_as(type) 
   633   
 637          result = [] 
 638          for i in xrange(self.sdl_alen): 
 639              result.append( 
 640                  "%.02X" % ord(self.sdl_data[self.sdl_nlen + i].v())) 
 641   
 642          return ":".join(result) 
  646      """Represents an open file, owned by a process.""" 
 647   
 648      DTYPE_TO_HUMAN = { 
 649          "DTYPE_SOCKET": "socket", 
 650          "DTYPE_VNODE": "vnode", 
 651          "DTYPE_PSXSEM": "POSIX Semaphore", 
 652          "DTYPE_PSXSHM": "POSIX Shared Mem.", 
 653          "DTYPE_KQUEUE": "kernel queue", 
 654          "DTYPE_PIPE": "pipe", 
 655          "DTYPE_FSEVENTS": "FS Events",   
 656   
 657           
 658           
 659           
 660           
 661           
 662          "DTYPE_ATALK": "<unknown>", 
 663          "-": "INVALID", 
 664      } 
 665   
 666      @utils.safe_property 
 668          """Returns type of the fileglob (e.g. vnode, socket, etc.)""" 
 669          return self.multi_m( 
 670               
 671              "f_fglob.fg_type", 
 672   
 673               
 674              "f_fglob.fg_ops.fo_type") 
  675   
 676      @property 
 678          """Return the associated socket if the dtype is for socket.""" 
 679          if self.fg_type == "DTYPE_SOCKET": 
 680              return self.f_fglob.fg_data.dereference_as("socket") 
  681   
 682      @property 
 684          """Return the associated vnode if the dtype is for vnode.""" 
 685          if self.fg_type == "DTYPE_VNODE": 
 686              return self.f_fglob.fg_data.dereference_as("vnode") 
  687   
 689          """Returns the correct struct with fg_type-specific information. 
 690   
 691          This can be one of vnode, socket, shared memory or semaphore [1]. 
 692   
 693          Of those four, we currently only get extra information for vnode and 
 694          socket. For everything else, we return a NoneObject. 
 695   
 696          [1]: 
 697            https://github.com/opensource-apple/xnu/blob/10.9/bsd/sys/file_internal.h#L184 
 698          """ 
 699          dtype = self.fg_type 
 700   
 701           
 702           
 703          if dtype == "DTYPE_SOCKET": 
 704              return self.f_fglob.fg_data.dereference_as("socket") 
 705          elif dtype == "DTYPE_VNODE": 
 706              return self.f_fglob.fg_data.dereference_as("vnode") 
 707           
 708           
 709           
 710           
 711   
 712           
 713          return self.f_fglob.fg_data 
  714   
 715      @utils.safe_property 
 718   
 719      @utils.safe_property 
  727   
 730      """Provides human-readable accessors for sockets of the more common AFs. 
 731   
 732      This class has two basic ways of getting information. Most attributes are 
 733      computed using the method fill_socketinfo, which is directly adapted from 
 734      the kernel function of the same name. For the few things that 
 735      fill_socketinfo doesn't care about, the properties themselves get the 
 736      data and provide references to the kernel source for anyone wondering 
 737      why and how all this works. 
 738      """ 
 739   
 740      cached_socketinfo = None 
 741   
 743          """Computes information about sockets of some addressing families. 
 744   
 745          This function is directly adapted from the kernel function 
 746          fill_socketinfo [1]. The original function is used to fill a struct 
 747          with addressing and other useful information about sockets of a few 
 748          key addressing families. All families are supported, but only the 
 749          following will return useful information: 
 750            - AF_INET (IPv4) 
 751            - AF_INET6 (IPv6) 
 752            - AF_UNIX (Unix socket) 
 753            - AF_NDRV (Network driver raw access) 
 754            - AF_SYSTEM (Darwin-specific; see documentation [3]) 
 755   
 756          Differences between the kernel function and this adaptation: 
 757            - The kernel uses Protocol Families (prefixed with PF_). Rekall 
 758            relies on Addressing Families (AF_) which are exactly the same. 
 759   
 760            - The kernel fills a struct; this function returns a dict with the 
 761            same members. 
 762   
 763            - The kernel returns the data raw. This function converts endianness 
 764            and unions to human-readable representations, as appropriate. 
 765   
 766            - Only a subset of members are filled in. 
 767   
 768            - Other differences as documented in code. 
 769   
 770          Returns: 
 771            A dict with the same members as struct socket_info and related. 
 772            Only member that's always filled is "soi_kind". That's not Spanish, 
 773            but one of the values in this anonymous enum [2], which determines 
 774            what other members are present. (Read the code.) 
 775   
 776          [1] 
 777          https://github.com/opensource-apple/xnu/blob/10.9/bsd/kern/socket_info.c#L98 
 778          [2] 
 779          https://github.com/opensource-apple/xnu/blob/10.9/bsd/sys/proc_info.h#L503 
 780          [3] "KEXT Controls and Notifications" 
 781          https://developer.apple.com/library/mac/documentation/Darwin/Conceptual/NKEConceptual/control/control.html 
 782          """ 
 783          domain = self.so_proto.pr_domain.dom_family 
 784          type_name = self.so_proto.pr_type 
 785          protocol = self.so_proto.pr_protocol 
 786   
 787          si = {"soi_kind": "SOCKINFO_GENERIC"} 
 788   
 789           
 790           
 791          if domain in ["AF_INET", "AF_INET6"]: 
 792              si["soi_kind"] = "SOCKINFO_IN" 
 793   
 794              inp = self.so_pcb.dereference_as("inpcb") 
 795   
 796              si["insi_fport"] = utils.ntoh(inp.inp_fport) 
 797              si["insi_lport"] = utils.ntoh(inp.inp_lport) 
 798              si["insi_ip_ttl"] = inp.inp_ip_ttl.v() 
 799   
 800               
 801               
 802               
 803              if domain == "AF_INET": 
 804                  si["insi_faddr"] = utils.FormatIPAddress( 
 805                      "AF_INET", 
 806                      inp.inp_dependfaddr.inp46_foreign.ia46_addr4.s_addr 
 807                  ) 
 808                  si["insi_laddr"] = utils.FormatIPAddress( 
 809                      "AF_INET", 
 810                      inp.inp_dependladdr.inp46_local.ia46_addr4.s_addr 
 811                  ) 
 812              else: 
 813                  si["insi_faddr"] = utils.FormatIPAddress( 
 814                      "AF_INET6", 
 815                      inp.inp_dependfaddr.inp6_foreign.m("__u6_addr") 
 816                  ) 
 817                  si["insi_laddr"] = utils.FormatIPAddress( 
 818                      "AF_INET6", 
 819                      inp.inp_dependladdr.inp6_local.m("__u6_addr") 
 820                  ) 
 821   
 822              if (type_name == "SOCK_STREAM" 
 823                      and (protocol == 0 or protocol == "IPPROTO_TCP") 
 824                      and inp.inp_ppcb != None): 
 825   
 826                  tp = inp.inp_ppcb.dereference_as("tcpcb") 
 827                  si["soi_kind"] = "SOCKINFO_TCP" 
 828   
 829                  si["tcpsi_state"] = tp.t_state 
 830                  si["tcpsi_flags"] = tp.t_flags 
 831          elif domain == "AF_UNIX": 
 832              unp = self.so_pcb.dereference_as("unpcb") 
 833              si["soi_kind"] = "SOCKINFO_UN" 
 834   
 835              if unp.unp_addr: 
 836                   
 837                   
 838                   
 839                  si["unsi_addr"] = unp.unp_addr.sun_path 
 840   
 841          elif domain == "AF_NDRV": 
 842               
 843               
 844              si["soi_kind"] = "SOCKINFO_NDRV" 
 845          elif domain == "AF_SYSTEM": 
 846               
 847               
 848               
 849               
 850              if protocol == "SYSPROTO_EVENT": 
 851                   
 852                   
 853                  si["soi_kind"] = "SOCKINFO_KERN_EVENT" 
 854              elif protocol == "SYSPROTO_CONTROL": 
 855                  kcb = self.so_pcb.dereference_as("ctl_cb") 
 856                  kctl = kcb.kctl 
 857                  si["soi_kind"] = "SOCKINFO_KERN_CTL" 
 858   
 859                  if kctl: 
 860                      si["kcsi_id"] = kctl.id 
 861                      si["kcsi_name"] = kctl.name 
 862   
 863          return si 
  864   
 878   
 879      @utils.safe_property 
 881          """For IPv[46] sockets, return source IP as string.""" 
 882          return self.get_socketinfo_attr("insi_laddr") 
  883   
 884      @utils.safe_property 
 886          """For IPv[46] sockets, return destination IP as string.""" 
 887          return self.get_socketinfo_attr("insi_faddr") 
  888   
 889      @utils.safe_property 
 891          """The Addressing Family corresponds roughly to OSI layer 3.""" 
 892          return self.so_proto.pr_domain.dom_family 
  893   
 894      @utils.safe_property 
 897   
 898      @utils.safe_property 
 900          """For Unix sockets, pointer to vnode, if any. 
 901   
 902          This is the same way that OS gathers this information in response to 
 903          syscall [1] (this is the API used by netstat, among others). 
 904   
 905          1: 
 906          https://github.com/opensource-apple/xnu/blob/10.9/bsd/kern/uipc_usrreq.c#L1683 
 907          """ 
 908          if self.addressing_family == "AF_UNIX": 
 909              return self.so_pcb.dereference_as("unpcb").unp_vnode 
  910   
 911      @utils.safe_property 
 913          """For Unix sockets, the pcb of the paired socket. [1] 
 914   
 915          You most likely want to do sock.conn_pcb.unp_socket to get at the 
 916          other socket in the pair. However, because the sockets are paired 
 917          through the protocol control block, it's actually useful to have 
 918          a direct pointer at it in order to be able to spot paired sockets. 
 919   
 920          1: 
 921          https://github.com/opensource-apple/xnu/blob/10.9/bsd/sys/unpcb.h#L128 
 922          """ 
 923          if self.addressing_family == "AF_UNIX": 
 924              return self.so_pcb.dereference_as("unpcb").unp_conn 
  925   
 926      @utils.safe_property 
 929   
 930      @utils.safe_property 
 933   
 934      @utils.safe_property 
 936          if self.addressing_family in ["AF_INET", "AF_INET6"]: 
 937               
 938              return str(self.so_proto.pr_protocol).replace("IPPROTO_", "") 
  939   
 940      @utils.safe_property 
 942          if self.addressing_family == "AF_UNIX": 
 943              pr_type = str(self.so_proto.pr_type) 
 944   
 945              if pr_type: 
 946                   
 947                  return pr_type.replace("SOCK_", "") 
 948              else: 
 949                   
 950                   
 951                   
 952                  return "Unix Socket" 
  953   
 954      @utils.safe_property 
 968   
 969      @utils.safe_property 
  987   
 991          addr = obj.NoneObject("Unknown socket family") 
 992   
 993          if self.sa_family == "AF_INET": 
 994              addr = self.cast("sockaddr_in").sin_addr.s_addr 
 995   
 996          elif self.sa_family == "AF_INET6": 
 997              addr = self.cast("sockaddr_in6").sin6_addr.m("__u6_addr") 
 998   
 999          elif self.sa_family == "AF_LINK": 
1000              addr = self.cast("sockaddr_dl") 
1001   
1002          return addr 
 1003   
1004      @utils.safe_property 
1006          result = "" 
1007          addr = self._get_address_obj() 
1008          if addr: 
1009              if self.sa_family in ("AF_INET6", "AF_INET"): 
1010                  result = utils.FormatIPAddress(self.sa_family, addr) 
1011   
1012              elif self.sa_family == "AF_LINK": 
1013                  result = addr 
1014   
1015          return str(result) 
 1016   
1020   
1021 -class vm_map_entry(obj.Struct): 
 1023          """Find the underlying vnode object for the given vm_map_entry. 
1024   
1025          xnu-2422.1.72/osfmk/vm/bsd_vm.c: 1339. 
1026          """ 
1027          if not self.is_sub_map.v(): 
1028               
1029               
1030               
1031               
1032   
1033              shadow = self.last_shadow 
1034              if not shadow: 
1035                  return shadow 
1036   
1037              if (shadow and not shadow.internal.v() and 
1038                      shadow.pager_ready.v() and 
1039                      not shadow.terminating.v() and 
1040                      shadow.alive.v()): 
1041                  memory_object = shadow.pager 
1042                  pager_ops = memory_object.mo_pager_ops 
1043   
1044                   
1045                   
1046                   
1047                   
1048   
1049                  if pager_ops == self.obj_profile.get_constant( 
1050                          "_vnode_pager_ops", is_address=True): 
1051                      return shadow.pager.dereference_as( 
1052                          "vnode_pager").vnode_handle 
1053   
1054          return obj.NoneObject("vnode not found") 
 1055   
1056      @utils.safe_property 
1057 -    def sharing_mode(self): 
 1058          """Returns the sharing mode of the backing vm_object. 
1059   
1060          This is losely adapted from vm_map.c, void vm_map_region_top_walk(), 
1061          except we're not filling page counts for resident/reusable, etc. 
1062          """ 
1063          if not self.vmo_object or self.is_sub_map: 
1064              return "SM_EMPTY"   
1065   
1066          vmobj = self.vmo_object 
1067          ref_count = vmobj.ref_count 
1068          if vmobj.paging_in_progress: 
1069              ref_count -= 1 
1070   
1071          if vmobj.shadow: 
1072              return "SM_COW"   
1073   
1074          if self.superpage_size: 
1075              return "SM_LARGE_PAGE"   
1076   
1077          if self.needs_copy: 
1078              return "SM_COW" 
1079   
1080          if ref_count == 1 or (not vmobj.pager_trusted and not 
1081                                vmobj.internal): 
1082              return "SM_PRIVATE" 
1083   
1084          return "SM_SHARED" 
 1085   
1086      @utils.safe_property 
1087 -    def code_signed(self): 
 1089   
1090      @utils.safe_property 
1091 -    def last_shadow(self): 
 1092          shadow = self.vmo_object 
1093          if not shadow: 
1094              return obj.NoneObject("no vm_object found") 
1095   
1096          while shadow.shadow: 
1097              shadow = shadow.shadow 
1098   
1099          return shadow 
 1100   
1101      @utils.safe_property 
1103          return self.links.start.v() 
 1104   
1105      @utils.safe_property 
1107          return self.links.end.v() 
 1108   
1109      @utils.safe_property 
1110 -    def vmo_object(self): 
 1111          """Return the vm_object instance for this entry. 
1112   
1113          There's an intermediate link called struct vm_map_entry. 
1114   
1115          The members will be called either 'object' and 'vm_object' or 
1116          'vme_object' and 'vmo_object'. 
1117   
1118          There is no easy heuristic for which it will be in a particular kernel 
1119          version* so we just try both, since they mean the same thing. 
1120   
1121          * The kernel version numbers could be identical for kernels built from 
1122          a feature branch and a kernel build from trunk, and the two could be 
1123          months apart. Furthermore, the profiles are generated not from the 
1124          kernel itself but from a debug kit and can end up using out of date 
1125          naming conventions. 
1126          """ 
1127          vme_object = self.multi_m("vme_object", "object") 
1128          return vme_object.multi_m("vmo_object", "vm_object") 
 1130   
1131 -class clist(obj.Struct): 
 1132   
1133      @utils.safe_property 
1135          """Gets the full contents of the ring buffer, which may be freed. 
1136   
1137          This is different from getting the legal contents as with b_to_q [1] 
1138          because clists are only used by TTYs and they seem to always be all 
1139          marked as consumed, so b_to_q wouldn't let us see any content. 
1140   
1141          1: github.com/opensource-apple/xnu/blob/10.9/bsd/kern/tty_subr.c#L358 
1142          """ 
1143          return utils.HexDumpedString( 
1144              self.obj_vm.read(self.c_cs, self.c_cn)) 
 1145   
1146      @utils.safe_property 
1148          return int(self.c_cn) 
  1149   
1150   
1151 -class tty(obj.Struct): 
 1152      @utils.safe_property 
1154          return self.t_session.s_ttyvp 
 1155   
1156      @utils.safe_property 
1159   
1160      @utils.safe_property 
 1163   
1164   
1165 -class proc(obj.Struct): 
 1166      """Represents a Darwin process.""" 
1167   
1168      @utils.safe_property 
1170          return self.task.map.hdr.walk_list("links.next", include_current=False) 
 1171   
1173          """Gets all open files (sockets, pipes...) owned by this proc. 
1174   
1175          Yields: 
1176            tuple of (fd, fileproc, flags) 
1177          """ 
1178           
1179           
1180           
1181           
1182           
1183           
1184           
1185           
1186           
1187           
1188           
1189           
1190           
1191           
1192           
1193           
1194           
1195           
1196          last_fd = self.p_fd.fd_lastfile 
1197          ofiles = self.p_fd.fd_ofiles.deref() 
1198          ofileflags = self.p_fd.fd_ofileflags 
1199   
1200          for fd in xrange(last_fd + 1):   
1201              file_obj = ofiles[fd].deref() 
1202   
1203               
1204               
1205               
1206               
1207               
1208              if file_obj: 
1209                  yield (fd, file_obj, ofileflags[fd]) 
 1210   
1212          cr3 = self.task.map.pmap.pm_cr3 
1213          as_class = self.obj_vm.__class__ 
1214          if self.task.map.pmap.pm_task_map == "TASK_MAP_64BIT_SHARED": 
1215              as_class = amd64.AMD64PagedMemory 
1216   
1217          return as_class(base=self.obj_vm.base, session=self.obj_vm.session, 
1218                          dtb=cr3, name="Pid %s" % self.p_pid) 
 1219   
1220      @utils.safe_property 
1222          return utils.SmartUnicode(self.p_comm) 
 1223   
1224      @utils.safe_property 
1226          return self.task.map.pmap.pm_cr3 
 1227   
1228      @utils.safe_property 
1230          return proc.task.map.pmap.pm_task_map == "TASK_MAP_64BIT" 
 1231   
1232      @utils.safe_property 
1234          result = [] 
1235          array = self.obj_profile.ListArray( 
1236              target="String", 
1237              offset=self.user_stack - self.p_argslen, 
1238              vm=self.get_process_address_space(), 
1239              maximum_size=self.p_argslen, 
1240          ) 
1241   
1242          for item in array: 
1243               
1244               
1245              if len(result) >= self.p_argc: 
1246                  break 
1247   
1248              item = unicode(item) 
1249   
1250               
1251               
1252              if not len(item): 
1253                  continue 
1254   
1255              result.append(item) 
1256   
1257           
1258           
1259          if len(result) > 1 and result[0] == result[1]: 
1260              result.pop(0) 
1261   
1262          return result 
 1263   
1265          """Use heuristics to guess whether this proc is valid.""" 
1266          return (self.p_argc > 0 
1267                  and len(self.p_comm) > 0 
1268                  and self.p_start.v() > 0 
1269                  and 99999 > self.pid > 0) 
  1270   
1271   
1272 -class vnode(obj.Struct): 
 1273      @utils.safe_property 
1275           
1276          result = [] 
1277          _vnode = self 
1278   
1279           
1280          while not (_vnode.v_flag.VROOT and 
1281                     _vnode.v_mount.mnt_flag.MNT_ROOTFS): 
1282              result.append(_vnode.v_name.deref()) 
1283   
1284               
1285              _vnode = _vnode.v_parent or _vnode.v_mount.mnt_vnodecovered 
1286   
1287               
1288               
1289              if not _vnode: 
1290                  self.obj_session.logging.warning("vnode at 0x%x is orphaned.", 
1291                                                   int(_vnode)) 
1292                  return "<Orphan>" 
1293   
1294          path = "/" + "/".join((str(x) for x in reversed(result) if x)) 
1295          return unicode(path.encode("string-escape")) 
 1296           
1297   
1298      @utils.safe_property 
1301   
1302      @utils.safe_property 
1305   
1306      @utils.safe_property 
1308          """If this is an HFS vnode, then v_data is a cnode.""" 
1309          node = self.v_data.dereference_as("cnode") 
1310          if node.c_rwlock != node: 
1311              return obj.NoneObject("This vnode has no valid cnode.") 
1312   
1313          return node 
 1314   
1315      @utils.safe_property 
1317          uid = self.v_cred.cr_posix.cr_ruid 
1318          if uid: 
1319              return uid 
1320   
1321          return obj.NoneObject("Could not retrieve POSIX creds.") 
  1322   
1323   
1324 -class cnode(obj.Struct): 
 1325      @utils.safe_property 
1328   
1329      @utils.safe_property 
1332   
1333      @utils.safe_property 
1336   
1337      @utils.safe_property 
 1340   
1341   
1342 -class zone(obj.Struct): 
 1343      @utils.safe_property 
1346   
1347      @utils.safe_property 
1349          return int(self.count) 
 1350   
1351      @utils.safe_property 
1353          return int(self.m("sum_count") - self.count) 
 1354   
1355      @utils.safe_property 
1356 -    def tracks_pages(self): 
 1357          return bool(self.m("use_page_list")) 
 1358   
1359      @utils.safe_property 
1361          """Find valid offsets in the zone as tuples of (state, offset). 
1362   
1363          Allocation zones keep track of potential places where an element of 
1364          fixed size may be stored. The most basic zones only keep track of free 
1365          pointers, so as to speed up allocation. Some zones also track already 
1366          allocated data, using a separate mechanism. We support both. 
1367   
1368          Returns a set of tuples of: 
1369              - State, which can be "freed", "allocated" or "unknown". 
1370              - Object offset, at which a struct may be located. 
1371                (You will want to validate the struct itself for sanity.) 
1372          """ 
1373           
1374          seen_offsets = set() 
1375   
1376           
1377          seen_pages = set() 
1378   
1379           
1380          for element in self.free_elements.walk_list("next"): 
1381              seen_offsets.add(element.obj_offset) 
1382   
1383           
1384           
1385           
1386           
1387          for offset in seen_offsets.copy(): 
1388               
1389               
1390              page_start = offset & ~0xfff 
1391              if page_start in seen_pages: 
1392                  continue 
1393   
1394              seen_pages.add(page_start) 
1395              seen_offsets.update(set(self._generate_page_offsets(page_start))) 
1396   
1397           
1398           
1399           
1400          page_lists = {"all_free", "all_used", "intermediate"} 
1401   
1402           
1403          if self.m("use_page_list"): 
1404              for page_list in page_lists: 
1405                  for page_start in self.m(page_list).walk_list("next"): 
1406                      if page_start in seen_pages: 
1407                          continue 
1408   
1409                      seen_pages.add(page_start) 
1410                      seen_offsets.update(self._generate_page_offsets(page_start)) 
1411   
1412          return seen_offsets 
 1413   
1414 -    def _generate_page_offsets(self, page_start): 
 1415          limit = page_start + 0x1000 - self.elem_size 
1416           
1417           
1418          limit -= self.obj_profile.get_obj_size("zone_page_metadata") 
1419   
1420          return xrange(page_start, limit, self.elem_size) 
  1421   
1422   
1423 -class ifnet(obj.Struct): 
 1424      @utils.safe_property 
1426          return "%s%d" % (self.if_name.deref(), self.if_unit) 
 1427   
1428      @utils.safe_property 
1430           
1431          for tqe in self.if_addrhead.tqh_first.walk_list( 
1432                  "ifa_link.tqe_next"): 
1433              family = tqe.ifa_addr.sa_family 
1434   
1435               
1436              if family == "AF_LINK": 
1437                  l2_addr = utils.SmartUnicode(tqe.ifa_addr.deref()) 
1438                  yield ("MAC", l2_addr) 
1439                  continue 
1440              elif family == "AF_INET": 
1441                  l3_proto = "IPv4" 
1442              elif family == "AF_INET6": 
1443                  l3_proto = "IPv6" 
1444              else: 
1445                  l3_proto = utils.SmartUnicode(family).replace("AF_", "") 
1446   
1447              l3_addr = utils.SmartUnicode(tqe.ifa_addr.deref()) 
1448              yield (l3_proto, l3_addr) 
 1449   
1450      @utils.safe_property 
1452          for proto, addr in self.addresses: 
1453              if proto == "MAC": 
1454                  return addr 
 1455   
1456      @utils.safe_property 
1458          return [(proto, addr) for proto, addr in self.addresses 
1459                  if proto != "MAC"] 
 1460   
1461      @utils.safe_property 
1463          result = [] 
1464          for proto, addr in self.addresses: 
1465              if proto == "IPv4": 
1466                  result.append(addr) 
1467   
1468          return ", ".join(result) 
 1469   
1470      @utils.safe_property 
1472          result = [] 
1473          for proto, addr in self.addresses: 
1474              if proto == "IPv6": 
1475                  result.append(addr) 
1476   
1477          return ", ".join(result) 
  1478   
1481      @utils.safe_property 
1484   
1485      @utils.safe_property 
1487          return "Session %d (%s)" % (self.s_sid, self.s_leader.command) 
 1488   
1489      @utils.safe_property 
1491          return utils.SmartUnicode(self.s_login) 
 1492   
1493      @utils.safe_property 
 1496   
1499      """The OSDictionary is a general purpose associative array described: 
1500   
1501      xnu-1699.26.8/libkern/libkern/c++/OSDictionary.h 
1502      """ 
1503   
1504 -    def items(self, value_class=None): 
 1505          """Iterate over the associative array and yield key, value pairs.""" 
1506          for entry in self.dictionary: 
1507              key = entry.key.dereference_as("OSString").value 
1508              if value_class: 
1509                  yield key, entry.value.dereference_as(value_class) 
1510              else: 
1511                  yield key, entry.value 
  1512   
1515      """An OSOrderedSet is a list of OSObject instances. 
1516   
1517      xnu-1699.26.8/libkern/libkern/c++/OSOrderedSet.h 
1518      """ 
1519   
 1523   
1524   
1525 -class Darwin32(basic.Profile32Bits, basic.BasicClasses): 
 1526      """A Darwin profile.""" 
1527      METADATA = dict( 
1528          os="darwin", 
1529          arch="I386", 
1530          type="Kernel") 
1531   
1532      @classmethod 
1534          super(Darwin32, cls).Initialize(profile) 
1535   
1536           
1537           
1538           
1539          for k in profile.vtypes.keys(): 
1540              if k.endswith("_class"): 
1541                  stripped_k = k[:-len("_class")] 
1542                  if stripped_k not in profile.vtypes: 
1543                      profile.vtypes[stripped_k] = profile.vtypes[k] 
1544                      if stripped_k in darwin_overlay: 
1545                          darwin_overlay[k] = darwin_overlay[stripped_k] 
1546   
1547          profile.add_classes( 
1548              LIST_ENTRY=LIST_ENTRY, queue_entry=queue_entry, 
1549              sockaddr=sockaddr, sockaddr_dl=sockaddr_dl, 
1550              vm_map_entry=vm_map_entry, proc=proc, vnode=vnode, 
1551              socket=socket, clist=clist, zone=zone, ifnet=ifnet, tty=tty, 
1552               
1553              OSDictionary=OSDictionary, OSDictionary_class=OSDictionary, 
1554              OSOrderedSet=OSOrderedSet, OSOrderedSet_class=OSOrderedSet, 
1555              fileproc=fileproc, session=session, cnode=cnode, 
1556              llinfo_arp=llinfo_arp) 
1557          profile.add_enums(**darwin_enums) 
1558          profile.add_overlay(darwin_overlay) 
1559          profile.add_constants(dict(default_text_encoding="utf8")) 
 1560   
1562          """A variant of get_constant_object which accounts for name mangling.""" 
1563          for key in self.constants: 
1564              if constant in key: 
1565                  return self.get_constant_object(key, **kwargs) 
  1566   
1567   
1568 -class Darwin64(basic.RelativeOffsetMixin, basic.ProfileLP64, Darwin32): 
 1569      """Support for 64 bit darwin systems.""" 
1570      METADATA = dict( 
1571          os="darwin", 
1572          arch="AMD64", 
1573          type="Kernel") 
1574   
1575      image_base = 0 
1576   
1577      @classmethod 
1581   
 1588