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.get_profile_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.maxindex + 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 is 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 != 0: # make the last parameter 1 to see the names of known modules that load policies good = common.is_known_address(ptr, kernel_symbol_addresses, kmods, 0) yield (good, check, name, ptr)
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) (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 check_filter(self, context, fname, ptr, kernel_symbol_addresses, kmods): if ptr == None: return # change the last paramter to 1 to get messages about which good modules hooks were found in good = common.is_known_address(ptr, kernel_symbol_addresses, kmods) return (good, context, fname, ptr)
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) 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: 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 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) 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) # 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.get_profile_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.maxindex + 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 is 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 != 0: # make the last parameter 1 to see the names of known modules that load policies good = common.is_known_address(ptr, kernel_symbol_addresses, kmods, 0) yield (good, check, name, ptr)
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)