标题: MSDN系列(11)--给SoftICE写插件
创建: 2004-03-30 20:17 更新: 2004-04-05 15:10 链接: https://scz.617.cn/windows/200406031438.txt
目录:
☆ 背景
☆ 最终可用的SoftICE插件
1) 编写PrivateExt.c文件
2) 编写PrivateExt.def文件
3) 编写sources文件
4) 编写makefile文件
5) 编译产生PrivateExt.dll文件
6) 测试windbg插件PrivateExt.dll
7) 转换并测试SoftICE插件PrivateExt.sys
☆ windbg插件转SoftICE插件友情提示
☆ 参考资源
☆ 背景
一般打开faults on,触发异常时可以用stack命令查看调用栈回溯。可是在异常处理 过程中再次触发异常,faults on就无能为力了。此时设置如下断点:
bpx ntdll!KiUserExceptionDispatcher do "dd (esp)+c L10;dd ((esp+4))+8c L40"
对照CONTEXT结构:
+0x08c SegGs +0x090 SegFs +0x094 SegEs +0x098 SegDs +0x09c Edi +0x0a0 Esi +0x0a4 Ebx +0x0a8 Edx +0x0ac Ecx +0x0b0 Eax +0x0b4 Ebp +0x0b8 Eip +0x0bc SegCs +0x0c0 EFlags +0x0c4 Esp +0x0c8 SegSs
用命令"stack SS:EBP"查看调用栈回溯即可。但每次都要对照CONTEXT结构,很不爽, 而SoftICE又没有windbg的"dt -v nt!_CONTEXT"命令可用,因此想写一个SoftICE的 插件。
官方解决办法只有将windbg插件转成SoftICE插件这一条路可走,毕竟KD2SYS是自带 工具。非官方解决办法估计得参考IceExt的源代码([7]),暂时没精力做这件事。
☆ 最终可用的SoftICE插件
1) 编写PrivateExt.c文件
hume同学成功地实现了SoftICE插件,区别在于编写PrivateExt.c时不要考虑64-bit 可移植性。
wdbgexts.h中PWINDBG_CHECK_VERSION的函数原型与CheckVersion不相符,但几乎所 有的(官方的、非官方的)例子中返回值都是VOID,所以我也采用之。由于该函数可选, 如果有顾虑,可以不实现CheckVersion()。
6.3版windbg开始携带debugext.chm文件,开始介绍WINDBG_EXTENSION_APIS的用法。
/ * Copyright (C) 2002, 2012 * The NSFOCUS INFORMATION TECHNOLOGY CO.,LTD. * ----------------------------------------------------------------------- * Author : NSFocus Security Team security@nsfocus.com * : http://www.nsfocus.net * Maintain : scz scz@nsfocus.com * Version : 1.10 * Compile : For x86/EWindows XP SP1 * : VC 7 * : Windows DDK 2600.1106 * : Windows Debugger Version 6.2.0007.4 * : build -cZMg -x86 * : * Create : 2004-03-31 15:02 * Modify : 2004-04-05 13:31 * ----------------------------------------------------------------------- * The only thing they can't take from us are our minds. !H /
/ * 这次为了成功转换成SoftICE插件,不要考虑64-bit可移植性。 /
/********** * * * Head File * * * **********/
include
include
/********** * * * Macro * * * **********/
define VERSION "1.10"
define OFFSETOF(TYPE, MEMBER) ((size_t)&((TYPE)0)->MEMBER)
/********** * * * Function Prototype * * * **********/
/********** * * * Static Global Var * * * **********/
EXT_API_VERSION ApiVersion = { 5, 0, EXT_API_VERSION_NUMBER, 0 }; WINDBG_EXTENSION_APIS ExtensionApis; ULONG SavedMajorVersion; ULONG SavedMinorVersion;
/************/
DECLARE_API ( help )
{
dprintf
(
"\n"
"Help for extension dll PrivateExt.dll\n"
"\n"
" help - Shows this help\n"
" showcontext
DECLARE_API ( showcontext ) { ULONG Address; PCONTEXT context = NULL; ULONG BytesRead = 0;
if ( !args || !args[0] )
{
dprintf
(
"Usage: showcontext <addr>\n"
);
goto showcontext_exit;
}
Address = GetExpression( args );
context = LocalAlloc
(
LPTR,
OFFSETOF( PCONTEXT, ExtendedRegisters )
);
if ( NULL == context )
{
dprintf
(
"Failed to allocate memory for context.\n"
);
goto showcontext_exit;
}
ReadMemory
(
Address,
context,
OFFSETOF( PCONTEXT, ExtendedRegisters ),
&BytesRead
);
if ( OFFSETOF( PCONTEXT, ExtendedRegisters ) == BytesRead )
{
dprintf
(
"EAX=%08X EBX=%08X ECX=%08X EDX=%08X ESI=%08X\n"
"EDI=%08X EBP=%08X ESP=%08X EIP=%08X EFLAGS=%08X\n"
"CS=%04X DS=%04X SS=%04X ES=%04X FS=%04X GS=%04X\n",
context->Eax,
context->Ebx,
context->Ecx,
context->Edx,
context->Esi,
context->Edi,
context->Ebp,
context->Esp,
context->Eip,
context->EFlags,
( WORD )context->SegCs,
( WORD )context->SegDs,
( WORD )context->SegSs,
( WORD )context->SegEs,
( WORD )context->SegFs,
( WORD )context->SegGs
);
}
else
{
dprintf
(
"OFFSETOF( PCONTEXT, ExtendedRegisters ) != BytesRead\n"
);
}
showcontext_exit:
if ( NULL != context )
{
LocalFree( context );
context = NULL;
}
return;
} / end of showcontext /
VOID WinDbgExtensionDllInit ( PWINDBG_EXTENSION_APIS lpExtensionApis, USHORT MajorVersion, USHORT MinorVersion ) { ExtensionApis = lpExtensionApis; SavedMajorVersion = MajorVersion; SavedMinorVersion = MinorVersion; return; } / end of WinDbgExtensionDllInit */
LPEXT_API_VERSION ExtensionApiVersion ( VOID ) { return( &ApiVersion ); } / end of ExtensionApiVersion /
VOID CheckVersion ( VOID ) { return; } / end of CheckVersion /
BOOL WINAPI DllMain ( HINSTANCE hinstDll, DWORD fdwReason, PVOID fImpLoad ) { switch ( fdwReason ) { case DLL_PROCESS_ATTACH: / * The DLL is being mapped into the process's address space. * * We don't need thread start/stop notifications, so disable them. / DisableThreadLibraryCalls( hinstDll ); break; case DLL_THREAD_ATTACH: / * A thread is being created. / break; case DLL_THREAD_DETACH: / * A thread is exiting cleanly. / break; case DLL_PROCESS_DETACH: / * The DLL is being unmapped from the process's address space. / break; } / end of switch / / * Used only for DLL_PROCESS_ATTACH / return( TRUE ); } / end of DllMain /
/************/
2) 编写PrivateExt.def文件
LIBRARY "PrivateExt.dll"
EXPORTS WinDbgExtensionDllInit ExtensionApiVersion CheckVersion help showcontext
3) 编写sources文件
TARGETNAME=PrivateExt TARGETPATH=obj TARGETTYPE=DYNLINK TARGETLIBS=J:\WINDDK\2600.1106\lib\wxp\i386\kernel32.lib DLLENTRY=_DllMainCRTStartup USE_PDB=1 USE_MSVCRT=1 UMTYPE=windows INCLUDES= MSC_WARNING_LEVEL=-W3 -WX SOURCES=PrivateExt.c
假设进入了"Win XP Free Build Environment":
set BUILD_ALT_DIR=
此时PrivateExt/下执行build -cZMg -x86,产生的目录/文件布局如下:
PrivateExt> build -cZMg -x86 PrivateExt> tree /F /A . PRIVATEEXT | build.log | makefile | PrivateExt.c | PrivateExt.def | sources | ---obj | _objects.mac | ---i386 PrivateExt.dll PrivateExt.exp PrivateExt.lib privateext.obj PrivateExt.pdb
4) 编写makefile文件
!INCLUDE $(NTMAKEENV)\makefile.def
PrivateExt> set NTMAKEENV NTMAKEENV=J:\WINDDK\2600~1.110\bin
5) 编译产生PrivateExt.dll文件
PrivateExt> set BUILD_ALT_DIR= PrivateExt> build -cZMg -x86 BUILD: Adding /Y to COPYCMD so xcopy ops won't hang. BUILD: Compile and Link for i386 BUILD: Examining privateext directory for files to compile. BUILD: Compiling privateext directory Compiling - privateext.c for i386 Building Library - obj\i386\privateext.lib for i386 BUILD: Linking privateext directory Linking Executable - obj\i386\privateext.dll for i386 BUILD: Done
2 files compiled
1 library built
1 executable built
PrivateExt> dumpbin /imports PrivateExt.dll msvcrt.dll B6 _adjust_fdiv 2D7 malloc 13A _initterm 2A4 free KERNEL32.dll 240 LocalAlloc 244 LocalFree 84 DisableThreadLibraryCalls PrivateExt> dumpbin /exports PrivateExt.dll 1 0 00001398 CheckVersion 2 1 00001392 ExtensionApiVersion 3 2 00001369 WinDbgExtensionDllInit 4 3 00001260 help 5 4 0000126F showcontext
6) 测试windbg插件PrivateExt.dll
/ * Matt Pietrek 1997 * ----------------------------------------------------------------------- * For x86/EWindows XP SP1 & VC 7 * cl SEHDEMO_1.c /nologo /Os /G6 /W3 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /link /RELEASE /
include
include
include
pragma comment( linker, "/INCREMENTAL:NO" )
pragma comment( linker, "/subsystem:console" )
static DWORD writable = 0xFFFFFFFF;
static EXCEPTION_DISPOSITION __cdecl seh_func ( struct _EXCEPTION_RECORD ExceptionRecord, void EstablisherFrame, struct _CONTEXT ContextRecord, void DispatcherContext ) { printf( "Hello from seh_func()\n" ); ContextRecord->Eax = ( DWORD )&writable; return( ExceptionContinueExecution ); } / end of seh_func /
int __cdecl main ( int argc, char * argv[] ) { __asm { push seh_func push FS:[0] mov FS:[0],ESP } printf( "writable = 0x%08X\n", writable ); __asm { mov EAX,0 mov DWORD PTR [EAX],0 } printf( "You should see this message\n" "writable = 0x%08X\n", writable ); __asm { mov EAX,[ESP] mov FS:[0],EAX add ESP,8 } return( EXIT_SUCCESS ); } / end of main /
ntsd -s SEHDEMO_1.exe
bp ntdll!KiUserExceptionDispatcher "dd poi(esp)+c L1;dd (dwo(esp+4))+8c L10" g writable = 0xFFFFFFFF (e54.a5c): Access violation - code c0000005 (first chance) First chance exceptions are reported before any exception handling. This exception may be expected and handled. 0040102d c70000000000 mov dword ptr [eax],0x0 ds:0023:00000000=???????? g 0012fc00 0040102d 0012fc9c 00000000 00000038 00000023 00000023 0012fcac 00000000 00000a28 7ffdf000 00000001 0012fcbc ffffffff 00000000 0012fee4 0040102d 0012fccc 0000001b 00010212 0012fedc 00000023 eax=00000000 ebx=7ffdf000 ecx=ffffffff edx=00000001 esi=00000a28 edi=00000000 eip=77f75dac esp=0012fbec ebp=0012fee4 iopl=0 nv up ei pl nz ac pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000212 ntdll!KiUserExceptionDispatcher: 77f75dac 8b4c2404 mov ecx,[esp+0x4] ss:0023:0012fbf0=0012fc10 bc * .restart .load PrivateExt.dll bp ntdll!KiUserExceptionDispatcher "dd poi(esp)+c L1;!showcontext dwo(esp+4)" g g 0012fc00 0040102d EAX=00000000 EBX=7FFDF000 ECX=FFFFFFFF EDX=00000001 ESI=00000A28 EDI=00000000 EBP=0012FEE4 ESP=0012FEDC EIP=0040102D EFLAGS=00010212 CS=001B DS=0023 SS=0023 ES=0023 FS=0038 GS=0000
7) 转换并测试SoftICE插件PrivateExt.sys
用KD2SYS转换:
Copying X:\onlytemp\PrivateExt.dll to X:\WINDOWS\SYSTEM32\DRIVERS\PrivateExt.SYS Original checksum was 0000db01, new checksum is 00006131 Adding device to registry... Creating SYSTEM\CurrentControlSet\Services\PrivateExt Updating KDExtensions key for NTICE KDExtensions='' i=16384 j=212 New extension list='PrivateExt.SYS' len 15
net start PrivateExt
:!help
Help for extension dll PrivateExt.dll
help - Shows this help
showcontext
☆ windbg插件转SoftICE插件友情提示
写程序写久了,就不可避免地出现"保持高可移植性"的僻好。如果哪位兄弟写windbg 插件,进而转SoftICE插件,一定要注意一件事,不要保持32-bit与64-bit之间的可 移植性,应该写一个纯32-bit的windbg插件。否则有两种下场:
a) SoftICE手动加载
此时用"net start"命令可以成功启动插件,driver命令也可以看到加载上来的插 件,但用!号看不到扩展命令。
b) SoftICE以其它方式加载
此时你会发现加载插件时SoftICE弹出,KeBugCheck()来了!回安全模式吧。
尤其那些下载了最新版windbg的兄弟要留心这个事。
当然,只写windbg插件,不打算转成SoftICE插件的话,就不存在这里所说的问题。 多谢hume的发现以及Immortal1015兄的蓝屏测试。
☆ 参考资源
[ 1] Writing a kd/WinDbg Debugger Extension DLL - Myk Willis[1998-12] http://www.windevnet.com/documents/s=7293/wdj9812c/9812c.htm ftp://ftp.wdj.com/pub/1998/dec98.zip
[ 2] Making WinDbg Your Friend - Creating Debugger Extensions http://www.osronline.com/article.cfm?id=52 http://www.osronline.com/custom.cfm?name=articlePrint.cfm&id=52
[ 3] Debug Tutorial Part 4: Writing WINDBG Extensions http://www.codeproject.com/useritems/cdbntsd4.asp http://www.codeproject.com/useritems/cdbntsd4/cdbntsd4_src.zip http://www.codeproject.com/useritems/cdbntsd4/cdbntsd4_demo.zip
[ 4] Kernel Debug Extensions http://frontline.compuware.com/nashua/papers/kernel_debug.htm
Error Translating Kernel Debugger Extention DLL [1999-08-19]
http://frontline.compuware.com/nashua/kb/doc/612.asp
[ 5] Writing Your Own WinDBG Extensions - John Robbins[2000-01] http://www.microsoft.com/msj/0100/bugslayer/bugslayer0100.aspx http://download.microsoft.com/download/0/6/7/0678184e-905e-4783-9511-d4dca1f492b4/Jan00Bugslayer.exe
[ 6] <
[ 7] IceExt official homepage - Sten http://stenri.pisem.net
[ 8] Using the Debugger Engine and Extension API (6.3版windbg开始携带debugext.chm文件)