[转帖]WinDbg插件编写——基础篇

导读:
  一.插件的类型
  他有两种不同类型的DLL文件:
  1.DbgEng类型DLL。这种类型的DLL都已“dbgeng.h” 头文件为基础。扩展命令的功能比较强大,可以用Debugger Engine API(这种调试API不依赖WinDbg,可以用来编写自己的调试器),也可以用WdbgExts API。
  2.WdbgExts类型DLL。这种类型的DLL以“Wdbgexts.h” 头文件为基础,它只能用WdbgExts API.
  二.两种插件的编写方法。
  一般来说编写一个扩展命令需要四个文件:.c/c++文件,.def文件,sources文件和makefile文件,和写一般DLL文件一样。下面主要讲c/c++文件和def文件,应为他们在两种类型的DLL中差异比较大。
  1.DbgEng类型。
  (1) c/c++文件,可以用dbgeng.h标准的C++代码调试接口也可以用wdbgexts.h中的c代码接口。如果在这个类型中用wdbgexts API,需要用到wdbgexts.h和KDEXT_64BIT宏,如:
  #define KDEXT_64BIT
  #include wdbgexts.h
  #include dbgeng.h
  这个文件主要依据dbgeng.h和wdbgexts.h中的调试接口函数实现特定功能的函数代码。第一行主要是编译64位的,两个头文件中的函数都有32和64位,如ReadIoSpace64和ReadIoSpace,你可以在这种类型的扩展中完全用64位的函数,既可以在64位cpu也可以在32为cpu 运行。
  (2)def文件,定义导出函数和自己的扩展命令
  DebugExtensionInitialize函数必须导出,当DLL被加载时用来初始化全局变量。其他的根据实际情况而定。
  2.WdbgExts类型
  这种类型扩展的功能比上一种来说差一些,但一般情况下也能完成很多任务。
  (1)C文件。
  I.只能用wdbgexts.h中的c接口,如果用64位,简单的包含
  #define KDEXT_64BIT
  #include wdbgexts.h
  只是编译32位的话,就无需包含第一句。
  II.必须用DECLARE_API宏
  这个宏定义在wdbgexts.h中,
  #define DECLARE_API(s) /
  CPPMOD VOID /
  s( /
  HANDLE hCurrentProcess, /
  HANDLE hCurrentThread, /
  ULONG64 dwCurrentPc, /
  ULONG dwProcessor, /
  PCSTR args /
  )
  如果是32位dwCurrentPc的类型就要换成ULONG.
  (2)def文件
  必须输出WinDbgExtensionDllInit.和ExtensionApiVersion两个函数。
  三.编译
  1.需要Windows Driver Kit(WDK),必须在windows 2003 server build environment环境下。
  2.设置DBGSDK_INC_PATH和DBGSDK_LIB_PATH环境变量。
  3.切换到你的原文件目录下
  4.执行build –cZMg
  四.加载
  把编译出的含DLL的文件夹放到WinDbg安装目录下,运行WinDbg后用.load dllname 就可以了。然后就尽情的享受你自己编写的命令把。
  *********************************************************************
  实例:
  下来用一个主要是以wdbgexts.h API调试接口的例子。这个dll文件主要是自己实现read(读指定地址值),
  edit(编辑指定地址的值),stack(取得堆栈值),help(显示以上三个命令的帮助信息).
  (1)编写simple.c文件
  (2)编写simple.def文件
  (3)编写sources文件
  (4)编写makefile文件
  (5)编写rc资源文件
  (6)编译并产生simple.dll
  (7)加载并执行自己的扩展命令
  **********************************************************************
  CODE:[Copy to clipboard](1)c文件
  //
  //头文件和宏定义
  #include
  #include "simple.h"
  #define KDEXT_64BIT
  #include
  #include
  //
  // 全局变量
  //
  EXT_API_VERSION ApiVersion = { (VER_PRODUCTVERSION_W >>8), (VER_PRODUCTVERSION_W &0xff), EXT_API_VERSION_NUMBER64, 0 };
  WINDBG_EXTENSION_APIS ExtensionApis;
  ULONG SavedMajorVersion;
  ULONG SavedMinorVersion;
  //
  //主程序
  //
  DllInit(
  HANDLE hModule,
  DWORD dwReason,
  DWORD dwReserved
  )
  {
  switch (dwReason) {
  case DLL_THREAD_ATTACH:
  break;
  case DLL_THREAD_DETACH:
  break;
  case DLL_PROCESS_DETACH:
  break;
  case DLL_PROCESS_ATTACH:
  break;
  }
  return TRUE;
  }
  VOID
  WinDbgExtensionDllInit(
  PWINDBG_EXTENSION_APIS lpExtensionApis,
  USHORT MajorVersion,
  USHORT MinorVersion
  )
  {
  ExtensionApis = *lpExtensionApis;
  SavedMajorVersion = MajorVersion;
  SavedMinorVersion = MinorVersion;
  return;
  }
  LPEXT_API_VERSION
  ExtensionApiVersion(
  VOID
  )
  {
  
  return &ApiVersion;
  }
  VOID
  CheckVersion(
  VOID
  )
  {
  return;
  }
  //
  // 读目标双字值
  //
  DECLARE_API( read )
  {
  ULONG cb;
  ULONG64 Address;
  ULONG Buffer[4];
  Address = GetExpression(args);
  
  if (ReadMemory(Address, &Buffer, sizeof(Buffer), &cb) &&cb == sizeof(Buffer)) {
  dprintf("%I64lx: %08lx %08lx %08lx %08lx/n/n", Address,
  Buffer[0], Buffer[1], Buffer[2], Buffer[3]);
  }
  }
  //
  // 编辑目标的双字值
  //
  // !edit

  //
  DECLARE_API( edit )
  {
  ULONG cb;
  ULONG64 Address;
  ULONG Value;
  if (GetExpressionEx(args, &Address, &args)) {
  Value = (ULONG) GetExpression( args);
  } else {
  dprintf("Usage: !edit
/n");
  return;
  }
  
  if (WriteMemory(Address, &Value, sizeof(Value), &cb) &&cb == sizeof(Value)) {
  dprintf("%I64lx: %08lx/n", Address, Value);
  }
  }
  //
  // 提取堆栈值
  //
  DECLARE_API ( stack )
  {
  EXTSTACKTRACE64 stk[20];
  ULONG frames, i;
  CHAR Buffer[256];
  ULONG64 displacement;
  // 在当前线程中获得堆栈祯值
  frames = StackTrace( 0, 0, 0, stk, 20 );
  if (!frames) {
  dprintf("Stacktrace failed/n");
  }
  for (i=0; i
  if (i==0) {
  dprintf( "ChildEBP RetAddr Args to Child/n" );
  }
  Buffer[0] = '!';
  GetSymbol(stk.ProgramCounter, (PUCHAR)Buffer, &displacement);
  
  dprintf( "%08p %08p %08p %08p %08p %s",
  stk.FramePointer,
  stk.ReturnAddress,
  stk.Args[0],
  stk.Args[1],
  stk.Args[2],
  Buffer
  );
  if (displacement) {
  dprintf( "+0x%p", displacement );
  }
  dprintf( "/n" );
  }
  }
  /*
  编写help扩展命令
  */
  DECLARE_API ( help )
  {
  dprintf("Help for extension dll simple.dll/n"
  "read
/n? dwords 4 dumps and reads It ->  "edit - It modifies a dword value to at /n"
  "stack - Printd current stack trace/n"
  "help - Shows this help/n"
  );
  }
  **********************************************************************
  (2)def文件
  --------------------------------------------------------------------
  
  Module:
  simple.def
  --------------------------------------------------------------------
  EXPORTS
  --------------------------------------------------------------------
  These are the extensions exported by dll
  --------------------------------------------------------------------
  read
  edit
  help
  stack
  --------------------------------------------------------------------
  these are the extension service functions provided for the debugger
  --------------------------------------------------------------------
  CheckVersion
  WinDbgExtensionDllInit
  ExtensionApiVersion
  **********************************************************************
  (3)source文件
  TARGETNAME=simple
  TARGETPATH=obj
  TARGETTYPE=DYNLINK
  DLLENTRY=_DllMainCRTStartup
  !if "$(DBGSDK_INC_PATH)" != ""
  INCLUDES = $(DBGSDK_INC_PATH);$(INCLUDES)
  !endif
  !if "$(DBGSDK_LIB_PATH)" == ""
  DBGSDK_LIB_PATH = $(SDK_LIB_PATH)
  !else
  DBGSDK_LIB_PATH = $(DBGSDK_LIB_PATH)/$(TARGET_DIRECTORY)
  !endif
  TARGETLIBS=$(SDK_LIB_PATH)/kernel32.lib
  USE_MSVCRT=1
  UMTYPE=windows
  SOURCES= simple.c /
  simple.rc
  **********************************************************************
  (4)makefile文件
  #
  # DO NOT EDIT THIS FILE!!! Edit ./sources. if you want to add a new source
  # file to this component. This file merely indirects to the real make file
  # that is shared by all the components of Windows
  #
  !INCLUDE $(NTMAKEENV)/makefile.def
  **********************************************************************
  (5)rc文件
  #include
  #include
  #define VER_FILETYPE VFT_DLL
  #define VER_FILESUBTYPE VFT2_UNKNOWN
  #define VER_FILEDESCRIPTION_STR "Sample Debugger Extensions"
  #define VER_INTERNALNAME_STR "simple.DLL"
  #define VER_ORIGINALFILENAME_STR "simple.DLL"
  #include "common.ver"
  **********************************************************************
  (6)编译并产生simple.dll
  i.切换到windows server 2003 ddk编译环境
  ii.设置windbg sdk环境变量
  set DBGSDK_INC_PATH=%debuggers%/sdk/inc
  set DBGSDK_LIB_PATH=%debuggers%/sdk/lib
  %debuggers%要换成你自己的目录
  iii.切换到包含源文件的文件夹,并执行build -cZMg
  **********************************************************************
  (7)加载并执行
  .load %debuggers%/simple
  然后就可以执行我们的扩展命令。
  后记:最新版的windbg 6.6.00007.5的安装时,要选择Custom,然后手工把SDK选中才会把SDK安装上。而且关于扩展命令编写的详细方法也集成到了帮助文档中。用Windbg还可以写.net调试命令扩展,如sos.dll,这一点是其他调试器所不具备的吧。
  自:BBs.77169.com

本文转自
http://bbs.77169.com/read.php?tid=179562
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值