【逆向知识】开发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 Files\Debugging Tools for Windows (x86)\sdk\inc”
注:include Directories指include 目录
6.将“Additional Library Directories” 配置为指向Windbg附带库文件的目录。x86库文件的默认文件夹路径是:"C:\Program Files\Debugging Tools for Windows (x86)\sdk\lib\i386″
注: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\n\n”);
return;
}
if (hResult = gDebugClient->QueryInterface(__uuidof(IDebugControl), (void**) &gExecuteCmd) != S_OK)
{
dprintf(“Acuqiring IDebugControl* Failled\n\n”);
return;
}
if (hResult = gDebugClient->QueryInterface(__uuidof(IDebugAdvanced2), (void**) &gAdvancedDebug2) != S_OK)
{
dprintf(“Acuqiring IDebugAdvanced2* Failled\n\n”);
return;
}
if (hResult = gDebugClient->QueryInterface(__uuidof(IDebugControl4), (void**) &gDebugControl4) != S_OK)
{
dprintf(“Acuqiring IDebugControl4* Failled\n\n”);
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;
- 下一步是实现调试引擎的回调接口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.*****\n\n”);
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\n”);
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\n”);
return;
}
dprintf(“***** Extracting locals & formal params from frame 2 *****”);
dprintf(“\n%s\n”, 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中提取和显示变量名。

【逆向知识】开发WinDBG扩展DLL的更多相关文章
- windows下开发PHP扩展dll(无需Cygwin)
windows下开发php扩展网上很多资料都说需要Cygwin,其实完全可以不必安装该东东.没错,是可以在linux下生成骨架后拷到windos下来用,但是,如果没有linux环境呢?什么,装虚拟机? ...
- VS 2013驱动开发 + Windbg + VM双机调试(亲测+详解)
------------VS 2013驱动开发 + Windbg + VM双机调试(亲测+详解)------------- WIN10已上线,随之而来的是VS2015:微软在 "WDK760 ...
- 手把手教你开发chrome扩展一:开发Chrome Extenstion其实很简单
手把手教你开发chrome扩展一:开发Chrome Extenstion其实很简单 手把手教你开发chrome扩展一:开发Chrome Extenstion其实很简单 手把手教你开发Chrome扩 ...
- php 扩展dll
一.准备工作: 注:php5.2没有vc9,php5.3.php5.4没有vc6.呵呵.PHP5.5开始,不支持xp和win2003了,更是vc11了.--------------->所以,扩展 ...
- Windbg扩展的一些参考文章
Windbg脚本和扩展工具开篇http://www.cnblogs.com/pugang/archive/2012/11/30/2796617.html WinDbg简单扩展DLL http://ww ...
- 逆向知识之CS辅助/外挂专题.2.实现CS1.6透视原理
逆向知识之CS辅助/外挂专题.2.实现CS1.6透视原理 一丶透视简介 我们涉及到FPS游戏.免不了说透视.自瞄什么的. 在CS1.6中. 有OpenGl.也有D3D. 透视的方法很多. gl透视(也 ...
- 手把手教你开发chrome扩展
转载:http://www.cnblogs.com/walkingp/archive/2011/04/04/2003875.html 手把手教你开发chrome扩展一:开发Chrome Extenst ...
- 手把手教你开发Chrome扩展三:关于本地存储数据
手把手教你开发chrome扩展一:开发Chrome Extenstion其实很简单 手把手教你开发Chrome扩展二:为html添加行为 手把手教你开发Chrome扩展三:关于本地存储数据 HTML5 ...
- 手把手教你开发Chrome扩展二:为html添加行为
手把手教你开发chrome扩展一:开发Chrome Extenstion其实很简单 手把手教你开发Chrome扩展二:为html添加行为 手把手教你开发Chrome扩展三:关于本地存储数据 上一节我们 ...
随机推荐
- jmete JSR223 PostProcessor使用
1.使用xpath Extractor提取页面值 2.使用 JSR223 PostProcessor拼接json数据 function genJsons() { var MaterialName = ...
- P4867 Gty的二逼妹子序列
题目描述 Autumn和Bakser又在研究Gty的妹子序列了!但他们遇到了一个难题. 对于一段妹子们,他们想让你帮忙求出这之内美丽度∈[a,b]的妹子的美丽度的种类数. 为了方便,我们规定妹子们的美 ...
- R2学习记录
Setting up the Libevent library1.重写log行为 #include <event2/event.h> #include <stdio.h> st ...
- 【UOJ228】基础数据结构练习题(线段树)
[UOJ228]基础数据结构练习题(线段树) 题面 UOJ 题解 我们来看看怎么开根? 如果区间所有值都相等怎么办? 显然可以直接开根 如果\(max-sqrt(max)=min-sqrt(min)\ ...
- 【ZJOI 2018】线图(树的枚举,hash,dp)
线图 题目描述 九条可怜是一个热爱出题的女孩子. 今天可怜想要出一道和图论相关的题.在一张无向图 $G$ 上,我们可以对它进行一些非常有趣的变换,比如说对偶,又或者说取补.这样的操作往往可以赋予一些传 ...
- 洛谷 P1777 帮助_NOI导刊2010提高(03) 解题报告
P1777 帮助_NOI导刊2010提高(03) 题目描述 Bubu的书架乱成一团了!帮他一下吧! 他的书架上一共有n本书.我们定义混乱值是连续相同高度书本的段数.例如,如果书的高度是30,30,31 ...
- BRIEF特征点描述子
简介 BRIEF是2010年的一篇名为<BRIEF:Binary Robust Independent Elementary Features>的文章中提出,BRIEF是对已检测到的特征点 ...
- java反射获取class
- 数据中有NA存在,处理办法
如果数据中有NA存在,表示这个位置数据遗失,不能进行值的类型描述.也不能用函数来计算,需要计算是可以加上na.rm=T表示忽略NA,但是这个位置并没有去除,使用length可以看到. > x&l ...
- NATS_01:NATS基础介绍
1.介绍 NATS(Message bus): 从CloudFoundry的总架构图看,位于各模块中心位置的是一个叫nats的组件.NATS是由CloudFoundry的架构师Derek开发的一个开源 ...