分享
 
 
 

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

王朝system·作者佚名  2006-11-24
窄屏简体版  字體: |||超大  

第四章 探索 Windows 2000 的内存管理机制

翻译: Kendiv ( [url=http://www.pccode.net].net"fcczj@263.net )

更新: Sunday, February 17, 2005

声明:转载请注明出处,并保证文章的完整性,本人保留译文的所有权利。

尽管 Spy 设备使用可缓冲的 I/O ,但它还是会检查输入 / 输出缓冲区的有效性。因为客户端程序传入的数据可能比所需的少或者提供的缓冲区不够容纳输出数据。系统不能捕获这些语意错误,因为它不知道在一次 IOCTL 传输中所传输的数据的类型。因此, SpyDispatcher() 调用帮助函数 SpyInput*() 和 SpyOutput*() 来从 I/O 缓冲区中复制或写入数据。这些函数仅在缓冲区大小与操作的需求相匹配时才执行。 列表 4-10 给出了基本的输入函数, 列表 4-11 给出了基本的输出函数。 SpyInputBinary() 和 SpyOutputBinary() 被广泛的使用,它们测试缓冲区的大小,如果 OK ,则使用 Windows 2000 运行时库函数 RtlCopyMemory() 复制被请求的数据。剩余的函数只是上述两个基本函数的简单外包,用来操作常见的数据类型 DWORD , BOOL , PVOID 和 HANDLE 等。 SpyOutputBlock() 复制由调用者在 SPY_MEMORY_BLOCK 结构中指定的数据块,当然这需要首先验证请求范围内的字节都是可读的。如果传入的输入缓冲区的大小不正确, SpyInput*() 函数将返回 STATUS_INVALID_BUFFER_SIZE ,如果输出缓冲区比需要的小, SpyOutput*() 函数将返回 STATUS_BUFFER_TOO_SMALL 。

NTSTATUS SpyInputBinary (PVOID pData,

DWORD dData,

PVOID pInput,

DWORD dInput)

{

NTSTATUS ns = STATUS_INVALID_BUFFER_SIZE;

if (dData <= dInput)

{

RtlCopyMemory (pData, pInput, dData);

ns = STATUS_SUCCESS;

}

return ns;

}

// -----------------------------------------------------------------

NTSTATUS SpyInputDword (PDWORD pdValue,

PVOID pInput,

DWORD dInput)

{

return SpyInputBinary (pdValue, DWORD_, pInput, dInput);

}

// -----------------------------------------------------------------

NTSTATUS SpyInputBool (PBOOL pfValue,

PVOID pInput,

DWORD dInput)

{

return SpyInputBinary (pfValue, BOOL_, pInput, dInput);

}

// -----------------------------------------------------------------

NTSTATUS SpyInputPointer (PPVOID ppAddress,

PVOID pInput,

DWORD dInput)

{

return SpyInputBinary (ppAddress, PVOID_, pInput, dInput);

}

// -----------------------------------------------------------------

NTSTATUS SpyInputHandle (PHANDLE phObject,

PVOID pInput,

DWORD dInput)

{

return SpyInputBinary (phObject, HANDLE_, pInput, dInput);

}

列表 4-10. 从 IOCTL 缓冲区中读取输入数据

NTSTATUS SpyOutputBinary (PVOID pData,

DWORD dData,

PVOID pOutput,

DWORD dOutput,

PDWORD pdInfo)

{

NTSTATUS ns = STATUS_BUFFER_TOO_SMALL;

*pdInfo = 0;

if (dData <= dOutput)

{

RtlCopyMemory (pOutput, pData, *pdInfo = dData);

ns = STATUS_SUCCESS;

}

return ns;

}

// -----------------------------------------------------------------

NTSTATUS SpyOutputBlock (PSPY_MEMORY_BLOCK psmb,

PVOID pOutput,

DWORD dOutput,

PDWORD pdInfo)

{

NTSTATUS ns = STATUS_INVALID_PARAMETER;

if (SpyMemoryTestBlock (psmb->pAddress, psmb->dBytes))

{

ns = SpyOutputBinary (psmb->pAddress, psmb->dBytes,

pOutput, dOutput, pdInfo);

}

return ns;

}

// -----------------------------------------------------------------

NTSTATUS SpyOutputDword (DWORD dValue,

PVOID pOutput,

DWORD dOutput,

PDWORD pdInfo)

{

return SpyOutputBinary (&dValue, DWORD_,

pOutput, dOutput, pdInfo);

}

// -----------------------------------------------------------------

NTSTATUS SpyOutputBool (BOOL fValue,

PVOID pOutput,

DWORD dOutput,

PDWORD pdInfo)

{

return SpyOutputBinary (&fValue, BOOL_,

pOutput, dOutput, pdInfo);

}

// -----------------------------------------------------------------

NTSTATUS SpyOutputPointer (PVOID pValue,

PVOID pOutput,

DWORD dOutput,

PDWORD pdInfo)

{

return SpyOutputBinary (&pValue, PVOID_,

pOutput, dOutput, pdInfo);

}

列表 4-11. 向 IOCTL 的缓冲区中写入数据

你可能注意到 列表 4-7 中的 SpyDispatcher() 还引用了其他的 SpyInput*() 和 SpyOutput*() 函数。尽管这些函数最终还是调用 SpyInputBinary() 和 SpyOutputBinary() ,但它们还是比 列表 4-10 和 4-11 中的基本函数要复杂些,因此,稍后我们在讨论它们。现在,让我们从 SpyDispatcher() 开始,一步步的分析它的 switch/case 语句。

IOCTL 函数 SPY_IO_VERSION_INFO

IOCTL 的 SPY_IO_VERSION_INFO 函数用有关 Spy 驱动自身的数据填充调用者提供的 SPY_VERSION_INFO 结构。该功能不需要输入参数,需要使用 SpyOutputVersionInfo() 帮助函数。 列表 4-12 给出了该函数和 SPY_VERSION_INFO 结构,该函数很简单,它将 dVersion 成员设置为 SPY_VERSION 常量(当前是 100 ,表示 V1.00 ),该常量定义于 w2k_spy.h 中。然后复制驱动程序的符号化名称,即字符串常量 DRV_NAME (“ SBS Windows 2000 Spy Device ”)到 awName 成员。通过整除 dVersion 可获取主版本号,剩下的是次版本号。

typedef struct _SPY_VERSION_INFO

{

DWORD dVersion;

WORD awName [SPY_NAME];

}

SPY_VERSION_INFO, *PSPY_VERSION_INFO, **PPSPY_VERSION_INFO;

#define SPY_VERSION_INFO_ sizeof (SPY_VERSION_INFO)

NTSTATUS SpyOutputVersionInfo (PVOID pOutput,

DWORD dOutput,

PDWORD pdInfo)

{

SPY_VERSION_INFO svi;

svi.dVersion = SPY_VERSION;

wcscpyn (svi.awName, USTRING (CSTRING (DRV_NAME)), SPY_NAME);

return SpyOutputBinary (&svi, SPY_VERSION_INFO_,

pOutput, dOutput, pdInfo);

}

列表 4-12. 获取 Spy 驱动程序的版本信息

IOCTL 函数 SPY_IO_OS_INFO

该函数比上一个有趣的多。它是另一个只有输出的函数,不需要输入参数,使用几个操作系统的内部参数来填充调用者提供的 SPY_OS_INFO 结构。 列表 4-13 列出了该结构的定义,和 Dispatcher 调用的 SpyOutputOsInfo() 帮助函数。有些结构体成员只是被简单的设为定义于 DDK 头文件和 w2k_spy.h 中的常量;其他的将被设为从几个内部的内核变量和结构体中读取的当前值。在第二章中,你已经了解了变量 NtBuildNumber 和 NtGlobalFlag (由 ntoskrnl.exe 导出,参见 附录 B 中的 表 B-1 )。和其他的 Nt* 符号不同,这两个符号不指向 API 函数,而是指向位于内核的 .data section 中的变量。在 Win32 世界里,导出变量是十分罕见的。不过, Windows 2000 的几个内核模块都使用了这一技术。 Ntoskrnl.exe 导出了至少 55 个变量, ntdll.dll 提供了 4 个, hal.dll 提供了 1 个。 SpyOutputOsInfo() 将从 ntoskrnl.exe 导出的变量中复制 MmHighestUserAddress 、 MmUserProbeAddress 、 MmSystemRangeStart 、 NtGlobalFlag 、 KeI386MachineType 、 KeNumberProcessors 和 NtBuildNumber 到输出缓冲区中。

当一个模块从另一个模块中导入数据时,它需要使用 extern 关键字来通知编译器和链接器。这会使链接器生成一个进入模块导出节的入口,并会解析符号名以确定其地址。有些 extern 声明已经包含在 ntddk.h 。 列表 4-13 给出了缺失的那些 extern 声明。

extern PWORD NlsAnsiCodePage;

extern PWORD NlsOemCodePage;

extern PWORD NtBuildNumber;

extern PDWORD NtGlobalFlag;

extern PDWORD KeI386MachineType;

typedef struct _SPY_OS_INFO

{

DWORD dPageSize;

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 = 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 = Sha

[1] [2] [3] 下一页

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有