首页
社区
课程
招聘
[原创]现学现用之windbg的高级玩法(1,3,5,13,14,76,80,81,84,118,119,121,122楼已更新,chm文档集成7篇实战18个辅助工具)
发表于: 2013-9-14 23:23 218340

[原创]现学现用之windbg的高级玩法(1,3,5,13,14,76,80,81,84,118,119,121,122楼已更新,chm文档集成7篇实战18个辅助工具)

2013-9-14 23:23
218340
收藏
免费 12
支持
分享
最新回复 (250)
雪    币: 541
活跃值: (654)
能力值: ( LV12,RANK:250 )
在线值:
发帖
回帖
粉丝
101
感谢支持
2013-9-23 19:12
0
雪    币: 309
活跃值: (88)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
102
这个是相当的给力,原来WINDBG可以这样玩
2013-9-24 20:22
0
雪    币: 306
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
103
这个必须顶
2013-9-26 13:57
0
雪    币: 31
活跃值: (17)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
104
强帖,留名学习。
2013-9-27 19:36
0
雪    币: 230
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
105
严重支持~~~~
2013-9-29 15:17
0
雪    币: 37
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
106
开始看楼主的文章,感谢搂主的分享!
2013-9-29 16:20
0
雪    币: 387
活跃值: (66)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
107
回帖收藏,感谢楼主的无私奉献。
2013-9-29 23:15
0
雪    币: 248
活跃值: (123)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
108
必須收藏啊
2013-9-30 09:50
0
雪    币: 44
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
109
牛掰啊。。。
2013-9-30 17:44
0
雪    币: 5
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
110
mark~
2013-9-30 17:56
0
雪    币: 1258
活跃值: (1434)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
111
标签[√]
2013-9-30 20:30
0
雪    币: 217
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
112
恩恩,整理的不错哟
2013-9-30 20:34
0
雪    币: 228
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
113
好帖 收藏了!WinDbg xp
2013-10-1 09:48
0
雪    币: 103
活跃值: (126)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
114
支持支持 十一要把你写的chm看完 多谢楼主的无私奉献
2013-10-2 13:27
0
雪    币: 265
活跃值: (76)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
115
支持楼主
2013-10-2 23:42
0
雪    币: 370
活跃值: (15)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
116
欢度国庆
感谢楼主更新:现学现用-玩转windbgV0.3国庆节彩色版.rar
2013-10-3 21:53
0
雪    币: 541
活跃值: (654)
能力值: ( LV12,RANK:250 )
在线值:
发帖
回帖
粉丝
117
感谢兄弟的大力支持。有没有兴趣加入群:151843490
2013-10-3 22:22
0
雪    币: 541
活跃值: (654)
能力值: ( LV12,RANK:250 )
在线值:
发帖
回帖
粉丝
118
在做这个实验之前,需要先构建数据。
首先是声明两个全局临界区和两个互斥对象
CRITICAL_SECTION g_cs1;
CRITICAL_SECTION g_cs2;
HANDLE g_hMutex1 = NULL;
HANDLE g_hMutex2 = NULL;
四个线程
1.
DWORD __stdcall TestThread1( LPVOID lpThreadParameter )
{
    for ( ;;)
    {
        EnterCriticalSection( &g_cs1 );
        EnterCriticalSection( &g_cs2 );
        WaitForSingleObject( g_hMutex1, INFINITE );
        WaitForSingleObject( g_hMutex2, INFINITE );
        printf( "Now Tid1 is : %d\n", GetCurrentThreadId() );
        ReleaseMutex( g_hMutex2 );
        ReleaseMutex(g_hMutex1);
        LeaveCriticalSection( &g_cs2 );
        LeaveCriticalSection( &g_cs1 );
        if ( g_bStop )
        {
            break;
        }
    }
    return 0;
}
2.
DWORD __stdcall TestThread2( LPVOID lpThreadParameter )
{
    for ( ;;)
    {
        EnterCriticalSection( &g_cs2 );
        WaitForSingleObject( g_hMutex1, INFINITE );
        WaitForSingleObject( g_hMutex2, INFINITE );
        printf( "Now Tid2 is : %d\n", GetCurrentThreadId() );
        ReleaseMutex( g_hMutex2 );
        ReleaseMutex(g_hMutex1);
        LeaveCriticalSection( &g_cs2 );
        if ( g_bStop )
        {
            break;
        }
    }
    return 0;
}
3.
DWORD __stdcall TestThread3( LPVOID lpThreadParameter )
{
    for ( ;;)
    {
        WaitForSingleObject( g_hMutex2, INFINITE );
        EnterCriticalSection( &g_cs1 );
        EnterCriticalSection( &g_cs2 );
        WaitForSingleObject( g_hMutex1, INFINITE );
        printf( "Now Tid3 is : %d\n", GetCurrentThreadId() );
        ReleaseMutex(g_hMutex1);
        LeaveCriticalSection( &g_cs2 );
        LeaveCriticalSection( &g_cs1 );
        ReleaseMutex( g_hMutex2 );
        if ( g_bStop )
        {
            break;
        }
    }
    return 0;
}
4.
DWORD __stdcall TestThread4( LPVOID lpThreadParameter )
{
    for ( ;;)
    {
        EnterCriticalSection( &g_cs1 );
        WaitForSingleObject( g_hMutex1, INFINITE );
        EnterCriticalSection( &g_cs2 );
        WaitForSingleObject( g_hMutex2, INFINITE );
        printf( "Now Tid4 is : %d\n", GetCurrentThreadId() );
        ReleaseMutex( g_hMutex2 );
        LeaveCriticalSection( &g_cs2 );
        ReleaseMutex(g_hMutex1);
        LeaveCriticalSection( &g_cs1 );
        if ( g_bStop )
        {
            break;
        }
    }
    return 0;
}
全局变量初始化以及线程创建:

int _tmain(int argc, _TCHAR* argv[])
{
    InitializeCriticalSection( &g_cs1 );
    InitializeCriticalSection( &g_cs2 );
    g_hMutex1 = CreateMutex( NULL, FALSE, NULL );
    g_hMutex2 = CreateMutex( NULL, FALSE, NULL );
    HANDLE hArrarys[4] = {0};
    hArrarys[0] = CreateThread( NULL, 0, TestThread1, NULL, 0, NULL );
    hArrarys[1] = CreateThread( NULL, 0, TestThread2, NULL, 0, NULL );
    hArrarys[2] = CreateThread( NULL, 0, TestThread3, NULL, 0, NULL );
    hArrarys[3] = CreateThread( NULL, 0, TestThread4, NULL, 0, NULL );

    getchar();
    g_bStop = TRUE;
    
    WaitForMultipleObjects( 4, hArrarys, TRUE, INFINITE);
    for ( int i=0; i<4; i++ )
    {
        CloseHandle( hArrarys[i]);
    }
    CloseHandle( g_hMutex1 );
    CloseHandle( g_hMutex2 );
    return 0;
}
整个代码比较简单,就是4个线程,会进入临界区和互斥对象。由于进入顺序不一样,就会导致死锁。
编译好后,生成了EXE:deadlocks.exe

用windbg启动调试。
0:000> [COLOR=Red]g
并观察屏幕输出。由于每个线程都会打印日志。如果不再打印日志了就证明死锁了。
(死锁的明显现象就是线程停止,处在等待状态。调入NtWaitForSingleObject等函数中不出来。所以当产生死锁时,CPU占用一定不高。)

楼主发现屏幕只打印了两条日志就停止打印了(由于死锁发生的时机跟线程调度有关,你在测试时可能输出的日志与楼主不同,死锁时堆栈也不同,不过排错的原理是一样的)。
Now Tid3 is : 3064
Now Tid1 is : 3944
看样子是锁住了。
按Ctrl+Break,进入调试状态
(230.e44): Break instruction exception - code 80000003 (first chance)
eax=7ffdc000 ebx=00000001 ecx=00000002 edx=00000003 esi=00000004 edi=00000005
eip=7c92120e esp=003bffcc ebp=003bfff4 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=0038  gs=0000             efl=00000246
ntdll!DbgBreakPoint:
7c92120e cc              int     3
楼主要看都有哪些线程锁住了,查一下所有线程的调用栈
0:005>[COLOR=Red] ~ * kv 10

   0  Id: 230.24c Suspend: 1 Teb: 7ffdf000 Unfrozen
