4 《Undocumented Windows 2000 Secrets》翻译 --- 第四章( 五 )


{
X86_SELECTOR Selector = {0, 0};
BOOL fOk = FALSE;
if (pSelector != NULL)
{
fOk = TRUE;
switch (dSegment)
{
case X86_SEGMENT_OTHER:
{
if (fOk = ((dSelector >> X86_SELECTOR_SHIFT)
<= X86_SELECTOR_LIMIT))
{
Selector.wValue = https://www.rkxy.com.cn/dnjc/(WORD) dSelector;
}
break;
}
case X86_SEGMENT_CS:
{
__asm mov Selector.wValue, cs
break;
}
case X86_SEGMENT_DS:
{
__asm mov Selector.wValue, ds
break;
}
case X86_SEGMENT_ES:
{
__asm mov Selector.wValue, es
break;
}
case X86_SEGMENT_FS:
{
__asm mov Selector.wValue, fs
break;
}
case X86_SEGMENT_GS:
{
__asm mov Selector.wValue, gs
break;
}
case X86_SEGMENT_SS:
{
__asm mov Selector.wValue, ss
break;
}
case X86_SEGMENT_TSS:
{
__asm str Selector.wValue
break;
}
default:
{
fOk = FALSE;
break;
}
}
RtlCopyMemory (pSelector, &Selector, X86_SELECTOR_);
}
return fOk;
}
列表 4-16. 获取选择器( selector )的值
SpyDispatcher() 将从一个 64 位的描述符中读取数据,段选择器指向该描述符(见 列表 4-17 ) 。像你记得的那样,所有的选择器都包含一个表指示符( Table Indicator, TI )位,以确定选择器引用的描述符是位于 GDT ( TI=0 )中还是 LDT ( TI=1 )中 。列表 4-17 的上半部分处理了是 LDT 的情况 。首先,使用汇编指令 SLDT 和 SGDT 分别读取 LDT 选择器的值以及段的大小限制和 GDT 的基地址 。还记得 GDT 的线性基地址是显示指定的,而 LDT 是由 GDT 中的选择器间接引用的吗?所以,SpyDispatcher() 会首先验证 LDT 选择器的值 。如果段选择器不为空并且没有超过 GDT 的限制,就会调用 SpyDescriptorType() 、 SpyDescriptorLimit() 和 SpyDescriptorBase()( 列表 4-17 给出了这些函数 ) 来获取 LDT 的基本属性:
l SpyDescriptorType() 返回描述符的类型数据及其 S 位域(参见 列表 4-2 ) 。LDT 选择器必须指向一个类型为 X86_DESCRIPTOR_SYS_LDT 的系统描述符 。
l SpyDescriptorLimit() 从描述符的 Limit1 、 Limit2 这两个位域中汇总段的大小限制 。根据描述符的 G 标志指定的内存分配粒度的不同,其处理方式也会不同 。
l SpyDescriptorBase() 只是简单的通过适当的组织描述符的 Base1 、 Base2 和 Base3 位域以获取一个 32 位的线性地址 。
BOOL SpyDescriptor (PX86_SELECTOR pSelector,
PX86_DESCRIPTOR pDescriptor)
{
X86_SELECTOR ldt;
X86_TABLE gdt;
DWORD dType, dLimit;
BOOL fSystem;
PX86_DESCRIPTOR pDescriptors = NULL;
BOOL fOk = FALSE;
if (pDescriptor != NULL)
{
if (pSelector != NULL)
{
if (pSelector->TI) // ldt descriptor
{
__asm
{
sldt ldt.wValue
sgdt gdt.wLimit
}
if ((!ldt.TI) && ldt.Index &&
((ldt.wValue & X86_SELECTOR_INDEX)
<= gdt.wLimit))
{
dType = SpyDescriptorType (gdt.pDescriptors
ldt.Index,
&fSystem);
dLimit = SpyDescriptorLimit (gdt.pDescriptors
ldt.Index);
if (fSystem && (dType == X86_DESCRIPTOR_SYS_LDT)
&&
((DWORD) (pSelector->wValue
& X86_SELECTOR_INDEX)
<= dLimit))
{
pDescriptors =
SpyDescriptorBase (gdt.pDescriptors
ldt.Index);
}
}
}
else // gdt descriptor
{
if (pSelector->Index)
{
__asm
{
sgdt gdt.wLimit
}
if ((pSelector->wValue & X86_SELECTOR_INDEX)
<= gdt.wLimit)
{
pDescriptors = gdt.pDescriptors;
}
}
}
}
if (pDescriptors != NULL)
{
RtlCopyMemory (pDescriptor,

推荐阅读