def collect(self, hint, sessions): for entity in sessions: session = entity["MemoryObject/base_object"] # Have to sanitize the usernames to prevent issues when comparing # them later. username = str(session.s_login).replace("\x00", "") if username: user_identity = self.manager.identify( {"User/username": username}) yield [user_identity, definitions.User(username=username)] else: user_identity = None sid = session.s_sid session_identity = self.manager.identify({"Session/sid": sid }) | entity.identity if session.s_ttyp: yield definitions.MemoryObject(base_object=session.s_ttyp, type="tty") yield definitions.MemoryObject( base_object=session.s_leader.deref(), type="proc") yield [ session_identity, definitions.Session(user=user_identity, sid=sid), definitions.Named(name="SID %d" % int(sid), kind="Session") ]
def collect(self, hint, vnodes): manager = self.manager for entity in vnodes: vnode = entity["MemoryObject/base_object"] path = vnode.full_path components = [ entity.identity, definitions.File(path=path), definitions.Named(name=path, kind="File") ] # Parse HFS-specific metadata. We could look at the mountpoint and # see if the filesystem is actually HFS, but it turns out that # cnodes are also used for stuff like the dev filesystem, so let's # just try and see if there's one that looks valid and go with it. cnode = vnode.v_data.dereference_as("cnode") if cnode.c_rwlock == cnode: cattr = vnode.v_data.dereference_as("cnode").c_attr # HFS+ stores timestamps as UTC. components.append( definitions.Timestamps( created_at=cattr.ca_ctime.as_datetime(), modified_at=cattr.ca_mtime.as_datetime(), accessed_at=cattr.ca_atime.as_datetime(), backup_at=cattr.ca_btime.as_datetime())) posix_uid = vnode.v_cred.cr_posix.cr_ruid if posix_uid and posix_uid != 0: components.append( definitions.Permissions( owner=manager.identify({"User/uid": posix_uid}))) yield components
def collect(self, hint, sessions): for entity in sessions: session = entity["Struct/base"] # Have to sanitize the usernames to prevent issues when comparing # them later. username = str(session.s_login).replace("\x00", "") if username: user_identity = self.manager.identify( {"User/username": username}) yield [user_identity, definitions.User(username=username)] else: user_identity = None sid = session.s_sid # Turns out, SID is not always unique. This is disabled as it is # not being currently used, and I need to investigate the causes # of duplicate sessions occurring on 10.10. # session_identity = self.manager.identify({ # "Session/sid": sid}) | entity.identity session_identity = entity.identity if session.s_ttyp: yield definitions.Struct(base=session.s_ttyp, type="tty") if session.s_leader: yield definitions.Struct(base=session.s_leader.deref(), type="proc") yield [ session_identity, definitions.Session(user=user_identity, sid=sid), definitions.Named(name="SID %d" % int(sid), kind="Session") ]
def collect(self, hint, endpoints): for entity in endpoints: struct = entity["Struct/base"] af_inet = struct.InetAF.dereference( vm=self.session.kernel_address_space) if af_inet.AddressFamily == AF_INET: family = "INET" elif af_inet.AddressFamily == AF_INET6: family = "INET6" else: continue l4_port = struct.Port for ver, laddr, _ in struct.dual_stack_sockets( vm=self.session.kernel_address_space): l3_protocol = "IP%s" % ver epoint_id = self.manager.identify({ ("OSILayer3/address", "OSILayer4/port", "OSILayer4/protocol"): (laddr, l4_port, "UDP") }) yield [ epoint_id, definitions.Named(kind="UDP Endpoint", name="%s:%s (%s)" % (laddr, l4_port, "UDP")), definitions.OSILayer3(address=laddr, protocol=l3_protocol), definitions.OSILayer4(port=l4_port, protocol="UDP"), definitions.Endpoint(addressing_family=family, local=True) ]
def collect(self, hint): for i in range(self.session.GetParameter("generate_ballast")): yield [ definitions.Named(name="Ballast entry #%d" % i, kind="Ballast"), definitions.Timestamps( created_at=datetime.datetime.fromtimestamp(0)) ]
def collect(self, users, hint): for user in users: username = user["User/username"] uid = user["User/uid"] if not (username and uid): continue name = "%s (uid=%d)" % (username, uid) yield [user.identity, definitions.Named(kind="User", name=name)]
def collect(self, hint): for head_const in ["_unp_dhead", "_unp_shead"]: lhead = self.session.get_constant_object(head_const, target="unp_head") for unp in lhead.lh_first.walk_list("unp_link.le_next"): yield [ definitions.Struct(base=unp.unp_socket, type="socket"), definitions.Named(kind="Unix Socket") ]
def collect(self, hint, procs): manager = self.manager for entity in procs: proc = entity["MemoryObject/base_object"] user_identity = manager.identify({"User/uid": proc.p_uid}) process_identity = manager.identify({ ("Process/pid", "Timestamps/created_at"): (proc.pid, proc.p_start.as_datetime()) }) # kern_proc.c:2706 session = proc.p_pgrp.pg_session if session: session_identity = manager.identify( {"MemoryObject/base_object": session}) yield definitions.MemoryObject(base_object=session, type="session") else: session_identity = None cr3 = proc.task.map.pmap.pm_cr3 if cr3: cr3_ptr = proc.obj_profile.Pointer( vm=self.session.physical_address_space, target="void", value=proc.task.map.pmap.pm_cr3) else: cr3_ptr = None yield [ # Reuse the base object identity but also use the PID. process_identity | entity.identity, definitions.Timestamps(created_at=proc.p_start.as_datetime()), definitions.Process(pid=proc.pid, command=utils.SmartUnicode(proc.p_comm), user=user_identity, cr3=cr3_ptr, is_64bit=proc.task.map.pmap.pm_task_map == "TASK_MAP_64BIT", session=session_identity), definitions.Named(name="%s (pid=%d)" % (proc.p_comm, proc.pid), kind="Process") ] # We don't know much about the user at this stage, but this # is still kind of useful in getting at least a list of UIDs. # Once we have more robustness in listing users this can go away. yield [user_identity, definitions.User(uid=proc.p_uid)]
def collect(self, hint, procs): for entity in procs: eproc = entity["MemoryObject/base_object"] yield [ entity.identity | self.manager.identify({"Process/pid": eproc.pid}), definitions.Process(pid=eproc.pid, parent=self.manager.identify({ "Process/pid": eproc.InheritedFromUniqueProcessId }), command=eproc.name, is_64bit=eproc.IsWow64), definitions.Timestamps(created_at=eproc.CreateTime, destroyed_at=eproc.ExitTime), definitions.Named(name=eproc.name, kind="Process") ]
def collect(self, hint, sockets): for socket in sockets: base_socket = socket["Struct/base"] family = str(base_socket.addressing_family).replace("AF_", "") if family in ("INET", "INET6"): l3_protocol = "IPv4" if family == "INET" else "IPv6" source_identity, source = self.prebuild( components=[ definitions.OSILayer3(address=base_socket.src_addr, protocol=l3_protocol), definitions.OSILayer4(port=base_socket.src_port, protocol=base_socket.l4_protocol, state=base_socket.tcp_state) ], keys=("OSILayer3/address", "OSILayer4/port", "OSILayer4/protocol")) destination_identity, destination = self.prebuild( components=[ definitions.OSILayer3(address=base_socket.dst_addr, protocol=l3_protocol), definitions.OSILayer4(port=base_socket.dst_port, protocol=base_socket.l4_protocol) ], keys=("OSILayer3/address", "OSILayer4/port", "OSILayer4/protocol")) connection = [ socket.identity, definitions.Named(name=base_socket.human_name, kind="IP Connection"), definitions.Connection(protocol_family=family, source=source_identity, destination=destination_identity) ] yield source yield destination yield connection elif family == "UNIX": if base_socket.vnode: path = base_socket.vnode.full_path file_identity = self.session.entities.identify( {"File/path": path}) else: path = None file_identity = None yield [ socket.identity, definitions.Named(name=base_socket.human_name, kind="Unix Socket"), definitions.Connection(protocol_family="UNIX"), definitions.Socket( type=base_socket.unix_type, file=file_identity, address="0x%x" % int(base_socket.so_pcb), connected="0x%x" % int(base_socket.unp_conn)) ] # There may be a vnode here - if so, yield it. if path: yield [ definitions.File(path=path, type="socket"), definitions.Named(name=path, kind="Socket"), definitions.Struct(base=base_socket.vnode.deref(), type="vnode") ] else: yield [ socket.identity, definitions.Named(kind="Unknown Socket"), definitions.Connection(protocol_family=family) ]
def collect(self, hint, procs): # We're going to have a much better time if we can ignore processes # that aren't relevant. hint_filter = hint.run_engine("hinter", selector="MemoryDescriptor/process") for proc in procs: if (hint_filter and not hint_filter.run_engine("matcher", bindings=proc)): continue vm = proc["Struct/base"].get_process_address_space() arch = "x86_32" if vm.end() <= 0x1000000000 else "x86_64" vm_identity, vm_entity = self.prebuild(components=[ definitions.AddressSpace(dtb=vm.dtb, type="virtual", architecture=arch, owner=proc.identity), definitions.Named(kind="Virtual Address Space", name="DTB @%#016x" % vm.dtb) ], keys=("AddressSpace/dtb", )) yield vm_entity for address in proc["Struct/base"].task.map.hdr.walk_list( "links.next", include_current=False): # Is this range backed by a vnode? If so yield it, and save the # identity. This should take care of __TEXT, __LINKEDIT and # memory mapped sections. vnode = address.find_vnode_object() file_identity = None if vnode: file_identity, file = self.prebuild(components=[ definitions.Struct(base=vnode, type="vnode") ], keys=("Struct/base", )) yield file # Sort out shared memory flags. sharing_mode = address.sharing_mode if sharing_mode in ("SM_SHARED", "SM_LARGE_PAGE"): sharing_enum = "shared" elif sharing_mode == "SM_COW": sharing_enum = "copy-on-write" elif sharing_mode == "SM_PRIVATE": sharing_enum = "private" elif sharing_mode == "SM_EMPTY": sharing_mode = None else: raise ValueError("Unknown sharing mode %r." % sharing_mode) # Sort out permission bits. perms = [] max_perms = [] for flag in address.protection: perm = self.PROTECTION_FLAGS.get(flag) if not perm: raise ValueError("Unknown protection flag %r." % flag) perms.append(perm) for flag in address.max_protection: perm = self.PROTECTION_FLAGS.get(flag) if not perm: raise ValueError("Unknown protection flag %r." % flag) max_perms.append(perm) _, result = self.prebuild( components=[ definitions.MemoryDescriptor( start=obj.Void(vm=vm, profile=self.session.profile, offset=address.links.start.v()), end=obj.Void(vm=vm, profile=self.session.profile, offset=address.links.end.v()), address_space=vm_identity, permissions=perms, max_permissions=max_perms, file=file_identity, shared=sharing_enum, code_signed=address.code_signed), definitions.Struct(base=address, type="vm_map_entry") ], keys=("MemoryDescriptor/address_space", "MemoryDescriptor/start", "MemoryDescriptor/end")) yield result