NDIS是微软WDM驱动的一种,目前只能用DDK来开发,Delphi是不能用来开发DNSI驱动的。我认为NDIS是微软windows构架中最成功,也是最复杂的分层驱动模型。从本人涉及过的NDIS开发来看,目前在这一层的拦截和过滤主要有两个方向,基于NDIS HOOK和基于NDIS miniport and protocol。前者主要是类似于我们win32层常用的api hook技术,利用微软未公开函数ntquerysysteminfomation得到微软的NDIS接口驱动“NDIS.SYS”的基地址,然后挂接它的接口函数,如下是部分代码片断:
if(GetNdisModuleAddress() && m_NdisBaseAddress != NULL)
{
if(HookFunction(m_NdisBaseAddress, "NdisRegisterProtocol", HookNdisRegisterProtocol
, (ULONG*)&m_pNdisRegisterProtocol) == NULL
)
dprintf(("Hook NdisRegisterProtocol Failure/n"
);
if(HookFunction(m_NdisBaseAddress, "NdisDeregisterProtocol", HookNdisDeregisterProtocol
, (ULONG*)&m_pNdisDeregisterProtocol) == NULL
)
dprintf(("Hook NdisDeregisterProtocol Failure/n"
);
if(HookFunction(m_NdisBaseAddress, "NdisOpenAdapter", HookNdisOpenAdapter
, (ULONG*)&m_pNdisOpenAdapter) == NULL
)
dprintf(("Hook NdisOpenAdapter Failure/n"
);
}
//
// Hook 一个系统函数
// 参数:
// pBaseAddress: 要Hook函数所在文件在内存映象的基地址,比如NDIS.SYS的基地址
// Name: 要Hook的函数名
// InFunc: 自己的函数地址
// OutFunc: Hook后保存系统的函数地址
// 返回值:
// NULL: Hook失败
// Not NULL: 返回系统函数地址,与*OutFunc相同
//
//
PVOID HookFunction(PVOID pBaseAddress, PCSTR Name, PVOID InFunc, ULONG* OutFunc)
{
PIMAGE_DOS_HEADER pDosHeader = NULL;
PIMAGE_NT_HEADERS pNtHeader = NULL;
PIMAGE_DATA_DIRECTORY pDirectory = NULL;
PIMAGE_EXPORT_DIRECTORY pExports = NULL;
ULONG nSize, Address, i;
PULONG pFunctions = NULL;
PSHORT pOrdinals = NULL;
PULONG pNames = NULL;
PVOID pFunction = NULL;
ULONG Ordinal = 0;
if(pBaseAddress == NULL)
return NULL;
pDosHeader = (PIMAGE_DOS_HEADER)pBaseAddress;
pNtHeader = (PIMAGE_NT_HEADERS)((PCHAR)pBaseAddress + pDosHeader->e_lfanew);
pDirectory = pNtHeader->OptionalHeader.DataDirectory + IMAGE_DIRECTORY_ENTRY_EXPORT;
nSize = pDirectory->Size;
Address = pDirectory->VirtualAddress;
pExports = (PIMAGE_EXPORT_DIRECTORY)((PCHAR)pBaseAddress + Address);
pFunctions = (PULONG)((PCHAR)pBaseAddress + pExports->AddressOfFunctions);
pOrdinals = (PSHORT)((PCHAR)pBaseAddress + pExports->AddressOfNameOrdinals);
pNames = (PULONG)((PCHAR)pBaseAddress + pExports->AddressOfNames);
for(i = 0; i < pExports->NumberOfNames; i++)
{
Ordinal = pOrdinals
;
if(pFunctions[Ordinal] < Address || pFunctions[Ordinal] >= Address + nSize)
{
if(strcmp((PSTR)((PCHAR)pBaseAddress + pNames), Name) == 0)
{
pFunction = (PCHAR)pBaseAddress + pFunctions[Ordinal];
*OutFunc = (ULONG)pFunction;
DisableProtection();
pFunctions[Ordinal] = (ULONG)((ULONG)InFunc - (ULONG)pBaseAddress);
EnableProtection();
break;
}
}
}
return pFunction;
}