Bitdefender Hypervisor Memory Introspection
winuser_checks.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020 Bitdefender
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 #include "winuser_checks.h"
6 #include "guests.h"
7 
13 
14 
15 // This field is used only on Windows 7 and it is at the same offset on all service packs so it doesn't makes sense to
16 // add it to the OsSpecificFields structure.
17 
18 #define PEB32_PCONTEXT_OFFSET 0x238
19 #define PEB64_PCONTEXT_OFFSET 0x368
20 
22 static BOOLEAN
24  _In_ PWIN_PROCESS_OBJECT Process,
25  _In_ QWORD Address,
26  _In_ DWORD Size,
27  _In_ DWORD PebSize
28  )
40 {
41  if (Process->Peb32Address <= Address &&
42  Process->Peb32Address + PebSize > Address)
43  {
44  // Additional check for pContextData
45  if (PEB32_PCONTEXT_OFFSET + Process->Peb32Address == Address && sizeof(DWORD) == Size)
46  {
47  Process->Peb32ContextWritten = TRUE;
48  }
49 
50  // The start is inside PEB. Is the end still there?
51  Address += Size;
52 
53  if (Process->Peb32Address <= Address &&
54  Process->Peb32Address + PebSize > Address)
55  {
56  return TRUE;
57  }
58  }
59 
60  // 64-bit process with 32-bit parent
61  if (!Process->Wow64Process && Process->ParentWow64)
62  {
63  if (Process->PebWrittenCount == 1)
64  {
65  return TRUE;
66  }
67  }
68 
69  return FALSE;
70 }
71 
72 
74 static BOOLEAN
76  _In_ PWIN_PROCESS_OBJECT Process,
77  _In_ QWORD Address,
78  _In_ DWORD Size,
79  _In_ DWORD PebSize
80  )
92 {
93  if (Process->Peb64Address <= Address &&
94  Process->Peb64Address + PebSize > Address)
95  {
96  // Additional check for pContextData
97  if (PEB64_PCONTEXT_OFFSET + Process->Peb64Address == Address && sizeof(QWORD) == Size)
98  {
99  Process->Peb64ContextWritten = TRUE;
100  }
101 
102  // The start is inside PEB. Is the end still there?
103  Address += Size;
104 
105  if (Process->Peb64Address <= Address &&
106  Process->Peb64Address + PebSize > Address)
107  {
108  return TRUE;
109  }
110  }
111 
112  return FALSE;
113 }
114 
115 
117 static BOOLEAN
119  _In_ PWIN_PROCESS_OBJECT Process,
120  _In_ QWORD Address,
121  _In_ DWORD Size
122  )
134 
135 {
136  if (Process->InjectionsCount == 1 && !Process->InjectedApphelp)
137  {
138  if (Size == 4)
139  {
140  return TRUE;
141  }
142 
143  if (gGuest.OSVersion < 9200 && Size == 0x20)
144  {
145  return TRUE;
146  }
147 
148  if (Size > 1000)
149  {
150  Process->InjectedApphelp = TRUE;
151  Process->InjectedApphelpAddress = Address;
152  Process->InjectedAppHelpSize = Size;
153 
154  return TRUE;
155  }
156  }
157 
158  return FALSE;
159 }
160 
161 
163 static BOOLEAN
165  _In_ PWIN_PROCESS_OBJECT Process
166  )
176 {
177  // on Windows 7 x64, initialization isn't done until PEB.pContextData is written
178  if (gGuest.Guest64 && gGuest.OSVersion <= 7602 && Process->InjectedApphelp)
179  {
180  if (Process->Subsystemx64 && Process->Subsystemx86)
181  {
182  if (Process->Peb64ContextWritten && Process->Peb32ContextWritten)
183  {
184  return TRUE;
185  }
186  else
187  {
188  return FALSE;
189  }
190  }
191  else if (Process->Subsystemx64 && Process->Peb64ContextWritten)
192  {
193  return TRUE;
194  }
195  else if (Process->Subsystemx86 && Process->Peb32ContextWritten)
196  {
197  return TRUE;
198  }
199  else
200  {
201  return FALSE;
202  }
203  }
204 
205  if (gGuest.Guest64)
206  {
207  // 32-bit process parent which injects apphelp, it does the PEB write 4 times
208  if (Process->PebWrittenCount == 2 && Process->Wow64Process && Process->ParentWow64 &&
209  Process->InjectedApphelp && gGuest.OSVersion < 9200)
210  {
211  Process->InjectedApphelp = FALSE;
212  Process->InjectionsCount = 0;
213  Process->PebWrittenCount = 0;
214 
215  return FALSE;
216  }
217 
218  if (Process->PebWrittenCount == 2)
219  {
220  return TRUE;
221  }
222 
223  if (!Process->Wow64Process && Process->PebWrittenCount == 1)
224  {
225  if (gGuest.OSVersion >= 14393 && Process->ParentWow64)
226  {
227  return TRUE;
228  }
229 
230  if (gGuest.OSVersion >= 9200 && Process->ParentWow64)
231  {
232  return FALSE;
233  }
234 
235  return TRUE;
236  }
237  }
238  else
239  {
240  if (Process->PebWrittenCount == 1)
241  {
242  if (Process->InjectedApphelp && gGuest.OSVersion < 9200)
243  {
244  Process->InjectedApphelp = FALSE;
245  Process->InjectionsCount = 0;
246  Process->PebWrittenCount = 0;
247 
248  return FALSE;
249  }
250 
251  return TRUE;
252  }
253  }
254 
255  return FALSE;
256 }
257 
258 
259 INTSTATUS
262  _In_ PEXCEPTION_UM_ORIGINATOR Originator
263  )
283 {
284  WIN_PROCESS_OBJECT *pProc;
285  DWORD pebSize, pebWriteCount;
286 
287  if (NULL == Victim)
288  {
290  }
291 
292  if (NULL == Originator)
293  {
295  }
296 
297  pProc = Victim->Object.WinProc;
298  if (NULL == pProc)
299  {
300  ERROR("[ERROR] Victim zone cannot have NULL process!\n");
302  }
303 
304  if (!pProc->StartInitializing)
305  {
307  }
308 
309  if (pProc->Initialized)
310  {
311  if (!pProc->LastPebWriteDone)
312  {
313  QWORD address = Victim->Injection.Gva;
314  DWORD size = Victim->Injection.Length;
315 
316  if (gGuest.OSVersion <= 7602 && pProc->Wow64Process)
317  {
318  if (PEB64_PCONTEXT_OFFSET + pProc->Peb64Address == address &&
319  sizeof(QWORD) == size)
320  {
321  pProc->LastPebWriteDone = TRUE;
323  }
324 
325  if (PEB32_PCONTEXT_OFFSET + pProc->Peb32Address == address &&
326  sizeof(DWORD) == size)
327  {
328  pProc->LastPebWriteDone = TRUE;
330  }
331  }
332  }
333 
335  }
336 
337  pebWriteCount = pProc->PebWrittenCount;
338  pProc->InjectionsCount++;
339 
340  if (ShouldIgnoreInjection(pProc, Victim->Injection.Gva, Victim->Injection.Length))
341  {
342  pProc->InjectionsCount--;
343 
345  }
346 
347  if (gGuest.Guest64)
348  {
349  pebSize = WIN_UM_FIELD(Peb, 64Size);
350 
351  if (IsPeb64Write(pProc, Victim->Injection.Gva, Victim->Injection.Length, pebSize))
352  {
353  pProc->PebWrittenCount++;
354  }
355  else
356  {
357  pebSize = WIN_UM_FIELD(Peb, 32Size);
358 
359  if (IsPeb32Write(pProc, Victim->Injection.Gva, Victim->Injection.Length, pebSize))
360  {
361  pProc->PebWrittenCount++;
362  }
363  }
364  }
365  else
366  {
367  pebSize = WIN_UM_FIELD(Peb, 32Size);
368 
369  if (IsPeb32Write(pProc, Victim->Injection.Gva, Victim->Injection.Length, pebSize))
370  {
371  pProc->PebWrittenCount++;
372  }
373  }
374 
375  //
376  // On pre-windows 10, everything until PEB writes are OK
377  //
378  if (gGuest.OSVersion < 10240)
379  {
380  if (pebWriteCount == pProc->PebWrittenCount)
381  {
383  }
384  }
385 
386  if (IsInitializationDone(pProc))
387  {
388  TRACE("[PROCESS] '%s' with EPROC: 0x%016llx is fully initialized!\n", pProc->Name, pProc->EprocessAddress);
389  pProc->Initialized = TRUE;
390  }
391 
393 }
static BOOLEAN ShouldIgnoreInjection(PWIN_PROCESS_OBJECT Process, QWORD Address, DWORD Size)
This function checks if the current injection should be ignored or not (based on the WIN_PROCESS_OBJE...
_Bool BOOLEAN
Definition: intro_types.h:58
static BOOLEAN IsInitializationDone(PWIN_PROCESS_OBJECT Process)
This function checks if all the initialization steps of a process are done.
#define INT_STATUS_EXCEPTION_CHECKS_FAILED
Definition: introstatus.h:411
#define _In_
Definition: intro_sal.h:21
#define WIN_UM_FIELD(Structure, Field)
Macro used to access user mode fields inside the WIN_OPAQUE_FIELDS structure.
Definition: winguest.h:778
#define INT_STATUS_EXCEPTION_CHECKS_OK
Definition: introstatus.h:396
BYTE InjectionsCount
The number of injections allowed at the initialization.
Definition: winprocess.h:173
#define ERROR(fmt,...)
Definition: glue.h:62
BYTE PebWrittenCount
The number writes to the (Process Environment Block).
Definition: winprocess.h:174
Describes a user-mode originator.
Definition: exceptions.h:994
int INTSTATUS
The status data type.
Definition: introstatus.h:24
DWORD OSVersion
Os version.
Definition: guests.h:281
#define PEB32_PCONTEXT_OFFSET
The PEB32 (Process Environment Block) context offset.
QWORD Peb64Address
PEB 64 address (on x86 OSes, this will be 0).
Definition: winprocess.h:103
DWORD Wow64Process
TRUE if this is a 32 bit process on a 64 bit OS.
Definition: winprocess.h:125
DWORD LastPebWriteDone
TRUE if the write into PEB is done (used for initialization checks).
Definition: winprocess.h:143
BOOLEAN Guest64
True if this is a 64-bit guest, False if it is a 32-bit guest.
Definition: guests.h:290
unsigned long long QWORD
Definition: intro_types.h:53
CHAR Name[IMAGE_BASE_NAME_LEN]
Process base name.
Definition: winprocess.h:108
static BOOLEAN IsPeb32Write(PWIN_PROCESS_OBJECT Process, QWORD Address, DWORD Size, DWORD PebSize)
This function checks if the current injection targets the PEB32 (Process Environment Block) structure...
#define TRUE
Definition: intro_types.h:30
DWORD StartInitializing
TRUE if the process actually started initializing (there is a time windows from the moment we add the...
Definition: winprocess.h:151
#define TRACE(fmt,...)
Definition: glue.h:58
#define INT_STATUS_INVALID_INTERNAL_STATE
Definition: introstatus.h:272
INTSTATUS IntWinUmCheckInitializationInjection(PEXCEPTION_VICTIM_ZONE Victim, PEXCEPTION_UM_ORIGINATOR Originator)
This function is used by the exception mechanism in order to verify the initialization state of a pro...
Describes the modified zone.
Definition: exceptions.h:893
#define __forceinline
Definition: introtypes.h:61
QWORD Peb32Address
PEB 32 address (on pure x64 processes, this will be 0).
Definition: winprocess.h:104
uint32_t DWORD
Definition: intro_types.h:49
#define PEB64_PCONTEXT_OFFSET
The PEB64 (Process Environment Block) context offset.
QWORD EprocessAddress
This will be the address of the ActiveProcess field.
Definition: winprocess.h:90
GUEST_STATE gGuest
The current guest state.
Definition: guests.c:50
static BOOLEAN IsPeb64Write(PWIN_PROCESS_OBJECT Process, QWORD Address, DWORD Size, DWORD PebSize)
This function checks if the current injection targets the PEB64 (Process Environment Block) structure...
Exposes the function used to perform initialization checks on Windows processes.
#define INT_STATUS_INVALID_PARAMETER_1
Definition: introstatus.h:62
#define INT_STATUS_INVALID_PARAMETER_2
Definition: introstatus.h:65
#define FALSE
Definition: intro_types.h:34
This structure describes a running process inside the guest.
Definition: winprocess.h:83