第五章 监控Native API调用
翻译:Kendiv( fcczj@263.net )
更新:Friday, April 29, 2005
声明:转载请注明出处,并保证文章的完整性,本人保留译文的所有权利。
为了帮助你编写自己的API Hook Client程序,我给出了一个简单的示例行的程序,该程序可以读取Hook协议缓冲区中的数据并在控制台窗口中显示。通过按下P、F和R键,可以实现暂停、过滤和重置功能,输出可以按照用户自定义的函数名模板进行过滤。这个示例程序叫做“SBS Windows 2000 API Hook Viewer”,其源代码位于本书光盘的\src\w2k_hook目录下。
控制Spy Device
为了方便,w2k_hook.exe程序使用了一组针对SPY_IO_HOOK_*函数的外包函数,列表5-19给出了这些函数。这些工具函数使得代码的可读性更好,并且在开发Spy Device的客户端程序时,大大降低了参数出错的可能性。
BOOL WINAPI SpyIoControl (HANDLE hDevice,
DWORD dCode,
PVOID pInput,
DWORD dInput,
PVOID pOutput,
DWORD dOutput)
{
DWORD dInfo = 0;
return DeviceIoControl (hDevice, dCode,
pInput, dInput,
pOutput, dOutput,
&dInfo, NULL)
&&
(dInfo == dOutput);
}
// -----------------------------------------------------------------
BOOL WINAPI SpyVersionInfo (HANDLE hDevice,
PSPY_VERSION_INFO psvi)
{
return SpyIoControl (hDevice, SPY_IO_VERSION_INFO,
NULL, 0,
psvi, SPY_VERSION_INFO_);
}
// -----------------------------------------------------------------
BOOL WINAPI SpyHookInfo (HANDLE hDevice,
PSPY_HOOK_INFO pshi)
{
return SpyIoControl (hDevice, SPY_IO_HOOK_INFO,
NULL, 0,
pshi, SPY_HOOK_INFO_);
}
// -----------------------------------------------------------------
BOOL WINAPI SpyHookInstall (HANDLE hDevice,
BOOL fReset,
PDWORD pdCount)
{
return SpyIoControl (hDevice, SPY_IO_HOOK_INSTALL,
&fReset, BOOL_,
pdCount, DWORD_);
}
// -----------------------------------------------------------------
BOOL WINAPI SpyHookRemove (HANDLE hDevice,
BOOL fReset,
PDWORD pdCount)
{
return SpyIoControl (hDevice, SPY_IO_HOOK_REMOVE,
&fReset, BOOL_,
pdCount, DWORD_);
}
// -----------------------------------------------------------------
BOOL WINAPI SpyHookPause (HANDLE hDevice,
BOOL fPause,
PBOOL pfPause)
{
return SpyIoControl (hDevice, SPY_IO_HOOK_PAUSE,
&fPause, BOOL_,
pfPause, BOOL_);
}
// -----------------------------------------------------------------
BOOL WINAPI SpyHookFilter (HANDLE hDevice,
BOOL fFilter,
PBOOL pfFilter)
{
return SpyIoControl (hDevice, SPY_IO_HOOK_FILTER,
&fFilter, BOOL_,
pfFilter, BOOL_);
}
// -----------------------------------------------------------------
BOOL WINAPI SpyHookReset (HANDLE hDevice)
{
return SpyIoControl (hDevice, SPY_IO_HOOK_RESET,
NULL, 0,
NULL, 0);
}
// -----------------------------------------------------------------
DWORD WINAPI SpyHookRead (HANDLE hDevice,
BOOL fLine,
PBYTE pbData,
DWORD dData)
{
DWORD dInfo;
if (!DeviceIoControl (hDevice, SPY_IO_HOOK_READ,
&fLine, BOOL_,
pbData, dData,
&dInfo, NULL))
{
dInfo = 0;
}
return dInfo;
}
// -----------------------------------------------------------------
BOOL WINAPI SpyHookWrite (HANDLE hDevice,
PBYTE pbData)
{
return SpyIoControl (hDevice, SPY_IO_HOOK_WRITE,
pbData, lstrlenA (pbData),
NULL, 0);
}
列表5-19. Device I/O Control工具函数
在使用列表5-19中的函数之前,Spy 设备驱动程序必须首先被加载并启动。这一操作和在第四章讨论的内存Spy程序w2k_mem.exe的要求大致相同。列表5-20给出了该程序的主函数:Execute(),该函数可加载/卸载Spy 设备驱动程序、打开/关闭一个设备句柄并可通过IOCTL和设备进行交互。如果你对比一下列表5-20和列表4-29,它们在开始和结尾处显然都是相似的。只是在中间部分,有所不同,因为这部分的代码依赖于具体的程序。
void WINAPI Execute (PPWORD ppwFilters,
DWORD dFilters)
{
SPY_VERSION_INFO svi;
SPY_HOOK_INFO shi;
DWORD dCount, i, j, k, n;
BOOL fPause, fFilter, fRepeat;
BYTE abData [HOOK_MAX_DATA];
WORD awData [HOOK_MAX_DATA];
WORD awPath [MAX_PATH] = L"?";
SC_HANDLE hControl = NULL;
HANDLE hDevice = INVALID_HANDLE_VALUE;
_printf (L"\r\nLoading \"%s\" (%s) ...\r\n",
awSpyDisplay, awSpyDevice);
if (w2kFilePath (NULL, awSpyFile, awPath, MAX_PATH))
{
_printf (L"Driver: \"%s\"\r\n",
awPath);
hControl = w2kServiceLoad (awSpyDevice, awSpyDisplay,
awPath, TRUE);
}
if (hControl != NULL)
{
_printf (L"Opening \"%s\" ...\r\n",
awSpyPath);
hDevice = CreateFile (awSpyPath,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
}
else
{
_printf (L"Unable to load the spy device driver.\r\n");
}
if (hDevice != INVALID_HANDLE_VALUE)
{
if (SpyVersionInfo (hDevice, &svi))
{
_printf (L"\r\n"
L"%s V%lu.%02lu ready\r\n",
svi.awName,
svi.dVersion / 100, svi.dVersion % 100);
}
if (SpyHookInfo (hDevice, &shi))
{
_printf (L"\r\n"
L"API hook parameters: 0x%08lX\r\n"
L"SPY_PROTOCOL structure: 0x%08lX\r\n"
L"SPY_PROTOCOL data buffer: 0x%08lX\r\n"
L"KeServiceDescriptorTable: 0x%08lX\r\n"
L"KiServiceTable: 0x%08lX\r\n"
L"KiArgumentTable: 0x%08lX\r\n"
L"Service table size: 0x%lX (%lu)\r\n",
shi.psc,
shi.psp,
shi.psp->abData,
shi.psdt,
shi.sdt.ntoskrnl.ServiceTable,
shi.sdt.ntoskrnl.ArgumentTable,
shi.ServiceLimit, shi.ServiceLimit);
}
SpyHookPause (hDevice, TRUE, &fPause ); fPause = FALSE;
SpyHookFilter (hDevice, TRUE, &fFilter); fFilter = FALSE;
if (SpyHookInstall (hDevice, TRUE, &dCount))
{
_printf (L"\r\n"
L"Installed %lu API hooks\r\n",
dCount);
}
_printf (L"\r\n"
L"Protocol control keys:\r\n"
L"\r\n"
L"P - pause ON/off\r\n"
L"F - filter ON/off\r\n"
L"R - reset protocol\r\n"
L"ESC - exit\r\n"
L"\r\n");
for (fRepeat = TRUE; fRepeat;)
{
if (n = SpyHookRead (hDevice, TRUE,
abData, HOOK_MAX_DATA))
{
if (abData [0] == ''''-'''')