代码:
#include <NTDDK.h> //----------------置全局变量+初始化.初始化是个好习惯.虽然我反汇编的时候发现编译器会帮你做这件事--------- ULONG JmpTest=0; UCHAR TestByte[5]={0x00,0x00,0x00,0x00,0x00}; ULONG retAddrIoCF_Xp=0; //---------------- //----------------下面是系统信息类.偷懒复制过来的.实际上只SystemModuleInformation再用--------- typedef enum _SYSTEM_INFORMATION_CLASS { SystemBasicInformation, // 0 Y N SystemProcessorInformation, // 1 Y N SystemPerformanceInformation, // 2 Y N SystemTimeOfDayInformation, // 3 Y N SystemNotImplemented1, // 4 Y N SystemProcessesAndThreadsInformation, // 5 Y N SystemCallCounts, // 6 Y N SystemConfigurationInformation, // 7 Y N SystemProcessorTimes, // 8 Y N SystemGlobalFlag, // 9 Y Y SystemNotImplemented2, // 10 Y N SystemModuleInformation, // 11 Y N SystemLockInformation, // 12 Y N SystemNotImplemented3, // 13 Y N SystemNotImplemented4, // 14 Y N SystemNotImplemented5, // 15 Y N SystemHandleInformation, // 16 Y N SystemObjectInformation, // 17 Y N SystemPagefileInformation, // 18 Y N SystemInstructionEmulationCounts, // 19 Y N SystemInvalidInfoClass1, // 20 SystemCacheInformation, // 21 Y Y SystemPoolTagInformation, // 22 Y N SystemProcessorStatistics, // 23 Y N SystemDpcInformation, // 24 Y Y SystemNotImplemented6, // 25 Y N SystemLoadImage, // 26 N Y SystemUnloadImage, // 27 N Y SystemTimeAdjustment, // 28 Y Y SystemNotImplemented7, // 29 Y N SystemNotImplemented8, // 30 Y N SystemNotImplemented9, // 31 Y N SystemCrashDumpInformation, // 32 Y N SystemExceptionInformation, // 33 Y N SystemCrashDumpStateInformation, // 34 Y Y/N SystemKernelDebuggerInformation, // 35 Y N SystemContextSwitchInformation, // 36 Y N SystemRegistryQuotaInformation, // 37 Y Y SystemLoadAndCallImage, // 38 N Y SystemPrioritySeparation, // 39 N Y SystemNotImplemented10, // 40 Y N SystemNotImplemented11, // 41 Y N SystemInvalidInfoClass2, // 42 SystemInvalidInfoClass3, // 43 SystemTimeZoneInformation, // 44 Y N SystemLookasideInformation, // 45 Y N SystemSetTimeSlipEvent, // 46 N Y SystemCreateSession, // 47 N Y SystemDeleteSession, // 48 N Y SystemInvalidInfoClass4, // 49 SystemRangeStartInformation, // 50 Y N SystemVerifierInformation, // 51 Y Y SystemAddVerifier, // 52 N Y SystemSessionProcessesInformation // 53 Y N } SYSTEM_INFORMATION_CLASS; typedef struct _SYSTEM_MODULE_INFORMATION { // Information Class 11 ULONG Reserved[2]; PVOID Base; ULONG Size; ULONG Flags; USHORT Index; USHORT Unknown; USHORT LoadCount; USHORT ModuleNameOffset; CHAR ImageName[256]; } SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION; //---------------------Api申明--------- PVOID GetUndocumentFunctionAdress(); NTSYSAPI NTSTATUS NTAPI ZwQuerySystemInformation( //这个函数使用起来十分繁琐.但是功能强大 IN SYSTEM_INFORMATION_CLASS SystemInformationClass, IN OUT PVOID SystemInformation, IN ULONG SystemInformationLength, OUT PULONG ReturnLength OPTIONAL ); //---------------------开关内存读写保护-------- VOID WPOFF(VOID) { __asm { cli mov eax,cr0 and eax,not 10000h mov cr0,eax } } VOID WPON(VOID) { __asm { mov eax,cr0 or eax,10000h mov cr0,eax sti } } //------------------获取未知函数地址 PVOID GetUndocumentFunctionAdress() { ULONG size,index; PULONG buf; ULONG i; PSYSTEM_MODULE_INFORMATION module; PVOID driverAddress=0; ULONG ntosknlBase; ULONG ntosknlEndAddr; ULONG curAddr; NTSTATUS status; ULONG code1_IoF=0x5d89db33,code2_IoF=0x1c758be0,code3_IoF=0x8903e683,code4_IoF=0xa164d475; ZwQuerySystemInformation(SystemModuleInformation,&size, 0, &size); //内存 if(NULL==(buf = (PULONG)ExAllocatePool(PagedPool, size))) { DbgPrint("failed alloc memory failed \n"); return 0; } status=ZwQuerySystemInformation(SystemModuleInformation,buf, size , 0); //请求 if(!NT_SUCCESS( status )) { DbgPrint("failed query\n"); return 0; } module = (PSYSTEM_MODULE_INFORMATION)(( PULONG )buf + 1); ntosknlEndAddr=(ULONG)module->Base+(ULONG)module->Size; ntosknlBase=(ULONG)module->Base; curAddr=ntosknlBase; ExFreePool(buf); for (i=curAddr;i<=ntosknlEndAddr;i++) //在ntoskn内存范围内搜索.由于函数类型Break就不+了 { if ((*((ULONG *)i)==code1_IoF)&&(*((ULONG *)(i+4))==code2_IoF)&&(*((ULONG *)(i+8))==code3_IoF)&&(*((ULONG *)(i+12))==code4_IoF)) { retAddrIoCF_Xp = i; JmpTest = i + 0x5; DbgPrint("."); DbgPrint("[retAddrIoCF_Xp] %x\n",retAddrIoCF_Xp); DbgPrint("[JmpTest] %x\n",JmpTest); } } return 0; } //--------------------------自定义函数-------------------- NTSTATUS _declspec(naked) MyKnowCall() //这里一定要naked.不然函数多3句经典代码.参数呢?我偷懒了 { __asm { xor ebx, ebx //这2句是原函数被HOOK地方的代码 mov dword ptr [ebp-0x20], ebx jmp JmpTest //调回到后面继续执行 } } //-------------------开始HOOK----------- VOID StartInLineHook() { ULONG JmpOffsetTest; UCHAR JmpCode[5]={0xe9,0x00,0x00,0x00,0x00}; //jmp UCHAR JmpCodeTest[5]={0xe9,0x00,0x00,0x00,0x00}; //----------------- RtlCopyMemory (TestByte, (PVOID)retAddrIoCF_Xp, 5); //备份原先没HOOK的时候该地址的代码 DbgPrint("[TestByte] 0x%x\n",TestByte); //---------------------新函数与老函数的偏移差 JmpOffsetTest=(PCHAR)MyKnowCall-(PCHAR)retAddrIoCF_Xp-0x5; //因为自己的驱动是后加载的,属于高位地址。所以放在前面减去老地址, -5是跳转所占的5个字节。得到偏移差 DbgPrint("[JmpOffsetTest]:%08X",JmpOffsetTest); DbgPrint("[MyKnowCall]:%08X",MyKnowCall); //----------------- RtlCopyMemory(JmpCodeTest+1,&JmpOffsetTest,4); //这是构成一条跳转语句 DbgPrint("[JmpCodeTest]:%08X",JmpCodeTest); DbgPrint("."); DbgPrint("[retAddrIoCF_Xp]:%08X",retAddrIoCF_Xp); DbgPrint("[JmpCodeTest]:%08X",(PVOID)JmpCodeTest); //ULONG.UCHAR.PVOID之类的+不+都不影响。同上语句 //----------------------------- //-----------开始HOOK-------- WPOFF(); //内存不可直接操作。先关保护,和提升IRQL级别一个道理、 RtlCopyMemory((PVOID)retAddrIoCF_Xp,(PVOID)JmpCodeTest,5); WPON(); //完了记得开启保护、内核不是R3;不开保护容易BSOD。 } //-----------------------卸载入口-------------- VOID DriverUnload (PDRIVER_OBJECT pDriverObject) //后面这个参数是用来卸载调用的 { WPOFF(); RtlCopyMemory((PVOID)retAddrIoCF_Xp,TestByte,5); //把原先备份的地址代码复制到我们HOOK的地址、就是还原、 WPON(); DbgPrint("InLine HOOK已恢复!!!\n驱动服务已卸载\n"); } //-------------------------驱动入口----------------- NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject,PUNICODE_STRING pRegistryPath) //其实这个代码只需要运行一次 { GetUndocumentFunctionAdress(); //获取未知函数地址.通过特征码搜索的、和aob一个道理 StartInLineHook(); //开始运行HOOK函数 pDriverObject->DriverUnload =DriverUnload; //记得给卸载派发例程 return STATUS_SUCCESS; //这里就直接返回成功了。 }