天天看点

Application Verifier使用起步

    网上Application Verifier(以下称AppVerf)关于的功能介绍已经很多,却鲜有介绍实际使用的文章(说真的,我很怀疑这些作者有没有用AppVeri测过程序),谨以此文总结我在使用过程中遇到的问题和解决方法。

    依次点击"Application Verifier"-File-"Add Application"选择并保存将要验证可执行程序后,AppVerf会往注册表HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options下创建一个键,里面包含用户在AppVerf中设置的测试项,同时设置GlobalFlag/PageHeapFlags等键值对。从这个角度看,AppVerf和windbg中gflags.exe的功能有点像,都是用来设置App运行属性的。下图是为verifiee.exe(这个可执行程序来自<软件调试>第19章)设置基本测试后的注册表值。

Application Verifier使用起步
Application Verifier使用起步

    设置完成后,exe并没有运行,需要用户手动启动。之后exe的一举一动都在后台程序AppVerf的监控中(其实AppVerf以修改exe的IAT表的形式,对exe进行API HOOK,实现行为审计)。MSDN建议用户用windbg启动exe(或者exe启动后windbg附件到exe),这是因为在执行过程中,一旦程序触碰到了AppVerf划的警戒线(如堆溢出/资源泄露等),就会触发断点异常,导致程序崩溃。如果程序处于调试状态,断点异常会被调试器捕获,并交由用户排错。

    上面说到程序越过雷池后会触发断点异常,这些断点异常源自AppVerf检测项中的"Verifier Stop"。以Basics-Handler检测项为例:右键该检测项,进入"Verifier Stop Options"后可以看到每个子检测项的错误报告机制"Error Reporting"默认就是"Breakpoint"。

Application Verifier使用起步
Application Verifier使用起步

现在,我们知道了断点异常的来源,再来看看如何调试,不得不说MS在这方面做得有点坑。按照AppVerf的文档所说,windbg可以输入!avrf扩展命令来分析错误原因(看着和!analyziz -v的功能有点接近)。一般情况下,在调试前,我们都会这样设置调试符号的路径:

0:000> .symfix C:\sym #设置c:\sym存放从MS符号服务器下载的调试符号
0:000> .sympath+ C:\docs\bin\Debug #指向verifiee.pdb所在路径      

如果这样设置没错,但是对于AppVerf会掉进坑里,Why?先来看下现象:运行程序并选择"Trying to free freed memory"触发双释放内存错误。

Application Verifier使用起步

从图中可以看到,AppVerf检测到这个错误并触发了断点异常。如果此时按AppVerf文档所说,输入扩展命令!avrf分析错误原因,会意外的得到如下输出:

0:001> !avrf
Verifier package version >= 3.00 
*************************************************************************
***                                                                   ***
***                                                                   ***
***    Either you specified an unqualified symbol, or your debugger   ***
***    doesn't have full symbol information.  Unqualified symbol      ***
***    resolution is turned off by default. Please either specify a   ***
***    fully qualified symbol module!symbolname, or enable resolution ***
***    of unqualified symbols by typing ".symopt- 100". Note that   ***
***    enabling unqualified symbol resolution with network symbol     ***
***    server shares in the symbol path may cause the debugger to     ***
***    appear to hang for long periods of time when an incorrect      ***
***    symbol name is typed or the network symbol server is down.     ***
***                                                                   ***
***    For some commands to work properly, your symbol path           ***
***    must point to .pdb files that have full type information.      ***
***                                                                   ***
***    Certain .pdb files (such as the public OS symbols) do not      ***
***    contain the required information.  Contact the group that      ***
***    provided you with these symbols if you need this command to    ***
***    work.                                                          ***
***                                                                   ***
***    Type referenced: vfbasics!_AVRF_EXCEPTION_LOG_ENTRY                ***
***                                                                   ***
*************************************************************************
No type information found for `_AVRF_EXCEPTION_LOG_ENTRY'.
Please fix the symbols for `vfbasics.dll'. ;windbg提示需要修正vfbasics.dll的符号      

