def calculate(self): common.set_plugin_members(self) # get the symbols need to check for if rootkit or not (kernel_symbol_addresses, kmods) = common.get_kernel_addrs(self) list_addrs = [ self.addr_space.profile.get_symbol("_ipv4_filters"), self.addr_space.profile.get_symbol("_ipv6_filters") ] for list_addr in list_addrs: plist = obj.Object("ipfilter_list", offset=list_addr, vm=self.addr_space) # type 'ipfilter' cur = plist.tqh_first while cur: filter = cur.ipf_filter name = filter.name.dereference() yield self.check_filter("INPUT", name, filter.ipf_input, kernel_symbol_addresses, kmods) yield self.check_filter("OUTPUT", name, filter.ipf_output, kernel_symbol_addresses, kmods) yield self.check_filter("DETACH", name, filter.ipf_detach, kernel_symbol_addresses, kmods) cur = cur.ipf_link.tqe_next
def calculate(self): common.set_plugin_members(self) (kernel_symbol_addresses, kmods) = common.get_kernel_addrs(self) sysctl_children_addr = self.addr_space.profile.get_symbol( "_sysctl__children") sysctl_list = obj.Object("sysctl_oid_list", offset=sysctl_children_addr, vm=self.addr_space) for (sysctl, name, val) in self._process_sysctl_list(sysctl_list): if val == "INVALID -1": continue is_known = common.is_known_address(sysctl.oid_handler, kernel_symbol_addresses, kmods) if is_known: status = "OK" else: status = "UNKNOWN" yield (sysctl, name, val, is_known, status)
def calculate(self): common.set_plugin_members(self) # get all the members of 'mac_policy_ops' so that we can check them (they are all function ptrs) ops_members = self.get_members() # get the symbols need to check for if rootkit or not (kernel_symbol_addresses, kmods) = common.get_kernel_addrs(self) list_addr = self.addr_space.profile.get_symbol("_mac_policy_list") plist = obj.Object("mac_policy_list", offset = list_addr, vm = self.addr_space) parray = obj.Object('Array', offset = plist.entries, vm = self.addr_space, targetType = 'mac_policy_list_element', count = plist.staticmax + 1) for ent in parray: # I don't know how this can happen, but the kernel makes this check all over the place # the policy isn't useful without any ops so a rootkit can't abuse this if ent.mpc == None: continue name = ent.mpc.mpc_name.dereference() ops = obj.Object("mac_policy_ops", offset = ent.mpc.mpc_ops, vm = self.addr_space) # walk each member of the struct for check in ops_members: ptr = ops.__getattr__(check) if ptr.v() != 0 and ptr.is_valid(): (good, module) = common.is_known_address_name(ptr, kernel_symbol_addresses, kmods) yield (good, check, module, name, ptr)
def calculate(self): common.set_plugin_members(self) (kernel_symbol_addresses, kmods) = common.get_kernel_addrs(self) gnotify_addr = common.get_cpp_sym("gNotifications", self.addr_space.profile) gnotify_ptr = obj.Object("Pointer", offset = gnotify_addr, vm = self.addr_space) gnotifications = gnotify_ptr.dereference_as("OSDictionary") ents = obj.Object('Array', offset = gnotifications.dictionary, vm = self.addr_space, targetType = 'dictEntry', count = gnotifications.count) # walk the current set of notifications for ent in ents: if ent == None: continue key = ent.key.dereference_as("OSString") # get the value valset = ent.value.dereference_as("OSOrderedSet") notifiers_ptrs = obj.Object('Array', offset = valset.array, vm = self.addr_space, targetType = 'Pointer', count = valset.count) for ptr in notifiers_ptrs: notifier = ptr.dereference_as("_IOServiceNotifier") if notifier == None: continue matches = self.get_matching(notifier) # this is the function that handles whatever the notification is for # this should be only in the kernel or in one of the known IOKit drivers for the specific kernel handler = notifier.handler good = common.is_known_address(handler, kernel_symbol_addresses, kmods) yield (good, key, notifier, matches)
def calculate(self): common.set_plugin_members(self) (kernel_symbol_addresses, kmods) = common.get_kernel_addrs(self) gnotify_addr = common.get_cpp_sym("gNotifications", self.addr_space.profile) p = obj.Object("Pointer", offset=gnotify_addr, vm=self.addr_space) gnotifications = p.dereference_as( self._struct_or_class("OSDictionary")) ents = obj.Object('Array', offset=gnotifications.dictionary, vm=self.addr_space, targetType=self._struct_or_class("dictEntry"), count=gnotifications.count) # walk the current set of notifications for ent in ents: if ent == None or not ent.is_valid(): continue key = str(ent.key.dereference_as( self._struct_or_class("OSString"))) # get the value valset = ent.value.dereference_as( self._struct_or_class("OSOrderedSet")) notifiers_ptrs = obj.Object('Array', offset=valset.array, vm=self.addr_space, targetType='Pointer', count=valset.count) for ptr in notifiers_ptrs: notifier = ptr.dereference_as( self._struct_or_class("_IOServiceNotifier")) if notifier == None: continue matches = self.get_matching(notifier) # this is the function that handles whatever the notification is for # this should be only in the kernel or in one of the known IOKit # drivers for the specific kernel handler = notifier.handler.v() ch = notifier.compatHandler.v() if ch: handler = ch (good, module) = common.is_known_address_name( handler, kernel_symbol_addresses, kmods) yield (good, module, key, notifier, matches, handler)
def calculate(self): common.set_plugin_members(self) # get the symbols need to check for if rootkit or not (kernel_symbol_addresses, kmods) = common.get_kernel_addrs(self) members = [ "sf_unregistered", "sf_attach", "sf_detach", "sf_notify", "sf_getpeername", "sf_getsockname", ] members = members + [ "sf_data_in", "sf_data_out", "sf_connect_in", "sf_connect_out", "sf_bind", "sf_setoption", ] members = members + ["sf_getoption", "sf_listen", "sf_ioctl"] sock_filter_head_addr = self.addr_space.profile.get_symbol( "_sock_filter_head") sock_filter_list = obj.Object( "socket_filter_list", offset=sock_filter_head_addr, vm=self.addr_space, ) cur = sock_filter_list.tqh_first while cur: filter = cur.sf_filter filter_name = self.addr_space.read(filter.sf_name, 256) idx = filter_name.index("\x00") if idx != -1: filter_name = filter_name[:idx] filter_socket = cur.sf_entry_head.sfe_socket.obj_offset for member in members: ptr = filter.m(member) if not ptr: continue (good, module) = common.is_known_address_name( ptr.v(), kernel_symbol_addresses, kmods) yield good, filter, filter_name, filter_socket, member, ptr, module cur = cur.sf_global_next.tqe_next
def calculate(self): common.set_plugin_members(self) (kernel_symbol_addresses, kmods) = common.get_kernel_addrs(self) sysctl_children_addr = self.get_profile_symbol("_sysctl__children") sysctl_list = obj.Object("sysctl_oid_list", offset = sysctl_children_addr, vm = self.addr_space) for (sysctl, name, val) in self._process_sysctl_list(sysctl_list): is_known = common.is_known_address(sysctl.oid_handler, kernel_symbol_addresses, kmods) yield (sysctl, name, val, is_known)
def calculate(self): common.set_plugin_members(self) (kernel_symbol_addresses, kmods) = common.get_kernel_addrs(self) sysctl_children_addr = self.get_profile_symbol("_sysctl__children") sysctl_list = obj.Object("sysctl_oid_list", offset=sysctl_children_addr, vm=self.addr_space) for (sysctl, name, val) in self._process_sysctl_list(sysctl_list): is_known = common.is_known_address(sysctl.oid_handler, kernel_symbol_addresses, kmods) yield (sysctl, name, val, is_known)
def calculate(self): common.set_plugin_members(self) (kernel_symbol_addresses, kmods) = common.get_kernel_addrs(self) sysctl_children_addr = self.addr_space.profile.get_symbol("_sysctl__children") sysctl_list = obj.Object("sysctl_oid_list", offset=sysctl_children_addr, vm=self.addr_space) for (sysctl, name, val) in self._process_sysctl_list(sysctl_list): if val == "INVALID -1": continue is_known = common.is_known_address(sysctl.oid_handler, kernel_symbol_addresses, kmods) if is_known: status = "OK" else: status = "UNKNOWN" yield (sysctl, name, val, is_known, status)
def calculate(self): common.set_plugin_members(self) # get the symbols need to check for if rootkit or not (kernel_symbol_addresses, kmods) = common.get_kernel_addrs(self) list_addrs = [self.addr_space.profile.get_symbol("_ipv4_filters"), self.addr_space.profile.get_symbol("_ipv6_filters")] for list_addr in list_addrs: plist = obj.Object("ipfilter_list", offset = list_addr, vm = self.addr_space) # type 'ipfilter' cur = plist.tqh_first while cur: filter = cur.ipf_filter name = filter.name.dereference() yield self.check_filter("INPUT", name, filter.ipf_input, kernel_symbol_addresses, kmods) yield self.check_filter("OUTPUT", name, filter.ipf_output, kernel_symbol_addresses, kmods) yield self.check_filter("DETACH", name, filter.ipf_detach, kernel_symbol_addresses, kmods) cur = cur.ipf_link.tqe_next
def calculate(self): common.set_plugin_members(self) # get the symbols need to check for if rootkit or not (kernel_symbol_addresses, kmods) = common.get_kernel_addrs(self) members = ["sf_unregistered", "sf_attach", "sf_detach", "sf_notify", "sf_getpeername", "sf_getsockname"] members = members + ["sf_data_in", "sf_data_out", "sf_connect_in", "sf_connect_out", "sf_bind", "sf_setoption"] members = members + ["sf_getoption", "sf_listen", "sf_ioctl"] sock_filter_head_addr = self.addr_space.profile.get_symbol("_sock_filter_head") sock_filter_list = obj.Object("socket_filter_list", offset = sock_filter_head_addr, vm = self.addr_space) cur = sock_filter_list.tqh_first while cur: filter = cur.sf_filter filter_name = self.addr_space.read(filter.sf_name, 256) idx = filter_name.index("\x00") if idx != -1: filter_name = filter_name[:idx] filter_socket = cur.sf_entry_head.sfe_socket.obj_offset for member in members: ptr = filter.m(member) if not ptr: continue (good, module) = common.is_known_address_name(ptr.v(), kernel_symbol_addresses, kmods) yield good, filter, filter_name, filter_socket, member, ptr, module cur = cur.sf_global_next.tqe_next