ChildEBP RetAddr  Args to Child              
0012faf4 7c92dacc 7c932dc8 000007ec 0012fb58 ntdll!KiFastSystemCallRet (FPO: [0,0,0])
0012faf8 7c932dc8 000007ec 0012fb58 0012fb58 ntdll!NtRequestWaitReplyPort+0xc (FPO: [3,0,0])
0012fb18 7c872931 00000000 00260688 0002021d ntdll!CsrClientCallServer+0x8c (FPO: [Non-Fpo])
0012fc14 7c872a78 00000003 10362ac0 00001000 kernel32!ReadConsoleInternal+0x1be (FPO: [Non-Fpo])
0012fc9c 7c8018b7 00000003 10362ac0 00001000 kernel32!ReadConsoleA+0x3b (FPO: [Non-Fpo])
0012fcf4 1030cc7c 00000003 10362ac0 00001000 kernel32!ReadFile+0x64 (FPO: [Non-Fpo])
0012fd88 1030c5c9 00000000 10362ac0 00001000 MSVCR100D!_read_nolock+0x62c (FPO: [Non-Fpo]) (CONV: cdecl) [f:\dd\vctools\crt_bld\self_x86\crt\src\read.c @ 230]
0012fdd8 10261093 00000000 10362ac0 00001000 MSVCR100D!_read+0x219 (FPO: [Non-Fpo]) (CONV: cdecl) [f:\dd\vctools\crt_bld\self_x86\crt\src\read.c @ 92]
0012fe00 1025f5ab 1035e498 c91a8a99 0012ff68 MSVCR100D!_filbuf+0x113 (FPO: [Non-Fpo]) (CONV: cdecl) [f:\dd\vctools\crt_bld\self_x86\crt\src\_filbuf.c @ 136]
0012fe5c 1025f660 1035e498 0012fe70 1025f67a MSVCR100D!getc+0x20b (FPO: [Non-Fpo]) (CONV: cdecl) [f:\dd\vctools\crt_bld\self_x86\crt\src\fgetc.c @ 75]
0012fe68 1025f67a 0012ff68 00413bb8 0169f554 MSVCR100D!_fgetchar+0x10 (FPO: [Non-Fpo]) (CONV: cdecl) [f:\dd\vctools\crt_bld\self_x86\crt\src\fgetchar.c @ 37]
*** WARNING: Unable to verify checksum for deadlocks.exe
0012fe70 00413bb8 0169f554 00c707ba 7ffdc000 MSVCR100D!getchar+0xa (FPO: [Non-Fpo]) (CONV: cdecl) [f:\dd\vctools\crt_bld\self_x86\crt\src\fgetchar.c @ 47]
0012ff68 00411d1f 00000001 00392b40 00392c68 deadlocks!wmain+0x118 (FPO: [Non-Fpo]) (CONV: cdecl) [c:\documents and settings\administrator\my documents\visual studio 2010\projects\deadlocks\deadlocks.cpp @ 103]
0012ffb8 00411b4f 0012fff0 7c817067 0169f554 deadlocks!__tmainCRTStartup+0x1bf (FPO: [Non-Fpo]) (CONV: cdecl) [f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c @ 552]
0012ffc0 7c817067 0169f554 00c707ba 7ffdc000 deadlocks!wmainCRTStartup+0xf (FPO: [Non-Fpo]) (CONV: cdecl) [f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c @ 371]
0012fff0 00000000 00411078 00000000 78746341 kernel32!BaseProcessStart+0x23 (FPO: [Non-Fpo])

   1  Id: 230.f68 Suspend: 1 Teb: 7ffde000 Unfrozen
ChildEBP RetAddr  Args to Child              
0051fe48 7c92df3c 7c93b22b 000007c8 00000000 ntdll!KiFastSystemCallRet (FPO: [0,0,0])
[COLOR=Blue]0051fe4c 7c93b22b 000007c8 00000000 00000000 ntdll!NtWaitForSingleObject+0xc (FPO: [3,0,0])
0051fed4 7c921046 00417150 0041386b 00417150 ntdll!RtlpWaitForCriticalSection+0x132 (FPO: [Non-Fpo])
[COLOR=Blue]0051fedc 0041386b [COLOR=Red]00417150 7ffdc000 7c9411de ntdll!RtlEnterCriticalSection+0x46 (FPO: [1,0,0])
0051ffb4 7c80b713 00000000 7ffdc000 7c9411de deadlocks!TestThread1+0x2b (FPO: [Non-Fpo]) (CONV: stdcall) [c:\documents and settings\administrator\my documents\visual studio 2010\projects\deadlocks\deadlocks.cpp @ 16]
0051ffec 00000000 004111f9 00000000 00000000 kernel32!BaseThreadStart+0x37 (FPO: [Non-Fpo])

   2  Id: 230.bf8 Suspend: 1 Teb: 7ffdb000 Unfrozen
ChildEBP RetAddr  Args to Child              
0071fe48 7c92df3c 7c93b22b 000007c4 00000000 ntdll!KiFastSystemCallRet (FPO: [0,0,0])
[COLOR=Blue]0071fe4c 7c93b22b 000007c4 00000000 00000000 ntdll!NtWaitForSingleObject+0xc (FPO: [3,0,0])
0071fed4 7c921046 00417138 00411686 00417138 ntdll!RtlpWaitForCriticalSection+0x132 (FPO: [Non-Fpo])
[COLOR=Blue]0071fedc 00411686 [COLOR=Red]00417138 7ffdc000 7c9411de ntdll!RtlEnterCriticalSection+0x46 (FPO: [1,0,0])
 0071ffb4 7c80b713 00000000 7ffdc000 7c9411de deadlocks!TestThread3+0x56 (FPO: [Non-Fpo]) (CONV: stdcall) [c:\documents and settings\administrator\my documents\visual studio 2010\projects\deadlocks\deadlocks.cpp @ 56]
0071ffec 00000000 00411203 00000000 00000000 kernel32!BaseThreadStart+0x37 (FPO: [Non-Fpo])

   3  Id: 230.d84 Suspend: 1 Teb: 7ffdd000 Unfrozen
ChildEBP RetAddr  Args to Child              
0061fe5c 7c92df3c 7c8025db 000007e8 00000000 ntdll!KiFastSystemCallRet (FPO: [0,0,0])
[COLOR=Blue]0061fe60 7c8025db 000007e8 00000000 00000000 ntdll!NtWaitForSingleObject+0xc (FPO: [3,0,0])
0061fec4 7c802542 000007e8 ffffffff 00000000 kernel32!WaitForSingleObjectEx+0xa8 (FPO: [Non-Fpo])
[COLOR=Blue]0061fed8 00411589 [COLOR=Red]000007e8 ffffffff 7ffdc000 kernel32!WaitForSingleObject+0x12 (FPO: [Non-Fpo])
0061ffb4 7c80b713 00000000 7ffdc000 7c9411de deadlocks!TestThread2+0x59 (FPO: [Non-Fpo]) (CONV: stdcall) [c:\documents and settings\administrator\my documents\visual studio 2010\projects\deadlocks\deadlocks.cpp @ 38]
0061ffec 00000000 004111fe 00000000 00000000 kernel32!BaseThreadStart+0x37 (FPO: [Non-Fpo])

   4  Id: 230.ea4 Suspend: 1 Teb: 7ffda000 Unfrozen
ChildEBP RetAddr  Args to Child              
0081fe48 7c92df3c 7c93b22b 000007c8 00000000 ntdll!KiFastSystemCallRet (FPO: [0,0,0])
[COLOR=Blue]0081fe4c 7c93b22b 000007c8 00000000 00000000 ntdll!NtWaitForSingleObject+0xc (FPO: [3,0,0])
0081fed4 7c921046 00417150 0041399b 00417150 ntdll!RtlpWaitForCriticalSection+0x132 (FPO: [Non-Fpo])
[COLOR=Blue]0081fedc 0041399b [COLOR=Red]00417150 7ffdc000 7c9411de ntdll!RtlEnterCriticalSection+0x46 (FPO: [1,0,0])
0081ffb4 7c80b713 00000000 7ffdc000 7c9411de deadlocks!TestThread4+0x2b (FPO: [Non-Fpo]) (CONV: stdcall) [c:\documents and settings\administrator\my documents\visual studio 2010\projects\deadlocks\deadlocks.cpp @ 74]
0081ffec 00000000 00411208 00000000 00000000 kernel32!BaseThreadStart+0x37 (FPO: [Non-Fpo])

#  5  Id: 230.e44 Suspend: 1 Teb: 7ffd9000 Unfrozen
ChildEBP RetAddr  Args to Child              
003bffc8 7c970010 00000005 00000004 00000001 ntdll!DbgBreakPoint (FPO: [0,0,0])
003bfff4 00000000 00000000 00000000 00000000 ntdll!DbgUiRemoteBreakin+0x2d (FPO: [Non-Fpo])

通过观察调用栈,发现如下信息
0号线程是主线程,正在等待用户输出,死锁和他没关系
1号线程在等待进入临界区
2号线程也在等待进入临界区
3号线程在等待一个对象,可能是互斥量
4号线程也在等待进入临界区
5号线程是调试线程,忽略之

问题只能出在 1,2,3,4号线程上面。
咱们逐一排查。先从一号线程开始
1号线程进入RtlEnterCriticalSection后处在等待状态,咱们看一下它等待的临界区当前属于哪个线程。临界区对象地址是00417150
0:005>[COLOR=Red] !cs 00417150 
-----------------------------------------
Critical section   = 0x00417150 (deadlocks!g_cs1+0x0)
DebugInfo          = 0x7c99b9a0
LOCKED
LockCount          = 0x2
[COLOR=Red]OwningThread       = 0x00000bf8
RecursionCount     = 0x1
LockSemaphore      = 0x7C8
SpinCount          = 0x00000000
临界区00417150属于0x00000bf8线程。咱们看一下0x00000bf8是几号线程
0:005> [COLOR=Red]~~[0x00000bf8]
   2  Id: 230.bf8 Suspend: 1 Teb: 7ffdb000 Unfrozen
      Start: kernel32!BaseThreadStartThunk (7c8106e9) 
      Priority: 0  Priority class: 32  Affinity: 3

属于2号线程。
2号线程也在等待临界区,看看2号线程等待的临界区现在属于哪个线程
0:002> [COLOR=Red]!cs 00417138 
-----------------------------------------
Critical section   = 0x00417138 (deadlocks!g_cs2+0x0)
DebugInfo          = 0x7c99b9c0
LOCKED
LockCount          = 0x1
[COLOR=Red]OwningThread       = 0x00000d84
RecursionCount     = 0x1
LockSemaphore      = 0x7C4
SpinCount          = 0x00000000
0:002> [COLOR=Red]~~[0x00000d84]
   3  Id: 230.d84 Suspend: 1 Teb: 7ffdd000 Unfrozen
      Start: kernel32!BaseThreadStartThunk (7c8106e9) 
      Priority: 0  Priority class: 32  Affinity: 3

