下面是主要代码
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 |