软件调试的主要任务是寻找软件下次的根源,其前提通常是已经知道了有瑕疵存在。
发现软件瑕疵
发现软件下次的最普遍方法是测试。常见的测试手段有:
- 黑盒测试
- 百合测试
- 内建自检,又称为BIST(Build-In Self-Test),是指在软件代码内部构建一些测试功能,这些功能(函数)可以在某些情况下执行,或者被自动测试工具所调用以发现问题。
- 压力测试
即使用了以上所有的测试手段,也不能保证会发现所有问题。原因之一是测试时的运行环境和条件不足以将错误触发并暴露出来。【比如轻微的内存泄漏,这个通常是比较难发现的】
验证机制
验证机制的主要目标是检查被测试软件,或者说是为被测试软件提供一个验证器(Verifier)。
- 驱动程序验证器
- 应用程序验证器
- WHQL测试。通过WHQL(Windows Hardware Quality Labs)测试是驱动程序取得Windows徽标和得到数字签名的必要条件。
驱动验证器的工作原理
设计原理:
- 在驱动程序调用设备驱动接口(DDI)函数时,对驱动程序执行各种检查,看其是否符合系统定义的设计要求,特别是DDK文档所定义的调用条件和规范。
- Windows采用通过修改被验证驱动程序的输入地址表(Import Address Table, IAT)来挂接驱动程序的DDI调用,即通常所说的IAT HOOK方法。
系统会将被验证驱动程序IAT表中的DDI函数地址替换为验证函数的地址。这样,当这个驱动程序调用DDI函数时,便会调用对应的验证函数。验证函数与原来的函数具有完全一致的函数原型,所以不会影响被验证程序的执行。
在验证函数被调用后,它执行的典型操作:
- 更新计数器,或者全局变量。
- 检查调用参数,或者做其他检查。如果检测到异常情况,即通过蓝屏机制来报告验证失败。
- 如果没有发现问题,那么验证函数会调用原来的函数,并返回原函数的返回值。
验证项目:
基本的:
- 自动检查
- 特殊内存池
- 强制的IRQL检查
- 低资源模拟
- I/O验证
Windows XP引入:
- 死锁验证
- 增强的I/O验证
- SCSI验证
Windows Server 2003引入:
- IRP记录
Windows Vista引入:
- 驱动滞留探测
- 安全检查
- 强制的I/O请求等待解决
- 零散检查
应用程序验证器的工作原理
原理与驱动程序验证器的工作原理类似。
应用验证器由以下三个部分组成:
- 位于NTDLL中的支持例程。这些函数大多以AVrf开头,位于系统的NTDLL.DLL模块中。
- 验证提供器模块,是安装应用程序验证工具时复制到系统system32目录下的多个DLL文件,每个文件为一个动态链接库,用于完成某一方面的验证任务。每个提供器都包含若干个验证函数和THUNK表,前者用来替代系统API,后者用来描述要挂接的函数信息。
- 应用验证管理器,用于管理(添加、删除)被验证的应用程序和选择验证项目的工具程序,也是应用程序验证工具包时需要安装的,位于system32目录下,文件名为appverif.exe。