对于这样的输出,第一反应是vfbasics.dll的符号不对,有2种可能1).没有下到符号;2)符号不匹配。但是根据windbg对符号的检验结果来看这两种情况都没有发生:

0:001> lml
start    end        module name
59020000 5905c000   vfbasics   (pdb symbols)          C:\sym\vfbasics.pdb\C5E20AA982AA49F69C1F6F001CF43D901\vfbasics.pdb #符号已加载

0:001> !itoldyouso vfbasics

C:\Windows\SYSTEM32\vfbasics.dll
    Timestamp: 48C7C636
  SizeOfImage: 3C000
          pdb: d:\avrf\source.obj.x86fre\base\avrf\avrf30\providers\basics\objfre\i386\vfbasics.pdb
      pdb sig: C5E20AA9-82AA-49F6-9C1F-6F001CF43D90
          age: 1

Loaded pdb is C:\sym\vfbasics.pdb\C5E20AA982AA49F69C1F6F001CF43D901\vfbasics.pdb

vfbasics.pdb
      pdb sig: C5E20AA9-82AA-49F6-9C1F-6F001CF43D90
          age: 1

MATCH: vfbasics.pdb and C:\Windows\SYSTEM32\vfbasics.dll #符号与image相匹配      

面对这样的结果我简直无所适从,没法分析结果,顿时觉得AppVerf就是个废物。bing搜索后才知道,原来AppVerf安装包中已经包含了各个模块的pdb文件并在安装时一并安装到%windir%\system32下(x86环境下)。

Application Verifier使用起步

像前面那样设置符号路径,从MS调试服务器下载的pdb是阉割过(striped)的调试符号,导致!avrf扩展命令失效。正确的做法是将%windir%\system32设置在所有调试符号的最前面,后面再跟着其他符号的路径:

0:000> .sympath c:\windows\system32
0:000> .sympath+ C:\symbols\dll      

再次出发异常并输入!avrf命令就能看到windbg分析错误原因了:

=======================================
VERIFIER STOP 0000060B: pid 0x264: Trying to free virtual memory block that is already free. 

  02F50000 : Memory block address.
  00000000 : Not used.
  00000000 : Not used.
  00000000 : Not used.


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

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

(264.a60): Break instruction exception - code 80000003 (first chance)
eax=1000e848 ebx=003788a4 ecx=00000001 edx=0012f158 esi=00000000 edi=1000e848
eip=7c92120e esp=0012f218 ebp=0012f41c 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> !avrf
...
Arguments:
Arg1: 02f50000, Memory block address. 
Arg2: 00000000, Not used. 
Arg3: 00000000, Not used. 
Arg4: 00000000, Not used. 
GetPageUrlData failed, server returned HTTP status 404
URL requested: http://watson.microsoft.com/StageOne/verifiee_exe/1_0_0_1/ntdll_dll/5_1_2600_5512/0000120e.htm?Retriage=1

FAULTING_IP: 
ntdll!DbgBreakPoint+0
7c92120e cc              int     3

EXCEPTION_RECORD:  ffffffff -- (.exr 0xffffffffffffffff)
ExceptionAddress: 7c92120e (ntdll!DbgBreakPoint)
   ExceptionCode: 80000003 (Break instruction exception)
  ExceptionFlags: 00000000
NumberParameters: 3
   Parameter[0]: 00000000
   Parameter[1]: 00000001
   Parameter[2]: 0012f158

FAULTING_THREAD:  00000a60

DEFAULT_BUCKET_ID:  STATUS_BREAKPOINT

PROCESS_NAME:  verifiee.exe

