以下实例来自AWD
代码:
- /*++
- Copyright (c) Advanced Windows Debugging (ISBN 0321374460) from Addison-Wesley Professional. All rights reserved.
- THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
- KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
- PURPOSE.
- --*/
- #include "stdafx.h"
- #include <windows.h>
- #include <stdio.h>
- #include <conio.h>
- VOID SimulateMemoryCorruption ( ) ;
- class CAppInfo
- {
- public:
- CAppInfo(LPWSTR wszAppName, LPWSTR wszVersion)
- {
- m_wszAppName=wszAppName;
- m_wszVersion=wszVersion;
- }
- VOID PrintAppInfo()
- {
- wprintf(L"\nFull application Name: %s\n", m_wszAppName);
- wprintf(L"Version: %s\n", m_wszVersion);
- }
- private:
- LPWSTR m_wszAppName ;
- LPWSTR m_wszVersion ;
- } ;
- CAppInfo* g_AppInfo ;
- int __cdecl wmain (int argc, WCHAR* args[])
- {
- wint_t iChar = 0 ;
- g_AppInfo = new CAppInfo(L"Memory Corruption Sample", L"1.0" );
- if(!g_AppInfo)
- {
- return 1;
- }
- wprintf(L"Press: \n");
- wprintf(L" 1 To display application information\n");
- wprintf(L" 2 To simulated memory corruption\n");
- wprintf(L" 3 To exit\n\n\n>");
- while((iChar=_getwche())!='3')
- {
- switch(iChar)
- {
- case '1':
- g_AppInfo->PrintAppInfo();
- break;
- case '2':
- SimulateMemoryCorruption();
- wprintf(L"\nMemory Corruption completed\n");
- break;
- default:
- wprintf(L"\nInvalid option\n");
- }
- wprintf(L"\n\n> ");
- }
- return 0;
- }
- VOID SimulateMemoryCorruption ( )
- {
- char* pszWrite="Corrupt";
- BYTE* p=(BYTE*) g_AppInfo;
- CopyMemory(p, pszWrite, strlen(pszWrite));
- }
编译,生成Release,运行,选1再选2再选1,程序崩溃,打开Dump:
- 0:000> lm
- start end module name
- 00400000 00406000 test1 (deferred)
- 62c20000 62c29000 lpk (deferred)
- 73fa0000 7400b000 usp10 (deferred)
- 76300000 7631d000 imm32 (deferred)
- 76d70000 76d92000 apphelp (deferred)
- 77bd0000 77bd8000 version (deferred)
- 77d10000 77da0000 user32 (deferred)
- 77da0000 77e49000 advapi32 (deferred)
- 77e50000 77ee3000 rpcrt4 (deferred)
- 77ef0000 77f39000 gdi32 (deferred)
- 77fc0000 77fd1000 secur32 (deferred)
- 78520000 785c3000 msvcr90 (private pdb symbols) c:\mysymbol\msvcr90.i386.pdb\3ADD2E755BC041BC9149BFBE7C33387C1\msvcr90.i386.pdb
- 7c800000 7c91e000 kernel32 (deferred)
- 7c920000 7c9b6000 ntdll (pdb symbols) c:\mysymbol\ntdll.pdb\CEFC0863B1F84130A11E0F54180CD21A2\ntdll.pdb
加载符号文件:
- 0:000> .sympath+ D:\Project1\test1\Release
- Symbol search path is: C:\WINDOWS\Symbols;SRV*c:\mysymbol* http://msdl.microsoft.com/download/symbols ;D:\Project1\test1\Release
- WARNING: Whitespace at end of path element
- 0:000> .reload /f
- ..............
- Loading unloaded module list
- .........
- 0:000> lm
- start end module name
- 00400000 00406000 test1 (private pdb symbols) D:\Project1\test1\Release\test1.pdb
- 62c20000 62c29000 lpk (pdb symbols) C:\WINDOWS\Symbols\dll\lpk.pdb
- 73fa0000 7400b000 usp10 (pdb symbols) c:\mysymbol\usp10.pdb\D4BA2952809F469BB6D1D3AF6B956E6B1\usp10.pdb
- 76300000 7631d000 imm32 (pdb symbols) C:\WINDOWS\Symbols\dll\imm32.pdb
- 76d70000 76d92000 apphelp (pdb symbols) C:\WINDOWS\Symbols\dll\apphelp.pdb
- 77bd0000 77bd8000 version (pdb symbols) C:\WINDOWS\Symbols\dll\version.pdb
- 77d10000 77da0000 user32 (pdb symbols) C:\WINDOWS\Symbols\dll\user32.pdb
- 77da0000 77e49000 advapi32 (pdb symbols) c:\mysymbol\advapi32.pdb\F759D3F1C6614313B07C84BC33F02E4D2\advapi32.pdb
- 77e50000 77ee3000 rpcrt4 (pdb symbols) c:\mysymbol\rpcrt4.pdb\1A465C67828242F28A8C70E3B9D5C4772\rpcrt4.pdb
- 77ef0000 77f39000 gdi32 (pdb symbols) c:\mysymbol\gdi32.pdb\372C0F0E08FB456EAB7B4CB2B53E27952\gdi32.pdb
- 77fc0000 77fd1000 secur32 (pdb symbols) c:\mysymbol\secur32.pdb\7867B3F28B5C41CE847895E3FC013DC52\secur32.pdb
- 78520000 785c3000 msvcr90 (private pdb symbols) c:\mysymbol\msvcr90.i386.pdb\3ADD2E755BC041BC9149BFBE7C33387C1\msvcr90.i386.pdb
- 7c800000 7c91e000 kernel32 (pdb symbols) c:\mysymbol\kernel32.pdb\072FF0EB54D24DFAAE9D13885486EE092\kernel32.pdb
- 7c920000 7c9b6000 ntdll (pdb symbols) c:\mysymbol\ntdll.pdb\CEFC0863B1F84130A11E0F54180CD21A2\ntdll.pdb
查看堆栈:
- 0:000> kb
- ChildEBP RetAddr Args to Child
- 0012ff20 78556215 785b73c8 004020f4 00000000 msvcr90!_woutput_l+0x94c [f:\dd\vctools\crt_bld\self_x86\crt\src\output.c @ 1624]
- 0012ff64 004010ba 004020f4 72726f43 00403380 msvcr90!wprintf+0x73 [f:\dd\vctools\crt_bld\self_x86\crt\src\wprintf.c @ 63]
- 0012ff7c 00401252 00000001 00392940 00392998 test1!wmain+0xba [d:\project1\test1\test1\test1.cpp @ 58]
- 0012ffc0 7c817077 00300031 0032002d 7ffdc000 test1!__tmainCRTStartup+0x10f [f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c @ 583]
- 0012fff0 00000000 0040139a 00000000 78746341 kernel32!BaseProcessStart+0x23
看下58行代码,使用了 g_AppInfo->PrintAppInfo();
我们猜测,g_AppInfo的两个成员无效,因为wprintf调用的就是它们
找到g_AppInfo,列出它的成员:
- 0:000> x test1!*g_*
- 00403374 test1!g_AppInfo = 0x00395b10
- 004022f0 test1!_load_config_used = struct IMAGE_LOAD_CONFIG_DIRECTORY32_2
- 00402098 test1!_imp___amsg_exit = <no type information>
- 004014fa test1!_amsg_exit = <no type information>
- 0:000> dt CAppInfo 0x00395b10
- test1!CAppInfo
- +0x000 m_wszAppName : 0x72726f43 "--- memory read error at address 0x72726f43 ---"
- +0x004 m_wszVersion : 0x00747075 "???"
注意,这里dt要用CAppInfo告诉它解析的地址类型
那我们再来看看这两个局变量的内容:
- 0:000> dt CAppInfo 0x00395b10
- test1!CAppInfo
- +0x000 m_wszAppName : 0x72726f43 "--- memory read error at address 0x72726f43 ---"
- +0x004 m_wszVersion : 0x00747075 "???"
- 0:000> !address 0x72726f43
- 62c29000 : 62c29000 - 11377000
- Type 00000000
- Protect 00000001 PAGE_NOACCESS
- State 00010000 MEM_FREE
- Usage RegionUsageFree
- 0:000> !address 0x00747075
- 005f0000 : 005f0000 - 001be000
- Type 00020000 MEM_PRIVATE
- Protect 00000004 PAGE_READWRITE
- State 00001000 MEM_COMMIT
- Usage RegionUsageIsVAD
我们发现第一个变量竟然是不可访问的,找到问题了,
- 0:000> dc 0x00395b10
- 00395b10 72726f43 00747075 00020201 000801c2 Corrupt.........
- 00395b20 6c75460a 7061206c 63696c70 6f697461 .Full applicatio
- 00395b30 614e206e 203a656d 64657465 4320790a n Name: eted.y C
- 00395b40 7572726f 6f697470 6153206e 656c706d orruption Sample
- 00395b50 0000000a 00000000 00000000 00000000 ................
- 00395b60 00000000 00000000 00000000 00000000 ................
- 00395b70 00000000 00000000 00000000 00000000 ................
- 00395b80 00000000 00000000 00000000 00000000 ................
原来第一个变量竟然成了字符串Corrupt,查看代码,我们发现在按2时,程序强行把字符串"Corrupt"写入了
一些的指导性的建议和策略:
1通过命令dc将指针的内存内容转储出来,dc可以将内存内容以双字形式转储出来,如果在输出中看到有任何的字符串,那么可以通过命令da或du把字符串转储出来
2通过!address收集关于内存的信息,!address可以告诉你内存的类型(如私有内存),保护级别(读取和写入),状态(已提交或保留)和用途(栈或堆)
3.通过dds命令将内存转储为双字或者符号,这有助于将内存和特定的类型关联起来,
4.通过dpp命令对指针解引用,并且以双字形式转储出内存的内容,如果有任何一个双字匹配某个符号,那么这个符号也会被显示,如果在指针指向的内存中包含了一个虚函数表,那么
这种技术是非常有用的
5.通过dpa和dpu将指针指向的内存分别显示为ASII格式和Unicode格式
6.如果内存的内容是个很小的数值(4的值数)那么它可能是一个句柄,可以通过!handle来转储这个句柄的信息.