在对 Spy 设备的 IOCTL 函数的讲解之后还将提供了一个示例程序,该示例程序会把返回的数据显示在屏幕上 。
#define KI_USER_SHARED_DATA 0xFFDF0000
#define SharedUserData ((KUSER_SHARED_DATA *const)KI_USER_SHARED_DATA)
列表 4-14. SharedUserData 结构定义
IOCTL 函数 SPY_IO_SEGMENT
到现在讨论以变得更加有趣了 。SPY_IO_SEGMENT 函数通过一些更底层的操作来查询指定段的属性,调用者需要首先给出一个选择器( selector ) 。SpyDispatcher() 首先调用 SpyInputDword() 来获取由调用程序传入的选择器的值 。你可能还记得选择器( selector )是一个 16 位的数 。不过,只要可能,我就会尝试避免使用 16 位的数据类型,这是因为原生的 WORD 在 i386 CPU 的 32 位模式下是 32 位的 DWORD 类型 。因此,我将选择器参数扩展为 DWORD,不过其高 16 位总是 0。如果 SpyInputDword() 报告操作成功,接下来就会调用 SpyOutputSegemnt() 函数( 列表 4-15 给出了此函数) 。不管 SpySegment() 帮助函数如何,SpyOutputSegemnt() 总是返回到调用者 。基本上来说,SpySegment() 将填充 SPY_SEGMENT 结构,该结构定义于 列表 4-15 的顶部 。它以 X86_SELECTOR 结构(参见 列表 4-2 )的形式给出选择器的值,紧随其后的是 64 位的 X86_DESCRIPTOR,以及相应的段基址,段的大小限制以及一个名为 fOk 的标志,该标志用来指出 SPY_SEGMENT 结构是否有效 。在稍后的一些函数中需要一次返回多个段的属性,利用 fOk 成员,调用者就可以将无效的段信息从输出数据中筛选出来 。
typedef struct _SPY_SEGMENT
{
X86_SELECTOR Selector;
X86_DESCRIPTOR Descriptor;
PVOID pBase;
DWORD dLimit;
BOOL fOk;
}
SPY_SEGMENT, *PSPY_SEGMENT, **PPSPY_SEGMENT;
#define SPY_SEGMENT_ sizeof (SPY_SEGMENT)
NTSTATUS SpyOutputSegment (DWORD dSelector,
PVOID pOutput,
DWORD dOutput,
PDWORD pdInfo)
{
SPY_SEGMENT ss;
SpySegment (X86_SEGMENT_OTHER, dSelector, &ss);
return SpyOutputBinary (&ss, SPY_SEGMENT_,
pOutput, dOutput, pdInfo);
}
BOOL SpySegment (DWORD dSegment,
DWORD dSelector,
PSPY_SEGMENT pSegment)
{
BOOL fOk = FALSE;
if (pSegment != NULL)
{
fOk = TRUE;
if (!SpySelector (dSegment, dSelector,
&pSegment->Selector))
{
fOk = FALSE;
}
if (!SpyDescriptor (&pSegment->Selector,
&pSegment->Descriptor))
{
fOk = FALSE;
}
pSegment->pBase =
SpyDescriptorBase (&pSegment->Descriptor);
pSegment->dLimit =
SpyDescriptorLimit (&pSegment->Descriptor);
pSegment->fOk = fOk;
}
return fOk;
}
列表 4-15. 查询段的属性
SpySegment() 函数依赖其他几个帮助函数,以构建 SPY_SEGMENT 结构的某些部分 。首先,SpySelector() 复制一个选择器的值到传入的 X86_SELECTOR 结构中 。如果 SpySelector() 函数的第一个参数 dSegment 被设置为 X86_SEGMENT_OTHER (即 0 ),dSelector 参数将假定已经指定了一个有效的选择器值,因此该值将被简单的附给输出结构 X86_SELECTOR 的 wValue 成员 。否则,dSelector 将被忽略,dSegment 会被用于一个 switch/case 结构中以便选择一个段寄存器或任务寄存器 TR。注意,这种请求需要少量的嵌入式汇编,C 语言没有提供标准的方法访问处理器相关的特性,如段寄存器 。
#define X86_SEGMENT_OTHER 0
#define X86_SEGMENT_CS 1
#define X86_SEGMENT_DS 2
#define X86_SEGMENT_ES 3
#define X86_SEGMENT_FS 4
#define X86_SEGMENT_GS 5
#define X86_SEGMENT_SS 6
#define X86_SEGMENT_TSS 7
//---------------------------------------------------------------
BOOL SpySelector (DWORD dSegment,
DWORD dSelector,
PX86_SELECTOR pSelector)
推荐阅读
- 3 《Undocumented Windows 2000 Secrets》翻译 --- 第四章
- Windows 2000/2003下如何使用组策略禁止用户修改密码
- windows 2000密码破解
- Windows 2000对调试技术的支持
- 永久删除 Windows 2000 默认本地 C, D 盘共享的两个批处理文件
- Windows 2000 无法直接关机解决方案
- 2 《Undocumented Windows 2000 Secrets》翻译 --- 第二章
- 2 《Undocumented Windows 2000 Secrets》翻译 --- 2
- 使用 Windows 2000 中的 IPSec IP 筛选器列表
- 火影忍者是哪一年出的