2号线程等待的临界区属于3号线程的。
那3号线程现在在等待什么那?通过堆栈咱们知道它调用了WaitForSingleObject,此函数第一个参数是等待的句柄。咱们看一下此句柄是什么类型
0:002>[COLOR=Red] !handle 000007e8 f  
Handle 7e8
  Type             [COLOR=Blue]Mutant
  Attributes       0
  GrantedAccess    0x1f0001:
         Delete,ReadControl,WriteDac,WriteOwner,Synch
         QueryState
  HandleCount      2
  PointerCount     4
  Name             <none>
  Object Specific Information
   [COLOR=Blue] Mutex is Owned

是一个互斥体对象。这个时候有一个麻烦,要想看到这个互斥体现在的所属线程在用户态是看不了的。天无绝人之路。咱们再开一个windbg,使用Local Kernel模式查看本地内核。并显示此互斥体句柄的详细信息
lkd> [COLOR=Red]!process 0 0 deadlocks.exe
PROCESS [COLOR=Blue]89e20750  SessionId: 0  Cid: 0230    Peb: 7ffdc000  ParentCid: 0bac
    DirBase: 0aae0860  ObjectTable: e1f064b8  HandleCount:  16.
    Image: deadlocks.exe

lkd> [COLOR=Red]!handle 000007e8 f 89e20750  

PROCESS 89e20750  SessionId: 0  Cid: 0230    Peb: 7ffdc000  ParentCid: 0bac
    DirBase: 0aae0860  ObjectTable: e1f064b8  HandleCount:  16.
    Image: deadlocks.exe

Handle table at e35d4000 with 16 entries in use

07e8: Object: [COLOR=Blue]89d7e020  GrantedAccess: 001f0001 Entry: e35d4fd0
Object: 89d7e020  Type: (8a327368) Mutant
    ObjectHeader: 89d7e008 (old version)
        HandleCount: 1  PointerCount: 2


lkd> [COLOR=Red]dt nt!_KMUTANT 89d7e020  
   +0x000 Header           : _DISPATCHER_HEADER
   +0x010 MutantListEntry  : _LIST_ENTRY [ 0x89aae770 - 0x89aae770 ]
   [COLOR=Blue]+0x018 OwnerThread      : 0x89aae760 _KTHREAD
   +0x01c Abandoned        : 0 ''
   +0x01d ApcDisable       : 0 ''
lkd> [COLOR=Red]!thread 0x89aae760 0
THREAD 89aae760  Cid [COLOR=Blue]0230.0bf8Teb: 7ffdb000 Win32Thread: 00000000 WAIT

经过一顿寻找找到000007e8句柄互斥体现在的拥有者是线程ID=0bf8的线程。
好,内核调试器用完了,咱们再切换到用户态windbg,看看0bf8是几号线程
0:002> [COLOR=Red]~~[0bf8]
.  2  Id: 230.bf8 Suspend: 1 Teb: 7ffdb000 Unfrozen
      Start: deadlocks!ILT+510(?TestThread3YGKPAXZ) (00411203) 
      Priority: 0  Priority class: 32  Affinity: 3

是2号线程!
当前基本上找到死锁的原因了。咱们来捋一下


[*]1号线程在等待2号线程拥有的临界区对象
[*]2号线程在等待3号线程拥有的临界区对象
[*]3号线程在等待2号线程拥有的互斥体对象


2号线程与3号线程之间构成了一个锁循环,2号线程等待3号释放临界区对象,3号线程在等待2号线程释放互斥体对象

好问题找到了。
那四号线程为啥也处在等待状态呢?咱们再看看4号线程在等待什么
0:002> [COLOR=Red]!cs 00417150 
-----------------------------------------
Critical section   = 0x00417150 (deadlocks!g_cs1+0x0)
DebugInfo          = 0x7c99b9a0
LOCKED
LockCount          = 0x2
[COLOR=Blue]OwningThread       = 0x00000bf8
RecursionCount     = 0x1
LockSemaphore      = 0x7C8
SpinCount          = 0x00000000
0:002> [COLOR=Red]~~[0x00000bf8]
.  2  Id: 230.bf8 Suspend: 1 Teb: 7ffdb000 Unfrozen
      Start: deadlocks!ILT+510(?TestThread3YGKPAXZ) (00411203) 
      Priority: 0  Priority class: 32  Affinity: 3

四号线程也在等待2号线程。
由此说来是2号和3号线程死锁,导致1,4号同时在等待2号线程释放资源。

问题找到了,下一步就是解决了。
死锁的一般解决方法:


[*]1. 避免一个线程同时拥有多个资源锁。
[*]2. 在进入一个锁时,发现已经被其他线程拥有,则不进入等待状态,而是干别的事情,等一会再检查此锁是否被释放。这样可以避免无限等待。

临界区使用TryEnterCriticalSection 互斥体使用WaitForSingleObject(hMutex,0)探测锁是否被占用

源码在此

deadlocks.rar
上传的附件:
2013-10-4 00:33
0
雪    币: 541
活跃值: (654)
能力值: ( LV12,RANK:250 )
在线值:
发帖
回帖
粉丝
119
由于堆存在自定义堆,如C++堆。C++会对堆做一些封装,这里分成两部分来测试。首先是使用windows 堆操作API。

和上一篇一样。先贴测试代码
int _tmain(int argc, _TCHAR* argv[])
{
    HANDLE hHeap = GetProcessHeap();
    if ( !hHeap )
    {
        return 1;
    }

    void* pBuffer1 = HeapAlloc( hHeap, HEAP_ZERO_MEMORY, 8 );
    void* pBuffer2 = HeapAlloc( hHeap, HEAP_ZERO_MEMORY, 6 );

    strcpy( (char*)pBuffer1, "123456789123456789123456789");
    strcpy( (char*)pBuffer2, "abcdefgddlx");

    HeapFree( hHeap, 0, pBuffer1 );
    HeapFree( hHeap, 0, pBuffer2 );
    getchar();
    return 0;
}

在堆中分配了两块内存,一个8字节,另外一个6字节。连个内存都内存溢出了。
咱们看一下运行效果。
用windbg启动运行,直接g
等一会就断下来了
[COLOR=Red]HEAP[HeapOverflow.exe]: Heap block at 00152BC0 modified at 00152BD0 past requested size of 8
(900.9d4): Break instruction exception - code 80000003 (first chance)
eax=00152bc0 ebx=00152bd0 ecx=7c93eab5 edx=0012fa04 esi=00152bc0 edi=00000008
eip=7c92120e esp=0012fc08 ebp=0012fc0c iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ntdll!DbgBreakPoint:
7c92120e cc              int     3


红色部分告诉我们,在堆中00152BC0分配了一块8字节的内存,结束位置为00152BD0,但是这块内存溢出了。
看一下堆栈
0:000> kv
ChildEBP RetAddr  Args to Child              
0012fc04 7c98c201 0012fc24 7c97d454 00152bc0 ntdll!DbgBreakPoint (FPO: [0,0,0])
0012fc0c 7c97d454 00152bc0 00152bc0 00150000 ntdll!RtlpBreakPointHeap+0x28 (FPO: [Non-Fpo])
0012fc24 7c98c5cf 00000000 00150000 00152bc8 ntdll!RtlpCheckBusyBlockTail+0x76 (FPO: [Non-Fpo])
0012fc38 7c98d826 00150000 00152bc0 7c98d9dc ntdll!RtlpValidateHeapEntry+0xa4 (FPO: [Non-Fpo])
0012fcac 7c969e1c 00150000 50000061 00152bc8 ntdll!RtlDebugFreeHeap+0x97 (FPO: [Non-Fpo])
0012fd94 7c947553 00150000 40000060 00152bc8 ntdll!RtlFreeHeapSlowly+0x37 (FPO: [Non-Fpo])
*** WARNING: Unable to verify checksum for HeapOverflow.exe
[COLOR=Red]0012fe64 00413628 00150000 00000000 00152bc8 ntdll!RtlFreeHeap+0xf9 (FPO: [Non-Fpo])
0012ff68 00411a6f 00000001 00392b40 00392bf8 HeapOverflow!wmain+0xa8 (FPO: [Non-Fpo]) (CONV: cdecl) [d:\test\windbgtest\heapoverflow\heapoverflow.cpp @ 22]
0012ffb8 0041189f 0012fff0 7c817067 012ff6ee HeapOverflow!__tmainCRTStartup+0x1bf (FPO: [Non-Fpo]) (CONV: cdecl) [f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c @ 552]
0012ffc0 7c817067 012ff6ee 012ff776 7ffd5000 HeapOverflow!wmainCRTStartup+0xf (FPO: [Non-Fpo]) (CONV: cdecl) [f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c @ 371]
0012fff0 00000000 0041106e 00000000 78746341 kernel32!BaseProcessStart+0x23 (FPO: [Non-Fpo])

