上次讲了关于 hook atapi 的 IRP_MJ_INTERNAL_DEVICE_CONTROL 例程
IdePortDispatch和StartIo,来阻止特定扇区的读写。但是dispatch hook是很容易被ARK
检测到的,图1即为xuter的检测结果。

为了绕过 ARK 的检测,笔者决定进行深度的HOOK,于是便有了此文。要进行深度的HOOK
就要了解 IdePortDispatch后的调用流程。在百度的帮助下,笔者知道了调用流程。这里引
用 AZY的一些内容,并略加修改:
“读写IRP->IdePortDispatch->IoStartPacket->IdePortStartIo,到这里分两支:有DMA
能力的走: BmSetup->BmReceiveScatterGatherList->IdePortAllocateAccessToken->以下
与无DMA能力流程相同;无DMA能力的走:
可以发现,无论设备是否有DMA能力,最终都会调用无 DMA 能力中的那些函数,于是可
以对这些函数进行 hook,这样一方面可以拦截请求,另一方面又不会被 ARK 检测到。那么
要拦截下发的请求,那就要知道这些函数所接受的参数,通过IDA的分析后,笔者得到了以
下 4 个函数的原型,其中类似于devext_add_ach这样的命名,意思是devext里偏移 0xac:
IdePortAllocateAccessToken->
CallIdeStartIoSynchronized->KeSynchronizeExecution->IdeStartIoSynchronized->Ata
piStartIo->IdeSendCommand->IdeReadWrite->Io端口”
BOOLEAN __stdcall
AtapiStartIo( ULONG devext_add_ach,
struct _SCSI_REQUEST_BLOCK* srb);
BOOLEAN __stdcall
IdeStartIoSynchronized(PVOID devobj);
int __stdcall
CallIdeStartIoSynchronized(int devext_add_7ch,
int devext_add_7ch,
int devext_add_7ch,
PVOID dev_obj);
int __stdcall
IdePortStartIo(PVOID dev_obj, PIRP Irp);
Devext+0x7c 处是一个函数的指针,笔者不清楚此处保存的的什么,望牛人告之。
经过比较后,笔者选择了 AtapiStartIo 进行 HOOK,但是 AtapiStartIo 并未被导出,
并且也不被保存在任何一个结构中,要找这个函数地址的办法就是特征搜索,或者栈回溯了。
先来说说栈回溯的方法。用IDA分析后,笔者发现AtapiStartIo在devext_add_ach==0
并且 srb-> Function==2时(如对 SRB 结构不清楚的,请看上期黑防文章“atapi层禁止特
定扇区的读写”),会调用到RtlCompareMemory,可以HOOK 这个函数进行栈回溯。但是笔者
考虑到 AtapiStartIo 调用 RtlCopareMemory 的种种限制条件,特别是 devext_add_ach==0
这个条件,笔者没有去尝试置此处为 0,并下发 srb-> Function==2 的 IRP,如果读者感兴
趣,可以自行尝试。最终笔者采用了最笨的特征搜索。
在仔细观察上面的流程后可以发现,atapi 流程中会调用 KeSynchronizeExecution 这
个导出的函数,于是思路就有了:先hook KeSynchronizeExecution,进行判断是否是Atapi
的调用,是则得到IdeStartIoSynchronized地址,然后在 IdeStartIoSynchronized中进行
特征搜索,得到AtapiStartIo地址;否则直接跳过。
那么新问题出现了,怎么判断是否是 Atapi 的调用呢?让我们来看看
CallIdeStartIoSynchronized的代码:
f97a42ce 8bff mov edi,edi
f97a42d0 55 push ebp
f97a42d1 8bec mov ebp,esp
f97a42d3 53 push ebx
f97a42d4 8b5d14 mov ebx,dword ptr [ebp+14h] // atapi生成的
设备
………………
f97a42ea 53 push ebx
f97a42eb 683e3f7af9 push offset atapi!IdeStartIoSynchronized
(f97a3f3e)
f97a42f0 ffb6d8000000 push dword ptr [esi+0D8h] |