想写这个程序主要是因为看了KSSD的一篇帖子,http://bbs.pediy.com/showthread.php?t=108378
讲 的是360保险箱保护游戏账号的原理,实际上就是对各种请求的拦截。这个帖子是大约6年前的了,我简单的看了一下现在的360保险箱应该不再采用这种方法 了,不再去HOOK KiFastCallEntry了,而且多增加了几个事件通知回调。这里主要是跟着那篇帖子作者的分析,来自己实现一个360游戏保险箱。
这里主要的思路就是HOOK住系统服务的分发,这已经不是什么新鲜的手法了。比方说,很多外挂作者都使用了内核重载来突破游戏保护的重重HOOK,内核重载也是劫持KiFastCallEntry来实现劫持服务分发的。这篇文章没有用什么前沿的技术,这里只是做一个练习。
基本流程是
1.应用层:
负责安装驱动模块并与驱动通信,由用户选择是否要放行指定操作
2.内核层:
(1)设置SSDT HOOK并调用HOOK 函数,进行栈回溯获取KiFastCallEntry()基址
(2)利用KiFastCallEntry()基址暴力搜索找到HOOK点位置并设置Inline Hook
(3)判断服务请求是否合法,合法则放行,不合法则传递消息给用户层,由用户决定是否放行
其实以上三步就是360保险箱的做法,程序里的有些内容因为不知道该怎么写,所以直接由那篇帖子的汇编分析逆写出来了。
1 #include "ntddk.h" 2 #include <ntdef.h> 3 4 #define NtSetEventID 219 5 6 typedef struct ServiceDescriptorEntry { 7 unsigned int *ServiceTableBase; 8 unsigned int *ServiceCounterTableBase; 9 unsigned int NumberOfServices; 10 unsigned char *ParamTableBase; 11 } ServiceDescriptorTableEntry_t, *PServiceDescriptorTableEntry_t; 12 13 __declspec(dllimport) ServiceDescriptorTableEntry_t KeServiceDescriptorTable; 14 15 NTSTATUS ZwSetEvent(__in HANDLE EventHandle,__out_opt PLONG PreviousState); 16 17 HANDLE HandleTemp = (HANDLE)0x288C58F1; 18 ULONG NtSetEventAddress; 19 ULONG KiFastCallEntryAddress; 20 ULONG TheHookAddress; 21 ULONG YesOrNo=0; 22 ULONG AddressOffset = 0; 23 ULONG TempDword; 24 ULONG ProcessPID = 0; 25 ULONG pid, DispatchAddress, TempBufferCopy; 26 PULONG DwordAddress = 0; 27 INT8 i; 28 INT8 *PbyteAddress; 29 KSPIN_LOCK MySpinLock1; 30 KSPIN_LOCK MySpinLock2; 31 KSPIN_LOCK MySpinLock3; 32 KIRQL TempKirql1; 33 KIRQL TempKirql2; 34 //设置SSDT HOOK 用来栈回溯得到KiFastCallEntry地址 35 NTSTATUS HookSSDT(PVOID FuncAdress) 36 { 37 ULONG OutTemp = 0; 38 NtSetEventAddress = (ULONG)KeServiceDescriptorTable.ServiceTableBase[NtSetEventID]; 39 KeInitializeSpinLock(&MySpinLock1); 40 KeAcquireSpinLock(&MySpinLock1,&TempKirql1); 41 _asm { 42 cli 43 push eax 44 mov eax, cr0 45 and eax, not 10000h 46 mov cr0, eax 47 pop eax 48 } 49 KeServiceDescriptorTable.ServiceTableBase[NtSetEventID] = (ULONG)FuncAdress; 50 __asm { 51 push eax 52 mov eax, cr0 53 or eax, 10000h 54 mov cr0, eax 55 pop eax 56 sti 57 } 58 KeReleaseSpinLock(&MySpinLock1,&TempKirql1); 59 ZwSetEvent(HandleTemp, 60 &OutTemp); 61 return STATUS_SUCCESS; 62 } 63 //解除SSDT HOOK 64 void UnhookSSDTHook() 65 { 66 KeInitializeSpinLock(&MySpinLock2); 67 KeAcquireSpinLock(&MySpinLock2,&TempKirql1); 68 _asm { 69 cli 70 push eax 71 mov eax, cr0 72 and eax, not 10000h 73 mov cr0, eax 74 pop eax 75 }; 76 KeServiceDescriptorTable.ServiceTableBase[NtSetEventID] = NtSetEventAddress; 77 78 _asm { 79 push eax 80 mov eax, cr0 81 or eax, 10000h 82 mov cr0, eax 83 pop eax 84 sti 85 }; 86 KeReleaseSpinLock(&MySpinLock2,&TempKirql1); 87 return; 88 } 89 ULONG TheDispatchFunc(ULONG arg1, ULONG arg2, ULONG arg3) 90 { 91 pid = (ULONG)PsGetCurrentProcessId(); 92 if (arg1 > 450) 93 { 94 return arg2; 95 } 96 //说明是SSDT服务分发 97 if (arg3== (ULONG)KeServiceDescriptorTable.ServiceTableBase) 98 { 99 //拦截122和257号调用 100 if (arg1==122||arg1==257) 101 { 102 103 { 104 return arg2; 105 } 106 } 107 else 108 { 109 return arg2; 110 } 111 } 112 return arg2; 113 } 114 //被挂载在KiFastCallEntry中(作为一个中转函数) 115 __declspec(naked) void InlineFunc() 116 { 117 _asm { 118 pushad 119 pushfd 120 121 push edi//服务表基址 122 push ebx//服务地址 123 push eax//服务序号 124 call TheDispatchFunc 125 mov DispatchAddress,eax 126 127 popfd 128 popad 129 //补全被覆盖的函数 130 mov ebx,DispatchAddress 131 SUB ESP, ECX 132 SHR ECX, 02 133 134 jmp TempBufferCopy 135 }; 136 137 } 138 //被挂载在SSDT的函数,需判断伪句柄 139 //并且要进行Inline HOOK 140 __declspec(naked) void SSDTFunc() 141 { 142 _asm { 143 push eax 144 mov eax, [esp + 8] 145 mov TempDword, eax 146 pop eax 147 } 148 149 if (TempDword == HandleTemp) 150 { 151 _asm { 152 push eax 153 mov eax, [esp + 4] 154 mov KiFastCallEntryAddress, eax 155 mov TempBufferCopy,eax 156 pop eax 157 }; 158 UnhookSSDTHook(); 159 } 160 else 161 { 162 _asm { 163 jmp NtSetEventAddress 164 }; 165 } 166 for (i = 0; i < 200; i++) 167 { 168 169 if (*((PULONG)KiFastCallEntryAddress)==0xe9c1e12b) 170 { 171 TheHookAddress = KiFastCallEntryAddress; 172 YesOrNo = 1; 173 break; 174 } 175 KiFastCallEntryAddress--; 176 } 177 if (YesOrNo) 178 { 179 AddressOffset = (ULONG)InlineFunc - 5 - (ULONG)TheHookAddress; 180 PbyteAddress = (INT8 *)TheHookAddress; 181 *PbyteAddress = 0xe9; 182 DwordAddress = (PULONG)((ULONG)TheHookAddress + 1); 183 *DwordAddress = AddressOffset; 184 } 185 _asm{retn 0x8 } 186 } 187 NTSTATUS UnloadFunc(PDRIVER_OBJECT MyDriver, PUNICODE_STRING RegPath) 188 { 189 //清理必要资源 190 return STATUS_SUCCESS; 191 } 192 NTSTATUS DriverEntry(PDRIVER_OBJECT MyDriver, PUNICODE_STRING RegPath) 193 { 194 NTSTATUS Status = 0; 195 MyDriver->DriverUnload = UnloadFunc; 196 Status = HookSSDT((PVOID)SSDTFunc); 197 if (!NT_SUCCESS(Status)) 198 { 199 return 1; 200 } 201 return STATUS_SUCCESS; 202 }
时间: 2024-11-05 14:41:57