Пример #1
0
def load_module(params):
    '''
        Callback trigger for every module loaded.
    '''
    global cm
    global pyrebox_print
    global entry_point_bp
    global target_pgd
    global target_procname
    import pefile
    import api
    from api import BP

    pid = params["pid"]
    pgd = params["pgd"]
    base = params["base"]
    size = params["size"]
    name = params["name"]
    fullname = params["fullname"]

    if pgd == target_pgd and target_procname.lower().startswith(name.lower()):
        cm.rm_callback("load_module")
        # Set a breakpoint on the EP, that will start a shell
        entry_point_bp = BP(base,
                            pgd,
                            size=size,
                            new_style=True,
                            func=module_entry_point)
        entry_point_bp.enable()
        # Call all our internal callbacks
        for cb in load_module_callbacks:
            cb(params)
def new_proc(params):
    '''
    Process creation callback. Receives 3 parameters:
        :param pid: The pid of the process
        :type pid: int
        :param pgd: The PGD of the process
        :type pgd: int
        :param name: The name of the process
        :type name: str
    '''
    global pyrebox_print
    global target_procname
    global cm
    global memwrite_breakpoint

    pid = params["pid"]
    pgd = params["pgd"]
    name = params["name"]

    pyrebox_print("New process created! pid: %x, pgd: %x, name: %s" %
                  (pid, pgd, name))
    # For instance, we can start the shell whenever a process is created
    if target_procname != "" and target_procname.lower() in name.lower():
        pyrebox_print(
            "Creating memory write callback for this process on user address space"
        )
        memwrite_breakpoint = BP(0x0,
                                 pgd,
                                 size=0x80000000,
                                 typ=BP.MEM_WRITE,
                                 func=mem_write,
                                 new_style=True)
        memwrite_breakpoint.enable()
def new_proc(params):
    '''
    Process creation callback. Receives 3 parameters:
        :param pid: The pid of the process
        :type pid: int
        :param pgd: The PGD of the process
        :type pgd: int
        :param name: The name of the process
        :type name: str
    '''
    global pyrebox_print
    global target_procname
    global cm
    global memwrite_breakpoint

    pid = params["pid"] 
    pgd = params["pgd"] 
    name = params["name"]

    pyrebox_print("New process created! pid: %x, pgd: %x, name: %s" % (pid, pgd, name))
    # For instance, we can start the shell whenever a process is created
    if target_procname != "" and target_procname.lower() in name.lower():
        pyrebox_print("Creating memory write callback for this process on user address space")
        memwrite_breakpoint = BP(0x0, pgd, size=0x80000000, typ=BP.MEM_WRITE, func=mem_write, new_style = True)
        memwrite_breakpoint.enable()
Пример #4
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)
Пример #5
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)
Пример #6
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)
Пример #7
0
def context_change(target_pgd, target_mod_name, old_pgd, new_pgd):
    '''Callback triggered for every context change
        :param target_pgd: This parameter is inserted using functools.partial (see callback registration)
        :param target_mod_name: This parameter is inserted using functools.partial (see callback registration)
        :param old_pgd: This is the first parameter of the callback
        :param new_pgd: This is the second parameter of the callback
    '''
    global cm
    if target_pgd == new_pgd:
        ep = find_ep(target_pgd, target_mod_name)
        if ep is not None:
            pyrebox_print("The entry point for %s is %x\n" % (target_mod_name, ep))
            cm.rm_callback("context_change")
            # Set a breakpoint on the EP, that will start a shell
            bp = BP(ep, target_pgd)
            bp.enable()
Пример #8
0
def load_module(params):
    '''
        Callback trigger for every module loaded.
    '''
    global cm
    global pyrebox_print
    global entry_point_bp
    global target_pgd
    global target_procname
    import pefile
    import api
    from api import BP

    pid = params["pid"]
    pgd = params["pgd"]
    base = params["base"]
    size = params["size"]
    name = params["name"]
    fullname = params["fullname"]

    if pgd == target_pgd and target_procname.lower().startswith(name.lower()):
        # Loaded main module, try to read EP
        ep = None
        try:
            pe_data = api.r_va(pgd, base, 0x1000)
            pe = pefile.PE(data=pe_data)
            ep = base + pe.OPTIONAL_HEADER.AddressOfEntryPoint
        except Exception as e:
            print(e)
            pyrebox_print("Could not read EP from module %s on load" % name)

        # If we have the EP, put a breakpoint there
        if ep is not None:
            pyrebox_print("The entry point for %s is 0x%x\n" %
                          (target_procname, ep))

            cm.rm_callback("load_module")

            pyrebox_print("Setting BP on entrypoint")

            # Set a breakpoint on the EP, that will start a shell
            entry_point_bp = BP(ep,
                                pgd,
                                new_style=True,
                                func=module_entry_point)
            entry_point_bp.enable()
