def _init_offset_mm(cls): """Brute-forces the offset of 'mm_struct *mm' below the found 'list_head tasks' structure.""" if not cls.is_offset_defined('tasks'): return ksymbol_command = linux_auto_ksymbol(cls.vm.get_config()) swapper_task_addr = ksymbol_command.get_symbol('init_task') swapper_task = obj.Object('task_struct', offset=swapper_task_addr, vm=cls.vm) tasks_iterator = iter(swapper_task.tasks) try: init_task = tasks_iterator.next() except StopIteration: debug.debug("Can't get the next task after 'swapper' in tasks list") return # Start brute-force from the bottom of 'list_head tasks' structure mm_offset_start = cls.vtypes['task_struct'][1]['tasks'][0] + swapper_task.tasks.size() for mm_offset in xrange(mm_offset_start, mm_offset_start + 0x40, 4): mm_ptr = obj.Object('Pointer', offset=swapper_task.obj_offset + mm_offset, vm=cls.vm) if mm_ptr.v() != 0: # 'mm' field for kernel threads is always NULL continue # Check 'mm' and 'active_mm' pointers in the 'task_struct' structure of 'init' process mm_ptr = obj.Object('Pointer', offset=init_task.obj_offset + mm_offset, vm=cls.vm) active_mm_ptr = obj.Object('Pointer', offset=init_task.obj_offset + mm_offset + 4, vm=cls.vm) if mm_ptr.v() != active_mm_ptr.v() or mm_ptr.v() < 0xc0000000 or not mm_ptr: continue # Check if the first member of 'mm_struct' points to 'vm_area_struct' mmap_ptr = obj.Object('Pointer', offset=mm_ptr.dereference().obj_offset, vm=cls.vm) mmap_struct = mmap_ptr.dereference() if not mmap_struct: continue # Check if there is a member of 'vm_area_struct' structure that points back to 'mm_struct' # # Before kernel versions 3.8: # struct vm_area_struct { # struct mm_struct * vm_mm; <--- # unsigned long vm_start; # unsigned long vm_end; # ... # } # Since kernel versions 3.8: # struct vm_area_struct { # unsigned long vm_start; # unsigned long vm_end; # ... # struct mm_struct * vm_mm; <--- # } is_vm_mm_found = False for vm_mm_offset in xrange(0, 0x64, 4): vm_mm = obj.Object('Pointer', offset=mmap_struct.obj_offset + vm_mm_offset, vm=cls.vm) if vm_mm.v() == mm_ptr.v(): is_vm_mm_found = True break if not is_vm_mm_found: continue cls.vtypes['task_struct'][1]['mm'][0] = mm_offset cls._update_profile() debug.debug("Found 'task_struct->mm' offset: {0}".format(mm_offset)) # Init offsets of 'mm_struct' structure mm_struct.init_offsets(cls.vm) return debug.debug("Can't find 'task_struct->mm' offset")
def _init_offset_tasks(cls): if not cls.is_offset_defined('comm'): return ksymbol_command = linux_auto_ksymbol(cls.vm.get_config()) swapper_task_addr = ksymbol_command.get_symbol('init_task') for tasks_offset in xrange(0, cls.MAX_SIZE, 4): cls.vtypes['task_struct'][1]['tasks'][0] = tasks_offset cls._update_profile() swapper_task = obj.Object('task_struct', offset=swapper_task_addr, vm=cls.vm) # Check first two tasks, they should be called 'init' and 'kthreadd' tasks_iterator = iter(swapper_task.tasks) try: init_task = tasks_iterator.next() if str(init_task.comm) == 'init': kthreadd_task = tasks_iterator.next() if str(kthreadd_task.comm) == 'kthreadd': debug.debug( "Found 'task_struct->tasks' offset: {0}".format( tasks_offset)) return except StopIteration: pass debug.debug("Can't find 'task_struct->tasks' offset") # Reset not found 'tasks' offset cls.vtypes['task_struct'][1]['tasks'][0] = None cls._update_profile()
def _init_offset_pgd(cls): if not task_struct.is_offset_defined('mm'): return ksymbol_command = linux_auto_ksymbol(cls.vm.get_config()) swapper_task_addr = ksymbol_command.get_symbol('init_task') swapper_task = obj.Object('task_struct', offset=swapper_task_addr, vm=cls.vm) init_task = iter(swapper_task.tasks).next() init_task_mm = init_task.mm.dereference() for pgd_offset in xrange(0, 0x100, 4): pgd = obj.Object('Pointer', offset=init_task_mm.obj_offset + pgd_offset, vm=cls.vm) if not pgd: continue dtb = cls.vm.vtop(pgd.v()) init_task_as = cls.vm.__class__(cls.vm.base, cls.vm.get_config(), dtb=dtb) if init_task_as.vtop(pgd.v()) == dtb: cls.vtypes['mm_struct'][1]['pgd'][0] = pgd_offset cls._update_profile() debug.debug( "Found 'mm_struct->pgd' offset: {0}".format(pgd_offset)) return debug.debug("Can't find 'mm_struct->pgd' offset")
def calculate(self): linux_common.set_plugin_members(self) # Automatically initialize task_struct offsets task_struct.init_offsets(self.addr_space) if not all([ task_struct.is_offset_defined(memname) for memname in ['comm', 'tasks', 'mm'] ]): debug.warning( "Some of required members of 'task_struct' structure were not found." ) return ksymbol_command = linux_auto_ksymbol(self._config) init_task_addr = ksymbol_command.get_symbol('init_task') if init_task_addr is None: debug.warning("Can't locate the first process (swapper).") return init_task = obj.Object('task_struct', offset=init_task_addr, vm=self.addr_space) tasks_dtb_list = [] for task in init_task.tasks: if mm_struct.is_offset_defined('pgd'): pgd = task.mm.pgd if pgd: tasks_dtb_list.append(self.addr_space.vtop(pgd)) yield task # List unnamed potentially hidden or terminated processes # auto-discovered by dtblist command. dtblist_command = linux_auto_dtblist(self._config) for dtb in dtblist_command.calculate(): if dtb not in tasks_dtb_list: yield dtb
def calculate(self): linux_common.set_plugin_members(self) # Automatically initialize task_struct offsets task_struct.init_offsets(self.addr_space) if not all([task_struct.is_offset_defined(memname) for memname in ['comm', 'tasks', 'mm']]): debug.warning("Some of required members of 'task_struct' structure were not found.") return ksymbol_command = linux_auto_ksymbol(self._config) init_task_addr = ksymbol_command.get_symbol('init_task') if init_task_addr is None: debug.warning("Can't locate the first process (swapper).") return init_task = obj.Object('task_struct', offset=init_task_addr, vm=self.addr_space) tasks_dtb_list = [] for task in init_task.tasks: if mm_struct.is_offset_defined('pgd'): pgd = task.mm.pgd if pgd: tasks_dtb_list.append(self.addr_space.vtop(pgd)) yield task # List unnamed potentially hidden or terminated processes # auto-discovered by dtblist command. dtblist_command = linux_auto_dtblist(self._config) for dtb in dtblist_command.calculate(): if dtb not in tasks_dtb_list: yield dtb
def test_ksymtab(self): print "### Start test linux_auto_ksymtab" ksymbol_command = linux_auto_ksymbol(self._config) ksymtab_test_file = KSYMTAB_TESTS[self.fileid()] for test in open(ksymtab_test_file): symbol_name, symbol_vaddr = test.split() symbol_vaddr = int(symbol_vaddr, 16) try: self.assertTrue(ksymbol_command.get_symbol(symbol_name) == symbol_vaddr) except: pdb.set_trace()
def _init_offset_comm(cls): ksymbol_command = linux_auto_ksymbol(cls.vm.get_config()) swapper_task_addr = ksymbol_command.get_symbol('init_task') if swapper_task_addr is None: return swapper_task_data = cls.vm.read(swapper_task_addr, cls.MAX_SIZE) comm_offset = swapper_task_data.find('swapper') if comm_offset != -1: debug.debug("Found 'task_struct->comm' offset: {0}".format(comm_offset)) cls.vtypes['task_struct'][1]['comm'][0] = comm_offset cls._update_profile() else: debug.debug("Can't find 'task_struct->comm' offset")
def _init_offset_comm(cls): ksymbol_command = linux_auto_ksymbol(cls.vm.get_config()) swapper_task_addr = ksymbol_command.get_symbol('init_task') if swapper_task_addr is None: return swapper_task_data = cls.vm.read(swapper_task_addr, cls.MAX_SIZE) comm_offset = swapper_task_data.find('swapper') if comm_offset != -1: debug.debug( "Found 'task_struct->comm' offset: {0}".format(comm_offset)) cls.vtypes['task_struct'][1]['comm'][0] = comm_offset cls._update_profile() else: debug.debug("Can't find 'task_struct->comm' offset")
def _init_offset_pgd(cls): if not task_struct.is_offset_defined('mm'): return ksymbol_command = linux_auto_ksymbol(cls.vm.get_config()) swapper_task_addr = ksymbol_command.get_symbol('init_task') swapper_task = obj.Object('task_struct', offset=swapper_task_addr, vm=cls.vm) init_task = iter(swapper_task.tasks).next() init_task_mm = init_task.mm.dereference() for pgd_offset in xrange(0, 0x100, 4): pgd = obj.Object('Pointer', offset=init_task_mm.obj_offset + pgd_offset, vm=cls.vm) if not pgd: continue dtb = cls.vm.vtop(pgd.v()) init_task_as = cls.vm.__class__(cls.vm.base, cls.vm.get_config(), dtb=dtb) if init_task_as.vtop(pgd.v()) == dtb: cls.vtypes['mm_struct'][1]['pgd'][0] = pgd_offset cls._update_profile() debug.debug("Found 'mm_struct->pgd' offset: {0}".format(pgd_offset)) return debug.debug("Can't find 'mm_struct->pgd' offset")
def _init_offset_tasks(cls): if not cls.is_offset_defined('comm'): return ksymbol_command = linux_auto_ksymbol(cls.vm.get_config()) swapper_task_addr = ksymbol_command.get_symbol('init_task') for tasks_offset in xrange(0, cls.MAX_SIZE, 4): cls.vtypes['task_struct'][1]['tasks'][0] = tasks_offset cls._update_profile() swapper_task = obj.Object('task_struct', offset=swapper_task_addr, vm=cls.vm) # Check first two tasks, they should be called 'init' and 'kthreadd' tasks_iterator = iter(swapper_task.tasks) try: init_task = tasks_iterator.next() if str(init_task.comm) == 'init': kthreadd_task = tasks_iterator.next() if str(kthreadd_task.comm) == 'kthreadd': debug.debug("Found 'task_struct->tasks' offset: {0}".format(tasks_offset)) return except StopIteration: pass debug.debug("Can't find 'task_struct->tasks' offset") # Reset not found 'tasks' offset cls.vtypes['task_struct'][1]['tasks'][0] = None cls._update_profile()
def _init_offset_mm(cls): """Brute-forces the offset of 'mm_struct *mm' below the found 'list_head tasks' structure.""" if not cls.is_offset_defined('tasks'): return ksymbol_command = linux_auto_ksymbol(cls.vm.get_config()) swapper_task_addr = ksymbol_command.get_symbol('init_task') swapper_task = obj.Object('task_struct', offset=swapper_task_addr, vm=cls.vm) tasks_iterator = iter(swapper_task.tasks) try: init_task = tasks_iterator.next() except StopIteration: debug.debug( "Can't get the next task after 'swapper' in tasks list") return # Start brute-force from the bottom of 'list_head tasks' structure mm_offset_start = cls.vtypes['task_struct'][1]['tasks'][ 0] + swapper_task.tasks.size() for mm_offset in xrange(mm_offset_start, mm_offset_start + 0x40, 4): mm_ptr = obj.Object('Pointer', offset=swapper_task.obj_offset + mm_offset, vm=cls.vm) if mm_ptr.v() != 0: # 'mm' field for kernel threads is always NULL continue # Check 'mm' and 'active_mm' pointers in the 'task_struct' structure of 'init' process mm_ptr = obj.Object('Pointer', offset=init_task.obj_offset + mm_offset, vm=cls.vm) active_mm_ptr = obj.Object('Pointer', offset=init_task.obj_offset + mm_offset + 4, vm=cls.vm) if mm_ptr.v() != active_mm_ptr.v() or mm_ptr.v( ) < 0xc0000000 or not mm_ptr: continue # Check if the first member of 'mm_struct' points to 'vm_area_struct' mmap_ptr = obj.Object('Pointer', offset=mm_ptr.dereference().obj_offset, vm=cls.vm) mmap_struct = mmap_ptr.dereference() if not mmap_struct: continue # Check if there is a member of 'vm_area_struct' structure that points back to 'mm_struct' # # Before kernel versions 3.8: # struct vm_area_struct { # struct mm_struct * vm_mm; <--- # unsigned long vm_start; # unsigned long vm_end; # ... # } # Since kernel versions 3.8: # struct vm_area_struct { # unsigned long vm_start; # unsigned long vm_end; # ... # struct mm_struct * vm_mm; <--- # } is_vm_mm_found = False for vm_mm_offset in xrange(0, 0x64, 4): vm_mm = obj.Object('Pointer', offset=mmap_struct.obj_offset + vm_mm_offset, vm=cls.vm) if vm_mm.v() == mm_ptr.v(): is_vm_mm_found = True break if not is_vm_mm_found: continue cls.vtypes['task_struct'][1]['mm'][0] = mm_offset cls._update_profile() debug.debug( "Found 'task_struct->mm' offset: {0}".format(mm_offset)) # Init offsets of 'mm_struct' structure mm_struct.init_offsets(cls.vm) return debug.debug("Can't find 'task_struct->mm' offset")