Beispiel #1
0
    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)
Beispiel #2
0
    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