DWORD dPageShift;
DWORD dPtiShift;
DWORD dPdiShift;
DWORD dPageMask;
DWORD dPtiMask;
DWORD dPdiMask;
PX86_PE PteArray;
PX86_PE PdeArray;
PVOID pLowestUserAddress;
PVOID pThreadEnvironmentBlock;
PVOID pHighestUserAddress;
PVOID pUserProbeAddress;
PVOID pSystemRangeStart;
PVOID pLowestSystemAddress;
PVOID pSharedUserData;
PVOID pProcessorControlRegion;
PVOID pProcessorControlBlock;
DWORD dGlobalFlag;
DWORD dI386MachineType;
DWORD dNumberProcessors;
DWORD dProductType;
DWORD dBuildNumber;
DWORD dNtMajorVersion;
DWORD dNtMinorVersion;
WORD awNtSystemRoot [MAX_PATH];
}
SPY_OS_INFO, *PSPY_OS_INFO, **PPSPY_OS_INFO;
#define SPY_OS_INFO_ sizeof (SPY_OS_INFO)
NTSTATUS SpyOutputOsInfo (PVOID pOutput,
DWORD dOutput,
PDWORD pdInfo)
{
SPY_SEGMENT ss;
SPY_OS_INFO soi;
NT_PRODUCT_TYPE NtProductType;
PKPCR pkpcr;
NtProductType = (SharedUserData->ProductTypeIsValid
? SharedUserData->NtProductType
: 0);
SpySegment (X86_SEGMENT_FS, 0, &ss);
pkpcr = ss.pBase;
soi.dPageSize = PAGE_SIZE;
soi.dPageShift = PAGE_SHIFT;
soi.dPtiShift = PTI_SHIFT;
soi.dPdiShift = PDI_SHIFT;
soi.dPageMask = X86_PAGE_MASK;
soi.dPtiMask = X86_PTI_MASK;
soi.dPdiMask = X86_PDI_MASK;
soi.PteArray = X86_PTE_ARRAY;
soi.PdeArray = X86_PDE_ARRAY;
soi.pLowestUserAddress = MM_LOWEST_USER_ADDRESS;
soi.pThreadEnvironmentBlock = pkpcr->NtTib.Self;
soi.pHighestUserAddress = *MmHighestUserAddress;
soi.pUserProbeAddress = (PVOID) *MmUserProbeAddress;
soi.pSystemRangeStart = *MmSystemRangeStart;
soi.pLowestSystemAddress = MM_LOWEST_SYSTEM_ADDRESS;
soi.pSharedUserData = https://www.rkxy.com.cn/dnjc/SharedUserData;
soi.pProcessorControlRegion = pkpcr;
soi.pProcessorControlBlock = pkpcr->Prcb;
soi.dGlobalFlag = *NtGlobalFlag;
soi.dI386MachineType = *KeI386MachineType;
soi.dNumberProcessors = *KeNumberProcessors;
soi.dProductType = NtProductType;
soi.dBuildNumber = *NtBuildNumber;
soi.dNtMajorVersion = SharedUserData->NtMajorVersion;
soi.dNtMinorVersion = SharedUserData->NtMinorVersion;
wcscpyn (soi.awNtSystemRoot, SharedUserData->NtSystemRoot,
MAX_PATH);
return SpyOutputBinary (&soi, SPY_OS_INFO_,
pOutput, dOutput, pdInfo);
}
列表 4-13. 获取有关操作系统的信息
SPY_OS_INFO 结构的剩余成员会由位于内存中的系统数据结构填充 。例如,SpyOutputOsInfo() 将内核的进程控制区域( Kernel"s Processor Control Region, KPCR )的基地址赋值给 pProcessorControlRegion 成员 。KPCR 是一个非常重要的数据结构,该结构包含很多线程相关的数据项,因此,它位于自己的内存段中,该内存段的地址由 CPU 的 FS 寄存器给出 。Windows NT 4.0 和 Windows 2000 都将 FS 指向处于内核模式的线性地址 0xFFDFF000。SpyOutputOsInfo() 调用 SpySegment() 函数(稍后讨论它)来查询 FS 段在线性地址空间中的基地址 。这个段中还包含内核的进程控制块( Kernel"s Processor Control Block, KPRCB ),KPCR 结构的 Prcb 成员指向 KPRCB 结构的首地址,紧随其后的是一个 CONTEXT 结构,该结构包含当前线程的底层 CPU 信息 。KPCR 、 KPRCB 和 CONTEXT 结构定义在 ntddk.h 头文件中 。
列表 4-13 中引用的另一个内部数据结构是 SharedUserData。该结构实际上是一个由一个“众所周知的地址”通过类型转化( TypeCast )得来的结构体指针 。列表 4-14 给出了它在 ntddk.h 中的定义 。那个“众所周知的地址”位于线性地址空间中,它会在编译时被设置,因此不需要花费额外的时间或进行配置 。显然,SharedUserData 是一个指向 KUSER_SHARED_DATA 结构的指针,该结构的基地址在 0xFFDF0000 (这是一个线性地址) 。这个内存区域由系统和用户模式的应用程序共享,它包含像操作系统版本号这样的数据,SpyOutputOsInfo() 将该版本数据复制到 SPY_OS_INFO 结构(由调用者提供)的 dNtMajorVersion 和 dNtMinorVersion 成员 。就像我稍后要展示的那样,KUSER_SHARED_DATA 结构将被映射到 0x7FFE0000,这样用户模式的代码就可以访问它了 。
推荐阅读
- 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 筛选器列表
- 火影忍者是哪一年出的