Exemple #1
0
def get_module_list(pgd):
    """ Return list of modules for a given PGD

        :param pgd: The PGD of the process for which we want to extract the modules, or 0 to extract kernel modules
        :type pgd: int

        :return: List of modules, each element is a dictionary with keys: "name", "base", and "size"
        :rtype: list
    """
    import vmi
    proc_list = get_process_list()
    mods = []
    found = False
    if pgd == 0:
        proc_pid = 0
        proc_pgd = 0
        found = True
    else:
        for proc in proc_list:
            proc_pid = proc["pid"]
            proc_pgd = proc["pgd"]
            if proc_pgd == pgd:
                found = True
                break

    if found:
        vmi.update_modules(proc_pgd, update_symbols=False)
        if (proc_pid, proc_pgd) in vmi.modules:
            for mod in vmi.modules[(proc_pid, proc_pgd)].values():
                mods.append({"name": mod.get_name(),
                             "base": mod.get_base(),
                             "size": mod.get_size()})
        return mods
    else:
        raise ValueError("Process with PGD %x not found" % pgd)
Exemple #2
0
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)
Exemple #3
0
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)
Exemple #4
0
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)
Exemple #5
0
def get_symbol_list():
    """ Return list of symbols

        :return: List of symbols, each element is a dictionary with keys: "mod", "name", and "addr"
        :rtype: list
    """
    import vmi
    from utils import pp_print
    res_syms = []
    diff_modules = {}
    proc_list = get_process_list()
    pp_print("[*] Updating symbol list... Be patient, this may take a while\n")
    for proc in proc_list:
        proc_pid = proc["pid"]
        proc_pgd = proc["pgd"]
        if proc_pgd != 0:
            vmi.update_modules(proc_pgd, update_symbols=True)
            if (proc_pid, proc_pgd) in vmi.modules:
                for module in vmi.modules[proc_pid, proc_pgd].values():
                    c = module.get_checksum()
                    n = module.get_fullname()
                    if (c, n) not in diff_modules:
                        diff_modules[(c, n)] = module

    # Include kernel modules too
    vmi.update_modules(0, update_symbols=True)
    if (0, 0) in vmi.modules:
        for module in vmi.modules[0, 0].values():
            c = module.get_checksum()
            n = module.get_fullname()
            if (c, n) not in diff_modules:
                diff_modules[(c, n)] = module

    for mod in diff_modules.values():
        syms = mod.get_symbols()
        for name in syms:
            res_syms.append({
                "mod": mod.get_name(),
                "name": name,
                "addr": syms[name]
            })
    return res_syms
Exemple #6
0
def get_module_list(pgd):
    """ Return list of modules for a given PGD

        :param pgd: The PGD of the process for which we want to extract the modules, or 0 to extract kernel modules
        :type pgd: int

        :return: List of modules, each element is a dictionary with keys: "name", "base", "size", and "symbols_resolved"
        :rtype: list
    """
    import vmi
    proc_list = get_process_list()
    mods = []
    found = False
    if pgd == 0:
        proc_pid = 0
        proc_pgd = 0
        found = True
    else:
        for proc in proc_list:
            proc_pid = proc["pid"]
            proc_pgd = proc["pgd"]
            if proc_pgd == pgd:
                found = True
                break

    if found:
        vmi.update_modules(proc_pgd, update_symbols=False)
        if (proc_pid, proc_pgd) in vmi.modules:
            for mod in vmi.modules[(proc_pid, proc_pgd)].values():
                mods.append({"name": mod.get_name(),
                             "base": mod.get_base(),
                             "size": mod.get_size(),
                             "symbols_resolved" : mod.are_symbols_resolved()})
        return mods
    else:
        raise ValueError("Process with PGD %x not found" % pgd)
