|
|
[求助]Irp结构体的操作
谁这么闲啊用偏移! |
|
|
[分享]发一下自己写的一个调试器,开源..求指导..求一起搞
强帖占位,广告招租 |
|
|
|
|
|
[原创]现学现用之windbg的高级玩法外篇一:获取某软件的聊天记录
318f9fa8属于模块内地址,是虚函数表的可能性很大。既然有虚函数,那一定是个类对象 |
|
|
|
|
|
[原创]获取URL中主机域名的小技巧!
楼主没考虑https |
|
|
[创业型(大公司背景)招人]Windows内核开发--欢迎大牛、小牛、安全行业等童鞋(6-20K,能力出众另议)
这话说的很中肯,做产品首先保证其稳定性。就是驱动写的很炫,不稳定有啥用啊。大家都知道写驱动就可能导致不稳定。尽量在应用层实现才是明智之选。 |
|
|
[求助]超级菜鸟求助各位大牛,a.dll 调用b.dll 我的为什么不成功呢
你加上全路径。这个问题应该是路径不对,找不到abc.dll |
|
|
|
|
|
[原创]现学现用之windbg的高级玩法(1,3,5,13,14,76,80,81,84,118,119,121,122楼已更新,chm文档集成7篇实战18个辅助工具)
生成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]一下子就可以定位出错误了。 |
|
|
[原创]现学现用之windbg的高级玩法(1,3,5,13,14,76,80,81,84,118,119,121,122楼已更新,chm文档集成7篇实战18个辅助工具)
先上代码
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 |
|
|
[原创]现学现用之windbg的高级玩法(1,3,5,13,14,76,80,81,84,118,119,121,122楼已更新,chm文档集成7篇实战18个辅助工具)
由于堆存在自定义堆,如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。此工具对这类错误检查非常好用,本身的用法很简单。这里不做介绍。 源码在此
|
|
|
[原创]现学现用之windbg的高级玩法(1,3,5,13,14,76,80,81,84,118,119,121,122楼已更新,chm文档集成7篇实战18个辅助工具)
在做这个实验之前,需要先构建数据。 首先是声明两个全局临界区和两个互斥对象 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)探测锁是否被占用 源码在此
|
|
|
[原创]现学现用之windbg的高级玩法(1,3,5,13,14,76,80,81,84,118,119,121,122楼已更新,chm文档集成7篇实战18个辅助工具)
感谢兄弟的大力支持。有没有兴趣加入群:151843490 |
|
|
[求助]windows权限的问题
楼主还是先学习一下windows的令牌和访问控制模型吧。 看懂了你就知道这个怎么办了。 下面的文章可以借鉴一下 http://bbs.pediy.com/showthread.php?t=173381 |
|
|
[原创]现学现用之windbg的高级玩法外篇一:获取某软件的聊天记录
执行到lea eax,[esp+0Ch] 时栈是这个样子的 |--------------------------------| |push 8 |--------------------------------| + c |call ret |--------------------------------| + 8 |push eax |--------------------------------| + 4 |push dword ptr fs:[0] |--------------------------------| + 0 --> esp 所以,esp+0Ch正好是调用此函数前的栈帧 |
|
|
[讨论]国产APEX,封死无数小白。求大神、教主级大湿指导。
APEX的悲哀啊,搞了这么多年,与主流游戏合作的很少。听说Apex的主程序不怎么更新了,期待以后能做出更出色的产品 |
|
|
[求助]WIN7 64位下的编程工具求分享
我就是win764+vs2010 |
|
|
[原创]中国招商银行设计严重缺陷
招商银行真是不拿国人当回事啊 |
操作理由
RANk
{{ user_info.golds == '' ? 0 : user_info.golds }}
雪币
{{ experience }}
课程经验
{{ score }}
学习收益
{{study_duration_fmt}}
学习时长
基本信息
荣誉称号:
{{ honorary_title }}
勋章
兑换勋章
证书
证书查询 >
能力值
