基于Sfilter框架Demo的缓冲区溢出BUG分析
来源:互联网 发布:linux系统怎么安装软件 编辑:程序博客网 时间:2024/05/16 11:57
实验了好几次, 才找到能崩溃的那个demoDrv.sys
做个应用层的启动程序, 只负责安装这个驱动, 指定该驱动随着系统启动.
(备注: 如果直接安装运行驱动, 有可能崩溃后, 调用栈链中没有我们的驱动)
安装驱动完成后, 重新启动计算机.
用WinDbg链接计算机进行调试, 当计算机启动起来后,被WinDbg断下.
设置合适的符号路径, 源文件路径, 映像路径.
在demoDrv.sys中DriverEntry中下断点, 然后全速运行
当demoDrv.sys启动后, 被WinDbg断下, 证实我们正在调试该驱动.
kd> gBreakpoint 0 hitdemoDrv!DriverEntry+0x12:ee859b22 8b450c mov eax,dword ptr [ebp+0Ch]
再全速运行, 就看到驱动挂掉了, 还没来的及在目标计算机里点击个目录~, 效果很理想
kd> gAccess violation - code c0000005 (!!! second chance !!!)nt!ExDeferredFreePool+0xfd:80545603 8913 mov dword ptr [ebx],edx
用 !analyze -v 命令分析报错信息
kd> !analyze -vConnected to Windows XP 2600 x86 compatible target at (Mon Jun 10 20:40:58.066 2013 (UTC + 8:00)), ptr64 FALSELoading Kernel Symbols..................................................................................................Loading User Symbols...Loading unloaded module list..*** ERROR: Symbol file could not be found. Defaulted to export symbols for sfcfiles.dll - *** ERROR: Module load completed but symbols could not be loaded for ipnat.sys*** ERROR: Module load completed but symbols could not be loaded for vmhgfs.sys*** ERROR: Module load completed but symbols could not be loaded for ipsec.sys*** ERROR: Module load completed but symbols could not be loaded for vmx_svga.sys*** ERROR: Module load completed but symbols could not be loaded for isapnp.sys*** ERROR: Symbol file could not be found. Defaulted to export symbols for vmci.sys - *** ERROR: Symbol file could not be found. Defaulted to export symbols for vsock.sys - *** ERROR: Symbol file could not be found. Defaulted to export symbols for drmk.sys - *** ERROR: Module load completed but symbols could not be loaded for intelppm.sys******************************************************************************** ** Bugcheck Analysis ** ********************************************************************************Unknown bugcheck code (0)Unknown bugcheck descriptionArguments:Arg1: 00000000Arg2: 00000000Arg3: 00000000Arg4: 00000000Debugging Details:------------------PROCESS_NAME: smss.exeFAULTING_IP: nt!ExDeferredFreePool+fd80545603 8913 mov dword ptr [ebx],edxEXCEPTION_RECORD: ffffffff -- (.exr 0xffffffffffffffff)ExceptionAddress: 80545603 (nt!ExDeferredFreePool+0x000000fd) ExceptionCode: c0000005 (Access violation) ExceptionFlags: 00000000NumberParameters: 2 Parameter[0]: 00000001 Parameter[1]: 00000000Attempt to write to address 00000000ERROR_CODE: (NTSTATUS) 0xc0000005 - 0x%08lxEXCEPTION_CODE: (NTSTATUS) 0xc0000005 - 0x%08lxEXCEPTION_PARAMETER1: 00000001EXCEPTION_PARAMETER2: 00000000WRITE_ADDRESS: 00000000 FOLLOWUP_IP: nt!ExDeferredFreePool+fd80545603 8913 mov dword ptr [ebx],edxBUGCHECK_STR: ACCESS_VIOLATIONDEFAULT_BUCKET_ID: NULL_DEREFERENCELAST_CONTROL_TRANSFER: from 80545c6f to 80545603STACK_TEXT: f71f92b4 80545c6f e12fd558 85fbf018 86174f38 nt!ExDeferredFreePool+0xfdf71f92f4 f780082f e14aac00 00000000 00000018 nt!ExFreePoolWithTag+0x489f71f9350 f78008c0 e14aa008 e14aa066 e13f79e8 demoDrv!QueryDirectoryForLongName+0x29f [d:\myworkdir\sfilterdebug\demo\driver\misc.c @ 499]f71f9378 f7800c8b e14aa008 e13f79e8 00000208 demoDrv!QueryLongName+0x80 [d:\myworkdir\sfilterdebug\demo\driver\misc.c @ 527]f71f93bc f77fe8ad f71f93f0 e16eb7a8 00000208 demoDrv!ConverShortToLongName+0x39b [d:\myworkdir\sfilterdebug\demo\driver\misc.c @ 640]f71f9a60 804ef119 85e5eef8 85fbf008 85fbf008 demoDrv!sfCreate+0x3bd [d:\myworkdir\sfilterdebug\demo\driver\sfilter.c @ 2530]f71f9a70 80579616 861ad8e8 85f51264 f71f9c18 nt!IopfCallDriver+0x31f71f9b50 805b5cbc 861ad900 00000000 85f511c0 nt!IopParseDevice+0xa12f71f9bd8 805b2065 00000000 f71f9c18 00000040 nt!ObpLookupObjectName+0x56af71f9c2c 8056c223 00000000 00000000 1b4e7001 nt!ObOpenObjectByName+0xebf71f9ca8 8056cb9a 0015fe50 00110000 0015fde8 nt!IopCreateFile+0x407f71f9d04 805703c1 0015fe50 00110000 0015fde8 nt!IoCreateFile+0x8ef71f9d44 8053e638 0015fe50 00110000 0015fde8 nt!NtOpenFile+0x27f71f9d44 7c92e4f4 0015fe50 00110000 0015fde8 nt!KiFastCallEntry+0xf80015fd74 7c92d58c 48587b32 0015fe50 00110000 ntdll!KiFastSystemCallRet0015fd78 48587b32 0015fe50 00110000 0015fde8 ntdll!NtOpenFile+0xc0015fe58 48588c79 00000000 7c921295 00000000 smss!SmpProcessFileRenames+0x2e10015fecc 48588f27 0015ff6c 00000005 00000000 smss!SmpLoadDataFromRegistry+0x31c0015ff18 48589bfc 0015ff6c 0015ff64 00000005 smss!SmpInit+0x1bd0015ffa8 4858ad97 00000001 00162340 00162348 smss!main+0x680015fff4 00000000 7ffdd000 000000c8 0000017c smss!NtProcessStartup+0x1d2STACK_COMMAND: kbSYMBOL_STACK_INDEX: 0SYMBOL_NAME: nt!ExDeferredFreePool+fdFOLLOWUP_NAME: Pool_corruptionIMAGE_NAME: Pool_CorruptionDEBUG_FLR_IMAGE_TIMESTAMP: 0MODULE_NAME: Pool_CorruptionFAILURE_BUCKET_ID: ACCESS_VIOLATION_nt!ExDeferredFreePool+fdBUCKET_ID: ACCESS_VIOLATION_nt!ExDeferredFreePool+fdFollowup: Pool_corruption---------
报错分析
可以看到最新的6条堆栈调用是引起报错的有效信息, 都是demoDrv.sys引起的
f71f92b4 80545c6f e12fd558 85fbf018 86174f38 nt!ExDeferredFreePool+0xfdf71f92f4 f780082f e14aac00 00000000 00000018 nt!ExFreePoolWithTag+0x489f71f9350 f78008c0 e14aa008 e14aa066 e13f79e8 demoDrv!QueryDirectoryForLongName+0x29f [d:\myworkdir\sfilterdebug\demo\driver\misc.c @ 499]f71f9378 f7800c8b e14aa008 e13f79e8 00000208 demoDrv!QueryLongName+0x80 [d:\myworkdir\sfilterdebug\demo\driver\misc.c @ 527]f71f93bc f77fe8ad f71f93f0 e16eb7a8 00000208 demoDrv!ConverShortToLongName+0x39b [d:\myworkdir\sfilterdebug\demo\driver\misc.c @ 640]f71f9a60 804ef119 85e5eef8 85fbf008 85fbf008 demoDrv!sfCreate+0x3bd [d:\myworkdir\sfilterdebug\demo\driver\sfilter.c @ 2530]f71f9a70 80579616 861ad8e8 85f51264 f71f9c18 nt!IopfCallDriver+0x31
下面直接对着调用栈,看着代码可以分析到最终引起报错的原因, 没有再分析WinDbg调试信息.
从demoDrv.sys调用链的最开始处分析代码, 如果不能找到错误,逐渐向报错处的函数分析.
分析顺序为 sfilter.c @ 2530 => misc.c @ 640 => misc.c @ 527 => misc.c @ 499
查离错误最远的一个函数 sfilter.c @ 2530
if (IsShortNamePath(lpNameControl->Name.Buffer)) {ConverShortToLongName(wszLongName, lpNameControl->Name.Buffer, sizeof(WCHAR)*MAX_PATH);RtlCopyMemory(lpNameControl->Name.Buffer, wszLongName, sizeof(WCHAR)*MAX_PATH); ///< line 2530, 这里有Buffer操作 }
wszLongName 是在函数中定义的缓冲区, 宽字符 _MAX_PATH, 没问题
查看 lpNameControl->Name 怎么来的
lpNameControl 是由前面的 GetFileNameFromObject 产生
ntStatus = GetFileNameFromObject(&lpNameControl, LookupFlags, lpIrpStack->FileObject, lpDevice);
查 GetFileNameFromObject 函数
NTSTATUSGetFileNameFromObject( PNAME_CONTROL* lppNameControl, ULONG ulFlag, FILE_OBJECT* lpFileObject, PDEVICE_OBJECT lpDevice){ BOOLEAN bCacheName = FALSE; NTSTATUS Status = STATUS_SUCCESS; PSFILTER_DEVICE_EXTENSION lpDevExt = (PSFILTER_DEVICE_EXTENSION)(lpDevice->DeviceExtension); Status = NLAllocateNameControl( lppNameControl, &gSfNameBufferLookasideList );///< 可以看到 lppNameControl 是由 NLAllocateNameControl函数分配
查NLAllocateNameControl函数
NTSTATUSNLAllocateNameControl ( __out PNAME_CONTROL *NameControl, __in PPAGED_LOOKASIDE_LIST LookasideList ){ PNAME_CONTROL nameCtrl = NULL; nameCtrl = ExAllocateFromPagedLookasideList( LookasideList ); if (nameCtrl == NULL) { *NameControl = NULL; return STATUS_INSUFFICIENT_RESOURCES; } NLInitNameControl( nameCtrl );///< 空间是由NLInitNameControl函数初始化 *NameControl = nameCtrl; return STATUS_SUCCESS;}
查NLInitNameControl函数
VOIDNLInitNameControl ( __inout PNAME_CONTROL NameCtrl ){ PAGED_CODE(); NameCtrl->AllocatedBuffer = NULL; NameCtrl->BufferSize = sizeof( NameCtrl->SmallBuffer );///< NameCtrl->SmallBuffer是真正的缓冲区, 供外部使用 RtlInitEmptyUnicodeString( &NameCtrl->Name, (PWCHAR)NameCtrl->SmallBuffer, (USHORT)NameCtrl->BufferSize );}
查NameCtrl->SmallBuffer定义
ypedef struct _NAME_CONTROL { UNICODE_STRING Name; PUCHAR AllocatedBuffer; ULONG BufferSize; DECLSPEC_PTRALIGN UCHAR SmallBuffer[254];///< 问题找到了, 缓冲区太小, 拷贝时, 用的是(sizeof(wchar_t ) * _MAX_PATH), 这里是(sizeof(BYTE) * 254)} NAME_CONTROL, *PNAME_CONTROL;
问题已经定位
最直接的修改方案是将SmallBuffer定义改大, 改成 sizeof(wchar_t)* _MAX_PATH
// 原始工程中头文件少包含了, 从标准定义中, 抄一个宏过来#ifndef _MAX_PATH#define _MAX_PATH 260 /* max. length of full pathname */#endiftypedef struct _NAME_CONTROL { // // UNICODE_STRING whos buffer is either SmallBuffer or AllocatedBuffer // if a larger buffer was needed. // UNICODE_STRING Name; // // AllocatedBuffer is used when we need a buffer larger than SmallBuffer. // PUCHAR AllocatedBuffer; // // The size of whatever buffer is currently being used (SmallBuffer or // AllocatedBuffer) in bytes. // ULONG BufferSize; // // This is the buffer that we start out with. The thinking is that this // should be large enough for most names. // /// original define => DECLSPEC_PTRALIGN UCHAR SmallBuffer[254]; DECLSPEC_PTRALIGN WCHAR SmallBuffer[_MAX_PATH];///< bigfix } NAME_CONTROL, *PNAME_CONTROL;
- 基于Sfilter框架Demo的缓冲区溢出BUG分析
- 缓冲区溢出引起奇怪的bug
- 缓冲区溢出分析第02课:缓冲区溢出的原理
- 缓冲区溢出分析第03课:缓冲区溢出的利用
- 基于安全的一些思考--缓冲区溢出
- 一个缓冲区溢出的简单分析
- 缓冲区溢出机理分析
- 缓冲区溢出原理分析
- 缓冲区溢出-shellcode分析
- 缓冲区溢出分析第11课:整数溢出的原理
- 缓冲区溢出攻击框架Metasploit
- 基于栈指纹检测缓冲区溢出的一点思路
- 点评"基于栈指纹检测缓冲区溢出的一点思路
- 利用基于帧栈的缓冲区溢出执行任意代码
- Storm netty client溢出的bug分析
- 缓冲区溢出分析第01课:缓冲区溢出分析导论
- 缓冲区溢出分析第06课:W32Dasm缓冲区溢出分析
- 缓冲区溢出攻击原理分析
- POJ 1291: This Sentence is False
- 亿万用户网站MySpace的成功秘密
- 第四届省赛F题
- 拉卡拉手机刷卡器音频通讯技术原理初步分析
- 一步步构建大型网站架构
- 基于Sfilter框架Demo的缓冲区溢出BUG分析
- 我的学习生涯(Delphi篇) - 22
- uestc oj 1876 聚会
- rh436 - 错把“Netmask Bits”当“Netmask”
- AdaBoost中利用Haar特征进行人脸识别算法分析与总结1——Haar特征与积分图
- Android 歌词解析(完美解析)
- 整數取反與字符串轉換成整數
- 程序员的职场潜意识Top10
- Log4j的使用和怎么在spring中集成log4j 【转】