def __unicode__(self): result = "" addr = self._get_address_obj() if addr: if self.sa_family in ("AF_INET6", "AF_INET"): result = utils.FormatIPAddress(self.sa_family, addr) elif self.sa_family == "AF_LINK": result = addr return str(result)
def fill_socketinfo(self): """Computes information about sockets of some addressing families. This function is directly adapted from the kernel function fill_socketinfo [1]. The original function is used to fill a struct with addressing and other useful information about sockets of a few key addressing families. All families are supported, but only the following will return useful information: - AF_INET (IPv4) - AF_INET6 (IPv6) - AF_UNIX (Unix socket) - AF_NDRV (Network driver raw access) - AF_SYSTEM (Darwin-specific; see documentation [3]) Differences between the kernel function and this adaptation: - The kernel uses Protocol Families (prefixed with PF_). Rekall relies on Addressing Families (AF_) which are exactly the same. - The kernel fills a struct; this function returns a dict with the same members. - The kernel returns the data raw. This function converts endianness and unions to human-readable representations, as appropriate. - Only a subset of members are filled in. - Other differences as documented in code. Returns: A dict with the same members as struct socket_info and related. Only member that's always filled is "soi_kind". That's not Spanish, but one of the values in this anonymous enum [2], which determines what other members are present. (Read the code.) [1] https://github.com/opensource-apple/xnu/blob/10.9/bsd/kern/socket_info.c#L98 [2] https://github.com/opensource-apple/xnu/blob/10.9/bsd/sys/proc_info.h#L503 [3] "KEXT Controls and Notifications" https://developer.apple.com/library/mac/documentation/Darwin/Conceptual/NKEConceptual/control/control.html """ domain = self.so_proto.pr_domain.dom_family type = self.so_proto.pr_type protocol = self.so_proto.pr_protocol si = {"soi_kind": "SOCKINFO_GENERIC"} # The kind of socket is determined by the triplet # {domain, type, protocol} if domain in ["AF_INET", "AF_INET6"]: si["soi_kind"] = "SOCKINFO_IN" inp = self.so_pcb.dereference_as("inpcb") si["insi_fport"] = utils.ntoh(inp.inp_fport) si["insi_lport"] = utils.ntoh(inp.inp_lport) si["insi_ip_ttl"] = inp.inp_ip_ttl.v() # Different from kernel: insi_[df]addr is a union, and by setting # the IPv6 address, you set the IPv4 address too. We instead return # a string with the appropriately formatted address. if domain == "AF_INET": si["insi_faddr"] = utils.FormatIPAddress( "AF_INET", inp.inp_dependfaddr.inp46_foreign.ia46_addr4.s_addr ) si["insi_laddr"] = utils.FormatIPAddress( "AF_INET", inp.inp_dependladdr.inp46_local.ia46_addr4.s_addr ) else: si["insi_faddr"] = utils.FormatIPAddress( "AF_INET6", inp.inp_dependfaddr.inp6_foreign.m("__u6_addr") ) si["insi_laddr"] = utils.FormatIPAddress( "AF_INET6", inp.inp_dependladdr.inp6_local.m("__u6_addr") ) if (type == "SOCK_STREAM" and (protocol == 0 or protocol == "IPPROTO_TCP") and inp.inp_ppcb != None): tp = inp.inp_ppcb.dereference_as("tcpcb") si["soi_kind"] = "SOCKINFO_TCP" si["tcpsi_state"] = tp.t_state si["tcpsi_flags"] = tp.t_flags elif domain == "AF_UNIX": unp = self.so_pcb.dereference_as("unpcb") si["soi_kind"] = "SOCKINFO_UN" if unp.unp_addr: # Difference from kernel: instead of copying the whole unp_addr # struct, we just get delegate getting the actual string to the # unp_addr struct. (Because it's trickier than it looks.) si["unsi_addr"] = unp.unp_addr.sun_path elif domain == "AF_NDRV": # This is how we get the pcb if we need to: # ndrv_cb = self.so_pcb.dereference_as("ndrv_cb") si["soi_kind"] = "SOCKINFO_NDRV" elif domain == "AF_SYSTEM": # AF_SYSTEM domain needs more research. It looks like it's used to # communicate between user space and kernel extensions, and allows # the former to control the latter. Naively, this looks ripe for # rootkits to me. if protocol == "SYSPROTO_EVENT": # This is how we get the pcb if we need to: # ev_pcb = self.so_pcb.dereference_as("kern_event_pcb") si["soi_kind"] = "SOCKINFO_KERN_EVENT" elif protocol == "SYSPROTO_CONTROL": kcb = self.so_pcb.dereference_as("ctl_cb") kctl = kcb.kctl si["soi_kind"] = "SOCKINFO_KERN_CTL" if kctl: si["kcsi_id"] = kctl.id si["kcsi_name"] = kctl.name return si