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__
|