红色部分告诉我们是在调用RtlFreeHeap时候抛出的异常。看来当时在溢出时是没异常的!这个就很危险了。如果溢出后我们又做了其他操作,引起其他的异常我们再排查会很困难。
那是释放哪块内存引起的呢?查该函数的参数,第三个是释放地址:
00152bc8
看一下
00152bc8里的数据是神马
0:000> [COLOR=Red]dc 00152bc8 
00152bc8  34333231 38373635 33323139 37363534  [COLOR=Blue]1234567891234567
00152bd8  32313938 36353433 00393837 001a076c  [COLOR=Blue]89123456789.l...
00152be8  64636261 64676665 00786c64 feeeabab  abcdefgddlx.....
00152bf8  00000000 00000000 00040080 00ee14ee  ................
00152c08  00150178 00150178 feeefeee feeefeee  x...x...........
00152c18  feeefeee feeefeee feeefeee feeefeee  ................
00152c28  feeefeee feeefeee feeefeee feeefeee  ................
00152c38  feeefeee feeefeee feeefeee feeefeee  ................


我们看到正是pBuffer1的数据。也就是说是pBuffer1内存溢出了。
到这里其实也就结束了。不过咱们再看一下堆信息吧
0:000> [COLOR=Red]!heap
NtGlobalFlag enables following debugging aids for new heaps:    tail checking
    free checking
    validate parameters
Stop inside heap manager...validating heap address 0x00152bc0
Index   Address  Name      Debugging options enabled
  1:   00150000 
    Segment at 00150000 to 00250000 (00003000 bytes committed)
    Flags:                50000062
    ForceFlags:           40000060
    Granularity:          8 bytes
    Segment Reserve:      00100000
    Segment Commit:       00002000
    DeCommit Block Thres: 00000200
    DeCommit Total Thres: 00002000
    Total Free Size:      00000080
    Max. Allocation Size: 7ffdefff
    Lock Variable at:     00150608
    Next TagIndex:        0000
    Maximum TagIndex:     0000
    Tag Entries:          00000000
    PsuedoTag Entries:    00000000
    Virtual Alloc List:   00150050
    UCR FreeList:        00150598
    FreeList Usage:      00000000 00000000 00000000 00000000
    FreeList[ 00 ] at 00150178: 00152c08 . 00152c08   (1 block )
        00152990: 00058 . 00230 [07] - busy (214), tail fill - unable to read heap entry extra at 00152bb8
        00152bc0: 00230 . 00020 [07] - busy (8), tail fill - unable to read heap entry extra at 00152bd8
    Heap block at 00152bc0 modified at 00152bd0 past requested size of 8 (4 * 8 - 18)
        00152be0: 001c8 . 1c1b8 [07] - busy (1c19e), tail fill - unable to read heap entry extra at 0016ed90
    
[COLOR=Red]##CORRUPTION FOUND at 0x00152BE0
    PreviousSize field does not match Size field in previous entry 
    Entry->PreviousSize == 0x3837
    PreviousEntry->Size == 0x46
            unable to read heap entry at 0016ed98
##The above errors were found in segment at 0x00150640
    Flags:                50000062
    ForceFlags:           40000060
    Granularity:          8 bytes
    Segment Reserve:      00100000
    Segment Commit:       00002000
    DeCommit Block Thres: 00000200
    DeCommit Total Thres: 00002000
    Total Free Size:      00000080
    Max. Allocation Size: 7ffdefff
    Lock Variable at:     00150608
    Next TagIndex:        0000
    Maximum TagIndex:     0000
    Tag Entries:          00000000
    PsuedoTag Entries:    00000000
    Virtual Alloc List:   00150050
    UCR FreeList:        00150598
    FreeList Usage:      00000000 00000000 00000000 00000000
    FreeList[ 00 ] at 00150178: 00152c08 . 00152c08   (1 block )
        00152990: 00058 . 00230 [07] - busy (214), tail fill - unable to read heap entry extra at 00152bb8
        00152bc0: 00230 . 00020 [07] - busy (8), tail fill - unable to read heap entry extra at 00152bd8
    Heap block at 00152bc0 modified at 00152bd0 past requested size of 8 (4 * 8 - 18)
        00152be0: 001c8 . 1c1b8 [07] - busy (1c19e), tail fill - unable to read heap entry extra at 0016ed90
    
##CORRUPTION FOUND at 0x00152BE0
    PreviousSize field does not match Size field in previous entry 
    Entry->PreviousSize == 0x3837
    PreviousEntry->Size == 0x46
            unable to read heap entry at 0016ed98
##The above errors were found in segment at 0x00150640


上面说找不到0x00152BE0这个堆块了。再看一下默认堆的详细信息
0:000> !heap -a 00150000 
Index   Address  Name      Debugging options enabled
  1:   00150000 
    Segment at 00150000 to 00250000 (00003000 bytes committed)
    Flags:                50000062
    ForceFlags:           40000060
    Granularity:          8 bytes
    Segment Reserve:      00100000
    Segment Commit:       00002000
    DeCommit Block Thres: 00000200
    DeCommit Total Thres: 00002000
    Total Free Size:      00000080
    Max. Allocation Size: 7ffdefff
    Lock Variable at:     00150608
    Next TagIndex:        0000
    Maximum TagIndex:     0000
    Tag Entries:          00000000
    PsuedoTag Entries:    00000000
    Virtual Alloc List:   00150050
    UCR FreeList:        00150598
    FreeList Usage:      00000000 00000000 00000000 00000000
    FreeList[ 00 ] at 00150178: 00152c08 . 00152c08  
        00152c00: 00020 . 00400 [14] - free
    Segment00 at 00150640:
        Flags:           00000000
        Base:            00150000
        First Entry:     00150680
        Last Entry:      00250000
        Total Pages:     00000100
        Total UnCommit:  000000fd
        Largest UnCommit:000fd000
        UnCommitted Ranges: (1)
            00153000: 000fd000

    Heap entries for Segment00 in Heap 00150000
        00150000: 00000 . 00640 [01] - busy (640)
        00150640: 00640 . 00040 [01] - busy (40)
        00150680: 00040 . 01818 [07] - busy (1800), tail fill - unable to read heap entry extra at 00151e90
        00151e98: 01818 . 00040 [07] - busy (22), tail fill - unable to read heap entry extra at 00151ed0
        00151ed8: 00040 . 00050 [07] - busy (37), tail fill - unable to read heap entry extra at 00151f20
        00151f28: 00050 . 002f0 [07] - busy (2d8), tail fill - unable to read heap entry extra at 00152210
        00152218: 002f0 . 00330 [07] - busy (314), tail fill - unable to read heap entry extra at 00152540
        00152548: 00330 . 00330 [07] - busy (314), tail fill - unable to read heap entry extra at 00152870
        00152878: 00330 . 00040 [07] - busy (24), tail fill - unable to read heap entry extra at 001528b0
        001528b8: 00040 . 00028 [07] - busy (10), tail fill - unable to read heap entry extra at 001528d8
        001528e0: 00028 . 00058 [07] - busy (40), tail fill - unable to read heap entry extra at 00152930
        00152938: 00058 . 00058 [07] - busy (40), tail fill - unable to read heap entry extra at 00152988
        00152990: 00058 . 00230 [07] - busy (214), tail fill - unable to read heap entry extra at 00152bb8
        [COLOR=Red]00152bc0: 00230 . 00020 [07] - busy (8), tail fill - unable to read heap entry extra at 00152bd8
        [COLOR=Blue]00152be0: [COLOR=Red]001c8 . 1c1b8 [07] - busy (1c19e), tail fill - unable to read heap entry extra at 0016ed90
            unable to read heap entry at 0016ed98


红色的那行有一个 busy (8)表示申请了8个字节的内存块。整个块占用00020字节。
但是到了下面蓝色的那行就出错了。为啥呢?因为有一个
001c8。本来001c8应该是上一块内存大小的。应该=00020。但是现在却=001c8。自身大小为1c1b8,分配的大小为1c19e。这就更不对了。查完一遍,就是没找到楼主申请的6字节的内存块。根据刚才的内存转储,6字节的内存块正在8字节内存块的下面。
这么说来,蓝色的哪一行本来要显示6字节内存块数据的。但是由于上一个块内存溢出了,吧它的堆元数据给冲了,导致堆数据被破坏,从而显示了错误的数据。

通过上面的观察,咱们已经知道,在溢出时是不会产生异常的,异常是在释放的时候才产生。那怎么才能在溢出时马上让其抛出异常?
使用应用程序检查器 Application Verifier。此工具对这类错误检查非常好用,本身的用法很简单。这里不做介绍。

源码在此

HeapOverflow.rar

上传的附件:
2013-10-4 01:35
0
雪    币: 1491
活跃值: (985)
能力值: (RANK:860 )
在线值:
发帖
回帖
粉丝
120
强烈支持,有些命令我都没有掌握。谢谢楼主的总结
2013-10-4 01:41
0
雪    币: 541
活跃值: (654)
能力值: ( LV12,RANK:250 )
在线值:
发帖
回帖
粉丝
121
先上代码
int _tmain(int argc, _TCHAR* argv[])
{

    char* pBuffer1 = new char[8];
    char* pBuffer2 = new char[6];

    strcpy( pBuffer1, "12345678");
    strcpy( pBuffer2, "abcdefg");

    delete [] pBuffer1;
    delete [] pBuffer2;
    getchar();
    return 0;
}
咱们先看Debug版
用windbg启动调试后,会抛出异常窗口

