dmp文件自动分析

时间:2024-02-25 11:59:17

dmp文件的分析,可以借助各种工具,比如WinDbg, CDB , NTSD,KD等。Windbg提供了窗口接口,而CDB , NTSD是基于命令行的工具,它们都使用了同样的调试引擎Dbgeng.dll,该调试引擎就是 “Windows 调试程序”。

 

dbgeng.dll 可以在基于x86,x64 或ARM的处理器上运行,并且可以调试在那些相同体系结构上运行的代码。

 

dbgeng.dll 的使用:

 

out.hpp  
复制代码
#ifndef __OUT_HPP__
#define __OUT_HPP__

#include <DbgEng.h>

class StdioOutputCallbacks : public IDebugOutputCallbacks
{
public:
    // IUnknown.
    STDMETHOD(QueryInterface)(
        THIS_
        _In_ REFIID InterfaceId,
        _Out_ PVOID* Interface
        );
    STDMETHOD_(ULONG, AddRef)(
        THIS
        );
    STDMETHOD_(ULONG, Release)(
        THIS
        );

    // IDebugOutputCallbacks.
    STDMETHOD(Output)(
        THIS_
        _In_ ULONG Mask,
        _In_ PCSTR Text
        );
};

extern StdioOutputCallbacks g_OutputCb;

#endif // #ifndef __OUT_HPP__
复制代码
 
out.cpp
复制代码
#include <stdio.h>
#include <windows.h>
#include <dbgeng.h>
#include "out.hpp"

StdioOutputCallbacks g_OutputCb;
FILE *fp = NULL;

STDMETHODIMP
StdioOutputCallbacks::QueryInterface(
    THIS_
    _In_ REFIID InterfaceId,
    _Out_ PVOID* Interface
    )
{
    if (!fp) {
        fp = fopen("D:/ZZZ/analyze.txt", "w+");
    }

    *Interface = NULL;
    if (IsEqualIID(InterfaceId, __uuidof(IUnknown)) ||
        IsEqualIID(InterfaceId, __uuidof(IDebugOutputCallbacks)))
    {
        *Interface = (IDebugOutputCallbacks *)this;
        AddRef();
        return S_OK;
    }
    else
    {
        return E_NOINTERFACE;
    }
}

STDMETHODIMP_(ULONG)
StdioOutputCallbacks::AddRef(
    THIS
    )
{
    // This class is designed to be static so
    // there\'s no true refcount.
    return 1;
}

STDMETHODIMP_(ULONG)
StdioOutputCallbacks::Release(
    THIS
    )
{
    // This class is designed to be static so
    // there\'s no true refcount.
    //fclose(fp);
    return 0;
}

STDMETHODIMP
StdioOutputCallbacks::Output(
    THIS_
    _In_ ULONG Mask,
    _In_ PCSTR Text
    )
{
    UNREFERENCED_PARAMETER(Mask);
    //fputs(Text, fp);
    fputs(Text, stdout);
    return S_OK;
}
 
复制代码
main.cpp
复制代码

#include "out.hpp" #include <stdlib.h> #include <stdio.h> #include <stdarg.h>
#include <windows.h> #include <dbgeng.h>

PSTR g_DumpFile; IDebugClient* g_Client; IDebugControl* g_Control; IDebugSymbols3* g_Symbols3; void Exit(int Code, _In_ _Printf_format_string_ PCSTR Format, ...) { // Clean up any resources. if (g_Symbols3 != NULL) { g_Symbols3->Release(); } if (g_Control != NULL) { g_Control->Release(); } if (g_Client != NULL) { g_Client->SetOutputCallbacks(NULL); g_Client->EndSession(DEBUG_END_PASSIVE); g_Client->Release(); } // Output an error message if given. if (Format != NULL) { va_list Args; va_start(Args, Format); vfprintf(stderr, Format, Args); va_end(Args); } exit(Code); } void CreateInterfaces(void) { HRESULT Status; // Start things off by getting an initial interface from // the engine. This can be any engine interface but is // generally IDebugClient as the client interface is // where sessions are started. if ((Status = DebugCreate(__uuidof(IDebugClient), (void**)&g_Client)) != S_OK) { Exit(1, "DebugCreate failed, 0x%X\n", Status); } // Query for some other interfaces that we\'ll need. if ((Status = g_Client->QueryInterface(__uuidof(IDebugControl), (void**)&g_Control)) != S_OK || (Status = g_Client->QueryInterface(__uuidof(IDebugSymbols3), (void**)&g_Symbols3)) != S_OK) { Exit(1, "QueryInterface failed, 0x%X\n", Status); } } //typedef _Null_terminated_ CHAR *TTPSTR; void ParseCommandLine(int Argc, _In_reads_(Argc) PSTR* Argv) { int i; while (--Argc > 0) { Argv++; if (!strcmp(Argv[0], "-z")) { Argv++; Argc--; if (Argc > 0) { g_DumpFile = Argv[0]; } else { Exit(1, "-z missing argument\n"); } } else { //Exit(1, "Unknown command line argument \'%s\'\n", Argv[0]); } } if (g_DumpFile == NULL) { Exit(1, "No dump file specified, use -z <file>\n"); } } void ApplyCommandLineArguments(void) { HRESULT Status; // Install output callbacks so we get any output that the // later calls produce. if ((Status = g_Client->SetOutputCallbacks(&g_OutputCb)) != S_OK) { Exit(1, "SetOutputCallbacks failed, 0x%X\n", Status); } // Everything\'s set up so open the dump file. if ((Status = g_Client->OpenDumpFile(g_DumpFile)) != S_OK) { Exit(1, "OpenDumpFile failed, 0x%X\n", Status); } // Finish initialization by waiting for the event that // caused the dump. This will return immediately as the // dump file is considered to be at its event. if ((Status = g_Control->WaitForEvent(DEBUG_WAIT_DEFAULT, INFINITE)) != S_OK) { Exit(1, "WaitForEvent failed, 0x%X\n", Status); } // Everything is now initialized and we can make any // queries we want. } void DumpStack(void) { HRESULT Status; DEBUG_STACK_FRAME Frames[3] = { 0 }; ULONG Filled; g_Symbols3->SetScopeFromStoredEvent(); if (Frames == NULL) { Exit(1, "Unable to allocate stack frames\n"); } if ((Status = g_Control-> GetStackTrace(0, 0, 0, Frames, 3, &Filled)) != S_OK) { Exit(1, "GetStackTrace failed, 0x%X\n", Status); } printf("\nFirst %d frames of the call stack:\n", Filled); //// Print the call stack. if ((Status = g_Control-> OutputStackTrace(DEBUG_OUTCTL_ALL_CLIENTS, Frames, Filled, DEBUG_STACK_ARGUMENTS | DEBUG_STACK_SOURCE_LINE | DEBUG_STACK_FRAME_ADDRESSES | DEBUG_STACK_COLUMN_NAMES | DEBUG_STACK_FRAME_NUMBERS)) != S_OK) { Exit(1, "OutputStackTrace failed, 0x%X\n", Status); } } int main(int argc, char *argv[]) { CreateInterfaces(); ParseCommandLine(argc, argv); ApplyCommandLineArguments(); DumpStack(); return 0; }
复制代码