王朝网络
分享
 
 
 

《Undocumented Windows 2000 Secrets》翻译 --- 第五章(5)

王朝system·作者佚名  2006-01-31
宽屏版  字体: |||超大  

第五章 监控Native API调用

翻译:Kendiv( fcczj@263.net )

更新:Tuesday, April 19, 2005

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

在用户模式下控制API Hooks

运行在用户模式的Spy客户端可通过一组IOCTL函数来控制API Hook机制及其生成的协议。这一组函数的名字都以SPY_IO_HOOK_开始,在第四章已介绍过它们,在第四章还讨论了w2k_spy.sys的内存Spy函数(参见列表4-7和表4-2)。

下面的表5-3再次给出了与表4-2相关的部分。列表5-10是列表4-7的一个摘录,示范了Hook管理函数是如何被分派(dispatch)的。这些管理函数在后面将会被反复提及。

表5-3. Spy Device支持的IOCTL Hook管理函数

函数名称

ID

IOCTL代码

描 述

SPY_IO_HOOK_INFO

11

0x8000602C

返回Native API Hook的相关信息

SPY_IO_HOOK_INSTALL

12

0x8000E030

安装Native API Hook

SPY_IO_HOOK_REMOVE

13

0x8000 E034

移除Native API Hook

SPY_IO_HOOK_PAUSE

14

0x8000 E038

暂停/恢复 Hook协议

SPY_IO_HOOK_FILTER

15

0x8000 E03C

允许/禁止 Hook协议过滤器

SPY_IO_HOOK_RESET

16

0x8000 E040

清除Hook协议

SPY_IO_HOOK_READ

17

0x80006044

从Hook协议中读取数据

SPY_IO_HOOK_WRITE

18

0x8000E048

向Hook协议中写入数据

NTSTATUS SpyDispatcher (PDEVICE_CONTEXT pDeviceContext,

DWORD dCode,

PVOID pInput,

DWORD dInput,

PVOID pOutput,

DWORD dOutput,

PDWORD pdInfo)