Пример #9
0
def context_change(target_pgd, target_mod_name, params):
    '''Callback triggered for every context change
        :param target_pgd: This parameter is inserted using functools.partial (see callback registration)
        :param target_mod_name: This parameter is inserted using functools.partial (see callback registration)
        :param old_pgd: This is the first parameter of the callback
        :param new_pgd: This is the second parameter of the callback
    '''
    global cm
    old_pgd = params["old_pgd"]
    new_pgd = params["new_pgd"]
    if target_pgd == new_pgd:
        ep = find_ep(target_pgd, target_mod_name)
        if ep is not None:
            pyrebox_print("The entry point for %s is %x\n" % (target_mod_name, ep))
            cm.rm_callback("context_change")
            # Set a breakpoint on the EP, that will start a shell
            bp = BP(ep, target_pgd, new_style = True)
            bp.enable()
Пример #10
0
def context_change(new_proc, target_mod_name, params):
    '''Callback triggered for every context change'''
    global ntdll_breakpoint
    from mw_monitor_classes import mwmon
    from api import BP
    import api
    from api import CallbackManager
    from functools import partial

    old_pgd = params["old_pgd"]
    new_pgd = params["new_pgd"]

    if new_proc.get_pgd() == new_pgd:
        ep = find_ep(new_proc, target_mod_name)
        if ep is not None:
            mwmon.printer("The entry point for %s is %x\n" %
                          (target_mod_name, ep))
            mwmon.cm.rm_callback("context_change_%x" % new_proc.get_pgd())

            try:
                # Load modules and symbols for the process
                mods = api.get_module_list(new_proc.get_pgd())
                if mods is not None:
                    for m in mods:
                        name = m["name"]
                        base = m["base"]
                        size = m["size"]
                        new_proc.set_module(name, base, size)
                        # NTDLL is a special case, and we set a breakpoint
                        # on the code of the main module to trigger the symbol resolution
                        # as soon as we execute one instruction in its
                        # region
                        if target_mod_name in name:
                            ntdll_breakpoint[new_proc.get_pgd()] = BP(
                                base,
                                new_proc.get_pgd(),
                                size=size,
                                func=partial(ntdll_breakpoint_func, new_proc),
                                new_style=True)
                            ntdll_breakpoint[new_proc.get_pgd()].enable()

            except ValueError as e:
                # The process has not been created yet, so we need to
                # wait for symbol resolution
                pass

            # Callback for each module loaded
            mwmon.cm.add_callback(CallbackManager.LOADMODULE_CB,
                                  module_loaded,
                                  pgd=new_proc.get_pgd(),
                                  name=("load_module_%x" % new_proc.get_pgd()))
Пример #11
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)
Пример #12
0
def gdb_breakpoint_insert(thread_id, thread_list, addr, length, bp_type):
    ''' Insert a breakpoing for GDB '''
    global gdb_breakpoint_list
    from api import BP
    import functools

    # Obtain PGD from thread
    thread = None
    # First, check if we can read the register from the CPU object
    for element in thread_list:
        if element['id'] == thread_id:
            thread = element
            break

    if thread is None:
        return 0

    pgd = thread['pgd']

    if bp_type not in gdb_breakpoint_list:
        gdb_breakpoint_list[bp_type] = {}
    if pgd not in gdb_breakpoint_list[bp_type]:
        gdb_breakpoint_list[bp_type][pgd] = {}
    if addr not in gdb_breakpoint_list[bp_type][pgd]:
        gdb_breakpoint_list[bp_type][pgd][addr] = []

    nb_breakpoints_added = 0

    if bp_type == GDB_BREAKPOINT_SW:
        f = functools.partial(gdb_breakpoint_callback, addr, pgd, length,
                              bp_type)
        bp = BP(addr=addr,
                pgd=pgd,
                size=length,
                typ=BP.EXECUTION,
                func=f,
                new_style=True)
        bp.enable()
        gdb_breakpoint_list[bp_type][pgd][addr].append(bp)
        nb_breakpoints_added += 1

    if bp_type == GDB_BREAKPOINT_HW:
        f = functools.partial(gdb_breakpoint_callback,
                              addr,
                              pgd,
                              length,
                              bp_type,
                              new_style=True)
        bp = BP(addr=addr, pgd=pgd, size=length, typ=BP.EXECUTION, func=f)
        bp.enable()
        gdb_breakpoint_list[bp_type][pgd][addr].append(bp)
        nb_breakpoints_added += 1

    if bp_type == GDB_WATCHPOINT_WRITE or bp_type == GDB_WATCHPOINT_ACCESS:
        f = functools.partial(gdb_breakpoint_callback,
                              addr,
                              pgd,
                              length,
                              bp_type,
                              new_style=True)
        bp = BP(addr=addr, pgd=pgd, size=length, typ=BP.MEM_WRITE, func=f)
        bp.enable()
        gdb_breakpoint_list[bp_type][pgd][addr].append(bp)
        nb_breakpoints_added += 1

    if bp_type == GDB_WATCHPOINT_READ or bp_type == GDB_WATCHPOINT_ACCESS:
        f = functools.partial(gdb_breakpoint_callback,
                              addr,
                              pgd,
                              length,
                              bp_type,
                              new_style=True)
        bp = BP(addr=addr, pgd=pgd, size=length, typ=BP.MEM_READ, func=f)
        bp.enable()
        gdb_breakpoint_list[bp_type][pgd][addr].append(bp)
        nb_breakpoints_added += 1

    return nb_breakpoints_added