直接粘源代码:
里面实现了一个简易HookPort驱动,并在XPSP3下通过。并且实现了大多数关键功能。
由于HookPort里面有太多的重复性劳动,所以对于Hook函数我只写了一个hookntcreatekey函数的原型,其他都类似。
没有注释,大家凑合看吧。
#include <ntddk.h>
#include <stdio.h>
#include <string.h>
#include <ntimage.h>
#include "MyHookPort.h"
extern PULONG InitSafeBootMode;
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRINGpRegistryPath)
{
ULONG MajorVersion;
ULONG MinorVersion;
ULONG BuildNumber;
PDEVICE_OBJECT pDeviceObject;
UNICODE_STRING DeviceName;
UNICODE_STRING SymboLinkName;
NTSTATUS status;
PsGetVersion(&MajorVersion,&MinorVersion, &BuildNumber,0);
if ( MajorVersion != 5&& MajorVersion != 6)
returnSTATUS_NOT_IMPLEMENTED;
if ( MinorVersion != 0&& MinorVersion != 1)
returnSTATUS_UNSUCCESSFUL;
if ( *InitSafeBootMode > 0)
return STATUS_UNSUCCESSFUL;
RtlInitUnicodeString(&DeviceName,L"\Device\MyHookPort");
RtlInitUnicodeString(&SymboLinkName,L"\DosDevices\MyHookPort");
status = IoCreateDevice(pDriverObject,sizeof(MYHOOKPORT_DEVICE_EXTENSION),&DeviceName,FILE_DEVICE_UNKNOWN, 0x100, 0,&pDeviceObject);
if ( !NT_SUCCESS(status) )
{
//HookPortInitial();
returnSTATUS_UNSUCCESSFUL;
}
if ( !NT_SUCCESS(IoCreateSymbolicLink(&SymboLinkName,&DeviceName)))
{
IoDeleteDevice(pDeviceObject);
returnSTATUS_UNSUCCESSFUL;
}
pDriverObject->MajorFunction[IRP_MJ_CREATE]= PassThrough;
pDriverObject->MajorFunction[IRP_MJ_CLOSE]= PassThrough;
pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]= MyDeviceIoControl;
//else
//{
//SetDeviceExtension(pDeviceObject);
//MonitorKiFastCallHook();
//}
HookPortInitial();
HookKiFastCallEntry();
//IoDeleteSymbolicLink(&SymboLinkName);
//IoDeleteDevice(pDeviceObject);
return STATUS_SUCCESS;
}
NTSTATUS PassThrough(PDEVICE_OBJECT pDev, PIRP pIrp)
{
pIrp->IoStatus.Status =STATUS_SUCCESS;
pIrp->IoStatus.Information =0;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS MyDeviceIoControl(PDEVICE_OBJECT pDev, PIRP pIrp)
{
return STATUS_SUCCESS;
}
NTSTATUS HookPortInitial()
{
UINT_PTR Win32Base;
SIZE_TWin32Size;
ANSI_STRING Name;
if( GetMoudleBaseAndSize("win32k.sys",&Win32Base, &Win32Size) )
{
if(!FindKeServiceDescriptorTableShadow())
returnSTATUS_UNSUCCESSFUL;
}
RtlInitAnsiString(&Name,"KeServiceDescriptorTable");
gTableAddress =(PKESERVICE_TABLE_DESCRIPTOR)GetFuncAddrAndEATAddrInNtoskrnl(&Name);
if ( gTableAddress == NULL ||!MmIsAddressValid((PVOID)gTableAddress) )
{
returnSTATUS_UNSUCCESSFUL;
}
return STATUS_UNSUCCESSFUL;
}
VOID SetDeviceExtension(PDEVICE_OBJECT pDevObj)
{
PMYHOOKPORT_DEVICE_EXTENSION pDevExt =(PMYHOOKPORT_DEVICE_EXTENSION)pDevObj->DeviceExtension;
pDevExt->Undefined = 2;
pDevExt->pPrepareFilterRuleTable =NULL;
pDevExt->pSetFilterFunctions =NULL;
pDevExt->pSetFilterRule =NULL;
}
VOID MonitorKiFastCallHook()
{
return;
}
BOOL GetMoudleBaseAndSize(CONST CHAR *szModuleName, PUINT_PTRpBase, PSIZE_T pModuleSize)
{
PSYSTEM_MODULE_INFORMATIONpSysModuleInforBuf;
ULONG ulPageSize;
NTSTATUS status;
ULONG ReturnLength;
ULONG ModuleCount;
ULONG i;
BOOL bRet;
pSysModuleInforBuf = NULL;
ulPageSize = PAGE_SIZE;
bRet = FALSE;
do
{
if ( pSysModuleInforBuf !=NULL)
ExFreePool(pSysModuleInforBuf);
pSysModuleInforBuf =(PSYSTEM_MODULE_INFORMATION)ExAllocatePoolWithTag(NonPagedPool,ulPageSize, POOL_TAG);
if ( pSysModuleInforBuf ==NULL)
returnFALSE;
status =ZwQuerySystemInformation(SystemModuleInformation,pSysModuleInforBuf, ulPageSize,&ReturnLength);
if ( !NT_SUCCESS(status)&& status !=STATUS_INFO_LENGTH_MISMATCH)
{
bRet =FALSE;
gotoFREE_BUF;
}
ulPageSize += PAGE_SIZE;
}while ( !NT_SUCCESS(status) );
if ( szModuleName == NULL)
{
*pBase =(UINT_PTR)pSysModuleInforBuf->Module[0].Base;
*pModuleSize =pSysModuleInforBuf->Module[0].Size;
bRet = TRUE;
goto FREE_BUF;
}
ModuleCount =pSysModuleInforBuf->Count;
for ( i = 0; i < ModuleCount;i++)
{
char * pRet =strrchr(pSysModuleInforBuf->Module[i].ImageName,'\');
if ( pRet == NULL )
pRet =pSysModuleInforBuf->Module[i].ImageName;
else
pRet +=1;
if( !strcmp(pRet ,szModuleName) )
{
*pBase =(UINT_PTR)pSysModuleInforBuf->Module[i].Base;
*pModuleSize= pSysModuleInforBuf->Module[i].Size;
bRet =TRUE;
break;
}
}
FREE_BUF:
if ( pSysModuleInforBuf )
{
ExFreePool(pSysModuleInforBuf);
}
return bRet;
}
BOOL MemoryIsVaild(PVOID VirtualAddress, SIZE_T size)
{
PUCHAR cur, end;
cur = (PUCHAR)VirtualAddress;
end = (PUCHAR)( ((ULONG)VirtualAddress +(ULONG)(size - 1))&0xfffff000 + PAGE_SIZE);
do
{
if ( !MmIsAddressValid(cur))
returnFALSE;
cur = (PUCHAR)((ULONG)((ULONG)cur & 0xfffff000) +(ULONG)PAGE_SIZE);
} while (cur != end);
return TRUE;
}
BOOL FindKeServiceDescriptorTableShadow()
{
ANSI_STRING Name;
UINT_PTR nAddress1, nAddress2;
PUCHAR Cur, End;
PKESERVICE_TABLE_DESCRIPTOR pServiceTable;
BOOL bFinded = FALSE;
RtlInitAnsiString(&Name,"KeAddSystemServiceTable");
nAddress1 =GetFuncAddrAndEATAddrInNtoskrnl(&Name);
//在KeAddSystemServiceTable中寻找
if ( nAddress1 != 0&&MmIsAddressValid((PVOID)nAddress1))
{
End = (PUCHAR)nAddress1 +0x100;
for ( Cur = (PUCHAR)nAddress1;Cur < End; Cur++)
{
if (MemoryIsVaild(Cur, 2) )
if( *(PUSHORT)Cur == 0x888D )
if( MemoryIsVaild(Cur + 2, 4) )
{
pServiceTable= (PKESERVICE_TABLE_DESCRIPTOR)( *(PULONG)(Cur + 2));
if( MemoryIsVaild((PUCHAR)pServiceTable + 0x10, 4) )
if(MemoryIsVaild((PUCHAR)pServiceTable + 0x18, 4))
{
bFinded= TRUE;
break;
}
}
}
}
//在KeRemoveSystemServiceTable中寻找
else
{
RtlInitAnsiString(&Name,"KeRemoveSystemServiceTable");
nAddress2 =GetFuncAddrAndEATAddrInNtoskrnl(&Name);
if ( nAddress2 != 0&&MmIsAddressValid((PVOID)nAddress2))
{
End =(PUCHAR)nAddress2 + 0x100;
for ( Cur =(PUCHAR)nAddress2; Cur < End; Cur++)
{
if( MemoryIsVaild(Cur, 2) )
if( *(PUSHORT)Cur == 0x8889 )
if( MemoryIsVaild(Cur + 2, 4) )
{
pServiceTable= (PKESERVICE_TABLE_DESCRIPTOR)( *(PULONG)(Cur + 2));
if( MemoryIsVaild((PUCHAR)pServiceTable + 0x10, 4) )
if(MemoryIsVaild((PUCHAR)pServiceTable + 0x18, 4))
{
bFinded= TRUE;
break;
}
}
}
}
else
{
if (nAddress1 )
{
nAddress2= nAddress1;
End= (PUCHAR)( (ULONG)nAddress2 & 0xfffff000 +0xffa);
for( Cur = (PUCHAR)nAddress1; Cur < End; Cur++)
{
if( *(PUSHORT)Cur == 0x888D )
{
pServiceTable= (PKESERVICE_TABLE_DESCRIPTOR)( *(PULONG)(Cur + 2));
if( MemoryIsVaild((PUCHAR)pServiceTable + 0x10, 4) )
if(MemoryIsVaild((PUCHAR)pServiceTable + 0x18, 4))
{
bFinded= TRUE;
break;
}
}
}
}
}
}
if ( bFinded == TRUE)
{
gShadowBase =pServiceTable[1].Base;
gShadowLimit =pServiceTable[1].Limit;
}
if ( gShadowBase == 0)
return FALSE;
return TRUE;
}
ULONG DisableProtectWriteCR0()
{
ULONG temp;
_asm push eax
_asm mov eax, CR0
_asm mov temp, eax
_asm and eax, 0xfffeffff
_asm mov CR0, eax
_asm pop eax
_asm cli
return temp;
}
UINT_PTR GetFuncAddrAndEATAddr(UINT_PTR ImageBase, PANSI_STRINGpFuncName, UINT_PTR nNewAddress, PUINT_PTR *outEatAddress)
{
ULONG ExportSize;
PULONG AddressOfNames;
PUSHORTAddressOfNameOrdinals;
PUINT_PTR AddressOfFunctions;
PIMAGE_EXPORT_DIRECTORY pExportVA;
LONG Low, High, Mid;
int nCompare;
ULONG nIndex;
UINT_PTR nRet;
pExportVA =(PIMAGE_EXPORT_DIRECTORY)RtlImageDirectoryEntryToData((PVOID)ImageBase,1, IMAGE_DIRECTORY_ENTRY_EXPORT,&ExportSize);
if( pExportVA == NULL )
return 0;
AddressOfNames =(PULONG)(pExportVA->AddressOfNames +ImageBase);
AddressO--fNameOrdinals =(PUSHORT)(pExportVA->AddressOfNameOrdinals +ImageBase);
Low = 0;
High = pExportVA->NumberOfNames -1;
do
{
Mid = ( Low + High ) / 2;
nCompare =strcmp(pFuncName->Buffer, (PCHAR)(ImageBase +AddressOfNames[Mid]) );
if ( nCompare <0 )
High = Mid -1;
else if ( nCompare> 0)
Low = Mid +1;
else
break;
} while ( High >= Low);
if ( Low > High)
return 0;
nIndex = (ULONG)AddressOfNameOrdinals[Mid];
if ( nIndex >=pExportVA->NumberOfFunctions)
return 0;
AddressOfFunctions =(PUINT_PTR)(pExportVA->AddressOfFunctions +ImageBase);
nRet = ImageBase +AddressOfFunctions[nIndex];
if ( nNewAddress )
{
OldCr0 =DisableProtectWriteCR0();
InterlockedExchange(&AddressOfFunctions[nIndex],nNewAddress - ImageBase);
ENABLE_WRITE_PROTECT(OldCr0);
}
*outEatAddress =&AddressOfFunctions[nIndex];
return nRet;
}
UINT_PTR GetFuncAddrAndEATAddrInNtoskrnl(PANSI_STRINGpFuncName)
{
if ( gImageBase == 0)
{
if( !GetMoudleBaseAndSize(NULL,&gImageBase, &gImageSize) )
{
gImageBase =0;
return0;
}
}
return GetFuncAddrAndEATAddr(gImageBase,pFuncName, 0, (PUINT_PTR *)&pFuncName);
}
NTSTATUS HookKiFastCallEntry()
{
ANSI_STRING FuncName;
UINT_PTR FuncAddress;
KSPIN_LOCK SpinLock;
KIRQL OldIrql;
ULONG tempOldCR0;
PULONG SSDTAddress;
RtlInitAnsiString(&FuncName,"ZwSetEvent");
FuncAddress =GetFuncAddrAndEATAddrInNtoskrnl(&FuncName);
if ( FuncAddress == 0 )
returnSTATUS_UNSUCCESSFUL;
gNtSetEventIndex = * (PULONG)((PUCHAR)FuncAddress+ 1);
KeInitializeSpinLock(&SpinLock);
OldIrql =KfAcquireSpinLock(&SpinLock);
_asm
{
push eax
push ebx
push edx
cli
mov eax, CR0
mov tempOldCR0, eax
and eax, 0xfffeffff
mov CR0, eax
}
SSDTAddress = gTableAddress[0].Base;
gOldNtSetEventAddress =(UINT_PTR)SSDTAddress[gNtSetEventIndex];
SSDTAddress[gNtSetEventIndex] =(ULONG)NewNtSetEvent;
_asm
{
mov eax, tempOldCR0
mov CR0, eax
sti
pop edx
pop ebx
pop eax
}
KfReleaseSpinLock(&SpinLock,OldIrql);
gMyValidHandle = (HANDLE)0x288C58F1;
ZwSetEvent(gMyValidHandle, NULL);
if ( gReturnAddress == 0)
{
if( gBufForJmp )
ExFreePool(gBufForJmp);
returnSTATUS_UNSUCCESSFUL;
}
if ( gFindedAddressEnd != 0)
{
KdPrint(("Hook KiFastCallokrn"));
return STATUS_SUCCESS;
}
return STATUS_SUCCESS;
}
VOID _declspec(naked) HookKiFastCallProcessForVista()
{
__asm
{
movedi, edi
pushfd
pushad
pushedi
pushedx
pusheax
callHookKiFastCallProcessReal
mov[esp+14h],eax//=edx 修改为处理后的函数地址
popad
popfd
subesp,ecx//被覆盖的两条指令
shrecx, 2
pushgFindedAddressEnd
retn// 跳回原函数
}
}
VOID _declspec(naked) HookKiFastCallProcessForNt()
{
__asm
{
movedi, edi
pushfd
pushad
pushedi
pushebx
pusheax
callHookKiFastCallProcessReal
mov[esp+10h],eax//=ebx 修改为处理后的函数地址
popad
popfd
subesp,ecx//被覆盖的两条指令
shrecx, 2
pushgFindedAddressEnd
retn// 跳回原函数
}
}
NTSTATUS NewNtSetEvent(HANDLE EventHandle, PULONGPreviousState)
{
PUCHAR HookFuncAddress;
KSPIN_LOCK SpinLock;
KIRQL OldIQL;
ULONG tempOldCR0;
PULONG SSDTAddress;
PUCHAR SearchCur;
BOOL bFinded = FALSE;
if ( EventHandle != gMyValidHandle ||ExGetPreviousMode() != KernelMode)
{
return((pFnSetEvent)gOldNtSetEventAddress)(EventHandle,PreviousState);
}
gBufForJmp =ExAllocatePoolWithTag(NonPagedPool,5, POOL_TAG);
if ( gBufForJmp == NULL)
{
return STATUS_SUCCESS;
}
*(PUCHAR)gBufForJmp = 0xE9;
//if ( *(PUSHORT)NtBuildNumber >=0x1770)
//HookFuncAddress =(PUCHAR)HookKiFastCallProcessForVista;
//else
HookFuncAddress =(PUCHAR)HookKiFastCallProcessForNt;
HookFuncAddress = (PUCHAR)(HookFuncAddress -(PUCHAR)gBufForJmp - 5);
*(PULONG)(gBufForJmp + 1) =(ULONG)HookFuncAddress;
KeInitializeSpinLock(&SpinLock);
OldIQL =KfAcquireSpinLock(&SpinLock);
_asm
{
push eax
push ecx
push edx
push esi
push edi
cli
mov eax, CR0
mov tempOldCR0, eax
and eax, 0xfffeffff
mov CR0, eax
}
//回复ZwSetEvent
SSDTAddress = gTableAddress[0].Base;
SSDTAddress[gNtSetEventIndex] =(ULONG)gOldNtSetEventAddress;
_asm
{
push eax
mov eax, [ebp + 4]
mov gReturnAddress, eax
pop eax
}
for ( SearchCur = gReturnAddress; SearchCur> gReturnAddress - 0x64; SearchCur--)
{
if (RtlEqualMemory(gForFindCode, SearchCur, 5) )
{
bFinded =TRUE;
break;
}
}
if ( bFinded )
{
gFindedAddressEnd = SearchCur +5;
gJmpFirst[0] = 0xE9;
*(PULONG)(gJmpFirst + 1) =gBufForJmp - gFindedAddressEnd;
RtlCopyMemory(SearchCur,gJmpFirst, 5);
}
_asm
{
mov eax, tempOldCR0
mov CR0, eax
sti
pop edi
pop esi
pop edx
pop ecx
pop eax
}
KfReleaseSpinLock(&SpinLock,OldIQL);
return STATUS_SUCCESS;
}
UINT_PTR HookKiFastCallProcessReal(ULONG ServiceIndex, UINT_PTRServiceFunAddr, PUINT_PTR ServiceTab)
{
return ServiceFunAddr;
}
//作用:根据索引调用过滤,并返回回调函数和回调函数参数以及过滤参数的个数
//只要一个过滤函数返回失败,则不能调用
NTSTATUS CallFilterFuncByIndex(ULONG nIndex, PULONGpParametersStartAddr, PULONG pCallBackArray, PULONGpUseForCallBackArray, PULONG pCallBackCount)
{
ULONG UseForCallBack;
ULONG CallBackCount = 0;
ULONG FilterFuncAddress;
NTSTATUS status;
ULONG CallBackTemp;
PFILTERFUN_RULE_TABLE pCur;
if ( nIndex >= 0x57)
return STATUS_SUCCESS;
if( gpFilterRuleTable == NULL)
{
if( pCallBackCount !=NULL)
*pCallBackCount=CallBackCount;
return STATUS_SUCCESS;
}
pCur = gpFilterRuleTable;
do
{
if(pCur->IsFilterFunFilledReady == 0)
continue;
if( ( FilterFuncAddress =pCur->FakeServiceRoutine[nIndex]) == 0 )
continue;
CallBackTemp = 0;
UseForCallBack = 0;
status =((pFnFilterFunc)FilterFuncAddress)(nIndex, pParametersStartAddr,&CallBackTemp,&UseForCallBack);
if( !NT_SUCCESS(status) )
returnstatus;
if( CallBackCount != 0&& pCallBackArray != 0&& CallBackCount <16)
{
CallBackCount++;
pCallBackArray[CallBackCount]= CallBackTemp;
pUseForCallBackArray[CallBackCount]= UseForCallBack;
}
pCur =pCur->pNext;
} while ( pCur != NULL);
if ( pCallBackCount == NULL)
return STATUS_SUCCESS;
*pCallBackCount = CallBackCount;
return STATUS_SUCCESS;
}
//被Hook的NtCreateKey函数
NTSTATUS HookNtCreateKey(
OUT PHANDLE KeyHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN ULONG TitleIndex,
IN PUNICODE_STRING ClassOPTIONAL,
IN ULONG CreateOptions,
OUT PULONG DispositionOPTIONAL
)
{
NTSTATUS status, status1;
ULONG CallBackCount;
ULONG Parameters[7];
ULONG CallBack[16];//其实最多也就16个
ULONG UseForCallBack[16]; //也是最多16个
ULONG FuncAddress;
ULONG i;
status = CallFilterFuncByIndex(0, Parameters,CallBack, UseForCallBack, &CallBackCount);
if( status == 0xC0000503)
return STATUS_SUCCESS;
if( !NT_SUCCESS(status))
return status;
if ( (gNtCreateKeyIndex &(ULONG)0x00001000) != 0) //shadow ssdt
{
if( MmIsAddressValid((PVOID)(gServiceFilterInfoTable->SavedShadowSSDTServiceAddress[gNtCreateKeyIndex &0xfff]) ) )
FuncAddress =gServiceFilterInfoTable->SavedShadowSSDTServiceAddress[gNtCreateKeyIndex & 0xfff];
else
FuncAddress =gShadowBase[gNtCreateKeyIndex & 0xfff];
}
else // ssdt
{
if( MmIsAddressValid((PVOID)(gServiceFilterInfoTable->SavedSSDTServiceAddress[gNtCreateKeyIndex ]) ) )
FuncAddress =gServiceFilterInfoTable->SavedSSDTServiceAddress[gNtCreateKeyIndex ];
else
FuncAddress =gTableBase[gNtCreateKeyIndex];
}
status =((pFnNtCreateKey)FuncAddress)(KeyHandle, DesiredAccess,ObjectAttributes,TitleIndex,Class,CreateOptions,Disposition);
for ( i = 0; i < CallBackCount;i++)
{
status1 =((pFnCallBackFunc)(CallBack[i]))(0, Parameters, status,UseForCallBack[i]);
if ( !NT_SUCCESS(status1))
returnstatus1;
}
return status;
}