下面是主要代码
01 |
DWORD gThreadsProcessOffset
=0x220; //
ETHREAD 在 EPROCESS偏移 |
02 |
/* |
03 |
04 |
+0x218
TopLevelIrp : Uint4B |
05 |
+0x21c
DeviceToVerify : Ptr32 _DEVICE_OBJECT |
06 |
+0x220
ThreadsProcess : Ptr32 _EPROCESS |
07 |
*/ |
08 |
09 |
ULONG ProcessNameOffset
= 0x174; //
进程对应的文件名 在 EPROCESS偏移 |
10 |
/* |
11 |
+0x170
Session : Ptr32 Void |
12 |
+0x174
ImageFileName : [16] UChar |
13 |
+0x184
JobLinks : _LIST_ENTRY |
14 |
*/ |
15 |
16 |
PProcessList
wLastItem = NULL; |
17 |
int BeTerminate
= 0; //1
表示线程必须要停止 3表示线程不是PENDING状态 0表示线程可以正常运行 |
18 |
19 |
void _stdcall
CollectProcess(PEPROCESS pEPROCESS) //
搜集EPROCESS |
20 |
{ |
21 |
if (!IsAdded(wLastItem,
pEPROCESS)) AddItem(&wLastItem, pEPROCESS); |
22 |
return ; |
23 |
} |
24 |
25 |
void __stdcall
ThreadCollect( PUCHAR pEthread) //根据ETHREAD得到EPROCESS
并调用CollectProcess来搜集 |
26 |
{ |
27 |
PEPROCESS
pEprocess = *(PEPROCESS *)(pEthread + gThreadsProcessOffset); |
28 |
if (pEprocess)
CollectProcess(pEprocess); |
29 |
return ; |
30 |
} |
31 |
32 |
33 |
DWORD outPEthread
= 0; |
34 |
void __stdcall
ProcessData( DWORD pInEthread, DWORD pOutEthread) |
35 |
{ |
36 |
DWORD pid,
eprocess; |
37 |
char *
pname; |
38 |
if (MmIsAddressValid( PVOID (pInEthread+0x220))
) |
1 |
//
这里以及下面要判断是不是一个真正的 Ethread 结构体 有时好像调用SwapContext传进来的不是 |
001 |
//Ethread
结构体 然后就蓝屏 具体没有深究 加个判断就不蓝了~ |
002 |
{ |
003 |
eprocess
= *( DWORD *)(pInEthread+0x220); |
004 |
|
005 |
if (MmIsAddressValid( PVOID (eprocess)
) ) |
006 |
{ |
007 |
ThreadCollect(( PUCHAR )pInEthread); |
008 |
} |
009 |
|
010 |
} |
011 |
} |
012 |
013 |
014 |
015 |
PBYTE GoBackAddr
= NULL; |
016 |
PBYTE ChangAddr
= NULL; |
017 |
018 |
DWORD CallContextOffset
= 0; |
019 |
020 |
__declspec ( naked ) VOID HookSwap() |
021 |
{ |
022 |
023 |
_asm |
024 |
{ |
025 |
pushad |
026 |
pushfd |
027 |
cli |
028 |
} |
029 |
030 |
_asm |
031 |
{ |
032 |
//
EDI 是换出的线程上下文 |
033 |
push
edi |
034 |
//ESI
是换入的线程上下文 |
035 |
push
esi |
036 |
call
ProcessData //搜集进程 |
037 |
} |
038 |
|
039 |
_asm |
040 |
{ |
041 |
sti |
042 |
popfd |
043 |
popad |
044 |
} |
045 |
_asm
jmp DWORD PTR[GoBackAddr] |
046 |
} |
047 |
048 |
/* |
049 |
得到SwapContext地址的原理是 |
050 |
用PsLookupThreadByThreadId得到Idle
System的KTHREAD |
051 |
res=(PCHAR)(Thread->Tcb.KernelStack); |
052 |
SwapAddr=*(DWORD
*)(res+0x08); |
053 |
*/ |
054 |
PCHAR GetSwapAddr() |
055 |
{ |
056 |
PCHAR res
= 0; |
057 |
NTSTATUS
Status; |
058 |
PETHREAD
Thread; |
059 |
|
060 |
if (*NtBuildNumber
<= 2195) |
061 |
Status
= PsLookupThreadByThreadId(( PVOID )4,
&(PETHREAD)Thread); |
062 |
else |
063 |
Status
= PsLookupThreadByThreadId(( PVOID )8,
&(PETHREAD)Thread); |
064 |
|
065 |
if (NT_SUCCESS(Status)) |
066 |
{ |
067 |
if (MmIsAddressValid(Thread)) |
068 |
{ |
069 |
res
= ( PCHAR )(Thread->Tcb.KernelStack); |
070 |
071 |
} |
072 |
if (MmIsAddressValid(res+8)) |
073 |
{ |
074 |
_asm |
075 |
{ |
076 |
mov
eax,res |
077 |
add
eax,8 |
078 |
mov
eax,[eax] |
079 |
mov
res,eax |
080 |
} |
081 |
} |
082 |
else |
083 |
{ |
084 |
res
= 0; |
085 |
return NULL; |
086 |
} |
087 |
} |
088 |
_asm |
089 |
{ |
090 |
mov
eax,res |
091 |
sub
eax,5 |
092 |
mov
ChangAddr,eax |
093 |
mov
edx,[eax+1] |
094 |
mov
CallContextOffset,edx |
095 |
add
eax,edx |
096 |
add
eax,5 |
097 |
mov
GoBackAddr,eax |
098 |
mov
res,eax |
099 |
} |
100 |
return res; |
101 |
} |
102 |
103 |
104 |
105 |
BOOL HookSwapFunction( BOOL flag) |
106 |
{ |
107 |
if (flag
== TRUE) |
108 |
{ |
109 |
KIRQL
OldIrql=0; |
110 |
DWORD NewOffset; //HookSwap-ChangAddr-5; |
111 |
_asm |
112 |
{ |
113 |
mov
eax,HookSwap |
114 |
mov
edx,ChangAddr |
115 |
sub
eax,edx |
116 |
sub
eax,5 |
117 |
mov
NewOffset,eax |
118 |
} |
119 |
120 |
PAGED_CODE() |
121 |
ASSERT(KeGetCurrentIrql()<=DISPATCH_LEVEL); |
122 |
KeRaiseIrql(2,&OldIrql); //HIGH_LEVEL |
123 |
__asm |
124 |
{ |
125 |
CLI |
126 |
MOV
EAX, CR0 |
127 |
AND
EAX, NOT 10000H //disable
WP bit |
128 |
MOV
CR0, EAX |
129 |
} |
130 |
_asm |
131 |
{ |
132 |
mov
eax,ChangAddr |
133 |
push
NewOffset |
134 |
pop
dword ptr[eax+1] |
135 |
|
136 |
} |
137 |
|
138 |
__asm |
139 |
{ |
140 |
MOV
EAX, CR0 |
141 |
OR
EAX, 10000H //enable
WP bit |
142 |
MOV
CR0, EAX |
143 |
STI |
144 |
} |
145 |
|
146 |
|
147 |
KeLowerIrql(OldIrql); |
148 |
|
149 |
} |
150 |
//Bug
Check 0xD1: DRIVER_IRQL_NOT_LESS_OR_EQUAL |
151 |
|
152 |
else |
153 |
{ |
154 |
KIRQL
OldIrql=0; |
155 |
KeRaiseIrql(2,&OldIrql); ///HIGH_LEVEL |
156 |
__asm |
157 |
{ |
158 |
CLI |
159 |
MOV
EAX, CR0 |
160 |
AND
EAX, NOT 10000H //disable
WP bit |
161 |
MOV
CR0, EAX |
162 |
} |
163 |
|
164 |
_asm |
165 |
{ |
166 |
mov
eax,ChangAddr |
167 |
push
CallContextOffset |
168 |
pop
dword ptr[eax+1] |
169 |
} |
170 |
|
171 |
|
172 |
__asm |
173 |
{ |
174 |
MOV
EAX, CR0 |
175 |
OR
EAX, 10000H //enable
WP bit |
176 |
MOV
CR0, EAX |
177 |
STI |
178 |
} |
179 |
KeLowerIrql(OldIrql); |
180 |
//
DbgPrint("HookSwapFunctionFALSE");//jution |
181 |
} |
182 |
|
183 |
} |
184 |
185 |
PEPROCESS
processObject (PETHREAD ethread) { |
186 |
return (PEPROCESS)(ethread->Tcb.ApcState.Process); |
187 |
} |
188 |
189 |