点击“重试”后,断在这里
[COLOR=Red](408.34c): Break instruction exception - code 80000003 (first chance)
eax=00000001 ebx=7ffd6000 ecx=f8cab03f edx=00150608 esi=0142f776 edi=0012ff68
eip=10316ccb esp=0012fdd0 ebp=0012fdd4 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
MSVCR100D!_free_dbg_nolock+0x31b:
10316ccb cc              int     3
注意,上面红色部分不是说堆坏了。这个是C++抛出的异常!
看一下栈
0:000> [COLOR=Red]kv
ChildEBP RetAddr  Args to Child              
0012fdd4 10316970 003946d0 00000001 f8d84e33 MSVCR100D!_free_dbg_nolock+0x31b (FPO: [Non-Fpo]) (CONV: cdecl) [f:\dd\vctools\crt_bld\self_x86\crt\src\dbgheap.c @ 1376]
0012fe0c 10315a39 003946d0 00000001 f8d84e77 MSVCR100D!_free_dbg+0x50 (FPO: [Non-Fpo]) (CONV: cdecl) [f:\dd\vctools\crt_bld\self_x86\crt\src\dbgheap.c @ 1265]
*** WARNING: Unable to verify checksum for HeapOverflow.exe
[COLOR=Blue]0012fe48 00411427 003946d0 0142f6ee 0142f776 MSVCR100D!operator delete+0xb9 (FPO: [Non-Fpo]) (CONV: cdecl) [f:\dd\vctools\crt_bld\self_x86\crt\src\dbgdel.cpp @ 54]
0012ff68 00411a0f 00000001 00392b40 00392bf8 HeapOverflow!wmain+0x87 (FPO: [Non-Fpo]) (CONV: cdecl) [d:\test\windbgtest\heapoverflow\heapoverflow.cpp @ 17]
0012ffb8 0041183f 0012fff0 7c817067 0142f6ee HeapOverflow!__tmainCRTStartup+0x1bf (FPO: [Non-Fpo]) (CONV: cdecl) [f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c @ 552]
0012ffc0 7c817067 0142f6ee 0142f776 7ffd6000 HeapOverflow!wmainCRTStartup+0xf (FPO: [Non-Fpo]) (CONV: cdecl) [f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c @ 371]
0012fff0 00000000 0041106e 00000000 78746341 kernel32!BaseProcessStart+0x23 (FPO: [Non-Fpo])

