def add_module_monitoring_hooks(pgd): ''' Adds initial set of breakpoints for a given process, so that we can detect when a new module is inserted, or a module is removed from any of its linked lists. ''' from api import BP import api from vmi import update_modules import functools from utils import pp_error if pgd not in module_load_remove_breakpoints: module_load_remove_breakpoints[pgd] = {} # Update the module list for this pgd hooking_points = update_modules(pgd) if hooking_points is not None: # Add the BPW breakpoints for module_base, addr, size in hooking_points: haddr = api.va_to_pa(pgd, addr) bp = BP(haddr, None, size=size, typ=BP.MEM_WRITE_PHYS, func=functools.partial(module_change_callback, pgd, addr, haddr), new_style=True) module_load_remove_breakpoints[pgd][(module_base, addr, size)] = bp bp.enable() else: pp_error( "Could not set initial list of breakpoints for module monitoring: %x" % pgd)
def add_module_monitoring_hooks(pgd): ''' Adds initial set of breakpoints for a given process, so that we can detect when a new module is inserted, or a module is removed from any of its linked lists. ''' from api import BP import api from vmi import update_modules import functools from utils import pp_error if pgd not in module_load_remove_breakpoints: module_load_remove_breakpoints[pgd] = {} # Update the module list for this pgd hooking_points = update_modules(pgd) if hooking_points is not None: # Add the BPW breakpoints for module_base, addr, size in hooking_points: haddr = api.va_to_pa(pgd, addr) bp = BP(haddr, None, size = size, typ = BP.MEM_WRITE_PHYS, func = functools.partial(module_change_callback, pgd, addr, haddr), new_style = True) module_load_remove_breakpoints[pgd][(module_base, addr, size)] = bp bp.enable() else: pp_error("Could not set initial list of breakpoints for module monitoring: %x" % pgd)
def module_change_callback(pgd, bp_vaddr, bp_haddr, cpu_index, vaddr, size, haddr, data): ''' Callback function triggered whenever there is a change in the list of linked modules for a given process. Updates the module list for that PGD (or kernel). ''' import functools import struct import api from api import BP from vmi import update_modules from utils import pp_error from vmi import set_modules_non_present from vmi import clean_non_present_modules # First, we check if the memory address written points to a module # that we have already detected (it is in our list of hooking points). # In this way we avoid triggering one update operation for every # modified pointer (inserting a module requires to change several # pointers, due to the different linked lists). # Return if it points inside a module that we have already added to our list for module_base, hook_addr, hook_size in module_load_remove_breakpoints[pgd]: if data >= module_base and data < (hook_addr + hook_size): return hooking_points = update_modules(pgd) if hooking_points is not None: # Update hooking points # 1) Remove the breakpoints not used anymore bps_to_remove = [] for hp in module_load_remove_breakpoints[pgd]: if hp not in hooking_points: bps_to_remove.append(hp) for hp in bps_to_remove: module_load_remove_breakpoints[pgd][hp].disable() del module_load_remove_breakpoints[pgd][hp] # 2) Add new breakpoints for hp in hooking_points: if hp not in module_load_remove_breakpoints[pgd]: module_base, addr, size = hp haddr = api.va_to_pa(pgd, addr) bp = BP(haddr, None, size = size, typ = BP.MEM_WRITE_PHYS, func = functools.partial(module_change_callback, pgd, addr, haddr)) module_load_remove_breakpoints[pgd][hp] = bp bp.enable() else: # Just remove all the modules for the process # Mark all modules as non-present set_modules_non_present(None, pgd) # Remove all the modules that are not marked as present clean_non_present_modules(None, pgd)
def module_change_callback(pgd, bp_vaddr, bp_haddr, params): ''' Callback function triggered whenever there is a change in the list of linked modules for a given process. Updates the module list for that PGD (or kernel). ''' import functools import struct import api from api import BP from vmi import update_modules from utils import pp_error from vmi import set_modules_non_present from vmi import clean_non_present_modules cpu_index = params["cpu_index"] vaddr = params["vaddr"] size = params["size"] haddr = params["haddr"] data = params["data"] # First, we check if the memory address written points to a module # that we have already detected (it is in our list of hooking points). # In this way we avoid triggering one update operation for every # modified pointer (inserting a module requires to change several # pointers, due to the different linked lists). # Return if it points inside a module that we have already added to our list for module_base, hook_addr, hook_size in module_load_remove_breakpoints[pgd]: if data >= module_base and data < (hook_addr + hook_size): return hooking_points = update_modules(pgd) if hooking_points is not None: # Update hooking points # 1) Remove the breakpoints not used anymore bps_to_remove = [] for hp in module_load_remove_breakpoints[pgd]: if hp not in hooking_points: bps_to_remove.append(hp) for hp in bps_to_remove: module_load_remove_breakpoints[pgd][hp].disable() del module_load_remove_breakpoints[pgd][hp] # 2) Add new breakpoints for hp in hooking_points: if hp not in module_load_remove_breakpoints[pgd]: module_base, addr, size = hp haddr = api.va_to_pa(pgd, addr) bp = BP(haddr, None, size = size, typ = BP.MEM_WRITE_PHYS, func = functools.partial(module_change_callback, pgd, addr, haddr), new_style = True) module_load_remove_breakpoints[pgd][hp] = bp bp.enable() else: # Just remove all the modules for the process # Mark all modules as non-present set_modules_non_present(None, pgd) # Remove all the modules that are not marked as present clean_non_present_modules(None, pgd)