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


#define SPY_MEMORY_BLOCK_ sizeof (SPY_MEMORY_BLOCK)
// -----------------------------------------------------------------
NTSTATUS SpyInputMemory (PSPY_MEMORY_BLOCK psmb,
PVOID pInput,
DWORD dInput)
{
return SpyInputBinary (psmb, SPY_MEMORY_BLOCK_, pInput, dInput);
}
// -----------------------------------------------------------------
NTSTATUS SpyOutputMemory (PSPY_MEMORY_BLOCK psmb,
PVOID pOutput,
DWORD dOutput,
PDWORD pdInfo)
{
NTSTATUS ns = STATUS_BUFFER_TOO_SMALL;
if (*pdInfo = SpyMemoryReadBlock (psmb, pOutput, dOutput))
{
ns = STATUS_SUCCESS;
}
return ns;
}
列表 4-23. 处理内存块
DWORD SpyMemoryReadBlock (PSPY_MEMORY_BLOCK psmb,
PSPY_MEMORY_DATA psmd,
DWORD dSize)
{
DWORD i;
DWORD n = SPY_MEMORY_DATA__ (psmb->dBytes);
if (dSize >= n)
{
psmd->smb = *psmb;
for (i = 0; i < psmb->dBytes; i)
{
psmd->awData [i] =
(SpyMemoryTestAddress (psmb->pbAddressi)
? SPY_MEMORY_DATA_VALUE (psmb->pbAddress [i], TRUE)
: SPY_MEMORY_DATA_VALUE (0, FALSE));
}
}
else
{
if (dSize >= SPY_MEMORY_DATA_)
{
psmd->smb.pbAddress = NULL;
psmd->smb.dBytes = 0;
}
n = 0;
}
return n;
}
// -----------------------------------------------------------------
BOOL SpyMemoryTestAddress (PVOID pVirtual)
{
return SpyMemoryPageEntry (pVirtual, NULL);
}
// -----------------------------------------------------------------
BOOL SpyMemoryTestBlock (PVOID pVirtual,
DWORD dBytes)
{
PBYTE pbData;
DWORD dData;
BOOL fOk = TRUE;
if (dBytes)
{
pbData = https://www.rkxy.com.cn/dnjc/(PBYTE) ((DWORD_PTR) pVirtual & X86_PAGE_MASK);
dData = https://www.rkxy.com.cn/dnjc/(((dBytesX86_OFFSET_4K (pVirtual) - 1)
/ PAGE_SIZE)1) * PAGE_SIZE;
do {
fOk = SpyMemoryTestAddress (pbData);
pbData= https://www.rkxy.com.cn/dnjc/PAGE_SIZE;
dData -= PAGE_SIZE;
}
while (fOk && dData);
}
return fOk;
}
列表 4-24. 复制内存块中的数据
SpyMemoryTestAddress() 用于测试数据的有效性,SpyMemoryReadBlock() 针对要读取的每个字节都会调用 SpyMemoryTestAddress()。SpyMemoryTestAddress() 在 列表 4-24 的下半部分给出,该函数只是简单的调用 SpyMemoryPageEntry(),不过传入的第二个参数为 NULL。SpyMemoryPageEntry() 在讨论 SPY_IO_PAGE_ENTRY 时已经介绍过( 列表 4-22 ) 。将其 PSPY_PAGE_ENTRY 指针参数设为 NULL,意味着调用者不关心指定线性地址对应的 page entry,因此,如果线性地址有效,函数将返回 TRUE。在 SpyMemoryPageEntry() 的上下文中,仅当一个线性地址对应的数据页存在于物理内存中,或者位于页面文件中,该地址才是有效的 。注意,这种行为与 ntoskrnl.exe 中的 API 函数 MmIsAddressValid() 并不一致,当指定的页不存在于物理内存中时,MmIsAddressValid() 总是返回 FALSE,即使这个有效的数据据页位于页面文件中也会如此 。列表 4-24 中的另一个函数 SpyMemoryTestBlock() 是 SpyMemoryTestAddress() 的增强版 。它可测试一个内存区域的有效性,它每次可测试指定块中的 4,096 个字节,直到测试完区域中的所有页为止 。
#define SPY_MEMORY_DATA_N(_n)
struct _SPY_MEMORY_DATA_##_n
【6 《Undocumented Windows 2000 Secrets》翻译 --- 第四章】{
SPY_MEMORY_BLOCK smb;
WORD awData [_n];
}
typedef SPY_MEMORY_DATA_N (0)
SPY_MEMORY_DATA, *PSPY_MEMORY_DATA, **PPSPY_MEMORY_DATA;
#define SPY_MEMORY_DATA_ sizeof (SPY_MEMORY_DATA)
#define SPY_MEMORY_DATA__(_n) (SPY_MEMORY_DATA_((_n) * WORD_))
#define SPY_MEMORY_DATA_BYTE 0x00FF
#define SPY_MEMORY_DATA_VALID 0x0100

推荐阅读