这个也是在释放的时候抛出的异常。正在Delete的内存块是003946d0。看一下里面的数据是什么
0:000> [COLOR=Red]dc 003946d0 
003946d0  34333231 38373635 fdfdfd00 abababab  [COLOR=Blue]12345678........
003946e0  abababab feeefeee 00000000 00000000  ................
003946f0  00090009 001e0769 003946b0 00000000  ....i....F9.....
00394700  00000000 00000000 00000006 00000001  ................
00394710  00000054 fdfdfdfd 64636261 00676665  T.......abcdefg.
00394720  ababfdfd abababab feeeabab feeefeee  ................
00394730  00000000 00000000 00090135 00ee04ee  ........5.......
00394740  003960f0 00390178 feeefeee feeefeee  .`9.x.9.........
正是pBuffer1。
咱们再看一下堆信息
0:000> [COLOR=Red]!heap
NtGlobalFlag enables following debugging aids for new heaps:    tail checking
    free checking
    validate parameters
Index   Address  Name      Debugging options enabled
  1:   00150000                 tail checking free checking validate parameters
  2:   00250000                 tail checking free checking validate parameters
  3:   00260000                 tail checking free checking validate parameters
[COLOR=Blue]  4:   00390000                 tail checking free checking validate parameters
  5:   003b0000                 tail checking free checking validate parameters
  6:   003e0000                 tail checking free checking validate parameters

刚才释放的内存是003946d0,在00390000 这个堆中。看一下这个堆的详细信息
0:000>[COLOR=Red] !heap -a 00390000                 
Index   Address  Name      Debugging options enabled
  4:   00390000 
    Segment at 00390000 to 003a0000 (00007000 bytes committed)
    Flags:                50001062
    ForceFlags:           40000060
    Granularity:          8 bytes
    Segment Reserve:      00100000
    Segment Commit:       00002000
    DeCommit Block Thres: 00000200
    DeCommit Total Thres: 00002000
    Total Free Size:      00000318
    Max. Allocation Size: 7ffdefff
    Lock Variable at:     00390608
    Next TagIndex:        0000
    Maximum TagIndex:     0000
    Tag Entries:          00000000
    PsuedoTag Entries:    00000000
    Virtual Alloc List:   00390050
    UCR FreeList:        00390598
    FreeList Usage:      00000000 00000000 00000000 00000000
    FreeList[ 00 ] at 00390178: 003960f0 . 00394740  
        00394738: 00048 . 009a8 [04] - free
        003960e8: 000d0 . 00f18 [14] - free
    Segment00 at 00390640:
        Flags:           00000000
        Base:            00390000
        First Entry:     00390680
        Last Entry:      003a0000
        Total Pages:     00000010
        Total UnCommit:  00000009
        Largest UnCommit:00009000
        UnCommitted Ranges: (1)
            00397000: 00009000

    Heap entries for Segment00 in Heap 00390000
        00390000: 00000 . 00640 [01] - busy (640)
        00390640: 00640 . 00040 [01] - busy (40)
        00390680: 00040 . 01818 [07] - busy (1800), tail fill - unable to read heap entry extra at 00391e90
        00391e98: 01818 . 00250 [07] - busy (238), tail fill - unable to read heap entry extra at 003920e0
        003920e8: 00250 . 00840 [07] - busy (824), tail fill - unable to read heap entry extra at 00392920
        00392928: 00840 . 000c0 [07] - busy (a4), tail fill - unable to read heap entry extra at 003929e0
        003929e8: 000c0 . 00090 [07] - busy (78), tail fill - unable to read heap entry extra at 00392a70
        00392a78: 00090 . 00048 [07] - busy (30), tail fill - unable to read heap entry extra at 00392ab8
        00392ac0: 00048 . 00058 [07] - busy (3c), tail fill - unable to read heap entry extra at 00392b10
        00392b18: 00058 . 000b8 [07] - busy (9a), tail fill - unable to read heap entry extra at 00392bc8
        00392bd0: 000b8 . 000c0 [07] - busy (a8), tail fill - unable to read heap entry extra at 00392c88
        00392c90: 000c0 . 000a8 [07] - busy (8c), tail fill - unable to read heap entry extra at 00392d30
        00392d38: 000a8 . 000c0 [07] - busy (a6), tail fill - unable to read heap entry extra at 00392df0
        00392df8: 000c0 . 00070 [07] - busy (4a), tail fill - unable to read heap entry extra at 00392e60
        00392e68: 00070 . 00260 [07] - busy (244), tail fill - unable to read heap entry extra at 003930c0
        003930c8: 00260 . 000c0 [07] - busy (a8), tail fill - unable to read heap entry extra at 00393180
        00393188: 000c0 . 00070 [07] - busy (58), tail fill - unable to read heap entry extra at 003931f0
        003931f8: 00070 . 00080 [07] - busy (65), tail fill - unable to read heap entry extra at 00393270
        00393278: 00080 . 00050 [07] - busy (37), tail fill - unable to read heap entry extra at 003932c0
        003932c8: 00050 . 00070 [07] - busy (55), tail fill - unable to read heap entry extra at 00393330
        00393338: 00070 . 00058 [07] - busy (3d), tail fill - unable to read heap entry extra at 00393388
        00393390: 00058 . 00060 [07] - busy (48), tail fill - unable to read heap entry extra at 003933e8
        003933f0: 00060 . 00050 [07] - busy (38), tail fill - unable to read heap entry extra at 00393438
        00393440: 00050 . 00050 [07] - busy (31), tail fill - unable to read heap entry extra at 00393488
        00393490: 00050 . 00070 [07] - busy (53), tail fill - unable to read heap entry extra at 003934f8
        00393500: 00070 . 00058 [07] - busy (3e), tail fill - unable to read heap entry extra at 00393550
        00393558: 00058 . 00058 [07] - busy (3b), tail fill - unable to read heap entry extra at 003935a8
        003935b0: 00058 . 00050 [07] - busy (32), tail fill - unable to read heap entry extra at 003935f8
        00393600: 00050 . 000e0 [07] - busy (c3), tail fill - unable to read heap entry extra at 003936d8
        003936e0: 000e0 . 00078 [07] - busy (5d), tail fill - unable to read heap entry extra at 00393750
        00393758: 00078 . 00058 [07] - busy (3f), tail fill - unable to read heap entry extra at 003937a8
        003937b0: 00058 . 00088 [07] - busy (69), tail fill - unable to read heap entry extra at 00393830
        00393838: 00088 . 00050 [07] - busy (37), tail fill - unable to read heap entry extra at 00393880
        00393888: 00050 . 00058 [07] - busy (3c), tail fill - unable to read heap entry extra at 003938d8
        003938e0: 00058 . 00060 [07] - busy (42), tail fill - unable to read heap entry extra at 00393938
        00393940: 00060 . 00050 [07] - busy (38), tail fill - unable to read heap entry extra at 00393988
        00393990: 00050 . 00050 [07] - busy (33), tail fill - unable to read heap entry extra at 003939d8
        003939e0: 00050 . 00058 [07] - busy (3a), tail fill - unable to read heap entry extra at 00393a30
        00393a38: 00058 . 00068 [07] - busy (4c), tail fill - unable to read heap entry extra at 00393a98
        00393aa0: 00068 . 00068 [07] - busy (4b), tail fill - unable to read heap entry extra at 00393b00
        00393b08: 00068 . 00058 [07] - busy (3b), tail fill - unable to read heap entry extra at 00393b58
        00393b60: 00058 . 00058 [07] - busy (3b), tail fill - unable to read heap entry extra at 00393bb0
        00393bb8: 00058 . 00070 [07] - busy (58), tail fill - unable to read heap entry extra at 00393c20
        00393c28: 00070 . 00088 [07] - busy (70), tail fill - unable to read heap entry extra at 00393ca8
        00393cb0: 00088 . 00060 [07] - busy (43), tail fill - unable to read heap entry extra at 00393d08
        00393d10: 00060 . 00080 [07] - busy (62), tail fill - unable to read heap entry extra at 00393d88
        00393d90: 00080 . 00050 [07] - busy (36), tail fill - unable to read heap entry extra at 00393dd8
        00393de0: 00050 . 00088 [07] - busy (6e), tail fill - unable to read heap entry extra at 00393e60
        00393e68: 00088 . 00840 [07] - busy (824), tail fill - unable to read heap entry extra at 003946a0
        003946a8: 00840 . 00048 [07] - busy (2c), tail fill - unable to read heap entry extra at 003946e8
        003946f0: 00048 . 00048 [07] - busy (2a), tail fill - unable to read heap entry extra at 00394730
        00394738: 00048 . 009a8 [04] free fill
        003950e0: 009a8 . 000a0 [07] - busy (86), tail fill - unable to read heap entry extra at 00395178
        00395180: 000a0 . 00070 [07] - busy (56), tail fill - unable to read heap entry extra at 003951e8
        003951f0: 00070 . 00088 [07] - busy (6c), tail fill - unable to read heap entry extra at 00395270
        00395278: 00088 . 00068 [07] - busy (4c), tail fill - unable to read heap entry extra at 003952d8
        003952e0: 00068 . 00058 [07] - busy (3e), tail fill - unable to read heap entry extra at 00395330
        00395338: 00058 . 000a0 [07] - busy (82), tail fill - unable to read heap entry extra at 003953d0
        003953d8: 000a0 . 00070 [07] - busy (58), tail fill - unable to read heap entry extra at 00395440
        00395448: 00070 . 00070 [07] - busy (52), tail fill - unable to read heap entry extra at 003954b0
        003954b8: 00070 . 00058 [07] - busy (40), tail fill - unable to read heap entry extra at 00395508
        00395510: 00058 . 00180 [07] - busy (162), tail fill - unable to read heap entry extra at 00395688
        00395690: 00180 . 000b0 [07] - busy (96), tail fill - unable to read heap entry extra at 00395738
        00395740: 000b0 . 00078 [07] - busy (5a), tail fill - unable to read heap entry extra at 003957b0
        003957b8: 00078 . 000c8 [07] - busy (ae), tail fill - unable to read heap entry extra at 00395878
        00395880: 000c8 . 00068 [07] - busy (4a), tail fill - unable to read heap entry extra at 003958e0
        003958e8: 00068 . 00070 [07] - busy (54), tail fill - unable to read heap entry extra at 00395950
        00395958: 00070 . 00078 [07] - busy (60), tail fill - unable to read heap entry extra at 003959c8
        003959d0: 00078 . 00068 [07] - busy (4c), tail fill - unable to read heap entry extra at 00395a30
        00395a38: 00068 . 00060 [07] - busy (42), tail fill - unable to read heap entry extra at 00395a90
        00395a98: 00060 . 00068 [07] - busy (50), tail fill - unable to read heap entry extra at 00395af8
        00395b00: 00068 . 00090 [07] - busy (74), tail fill - unable to read heap entry extra at 00395b88
        00395b90: 00090 . 00090 [07] - busy (72), tail fill - unable to read heap entry extra at 00395c18
        00395c20: 00090 . 00070 [07] - busy (52), tail fill - unable to read heap entry extra at 00395c88
        00395c90: 00070 . 00070 [07] - busy (52), tail fill - unable to read heap entry extra at 00395cf8
        00395d00: 00070 . 000a8 [07] - busy (8c), tail fill - unable to read heap entry extra at 00395da0
        00395da8: 000a8 . 000d8 [07] - busy (bc), tail fill - unable to read heap entry extra at 00395e78
        00395e80: 000d8 . 00080 [07] - busy (62), tail fill - unable to read heap entry extra at 00395ef8
        00395f00: 00080 . 000b8 [07] - busy (a0), tail fill - unable to read heap entry extra at 00395fb0
        00395fb8: 000b8 . 00060 [07] - busy (48), tail fill - unable to read heap entry extra at 00396010
        00396018: 00060 . 000d0 [07] - busy (b8), tail fill - unable to read heap entry extra at 003960e0
        003960e8: 000d0 . 00f18 [14] free fill
        00397000:      00009000      - uncommitted bytes.
找不到分配的8字节和6字节内存块,这是为什么呢?因为C++在申请内存时会申请更大的一块内存,用来存放C++运行时信息。所以虽然你申请的是8字节,但是实际上申请的自己数比8大。
再来看一下Release版
用windbg启动调试后,不会抛出异常对话框(与Debug版区别一)
直接断下来
[COLOR=Red]HEAP[HeapOverflow.exe]: Heap block at 00395630 modified at 00395640 past requested size of 8
(650.61c): Break instruction exception - code 80000003 (first chance)
eax=00395630 ebx=00395640 ecx=7c93eab5 edx=0012faf0 esi=00395630 edi=00000008
eip=7c92120e esp=0012fcf4 ebp=0012fcf8 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ntdll!DbgBreakPoint:
7c92120e cc              int     3
看红色部分证明堆被破坏了。再看一下栈
0:000> [COLOR=Red]kv
ChildEBP RetAddr  Args to Child              
0012fcf0 7c98c201 0012fd10 7c97d454 00395630 ntdll!DbgBreakPoint (FPO: [0,0,0])
0012fcf8 7c97d454 00395630 00395630 00390000 ntdll!RtlpBreakPointHeap+0x28 (FPO: [Non-Fpo])
0012fd10 7c98c5cf 00000000 00390000 00395638 ntdll!RtlpCheckBusyBlockTail+0x76 (FPO: [Non-Fpo])
0012fd24 7c98d826 00390000 00395630 7c98d9dc ntdll!RtlpValidateHeapEntry+0xa4 (FPO: [Non-Fpo])
0012fd98 7c969e1c 00390000 50000061 00395638 ntdll!RtlDebugFreeHeap+0x97 (FPO: [Non-Fpo])
0012fe80 7c947553 00390000 40000060 00395638 ntdll!RtlFreeHeapSlowly+0x37 (FPO: [Non-Fpo])
0012ff50 78ab016a 00390000 00000000 00395638 ntdll!RtlFreeHeap+0xf9 (FPO: [Non-Fpo])
[COLOR=Blue]0012ff64 00401046 00395638 00000006 00000008 MSVCR100!free+0x1c (FPO: [Non-Fpo])
0012ff7c 004011d3 00000001 00392a48 00392ae0 HeapOverflow!wmain+0x46 (FPO: [2,0,0]) (CONV: cdecl) [d:\test\windbgtest\heapoverflow\heapoverflow.cpp @ 18]
0012ffc0 7c817067 0142f6ee 0142f77a 7ffda000 HeapOverflow!__tmainCRTStartup+0x122 (FPO: [Non-Fpo]) (CONV: cdecl) [f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c @ 552]
0012fff0 00000000 004012f4 00000000 78746341 kernel32!BaseProcessStart+0x23 (FPO: [Non-Fpo])
还是在释放的时候抛的异常。此时不再走Delete,而是走的free。
看看00395638是哪个变量
0:000> [COLOR=Red]dc 00395638
00395638  34333231 38373635 ababab00 abababab  [COLOR=Blue]12345678........
00395648  00000000 00000000 00040004 001a07b3  ................
00395658  64636261 00676665 abababab feeeabab  abcdefg.........
00395668  00000000 00000000 00040132 00ee14ee  ........2.......
00395678  00394150 00390178 feeefeee feeefeee  PA9.x.9.........
00395688  feeefeee feeefeee feeefeee feeefeee  ................
00395698  feeefeee feeefeee feeefeee feeefeee  ................
003956a8  feeefeee feeefeee feeefeee feeefeee  ................
是pBuffer1的内存块。证明是pBuffer1内存溢出了。
在分析一下堆
0:000>[COLOR=Red] !heap 
NtGlobalFlag enables following debugging aids for new heaps:    tail checking
    free checking
    validate parameters
Stop inside heap manager...validating heap address 0x00395630
Index   Address  Name      Debugging options enabled
  1:   00150000 
    Segment at 00150000 to 00250000 (00003000 bytes committed)
  2:   00250000 
    Segment at 00250000 to 00260000 (00006000 bytes committed)
  3:   00260000 
    Segment at 00260000 to 00270000 (00003000 bytes committed)
  [COLOR=Blue]4:   00390000 
    Segment at 00390000 to 003a0000 (00006000 bytes committed)
    Flags:                50001062
    ForceFlags:           40000060
    Granularity:          8 bytes
    Segment Reserve:      00100000
    Segment Commit:       00002000
    DeCommit Block Thres: 00000200
    DeCommit Total Thres: 00002000
    Total Free Size:      00000277
    Max. Allocation Size: 7ffdefff
    Lock Variable at:     00390608
    Next TagIndex:        0000
    Maximum TagIndex:     0000
    Tag Entries:          00000000
    PsuedoTag Entries:    00000000
    Virtual Alloc List:   00390050
    UCR FreeList:        00390598
    FreeList Usage:      00000004 00000000 00000000 00000000
    FreeList[ 00 ] at 00390178: 00394150 . 00395678   (2 blocks)
    FreeList[ 02 ] at 00390188: 00392df0 . 00392df0   (1 block )
        00395580: 00040 . 000b0 [07] - busy (94), tail fill - unable to read heap entry extra at 00395628
        00395630: 000b0 . 00020 [07] - busy (8), tail fill - unable to read heap entry extra at 00395648
    Heap block at 00395630 modified at 00395640 past requested size of 8 (4 * 8 - 18)
        00395650: 00020 . 00020 [07] - busy (6), tail fill - unable to read heap entry extra at 00395668
    [COLOR=Red]Heap block at 00395650 modified at 0039565e past requested size of 6 (4 * 8 - 1a)
##The above errors were found in segment at 0x00390640
    Flags:                50001062
    ForceFlags:           40000060
    Granularity:          8 bytes
    Segment Reserve:      00100000
    Segment Commit:       00002000
    DeCommit Block Thres: 00000200
    DeCommit Total Thres: 00002000
    Total Free Size:      00000277
    Max. Allocation Size: 7ffdefff
    Lock Variable at:     00390608
    Next TagIndex:        0000
    Maximum TagIndex:     0000
    Tag Entries:          00000000
    PsuedoTag Entries:    00000000
    Virtual Alloc List:   00390050
    UCR FreeList:        00390598
    FreeList Usage:      00000004 00000000 00000000 00000000
    FreeList[ 00 ] at 00390178: 00394150 . 00395678   (2 blocks)
    FreeList[ 02 ] at 00390188: 00392df0 . 00392df0   (1 block )
        00395580: 00040 . 000b0 [07] - busy (94), tail fill - unable to read heap entry extra at 00395628
        00395630: 000b0 . 00020 [07] - busy (8), tail fill - unable to read heap entry extra at 00395648
    Heap block at 00395630 modified at 00395640 past requested size of 8 (4 * 8 - 18)
        00395650: 00020 . 00020 [07] - busy (6), tail fill - unable to read heap entry extra at 00395668
    Heap block at 00395650 modified at 0039565e past requested size of 6 (4 * 8 - 1a)
##The above errors were found in segment at 0x00390640
此时告诉我们00390000 堆的00395630处出错了。pBuffer1=003946d0,正好是00390000堆中的内存。
再看一下详细数据:
0:000> [COLOR=Red]!heap -a 00390000
Index   Address  Name      Debugging options enabled
  4:   00390000 
    Segment at 00390000 to 003a0000 (00006000 bytes committed)
    Flags:                50001062
    ForceFlags:           40000060
    Granularity:          8 bytes
    Segment Reserve:      00100000
    Segment Commit:       00002000
    DeCommit Block Thres: 00000200
    DeCommit Total Thres: 00002000
    Total Free Size:      00000277
    Max. Allocation Size: 7ffdefff
    Lock Variable at:     00390608
    Next TagIndex:        0000
    Maximum TagIndex:     0000
    Tag Entries:          00000000
    PsuedoTag Entries:    00000000
    Virtual Alloc List:   00390050
    UCR FreeList:        00390598
    FreeList Usage:      00000004 00000000 00000000 00000000
    FreeList[ 00 ] at 00390178: 00394150 . 00395678  
        00395670: 00020 . 00990 [14] - free
        00394148: 00818 . 00a18 [04] - free
    FreeList[ 02 ] at 00390188: 00392df0 . 00392df0  
        00392de8: 00040 . 00010 [04] - free
    Segment00 at 00390640:
        Flags:           00000000
        Base:            00390000
        First Entry:     00390680
        Last Entry:      003a0000
        Total Pages:     00000010
        Total UnCommit:  0000000a
        Largest UnCommit:0000a000
        UnCommitted Ranges: (1)
            00396000: 0000a000

    Heap entries for Segment00 in Heap 00390000
        00390000: 00000 . 00640 [01] - busy (640)
        00390640: 00640 . 00040 [01] - busy (40)
        00390680: 00040 . 01818 [07] - busy (1800), tail fill - unable to read heap entry extra at 00391e90
        00391e98: 01818 . 00230 [07] - busy (214), tail fill - unable to read heap entry extra at 003920c0
        003920c8: 00230 . 00818 [07] - busy (800), tail fill - unable to read heap entry extra at 003928d8
        003928e0: 00818 . 00098 [07] - busy (80), tail fill - unable to read heap entry extra at 00392970
        00392978: 00098 . 00070 [07] - busy (54), tail fill - unable to read heap entry extra at 003929e0
        003929e8: 00070 . 00028 [07] - busy (c), tail fill - unable to read heap entry extra at 00392a08
        00392a10: 00028 . 00030 [07] - busy (18), tail fill - unable to read heap entry extra at 00392a38
        00392a40: 00030 . 00098 [07] - busy (7a), tail fill - unable to read heap entry extra at 00392ad0
        00392ad8: 00098 . 000a0 [07] - busy (84), tail fill - unable to read heap entry extra at 00392b70
        00392b78: 000a0 . 00080 [07] - busy (68), tail fill - unable to read heap entry extra at 00392bf0
        00392bf8: 00080 . 000a0 [07] - busy (82), tail fill - unable to read heap entry extra at 00392c90
        00392c98: 000a0 . 00040 [07] - busy (26), tail fill - unable to read heap entry extra at 00392cd0
        00392cd8: 00040 . 00080 [07] - busy (62), tail fill - unable to read heap entry extra at 00392d50
        00392d58: 00080 . 00050 [07] - busy (32), tail fill - unable to read heap entry extra at 00392da0
        00392da8: 00050 . 00040 [07] - busy (28), tail fill - unable to read heap entry extra at 00392de0
        00392de8: 00040 . 00010 [04] free fill
        00392df8: 00010 . 00238 [07] - busy (220), tail fill - unable to read heap entry extra at 00393028
        00393030: 00238 . 000a0 [07] - busy (84), tail fill - unable to read heap entry extra at 003930c8
        003930d0: 000a0 . 00050 [07] - busy (34), tail fill - unable to read heap entry extra at 00393118
        00393120: 00050 . 00060 [07] - busy (41), tail fill - unable to read heap entry extra at 00393178
        00393180: 00060 . 00030 [07] - busy (13), tail fill - unable to read heap entry extra at 003931a8
        003931b0: 00030 . 00050 [07] - busy (31), tail fill - unable to read heap entry extra at 003931f8
        00393200: 00050 . 00038 [07] - busy (19), tail fill - unable to read heap entry extra at 00393230
        00393238: 00038 . 00040 [07] - busy (24), tail fill - unable to read heap entry extra at 00393270
        00393278: 00040 . 00030 [07] - busy (14), tail fill - unable to read heap entry extra at 003932a0
        003932a8: 00030 . 00028 [07] - busy (d), tail fill - unable to read heap entry extra at 003932c8
        003932d0: 00028 . 00048 [07] - busy (2f), tail fill - unable to read heap entry extra at 00393310
        00393318: 00048 . 00038 [07] - busy (1a), tail fill - unable to read heap entry extra at 00393348
        00393350: 00038 . 00030 [07] - busy (17), tail fill - unable to read heap entry extra at 00393378
        00393380: 00030 . 00028 [07] - busy (e), tail fill - unable to read heap entry extra at 003933a0
        003933a8: 00028 . 000b8 [07] - busy (9f), tail fill - unable to read heap entry extra at 00393458
        00393460: 000b8 . 00058 [07] - busy (39), tail fill - unable to read heap entry extra at 003934b0
        003934b8: 00058 . 00038 [07] - busy (1b), tail fill - unable to read heap entry extra at 003934e8
        003934f0: 00038 . 00060 [07] - busy (45), tail fill - unable to read heap entry extra at 00393548
        00393550: 00060 . 00030 [07] - busy (13), tail fill - unable to read heap entry extra at 00393578
        00393580: 00030 . 00030 [07] - busy (18), tail fill - unable to read heap entry extra at 003935a8
        003935b0: 00030 . 00038 [07] - busy (1e), tail fill - unable to read heap entry extra at 003935e0
        003935e8: 00038 . 00030 [07] - busy (14), tail fill - unable to read heap entry extra at 00393610
        00393618: 00030 . 00028 [07] - busy (f), tail fill - unable to read heap entry extra at 00393638
        00393640: 00028 . 00030 [07] - busy (16), tail fill - unable to read heap entry extra at 00393668
        00393670: 00030 . 00040 [07] - busy (28), tail fill - unable to read heap entry extra at 003936a8
        003936b0: 00040 . 00040 [07] - busy (27), tail fill - unable to read heap entry extra at 003936e8
        003936f0: 00040 . 00030 [07] - busy (17), tail fill - unable to read heap entry extra at 00393718
        00393720: 00030 . 00030 [07] - busy (17), tail fill - unable to read heap entry extra at 00393748
        00393750: 00030 . 00050 [07] - busy (34), tail fill - unable to read heap entry extra at 00393798
        003937a0: 00050 . 00068 [07] - busy (4c), tail fill - unable to read heap entry extra at 00393800
        00393808: 00068 . 00038 [07] - busy (1f), tail fill - unable to read heap entry extra at 00393838
        00393840: 00038 . 00058 [07] - busy (3e), tail fill - unable to read heap entry extra at 00393890
        00393898: 00058 . 00030 [07] - busy (12), tail fill - unable to read heap entry extra at 003938c0
        003938c8: 00030 . 00068 [07] - busy (4a), tail fill - unable to read heap entry extra at 00393928
        00393930: 00068 . 00818 [07] - busy (800), tail fill - unable to read heap entry extra at 00394140
        00394148: 00818 . 00a18 [04] free fill
        00394b60: 00a18 . 00060 [07] - busy (48), tail fill - unable to read heap entry extra at 00394bb8
        00394bc0: 00060 . 00038 [07] - busy (1a), tail fill - unable to read heap entry extra at 00394bf0
        00394bf8: 00038 . 00078 [07] - busy (5e), tail fill - unable to read heap entry extra at 00394c68
        00394c70: 00078 . 00050 [07] - busy (34), tail fill - unable to read heap entry extra at 00394cb8
        00394cc0: 00050 . 00048 [07] - busy (2e), tail fill - unable to read heap entry extra at 00394d00
        00394d08: 00048 . 00038 [07] - busy (1c), tail fill - unable to read heap entry extra at 00394d38
        00394d40: 00038 . 00158 [07] - busy (13e), tail fill - unable to read heap entry extra at 00394e90
        00394e98: 00158 . 00090 [07] - busy (72), tail fill - unable to read heap entry extra at 00394f20
        00394f28: 00090 . 00050 [07] - busy (36), tail fill - unable to read heap entry extra at 00394f70
        00394f78: 00050 . 000a8 [07] - busy (8a), tail fill - unable to read heap entry extra at 00395018
        00395020: 000a8 . 00040 [07] - busy (26), tail fill - unable to read heap entry extra at 00395058
        00395060: 00040 . 00048 [07] - busy (30), tail fill - unable to read heap entry extra at 003950a0
        003950a8: 00048 . 00058 [07] - busy (3c), tail fill - unable to read heap entry extra at 003950f8
        00395100: 00058 . 00040 [07] - busy (28), tail fill - unable to read heap entry extra at 00395138
        00395140: 00040 . 00038 [07] - busy (1e), tail fill - unable to read heap entry extra at 00395170
        00395178: 00038 . 00048 [07] - busy (2c), tail fill - unable to read heap entry extra at 003951b8
        003951c0: 00048 . 00068 [07] - busy (50), tail fill - unable to read heap entry extra at 00395220
        00395228: 00068 . 00068 [07] - busy (4e), tail fill - unable to read heap entry extra at 00395288
        00395290: 00068 . 00048 [07] - busy (2e), tail fill - unable to read heap entry extra at 003952d0
        003952d8: 00048 . 00048 [07] - busy (2e), tail fill - unable to read heap entry extra at 00395318
        00395320: 00048 . 00080 [07] - busy (68), tail fill - unable to read heap entry extra at 00395398
        003953a0: 00080 . 000b0 [07] - busy (98), tail fill - unable to read heap entry extra at 00395448
        00395450: 000b0 . 00058 [07] - busy (3e), tail fill - unable to read heap entry extra at 003954a0
        003954a8: 00058 . 00098 [07] - busy (7c), tail fill - unable to read heap entry extra at 00395538
        00395540: 00098 . 00040 [07] - busy (24), tail fill - unable to read heap entry extra at 00395578
        00395580: 00040 . 000b0 [07] - busy (94), tail fill - unable to read heap entry extra at 00395628
[COLOR=Blue]        00395630: 000b0 . 00020 [07] - busy (8), tail fill - unable to read heap entry extra at 00395648
        00395650: 00020 . 00020 [07] - busy (6), tail fill - unable to read heap entry extra at 00395668
        00395670: 00020 . 00990 [14] free fill
        00396000:      0000a000      - uncommitted bytes.
由于堆的元数据没有遭到严重破坏,堆块还是能分析出来的。

经过两篇堆溢出分析,可以得到结论就是:堆破坏越早发现越好。而系统只有在释放的时候才能检查出堆被破坏了。这不是我们想要的。
这个时候使用应用程序检查器 Application Verifier。可以帮助我们在溢出时就抛出异常。

源码在此:

HeapOverflow2.rar
上传的附件:
2013-10-4 02:33
0
雪    币: 541
活跃值: (654)
能力值: ( LV12,RANK:250 )
在线值:
发帖
回帖
粉丝
122
生成DMP命令: .dump
生成mini dmp
0:001>[COLOR=Red] .dump /m c:\dump3.dmp[/COLOR]
Creating c:\dump3.dmp - mini user dump
Dump successfully written
生成full dmp
0:001>[COLOR=Red] .dump /f c:\dump1.dmp[/COLOR]
Creating c:\dump1.dmp - user full dump
Dump successfully written
显示异常记录:.exr
显示上下文记录:.cxr

此两个命令通常在一块使用。在排查问题时非常好用。
如当我出现下列问题时
0:000> g

[COLOR=Silver]//下面的日志是有应用程序检查器输出的[/COLOR]
=======================================
VERIFIER STOP 00000013: pid 0x6DC: First chance access violation for current stack trace. 

    02245000 : Invalid address causing the exception.
    0040102A : Code address executing the invalid access.
    [COLOR=Red][B]0012FC88 [/B]: Exception record.
    [B]0012FCA4 [/B]: Context record.[/COLOR]


=======================================
This verifier stop is continuable.
After debugging it use `go' to continue.

