def calculate(self): linux_common.set_plugin_members(self) hook_names = ["PRE_ROUTING", "LOCAL_IN", "FORWARD", "LOCAL_OUT", "POST_ROUTING"] proto_names = ["", "", "IPV4", "", "", "", "", "", "", "", "" , "", "", ""] # struct list_head nf_hooks[NFPROTO_NUMPROTO][NF_MAX_HOOKS] # NFPROTO_NUMPROTO = 12 # NF_MAX_HOOKS = 7 nf_hooks_addr = self.addr_space.profile.get_symbol("nf_hooks") if nf_hooks_addr == None: debug.error("Unable to analyze NetFilter. It is either disabled or compiled as a module.") modules = linux_lsmod.linux_lsmod(self._config).get_modules() list_head_size = self.addr_space.profile.get_obj_size("list_head") for outer in range(13): arr = nf_hooks_addr + (outer * (list_head_size * 8)) for inner in range(7): list_head = obj.Object("list_head", offset = arr + (inner * list_head_size), vm = self.addr_space) for hook_ops in list_head.list_of_type("nf_hook_ops", "list"): if self.is_known_address(hook_ops.hook.v(), modules): hooked = "False" else: hooked = "True" yield proto_names[outer], hook_names[inner], hook_ops.hook.v(), hooked
def calculate(self): linux_common.set_plugin_members(self) modules = linux_lsmod.linux_lsmod(self._config).get_modules() op_members = self.profile.types['file_operations'].keywords["members"].keys() seq_members = self.profile.types['seq_operations'].keywords["members"].keys() tcp = ("tcp_seq_afinfo", ["tcp6_seq_afinfo", "tcp4_seq_afinfo"]) udp = ("udp_seq_afinfo", ["udplite6_seq_afinfo", "udp6_seq_afinfo", "udplite4_seq_afinfo", "udp4_seq_afinfo"]) protocols = [tcp, udp] for proto in protocols: struct_type = proto[0] for global_var_name in proto[1]: global_var_addr = self.addr_space.profile.get_symbol(global_var_name) if not global_var_addr: continue global_var = obj.Object(struct_type, offset = global_var_addr, vm = self.addr_space) for (name, member, address) in self.check_afinfo(global_var_name, global_var, op_members, seq_members, modules): yield (name, member, address)
def calculate(self): linux_common.set_plugin_members(self) modules = linux_lsmod.linux_lsmod(self._config).get_modules() f_op_members = self.profile.types['file_operations'].keywords[ "members"].keys() f_op_members.remove('owner') if self._config.INODE: inode = obj.Object("inode", offset=self._config.INODE, vm=self.addr_space) if not inode.is_valid(): debug.error( "Invalid inode address given. Please use linux_find_file to determine valid inode addresses." ) for (hooked_member, hook_address) in self.verify_ops(inode.i_fop, f_op_members, modules): yield ("inode at {0:x}".format(inode.obj_offset), hooked_member, hook_address) else: funcs = [ self.check_open_files_fop, self.check_proc_fop, self.check_proc_root_fops ] for func in funcs: for (name, member, address) in func(f_op_members, modules): yield (name, member, address)
def calculate(self): linux_common.set_plugin_members(self) modules = linux_lsmod.linux_lsmod(self._config).get_modules() f_op_members = self.profile.types["file_operations"].keywords["members"].keys() f_op_members.remove("owner") if self._config.INODE: inode = obj.Object("inode", offset=self._config.INODE, vm=self.addr_space) if not inode.is_valid(): debug.error( "Invalid inode address given. Please use linux_find_file to determine valid inode addresses." ) for (hooked_member, hook_address) in self.verify_ops(inode.i_fop, f_op_members, modules): yield ("inode at {0:x}".format(inode.obj_offset), hooked_member, hook_address) else: funcs = [self.check_open_files_fop, self.check_proc_fop, self.check_proc_root_fops, self.check_file_cache] for func in funcs: for (name, member, address) in func(f_op_members, modules): yield (name, member, address)
def walk_modules_address_space(self, addr_space): list_mods = [x[0].obj_offset for x in linux_lsmod.linux_lsmod(self._config).calculate()] min_addr_sym = obj.Object("unsigned long", offset = addr_space.profile.get_symbol("module_addr_min"), vm = addr_space) max_addr_sym = obj.Object("unsigned long", offset = addr_space.profile.get_symbol("module_addr_max"), vm = addr_space) min_addr = min_addr_sym & ~0xfff max_addr = (max_addr_sym & ~0xfff) + 0x1000 scan_buf = "" llen = max_addr - min_addr allfs = "\xff" * 4096 memory_model = self.addr_space.profile.metadata.get('memory_model', '32bit') if memory_model == '32bit': minus_size = 4 else: minus_size = 8 check_bufs = [] replace_bufs = [] check_nums = [3000, 2800, 2700, 2500, 2300, 2100, 2000, 1500, 1300, 1200, 1024, 512, 256, 128, 96, 64, 48, 32, 24, 16, 12, 9] if minus_size == 4: check_nums = check_nums + [8, 6, 5] for num in check_nums: check_bufs.append("\x00" * num) replace_bufs.append(("\xff" * (num-minus_size)) + "\x00" * minus_size) for page in range(min_addr, max_addr, 4096): to_append = allfs tmp = addr_space.read(page, 4096) if tmp: non_zero = False for t in tmp: if t != "\x00": non_zero = True break if non_zero: for i in range(len(check_nums)): tmp = tmp.replace(check_bufs[i], replace_bufs[i]) to_append = tmp scan_buf = scan_buf + to_append for cur_addr in re.finditer("(?=(\x00\x00\x00\x00|\x01\x00\x00\x00|\x02\x00\x00\x00))", scan_buf): mod_addr = min_addr + cur_addr.start() if mod_addr in list_mods: continue m = obj.Object("module", offset = mod_addr, vm = addr_space) if m.is_valid(): yield m
def get_syscalls(self, index_info=None, get_hidden=False, compute_name=True): linux_common.set_plugin_members(self) if get_hidden: hidden_mods = list( linux_hidden_modules.linux_hidden_modules( self._config).calculate()) else: hidden_mods = [] if compute_name: visible_mods = linux_lsmod.linux_lsmod(self._config).calculate() else: visible_mods = [] if index_info == None: index_info = self._find_and_parse_index_file() table_name = self.addr_space.profile.metadata.get( 'memory_model', '32bit') sym_addrs = self.profile.get_all_addresses() sys_call_info = self._get_table_info("sys_call_table") addrs = [(table_name, sys_call_info)] # 64 bit systems with 32 bit emulation ia32 = self.addr_space.profile.get_symbol("ia32_sys_call_table") if ia32: ia32_info = self._get_table_info("ia32_sys_call_table") addrs.append(("32bit", ia32_info)) for (table_name, (tableaddr, tblsz)) in addrs: table = obj.Object(theType='Array', offset=tableaddr, vm=self.addr_space, targetType='unsigned long', count=tblsz + 1) for (i, call_addr) in enumerate(table): if not call_addr: continue idx_name = self._index_name(table_name, index_info, i) call_addr = int(call_addr) if not call_addr in sym_addrs: hooked = 1 sym_name = self._compute_hook_sym_name( visible_mods, hidden_mods, call_addr) else: hooked = 0 sym_name = self.profile.get_symbol_by_address( "kernel", call_addr) yield (tableaddr, table_name, i, idx_name, call_addr, sym_name, hooked)
def calculate(self): linux_common.set_plugin_members(self) kset_modules = self.get_kset_modules() lsmod_modules = set([str(module.name) for (module, params, sects) in linux_lsmod.linux_lsmod(self._config).calculate()]) for mod_name in set(kset_modules.keys()).difference(lsmod_modules): yield kset_modules[mod_name]
def listModulesLinux(): modules = set([ module for (module, params, sects) in linux_lsmod.linux_lsmod(config).calculate() ]) for mod in modules: #print (list(mod.obj_vm.get_available_pages()))[-1] print mod.name, hex(mod.module_core), hex(mod.module_core + mod.core_size)
def calculate(self): linux_common.set_plugin_members(self) if not has_distorm3: debug.error("This plugin cannot operate without distrom installed.") modules = linux_lsmod.linux_lsmod(self._config).get_modules() funcs = [self._check_known_functions, self._check_file_op_pointers, self._check_afinfo, self._check_inetsw] for func in funcs: for (sym_name, member, hook_type, sym_addr) in func(modules): yield (sym_name, member, hook_type, sym_addr)
def get_modules(cls, addr_space): """Enumerate the kernel modules. :param addr_space | <addrspace.AbstractVirtualAddressSpace> :returns <tuple> """ mask = addr_space.address_mask config = addr_space.get_config() modules = linux_lsmod.linux_lsmod(config).calculate() mods = dict((mask(mod[0].module_core), mod[0]) for mod in modules) mod_addrs = sorted(mods.keys()) return (mods, mod_addrs)
def calculate(self): linux_common.set_plugin_members(self) modules = linux_lsmod.linux_lsmod(self._config).get_modules() seq_members = self.profile.types['seq_operations'].keywords[ "members"].keys() if self.addr_space.profile.obj_has_member("tcp_seq_afinfo", "seq_fops"): func = self._pre_4_18 else: func = self._4_18_plus for name, member, address in func(modules, seq_members): yield name, member, address
def walk_modules_address_space(self, addr_space): mods = [ x[0].obj_offset for x in linux_lsmod.linux_lsmod(self._config).calculate() ] min_addr = obj.Object( "unsigned long", offset=addr_space.profile.get_symbol("module_addr_min"), vm=addr_space) max_addr = obj.Object( "unsigned long", offset=addr_space.profile.get_symbol("module_addr_max"), vm=addr_space) for cur_addr in range(min_addr, max_addr, 8): m = obj.Object("module", offset=cur_addr, vm=addr_space) if m.state.v() not in [0, 1, 2]: continue if m.core_size < 4096 or m.core_size > 1000000: continue if m.core_text_size < 4096 or m.core_text_size > 1000000: continue s = self.addr_space.read(m.name.obj_offset, 64) if not s: continue idx = s.find("\x00") if idx < 1: continue name = s[:idx] for n in name: if not (32 < ord(n) < 127): continue if not m.module_core.is_valid(): continue if m.obj_offset not in mods: yield m
def get_syscalls(self, index_info = None, get_hidden = False, compute_name = True): linux_common.set_plugin_members(self) if get_hidden: hidden_mods = list(linux_hidden_modules.linux_hidden_modules(self._config).calculate()) else: hidden_mods = [] if compute_name: visible_mods = linux_lsmod.linux_lsmod(self._config).calculate() else: visible_mods = [] if index_info == None: index_info = self._find_and_parse_index_file() table_name = self.addr_space.profile.metadata.get('memory_model', '32bit') sym_addrs = self.profile.get_all_addresses() sys_call_info = self._get_table_info("sys_call_table") addrs = [(table_name, sys_call_info)] # 64 bit systems with 32 bit emulation ia32 = self.addr_space.profile.get_symbol("ia32_sys_call_table") if ia32: ia32_info = self._get_table_info("ia32_sys_call_table") addrs.append(("32bit", ia32_info)) for (table_name, (tableaddr, tblsz)) in addrs: table = obj.Object(theType = 'Array', offset = tableaddr, vm = self.addr_space, targetType = 'unsigned long', count = tblsz) for (i, call_addr) in enumerate(table): if not call_addr: continue idx_name = self._index_name(table_name, index_info, i) call_addr = int(call_addr) if not call_addr in sym_addrs: hooked = 1 sym_name = self._compute_hook_sym_name(visible_mods, hidden_mods, call_addr) else: hooked = 0 sym_name = self.profile.get_symbol_by_address("kernel", call_addr) yield (tableaddr, table_name, i, idx_name, call_addr, sym_name, hooked)
def calculate(self): linux_common.set_plugin_members(self) modules = linux_lsmod.linux_lsmod(self._config).get_modules() tty_addr = self.addr_space.profile.get_symbol("tty_drivers") if not tty_addr: debug.error("Symbol tty_drivers not found in kernel") drivers = obj.Object("list_head", offset=tty_addr, vm=self.addr_space) sym_cache = {} for tty in drivers.list_of_type("tty_driver", "tty_drivers"): name = tty.name.dereference_as( "String", length=linux_common.MAX_STRING_LENGTH) ttys = obj.Object( "Array", targetType="Pointer", vm=self.addr_space, offset=tty.ttys, count=tty.num, ) for tty_dev in ttys: if tty_dev == 0: continue tty_dev = tty_dev.dereference_as("tty_struct") name = tty_dev.name recv_buf = tty_dev.ldisc.ops.receive_buf known = self.is_known_address(recv_buf, modules) if not known: sym_name = "HOOKED" hooked = 1 else: sym_name = self.profile.get_symbol_by_address( "kernel", recv_buf) hooked = 0 sym_cache[recv_buf] = sym_name yield (name, recv_buf, sym_name, hooked)
def calculate(self): linux_common.set_plugin_members(self) modules = linux_lsmod.linux_lsmod(self._config).get_modules() tty_addr = self.addr_space.profile.get_symbol("tty_drivers") if not tty_addr: debug.error("Symbol tty_drivers not found in kernel") drivers = obj.Object("list_head", offset = tty_addr, vm = self.addr_space) sym_cache = {} for tty in drivers.list_of_type("tty_driver", "tty_drivers"): name = tty.name.dereference_as("String", length = linux_common.MAX_STRING_LENGTH) ttys = obj.Object("Array", targetType = "Pointer", vm = self.addr_space, offset = tty.ttys, count = tty.num) for tty_dev in ttys: if tty_dev == 0: continue tty_dev = tty_dev.dereference_as("tty_struct") name = tty_dev.name recv_buf = tty_dev.ldisc.ops.receive_buf known = self.is_known_address(recv_buf, modules) if not known: sym_name = "HOOKED" hooked = 1 else: sym_name = self.profile.get_symbol_by_address("kernel", recv_buf) hooked = 0 sym_cache[recv_buf] = sym_name yield (name, recv_buf, sym_name, hooked)
def walk_modules_address_space(self, addr_space): mods = [x[0].obj_offset for x in linux_lsmod.linux_lsmod(self._config).calculate()] min_addr = obj.Object("unsigned long", offset = addr_space.profile.get_symbol("module_addr_min"), vm = addr_space) max_addr = obj.Object("unsigned long", offset = addr_space.profile.get_symbol("module_addr_max"), vm = addr_space) for cur_addr in range(min_addr, max_addr, 8): m = obj.Object("module", offset = cur_addr, vm = addr_space) if m.state.v() not in [0, 1, 2]: continue if m.core_size < 4096 or m.core_size > 1000000: continue if m.core_text_size < 4096 or m.core_text_size > 1000000: continue s = self.addr_space.read(m.name.obj_offset, 64) if not s: continue idx = s.find("\x00") if idx < 1: continue name = s[:idx] for n in name: if not (32 < ord(n) < 127): continue if not m.module_core.is_valid(): continue if m.obj_offset not in mods: yield m
def walk_modules_address_space(self, addr_space): list_mods = [ x[0].obj_offset for x in linux_lsmod.linux_lsmod(self._config).calculate() ] if addr_space.profile.get_symbol("module_addr_min"): min_addr_sym = obj.Object( "unsigned long", offset=addr_space.profile.get_symbol("module_addr_min"), vm=addr_space, ) max_addr_sym = obj.Object( "unsigned long", offset=addr_space.profile.get_symbol("module_addr_max"), vm=addr_space, ) elif addr_space.profile.get_symbol("mod_tree"): skip_size = addr_space.profile.get_obj_size("latch_tree_root") addr = addr_space.profile.get_symbol("mod_tree") ulong_size = addr_space.profile.get_obj_size("unsigned long") min_addr_sym = obj.Object("unsigned long", offset=addr + skip_size, vm=addr_space) max_addr_sym = obj.Object( "unsigned long", offset=addr + skip_size + ulong_size, vm=addr_space, ) else: debug.error( "Unsupport kernel verison. Please file a bug ticket that includes your kernel version and distribution." ) min_addr = min_addr_sym & ~0xFFF max_addr = (max_addr_sym & ~0xFFF) + 0x1000 scan_buf = b"" llen = max_addr - min_addr allfs = b"\xff" * 4096 memory_model = self.addr_space.profile.metadata.get( 'memory_model', '32bit') if memory_model == '32bit': minus_size = 4 else: minus_size = 8 check_bufs = [] replace_bufs = [] check_nums = [ 3000, 2800, 2700, 2500, 2300, 2100, 2000, 1500, 1300, 1200, 1024, 512, 256, 128, 96, 64, 48, 32, 24, ] for num in check_nums: check_bufs.append(b"\x00" * num) replace_bufs.append((b"\xff" * (num - minus_size)) + b"\x00" * minus_size) for page in range(min_addr, max_addr, 4096): to_append = allfs tmp = addr_space.read(page, 4096) if tmp: non_zero = False for t in tmp: if t != b"\x00": non_zero = True break if non_zero: for i in range(len(check_nums)): tmp = tmp.replace(check_bufs[i], replace_bufs[i]) to_append = tmp scan_buf = scan_buf + to_append for cur_addr in re.finditer( rb"(?=(\x00\x00\x00\x00|\x01\x00\x00\x00|\x02\x00\x00\x00))", scan_buf, ): mod_addr = min_addr + cur_addr.start() if mod_addr in list_mods: continue m = obj.Object("module", offset=mod_addr, vm=addr_space) if m.is_valid(): yield m
def modules(self): mods = lsmod.linux_lsmod(self._config).calculate() for (module, _, __) in mods: print "{0:24} {1:d}".format(module.name, module.init_size + module.core_size)
def walk_modules_address_space(self, addr_space): list_mods = [x[0].obj_offset for x in linux_lsmod.linux_lsmod(self._config).calculate()] # this for is for pre-2008 kernels: # https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/kernel/module.c?id=3a642e99babe0617febb6f402e1e063479f489db) if addr_space.profile.get_symbol("module_addr_min") == None: return min_addr_sym = obj.Object( "unsigned long", offset=addr_space.profile.get_symbol("module_addr_min"), vm=addr_space ) max_addr_sym = obj.Object( "unsigned long", offset=addr_space.profile.get_symbol("module_addr_max"), vm=addr_space ) min_addr = min_addr_sym & ~0xFFF max_addr = (max_addr_sym & ~0xFFF) + 0x1000 scan_buf = "" llen = max_addr - min_addr allfs = "\xff" * 4096 memory_model = self.addr_space.profile.metadata.get("memory_model", "32bit") if memory_model == "32bit": minus_size = 4 else: minus_size = 8 check_bufs = [] replace_bufs = [] check_nums = [ 3000, 2800, 2700, 2500, 2300, 2100, 2000, 1500, 1300, 1200, 1024, 512, 256, 128, 96, 64, 48, 32, 24, ] for num in check_nums: check_bufs.append("\x00" * num) replace_bufs.append(("\xff" * (num - minus_size)) + "\x00" * minus_size) for page in range(min_addr, max_addr, 4096): to_append = allfs tmp = addr_space.read(page, 4096) if tmp: non_zero = False for t in tmp: if t != "\x00": non_zero = True break if non_zero: for i in range(len(check_nums)): tmp = tmp.replace(check_bufs[i], replace_bufs[i]) to_append = tmp scan_buf = scan_buf + to_append for cur_addr in re.finditer("(?=(\x00\x00\x00\x00|\x01\x00\x00\x00|\x02\x00\x00\x00))", scan_buf): mod_addr = min_addr + cur_addr.start() if mod_addr in list_mods: continue m = obj.Object("module", offset=mod_addr, vm=addr_space) if m.is_valid(): yield m
def calculate(self): """ This works by walking the system call table and verifies that each is a symbol in the kernel """ linux_common.set_plugin_members(self) if not has_distorm: debug.warning( "distorm not installed. The best method to calculate the system call table size will not be used." ) if self._config.SYSCALL_INDEXES: if not os.path.exists(self._config.SYSCALL_INDEXES): debug.error("Given syscall indexes file does not exist!") index_names = {} for line in open(self._config.SYSCALL_INDEXES, "r").readlines(): ents = line.split() if len(ents) == 3 and ents[0] == "#define": name = ents[1].replace("__NR_", "") # "(__NR_timer_create+1)" index = ents[2] if index[0] == "(": index = self._find_index(index_names, index) else: index = int(index) index_names[index] = name else: index_names = None hidden_mods = list( linux_hidden_modules.linux_hidden_modules( self._config).calculate()) visible_mods = linux_lsmod.linux_lsmod(self._config).calculate() table_name = self.addr_space.profile.metadata.get( 'memory_model', '32bit') sym_addrs = self.profile.get_all_addresses() sys_call_info = self._get_table_info("sys_call_table") addrs = [(table_name, sys_call_info)] # 64 bit systems with 32 bit emulation ia32 = self.addr_space.profile.get_symbol("ia32_sys_call_table") if ia32: ia32_info = self._get_table_info("ia32_sys_call_table") addrs.append(("32bit", ia32_info)) for (table_name, (tableaddr, tblsz)) in addrs: table = obj.Object(theType='Array', offset=tableaddr, vm=self.addr_space, targetType='unsigned long', count=tblsz) for (i, call_addr) in enumerate(table): if not call_addr: continue if index_names: idx_name = self._index_name(index_names, i) else: idx_name = "" call_addr = int(call_addr) if not call_addr in sym_addrs: hooked = 1 sym_name = self._compute_hook_sym_name( visible_mods, hidden_mods, call_addr) else: hooked = 0 sym_name = self.profile.get_symbol_by_address( "kernel", call_addr) yield (tableaddr, table_name, i, idx_name, call_addr, sym_name, hooked)
def walk_modules_address_space(self, addr_space): list_mods = [x[0].obj_offset for x in linux_lsmod.linux_lsmod(self._config).calculate()] # this for is for pre-2008 kernels: # https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/kernel/module.c?id=3a642e99babe0617febb6f402e1e063479f489db) if addr_space.profile.get_symbol("module_addr_min") == None: return min_addr_sym = obj.Object("unsigned long", offset = addr_space.profile.get_symbol("module_addr_min"), vm = addr_space) max_addr_sym = obj.Object("unsigned long", offset = addr_space.profile.get_symbol("module_addr_max"), vm = addr_space) min_addr = min_addr_sym & ~0xfff max_addr = (max_addr_sym & ~0xfff) + 0x1000 scan_buf = "" llen = max_addr - min_addr allfs = "\xff" * 4096 memory_model = self.addr_space.profile.metadata.get('memory_model', '32bit') if memory_model == '32bit': minus_size = 4 else: minus_size = 8 check_bufs = [] replace_bufs = [] check_nums = [3000, 2800, 2700, 2500, 2300, 2100, 2000, 1500, 1300, 1200, 1024, 512, 256, 128, 96, 64, 48, 32, 24] for num in check_nums: check_bufs.append("\x00" * num) replace_bufs.append(("\xff" * (num-minus_size)) + "\x00" * minus_size) for page in range(min_addr, max_addr, 4096): to_append = allfs tmp = addr_space.read(page, 4096) if tmp: non_zero = False for t in tmp: if t != "\x00": non_zero = True break if non_zero: for i in range(len(check_nums)): tmp = tmp.replace(check_bufs[i], replace_bufs[i]) to_append = tmp scan_buf = scan_buf + to_append for cur_addr in re.finditer("(?=(\x00\x00\x00\x00|\x01\x00\x00\x00|\x02\x00\x00\x00))", scan_buf): mod_addr = min_addr + cur_addr.start() if mod_addr in list_mods: continue m = obj.Object("module", offset = mod_addr, vm = addr_space) if m.is_valid(): yield m
def calculate(self): """ This works by walking the system call table and verifies that each is a symbol in the kernel """ linux_common.set_plugin_members(self) if not has_distorm: debug.warning("distorm not installed. The best method to calculate the system call table size will not be used.") if self._config.SYSCALL_INDEXES: if not os.path.exists(self._config.SYSCALL_INDEXES): debug.error("Given syscall indexes file does not exist!") index_names = {} for line in open(self._config.SYSCALL_INDEXES, "r").readlines(): ents = line.split() if len(ents) == 3 and ents[0] == "#define": name = ents[1].replace("__NR_", "") # "(__NR_timer_create+1)" index = ents[2] if index[0] == "(": index = self._find_index(index_names, index) else: index = int(index) index_names[index] = name else: index_names = None hidden_mods = list(linux_hidden_modules.linux_hidden_modules(self._config).calculate()) visible_mods = linux_lsmod.linux_lsmod(self._config).calculate() table_name = self.addr_space.profile.metadata.get('memory_model', '32bit') sym_addrs = self.profile.get_all_addresses() sys_call_info = self._get_table_info("sys_call_table") addrs = [(table_name, sys_call_info)] # 64 bit systems with 32 bit emulation ia32 = self.addr_space.profile.get_symbol("ia32_sys_call_table") if ia32: ia32_info = self._get_table_info("ia32_sys_call_table") addrs.append(("32bit", ia32_info)) for (table_name, (tableaddr, tblsz)) in addrs: table = obj.Object(theType = 'Array', offset = tableaddr, vm = self.addr_space, targetType = 'unsigned long', count = tblsz) for (i, call_addr) in enumerate(table): if not call_addr: continue if index_names: idx_name = self._index_name(index_names, i) else: idx_name = "" call_addr = int(call_addr) if not call_addr in sym_addrs: hooked = 1 sym_name = self._compute_hook_sym_name(visible_mods, hidden_mods, call_addr) else: hooked = 0 sym_name = self.profile.get_symbol_by_address("kernel", call_addr) yield (tableaddr, table_name, i, idx_name, call_addr, sym_name, hooked)
def walk_modules_address_space(self, addr_space): list_mods = [x[0].obj_offset for x in linux_lsmod.linux_lsmod(self._config).calculate()] if addr_space.profile.get_symbol("module_addr_min"): min_addr_sym = obj.Object("unsigned long", offset = addr_space.profile.get_symbol("module_addr_min"), vm = addr_space) max_addr_sym = obj.Object("unsigned long", offset = addr_space.profile.get_symbol("module_addr_max"), vm = addr_space) elif addr_space.profile.get_symbol("mod_tree"): skip_size = addr_space.profile.get_obj_size("latch_tree_root") addr = addr_space.profile.get_symbol("mod_tree") ulong_size = addr_space.profile.get_obj_size("unsigned long") min_addr_sym = obj.Object("unsigned long", offset = addr + skip_size, vm = addr_space) max_addr_sym = obj.Object("unsigned long", offset = addr + skip_size + ulong_size, vm = addr_space) else: debug.error("Unsupport kernel verison. Please file a bug ticket that includes your kernel version and distribution.") min_addr = min_addr_sym & ~0xfff max_addr = (max_addr_sym & ~0xfff) + 0x1000 scan_buf = "" llen = max_addr - min_addr allfs = "\xff" * 4096 memory_model = self.addr_space.profile.metadata.get('memory_model', '32bit') if memory_model == '32bit': minus_size = 4 else: minus_size = 8 check_bufs = [] replace_bufs = [] check_nums = [3000, 2800, 2700, 2500, 2300, 2100, 2000, 1500, 1300, 1200, 1024, 512, 256, 128, 96, 64, 48, 32, 24] for num in check_nums: check_bufs.append("\x00" * num) replace_bufs.append(("\xff" * (num-minus_size)) + "\x00" * minus_size) for page in range(min_addr, max_addr, 4096): to_append = allfs tmp = addr_space.read(page, 4096) if tmp: non_zero = False for t in tmp: if t != "\x00": non_zero = True break if non_zero: for i in range(len(check_nums)): tmp = tmp.replace(check_bufs[i], replace_bufs[i]) to_append = tmp scan_buf = scan_buf + to_append for cur_addr in re.finditer("(?=(\x00\x00\x00\x00|\x01\x00\x00\x00|\x02\x00\x00\x00))", scan_buf): mod_addr = min_addr + cur_addr.start() if mod_addr in list_mods: continue m = obj.Object("module", offset = mod_addr, vm = addr_space) if m.is_valid(): yield m
def get_syscalls(self, index_lines = None, get_hidden = False): linux_common.set_plugin_members(self) if get_hidden: hidden_mods = list(linux_hidden_modules.linux_hidden_modules(self._config).calculate()) else: hidden_mods = [] visible_mods = linux_lsmod.linux_lsmod(self._config).calculate() if not index_lines: index_lines = self._find_and_parse_index_file() if index_lines: index_names = {} for line in index_lines.split("\n"): ents = line.split() if len(ents) == 3 and ents[0] == "#define": name = ents[1].replace("__NR_", "") # "(__NR_timer_create+1)" index = ents[2] if index[0] == "(": index = self._find_index(index_names, index) else: index = int(index) index_names[index] = name else: index_names = None table_name = self.addr_space.profile.metadata.get('memory_model', '32bit') sym_addrs = self.profile.get_all_addresses() sys_call_info = self._get_table_info("sys_call_table") addrs = [(table_name, sys_call_info)] # 64 bit systems with 32 bit emulation ia32 = self.addr_space.profile.get_symbol("ia32_sys_call_table") if ia32: ia32_info = self._get_table_info("ia32_sys_call_table") addrs.append(("32bit", ia32_info)) for (table_name, (tableaddr, tblsz)) in addrs: table = obj.Object(theType = 'Array', offset = tableaddr, vm = self.addr_space, targetType = 'unsigned long', count = tblsz) for (i, call_addr) in enumerate(table): if not call_addr: continue if index_names: idx_name = self._index_name(index_names, i) else: idx_name = "" call_addr = int(call_addr) if not call_addr in sym_addrs: hooked = 1 sym_name = self._compute_hook_sym_name(visible_mods, hidden_mods, call_addr) else: hooked = 0 sym_name = self.profile.get_symbol_by_address("kernel", call_addr) yield (tableaddr, table_name, i, idx_name, call_addr, sym_name, hooked)
def walk_modules_address_space(self, addr_space): list_mods = [ x[0].obj_offset for x in linux_lsmod.linux_lsmod(self._config).calculate() ] min_addr_sym = obj.Object( "unsigned long", offset=addr_space.profile.get_symbol("module_addr_min"), vm=addr_space) max_addr_sym = obj.Object( "unsigned long", offset=addr_space.profile.get_symbol("module_addr_max"), vm=addr_space) min_addr = min_addr_sym & ~0xfff max_addr = (max_addr_sym & ~0xfff) + 0x1000 scan_buf = "" llen = max_addr - min_addr allfs = "\xff" * 4096 memory_model = self.addr_space.profile.metadata.get( 'memory_model', '32bit') if memory_model == '32bit': minus_size = 4 else: minus_size = 8 check_bufs = [] replace_bufs = [] check_nums = [ 3000, 2800, 2700, 2500, 2300, 2100, 2000, 1500, 1300, 1200, 1024, 512, 256, 128, 96, 64, 48, 32, 24, 16, 12, 9 ] if minus_size == 4: check_nums = check_nums + [8, 6, 5] for num in check_nums: check_bufs.append("\x00" * num) replace_bufs.append(("\xff" * (num - minus_size)) + "\x00" * minus_size) for page in range(min_addr, max_addr, 4096): to_append = allfs tmp = addr_space.read(page, 4096) if tmp: non_zero = False for t in tmp: if t != "\x00": non_zero = True break if non_zero: for i in range(len(check_nums)): tmp = tmp.replace(check_bufs[i], replace_bufs[i]) to_append = tmp scan_buf = scan_buf + to_append for cur_addr in re.finditer( "(?=(\x00\x00\x00\x00|\x01\x00\x00\x00|\x02\x00\x00\x00))", scan_buf): mod_addr = min_addr + cur_addr.start() if mod_addr in list_mods: continue m = obj.Object("module", offset=mod_addr, vm=addr_space) if m.is_valid(): yield m
def get_syscalls(self, index_lines=None, get_hidden=False): linux_common.set_plugin_members(self) if get_hidden: hidden_mods = list( linux_hidden_modules.linux_hidden_modules( self._config).calculate()) else: hidden_mods = [] visible_mods = linux_lsmod.linux_lsmod(self._config).calculate() if not index_lines: index_lines = self._find_and_parse_index_file() if index_lines: index_names = {} for line in index_lines.split("\n"): ents = line.split() if len(ents) == 3 and ents[0] == "#define": name = ents[1].replace("__NR_", "") # "(__NR_timer_create+1)" index = ents[2] if index[0] == "(": index = self._find_index(index_names, index) else: index = int(index) index_names[index] = name else: index_names = None table_name = self.addr_space.profile.metadata.get( 'memory_model', '32bit') sym_addrs = self.profile.get_all_addresses() sys_call_info = self._get_table_info("sys_call_table") addrs = [(table_name, sys_call_info)] # 64 bit systems with 32 bit emulation ia32 = self.addr_space.profile.get_symbol("ia32_sys_call_table") if ia32: ia32_info = self._get_table_info("ia32_sys_call_table") addrs.append(("32bit", ia32_info)) for (table_name, (tableaddr, tblsz)) in addrs: table = obj.Object(theType='Array', offset=tableaddr, vm=self.addr_space, targetType='unsigned long', count=tblsz) for (i, call_addr) in enumerate(table): if not call_addr: continue if index_names: idx_name = self._index_name(index_names, i) else: idx_name = "" call_addr = int(call_addr) if not call_addr in sym_addrs: hooked = 1 sym_name = self._compute_hook_sym_name( visible_mods, hidden_mods, call_addr) else: hooked = 0 sym_name = self.profile.get_symbol_by_address( "kernel", call_addr) yield (tableaddr, table_name, i, idx_name, call_addr, sym_name, hooked)