{

SPY_MEMORY_BLOCK smb;

SPY_PAGE_ENTRY spe;

SPY_CALL_INPUT sci;

PHYSICAL_ADDRESS pa;

DWORD dValue, dCount;

BOOL fReset, fPause, fFilter, fLine;

PVOID pAddress;

PBYTE pbName;

HANDLE hObject;

NTSTATUS ns = STATUS_INVALID_PARAMETER;

MUTEX_WAIT (pDeviceContext->kmDispatch);

*pdInfo = 0;

switch (dCode)

{

case SPY_IO_VERSION_INFO:

{

ns = SpyOutputVersionInfo (pOutput, dOutput, pdInfo);

break;

}

case SPY_IO_OS_INFO:

{

ns = SpyOutputOsInfo (pOutput, dOutput, pdInfo);

break;

}

case SPY_IO_SEGMENT:

{

if ((ns = SpyInputDword (&dValue,

pInput, dInput))

== STATUS_SUCCESS)

{

ns = SpyOutputSegment (dValue,

pOutput, dOutput, pdInfo);

}

break;

}

case SPY_IO_INTERRUPT:

{

if ((ns = SpyInputDword (&dValue,

pInput, dInput))

== STATUS_SUCCESS)

{

ns = SpyOutputInterrupt (dValue,

pOutput, dOutput, pdInfo);

}

break;

}

case SPY_IO_PHYSICAL:

{

if ((ns = SpyInputPointer (&pAddress,

pInput, dInput))

== STATUS_SUCCESS)

{

pa = MmGetPhysicalAddress (pAddress);

ns = SpyOutputBinary (&pa, PHYSICAL_ADDRESS_,

pOutput, dOutput, pdInfo);

}

break;

}

case SPY_IO_CPU_INFO:

{

ns = SpyOutputCpuInfo (pOutput, dOutput, pdInfo);

break;

}

case SPY_IO_PDE_ARRAY:

{

ns = SpyOutputBinary (X86_PDE_ARRAY, SPY_PDE_ARRAY_,

pOutput, dOutput, pdInfo);

break;

}

case SPY_IO_PAGE_ENTRY:

{

if ((ns = SpyInputPointer (&pAddress,

pInput, dInput))

== STATUS_SUCCESS)

{

SpyMemoryPageEntry (pAddress, &spe);

ns = SpyOutputBinary (&spe, SPY_PAGE_ENTRY_,

pOutput, dOutput, pdInfo);

}

break;

}

case SPY_IO_MEMORY_DATA:

{

if ((ns = SpyInputMemory (&smb,

pInput, dInput))

== STATUS_SUCCESS)

{

ns = SpyOutputMemory (&smb,

pOutput, dOutput, pdInfo);

}

break;

}

case SPY_IO_MEMORY_BLOCK:

{

if ((ns = SpyInputMemory (&smb,

pInput, dInput))

== STATUS_SUCCESS)

{

ns = SpyOutputBlock (&smb,

pOutput, dOutput, pdInfo);

}

break;

}

case SPY_IO_HANDLE_INFO:

{

if ((ns = SpyInputHandle (&hObject,

pInput, dInput))

== STATUS_SUCCESS)

{

ns = SpyOutputHandleInfo (hObject,

pOutput, dOutput, pdInfo);

}

break;

}

case SPY_IO_HOOK_INFO:

{

ns = SpyOutputHookInfo (pOutput, dOutput, pdInfo);

break;

}

case SPY_IO_HOOK_INSTALL:

{

if (((ns = SpyInputBool (&fReset,

pInput, dInput))

== STATUS_SUCCESS)

&&

((ns = SpyHookInstall (fReset, &dCount))

== STATUS_SUCCESS))

{

ns = SpyOutputDword (dCount,

pOutput, dOutput, pdInfo);

}

break;

}

case SPY_IO_HOOK_REMOVE:

{

if (((ns = SpyInputBool (&fReset,

pInput, dInput))

== STATUS_SUCCESS)

&&

((ns = SpyHookRemove (fReset, &dCount))

== STATUS_SUCCESS))

{

ns = SpyOutputDword (dCount,

pOutput, dOutput, pdInfo);

}

break;

}

case SPY_IO_HOOK_PAUSE:

{

if ((ns = SpyInputBool (&fPause,

pInput, dInput))

== STATUS_SUCCESS)

{

fPause = SpyHookPause (fPause);

ns = SpyOutputBool (fPause,

pOutput, dOutput, pdInfo);

}

break;

}

case SPY_IO_HOOK_FILTER:

{

if ((ns = SpyInputBool (&fFilter,

pInput, dInput))

== STATUS_SUCCESS)

{

fFilter = SpyHookFilter (fFilter);

ns = SpyOutputBool (fFilter,

pOutput, dOutput, pdInfo);

}

break;

}

case SPY_IO_HOOK_RESET:

{

SpyHookReset ();

ns = STATUS_SUCCESS;

break;

}

case SPY_IO_HOOK_READ:

{

if ((ns = SpyInputBool (&fLine,

pInput, dInput))

== STATUS_SUCCESS)

{

ns = SpyOutputHookRead (fLine,

pOutput, dOutput, pdInfo);

}

break;

}

case SPY_IO_HOOK_WRITE:

{

SpyHookWrite (pInput, dInput);

ns = STATUS_SUCCESS;

break;

}

case SPY_IO_MODULE_INFO:

{

if ((ns = SpyInputPointer (&pbName,

pInput, dInput))

== STATUS_SUCCESS)

{

ns = SpyOutputModuleInfo (pbName,

pOutput, dOutput, pdInfo);

}

break;

}

case SPY_IO_PE_HEADER:

{

if ((ns = SpyInputPointer (&pAddress,

pInput, dInput))

== STATUS_SUCCESS)

{

ns = SpyOutputPeHeader (pAddress,

pOutput, dOutput, pdInfo);

}

break;

}

case SPY_IO_PE_EXPORT:

{

if ((ns = SpyInputPointer (&pAddress,

pInput, dInput))

== STATUS_SUCCESS)

{

ns = SpyOutputPeExport (pAddress,

pOutput, dOutput, pdInfo);

}

break;

}

case SPY_IO_PE_SYMBOL:

{

if ((ns = SpyInputPointer (&pbName,

pInput, dInput))

== STATUS_SUCCESS)

{

ns = SpyOutputPeSymbol (pbName,

pOutput, dOutput, pdInfo);

}

break;

}

case SPY_IO_CALL:

{

if ((ns = SpyInputBinary (&sci, SPY_CALL_INPUT_,

pInput, dInput))

== STATUS_SUCCESS)

{

ns = SpyOutputCall (&sci,

pOutput, dOutput, pdInfo);

}

break;

}

}

MUTEX_RELEASE (pDeviceContext->kmDispatch);

return ns;

}

列表5-10. Spy Driver的Hook命令分派器

IOCTL函数 SPY_IO_HOOK_INFO

IOCTL函数SPY_IO_HOOK_INFO采用Hook机制的当前信息来填充一个SPY_HOOK_INFO结构,这和系统的SDT类似。SPY_HOOK_INFO结构(列表5-11)中引用了多个前面介绍过的结构:

l SERVICE_DESCRIPTOR_TABLE结构,定义于列表5-1

l SPY_CALL和SPY_HOOK_ENTRY结构,定义于列表5-2

l SPY_HEADER和SPY_PROTOCOL结构,定义于列表5-9

typedef struct _SPY_HOOK_INFO

