windbg-内存破坏实例分析

以下实例来自AWD

代码:

[cpp]  view plain  copy
  1. /*++ 
  2. Copyright (c) Advanced Windows Debugging (ISBN 0321374460) from Addison-Wesley Professional.  All rights reserved. 
  3.  
  4.     THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY 
  5.     KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 
  6.     IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR 
  7.     PURPOSE. 
  8.  
  9. --*/  
  10. #include "stdafx.h"  
  11. #include <windows.h>  
  12. #include <stdio.h>  
  13. #include <conio.h>  
  14.   
  15. VOID SimulateMemoryCorruption ( ) ;  
  16.   
  17. class CAppInfo  
  18. {  
  19. public:   
  20.     CAppInfo(LPWSTR wszAppName, LPWSTR wszVersion)  
  21.     {  
  22.         m_wszAppName=wszAppName;  
  23.         m_wszVersion=wszVersion;  
  24.     }  
  25.   
  26.     VOID PrintAppInfo()  
  27.     {  
  28.         wprintf(L"\nFull application Name: %s\n", m_wszAppName);  
  29.         wprintf(L"Version: %s\n", m_wszVersion);  
  30.     }  
  31.   
  32. private:  
  33.     LPWSTR m_wszAppName ;  
  34.     LPWSTR m_wszVersion ;  
  35. } ;  
  36.   
  37. CAppInfo* g_AppInfo ;  
  38.   
  39. int __cdecl wmain (int argc, WCHAR* args[])  
  40. {  
  41.     wint_t iChar = 0 ;  
  42.     g_AppInfo = new CAppInfo(L"Memory Corruption Sample", L"1.0" );  
  43.     if(!g_AppInfo)  
  44.     {  
  45.         return 1;  
  46.     }  
  47.   
  48.     wprintf(L"Press: \n");  
  49.     wprintf(L"    1    To display application information\n");  
  50.     wprintf(L"    2    To simulated memory corruption\n");  
  51.     wprintf(L"    3    To exit\n\n\n>");  
  52.   
  53.     while((iChar=_getwche())!='3')  
  54.     {  
  55.         switch(iChar)  
  56.         {  
  57.             case '1':  
  58.                g_AppInfo->PrintAppInfo();  
  59.                break;  
  60.   
  61.             case '2':  
  62.               SimulateMemoryCorruption();  
  63.               wprintf(L"\nMemory Corruption completed\n");  
  64.               break;  
  65.   
  66.             default:  
  67.               wprintf(L"\nInvalid option\n");  
  68.         }  
  69.         wprintf(L"\n\n> ");  
  70.     }  
  71.     return 0;  
  72. }  
  73.   
  74.   
  75. VOID SimulateMemoryCorruption ( )  
  76. {  
  77.     char* pszWrite="Corrupt";  
  78.     BYTE* p=(BYTE*) g_AppInfo;  
  79.     CopyMemory(p, pszWrite, strlen(pszWrite));  
  80. }  

编译,生成Release,运行,选1再选2再选1,程序崩溃,打开Dump:

[cpp]  view plain  copy
  1. 0:000> lm  
  2. start    end        module name  
  3. 00400000 00406000   test1      (deferred)               
  4. 62c20000 62c29000   lpk        (deferred)               
  5. 73fa0000 7400b000   usp10      (deferred)               
  6. 76300000 7631d000   imm32      (deferred)               
  7. 76d70000 76d92000   apphelp    (deferred)               
  8. 77bd0000 77bd8000   version    (deferred)               
  9. 77d10000 77da0000   user32     (deferred)               
  10. 77da0000 77e49000   advapi32   (deferred)               
  11. 77e50000 77ee3000   rpcrt4     (deferred)               
  12. 77ef0000 77f39000   gdi32      (deferred)               
  13. 77fc0000 77fd1000   secur32    (deferred)               
  14. 78520000 785c3000   msvcr90    (private pdb symbols)  c:\mysymbol\msvcr90.i386.pdb\3ADD2E755BC041BC9149BFBE7C33387C1\msvcr90.i386.pdb  
  15. 7c800000 7c91e000   kernel32   (deferred)               
  16. 7c920000 7c9b6000   ntdll      (pdb symbols)          c:\mysymbol\ntdll.pdb\CEFC0863B1F84130A11E0F54180CD21A2\ntdll.pdb  

加载符号文件:

[cpp]  view plain  copy
  1. 0:000> .sympath+ D:\Project1\test1\Release  
  2. Symbol search path is: C:\WINDOWS\Symbols;SRV*c:\mysymbol* http://msdl.microsoft.com/download/symbols ;D:\Project1\test1\Release  
  3. WARNING: Whitespace at end of path element  
  4. 0:000> .reload /f  
  5. ..............  
  6. Loading unloaded module list  
  7. .........  
  8. 0:000> lm  
  9. start    end        module name  
  10. 00400000 00406000   test1      (private pdb symbols)  D:\Project1\test1\Release\test1.pdb  
  11. 62c20000 62c29000   lpk        (pdb symbols)          C:\WINDOWS\Symbols\dll\lpk.pdb  
  12. 73fa0000 7400b000   usp10      (pdb symbols)          c:\mysymbol\usp10.pdb\D4BA2952809F469BB6D1D3AF6B956E6B1\usp10.pdb  
  13. 76300000 7631d000   imm32      (pdb symbols)          C:\WINDOWS\Symbols\dll\imm32.pdb  
  14. 76d70000 76d92000   apphelp    (pdb symbols)          C:\WINDOWS\Symbols\dll\apphelp.pdb  
  15. 77bd0000 77bd8000   version    (pdb symbols)          C:\WINDOWS\Symbols\dll\version.pdb  
  16. 77d10000 77da0000   user32     (pdb symbols)          C:\WINDOWS\Symbols\dll\user32.pdb  
  17. 77da0000 77e49000   advapi32   (pdb symbols)          c:\mysymbol\advapi32.pdb\F759D3F1C6614313B07C84BC33F02E4D2\advapi32.pdb  
  18. 77e50000 77ee3000   rpcrt4     (pdb symbols)          c:\mysymbol\rpcrt4.pdb\1A465C67828242F28A8C70E3B9D5C4772\rpcrt4.pdb  
  19. 77ef0000 77f39000   gdi32      (pdb symbols)          c:\mysymbol\gdi32.pdb\372C0F0E08FB456EAB7B4CB2B53E27952\gdi32.pdb  
  20. 77fc0000 77fd1000   secur32    (pdb symbols)          c:\mysymbol\secur32.pdb\7867B3F28B5C41CE847895E3FC013DC52\secur32.pdb  
  21. 78520000 785c3000   msvcr90    (private pdb symbols)  c:\mysymbol\msvcr90.i386.pdb\3ADD2E755BC041BC9149BFBE7C33387C1\msvcr90.i386.pdb  
  22. 7c800000 7c91e000   kernel32   (pdb symbols)          c:\mysymbol\kernel32.pdb\072FF0EB54D24DFAAE9D13885486EE092\kernel32.pdb  
  23. 7c920000 7c9b6000   ntdll      (pdb symbols)          c:\mysymbol\ntdll.pdb\CEFC0863B1F84130A11E0F54180CD21A2\ntdll.pdb  

查看堆栈:

[cpp]  view plain  copy
  1. 0:000> kb  
  2. ChildEBP RetAddr  Args to Child                
  3. 0012ff20 78556215 785b73c8 004020f4 00000000 msvcr90!_woutput_l+0x94c [f:\dd\vctools\crt_bld\self_x86\crt\src\output.c @ 1624]  
  4. 0012ff64 004010ba 004020f4 72726f43 00403380 msvcr90!wprintf+0x73 [f:\dd\vctools\crt_bld\self_x86\crt\src\wprintf.c @ 63]  
  5. 0012ff7c 00401252 00000001 00392940 00392998 test1!wmain+0xba [d:\project1\test1\test1\test1.cpp @ 58]  
  6. 0012ffc0 7c817077 00300031 0032002d 7ffdc000 test1!__tmainCRTStartup+0x10f [f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c @ 583]  
  7. 0012fff0 00000000 0040139a 00000000 78746341 kernel32!BaseProcessStart+0x23  

看下58行代码,使用了   g_AppInfo->PrintAppInfo();

我们猜测,g_AppInfo的两个成员无效,因为wprintf调用的就是它们

找到g_AppInfo,列出它的成员:

[cpp]  view plain  copy
  1. 0:000> x test1!*g_*  
  2. 00403374 test1!g_AppInfo = 0x00395b10  
  3. 004022f0 test1!_load_config_used = struct IMAGE_LOAD_CONFIG_DIRECTORY32_2  
  4. 00402098 test1!_imp___amsg_exit = <no type information>  
  5. 004014fa test1!_amsg_exit = <no type information>  
  6. 0:000> dt CAppInfo 0x00395b10  
  7. test1!CAppInfo  
  8.    +0x000 m_wszAppName     : 0x72726f43  "--- memory read error at address 0x72726f43 ---"  
  9.    +0x004 m_wszVersion     : 0x00747075  "???"  

注意,这里dt要用CAppInfo告诉它解析的地址类型

那我们再来看看这两个局变量的内容:

[cpp]  view plain  copy
  1. 0:000> dt CAppInfo 0x00395b10  
  2. test1!CAppInfo  
  3.    +0x000 m_wszAppName     : 0x72726f43  "--- memory read error at address 0x72726f43 ---"  
  4.    +0x004 m_wszVersion     : 0x00747075  "???"  
  5. 0:000> !address 0x72726f43    
  6.     62c29000 : 62c29000 - 11377000  
  7.                     Type     00000000   
  8.                     Protect  00000001 PAGE_NOACCESS  
  9.                     State    00010000 MEM_FREE  
  10.                     Usage    RegionUsageFree  
  11. 0:000> !address 0x00747075    
  12.     005f0000 : 005f0000 - 001be000  
  13.                     Type     00020000 MEM_PRIVATE  
  14.                     Protect  00000004 PAGE_READWRITE  
  15.                     State    00001000 MEM_COMMIT  
  16.                     Usage    RegionUsageIsVAD  

我们发现第一个变量竟然是不可访问的,找到问题了,

[cpp]  view plain  copy
  1. 0:000> dc 0x00395b10  
  2. 00395b10  72726f43 00747075 00020201 000801c2  Corrupt.........  
  3. 00395b20  6c75460a 7061206c 63696c70 6f697461  .Full applicatio  
  4. 00395b30  614e206e 203a656d 64657465 4320790a  n Name: eted.y C  
  5. 00395b40  7572726f 6f697470 6153206e 656c706d  orruption Sample  
  6. 00395b50  0000000a 00000000 00000000 00000000  ................  
  7. 00395b60  00000000 00000000 00000000 00000000  ................  
  8. 00395b70  00000000 00000000 00000000 00000000  ................  
  9. 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来转储这个句柄的信息.


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值