Bitdefender Hypervisor Memory Introspection
winumcrash.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020 Bitdefender
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 
6 #include "winumcrash.h"
7 #include "alerts.h"
8 #include "guests.h"
9 #include "shellcode.h"
10 #include "winprocesshp.h"
11 #include "winthread.h"
12 
13 
14 // These are defined by the Windows SDK headers in minwinbase.h
15 // Can also be found on here: https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-exception_record
16 #define STILL_ACTIVE 0x00000103L
17 #define EXCEPTION_ACCESS_VIOLATION 0xC0000005L
18 #define EXCEPTION_DATATYPE_MISALIGNMENT 0x80000002L
19 #define EXCEPTION_BREAKPOINT 0x80000003L
20 #define EXCEPTION_SINGLE_STEP 0x80000004L
21 #define EXCEPTION_ARRAY_BOUNDS_EXCEEDED 0xC000008CL
22 #define EXCEPTION_FLT_DENORMAL_OPERAND 0xC000008DL
23 #define EXCEPTION_FLT_DIVIDE_BY_ZERO 0xC000008EL
24 #define EXCEPTION_FLT_INEXACT_RESULT 0xC000008FL
25 #define EXCEPTION_FLT_INVALID_OPERATION 0xC0000090L
26 #define EXCEPTION_FLT_OVERFLOW 0xC0000091L
27 #define EXCEPTION_FLT_STACK_CHECK 0xC0000092L
28 #define EXCEPTION_FLT_UNDERFLOW 0xC0000093L
29 #define EXCEPTION_INT_DIVIDE_BY_ZERO 0xC0000094L
30 #define EXCEPTION_INT_OVERFLOW 0xC0000095L
31 #define EXCEPTION_PRIV_INSTRUCTION 0xC0000096L
32 #define EXCEPTION_IN_PAGE_ERROR 0xC0000006L
33 #define EXCEPTION_ILLEGAL_INSTRUCTION 0xC000001DL
34 #define EXCEPTION_NONCONTINUABLE_EXCEPTION 0xC0000025L
35 #define EXCEPTION_STACK_OVERFLOW 0xC00000FDL
36 #define EXCEPTION_INVALID_DISPOSITION 0xC0000026L
37 #define EXCEPTION_GUARD_PAGE 0x80000001L
38 #define EXCEPTION_INVALID_HANDLE 0xC0000008L
39 #define EXCEPTION_POSSIBLE_DEADLOCK 0xC0000194L
40 #define CONTROL_C_EXIT 0xC000013AL
41 
42 
43 // These values are used internally by the Windows exception dispatching mechanism
44 #define KI_EXCEPTION_INTERNAL 0x10000000
45 #define KI_EXCEPTION_GP_FAULT ((INTSTATUS)(KI_EXCEPTION_INTERNAL | 0x01))
47 #define KI_EXCEPTION_INVALID_OP ((INTSTATUS)(KI_EXCEPTION_INTERNAL | 0x02))
49 #define KI_EXCEPTION_INTEGER_DIVIDE_BY_ZERO ((INTSTATUS)(KI_EXCEPTION_INTERNAL | 0x03))
51 #define KI_EXCEPTION_ACCESS_VIOLATION ((INTSTATUS)(KI_EXCEPTION_INTERNAL | 0x04))
53 
54 #define KERNEL_MODE 0
55 #define USER_MODE 1
56 
57 // See https://msdn.microsoft.com/en-us/library/windows/desktop/aa363082(v=vs.85).aspx
58 #define FLG_CONTINUABLE 0
59 #define FLG_NON_CONTINUABLE 1
60 
67 typedef enum
68 {
71  PARAM1_DEP = 8,
73 
81 #define IS_DEP_FAULT(Er) ((EXCEPTION_ACCESS_VIOLATION == (Er).ExceptionCode) && \
82  !IS_KERNEL_POINTER_WIN(gGuest.Guest64, (Er).ExceptionAddress) && \
83  (PARAM1_DEP == (Er).ExceptionInformation[0]))
84 
85 #define CODE_SEG_UM_32 0x20
86 #define CODE_SEG_UM_64 0x30
87 
88 
89 static __forceinline
90 _Success_(return != FALSE) BOOLEAN
92  _In_ DWORD ExceptionCode,
93  _Out_ DWORD *Status
94  )
108 {
109  switch (ExceptionCode)
110  {
113  return TRUE;
114 
117  return TRUE;
118 
120  // it seems that KiPreprocessFault treats KI_EXCEPTION_GP_FAULT the same as EXCEPTION_ACCESS_VIOLATION
122  *Status = EXCEPTION_ACCESS_VIOLATION;
123  return TRUE;
124 
125  // nothing to change for these
126  case STILL_ACTIVE:
150  case CONTROL_C_EXIT:
151  *Status = ExceptionCode;
152  return TRUE;
153 
154  default:
155  return FALSE;
156  }
157 }
158 
159 
160 static void
162  _In_ void const *TrapFrame,
163  _In_opt_ KEXCEPTION_FRAME64 const *ExFrame,
164  _Out_ IG_ARCH_REGS *Regs
165  )
174 {
175  if (gGuest.Guest64)
176  {
177  KTRAP_FRAME64 const *tf = TrapFrame;
178 
179  Regs->Rax = tf->Rax;
180  Regs->Rcx = tf->Rcx;
181  Regs->Rdx = tf->Rdx;
182  Regs->Rbx = tf->Rbx;
183  Regs->Rsp = tf->Rsp;
184  Regs->Rbp = tf->Rbp;
185  Regs->Rsi = tf->Rsi;
186  Regs->Rdi = tf->Rdi;
187  Regs->R8 = tf->R8;
188  Regs->R9 = tf->R9;
189  Regs->R10 = tf->R10;
190  Regs->R11 = tf->R11;
191 
192  if (ExFrame)
193  {
194  Regs->R12 = ExFrame->R12;
195  Regs->R13 = ExFrame->R13;
196  Regs->R14 = ExFrame->R14;
197  Regs->R15 = ExFrame->R15;
198  }
199 
200  Regs->Flags = tf->EFlags;
201  }
202  else
203  {
204  KTRAP_FRAME32 const *tf = TrapFrame;
205 
206  Regs->Rax = tf->Eax;
207  Regs->Rcx = tf->Ecx;
208  Regs->Rdx = tf->Edx;
209  Regs->Rbx = tf->Ebx;
210  Regs->Rsp = tf->HardwareEsp;
211  Regs->Rbp = tf->Ebp;
212  Regs->Rsi = tf->Esi;
213  Regs->Rdi = tf->Edi;
214  Regs->Flags = tf->EFlags;
215  }
216 }
217 
218 
219 static INTSTATUS
221  _In_ void const *ExceptionRecord,
222  _In_ QWORD ExceptionFrameGva,
223  _In_ QWORD TrapFrameGva
224  )
250 {
251  INTSTATUS status;
252  PWIN_PROCESS_OBJECT pProc;
253  IG_ARCH_REGS regs = { 0 };
254  QWORD gpa = 0;
255  DWORD csType;
256  EVENT_EPT_VIOLATION *pEvent;
257  QWORD tibBase = 0;
258  QWORD stackBase = 0;
259  QWORD stackLimit = 0;
260  BOOLEAN bRspOut = FALSE;
261  BOOLEAN bIsStack = FALSE;
262  EXCEPTION_UM_ORIGINATOR originator;
263  EXCEPTION_VICTIM_ZONE victim;
264  QWORD scflags = 0;
265 
267  if (NULL == pProc || !pProc->Protected || !pProc->ProtExploits || !pProc->EnforcedDep)
268  {
270  }
271 
272  if (gGuest.Guest64)
273  {
274  EXCEPTION_RECORD64 const *pEr = ExceptionRecord;
275  KTRAP_FRAME64 tf = { 0 };
276  KEXCEPTION_FRAME64 ef = { 0 };
277 
278  // Read the trap and the exception frames in order to reconstruct the process state at the moment of the #PF
279  status = IntKernVirtMemRead(TrapFrameGva, sizeof(tf), &tf, NULL);
280  if (!INT_SUCCESS(status))
281  {
282  ERROR("[ERROR] IntKernVirtMemRead failed for 0x%016llx: 0x%08x\n", TrapFrameGva, status);
283  return status;
284  }
285 
286  status = IntKernVirtMemRead(ExceptionFrameGva, sizeof(ef), &ef, NULL);
287  if (!INT_SUCCESS(status))
288  {
289  ERROR("[ERROR] IntKernVirtMemRead failed for 0x%016llx: 0x%08x\n", ExceptionFrameGva, status);
290  return status;
291  }
292 
293  // Reconstruct the context
294  IntWinFillRegsFromExceptionInfo(&tf, &ef, &regs);
295  regs.Rip = pEr->ExceptionAddress;
296  regs.Cr3 = gVcpu->Regs.Cr3;
297 
298  switch (tf.SegCs & ~0x7)
299  {
300  case CODE_SEG_UM_32:
301  csType = IG_CS_TYPE_32B;
302  break;
303 
304  case CODE_SEG_UM_64:
305  csType = IG_CS_TYPE_64B;
306  break;
307 
308  default:
309  WARNING("[WARNING] Unrecognized CS value: 0x%08x\n", tf.SegCs);
311  }
312  }
313  else
314  {
315  EXCEPTION_RECORD32 const *pEr = ExceptionRecord;
316  KTRAP_FRAME32 tf = { 0 };
317 
318  // Read the trap frame in order to reconstruct the process state at the moment of the #PF
319  status = IntKernVirtMemRead(TrapFrameGva, sizeof(tf), &tf, NULL);
320  if (!INT_SUCCESS(status))
321  {
322  ERROR("[ERROR] IntKernVirtMemRead failed for 0x%016llx: 0x%08x\n", TrapFrameGva, status);
323  return status;
324  }
325 
326  // The exception frame is not needed on 32-bit guests
327 
328  // Reconstruct the context
329  IntWinFillRegsFromExceptionInfo(&tf, NULL, &regs);
330  regs.Rip = pEr->ExceptionAddress;
331  regs.Cr3 = gVcpu->Regs.Cr3;
332 
333  csType = IG_CS_TYPE_32B;
334  }
335 
336  status = IntTranslateVirtualAddress(regs.Rip, gVcpu->Regs.Cr3, &gpa);
337  if (!INT_SUCCESS(status))
338  {
339  WARNING("[WARNING] IntTranslateVirtualAddress failed for 0x%016llx and Cr3 0x%016llx: 0x%08x\n",
340  regs.Rip, gVcpu->Regs.Cr3, status);
341  // I think we can safely go on with sending the alert
342  // NOTE: We won't send the alert if we couldn't translate the RIP page, because we won't be able to run the
343  // shellcode emulator on it.
344  return INT_STATUS_SUCCESS;
345  }
346 
347  status = IntWinThrGetCurrentTib(IG_CS_RING_0, csType, &tibBase);
348  if (!INT_SUCCESS(status))
349  {
350  WARNING("[WARNING] IntWinThrGetCurrentTib failed: 0x%08x\n", status);
351  // Go on with stack base/limit set to 0
352  }
353  else
354  {
355  status = IntWinThrGetUmStackBaseAndLimitFromTib(tibBase, csType, regs.Cr3, &stackBase, &stackLimit);
356  if (!INT_SUCCESS(status))
357  {
358  WARNING("[WARNING] IntWinThrGetUmStackBaseAndLimitFromTib failed: 0x%08x\n", status);
359  // Go on with stack base/limit set to 0
360  }
361  else
362  {
363  bRspOut = ((regs.Rsp < stackLimit - 0x3000) || (regs.Rsp >= stackBase));
364  bIsStack = (regs.Rip >= stackLimit) && (regs.Rip < stackBase);
365  }
366  }
367 
368  // Call the shellcode emulator on the affected page. Note that we have to provide the CS type ourselves, because
369  // right now, we are in kernel context, and on a 64 bit machine, this will result in a 64b CS type, even if the
370  // crashing application was running in compatibility (32b) mode.
371  status = IntShcIsSuspiciousCode(regs.Rip, gpa, csType, &regs, &scflags);
372  if (!INT_SUCCESS(status))
373  {
374  scflags = 0;
375  }
376 
377  if (!(bRspOut || bIsStack || (0 != scflags)))
378  {
379  // No detection was triggered by our heuristics, there's no need to send an alert. This avoids multiple FPs
380  // triggered in various places due to faulty code which randomly crashes.
381  return INT_STATUS_SUCCESS;
382  }
383 
384  memzero(&originator, sizeof(originator));
385  memzero(&victim, sizeof(victim));
386 
387  status = IntExceptUserGetExecOriginator(pProc, &originator);
388  if (!INT_SUCCESS(status))
389  {
390  ERROR("[ERROR] Failed getting originator: 0x%08x\n", status);
391  goto _skip_log;
392  }
393 
394  originator.Rip = regs.Rip;
395  originator.SourceVA = regs.Rip;
396 
397  status = IntExceptGetVictimEpt(pProc, gpa, regs.Rip, introObjectTypeUmGenericNxZone,
398  ZONE_EXECUTE | ZONE_DEP_EXECUTION, &victim);
399  if (!INT_SUCCESS(status))
400  {
401  ERROR("[ERROR] Failed getting modified zone: 0x%08x\n", status);
402  goto _skip_log;
403  }
404 
406 
407 _skip_log:
408  LOG("[DEP] [CPU %d] EXPLOIT detected! Execution attempted at 0x%016llx!\n", gVcpu->Index, regs.Rip);
409  LOG("[DEP] Current address: 0x%016llx, current stack: 0x%016llx, known stack: 0x%016llx/0x%016llx, "
410  "TIB: 0x%016llx\n", regs.Rip, regs.Rsp, stackBase, stackLimit, tibBase);
411  LOG("[DEP] RSP out: %d; Is stack: %d; ScFlags: 0x%llx\n", bRspOut, bIsStack, scflags);
412 
413  IntDumpCodeAndRegs(regs.Rip, gpa, &regs);
414 
415  pEvent = &gAlert.Ept;
416  memzero(pEvent, sizeof(*pEvent));
417 
421 
422  pEvent->Header.Flags = IntAlertProcGetFlags(0, NULL, introReasonUnknown, 0);
423 
424  if (pProc->SystemProcess)
425  {
426  pEvent->Header.Flags |= ALERT_FLAG_SYSPROC;
427  }
428 
430 
432  pEvent->Violation = IG_EPT_HOOK_EXECUTE;
433 
434  pEvent->HookStartPhysical = gpa & PHYS_PAGE_MASK;
435  pEvent->HookStartVirtual = regs.Rip & PAGE_MASK;
436  pEvent->VirtualPage = regs.Rip & PAGE_MASK;
437  pEvent->Offset = regs.Rip & 0xFFF;
438 
439  pEvent->Header.CpuContext.Valid = TRUE;
440  pEvent->Header.CpuContext.Rip = regs.Rip;
441  pEvent->Header.CpuContext.Cr3 = regs.Cr3;
442  pEvent->Header.CpuContext.Cpu = gVcpu->Index;
443 
445 
446  // For execute-alerts, original & new value have different meaning, since an actual write is not being made.
447  pEvent->ExecInfo.Rsp = regs.Rsp;
448  pEvent->ExecInfo.StackBase = stackBase;
449  pEvent->ExecInfo.StackLimit = stackLimit;
450  pEvent->ExecInfo.Length = 0;
451 
452  pEvent->CodeBlocks.Valid = FALSE;
453 
454  pEvent->ExecContext.CsType = csType;
455  memcpy(&pEvent->ExecContext.Registers, &regs, sizeof(pEvent->ExecContext.Registers));
456  status = IntVirtMemRead(regs.Rip & PAGE_MASK, sizeof(pEvent->ExecContext.RipCode),
457  regs.Cr3, &pEvent->ExecContext.RipCode, NULL);
458  if (!INT_SUCCESS(status))
459  {
460  WARNING("[WARNING] IntVirtMemRead failed for 0x%016llx: 0x%08x\n", regs.Rip & PAGE_MASK, status);
461  }
462 
464 
465  status = IntNotifyIntroEvent(introEventEptViolation, pEvent, sizeof(*pEvent));
466  if (!INT_SUCCESS(status))
467  {
468  WARNING("[WARNING] IntNotifyIntroEvent failed: 0x%08x\n", status);
469  }
470 
471  return status;
472 }
473 
474 
475 static INTSTATUS
477  _In_ void const *ExceptionRecord
478  )
494 {
495  PWIN_PROCESS_OBJECT pProc;
496 
497  if (NULL == ExceptionRecord)
498  {
500  }
501 
502  pProc = IntWinGetCurrentProcess();
503  if (NULL == pProc)
504  {
505  ERROR("[ERROR] Can not find process. Current CR3 = 0x%016llx\n", gVcpu->Regs.Cr3);
506  return INT_STATUS_NOT_FOUND;
507  }
508 
509  if (gGuest.Guest64)
510  {
511  EXCEPTION_RECORD64 const *pRecord = ExceptionRecord;
512 
513  pProc->LastException = pRecord->ExceptionCode;
514  pProc->LastExceptionRip = pRecord->ExceptionAddress;
516 
517  if (pProc->Protected)
518  {
519  LOG("[UMEXCEPTION] Code: 0x%08x at RIP 0x%016llx inside process `%s` (Pid %d, Cr3 0x%016llx). "
520  "Continuable: %d\n", pRecord->ExceptionCode, pRecord->ExceptionAddress, pProc->Name, pProc->Pid,
521  pProc->Cr3, pProc->LastExceptionContinuable);
522  }
523  }
524  else
525  {
526  EXCEPTION_RECORD32 const *pRecord = ExceptionRecord;
527 
528  pProc->LastException = pRecord->ExceptionCode;
529  pProc->LastExceptionRip = pRecord->ExceptionAddress;
531 
532  if (pProc->Protected)
533  {
534  LOG("[UMEXCEPTION] Code: 0x%08x at RIP 0x%08x inside process `%s` (Pid %d, Cr3 0x%016llx). "
535  "Continuable: %d\n", (DWORD)pRecord->ExceptionCode, pRecord->ExceptionAddress, pProc->Name, pProc->Pid,
536  pProc->Cr3, pProc->LastExceptionContinuable);
537  }
538  }
539  return INT_STATUS_SUCCESS;
540 }
541 
542 
543 INTSTATUS
545  _In_ void *Detour
546  )
577 {
578  INTSTATUS status;
579  PIG_ARCH_REGS pRegs;
580  QWORD prevMode;
581  QWORD erGva;
582  QWORD efGva;
583  QWORD tfGva;
584  QWORD args[4];
585 
586  if (NULL == Detour)
587  {
589  }
590 
591  status = IntDetGetArguments(Detour, 4, args);
592  if (!INT_SUCCESS(status))
593  {
594  ERROR("[ERROR] IntDetGetArguments failed: 0x%08x\n", status);
595  goto _cleanup_and_exit;
596  }
597 
598  erGva = args[0];
599  efGva = args[1];
600  tfGva = args[2];
601  prevMode = args[3];
602 
604 
605  pRegs = &gVcpu->Regs;
606 
607  // we only care about user mode
608  if (KERNEL_MODE == prevMode)
609  {
610  status = INT_STATUS_SUCCESS;
611  goto _cleanup_and_exit;
612  }
613 
614  if (gGuest.Guest64)
615  {
616  EXCEPTION_RECORD64 er = { 0 };
617 
618  status = IntKernVirtMemRead(erGva, sizeof(EXCEPTION_RECORD64), &er, NULL);
619  if (!INT_SUCCESS(status))
620  {
621  ERROR("[ERROR] IntKernVirtMemRead failed for 0x%016llx: 0x%08x\n", pRegs->Rcx, status);
622  goto _cleanup_and_exit;
623  }
624 
625  // translate from KI_INTERNAL_EXCEPTION to a NTSTATUS value and also determine if we should care about
626  // this exception
628  {
629  goto _cleanup_and_exit;
630  }
631 
634  {
635  status = INT_STATUS_SUCCESS;
636  goto _cleanup_and_exit;
637  }
638 
639  if (IS_DEP_FAULT(er))
640  {
642 
643  status = IntWinCrashHandleDepViolation(&er, efGva, tfGva);
644  if (!INT_SUCCESS(status))
645  {
646  ERROR("[ERROR] IntWinCrashHandleDepViolation failed: 0x%08x\n", status);
647  }
648 
650  }
651 
652  status = IntWinSetUmExceptionEvent(&er);
653  if (!INT_SUCCESS(status))
654  {
655  ERROR("[ERROR] IntWinSendUmExceptionEvent failed: 0x%08x\n", status);
656  goto _cleanup_and_exit;
657  }
658  }
659  else
660  {
661  EXCEPTION_RECORD32 er = { 0 };
662 
663  // read the exception record structure
664  status = IntKernVirtMemRead(erGva, sizeof(EXCEPTION_RECORD32), &er, NULL);
665  if (!INT_SUCCESS(status))
666  {
667  ERROR("[ERROR] IntKernVirtMemRead failed for 0x%016llx: 0x%08x\n", erGva, status);
668  goto _cleanup_and_exit;
669  }
670 
671  // translate from KI_INTERNAL_EXCEPTION to a INTSTATUS value and also determine if we should care about this
672  // exception
674  {
675  goto _cleanup_and_exit;
676  }
677 
678  if (IS_DEP_FAULT(er))
679  {
681 
682  // There is no need for the exception frame on 32-bit, so NULL is ok here
683  status = IntWinCrashHandleDepViolation(&er, 0, tfGva);
684  if (!INT_SUCCESS(status))
685  {
686  ERROR("[ERROR] IntWinCrashHandleDepViolation failed: 0x%08x\n", status);
687  }
688 
690  }
691 
692  status = IntWinSetUmExceptionEvent(&er);
693  if (!INT_SUCCESS(status))
694  {
695  ERROR("[ERROR] IntWinSendUmExceptionEvent failed: 0x%08x\n", status);
696  goto _cleanup_and_exit;
697  }
698  }
699 
700 _cleanup_and_exit:
701 
703 
704  return INT_STATUS_SUCCESS;
705 }
#define EXCEPTION_IN_PAGE_ERROR
Definition: winumcrash.c:32
DWORD Edx
Definition: wddefs.h:961
#define _In_opt_
Definition: intro_sal.h:16
struct _EVENT_EPT_VIOLATION::@284 Victim
INTRO_CODEBLOCKS CodeBlocks
Code blocks extracted for the alert.
Definition: intro_types.h:1263
Measures IntWinHandleException invocations done for DEP violations.
Definition: stats.h:76
#define CODE_SEG_UM_64
64-bit user mode code selector
Definition: winumcrash.c:86
BOOLEAN EnforcedDep
TRUE is the DEP (Data Execution Prevention) has been enforced.
Definition: winprocess.h:189
#define _Out_
Definition: intro_sal.h:22
_Bool BOOLEAN
Definition: intro_types.h:58
DWORD EFlags
Definition: wddefs.h:979
#define EXCEPTION_FLT_DENORMAL_OPERAND
Definition: winumcrash.c:22
A user-mode data execution prevention (DEP) violation.
Definition: winumcrash.c:71
Attempt to read inaccessible data.
Definition: winumcrash.c:69
INTSTATUS IntWinHandleException(void *Detour)
Handles a hardware exception triggered inside the guestThis is the detour handler for the guest KiDis...
Definition: winumcrash.c:544
#define EXCEPTION_SINGLE_STEP
Definition: winumcrash.c:20
#define EXCEPTION_GUARD_PAGE
Definition: winumcrash.c:37
BYTE Violation
The type of the access. It must be one of the IG_EPT_HOOK_TYPE values.
Definition: intro_types.h:1265
IG_ARCH_REGS Regs
The current state of the guest registers.
Definition: guests.h:95
DWORD Index
The VCPU number.
Definition: guests.h:172
#define _In_
Definition: intro_sal.h:21
#define EXCEPTION_NONCONTINUABLE_EXCEPTION
Definition: winumcrash.c:34
MITRE_ID MitreID
The Mitre ID that corresponds to this attack.
Definition: intro_types.h:1199
#define INT_STATUS_SUCCESS
Definition: introstatus.h:54
DWORD Ebp
Definition: wddefs.h:974
#define EXCEPTION_PRIV_INSTRUCTION
Definition: winumcrash.c:31
QWORD ExceptionAddress
The address at which the exception was generated.
Definition: wddefs.h:1195
DWORD ExceptionCode
The code generated by hardware, or the one used with RaiseException(), or DBG_CONTROL_C.
Definition: wddefs.h:1191
DWORD HardwareEsp
Definition: wddefs.h:980
#define STATS_EXIT(id)
Definition: stats.h:160
INTSTATUS IntWinThrGetCurrentTib(IG_CS_RING CurrentRing, IG_CS_TYPE CsType, QWORD *Tib)
Obtain the TIB (Thread Information Block) of the thread running on the current CPU.
Definition: winthread.c:170
void IntAlertFillWinProcess(const WIN_PROCESS_OBJECT *Process, INTRO_PROCESS *EventProcess)
Saves information about a windows process inside an alert.
Definition: alerts.c:689
User-mode non executable zone.
Definition: intro_types.h:247
BOOLEAN LastExceptionContinuable
TRUE if the last exception is continuable (for example a #PF that was caused due to the way the OS do...
Definition: winprocess.h:184
#define _Success_(expr)
Definition: intro_sal.h:47
QWORD HookStartPhysical
The start of the monitored guest physical memory area for which this alert was generated.
Definition: intro_types.h:1270
static INTSTATUS IntWinSetUmExceptionEvent(void const *ExceptionRecord)
Sets the last exception triggered by a process.
Definition: winumcrash.c:476
#define INT_SUCCESS(Status)
Definition: introstatus.h:42
#define EXCEPTION_FLT_STACK_CHECK
Definition: winumcrash.c:27
QWORD Flags
A combination of ALERT_FLAG_* values describing the alert.
Definition: intro_types.h:1198
DWORD Eax
Definition: wddefs.h:963
#define EXCEPTION_FLT_INVALID_OPERATION
Definition: winumcrash.c:25
#define EXCEPTION_POSSIBLE_DEADLOCK
Definition: winumcrash.c:39
#define INT_STATUS_NOT_NEEDED_HINT
Definition: introstatus.h:317
#define ERROR(fmt,...)
Definition: glue.h:62
Describes a user-mode originator.
Definition: exceptions.h:994
static INTSTATUS IntWinCrashHandleDepViolation(void const *ExceptionRecord, QWORD ExceptionFrameGva, QWORD TrapFrameGva)
Handles a crash generated by a DEP violation.
Definition: winumcrash.c:220
INTSTATUS IntShcIsSuspiciousCode(QWORD Gva, QWORD Gpa, DWORD CsType, IG_ARCH_REGS *Registers, QWORD *ShellcodeFlags)
Checks if the code located at the given guest virtual address is suspicious or not.
Definition: shellcode.c:25
#define PHYS_PAGE_MASK
Definition: pgtable.h:38
int INTSTATUS
The status data type.
Definition: introstatus.h:24
#define EXCEPTION_FLT_UNDERFLOW
Definition: winumcrash.c:28
#define FLG_NON_CONTINUABLE
Definition: winumcrash.c:59
#define KI_EXCEPTION_ACCESS_VIOLATION
Page fault.
Definition: winumcrash.c:52
#define INT_STATUS_NOT_FOUND
Definition: introstatus.h:284
QWORD Rip
The value of the guest RIP register when the event was generated.
Definition: intro_types.h:968
#define EXCEPTION_INT_DIVIDE_BY_ZERO
Definition: winumcrash.c:29
INTSTATUS IntDumpCodeAndRegs(QWORD Gva, QWORD Gpa, IG_ARCH_REGS *Registers)
This function dumps an entire page (textual disassembly and opcodes) as well as the values of the reg...
Definition: dumper.c:692
DWORD Ecx
Definition: wddefs.h:962
An _KEXCEPTION_FRAME structure used by 64-bit guests.
Definition: wddefs.h:1223
QWORD HookStartVirtual
The start of the monitored guest virtual memory area for which this alert was generated.
Definition: intro_types.h:1268
EVENT_EPT_VIOLATION Ept
Definition: alerts.h:16
DWORD Protected
TRUE if this is a protected process. If this is FALSE, most of the above fields aren&#39;t used at all...
Definition: winprocess.h:130
QWORD SourceVA
The GVA from where the injection is.
Definition: exceptions.h:1020
#define LOG(fmt,...)
Definition: glue.h:61
32-bit selector.
Definition: glueiface.h:187
ACCESS_VIOLATION_EVENT
The type of event that caused the access violation.
Definition: winumcrash.c:67
void IntAlertFillVersionInfo(INTRO_VIOLATION_HEADER *Header)
Fills version information for an alert.
Definition: alerts.c:327
QWORD IntAlertProcGetFlags(QWORD ProtectionFlag, const void *Process, INTRO_ACTION_REASON Reason, QWORD AdditionalFlags)
Returns the flags for an alert.
Definition: alerts.c:425
INTRO_VIOLATION_HEADER Header
The alert header.
Definition: intro_types.h:1217
INTRO_ACTION_REASON Reason
The reason for which Action was taken.
Definition: intro_types.h:1195
Exposes the functions used to provide Windows Threads related support.
QWORD Cr3
Process PDBR. Includes PCID.
Definition: winprocess.h:98
#define EXCEPTION_ILLEGAL_INSTRUCTION
Definition: winumcrash.c:33
INTRO_GPRS Registers
Definition: intro_types.h:1119
#define ALERT_FLAG_DEP_VIOLATION
If set, the alert was generated by a DEP violation.
Definition: intro_types.h:684
#define EXCEPTION_ACCESS_VIOLATION
Definition: winumcrash.c:17
GENERIC_ALERT gAlert
Global alert buffer.
Definition: alerts.c:27
#define EXCEPTION_FLT_INEXACT_RESULT
Definition: winumcrash.c:24
#define EXCEPTION_DATATYPE_MISALIGNMENT
Definition: winumcrash.c:18
#define KI_EXCEPTION_GP_FAULT
General protection fault.
Definition: winumcrash.c:46
#define STATS_ENTER(id)
Definition: stats.h:153
INTRO_CPUCTX CpuContext
The context of the CPU that triggered the alert.
Definition: intro_types.h:1196
#define EXCEPTION_INVALID_HANDLE
Definition: winumcrash.c:38
INTSTATUS IntNotifyIntroEvent(INTRO_EVENT_TYPE EventClass, void *Param, size_t EventSize)
Notifies the integrator about an introspection alert.
Definition: glue.c:1042
#define ZONE_EXECUTE
Used for execute violation.
Definition: exceptions.h:736
BOOLEAN Valid
Set to True if the information in the structure is valid, False otherwise.
Definition: intro_types.h:1043
#define memzero(a, s)
Definition: introcrt.h:35
BOOLEAN Guest64
True if this is a 64-bit guest, False if it is a 32-bit guest.
Definition: guests.h:290
INTSTATUS IntExceptGetVictimEpt(void *Context, QWORD Gpa, QWORD Gva, INTRO_OBJECT_TYPE Type, DWORD ZoneFlags, EXCEPTION_VICTIM_ZONE *Victim)
Fills an EXCEPTION_VICTIM_ZONE with relevant information from an EPT violation.
Definition: exceptions.c:742
unsigned long long QWORD
Definition: intro_types.h:53
CHAR Name[IMAGE_BASE_NAME_LEN]
Process base name.
Definition: winprocess.h:108
#define IS_DEP_FAULT(Er)
Checks if a fault is an access violation caused by DEP.
Definition: winumcrash.c:81
An _EXCEPTION_RECORD structure used by 64-bit guests.
Definition: wddefs.h:1208
void IntExceptUserLogInformation(EXCEPTION_VICTIM_ZONE *Victim, EXCEPTION_UM_ORIGINATOR *Originator, INTRO_ACTION Action, INTRO_ACTION_REASON Reason)
Print the information about a user-mode violation, dumps the code-blocks and the injection buffer...
INTSTATUS IntTranslateVirtualAddress(QWORD Gva, QWORD Cr3, QWORD *PhysicalAddress)
Translates a guest virtual address to a guest physical address.
Definition: introcore.c:1999
#define TRUE
Definition: intro_types.h:30
#define IS_KERNEL_POINTER_WIN(is64, p)
Checks if a guest virtual address resides inside the Windows kernel address space.
Definition: wddefs.h:76
#define CONTROL_C_EXIT
Definition: winumcrash.c:40
PWIN_PROCESS_OBJECT IntWinProcFindObjectByCr3(QWORD Cr3)
Finds a process by its kernel CR3.
Definition: winprocesshp.c:195
QWORD LastExceptionRip
The RIP of the last exception that took place.
Definition: winprocess.h:180
static void IntWinFillRegsFromExceptionInfo(void const *TrapFrame, KEXCEPTION_FRAME64 const *ExFrame, IG_ARCH_REGS *Regs)
Reads the guest registers available inside the guest exception information structures.
Definition: winumcrash.c:161
#define KERNEL_MODE
The event was triggered inside the kernel space.
Definition: winumcrash.c:54
QWORD StackLimit
The stack limit for the thread that attempted the execution.
Definition: intro_types.h:1003
#define STILL_ACTIVE
Definition: winumcrash.c:16
INTRO_EXEC_CONTEXT ExecContext
Information about the instruction that triggered the alert.
Definition: intro_types.h:1309
#define WARNING(fmt,...)
Definition: glue.h:60
DWORD Pid
Process ID (the one used by Windows).
Definition: winprocess.h:100
#define EXCEPTION_FLT_DIVIDE_BY_ZERO
Definition: winumcrash.c:23
Sent when an EPT violation triggers an alert. See EVENT_EPT_VIOLATION.
Definition: intro_types.h:84
Describes the modified zone.
Definition: exceptions.h:893
DWORD CsType
The type of the code segment. Can be one of the IG_CS_TYPE values.
Definition: intro_types.h:1118
INTSTATUS IntWinThrGetUmStackBaseAndLimitFromTib(QWORD Tib, IG_CS_TYPE CsType, QWORD Cr3, QWORD *StackBase, QWORD *StackLimit)
Obtains the user mode stack base and stack limit values.
Definition: winthread.c:259
#define __forceinline
Definition: introtypes.h:61
uint32_t DWORD
Definition: intro_types.h:49
INTSTATUS IntDetGetArguments(void const *Detour, DWORD Argc, QWORD *Argv)
Reads multiple arguments from a detour.
Definition: detours.c:2296
BOOLEAN Valid
Set to True if the information in the structure is valid, False otherwise.
Definition: intro_types.h:965
#define EXCEPTION_BREAKPOINT
Definition: winumcrash.c:19
#define EXCEPTION_ARRAY_BOUNDS_EXCEEDED
Definition: winumcrash.c:21
DWORD Offset
The offset inside the page where the violation took place.
Definition: intro_types.h:1274
QWORD Cr3
The value of the guest CR3 register when the event was generated.
Definition: intro_types.h:970
#define ALERT_FLAG_SYSPROC
If set, the alert is on system process.
Definition: intro_types.h:673
DWORD SystemProcess
TRUE if this is a system process.
Definition: winprocess.h:136
GUEST_STATE gGuest
The current guest state.
Definition: guests.c:50
INTSTATUS IntVirtMemRead(QWORD Gva, DWORD Length, QWORD Cr3, void *Buffer, DWORD *RetLength)
Reads data from a guest virtual memory range.
Definition: introcore.c:627
DWORD ExceptionAddress
Definition: wddefs.h:1213
#define CODE_SEG_UM_32
32-bit user mode code selector
Definition: winumcrash.c:85
QWORD Rsp
The value of the guest RSP register at the moment of execution.
Definition: intro_types.h:1001
INTRO_ACTION Action
The action that was taken as the result of this alert.
Definition: intro_types.h:1194
INTSTATUS IntKernVirtMemRead(QWORD KernelGva, DWORD Length, void *Buffer, DWORD *RetLength)
Reads data from a guest kernel virtual memory range.
Definition: introcore.c:674
DWORD EFlags
Definition: wddefs.h:1161
#define ZONE_DEP_EXECUTION
Used for executions inside DEP zones.
Definition: exceptions.h:730
DWORD Edi
Definition: wddefs.h:971
QWORD VirtualPage
The guest virtual page in which the access was made.
Definition: intro_types.h:1272
DWORD LastException
The code of the last exception that took place.
Definition: winprocess.h:179
INTSTATUS IntExceptUserGetExecOriginator(void *Process, EXCEPTION_UM_ORIGINATOR *Originator)
This function is used to get the originator for heap execution.
#define EXCEPTION_STACK_OVERFLOW
Definition: winumcrash.c:35
QWORD StackBase
The stack base for the thread that attempted the execution.
Definition: intro_types.h:1002
#define INT_STATUS_INVALID_PARAMETER_1
Definition: introstatus.h:62
INTRO_PROCESS CurrentProcess
The current process.
Definition: intro_types.h:1197
#define EXCEPTION_FLT_OVERFLOW
Definition: winumcrash.c:26
VCPU_STATE * gVcpu
The state of the current VCPU.
Definition: guests.c:59
The action was blocked because there was no exception for it.
Definition: intro_types.h:189
DWORD Esi
Definition: wddefs.h:972
64-bit selector.
Definition: glueiface.h:188
DWORD ExceptionFlags
Definition: wddefs.h:1192
static BOOLEAN IntWinPreProcessException(DWORD ExceptionCode, DWORD *Status)
Translates an internal kernel exception code to an exception status known by used mode applications...
Definition: winumcrash.c:91
#define EXCEPTION_INVALID_DISPOSITION
Definition: winumcrash.c:36
UINT16 SegCs
Definition: wddefs.h:1157
Holds register state.
Definition: glueiface.h:30
#define KI_EXCEPTION_INTEGER_DIVIDE_BY_ZERO
Divide error.
Definition: winumcrash.c:50
INTRO_EXEC_INFO ExecInfo
Execution information. Valid only if Violation is IG_EPT_HOOK_EXECUTE.
Definition: intro_types.h:1260
Event structure for EPT violations.
Definition: intro_types.h:1215
DWORD ExceptionFlags
Definition: wddefs.h:1211
#define KI_EXCEPTION_INVALID_OP
Invalid opcode exceptions.
Definition: winumcrash.c:48
Execute-access hook.
Definition: glueiface.h:300
Exploitation for Client Execution.
Definition: intro_types.h:1157
DWORD Length
The length of the instruction.
Definition: intro_types.h:1004
Measures user mode crash handlers.
Definition: stats.h:54
#define IntWinGetCurrentProcess()
Definition: winprocesshp.h:20
BYTE RipCode[0x1000]
The contents of the guest memory page that contains the RIP at which the execution attempt was detect...
Definition: intro_types.h:1121
#define PAGE_MASK
Definition: pgtable.h:35
QWORD Rip
Where the write/exec came.
Definition: exceptions.h:1019
An _EXCEPTION_RECORD structure used by 64-bit guests.
Definition: wddefs.h:1188
Attempt to write inaccessible data.
Definition: winumcrash.c:70
INTRO_OBJECT_TYPE Type
The type of the accessed memory area.
Definition: intro_types.h:1237
#define EXCEPTION_INT_OVERFLOW
Definition: winumcrash.c:30
DWORD Ebx
Definition: wddefs.h:973
#define FALSE
Definition: intro_types.h:34
This structure describes a running process inside the guest.
Definition: winprocess.h:83