必须采用 SPY_CALL 数组是因为 Windows 2000 的多线程本性 。当 Native API 函数被暂停( suspended )时,这种情况就会经常出现 ---- 此时,另一个线程将获得控制权,然后在它自己的时间片( time slice )内调用另一个 Native API 函数 。这意味着 Spy 设备的 Hook Dispatcher 必须允许在任何时间和任何执行点上的重进入( reenter ) 。如果 Hook Dispatcher 有单一的全局 SPY_CALL 存储区域,它就可能在处于等待状态的线程使用完之前被当前运行的线程覆写( overwritten ) 。而这种情况正是蓝屏的最佳候选人 。为了进一步了解 Native API 的嵌套,我在 Spy 的 DEVICE_CONTEXT 结构中增加了 dLevel 和 dMisses 成员 。无论何时只要重进入 hook dispatcher (如,向 SPY_CALL 数组中增加一个新的 SPY_CALL ) dLevel 都不会累加一个 1。如果超过了最大嵌套层数(如,SPY_CALL 数组已满),dMisses 就会累加一个 1 ,来标识丢失了一个日志记录 。根据我的观察,在实际环境下,可以很容易的发现嵌套层达到 4。这表示即时在高负载( heavy-load )的情况下,Native API 也会被重进入,因此,我将嵌套层数的上限设为 256。
在调用原始的 API 处理例程之前,Hook Dispatcher 会保存所有的 CPU 寄存器(包括 EFLAGS ),随后执行路径将导向函数的进入点 。这会在 列表 5-3 中的 SpyHook5 标签之前立即完成 。此时,SpyHook6 将位于栈顶,仅随其后的是调用者的参数 。一旦 API 处理例程推出了,控制将被传回到 hook dispatcher 的 SpyHook6 标签 。从此处开始执行的代码也被设计为非入侵的 。此时,主要目标是允许调用者可以看到调用上下文,这和原始 API 函数建立的上下文几乎完全一致 。Dispatcher 的主要问题是要能立即找到保存有当前 API 调用信息的 SPY_CALL 结构 。唯一可以依赖的就是调用者的线程 ID ,该 ID 保存在 SPY_CALL 结构的 hThread 成员中 。因此,Dispatcher 循环遍历整个 SPY_CALL 数组以寻找匹配的线程 ID。注意,代码不会关心 fmuse 标志的值;这并不是必须的,因为数组中所有未使用的 SPY_CALL 结构的 hThread 都被设为了 0 ,这是系统空闲线程的 ID。循环会在到达数组结尾时终止 。否则的话(译注:即没有找到匹配的线程 ID ),Dispatcher 不会将控制返回给调用者,因为这样做将是致命的 。在这种情况下,代码的选择余地很小,因此,它会进入 KeBugCheck() ,这样做的结果当然是使系统以受控的方式终止 。不过这种情况应该从来不会发生,但如果它发生了,那表示系统必然出现了很严重的错误,因此,使系统终止是最佳解决方案 。
如果发现了匹配的 SPY_CALL ,Hook Dispatcher 将结束它的工作 。最后的动作是调用日志记录函数 SpyHookProtocol() ,需要给该函数传入一个指向 SPY_CALL 结构的指针 。日志记录所需的信息都保存在该结构中 。当 SpyHookProtocol() 返回后,Dispatcher 就释放它刚才使用的 SPY_CALL ,恢复所有的 CPU 寄存器,然后返回到调用者 。
API HOOK 协议
一个好的 API Spy 应该可以在原始函数被调用后还能察看它使用的参数,因为函数可能会通过传入的缓冲区返回附加的数据 。因此,日志函数 SpyHookProtocol() 在 hook 例程结束时将被调用,而此时 API 函数还未返回到调用者 。在讨论它的实现秘诀之前,请先看看下面给出的两个示例性的协议( Protocol ),它们会为你提供一个大概的方向 。图 5-6 是在命令行下执行 dir c: 时产生的日志文件的快照 。
请对比 图 5-6 中列出的日志项和 列表 5-6 给出的协议格式化字符串 。在 示列 5-1 中,NtOpenFile() 和 NtClose() 的格式化字符串分别对应 图 5-6 中的第一行和第四行 。它们有着惊人的相似处;每一个格式化控制 ID 都紧随在一个 % 号后(参考 表 5-2 ),与其相关的参数项将包含在协议中 。不过,协议还包含一些附加的信息,这些信息明显不属于格式字符串 。稍后我将解释这种差异的原因 。
推荐阅读
- 为Windows请个“系统医生”
- Windows 2000桌面也美丽
- 荒野行动送快递是什么梗
- windows 2000是怎样引导的
- 三倍工资的节日有哪些
- Windows2000下用户模式的内存扫描
- 3 《Undocumented Windows 2000 Secrets》翻译 --- 第三章
- 暗恋橘生淮南是在哪拍的
- 9 《Undocumented Windows 2000 Secrets》翻译 --- 第四章
- 奶酪陷阱大结局是什么