Exemple #7
0
def get_symbol_list(pgd = None):
    """ Return list of symbols

        :param pgd: The pgd to obtain the symbols from. 0 to get kernel symbols
        :type pgd: int

        :return: List of symbols, each element is a dictionary with keys: "mod", "name", and "addr"
        :rtype: list
    """
    import vmi
    from utils import pp_print
    res_syms = []
    diff_modules = {}
    if pgd is None: 
        proc_list = get_process_list()
        pp_print("[*] Updating symbol list... Be patient, this may take a while\n")
        for proc in proc_list:
            proc_pid = proc["pid"]
            proc_pgd = proc["pgd"]
            if proc_pgd != 0:
                vmi.update_modules(proc_pgd, update_symbols=True)
                if (proc_pid, proc_pgd) in vmi.modules:
                    for module in vmi.modules[proc_pid, proc_pgd].values():
                        c = module.get_checksum()
                        n = module.get_fullname()
                        if (c, n) not in diff_modules:
                            diff_modules[(c, n)] = [module]
                        else:
                            diff_modules[(c, n)].append(module)
        # Include kernel modules too
        vmi.update_modules(0, update_symbols=True)
        if (0, 0) in vmi.modules:
            for module in vmi.modules[0, 0].values():
                c = module.get_checksum()
                n = module.get_fullname()
                if (c, n) not in diff_modules:
                    diff_modules[(c, n)] = [module]
                else:
                    diff_modules[(c, n)].append(module)

    else:
        pp_print("[*] Updating symbol list for one process... Be patient, this may take a while\n")
        vmi.update_modules(pgd, update_symbols=True)
        for proc_pid, proc_pgd in vmi.modules:
            if proc_pgd == pgd:
                for module in vmi.modules[proc_pid, proc_pgd].values():
                    c = module.get_checksum()
                    n = module.get_fullname()
                    if (c, n) not in diff_modules:
                        diff_modules[(c, n)] = [module]
                    else:
                        diff_modules[(c, n)].append(module)

    for mod_list in diff_modules.values():
        added_names = []
        for mod in mod_list:
            syms = mod.get_symbols()
            for name in syms:
                if name not in added_names:
                    res_syms.append({"mod": mod.get_name(), "name": name, "addr": syms[name]})
                    added_names.append(name)
    return res_syms
Exemple #8
0
def get_symbol_list(pgd = None):
    """ Return list of symbols

        :param pgd: The pgd to obtain the symbols from. 0 to get kernel symbols
        :type pgd: int

        :return: List of symbols, each element is a dictionary with keys: "mod", "name", and "addr"
        :rtype: list
    """
    import vmi
    from utils import pp_print
    res_syms = []
    diff_modules = {}
    if pgd is None: 
        proc_list = get_process_list()
        pp_print("[*] Updating symbol list... Be patient, this may take a while\n")
        for proc in proc_list:
            proc_pid = proc["pid"]
            proc_pgd = proc["pgd"]
            if proc_pgd != 0:
                vmi.update_modules(proc_pgd, update_symbols=True)
                if (proc_pid, proc_pgd) in vmi.modules:
                    for module in vmi.modules[proc_pid, proc_pgd].values():
                        c = module.get_checksum()
                        n = module.get_fullname()
                        if (c, n) not in diff_modules:
                            diff_modules[(c, n)] = [module]
                        else:
                            diff_modules[(c, n)].append(module)
        # Include kernel modules too
        vmi.update_modules(0, update_symbols=True)
        if (0, 0) in vmi.modules:
            for module in vmi.modules[0, 0].values():
                c = module.get_checksum()
                n = module.get_fullname()
                if (c, n) not in diff_modules:
                    diff_modules[(c, n)] = [module]
                else:
                    diff_modules[(c, n)].append(module)

    else:
        pp_print("[*] Updating symbol list for one process... Be patient, this may take a while\n")
        vmi.update_modules(pgd, update_symbols=True)
        for proc_pid, proc_pgd in vmi.modules:
            if proc_pgd == pgd:
                for module in vmi.modules[proc_pid, proc_pgd].values():
                    c = module.get_checksum()
                    n = module.get_fullname()
                    if (c, n) not in diff_modules:
                        diff_modules[(c, n)] = [module]
                    else:
                        diff_modules[(c, n)].append(module)

    for mod_list in diff_modules.values():
        added_names = []
        for mod in mod_list:
            syms = mod.get_symbols()
            for name in syms:
                if name not in added_names:
                    res_syms.append({"mod": mod.get_name(), "name": name, "addr": syms[name]})
                    added_names.append(name)
    return res_syms
Exemple #9
0
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)