zoukankan      html  css  js  c++  java
  • 【逆向知识】开发WinDBG扩展DLL

    如何开发WinDbg扩展DLL

    WinDbg扩展DLL是一组导出的回调函数,用于实现用户定义的命令。以便从内存转储中提取特定的信息。扩展dll由调试器引擎加载,可以在执行用户模式或内核模式调试时提供自动化任务的扩展功能。扩展DLL可以导出任意数量用于执行扩展命令的函数。每个函数都被显式地声明为DLL定义文件中的导出函数,.def文件和函数名必须是小写字母。

    ​ WinDbg(DbgEng)扩展DLL必须导出DebugExtensionInitialize。 这将在DLL加载时调用,以便于初始化DLL。 它可能被DLL用来初始化全局变量。

    ​ 扩展DLL导出的可选函数DebugExtensionUninitialize。如果导出这个函数,那么卸载扩展时将调用这个DebugExtensionUninitialize 函数。

    ​ 扩展DLL导出的DebugExtensionNotify函数。如果导出这个函数将会在会话开始或结束时调用,当目标开始或停止执行时。这些通知还提供给在客户端注册的IDebugEventCallbacks对象。

    ​ 扩展DLL可以导出KnownStructOutput。如果导出这个函数将会在加载DLL时调用它。该函数返回在一行上打印的结构列表。稍后可以调用它来格式化这些结构的实例以便打印。

    ​ 开发自己的Windbg扩展DLL,可以按照以下步骤:

    • 1.下载并安装Windows的调试工具

    http://www.microsoft.com/whdc/devtools/debugging/installx86.Mspx

    • 2.使用VS 2008创建“Win32 Console Application”
    • 3.选择应用程序类型为“DLL”,然后单击“完成”

    图1

    • 4.在项目中添加一个名为“wdbrowser”的“Module-Definition File (.def) ”。 导出扩展功能的一种方法是在.def文件的EXPORTS部分中指定函数名称。 也可以使用其他方式导出函数,如__dllexport

    图2

    • 5.将“Additional include Directories”配置为指向Windbg附带的头文件的目录。 x86的默认文件夹路径是“C:Program FilesDebugging Tools for Windows (x86)sdkinc”

      注:include Directories指include 目录

    • 6.将“Additional Library Directories” 配置为指向Windbg附带库文件的目录。x86库文件的默认文件夹路径是:"C:Program FilesDebugging Tools for Windows (x86)sdklibi386″

      注:Library Directories指Library 目录

    • 7.“dbgeng.lib ” & “dbgeng.dll” 具有实现调试引擎输出的功能。所以需要添加“dbgeng.lib ”到附加依赖项里

    • 8.添加在步骤#3中创建的模块定义文件名称“wdbrowser.def”

    • 9.在“stdafx.h”中包含以下所需的头文件

      #include <windows.h>
      #include <imagehlp.h>
      #include <wdbgexts.h>
      #include <dbgeng.h>
      #include <extsfns.h>
      
    • 10.声明以下两个全局变量

    //Version.
    EXT_API_VERSION g_ExtApiVersion = {1,1,EXT_API_VERSION_NUMBER,0} ;
    WINDBG_EXTENSION_APIS ExtensionApis = {0};
    
    • 11.声明以下调试引擎COM接口指针。
    IDebugAdvanced2*  gAdvancedDebug2=NULL;
    IDebugControl4*   gDebugControl4=NULL;
    IDebugControl*    gExecuteCmd=NULL;
    IDebugClient*                 gDebugClient=NULL;
    
    • 12.下一步是在DLL Main实现源文件中声明和实现WinDbgExtensionDllInit函数。 在这个例子中是“wdbrowser.cpp”。 WinDbgExntensionDllInit是第一个将被windbg调用的函数。 所以这个函数是空闲的,用于实现任何扩展特定的初始化或相关功能。

      有关此功能的更多详细信息,请参阅http://msdn.microsoft.com/en-us/library/cc267872.aspx。

    VOID WDBGAPI WinDbgExtensionDllInit (PWINDBG_EXTENSION_APIS lpExtensionApis, USHORT usMajorVersion, USHORT usMinorVersion)
    {
                      ExtensionApis = *lpExtensionApis;
                      HRESULT hResult = S_FALSE;
                            if (hResult = DebugCreate(__uuidof(IDebugClient), (void**) &gDebugClient) != S_OK)
                             {
                                                    dprintf(“Acuqiring IDebugClient* Failled
    
    ”);
                                                    return;
                             }
                             if (hResult = gDebugClient->QueryInterface(__uuidof(IDebugControl), (void**) &gExecuteCmd) != S_OK)
                             {
                                            dprintf(“Acuqiring IDebugControl* Failled
    
    ”);
                                                    return;
                             }
                             if (hResult = gDebugClient->QueryInterface(__uuidof(IDebugAdvanced2), (void**) &gAdvancedDebug2) != S_OK)
                             {
                                                  dprintf(“Acuqiring IDebugAdvanced2* Failled
    
    ”);
                                                    return;
                             }
                             if (hResult = gDebugClient->QueryInterface(__uuidof(IDebugControl4), (void**) &gDebugControl4) != S_OK)
                             {
                                dprintf(“Acuqiring IDebugControl4* Failled
    
    ”);
                                                    return;
                             }
    }
    
    
    • 13.声明另一个导出的函数ExtensionApiVersion,向windbg报告扩展版本。

      有关此函数的详细信息,请参见http://msdn.microsoft.com/en-us/library/cc267873.aspx。

    LPEXT_API_VERSION WDBGAPI ExtensionApiVersion (void)
    {
        return &g_ExtApiVersion;
    }
    
    • 14.定义调试引擎的接口指针,以便扩展模块可以与调试引擎交互。更多信息请参考
    http://msdn.microsoft.com/en-us/library/cc265976.aspx  – IDebugClient, http://msdn.microsoft.com/en-us/library/cc266102.aspx – IDebugControl
    http://msdn.microsoft.com/en-us/library/cc265957.aspx – IDebugAdvanced
    IDebugAdvanced2* gAdvancedDebug2=NULL;
    IDebugControl4* gDebugControl4=NULL;
    IDebugControl* gExecuteCmd=NULL;
    IDebugClient*               gDebugClient=NULL;
    
      1. 下一步是实现调试引擎的回调接口IDebugOutputCallbacks。调试引擎回调IDebugOutCallbacks::Output()的实现,输出扩展函数执行命令后的结果。
    有关idebugoutput回调的详细信息,请参见http://msdn.microsoft.com/en-us/library/cc265716.aspx::Output()
    
    • 16.在继承idebugoutputcallback接口的头文件中添加以下新类。
    #ifndef __OUT_HPP__
    #define __OUT_HPP__
    #include <string>
    #include <sstream>
    class StdioOutputCallbacks : public IDebugOutputCallbacks
    {
    private:
                            std::string m_OutputBuffer;
                            //
                            //This buffer holds the output from the command execution.
                            //
                            CHAR m_OutPutBuffer[4096];
    public:
                            void InitOutPutBuffer();
                            std::string GetOutputBuffer()
                            {
                                                    return m_OutputBuffer;
                            };
                            void ClearOutPutBuffer()              
                            {
                                                    m_OutputBuffer = “”;
                            };
        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__
    
    • 17.添加实现IDebugOutputCallbacks接口方法的代码,特别是Output()
    #include “stdafx.h”
    #include <stdio.h>
    #include <windows.h>
    #include <dbgeng.h>
    #include “OutputCallBack.h”
    StdioOutputCallbacks g_OutputCb;
    STDMETHODIMP
    StdioOutputCallbacks::QueryInterface(
        THIS_
        IN REFIID InterfaceId,
        OUT PVOID* Interface
        )
    {
        *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.
        return 0;
    }
    STDMETHODIMP
    StdioOutputCallbacks::Output(
        THIS_
        IN ULONG Mask,
        IN PCSTR Text
        )
    {
        UNREFERENCED_PARAMETER(Mask);
                            m_OutputBuffer += Text;
        return S_OK;
    }
    void StdioOutputCallbacks::InitOutPutBuffer()
    {
                            m_OutputBuffer.erase();
    }
    
    • 18.添加扩展函数的实现。在本例我们实现了一个扩展,该扩展显示当前线程第2帧中的变量名和类型。实现代码:
    DECLARE_API (dvf3)
    {
    //
    // Install output callbacks.
    //
    if ((gDebugClient->SetOutputCallbacks((PDEBUG_OUTPUT_CALLBACKS) &g_OutputCb))!= S_OK)
    {
    dprintf(“*****Error while installing Outputcallback.*****
    
    ”);
    return;
    }
    //
    // Since frame count starts from 0 index, we have to pass 2 as parameter for .frame command for the frame# 2
    //
    //Execute command to extrac 2nd frame.
    if (gExecuteCmd->Execute(DEBUG_OUTCTL_THIS_CLIENT | //Send output to only outputcallbacks
    DEBUG_OUTCTL_OVERRIDE_MASK |
    DEBUG_OUTCTL_NOT_LOGGED,
    “.frame 2”,
    DEBUG_EXECUTE_DEFAULT ) != S_OK)
    {
    dprintf(“Executing .frame 2 failled
    ”);
    return;
    }
    //Execute command to extrac 2nd frame.
    if (gExecuteCmd->Execute(DEBUG_OUTCTL_THIS_CLIENT | //Send output to only outputcallbacks
    DEBUG_OUTCTL_OVERRIDE_MASK |
    DEBUG_OUTCTL_NOT_LOGGED,
    “dv /i /t /v”,
    DEBUG_EXECUTE_DEFAULT ) != S_OK)
    {
    dprintf(“Executing dv /i /t /v failled
    ”);
    return;
    }
    dprintf(“***** Extracting locals & formal params from frame 2 *****”);
    dprintf(“
    %s
    ”, g_OutputCb.GetOutputBuffer().c_str());
    }
    
    
    • 19.重建项目。将. dll从发布文件夹中复制到Windbg查找扩展dll的文件夹中。
    在x86机器上,默认目录为“<Drive letter>Program Files debug Tools for Windows (x86)winext”。
    
    • 20.扩展已经准备好用于使用或测试。
    • 21.启动windbg并打开一个完整的用户模式转储。输入.load myextension和hit enter,将扩展DLL加载到Windbg进程空间中。

    • 22.运行.chain命令来验证是否由WinDbg加载扩展。如果扩展被加载,将看到类似于下面输出的内容。

    • 23.输入!dvf3以运行扩展函数,用于从框架2中提取和显示变量名。

  • 相关阅读:
    234. Palindrome Linked List
    Remove duplicates
    Unsorted, maximum ==> sorted
    Find one unique integer
    TwoSum
    13. Roman to Integer
    38. Count and Say
    543. Diameter of Binary Tree
    LuoguP1131 [ZJOI2007]时态同步 (树形DP,贪心)
    Luogu3177 [HAOI2015]树上染色 (树形DP)
  • 原文地址:https://www.cnblogs.com/17bdw/p/9209837.html
Copyright © 2011-2022 走看看