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, module_name) = common.is_known_address_name( sysctl.oid_handler.v(), kernel_symbol_addresses, kmods) if is_known: status = "OK" else: status = "UNKNOWN" yield (sysctl, name, val, is_known, module_name, 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 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_name(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) 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) 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) (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, module_name) = common.is_known_address_name(sysctl.oid_handler.v(), kernel_symbol_addresses, kmods) if is_known: status = "OK" else: status = "UNKNOWN" yield (sysctl, name, val, is_known, module_name, 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) 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