看了几个例子,一般都是在ExAllocatePoolWithTag这里挂钩啊,根据MemoryTag来判断,以后再发现发现有没有更精准的挂钩位置
#include <ntddk.h> #include <windef.h> #include <stdio.h> #include <string.h> #include "MmLoadSystemImage.h" #define pwszModuleName L"ntoskrnl.exe" //这里只考虑单核的情况 #define ObjectNameInformation 1 UCHAR oldcode[5]={0}; UCHAR jmpcode[5]={0xE9,0x00,0x00,0x00,0x00}; ULONG g_ntoskrnl_addr=0; ULONG g_ntoskrnl_size=0; ULONG oldExAllocatePoolWithTagaddr=0; ULONG Address_MmLoadSystemImage=0;//通过栈回溯(技术难点)得到MmLoadSystemImage函数的地址 /* 这里说明一下原先通过东方微点的Mp110003的驱动是通过Hook KeWaitForSingleObject, 然后通过栈回溯来找到MmLoadSystemImage的地址,但是通过我跟踪堆栈调用, 发现要经过很多次KeWaitForSingleObject调用,才会进入到 KeWaitForSingleObject MmLoadSystemImage NtSetSystemInformation nt!KiFastCallEntry nt!ZwSetSystemInformation 反正是猥琐,我就更猥琐,大米兄就是这么干的,调用流程中来找到MmLoadSystemImage地址,调用过程如下: ExAllocatePoolWithTag MmLoadSystemImage NtSetSystemInformation nt!KiFastCallEntry nt!ZwSetSystemInformation 因此我直接HOOK ExAllocatePoolWithTag来进行栈回溯 */ __declspec(naked) PVOID fake_ExAllocatePoolWithTag( IN POOL_TYPE PoolType, IN SIZE_T NumberOfBytes, IN ULONG Tag) { ULONG *PEBP; _asm{ mov edi,edi push ebp mov ebp,esp mov eax,[ebp+0xc] //参数是NumberOfBytes cmp eax,0x100 jnz end mov eax,[ebp+0x10] //第三个参数Tag cmp eax,0x6E4C6D4D //标志为"nLmM",也就是MmLoadSystemImage装载的镜像标志 jnz end mov eax,[ebp] //堆栈回溯的原理 mov eax,[eax+4] push eax //上一个函数的地址 call StackTrace_for_ExAllocatePoolWithTag end: mov eax,oldExAllocatePoolWithTagaddr add eax,5 jmp eax } } //通过栈回溯找到 ULONG StackTrace_for_ExAllocatePoolWithTag(ULONG RetAddress) { ULONG CallAddress=0; ULONG JmpOffset=0; if (RetAddress) { CallAddress=(ULONG)RetAddress- 5 ;//Ret --->call Address //跳转的偏移量 JmpOffset=*(ULONG*)((PUCHAR)CallAddress+1); //(PUCHAR)CallAddress+1--->指针CallAddress往后走一位,(PULONG)CallAddress+1,指针CallAddress往后走(sizeof(ULONG)=4)字节 //MmLoadSystemImage函数的地址 Address_MmLoadSystemImage=(ULONG)CallAddress + 5 +JmpOffset; KdPrint(("MmLoadSystemImage Address=0x%x/n",Address_MmLoadSystemImage)); //加入判定如果ntoskrnl.Base<Address_MmLoadSystemImage<ntoskrnl.Base+size,则说明可以进行inlineHook_MmLoadSystemImage() if (Address_MmLoadSystemImage>g_ntoskrnl_addr&&Address_MmLoadSystemImage<(g_ntoskrnl_addr+g_ntoskrnl_size)) { unlineHook_ExAllocatePoolWithTag(); inlineHook_MmLoadSystemImage(); KdPrint(("inlineHook MmLoadSystemImage Success!")); } } return 0; } __declspec(naked) NTSTATUS OrigiMmLoadSystemImage( IN PUNICODE_STRING ImageFileName, IN PUNICODE_STRING NamePrefix OPTIONAL, IN PUNICODE_STRING LoadedBaseName OPTIONAL, IN ULONG LoadFlags, OUT PVOID *ImageHandle, OUT PVOID *ImageBaseAddress) { __asm{ push 174h mov eax,Address_MmLoadSystemImage add eax,5 jmp eax } } //拦截驱动的过程 NTSTATUS fake_MmLoadSystemImage( IN PUNICODE_STRING ImageFileName, IN PUNICODE_STRING NamePrefix OPTIONAL, IN PUNICODE_STRING LoadedBaseName OPTIONAL, IN ULONG LoadFlags, OUT PVOID *ImageHandle, OUT PVOID *ImageBaseAddress) { ANSI_STRING ImageName; RtlUnicodeStringToAnsiString(&ImageName,ImageFileName,TRUE); KdPrint(("MmLoadSystemImage LoadDriver :%s/n",ImageName.Buffer)); return OrigiMmLoadSystemImage(ImageFileName, NamePrefix, LoadFlags, LoadFlags, ImageHandle, ImageBaseAddress); } NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,IN PIRP Irp) { NTSTATUS status; PEPROCESS crsEProc; ANSI_STRING TestSysName; SYSTEM_LOAD_AND_CALL_IMAGE sysImage; DriverObject->DriverUnload=DriverUnload; status=PsLookupProcessByProcessId((ULONG)GetCsrPid(),&crsEProc); if (!NT_SUCCESS(status)) { KdPrint(("PsLookupProcessByProcessId() error/n")); return status; } //通过DriverObject->DriverSection获得加载驱动的模块 if (GetBase((ULONG)DriverObject)&&inlineHook_ExAllocatePoolWithTag()) { //下面是调用ZwSetSystemInformation来加载驱动,从而引发跳转到fake_ExAllocatePoolWithTag中,先依附进csrss.exe,再加载测试驱动 KeAttachProcess(crsEProc); //加载测试驱动; RtlInitAnsiString(&TestSysName,"//??//c://Hooksys.sys"); RtlAnsiStringToUnicodeString(&(sysImage.ModuleName),&TestSysName,TRUE); status= ZwSetSystemInformation(SystemExtendServiceTableInformation,&sysImage,sizeof(sysImage)); if (!NT_SUCCESS(status)) { KdPrint(("Driver STATUS=0X%x/n",status)); } KeDetachProcess(); } return STATUS_SUCCESS; } NTSTATUS DriverUnload(IN PDRIVER_OBJECT DriverObject ) { unlineHook_MmLoadSystemImage(); KdPrint(("DriverUnload!/n")); return STATUS_SUCCESS; } //得到模块的基址和映像大小 int GetBase(IN ULONG EntryAddress) { ULONG listHead; ULONG currentList; ULONG NameAddress; int reault=0; listHead=*(ULONG*)(EntryAddress+0x14); currentList=*(ULONG*)(listHead+0x4); //Blink if (currentList!=listHead) { while (1) { NameAddress=*(ULONG*)(currentList+0x030); if ((PCWSTR)NameAddress!=NULL) { KdPrint(("ModuleName=%ws/n",(PCWSTR)NameAddress)); } if(!_wcsicmp((PCWSTR)NameAddress,pwszModuleName)) { g_ntoskrnl_addr=*(ULONG*)(currentList+0x18); g_ntoskrnl_size=*(ULONG*)(currentList+0x20); KdPrint(("ntoskrnl.exe [base]=0x%X,[size]=0x%X/n",g_ntoskrnl_addr,g_ntoskrnl_size)); reault=1; break; } currentList=*(DWORD*)(currentList + 0x4);//下一个Blink if (currentList == listHead) { KdPrint(("链表查询结束!/n")); break; } } } return reault; } PVOID GetInfoTable(ULONG ATableType) { ULONG mSize=0x4000; PVOID mPtr=NULL; NTSTATUS status; do { mPtr=ExAllocatePool(PagedPool,mSize); memset(mPtr, 0, mSize); if (mPtr) { status = ZwQuerySystemInformation(ATableType,mPtr,mSize,NULL); }else return NULL; if (status == STATUS_INFO_LENGTH_MISMATCH) { ExFreePool(mPtr); mSize *=2; } } while(status == STATUS_INFO_LENGTH_MISMATCH); if (status == STATUS_SUCCESS) return mPtr; ExFreePool(mPtr); return NULL; } //得到csrss.exe的PID HANDLE GetCsrPid() { HANDLE Process,hObject; HANDLE CsrssId=(HANDLE)0; OBJECT_ATTRIBUTES obj; CLIENT_ID cid; UCHAR buff[0x100]; POBJECT_NAME_INFORMATION objName=(PVOID)&buff; PSYSTEM_HANDLE_INFORMATION_EX Handles; ULONG i; Handles=GetInfoTable(SystemHandleInformation); if (!Handles) return CsrssId; for (i=0;i<Handles->NumberOfHandles;i++) { if (Handles->Information[i].ObjectTypeNumber == 21) { InitializeObjectAttributes(&obj,NULL,OBJ_KERNEL_HANDLE,NULL,NULL); cid.UniqueProcess=(HANDLE)Handles->Information[i].ProcessId; cid.UniqueThread = 0; if (NT_SUCCESS(NtOpenProcess(&Process,PROCESS_DUP_HANDLE,&obj,&cid))) { if (NT_SUCCESS(ZwDuplicateObject(Process,(HANDLE)Handles->Information[i].Handle,NtCurrentProcess(),&hObject,0,0,DUPLICATE_SAME_ACCESS))) { if (NT_SUCCESS(ZwQueryObject(hObject, ObjectNameInformation, objName, 0x100, NULL))) { if (objName->Name.Buffer&& !wcsncmp(L"//Windows//ApiPort",objName->Name.Buffer,20)) { CsrssId=(HANDLE)Handles->Information[i].ProcessId; } } ZwClose(hObject); } ZwClose(Process); } } } ExFreePool(Handles); return CsrssId; } //inline Hook ExAllocatePoolWithTag BOOLEAN inlineHook_ExAllocatePoolWithTag() { KIRQL oldIrql; DWORD distance; UNICODE_STRING unamestr; BOOLEAN result; RtlInitUnicodeString(&unamestr,L"ExAllocatePoolWithTag"); oldExAllocatePoolWithTagaddr=(ULONG)MmGetSystemRoutineAddress(&unamestr); if (oldExAllocatePoolWithTagaddr) { //保存原来开始的5个字节 RtlCopyMemory(oldcode,(BYTE*)oldExAllocatePoolWithTagaddr,5); distance=(BYTE*)fake_ExAllocatePoolWithTag - (BYTE*)oldExAllocatePoolWithTagaddr -5; RtlCopyMemory(jmpcode+1,&distance,4); WPOff(); oldIrql=KeRaiseIrqlToDpcLevel(); RtlCopyMemory((BYTE*)oldExAllocatePoolWithTagaddr,jmpcode,5); KeLowerIrql(oldIrql); WPOn(); result=TRUE; } else result=FALSE; return result; } VOID unlineHook_ExAllocatePoolWithTag() { KIRQL oldIrql; WPOff(); oldIrql=KeRaiseIrqlToDpcLevel(); RtlCopyMemory((BYTE*)oldExAllocatePoolWithTagaddr,oldcode,5); KeLowerIrql(oldIrql); WPOn(); return; } BOOLEAN inlineHook_MmLoadSystemImage() { KIRQL oldIrql; DWORD distance; BOOLEAN result; if (Address_MmLoadSystemImage) { //保存原来开始的5个字节 RtlCopyMemory(oldcode,(BYTE*)Address_MmLoadSystemImage,5); distance=(BYTE*)fake_MmLoadSystemImage - Address_MmLoadSystemImage -5; RtlCopyMemory(jmpcode+1,&distance,4); WPOff(); oldIrql=KeRaiseIrqlToDpcLevel(); RtlCopyMemory((BYTE*)Address_MmLoadSystemImage,jmpcode,5); KeLowerIrql(oldIrql); WPOn(); result=TRUE; }else result=FALSE; return result; } VOID unlineHook_MmLoadSystemImage() { KIRQL oldIrql; WPOff(); oldIrql=KeRaiseIrqlToDpcLevel(); RtlCopyMemory((BYTE*)Address_MmLoadSystemImage,oldcode,5); KeLowerIrql(oldIrql); WPOn(); return; } VOID WPOn() { __asm { mov eax,cr0 or eax,0x10000 mov cr0,eax STI } } VOID WPOff() { __asm{ cli mov eax, cr0 and eax,not 0x10000 mov cr0,eax } }