ERROR_CODE: (NTSTATUS) 0x80000003 - {

EXCEPTION_CODE: (NTSTATUS) 0x80000003 (2147483651) - {

EXCEPTION_PARAMETER1:  00000000

EXCEPTION_PARAMETER2:  00000001

EXCEPTION_PARAMETER3:  0012f158

MOD_LIST: <ANALYSIS/>

NTGLOBALFLAG:  2000100

APPLICATION_VERIFIER_FLAGS:  80443027

PRIMARY_PROBLEM_CLASS:  STATUS_BREAKPOINT

BUGCHECK_STR:  APPLICATION_FAULT_STATUS_BREAKPOINT

LAST_CONTROL_TRANSFER:  from 10003b68 to 7c92120e

STACK_TEXT:  
0012f214 10003b68 1012237c 00000000 02f50000 ntdll!DbgBreakPoint
0012f41c 00372aa1 003761c8 0000060b 02f50000 vrfcore!VerifierStopMessageEx+0x4d1 [d:\avrf\source\base\avrf\avrf30\vrfcore\sdk.cpp @ 551]
0012f46c 00372b46 ffffffff 00000001 02f50000 vfbasics!AVrfpFreeVirtualMemNotify+0x193 [d:\avrf\source\base\avrf\vrfcommon\vspace.c @ 703]
0012f498 7c809bbf ffffffff 0012f4c4 00000000 vfbasics!AVrfpNtFreeVirtualMemory+0x96 [d:\avrf\source\base\avrf\vrfcommon\vspace.c @ 243]
0012f4b8 7c809b89 ffffffff 02f50000 00000000 kernel32!VirtualFreeEx+0x37
0012f4d0 003727ff 02f50000 00000000 00008000 kernel32!VirtualFree+0x15
0012f518 004012b4 02f50000 00000000 00008000 vfbasics!AVrfpVirtualFree+0x82 [d:\avrf\source\base\avrf\vrfcommon\vspace.c @ 1499]
0012f5a4 0040149f 0012fed4 0012f65c 0205cf38 verifiee!BugDoubleFree+0xa4 [C:\dig\dbg\author\code\chap19\verifiee\Bugs.cpp @ 48]
0012f600 00402169 00000002 0012f8fc 0205cf38 verifiee!CBugs::FireBug+0x2f [C:\dig\dbg\author\code\chap19\verifiee\Bugs.cpp @ 83]
0012f65c 5f4373fc 0012f8fc 0205cf38 00000000 verifiee!CVerifieeDlg::OnBang+0x59 [C:\dig\dbg\author\code\chap19\verifiee\verifieeDlg.cpp @ 184]
WARNING: Stack unwind information not available. Following frames may be wrong.
0012f694 5f437b2b 0012fe30 000003e8 00000000 MFC42D!Ordinal563+0x133
0012f6ec 5f43374b 000003e8 00000000 00000000 MFC42D!Ordinal3657+0x274
0012f71c 5f42fa63 000003e8 00000000 00000000 MFC42D!Ordinal3658+0x24
0012f77c 5f42ec65 000003e8 00090246 0012f8fc MFC42D!Ordinal3670+0x138
0012f87c 5f42ebe8 00000111 000003e8 00090246 MFC42D!Ordinal4118+0x53
0012f89c 5f42c789 00000111 000003e8 00090246 MFC42D!Ordinal5076+0x2e
0012f910 5f42cc25 0012fe30 001b027a 00000111 MFC42D!Ordinal1045+0xed
0012f93c 5f49049d 001b027a 00000111 000003e8 MFC42D!Ordinal1192+0x81
0012f96c 77d18734 001b027a 00000111 000003e8 MFC42D!Ordinal1193+0x4a
0012f998 77d18816 5f490453 001b027a 00000111 USER32!InternalCallWinProc+0x28
0012fa00 77d2927b 00000000 5f490453 001b027a USER32!UserCallWinProcCheckWow+0x150
0012fa3c 77d292e3 005de008 025df140 000003e8 USER32!SendMessageWorker+0x4a5
0012fa5c 77d4ff7d 001b027a 00000111 000003e8 USER32!SendMessageW+0x7f
0012fa74 77d465d2 025de4c0 00000000 025de4c0 USER32!xxxButtonNotifyParent+0x41
0012fa90 77d25e94 02bc8fd8 00000001 00000000 USER32!xxxBNReleaseCapture+0xf8
0012fb14 77d3b082 025de4c0 00000202 00000000 USER32!ButtonWndProcWorker+0x6df
0012fb34 77d18734 00090246 00000202 00000000 USER32!ButtonWndProcA+0x5d
0012fb60 77d18816 77d3b036 00090246 00000202 USER32!InternalCallWinProc+0x28
0012fbc8 77d189cd 00000000 77d3b036 00090246 USER32!UserCallWinProcCheckWow+0x150
0012fc28 77d18a10 00416878 00000000 0012fc5c USER32!DispatchMessageWorker+0x306
0012fc38 77d274ff 00416878 00416878 00416880 USER32!DispatchMessageW+0xf
0012fc5c 77d3c6d3 001b027a 025de4c0 0012fedc USER32!IsDialogMessageW+0x572
0012fc7c 5f436725 001b027a 00416878 0012fedc USER32!IsDialogMessageA+0xfd
0012fca0 5f431f94 00416878 0012fedc 00fff790 MFC42D!Ordinal3337+0x7b
0012fcbc 5f43371e 00416878 0012fedc 00fff790 MFC42D!Ordinal4206+0x75
0012fce0 5f430b48 00416878 0012fedc 00fff790 MFC42D!Ordinal4208+0xf8
0012fd00 5f439243 001b027a 00416878 00416840 MFC42D!Ordinal5070+0x98
0012fd1c 5f4396aa 00416878 0012fedc 00fff790 MFC42D!Ordinal4215+0x55
0012fd38 5f43219f 0012fedc 00fff790 7ffdc000 MFC42D!Ordinal4239+0xe2
0012fd74 5f43459f 00000004 0012fedc 00fff790 MFC42D!Ordinal4410+0x202
0012fdd4 004017e5 00fff6ee 00fff790 7ffdc000 MFC42D!Ordinal1862+0x191
0012fee8 5f433523 00fff6ee 00fff790 7ffdc000 verifiee!CVerifieeApp::InitInstance+0x75 [C:\dig\dbg\author\code\chap19\verifiee\verifiee.cpp @ 59]
0012ff08 00402768 00400000 00000000 01fd4ffb MFC42D!Ordinal1190+0x83
0012ff20 00402653 00400000 00000000 01fd4ffb verifiee!WinMain+0x18 [appmodul.cpp @ 30]
0012ffc0 7c817067 00fff6ee 00fff790 7ffdc000 verifiee!WinMainCRTStartup+0x1b3 [crtexe.c @ 330]
0012fff0 00000000 004024a0 00000000 78746341 kernel32!BaseProcessStart+0x23


FOLLOWUP_IP: 
verifiee!CBugs::FireBug+2f [C:\dig\dbg\author\code\chap19\verifiee\Bugs.cpp @ 83]
0040149f 83c404          add     esp,4

FAULTING_SOURCE_CODE:  
No source found for 'C:\dig\dbg\author\code\chap19\verifiee\Bugs.cpp'


SYMBOL_STACK_INDEX:  8

SYMBOL_NAME:  verifiee!CBugs::FireBug+2f

FOLLOWUP_NAME:  MachineOwner

MODULE_NAME: verifiee

IMAGE_NAME:  verifiee.exe

DEBUG_FLR_IMAGE_TIMESTAMP:  47fb7887

STACK_COMMAND:  dt ntdll!LdrpLastDllInitializer BaseDllName ; dt ntdll!LdrpFailureData ; ~0s ; kb

FAILURE_BUCKET_ID:  STATUS_BREAKPOINT_80000003_verifiee.exe!CBugs::FireBug

BUCKET_ID:  APPLICATION_FAULT_STATUS_BREAKPOINT_verifiee!CBugs::FireBug+2f

WATSON_STAGEONE_URL:  http://watson.microsoft.com/StageOne/verifiee_exe/1_0_0_1/47fb7887/ntdll_dll/5_1_2600_5512/4802bdc5/80000003/0000120e.htm?Retriage=1

Followup: MachineOwner
---------      

现在!avrf正常工作起来,剩下的事就可以参考它的文档了~

继续阅读