Beispiel #1
0
// this function is called to process every breakpoint entry, so it should be as fast as possible.
void normal_break (DEBUG_EVENT *db)
{
    t_disassembly dis;
    DWORD         address;
    HANDLE        process;
    HANDLE        thread;
    node          *bp_node;
    bool          stalking = false;
    DWORD         tick_count;
    CONTEXT       context;
    LDT_ENTRY     selector_entry;
    DWORD         fs_base;
    DWORD         stack_top;
    DWORD         stack_bottom;

    tick_count = GetTickCount();
    address    = (DWORD)(db->u.Exception.ExceptionRecord.ExceptionAddress);
    thread     = dbg.FindThread((DWORD)db->dwThreadId)->hThread;
    process    = dbg.getProcessHandle();

    // bring the called function to the top of the list.
    //function_list = splay(address, function_list);

    // ensure the breakpoint lies in a module we are stalking.
    for (node *cursor = bp_modules; cursor != NULL; cursor = cursor->next)
    {
        if (address >= cursor->base && address <= cursor->base + cursor->size)
        {
                stalking = true;
                break;
        }
    }

    // if we're not stalking the current module, return now.
    if (!stalking)
        return;

    //
    // if we're recording, log the entry to the appropriate recorder file.
    //

    if (recorder_mode != NOT_RECORDING)
    {
        //function_list->recorded[recorder_mode]++;
        //printf("T:%04x [R%d] %08X %-25s [%5u] ", db->dwThreadId, recorder_mode, address, function_list->name, function_list->recorded[recorder_mode]);

        if (disassemble_flag)
            printf("%08x T:%08x [R%d] %08X ", tick_count, db->dwThreadId, recorder_mode, address);

        if ((bp_node = ps_node_find_by_address(address, bp_modules)) != NULL)
            fprintf(recorder, "%08x:%08x:%s:%08x:%08x\n", tick_count, db->dwThreadId, bp_node->name, bp_node->base, address - bp_node->base);
    }
    // else, not recording.
    else
    {
        if (disassemble_flag)
            printf("%08x T:%08x [bp] %08X ", tick_count, db->dwThreadId, address);
    }

    // if enabled, print the disassembly at the breakpoint address.
    if (disassemble_flag)
    {
        // XXX - wonder if there is any significant speed increase when we skip just the disassembly output.
        if (dbg.Disassemble(thread, address, &dis))
            printf("%s\n", dis.mnemonic.c_str());
        else
            printf("\n");
    }

    // if we are recording and register enumeration / dereferencing is enabled, process the registers we are interested in.
    if (recorder_mode != NOT_RECORDING && reg_enum_flag)
    {
        context.ContextFlags = CONTEXT_FULL;

        // get the thread context (containing the register values).
        if (GetThreadContext(thread, &context) == 0)
            return;

        // get the thread selector entry and calculate the 32-bit address for the FS register.
        if (GetThreadSelectorEntry(thread, context.SegFs, &selector_entry) == 0)
            return;

        fs_base = selector_entry.BaseLow + (selector_entry.HighWord.Bits.BaseMid << 16) + (selector_entry.HighWord.Bits.BaseHi << 24);
        
        // determine the top/bottom of the debuggee's stack.
        ReadProcessMemory(process, (void *)(fs_base + 4), &stack_top,    4, NULL);
        ReadProcessMemory(process, (void *)(fs_base + 8), &stack_bottom, 4, NULL);

        ps_analyze_register(process, tick_count, address, bp_node, stack_top, stack_bottom, context.Eax, "EAX");
        ps_analyze_register(process, tick_count, address, bp_node, stack_top, stack_bottom, context.Ebx, "EBX");
        ps_analyze_register(process, tick_count, address, bp_node, stack_top, stack_bottom, context.Ecx, "ECX");
        ps_analyze_register(process, tick_count, address, bp_node, stack_top, stack_bottom, context.Edx, "EDX");
        ps_analyze_register(process, tick_count, address, bp_node, stack_top, stack_bottom, context.Esi, "ESI");
        ps_analyze_register(process, tick_count, address, bp_node, stack_top, stack_bottom, context.Edi, "EDI");
    }

    // to restore the break point we just processed:
    //      - save the breakpoint address.
    //      - enable single stepping.
    //      - let the single step handler restore the breakpoint and disable single stepping.
    if (!dbg.one_time)
    {
        dbg.breakpoint_restore        = address;
        dbg.breakpoint_restore_thread = thread;
        dbg.SetSingleStep(thread, true);
    }
}
Beispiel #2
0
//////////////////////////////////////////////////////////////////////////////////////////////////////////
// callback functions
//
void initial_break (DEBUG_EVENT *db)
{
    char  line[256], module[128];
    DWORD f_offset, offset, base, size;
    int loaded = 0;
    node *bp_node;

    dbg.ActivateTraces();

    printf("initial break, tid = %04x.\n\n", dbg.FindThread( (DWORD)db->dwThreadId )->hThread);

    if (!dbg.get_thandle())
    {
        printf("manually setting thread handle.\n");
        dbg.set_thandle(dbg.FindThread( (DWORD)db->dwThreadId )->hThread);
    }

    // if an initial breakpoint list was provided, process it.
    if (bpl != NULL)
    {
        printf("loading breakpoints from %s\n", breakpoint_list);

        // process the breakpoint list line by line.
        for (int i = 0; fgets(line, sizeof(line), bpl) != NULL; i++)
        {
            // line format: module name:function offset:offset
            // ignore malformatted lines.
            if (sscanf(line, "%127[^:]:%08x:%08x", module, &f_offset, &offset) == 0)
                continue;
            
            // determine if this module already exists in our linked list.
            // if not attempt to locate the module in memory.
            if ((bp_node = ps_node_find_by_name(module, bp_modules)) == NULL)
            {
                // attempt to determine the module address / size.
                if (!ps_base_address(module, &base, &size))
                {
                    printf("failed locating base address for module %s\n", module);
                    continue;
                }

                // add a bp_node to the linked list.
                bp_node = (node *) malloc(sizeof(node));
                
                bp_node->base = base;
                bp_node->size = size;
                
                strncpy(bp_node->name, module, sizeof(bp_node->name) - 1);

                ps_node_add(bp_node, &bp_modules, &num_bp_modules);
            }

            // the '-25' means we want to reserve 25 left justified characters for the name.
            // the '.25' specifies that we want the string truncated after 25 characters.
            //printf("Setting breakpoint @%08x [%-25.25s] ... ", address, name);

            if (!dbg.bpx(bp_node->base + offset))
            {
                //printf("failed setting breakpoint @ 0x%08x\n", bp_node->base + offset);
                continue;
            }

            // at this point a breakpoint was successfully loaded.
            loaded++;

            if (i % 100 == 0)
                printf("setting breakpoint %d\r", i);

            // add function to splay tree.
            //if (offset == f_offset)
            //    function_list = splay_insert(address, name, function_list);
        }

        printf("done. %d of %d breakpoints set.\n", loaded, i);
        fclose(bpl);
    }
    // display the command menu.
    ps_commands();
}