码迷,mamicode.com
首页 > 其他好文 > 详细

通过构造系统服务分发实现拦截&过滤 (仿360游戏保险箱)

时间:2016-03-03 01:31:47      阅读:285      评论:0      收藏:0      [点我收藏+]

标签:

想写这个程序主要是因为看了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 }

 

通过构造系统服务分发实现拦截&过滤 (仿360游戏保险箱)

标签:

原文地址:http://www.cnblogs.com/Ox9A82/p/5237069.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!