{

SPY_HEADER sh;

PSPY_CALL psc;

PSPY_PROTOCOL psp;

PSERVICE_DESCRIPTOR_TABLE psdt;

SERVICE_DESCRIPTOR_TABLE sdt;

DWORD ServiceLimit;

NTPROC ServiceTable [SDT_SYMBOLS_MAX];

BYTE ArgumentTable [SDT_SYMBOLS_MAX];

SPY_HOOK_ENTRY SpyHooks [SDT_SYMBOLS_MAX];

}

SPY_HOOK_INFO, *PSPY_HOOK_INFO, **PPSPY_HOOK_INFO;

#define SPY_HOOK_INFO_ sizeof (SPY_HOOK_INFO)

列表5-11. SPY_HOOK_INFO结构定义

在计算该结构体成员的值时一定要小心。某些成员中的指针指向内核模式下的内存块,这些内存地址在用户模式下是无法访问的。不过,你可以使用Spy设备的SPY_IO_MEMORY_DATA函数来检查这些内存块中的数据。

IOCTL函数 SPY_IO_HOOK_INSTALL

SPY_IO_HOOK_INSTALL函数使用存储在全局aSpyHooks[]数组中的Hook进入点(Hook Entry Point)来修改(patch)ntoskrnl.exe在系统SDT中的服务表(Service Table)。该全局数组在驱动程序初始化时由SpyHookInitialize()(列表5-5)和SpyHookInitializeEx()(列表5-3)函数构建。aSpyHooks[]数组中的每个有效的元素均包含一个hook进入点以及相应的格式字符串地址。SpyDispatcher()调用辅助函数SpyHookInstall()(见列表5-12)来安装Hook。SpyHookInstall()使用的SpyHookExchange()函数也包含在列表5-12中。

DWORD SpyHookExchange (void)

{

PNTPROC ServiceTable;

BOOL fPause;

DWORD i;

DWORD n = 0;

fPause = SpyHookPause (TRUE);

ServiceTable = KeServiceDescriptorTable->ntoskrnl.ServiceTable;

for (i = 0; i < SDT_SYMBOLS_MAX; i++)

{

if (aSpyHooks [i].pbFormat != NULL)

{

aSpyHooks [i].Handler = (NTPROC)

InterlockedExchange ((PLONG) ServiceTable+i,

( LONG) aSpyHooks [i].Handler);

n++;

}

}

gfSpyHookState = !gfSpyHookState;

SpyHookPause (fPause);

return n;

}

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

NTSTATUS SpyHookInstall (BOOL fReset,

PDWORD pdCount)

{

DWORD n = 0;

NTSTATUS ns = STATUS_INVALID_DEVICE_STATE;

if (!gfSpyHookState)

{

ghSpyHookThread = PsGetCurrentThreadId ();

n = SpyHookExchange ();

if (fReset) SpyHookReset ();

ns = STATUS_SUCCESS;

}

*pdCount = n;

return ns;

}

列表5-12. Patch the System’s API Service Table

在安装和移除Hooks时都需要用到SpyHookExchange()函数,该函数只是简单的交换系统的API服务表和aSpyHooks[]数组中的内容。因此,若调用两次SpyHookExchange(),则可恢复服务表和数组的初始状态。SpyHookExchange()遍历aSpyHooks[]数组来寻找包含格式字符串指针的数组元素。这里的格式字符串是为了指定要监控的API函数。在这种情况下,将使用ntoskrnl.exe中的InterlockedExchange()函数来交换服务表中的API函数指针和aSpyHooks[]元素的Handler成员,使用InterlockedExchange()函数是为了保证没有其他线程干扰这一操作。协议机制在这一过程中将被临时停止,直到对服务表的修改结束。SpyHookInstall()仅是SpyHookExchange()的一个外包函数,这样做是为了执行一些附加的操作:

l 如果全局标志gfSpyHookState表示Hooks仍在安装,则禁止访问服务表(Service Table)。

l 调用者的线程ID将被写入全局变量ghSpyHookThread。SpyHookInitializeEx()函数中的Hook分派器(Dispatcher)将屏蔽该变量所指线程发出的API调用。以避免Hook协议受到干扰。

l 根据客户端的请求,协议会被重置。这意味着所有的缓冲区都将被清空,并且句柄目录也将被重新初始化。

SPY_IO_HOOK_INSTALL接收调用者传入的一个逻辑型参数。如果为TRUE,协议将在Hooks安装完成后被重置。这是常用的一个选项。如果为FALSE,协议将从前一次Hook会话结束的位置继续。该函数的返回值表示服务表中被修改的项数。如果是Windows 2000,SPY_IO_HOOK_INSTALL返回的是44,这一数值正是列表5-6给出的格式字符串数组apdSdtFormats[]的大小。在Windows NT 4.0下,则仅有42个Hook被安装,因为API函数NtNotifyChangeMultipleKeys()和NtQueryOpenSubKeys()并不被NT 4.0支持。

…………待续…………..

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
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- 王朝网络 版权所有