Example #1
0
/*
  This gets called (by DebugExtensionNotify whentarget is halted and is accessible
*/
HRESULT
NotifyOnTargetAccessible(PDEBUG_CONTROL Control)
{
    dprintf("Extension dll detected a break");
    if (Connected) {
        dprintf(" connected to ");
        switch (TargetMachine) {
        case IMAGE_FILE_MACHINE_I386:
            dprintf("X86");
            break;
        case IMAGE_FILE_MACHINE_IA64:
            dprintf("IA64");
            break;
        default:
            dprintf("Other");
            break;
        }
    }
    dprintf("\n");

    //
    // show the top frame and execute dv to dump the locals here and return
    //
    Control->Execute(DEBUG_OUTCTL_ALL_CLIENTS |
                     DEBUG_OUTCTL_OVERRIDE_MASK |
                     DEBUG_OUTCTL_NOT_LOGGED,
                     ".frame", // Command to be executed
                     DEBUG_EXECUTE_DEFAULT );
    Control->Execute(DEBUG_OUTCTL_ALL_CLIENTS |
                     DEBUG_OUTCTL_OVERRIDE_MASK |
                     DEBUG_OUTCTL_NOT_LOGGED,
                     "dv", // Command to be executed
                     DEBUG_EXECUTE_DEFAULT );
    return S_OK;
}
Example #2
0
HRESULT
ExecCmdList(PCSTR cmd)
{
    HRESULT hRes=S_OK;
    ULONG Status;
    char *ptr, *orig, *end;

    ptr = orig = (char *)cmd;
    end = ptr+strlen(cmd);

    while(cmd < end)
    {
        ptr = (char *) strchr(cmd, 0xA);
        if( ptr != NULL)
            *ptr = 0;
        else
            break;

        // msdn: Executes the specified debugger commands.
        hRes=g_ExtControl->Execute(DEBUG_OUTCTL_ALL_CLIENTS, cmd, DEBUG_EXECUTE_ECHO|DEBUG_EXECUTE_NO_REPEAT);

        // msdn: Describes the nature of the current target.
        hRes=g_ExtControl->GetExecutionStatus(&Status);
        if (FAILED(hRes))
            break;

        // Drop commands if the target is not paused
        if (!(Status==DEBUG_STATUS_BREAK))
            break;

        cmd= ptr+1;
    }

    return hRes;
}
Example #3
0
// Poll socket for incoming commands
HRESULT
PollCmd()
{
    HRESULT hRes=S_OK;
    int NbBytesRecvd = 0;
    int ch = 0xA;
    char *msg, *next, *orig = NULL;

    hRes=TunnelPoll(&NbBytesRecvd, &msg);
    if (SUCCEEDED(hRes) & (NbBytesRecvd>0) & (msg != NULL))
    {
        next = orig = msg;

        while((msg-orig) < NbBytesRecvd)
        {
            next = strchr(msg, ch);
            if( next != NULL)
                *next = 0;

            hRes=g_ExtControl->Execute(DEBUG_OUTCTL_ALL_CLIENTS, msg, DEBUG_EXECUTE_ECHO);
            if (FAILED(hRes))
                dprintf("[sync] failed to execute received command\n", msg);

            // No more command
            if( next == NULL)
                break;

            msg = next+1;
        }

        free(orig);
    }

    return hRes;
}
Example #4
0
void ExtExec(PCSTR Command)
{
    g_Control->Execute(
        DEBUG_OUTCTL_ALL_CLIENTS | DEBUG_OUTCTL_AMBIENT_DML, 
        Command, DEBUG_EXECUTE_DEFAULT
    );
}
Example #5
0
HRESULT
CALLBACK
cmd(PDEBUG_CLIENT4 Client, PCSTR Args)
{
    HRESULT hRes=S_OK;
    ULONG Flags;
    PDEBUG_OUTPUT_CALLBACKS Callbacks;
    INIT_API();

    #if VERBOSE >= 2
    dprintf("[sync] !cmd command called\n");
    #endif

    if (!Args || !*Args) {
        dprintf("[sync] !cmd <command to execute and dump>\n");
        return E_FAIL;
    }

    if (FAILED(hRes=g_ExtClient->GetOutputCallbacks(&Callbacks)))
    {
        dprintf("[sync] GetOutputCallbacks failed\n");
        goto exit;
    }

    if (FAILED(hRes=g_ExtClient->SetOutputCallbacks(&g_OutputCb)))
    {
        dprintf("[sync] SetOutputCallbacks failed\n");
        goto exit;
    }

    // msdn: Execute method executes the specified debugger commands.
    Flags = DEBUG_EXECUTE_ECHO;

    if (g_OutputCbLocal)
        Flags = DEBUG_EXECUTE_NOT_LOGGED;

    hRes=g_ExtControl->Execute(DEBUG_OUTCTL_ALL_CLIENTS, Args, Flags);

    g_ExtClient->FlushCallbacks();
    g_ExtClient->SetOutputCallbacks(Callbacks);

    #if VERBOSE >= 2
    dprintf("[sync] OutputCallbacks removed\n");
    #endif

exit:
    return hRes;
}
Example #6
0
HRESULT CALLBACK testext(PDEBUG_CLIENT4 Client, PCSTR args)
{
    PDEBUG_OUTPUT_CALLBACKS prev;
    PDEBUG_CONTROL Control;
    char cmd[256];

    sprintf(cmd, "!E:\\talk\\demo\\Debug\\dbgexts.plusplus %s", args);

    Client->GetOutputCallbacks(&prev);
    Client->SetOutputCallbacks(&g_OutputCb);
    Client->QueryInterface(__uuidof(IDebugControl), (void **)&Control);
    Control->Execute(DEBUG_OUTCTL_ALL_CLIENTS |
                     DEBUG_OUTCTL_OVERRIDE_MASK |
                     DEBUG_OUTCTL_NOT_LOGGED,
                     cmd, // Command to be executed
                     DEBUG_EXECUTE_DEFAULT );
    Control->Release();
    Client->SetOutputCallbacks(prev);

    return S_OK;
}
Example #7
0
HRESULT
CALLBACK
DebugExtensionInitialize(PULONG Version, PULONG Flags)
{
    IDebugClient *DebugClient;
    PDEBUG_CONTROL DebugControl;
    HRESULT Hr;

    *Version = DEBUG_EXTENSION_VERSION(1, 0);
    *Flags = 0;

    if (g_Initialized)
    {
        return S_OK;
    }
    g_Initialized = true;

    if ((Hr = DebugCreate(__uuidof(IDebugClient),
                          (void **)&DebugClient)) != S_OK)
    {
        return Hr;
    }
    if ((Hr = DebugClient->QueryInterface(__uuidof(IDebugControl),
                                              (void **)&DebugControl)) != S_OK)
    {
        return Hr;
    }

    ExtensionApis.nSize = sizeof (ExtensionApis);
    if ((Hr = DebugControl->GetWindbgExtensionApis64(&ExtensionApis)) != S_OK)
    {
        return Hr;
    }
    
    // Fixes the "Unable to read dynamic function table entries" error messages by disabling the WinDbg security
    // feature that prevents the loading of unknown out of proc tack walkers.
    DebugControl->Execute(DEBUG_OUTCTL_IGNORE, ".settings set EngineInitialization.VerifyFunctionTableCallbacks=false", 
        DEBUG_EXECUTE_NOT_LOGGED | DEBUG_EXECUTE_NO_REPEAT);

    ExtQuery(DebugClient);
    if (IsMiniDumpFileNODAC())
    {
        ExtOut (
            "----------------------------------------------------------------------------\n"
            "The user dump currently examined is a minidump. Consequently, only a subset\n"
            "of sos.dll functionality will be available. If needed, attaching to the live\n"
            "process or debugging a full dump will allow access to sos.dll's full feature\n"
            "set.\n"
            "To create a full user dump use the command: .dump /ma <filename>\n"
            "----------------------------------------------------------------------------\n");
    }
    ExtRelease();
    
    OnUnloadTask::Register(CleanupEventCallbacks);
    g_pCallbacksClient = DebugClient;
    EventCallbacks* pCallbacksObj = new EventCallbacks(DebugClient);
    IDebugEventCallbacks* pCallbacks = NULL;
    pCallbacksObj->QueryInterface(__uuidof(IDebugEventCallbacks), (void**)&pCallbacks);
    pCallbacksObj->Release();

    if(FAILED(Hr = g_pCallbacksClient->SetEventCallbacks(pCallbacks)))
    {
        ExtOut ("SOS: Failed to register callback events\n");
        pCallbacks->Release();
        return Hr;
    }
    pCallbacks->Release();

#ifndef _ARM_
    // Make sure we do not tear down the debugger when a security function fails
    // Since we link statically against CRT this will only affect the SOS module.
    _set_invalid_parameter_handler(_SOS_invalid_parameter);
#endif
    
    DebugControl->Release();
    return S_OK;
}
Example #8
0
STDMETHODIMP
EventCallbacks::Exception(
    THIS_
    IN PEXCEPTION_RECORD64 Exception,
    IN ULONG FirstChance)
{    
    g_ResumeState = FALSE;

    if (Exception->ExceptionCode == STATUS_BREAKPOINT)
    {
        if (FirstChance)
        {
            DEBUG_VALUE Reg, Ecx, Edx;            

            // Query EIP, EAX and ECX value.
            if (g_Registers->GetValue(g_EipIndex, &Reg) == S_OK &&
                g_Registers->GetValue(g_EdxIndex, &Edx) == S_OK &&
                g_Registers->GetValue(g_EcxIndex, &Ecx) == S_OK)
            {
                char szParam[MAX_PATH];
                ULONG ReadedBytes = 0;

                // Read current instruction opcode value.
                ZeroMemory(szParam, sizeof(szParam));
                HRESULT Hr = g_DataSpaces->ReadVirtual(RegPtrGet(&Reg), &szParam, 1, &ReadedBytes);                
                if (Hr != S_OK)
                {
                    ExtErr(__FUNCTION__"() ERROR: IDebugDataSpaces::ReadVirtual() fails: %lx\n", Hr);
                    return DEBUG_STATUS_NO_CHANGE;
                }

                // Check for int 3 at EIP.
                if (szParam[0] != '\xCC')
                {
                    return DEBUG_STATUS_NO_CHANGE;
                }

                // Check for the magic engine constnat in EDX.
                if (Edx.I32 != DBGCB_GET_SYMBOL &&
                    Edx.I32 != DBGCB_EXECUTE &&
                    Edx.I32 != DBGCB_FIELD_OFFSET)
                {
                    return DEBUG_STATUS_NO_CHANGE;
                }
                
                g_ResumeState = TRUE;                

                // Read ASCII string with command arguments.
                ZeroMemory(szParam, sizeof(szParam));
                Hr = g_DataSpaces->ReadVirtual(RegPtrGet(&Ecx), &szParam, sizeof(szParam), &ReadedBytes);
                if (Hr != S_OK)
                {
                    ExtErr(__FUNCTION__"() ERROR: IDebugDataSpaces::ReadVirtual() fails: %lx\n", Hr);
                    return DEBUG_STATUS_NO_CHANGE;
                }

                switch (Edx.I32)
                {
                case DBGCB_GET_SYMBOL:
                    {
                        ExtOut("<col fg=\"srccmnt\">" __FUNCTION__"(): DBGCB_GET_SYMBOL \"%s\"</col>\n", szParam);

                        RegPtrSet(&Reg, 0);
                        g_Registers->SetValue(g_EaxIndex, &Reg);

                        Hr = g_Control->Evaluate(szParam, g_RegPtrType, &Reg, NULL);
                        if (Hr == S_OK)
                        {
                            // Return symbol address in EAX.
                            g_Registers->SetValue(g_EaxIndex, &Reg);
                        }
                        else
                        {
                            ExtErr(__FUNCTION__"() WARNING: IDebugControl::Evaluate() fails: %lx\n", Hr);
                        }

                        break;
                    }                                 

                case DBGCB_EXECUTE:
                    {
                        ExtOut("<col fg=\"srccmnt\">" __FUNCTION__ "(): DBGCB_EXECUTE</col>\n");

                        // execute debugger command
                        Hr = g_Control->Execute(
                            DEBUG_OUTCTL_ALL_CLIENTS | DEBUG_OUTCTL_AMBIENT_DML, 
                            szParam, 
                            DEBUG_EXECUTE_DEFAULT
                        );
                        if (Hr == S_OK)
                        {
                            // Return TRUE in EAX
                            RegPtrSet(&Reg, 1);
                            g_Registers->SetValue(g_EaxIndex, &Reg);
                        }
                        else
                        {
                            ExtErr(__FUNCTION__"() WARNING: IDebugControl::Execute() fails: %lx\n", Hr);
                        }

                        break;
                    }                    

                case DBGCB_FIELD_OFFSET:
                    {
                        RegPtrSet(&Reg, (ULONG64)-1);

                        char *lpszModule = szParam, *lpszStruct = NULL, *lpszField = NULL;

                        ExtOut("<col fg=\"srccmnt\">" __FUNCTION__"(): DBGCB_FIELD_OFFSET \"%s\"</col>\n", szParam);

                        // parse structure and field description string
                        if (lpszStruct = strstr(lpszModule, "!"))
                        {
                            *lpszStruct = '\x00';
                            lpszStruct += 1;

                            if (lpszField = strstr(lpszStruct, "::"))
                            {
                                *lpszField = '\x00';
                                lpszField += 2;
                            }
                        }                        

                        if (lpszStruct && lpszField)
                        {
                            // enumerate fields
                            for (ULONG i = 0; ;i++) 
                            {   
                                ULONG64 Module = 0;
                                ULONG TypeId = 0;    

                                // get ID of this symbol
                                Hr = g_Symbols->GetSymbolTypeId(lpszStruct, &TypeId, &Module);
                                if (Hr == S_OK) 
                                {
                                    char szFieldName[MAX_PATH];

                                    // query name of the filed
                                    HRESULT Hr = g_Symbols->GetFieldName(Module, TypeId, i, szFieldName, MAX_PATH, NULL);
                                    if (Hr == S_OK) 
                                    {
                                        ULONG Offset = 0, FieldTypeId = 0;

                                        // query filed type and offset
                                        Hr = g_Symbols->GetFieldTypeAndOffset(Module, TypeId, szFieldName, &FieldTypeId, &Offset);                                   
                                        if (Hr == S_OK)
                                        {
                                            if (!strcmp(szFieldName, lpszField))
                                            {
                                                // Return symbol offset in EAX
                                                RegPtrSet(&Reg, (ULONG64)Offset);                                                
                                                break;
                                            }
                                        }            
                                        else 
                                        {
                                            ExtErr(__FUNCTION__"() WARNING: IDebugSymbols3::GetFieldTypeAndOffset() fails: %lx\n", Hr);
                                        }
                                    } 
                                    else if (Hr == E_INVALIDARG) 
                                    {
                                        // All Fields done
                                        break;
                                    } 
                                    else 
                                    {
                                        ExtErr(__FUNCTION__"() WARNING: IDebugSymbols3::GetFieldName() fails: %lx\n", Hr);
                                    }
                                }
                                else
                                {
                                    ExtErr(__FUNCTION__"() WARNING: IDebugSymbols3::GetSymbolTypeId() fails: %lx\n", Hr);
                                }                                
                            }
                        }
                        else
                        {
                            ExtErr(__FUNCTION__"() WARNING: Bad name format (must be <module>!<struct_name>::<field_name>)\n");
                        }

                        g_Registers->SetValue(g_EaxIndex, &Reg);

                        break;
                    }                    

                default:

                    return DEBUG_STATUS_NO_CHANGE;
                }

                // Skip current int 3 instruction and continue execution
                if (g_Registers->GetValue(g_EipIndex, &Reg) == S_OK && Reg.Type == DEBUG_VALUE_INT32)
                {
                    if (g_bIs64)
                    {
                        Reg.I64 += 1;
                    }
                    else
                    {
                        Reg.I32 += 1;
                    }

                    g_Registers->SetValue(g_EipIndex, &Reg);                    
                }                 

                return DEBUG_STATUS_GO_HANDLED;
            }                      
        }
    }    

    return DEBUG_STATUS_NO_CHANGE;
}