=======================================

(6dc.314): Break instruction exception - code [COLOR=Blue]80000003 [/COLOR](first chance)
eax=1000e848 ebx=1000d088 ecx=00000001 edx=0012f891 esi=00000000 edi=1000e848
eip=7c92120e esp=0012f914 ebp=0012fb18 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ntdll!DbgBreakPoint:
7c92120e cc              int     3
0:000> [COLOR=Red]kv[/COLOR]
ChildEBP RetAddr  Args to Child              
0012f910 10003b68 10122c78 02245000 0012fc88 ntdll!DbgBreakPoint (FPO: [0,0,0])
0012fb18 100078c9 1000c540 00000013 02245000 vrfcore!VerifierStopMessageEx+0x4d1 (FPO: [Non-Fpo])
0012fb3c 00376262 00000013 00371b5c 02245000 vrfcore!VfCoreRedirectedStopMessage+0x81 (FPO: [Non-Fpo])
0012fb6c 00376af1 00000013 00371b5c 02245000 vfbasics!VerifierStopMessage+0x292 (FPO: [Non-Fpo])
0012fbc4 00377316 0012fbf0 7c99b3c0 01fbeff0 vfbasics!AVrfpCheckFirstChanceException+0xc8 (FPO: [Non-Fpo])
0012fbd8 7c962628 0012fbf0 0012fc88 0012fc88 vfbasics!AVrfpVectoredExceptionHandler+0x16 (FPO: [Non-Fpo])
0012fbf8 7c94a969 0012fc88 0012fca4 02244ff8 ntdll!RtlCallVectoredExceptionHandlers+0x48 (FPO: [Non-Fpo])
[COLOR=Blue]0012fc70 7c92e46a [B]0012fc88 0012fca4 [/B]0012fc88 ntdll!RtlDispatchException+0x19 (FPO: [Non-Fpo])[/COLOR]
[COLOR=Blue]0012fc70 0040102a [B]0012fc88 0012fca4 [/B]0012fc88 ntdll!KiUserExceptionDispatcher+0xe (FPO: [2,0,0]) (CONTEXT @ 0012fca4)[/COLOR]
0012ff7c 004011d3 00000001 021fcf80 02200f78 HeapOverflow!wmain+0x2a (FPO: [2,0,0]) (CONV: cdecl) [d:\test\windbgtest\heapoverflow\heapoverflow.cpp @ 14]
0012ffc0 7c817067 016af6ee 016af77a 7ffd4000 HeapOverflow!__tmainCRTStartup+0x122 (FPO: [Non-Fpo]) (CONV: cdecl) [f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c @ 552]
0012fff0 00000000 004012f4 00000000 78746341 kernel32!BaseProcessStart+0x23 (FPO: [Non-Fpo])

