windows的应用验证机制

windows的验证机制

发现软件瑕疵的最普遍方法就是测试,常用的测试手段有如下几种:

  1. 黑盒测试
  2. 白盒测试
  3. 内建自检
  4. 压力测试

虽然以上每种测试都有它的优势和侧重点,但即使用上了以上所有测试手段,也不能保证会发现所有问题。
比如某个程序有轻微的内存泄漏,就很难发现。
比如有些异常需要再比较苛刻的环境下才会出现,但测试时会很难满足。
……

windows操作系统的验证机制(Verifier)就是为了满足这个需求而设计的。

windows 验证机制分为驱动验证器和应用程序验证器,这里主要讲解应用程序验证器。

应用程序验证器工作原理

验证器的基本设计思想是在应用程序调用内核函数时,对应用程序执行各种检查,看其是否符合windows sdk的调用条件和规范。

windows 采用的是通过修改被验证程序的输入地址表(IAT)来挂载(hook)应用程序的api调用。 系统会将被验证驱动程序的IAT表中的api函数地址替换为验证函数的地址。这样,当这个应用程序调用api函数时,便会调用对应的验证函数。

应用检测器组成

位于NTDLL中的支持例程

位于ntdll.dll 中,大多已 AVrf 开头

验证提供器模块

安装验证工具时复制到system32目录下的多个dll文件

应用验证管理器

关于管理验证程序参数的图形界面工具。

执行过程

执行过程是详细讲解是比较复杂的,这里我已简单的doublefree来简单介绍下执行过程。
当函数中执行free时,最终会调用到virtualfree,这时应用验证器实际调用的是AVrfVirtualFree,改函数会调用AVrfVirtualFreeSanityChecks 执行健全性检查……
当第二次对同一个地址进行free时,健全性检查会验证不过,从而主动触发一个异常。

使用应用验证器

下载:链接:https://pan.baidu.com/s/1JKst9CbDKTFROKL0yWsmjg 提取码:7291 ,里面的ApplicationVerifier.x86.msi 和 ApplicationVerifier.amd64.msi

验证项目

目前的验证器设计了6个类别,19个验证项目。

basics

COM 正确使用组件对象模型(COM)
Exceptions 检查非法访问异常
handles 正确使用句柄
Heaps 正确使用堆
Locks 正确使用同步对象
Memory 合理使用虚拟内存
RPC 正确使用rpc
Threadpool 正确使用内存池
Tls 正确使用线程局部存储

Compatibility(兼容性)

FilesPaths 正确读取公共目录和使用有个api
HighVersionLie 读取版本信息的方式
Interactive-service 验证交互式系统服务
KernelMode-DriverInstall 正确安装内核态驱动程序

hangs

hangs 检测可能导致程序僵死的情况

lowRes(低资源模拟)

lowRes 模拟低资源情况,对分配资源请求返回失败

LuaPriv

LuaPriv 判断在管理员权限可以运行的程序是否也可以在受限账号下正常运行

杂项

DangerousAPIs 检查使用危险api的情况
DirtyStacks 检测使用未初始化局部变量的情况
TimeRoolOver 强制GetTickCount api快速重新计数,已考验是否处理该异常

打印

PrintAPI 正确使用打印API
PrintDriver 验证打印驱动程序

服务

Service 验证系统服务

doublefree操作举例

安装应用验证

安装后,找到appverif.exe

doublefree代码

1
2
3
int *p = new int[100];
delete []p;
delete []p;

不开启应用验证时,程序不会出现异常。

开启应用验证

“file” –>”add application” —>”xxx.exe” (不要在.exe 运行时操作),选择“heaps”

启动 .exe ,然后执行doublefree 程序崩溃。
使用windbg可以查看异常堆栈

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
0:000> kv
ChildEBP RetAddr Args to Child
WARNING: Stack unwind information not available. Following frames may be wrong.
004feafc 6ade80c8 6aded258 00000007 07041000 vrfcore!VerifierStopMessageEx+0x5b8
004feb20 0fdcdfbe 00000007 0fdc1cac 07041000 vrfcore!VerifierDisableVerifier+0x598
004feb78 0fdcbb9f 00000007 0fdc1cac 07041000 verifier!VerifierStopMessage+0x8e
004febe4 0fdc89bd 07041000 00000000 0a8607ec verifier!VerifierDisableFaultInjectionExclusionRange+0x44af
004fec48 0fdc8b15 07041000 0a6d6e70 00000000 verifier!VerifierDisableFaultInjectionExclusionRange+0x12cd
004fec6c 0fdc8d90 07041000 0a6d6e70 004fed04 verifier!VerifierDisableFaultInjectionExclusionRange+0x1425
004fec88 0fdcadd0 07041000 0a6d6e70 0a8607ec verifier!VerifierDisableFaultInjectionExclusionRange+0x16a0
004feca4 77b72fa1 07040000 01001002 0a6d6e70 verifier!VerifierDisableFaultInjectionExclusionRange+0x36e0
004fed14 77ad2735 0a6d6e70 08ba3c35 00000000 ntdll!RtlpNtSetValueKey+0x3cf1
004fee60 77ad2302 00000000 0a6d6e70 00000111 ntdll!RtlGetCurrentServiceSessionId+0xf5
004feeb4 6adead3b 07040000 00000000 0a6d6e70 ntdll!RtlFreeHeap+0x222
004feed4 71de3c1b 07040000 00000000 0a6d6e70 vrfcore!VerifierSetAPIClassName+0x16b
004fef20 00181660 0a6d6e70 004ff758 0a6d6e70 MSVCR90!free+0xcd
004fef40 78409479 004ff758 004fef68 7840965b TraceMe!CTraceMeDlg::OnBnClickedButton1+0x40 (CONV: thiscall) [c:\users\b41-cx\documents\visual studio 2008\projects\traceme\traceme\tracemedlg.cpp @ 195]
004fef4c 7840965b 000003e9 00000039 00000000 mfc90!_AfxDispatchCmdMsg+0x3b

个人常用方法

  1. 一般用这个工具来分析踩内存
  2. 可以在测试环境中验证服务

注意点

  1. 只能检查native代码
  2. 程序序正常退出才行,强行杀进程不能得到正确的报告
  3. 只能做Run-time检测。尽量使用程序的所有功能已保证检测到更多代码
  4. 开启检测时,性能会下降,内存会升高,不要在生产环境中使用。