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


#define SPY_MEMORY_DATA_VALUE(_b,_v)
((WORD) (((_b) & SPY_MEMORY_DATA_BYTE ) |
((_v) ? SPY_MEMORY_DATA_VALID : 0)))
列表 4-25. SPY_MEMORY_DATA 的定义
将置换出去的页作为有效的地址范围有一个很重要的好处:当 SpyMemoryReadBlock() 试图读取这些页中的第一个字节时,这些页就会被很快的再次调入内存中 。稍后给出的内存 Dump 工具如果依赖 MmIsAddressValid(),有时就会拒绝显示指定地址范围中的数据(即使 5 分钟之前,它还可以显示这些数据),而这仅仅是因为这些页可能已被传送到了页面文件中 。
IOCTL 函数 SPY_IO_MEMORY_BLOCK
SPY_IO_MEMORY_BLOCK 依赖于 SPY_IO_MEMORY_DATA,因为它也是从任意地址复制内存块到调用者的缓冲区中 。主要的区别是: SPY_IO_MEMORY_DATA 试图复制所有可读取的字节,而对于 SPY_IO_MEMORY_BLOCK 来说,只要请求的范围中包含无效地址它就会失败,一个字节也不会复制 。第 6 章中需要这个函数来将位于内核空间中的数据结构传递给用户模式下的程序 。这一要求显然会大大限制这个函数,所以若一个结构体中包含无法读取的字节,就跳过它们,仅复制可读取的字节 。
和 SPY_IO_MEMORY_DATA 类似,SPY_IO_MEMORY_BLOCK 期望输入一个 SPY_MEMORY_BLOCK 结构来指定要复制的内存块的基地址和大小 。返回的数据,将是原始数据的 1:1 复制品 。输出缓冲区必须足够容纳要复制的全部内容 。否则,将会报告一个错误,并且不会返回任何数据 。
IOCTL 函数 SPY_IO_HANDLE_INFO
和前面介绍的 SPY_IO_PHSICAL 类似,这个函数允许用户模式下的程序调用其他途经无法调用的内核模式 API。内核驱动程序可通过 ntoskrnl.exe 导出的 obReferenceObjectByHandle() 来获取由句柄描述的对象的指针 。而在 Win32 下没有对等的函数 。不过,应用程序可以命令 Spy 设备执行这一函数,并返回对象的指针 。列表 4-26 展示了由 SpyDispatcher() 调用的 SpyOutputHandleInfo() 函数 。可通过 SpyInputHandle() 获(定义于 列表 4-10 )取输入的句柄 。
列表 4-26 顶部的 SPY_HANDLE_INFO 结构包含与句柄相关的对象体的指针,以及该句柄的属性,这两个都会由 ObReferenceObjectByHandle() 返回 。特别重要的一点是:如果 ObReferenceObjectByHandle() 调用成功,就必须调用 ObDereferenceObject() 来将对象的引用计数器恢复到先前的值 。如果没有这样做,将会导致“对象引用漏洞” 。
typedef struct _SPY_HANDLE_INFO
{
PVOID pObjectBody;
DWORD dHandleAttributes;
}
SPY_HANDLE_INFO, *PSPY_HANDLE_INFO, **PPSPY_HANDLE_INFO;
#define SPY_HANDLE_INFO_ sizeof (SPY_HANDLE_INFO)
// -----------------------------------------------------------------
NTSTATUS SpyOutputHandleInfo (HANDLE hObject,
PVOID pOutput,
DWORD dOutput,
PDWORD pdInfo)
{
SPY_HANDLE_INFO shi;
OBJECT_HANDLE_INFORMATION ohi;
NTSTATUS ns = STATUS_INVALID_PARAMETER;
if (hObject != NULL)
{
ns = ObReferenceObjectByHandle (hObject,
STANDARD_RIGHTS_READ,
NULL, KernelMode,
&shi.pObjectBody, &ohi);
}
if (ns == STATUS_SUCCESS)
{
shi.dHandleAttributes = ohi.HandleAttributes;
ns = SpyOutputBinary (&shi, SPY_HANDLE_INFO_,
pOutput, dOutput, pdInfo);
ObDereferenceObject (shi.pObjectBody);
}
return ns;
}
列表 4-26. 通过句柄引用一个对象

推荐阅读