通过堆栈也能找到对应错误的异常记录和上下文记录。
异常记录为0012fc88
上下文记录为
0012fca4
查看异常的详细信息
0:000> [COLOR=Red].exr 0012fc88 [/COLOR]
[COLOR=Blue]ExceptionAddress: [B]0040102a [/B](HeapOverflow!wmain+0x0000002a)[/COLOR]
  [COLOR=Blue] ExceptionCode: [B]c0000005 [/B](Access violation)[/COLOR]
  ExceptionFlags: 00000000
NumberParameters: 2
   Parameter[0]: 00000001
   Parameter[1]: 02245000
Attempt to write to address 02245000
查看异常时的上下文
0:000>[COLOR=Red] .cxr 0012fca4 [/COLOR]
eax=34333231 ebx=00000000 ecx=38373635 edx=00000000 esi=02244ff8 edi=02246ff8
eip=0040102a esp=0012ff70 ebp=0012ffc0 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010202
HeapOverflow!wmain+0x2a:
[COLOR=Blue]0040102a 885608          mov     byte ptr [esi+8],dl        ds:0023:[B]02245000[/B]=??[/COLOR]
一下子就可以定位出错误了。
2013-10-4 03:08
0
雪    币: 541
活跃值: (654)
能力值: ( LV12,RANK:250 )
在线值:
发帖
回帖
粉丝
123
感谢老大鼓励
2013-10-4 03:10
0
雪    币: 433
活跃值: (1870)
能力值: ( LV17,RANK:1820 )
在线值:
发帖
回帖
粉丝
124
这个系列整理的挺不错的,有些命令自己平时也没用上,必须支持下
2013-10-4 10:37
0
雪    币: 6386
活跃值: (3475)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
125
国庆节大假,更新《现学现用-玩转windbgV0.3国庆节彩色版.chm》,学习学习。
2013-10-5 11:50
0
游客
登录 | 注册 方可回帖
返回
//