写一个SSDTShadow Hook
来源:互联网 发布:pigalle红磨坊 知乎 编辑:程序博客网 时间:2024/05/24 05:38
http://hi.baidu.com/ejoywx/item/b9149cf75d1f7f1ce2e3bdf4
我本菜鸟,班门弄斧之辈,大牛不要笑话。
以下程序名称为BugHook,是在Win7sp1X64上对SSDTShadow::NtUserFindWindowEx进行Hook:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
#include "BugHook.h"
#pragma intrinsic(__readcr0)
#pragma intrinsic(__writecr0)
#pragma intrinsic(_disable)
#pragma intrinsic(_enable)
#pragma intrinsic(__readmsr)
extern
PUSHORT
NtBuildNumber;
static
PFN_NTUSERFINDWINDOWEX g_NtUserFindWindowEx;
KIRQL FORCEINLINE WPOFF( )
{
KIRQL Irql = KeRaiseIrqlToDpcLevel();
UINT_PTR
cr0 = __readcr0();
cr0 &= ~0x10000;
__writecr0( cr0 );
_disable();
return
Irql;
}
VOID
FORCEINLINE WPON( KIRQL Irql )
{
UINT_PTR
cr0 = __readcr0();
cr0 |= 0x10000;
_enable();
__writecr0( cr0 );
KeLowerIrql( Irql );
}
PVOID
SearchHookPoint(
PVOID
StartPoint,
PUCHAR
EndPoint )
{
PVOID
HookPoint= NULL;
PUCHAR
pCurPoint = (
PUCHAR
)StartPoint;
__try
{
while
( ++pCurPoint < (
PUCHAR
)EndPoint )
{
if
( ( (
ULONG_PTR
)pCurPoint %
sizeof
(
PVOID
) ) == 0 &&
//考虑地址对齐
*(
PULONG_PTR
)(pCurPoint+0) == 0 &&
//期望搜索到当前(.text)节的尾部
*(
PULONG_PTR
)(pCurPoint+1) == 0 &&
*(
PULONG_PTR
)(pCurPoint+2) == 0 &&
*(
PULONG_PTR
)(pCurPoint+3) == 0
)
{
HookPoint = (
PVOID
)pCurPoint;
break
;
}
}
}
__except( EXCEPTION_EXECUTE_HANDLER )
{
}
return
HookPoint;
}
VOID
PatchHookPoint(
PVOID
HookPos,
PVOID
FakeNtFunc )
//perfect! Infact, do not do that!
{
KIRQL Irql;
UCHAR
jmp_code[] =
"\x48\xB8\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xE0"
;
//mov rax, xxx ; jmp rax
*(
PULONGLONG
)( jmp_code + 2 ) = (
ULONGLONG
)FakeNtFunc;
Irql = WPOFF();
RtlFillMemory( HookPos, 16, 0xCC );
RtlMoveMemory( HookPos, jmp_code, 12 );
WPON( Irql );
}
PEPROCESS LookupCsrssProcess( )
{
PEPROCESS CsrssProcess = NULL;
NTSTATUS Status ;
PEPROCESS Process;
ULONG
Index ;
for
( Index = 8; Index < 0x1000; Index += 4 )
{
Status = PsLookupProcessByProcessId( (
HANDLE
)Index, &Process );
if
( !NT_SUCCESS(Status) )
{
continue
;
}
if
( !_stricmp( PsGetProcessImageFileName(Process),
"csrss.exe"
) )
{
CsrssProcess = Process;
Index = 0x20000;
}
ObDereferenceObject( Process );
}
return
CsrssProcess;
}
ULONG_PTR
GetSSDTShadow64( )
{
/*
KiSystemServiceRepeat proc near
4C 8D 15 C7 20 23 00 lea r10, KeServiceDescriptorTable
4C 8D 1D 00 21 23 00 lea r11, KeServiceDescriptorTableShadow
F7 83 00 01 00 00 80 00 00 00 test dword ptr [rbx+100h], 80h
*/
PUCHAR
pStartSearchAddress = (
PUCHAR
)__readmsr(0xC0000082);
//得到KiSystemCall64
PUCHAR
pEndSearchAddress = (
PUCHAR
)( ((
ULONG_PTR
)pStartSearchAddress + PAGE_SIZE) & (~0x0FFF) );
PULONG
pFindCodeAddress = NULL;
ULONG_PTR
pSSDTShadow = 0;
while
( ++pStartSearchAddress < pEndSearchAddress )
{
if
( (*(
PULONG
)pStartSearchAddress & 0xFFFFFF00) == 0x83f70000 )
{
//-12得到KeServiceDescriptorTable;-5得到KeServiceDescriptorTableShadow
pFindCodeAddress = (
PULONG
)(pStartSearchAddress - 5);
pSSDTShadow = (
ULONG_PTR
)pFindCodeAddress +
( ( (*(
PULONG
)pFindCodeAddress) >> 24 ) + 7 ) +
//ae
(
ULONG_PTR
)( ( ( *(
PULONG
)(pFindCodeAddress + 1) ) & 0x0FFFF ) << 8 );
//id4c
break
;
}
}
return
pSSDTShadow;
}
ULONG
FORCEINLINE GetSSDTEntry(
PULONG
KiServiceTable,
PVOID
FuncAddress )
{
return
( (
ULONG
)((
ULONGLONG
)FuncAddress-(
ULONGLONG
)KiServiceTable) ) << 4;
}
ULONG_PTR
FORCEINLINE GetSSDTFunc(
PULONG
KiServiceTable,
ULONG
ServiceId )
{
return
(
LONGLONG
)( KiServiceTable[ServiceId] >> 4 )
+ (
ULONGLONG
)KiServiceTable;
}
NTSTATUS LoadSSDTShadowHook( IN
ULONG
ServiceId, IN
PVOID
NewFunc, OUT
PVOID
* OldFunc )
{
PKSERVICE_TABLE_DESCRIPTOR SSDTShadow;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
ULONG
SsdtEntry;
PULONG
W32pServiceTable;
PVOID
HookPoint;
PEPROCESS CsrssProcess;
KAPC_STATE ApcState;
KIRQL Irql;
BOOLEAN
bNeedDetach = FALSE;
do
{
if
( (
LONG
)ServiceId < 0x1000 )
{
break
;
}
ServiceId &= 0x0FFF;
SSDTShadow = (PKSERVICE_TABLE_DESCRIPTOR)GetSSDTShadow64();
if
( !SSDTShadow )
{
break
;
}
W32pServiceTable = SSDTShadow[1].Base;
CsrssProcess = LookupCsrssProcess( );
if
( !CsrssProcess )
{
break
;
}
if
( PsGetCurrentProcess() != CsrssProcess )
{
KeStackAttachProcess( CsrssProcess, &ApcState );
bNeedDetach = TRUE;
}
HookPoint = SearchHookPoint( (
PVOID
)W32pServiceTable, (
PUCHAR
)W32pServiceTable + 0x4000000 );
if
( !HookPoint )
{
break
;
}
if
( OldFunc )
{
*OldFunc = (
PVOID
)GetSSDTFunc( W32pServiceTable, ServiceId );
PatchHookPoint( HookPoint, NewFunc );
SsdtEntry = GetSSDTEntry( W32pServiceTable, HookPoint );
SsdtEntry &= 0xFFFFFFF0;
//perfect!!!
SsdtEntry += W32pServiceTable[ServiceId] & 0x0F;
}
else
{
SsdtEntry = GetSSDTEntry( W32pServiceTable, NewFunc );
SsdtEntry &= 0xFFFFFFF0;
SsdtEntry += W32pServiceTable[ServiceId] & 0x0F;
}
Irql = WPOFF();
W32pServiceTable[ServiceId] = SsdtEntry;
WPON( Irql );
Status = STATUS_SUCCESS;
}
while
( FALSE );
if
( bNeedDetach )
{
KeUnstackDetachProcess( &ApcState );
}
return
Status;
}
NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath )
{
NTSTATUS Status = STATUS_NOT_SUPPORTED;
if
( *NtBuildNumber == 7601 &&
sizeof
(
PVOID
) == 8 )
{
DriverObject->DriverUnload = BugHookUnload;
Status = LoadSSDTShadowHook( 0x106E, (
PVOID
)ProxyNtUserFindWindowEx, (
PVOID
*)&g_NtUserFindWindowEx );
}
KdPrintEx(( DPFLTR_IHVDRIVER_ID,DPFLTR_ERROR_LEVEL,
"[BugHook] DriverEntry is called with Status 0x%08X \n"
, Status ));
return
Status;
}
VOID
BugHookUnload( IN PDRIVER_OBJECT DriverObject )
{
LoadSSDTShadowHook( 0x106E, (
PVOID
)g_NtUserFindWindowEx, NULL );
KdPrintEx(( DPFLTR_IHVDRIVER_ID,DPFLTR_ERROR_LEVEL,
"[BugHook] BugHookUnload is called.\n"
));
}
HWND
NTAPI
ProxyNtUserFindWindowEx(
IN
HWND
hwndParent,
IN
HWND
hwndChild,
IN PUNICODE_STRING pstrClassName,
IN PUNICODE_STRING pstrWindowName,
DWORD
dwType
)
{
if
( ExGetPreviousMode() == UserMode )
{
UNICODE_STRING CapturedClassName = {0};
UNICODE_STRING CapturedWindowName = {0};
WCHAR
NameBuffer[260] = {0};
WCHAR
* pNameBuf = NameBuffer;
__try
{
if
( pstrClassName )
{
ProbeAndReadUnicodeStringEx( &CapturedClassName, pstrClassName );
ProbeForRead(
CapturedClassName.Buffer,
CapturedClassName.Length,
sizeof
(
WCHAR
)
);
RtlMoveMemory( pNameBuf, CapturedClassName.Buffer, CapturedClassName.Length );
//未判断缓冲区长度,巨大的安全隐患
pNameBuf += CapturedClassName.Length;
}
if
( pstrWindowName )
{
ProbeAndReadUnicodeStringEx( &CapturedWindowName, pstrWindowName );
ProbeForRead(
CapturedWindowName.Buffer,
CapturedWindowName.Length,
sizeof
(
WCHAR
)
);
RtlMoveMemory( pNameBuf, CapturedWindowName.Buffer, CapturedWindowName.Length );
//未判断缓冲区长度,巨大的安全隐患
pNameBuf += CapturedWindowName.Length;
}
if
( pNameBuf > NameBuffer )
{
//
//Here, you can do something like analyzing NameBuffer.
//
KdPrintEx(( DPFLTR_IHVDRIVER_ID,DPFLTR_ERROR_LEVEL,
"[BugHook] NtUserFindWindowEx : %ws\n"
, NameBuffer ));
}
}
__except( EXCEPTION_EXECUTE_HANDLER )
{
/* KdPrintEx(( DPFLTR_IHVDRIVER_ID,DPFLTR_ERROR_LEVEL,
"[BugHook] Catch a bug with status : %08X\n",
GetExceptionCode() ) ); */
}
}
return
g_NtUserFindWindowEx( hwndParent, hwndChild, pstrClassName, pstrWindowName, dwType ) ;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#ifndef __BUGHHOK_H__
#define __BUGHHOK_H__
#
include
<ntifs.h>
#
include
<ntimage.h>
DRIVER_UNLOAD BugHookUnload;
DRIVER_INITIALIZE DriverEntry;
typedef HANDLE HWND;
typedef ULONG DWORD;
typedef HWND ( NTAPI *PFN_NTUSERFINDWINDOWEX)( \
HWND hwndParent, \
HWND hwndChildAfter, \
PUNICODE_STRING ucClassName, \
PUNICODE_STRING ucWindowName, \
DWORD dwType \
) ;
HWND NTAPI
ProxyNtUserFindWindowEx(
HWND hwndParent,
HWND hwndChildAfter,
PUNICODE_STRING ucClassName,
PUNICODE_STRING ucWindowName,
DWORD dwType
) ;
//---------------------------------------------------------------------------------------
//copy from wrk
typedef struct _KSERVICE_TABLE_DESCRIPTOR {
PULONG Base;
PULONG Count;
ULONG Limit;
PUCHAR
Number
;
} KSERVICE_TABLE_DESCRIPTOR, *PKSERVICE_TABLE_DESCRIPTOR;
NTKERNELAPI
UCHAR *
PsGetProcessImageFileName(
__in PEPROCESS Process
);
#
if
!defined(__cplusplus)
#define ProbeAndReadUnicodeString(Source) \
(((Source) >= (UNICODE_STRING *
const
)MM_USER_PROBE_ADDRESS) ? \
(*(volatile UNICODE_STRING *
const
)MM_USER_PROBE_ADDRESS) : (*(volatile UNICODE_STRING *)(Source)))
#endif
#
if
defined(_AMD64_)
FORCEINLINE
VOID
ProbeAndReadUnicodeStringEx (
OUT PUNICODE_STRING Destination,
IN PUNICODE_STRING Source
)
{
if
(Source >= (UNICODE_STRING *
const
)MM_USER_PROBE_ADDRESS) {
Source = (UNICODE_STRING *
const
)MM_USER_PROBE_ADDRESS;
}
_ReadWriteBarrier();
*Destination = *((volatile UNICODE_STRING *)Source);
return
;
}
#
else
#define ProbeAndReadUnicodeStringEx(Dst, Src) *(Dst) = ProbeAndReadUnicodeString(Src)
#endif
//---------------------------------------------------------------------------------------
#endif
//__BUGHHOK_H__
- 写一个SSDTShadow Hook
- 普及X64 ssdtshadow inline HOOK
- 普及X64 ssdtshadow inline HOOK
- hook api的一个自己写的例子
- Delphi写的一个函数的Hook类
- 自己写的一个hook库 比较适合做inline hook
- 如何Hook一个函数
- HOOK一个C函数
- 让我们hook一个库函数
- HOOK API的一个类
- 一个 Hook Api 的源代码
- 一个简单的hook 新手入门
- netfilter:开发一个hook函数
- 偶写的API Hook类
- 用 lua 写 VisualSvn Server 的 hook
- python写 svn hook脚本问题总结
- 发一个支持任意地点hook的类(包含驱动hook和应用层hook)
- 一个简单的HOOK API的DLL
- iOS7适配之设计篇
- 【Java工程师之路】[2-1.9]数据库视图介绍
- 【笔记】安卓不支持JSON包
- hbase phoenix批量插入数据例子
- 解决eclipse老是检测不到手机设备方法
- 写一个SSDTShadow Hook
- Android PopupWindow 与 软键盘 的遮挡问题解决
- sql语句的执行机制
- EasyUi_学习之路_06
- 2013年10月15日星期二——java web 环境搭建(MySQL)
- 百度搜索引擎
- 1.1 《硬啃设计模式》 第1章 大话设计模式
- xcode:关于Other Linker Flags
- LIRe提供的6种图像特征描述方法的评测