Bitdefender Hypervisor Memory Introspection
alerts.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020 Bitdefender
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 #include "alerts.h"
6 #ifdef INT_COMPILER_MSVC
7 #include "../../autogen/ver.h"
8 #endif // INT_COMPILER_MSVC
9 #include "codeblocks.h"
10 #include "crc32.h"
11 #include "guests.h"
12 #include "visibility.h"
13 #include "windrv_protected.h"
14 #include "winpe.h"
15 #include "winprocesshp.h"
16 #include "winthread.h"
17 
28 
29 
32  _In_ QWORD Cr3,
33  _Out_ INTRO_EXEC_CONTEXT *ExecContext
34  )
47 {
48  INTSTATUS status;
49  IG_ARCH_REGS const *pRegs = &gVcpu->Regs;
50 
51  if (0 == Cr3)
52  {
53  Cr3 = pRegs->Cr3;
54  }
55 
56  status = IntGetCurrentMode(IG_CURRENT_VCPU, &ExecContext->CsType);
57  if (!INT_SUCCESS(status))
58  {
59  ERROR("[ERROR] IntGetCurrentMode failed: 0x%08x\n", status);
60  return status;
61  }
62 
63  memcpy(&ExecContext->Registers, pRegs, sizeof(ExecContext->Registers));
64 
65  return IntVirtMemRead(pRegs->Rip & PAGE_MASK, sizeof(ExecContext->RipCode),
66  Cr3, ExecContext->RipCode, NULL);
67 }
68 
69 
72  _In_ QWORD Rip,
73  _In_ QWORD Cr3,
74  _In_ BOOLEAN Execute,
75  _Out_ INTRO_CODEBLOCKS *CodeBlocks
76  )
91 {
92  static CODE_BLOCK gCodeBlocks[PAGE_SIZE / sizeof(CODE_BLOCK)];
93  static CODE_BLOCK_PATTERN gPatterns[PAGE_SIZE / sizeof(CODE_BLOCK_PATTERN)];
94  INTSTATUS status;
95  DWORD startOffset, endOffset, totalSize;
96  DWORD patternSize, cbCount, csType;
97  DWORD ripCb, startCb;
98  BYTE level;
99  void *pCode;
100 
101  startOffset = endOffset = Rip & PAGE_OFFSET;
102  patternSize = ripCb = cbCount = 0;
103 
104  status = IntGetCurrentMode(IG_CURRENT_VCPU, &csType);
105  if (!INT_SUCCESS(status))
106  {
107  ERROR("[ERROR] IntGetCurrentMode failed: 0x%08x\n", status);
108  return status;
109  }
110 
111  if ((csType != IG_CS_TYPE_32B) && (csType != IG_CS_TYPE_64B))
112  {
113  ERROR("[ERROR] Unsupported CS type: %d\n", csType);
115  }
116 
117  if (!Execute)
118  {
119  if (startOffset > EXCEPTION_CODEBLOCKS_OFFSET)
120  {
121  if (endOffset + EXCEPTION_CODEBLOCKS_OFFSET < PAGE_SIZE)
122  {
123  startOffset -= EXCEPTION_CODEBLOCKS_OFFSET;
124  endOffset += EXCEPTION_CODEBLOCKS_OFFSET - 1;
125  }
126  else
127  {
128  startOffset = PAGE_SIZE - (EXCEPTION_CODEBLOCKS_OFFSET * 2);
129  endOffset = PAGE_SIZE - 1;
130  }
131  }
132  else
133  {
134  startOffset = 0;
135  endOffset = (EXCEPTION_CODEBLOCKS_OFFSET * 2) - 1;
136  }
137  }
138  else
139  {
140  endOffset += EXCEPTION_CODEBLOCKS_OFFSET - 1;
141  }
142 
144  {
146  {
147  level = cbLevelNormal;
148  }
149  else
150  {
151  level = cbLevelMedium;
152  }
153  }
154  else if (gGuest.OSType == introGuestLinux)
155  {
156  if (IS_KERNEL_POINTER_LIX(Rip))
157  {
158  level = cbLevelNormal;
159  }
160  else
161  {
162  level = cbLevelMedium;
163  }
164  }
165  else
166  {
168  }
169 
170  totalSize = endOffset - startOffset;
171 
172  memzero(gCodeBlocks, sizeof(gCodeBlocks));
173  memzero(gPatterns, sizeof(gPatterns));
174 
175  status = IntVirtMemMap((Rip & PAGE_MASK) + startOffset, totalSize, Cr3, 0, &pCode);
176  if (!INT_SUCCESS(status))
177  {
178  WARNING("[WARNING] IntVirtMemMap failed for RIP %llx and cr3 %llx: 0x%08x\n",
179  Rip & PAGE_MASK, Cr3, status);
180  return status;
181  }
182 
183  status = IntFragExtractCodePattern(pCode,
184  startOffset,
185  totalSize,
186  csType,
187  level,
188  PAGE_SIZE / sizeof(CODE_BLOCK_PATTERN),
189  gPatterns,
190  &patternSize);
191  if (!INT_SUCCESS(status))
192  {
193  if (status == INT_STATUS_DATA_BUFFER_TOO_SMALL)
194  {
195  WARNING("[WARNNING] Buffer too small to extract codeblocks (size %d): 0x%08x\n", totalSize, status);
196  }
197  else
198  {
199  ERROR("[ERROR] IntFragExtractCodePattern: 0x%08x\n", status);
200  }
201 
202  goto unmap_and_leave;
203  }
204 
205  if (patternSize < CODE_BLOCK_CHUNKS_COUNT)
206  {
207  WARNING("[WARNING] Could not extract enough code-blocks from RIP %llx: %d\n", Rip, patternSize);
209  goto unmap_and_leave;
210  }
211 
212  for (DWORD i = 0; i < patternSize - CODE_BLOCK_CHUNKS_COUNT; i++)
213  {
214  if (cbLevelNormal == level &&
215  (codeInsCall != gPatterns[i].Value &&
216  codeInsJmp != gPatterns[i].Value))
217  {
218  continue;
219  }
220 
221  if (cbLevelMedium == level &&
222  (codeInsCall != gPatterns[i].Value &&
223  codeInsJmp != gPatterns[i].Value &&
224  codeInsMovMem != gPatterns[i].Value &&
225  codeInsMovFsGs != gPatterns[i].Value))
226  {
227  continue;
228  }
229 
230  gCodeBlocks[cbCount].PivotInstruction = gPatterns[i].Value;
231  gCodeBlocks[cbCount].OffsetStart = gPatterns[i].Offset;
232 
233  // Extract from offset, CODE_BLOCK_CHUNKS_COUNT forward
234  for (DWORD j = 0; j < CODE_BLOCK_CHUNKS_COUNT; j++)
235  {
236  gCodeBlocks[cbCount].Chunks[j] = gPatterns[i + j].Value;
237  gCodeBlocks[cbCount].Size++;
238  }
239 
240  ++cbCount;
241 
242  if (cbCount >= sizeof(gCodeBlocks) / sizeof(gCodeBlocks[0]))
243  {
244  break;
245  }
246  }
247 
248  if (!Execute)
249  {
250  DWORD previous = gCodeBlocks[0].OffsetStart;
251  DWORD ripOffset = Rip & PAGE_OFFSET;
252 
253  // We must find where the RIP is inside the extracted codeblocks
254  for (DWORD i = 0; i < cbCount; i++)
255  {
256  if (i == 0 && gCodeBlocks[i].OffsetStart >= ripOffset)
257  {
258  ripCb = 0;
259  break;
260  }
261  else if (i == cbCount - 1 || (previous <= ripOffset && ripOffset <= gCodeBlocks[i].OffsetStart))
262  {
263  ripCb = i;
264  break;
265  }
266 
267  previous = gCodeBlocks[i].OffsetStart;
268  }
269 
270  if (cbCount <= ALERT_MAX_CODEBLOCKS || (ripCb <= ALERT_MAX_CODEBLOCKS / 2))
271  {
272  // [0; MIN(ALERT_MAX_CODEBLOCKS, cbCount)]
273  startCb = 0;
274  }
275  else if (cbCount - ripCb < ALERT_MAX_CODEBLOCKS)
276  {
277  // [cbCount - ALERT_MAX_CODEBLOCKS; cbCount]
278  startCb = cbCount >= ALERT_MAX_CODEBLOCKS ? cbCount - ALERT_MAX_CODEBLOCKS : 0;
279  }
280  else
281  {
282  // save before & after RIP
283  startCb = ripCb - (ALERT_MAX_CODEBLOCKS / 2);
284  }
285  }
286  else
287  {
288  startCb = 0;
289  }
290 
291  CodeBlocks->StartAddress = (Rip & PAGE_MASK) + gCodeBlocks[startCb].OffsetStart;
292  CodeBlocks->Rip = Rip;
293  CodeBlocks->Count = 0;
294 
295  for (DWORD i = startCb; i < cbCount; i++)
296  {
297  CodeBlocks->CodeBlocks[CodeBlocks->Count].Offset = (WORD)gCodeBlocks[i].OffsetStart;
298  CodeBlocks->CodeBlocks[CodeBlocks->Count].Pivot = gCodeBlocks[i].PivotInstruction;
299  CodeBlocks->CodeBlocks[CodeBlocks->Count].Value = Crc32Compute(gCodeBlocks[i].Chunks,
300  CODE_BLOCK_CHUNKS_COUNT,
302  if (i == ripCb)
303  {
304  CodeBlocks->RipCbIndex = CodeBlocks->Count;
305  }
306 
307  CodeBlocks->Count++;
308 
309  if (CodeBlocks->Count >= ALERT_MAX_CODEBLOCKS)
310  {
311  break;
312  }
313  }
314 
315  CodeBlocks->Valid = TRUE;
316 
317  status = INT_STATUS_SUCCESS;
318 
319 unmap_and_leave:
320  IntVirtMemUnmap(&pCode);
321 
322  return status;
323 }
324 
325 
326 void
329  )
336 {
337  INTSTATUS status;
338 
339  if (gGuest.Exceptions)
340  {
341  Header->VerInfo.ExceptionBuild = gGuest.Exceptions->Version.Build;
342  Header->VerInfo.ExceptionMajor = gGuest.Exceptions->Version.Major;
343  Header->VerInfo.ExceptionMinor = gGuest.Exceptions->Version.Minor;
344  }
345 
346  Header->VerInfo.IntroMajor = INTRO_VERSION_MAJOR;
347  Header->VerInfo.IntroMinor = INTRO_VERSION_MINOR;
348  Header->VerInfo.IntroRevision = INTRO_VERSION_REVISION;
349  Header->VerInfo.IntroBuildNumber = INTRO_VERSION_BUILDNUMBER;
350 
351  Header->VerInfo.OsVer = gGuest.OSVersion;
352 
353  Header->ViolationVersion = INTRO_VIOLATION_VERSION;
354 
355  status = IntCamiGetVersion(&Header->VerInfo.CamiMajor,
356  &Header->VerInfo.CamiMinor,
357  &Header->VerInfo.CamiBuildNumber);
358  if (!INT_SUCCESS(status))
359  {
360  WARNING("[WARNING] IntCamiGetVersion failed: 0x%08x\n", status);
361  }
362 }
363 
364 
365 QWORD
367  _In_ QWORD ProtectionFlag,
369  )
379 {
380  INTSTATUS status;
381  QWORD flags;
382  DWORD ring;
383 
384  flags = 0;
385  ring = 0;
386 
387  // Get the current ring.
388  status = IntGetCurrentRing(gVcpu->Index, &ring);
389  if (!INT_SUCCESS(status))
390  {
391  WARNING("[WARNING] IntGetCurrentRing failed: 0x%08x\n", status);
392  ring = IG_CS_RING_0;
393  }
394 
395  if (IG_CS_RING_0 != ring)
396  {
397  flags |= ALERT_FLAG_NOT_RING0;
398  }
399 
401  {
402  flags |= ALERT_FLAG_LINUX;
403  }
404 
405  if (Reason == introReasonAllowedFeedback || IntPolicyIsCoreOptionFeedback(ProtectionFlag))
406  {
407  flags |= ALERT_FLAG_FEEDBACK_ONLY;
408  }
409 
410  if (IntPolicyCoreIsOptionBeta(ProtectionFlag))
411  {
412  flags |= ALERT_FLAG_BETA;
413  }
414 
415  if (ProtectionFlag == INTRO_OPT_PROT_UM_SYS_PROCS)
416  {
417  flags |= ALERT_FLAG_SYSPROC;
418  }
419 
420  return flags;
421 }
422 
423 
424 QWORD
426  _In_ QWORD ProtectionFlag,
427  _In_opt_ const void *Process,
428  _In_ INTRO_ACTION_REASON Reason,
429  _In_ QWORD AdditionalFlags
430  )
444 {
445  INTSTATUS status;
446  QWORD flags;
447  DWORD ring;
448 
449  flags = 0;
450  ring = 0;
451 
452  // Get the current ring.
453  status = IntGetCurrentRing(gVcpu->Index, &ring);
454  if (!INT_SUCCESS(status))
455  {
456  WARNING("[WARNING] IntGetCurrentRing failed: 0x%08x\n", status);
457  ring = IG_CS_RING_0;
458  }
459 
460  if (IG_CS_RING_0 != ring)
461  {
462  flags |= ALERT_FLAG_NOT_RING0;
463  }
464 
466  {
467  flags |= ALERT_FLAG_LINUX;
468  }
469 
470  if (Reason == introReasonAllowedFeedback || IntPolicyProcIsFeedback(Process, ProtectionFlag))
471  {
472  flags |= ALERT_FLAG_FEEDBACK_ONLY;
473  }
474 
475  if (IntPolicyProcIsBeta(Process, ProtectionFlag))
476  {
477  flags |= ALERT_FLAG_BETA;
478  }
479 
481  {
482  flags |= ALERT_FLAG_SYSPROC;
483  }
484 
485  flags |= AdditionalFlags;
486 
487  return flags;
488 }
489 
490 
491 void
493  _In_ BOOLEAN CopyInstruction,
494  _Out_ INTRO_CPUCTX *CpuContext
495  )
504 {
505  CpuContext->Valid = TRUE;
506  CpuContext->Rip = gVcpu->Regs.Rip;
507  CpuContext->Cr3 = gVcpu->Regs.Cr3;
508  CpuContext->Cpu = gVcpu->Index;
509 
510  if (CopyInstruction)
511  {
512  NdToText(&gVcpu->Instruction,
513  CpuContext->Rip,
514  sizeof(CpuContext->Instruction),
515  CpuContext->Instruction);
516  }
517 }
518 
519 
520 void
522  _In_ const EXCEPTION_VICTIM_ZONE *Victim,
523  _Out_ INTRO_WRITE_INFO *WriteInfo
524  )
531 {
532  if (NULL == Victim)
533  {
534  return;
535  }
536 
537  WriteInfo->Size = Victim->WriteInfo.AccessSize;
538 
539  memcpy(WriteInfo->NewValue, Victim->WriteInfo.NewValue, MIN(sizeof(WriteInfo->NewValue), WriteInfo->Size));
540  memcpy(WriteInfo->OldValue, Victim->WriteInfo.OldValue, MIN(sizeof(WriteInfo->OldValue), WriteInfo->Size));
541 }
542 
543 
544 void
546  _In_ const EXCEPTION_VICTIM_ZONE *Victim,
547  _Out_ INTRO_READ_INFO *ReadInfo
548  )
555 {
556  if (NULL == Victim)
557  {
558  return;
559  }
560 
561  ReadInfo->Size = Victim->ReadInfo.AccessSize;
562 
563  memcpy(ReadInfo->Value, Victim->ReadInfo.Value, MIN(sizeof(ReadInfo->Value), ReadInfo->Size));
564 }
565 
566 
567 void
569  _In_ const EXCEPTION_VICTIM_ZONE *Victim,
570  _Out_ INTRO_EXEC_INFO *ExecInfo
571  )
578 {
579  if (NULL == Victim)
580  {
581  return;
582  }
583 
584  ExecInfo->Length = Victim->ExecInfo.Length;
585  ExecInfo->Rsp = Victim->ExecInfo.Rsp;
586  ExecInfo->StackBase = Victim->ExecInfo.StackBase;
587  ExecInfo->StackLimit = Victim->ExecInfo.StackLimit;
588 }
589 
590 
591 void
593  _In_ const WIN_DRIVER_OBJECT *DriverObject,
594  _Out_ INTRO_DRVOBJ *EventDrvObj
595  )
602 {
603  if (NULL == DriverObject)
604  {
605  return;
606  }
607 
608  wstrlcpy(EventDrvObj->Name, DriverObject->Name, ARRAYSIZE(EventDrvObj->Name));
609 
610  EventDrvObj->Valid = TRUE;
611  EventDrvObj->Address = DriverObject->DriverObjectGva;
612  EventDrvObj->Owner = DriverObject->Owner;
613 }
614 
615 
616 void
618  _In_opt_ const KERNEL_DRIVER *Driver,
619  _Out_ INTRO_MODULE *EventModule
620  )
627 {
628  if (NULL == Driver)
629  {
630  EventModule->Valid = FALSE;
631  return;
632  }
633 
634  if (NULL != Driver->Win.Path && Driver->Win.Path[0] != u'\0')
635  {
636  wstrlcpy(EventModule->Path, Driver->Win.Path, ARRAYSIZE(EventModule->Path));
637  }
638 
639  if (NULL != Driver->Name && *(WCHAR *)Driver->Name != u'\0')
640  {
641  wstrlcpy(EventModule->Name, Driver->Name, ARRAYSIZE(EventModule->Name));
642  }
643 
644  EventModule->Base = Driver->BaseVa;
645  EventModule->Size = (DWORD)Driver->Size;
646  EventModule->TimeDateStamp = Driver->Win.TimeDateStamp;
647 
648  EventModule->Valid = TRUE;
649 }
650 
651 
652 void
654  _In_opt_ const WIN_PROCESS_MODULE *Module,
655  _Out_ INTRO_MODULE *EventModule
656  )
663 {
664  if (NULL == Module)
665  {
666  EventModule->Valid = FALSE;
667  return;
668  }
669 
670  if (NULL != Module->Path && Module->Path->Path[0] != u'\0')
671  {
672  wstrlcpy(EventModule->Path, Module->Path->Path, ARRAYSIZE(EventModule->Path));
673  wstrlcpy(EventModule->Name, Module->Path->Name, ARRAYSIZE(EventModule->Name));
674  }
675 
676  EventModule->Base = Module->VirtualBase;
677  EventModule->Size = Module->Size;
678 
679  if (Module->Cache)
680  {
681  EventModule->TimeDateStamp = Module->Cache->Info.TimeDateStamp;
682  }
683 
684  EventModule->Valid = TRUE;
685 }
686 
687 
688 void
690  _In_ const WIN_PROCESS_OBJECT *Process,
691  _Out_ INTRO_PROCESS *EventProcess
692  )
699 {
700  INTSTATUS status;
701  QWORD ethreadGva = 0;
702 
703  if (NULL == Process)
704  {
705  return;
706  }
707 
708  EventProcess->Cr3 = Process->Cr3;
709  EventProcess->CreationTime = Process->CreationTime;
710  EventProcess->Pid = Process->Pid;
711 
712  strlcpy(EventProcess->ImageName, Process->Name, sizeof(EventProcess->ImageName));
713 
714  if (NULL != Process->Path)
715  {
716  wstrlcpy(EventProcess->Path, Process->Path->Path, ARRAYSIZE(EventProcess->Path));
717  }
718 
719  EventProcess->Valid = TRUE;
720 
721  status = IntWinThrGetCurrentThread(IG_CURRENT_VCPU, &ethreadGva);
722  if (INT_SUCCESS(status))
723  {
724  status = IntWinGetAccesTokenFromThread(ethreadGva, &EventProcess->SecurityInfo.WindowsToken);
725  if (INT_SUCCESS(status))
726  {
727  EventProcess->SecurityInfo.WindowsToken.ImpersonationToken = TRUE;
728  goto _skip_process_token;
729  }
730  }
731 
732  status = IntWinGetAccessTokenFromProcess(Process->Pid,
733  Process->EprocessAddress,
734  &EventProcess->SecurityInfo.WindowsToken);
735  if (!INT_SUCCESS(status))
736  {
737  EventProcess->SecurityInfo.WindowsToken.Valid = FALSE;
738  }
739  else
740  {
741  EventProcess->SecurityInfo.WindowsToken.Valid = TRUE;
742  }
743 
744 _skip_process_token:
745  if (Process->CommandLine != NULL)
746  {
747  strlcpy(EventProcess->CmdLine, Process->CommandLine, sizeof(EventProcess->CmdLine));
748  }
749 
750  EventProcess->Context = Process->Context;
751  EventProcess->Wow64 = !!Process->Wow64Process;
752 }
753 
754 
755 void
757  _In_ QWORD ProcessCr3,
758  _Out_ INTRO_PROCESS *EventProcess
759  )
768 {
769  WIN_PROCESS_OBJECT *pProc = IntWinProcFindObjectByCr3(ProcessCr3);
770  if (NULL == pProc)
771  {
772  EventProcess->Valid = FALSE;
773  return;
774  }
775 
776  IntAlertFillWinProcess(pProc, EventProcess);
777 }
778 
779 
780 void
782  _Out_ INTRO_PROCESS *EventProcess
783  )
791 {
792  INTSTATUS status;
793  QWORD cr3 = 0;
794 
795  status = IntCr3Read(IG_CURRENT_VCPU, &cr3);
796  if (!INT_SUCCESS(status))
797  {
798  EventProcess->Valid = FALSE;
799  return;
800  }
801 
802  IntAlertFillWinProcessByCr3(cr3, EventProcess);
803 }
804 
805 
806 void
808  _In_ const EXCEPTION_UM_ORIGINATOR *Originator,
809  _Out_ EVENT_EPT_VIOLATION *EptViolation
810  )
819 {
820  IntAlertFillWinUmModule(Originator->Library, &EptViolation->Originator.Module);
821 
822  if (Originator->Return.Library)
823  {
824  IntAlertFillWinUmModule(Originator->Return.Library, &EptViolation->Originator.ReturnModule);
825 
826  EptViolation->ReturnRip = Originator->Return.Rip;
827  }
828 }
829 
830 
831 void
833  _In_ const EXCEPTION_KM_ORIGINATOR *Originator,
834  _Out_ EVENT_EPT_VIOLATION *EptViolation
835  )
844 {
845  if (Originator->Original.Driver)
846  {
847  IntAlertFillWinKmModule(Originator->Original.Driver, &EptViolation->Originator.Module);
848 
849  memcpy(EptViolation->RipSectionName,
850  Originator->Original.Section,
851  sizeof(EptViolation->RipSectionName));
852  }
853 
854  if (Originator->Return.Driver)
855  {
856  IntAlertFillWinKmModule(Originator->Return.Driver, &EptViolation->Originator.ReturnModule);
857 
858  memcpy(EptViolation->ReturnRipSectionName,
859  Originator->Return.Section,
860  sizeof(EptViolation->ReturnRipSectionName));
861  }
862 
863  EptViolation->ReturnRip = Originator->Return.Rip;
864 }
865 
866 
867 void
869  _In_ const EXCEPTION_VICTIM_ZONE *Victim,
870  _Out_ EVENT_EPT_VIOLATION *EptViolation
871  )
879 {
880  switch (Victim->Object.Type)
881  {
883  case introObjectTypeSsdt:
886  {
888  {
889  break;
890  }
891 
892  if (Victim->Object.Module.Module)
893  {
894  KERNEL_DRIVER *pDriver = Victim->Object.Module.Module;
895  PWCHAR pModName = pDriver->Name;
896 
897  IntAlertFillWinKmModule(pDriver, &EptViolation->Victim.Module);
898 
899  if (IntWinDrvIsProtectedAv(pModName))
900  {
901  EptViolation->Header.Flags |= ALERT_FLAG_ANTIVIRUS;
902  }
903 
904  memcpy(EptViolation->ModifiedSectionName,
905  Victim->Object.Module.SectionName,
906  sizeof(EptViolation->ModifiedSectionName));
907  }
908 
909  // It shouldn't write more than 8 bytes...
910  if ((Victim->ZoneFlags & ZONE_LIB_IMPORTS) &&
911  IS_KERNEL_POINTER_WIN(gGuest.Guest64, Victim->WriteInfo.OldValue[0]))
912  {
913  KERNEL_DRIVER *pDriver;
914  INTSTATUS status;
915 
916  pDriver = IntDriverFindByAddress(Victim->WriteInfo.OldValue[0]);
917  if (NULL == pDriver)
918  {
919  ERROR("[ERROR] IntDriverFindByAddress for GVA 0x%016llx\n", Victim->WriteInfo.OldValue[0]);
920  break;
921  }
922 
923  if (pDriver->BaseVa != gGuest.KernelVa)
924  {
925  status = IntPeGetExportNameByRva(pDriver->BaseVa,
926  NULL,
927  (DWORD)(Victim->WriteInfo.OldValue[0] - pDriver->BaseVa),
929  EptViolation->FunctionName);
930  }
931  else
932  {
933  status = IntPeGetExportNameByRvaInBuffer(pDriver->BaseVa,
936  (DWORD)(Victim->WriteInfo.OldValue[0] - pDriver->BaseVa),
938  EptViolation->FunctionName);
939  }
940 
941  if (!INT_SUCCESS(status) && status != INT_STATUS_NOT_FOUND)
942  {
943  WARNING("[WARNING] IntPeGetExportNameByRva failed for module 0x%016llx, "
944  "RVA %x, GVA 0x%016llx: 0x%08x\n",
945  pDriver->BaseVa,
946  (DWORD)(Victim->WriteInfo.OldValue[0] - pDriver->BaseVa),
947  Victim->WriteInfo.OldValue[0],
948  status);
949  }
950  }
951  else if (Victim->Object.Type == introObjectTypeKmModule)
952  {
953  DWORD functionStart;
954  INTSTATUS status;
955 
956  if (Victim->Object.BaseAddress != gGuest.KernelVa)
957  {
958  status = IntPeFindFunctionStart(Victim->Object.BaseAddress,
959  NULL,
960  (DWORD)(Victim->Ept.Gva - Victim->Object.BaseAddress),
961  &functionStart);
962  }
963  else
964  {
965  // It's safe to use WinGuest->KernelBuffer here, as we already checked the OS type
966  // (and bailed out if we were on Linux)
967  status = IntPeFindFunctionStartInBuffer(Victim->Object.BaseAddress,
970  (DWORD)(Victim->Ept.Gva - Victim->Object.BaseAddress),
971  &functionStart);
972  }
973 
974  if (!INT_SUCCESS(status))
975  {
976  // maybe it's an exported variable
977  functionStart = (DWORD)(Victim->Ept.Gva - Victim->Object.BaseAddress);
978  }
979 
980  if (Victim->Object.BaseAddress != gGuest.KernelVa)
981  {
982  status = IntPeGetExportNameByRva(Victim->Object.BaseAddress,
983  NULL,
984  functionStart,
986  EptViolation->FunctionName);
987  }
988  else
989  {
990  status = IntPeGetExportNameByRvaInBuffer(Victim->Object.BaseAddress,
993  functionStart,
995  EptViolation->FunctionName);
996  }
997  if (!INT_SUCCESS(status) && status != INT_STATUS_NOT_FOUND)
998  {
999  WARNING("[WARNING] IntPeGetExportNameByRva failed for module 0x%016llx, "
1000  "RVA %x, GVA 0x%016llx: 0x%08x\n",
1001  Victim->Object.BaseAddress,
1002  (DWORD)(Victim->Ept.Gva - Victim->Object.BaseAddress),
1003  Victim->Ept.Gva,
1004  status);
1005  }
1006  }
1007 
1008  break;
1009  }
1010 
1013  {
1014  PWIN_DRIVER_OBJECT pDrvObj = Victim->Object.DriverObject;
1015 
1016  IntAlertFillDriverObject(pDrvObj, &EptViolation->Victim.DriverObject);
1017 
1018  if (IntWinDrvObjIsProtectedAv(pDrvObj->Name))
1019  {
1020  EptViolation->Header.Flags |= ALERT_FLAG_ANTIVIRUS;
1021  }
1022 
1023  break;
1024  }
1025 
1033  case introObjectTypeAcl:
1034  break;
1035 
1036  case introObjectTypeIdt:
1037  {
1038  EptViolation->Victim.IdtEntry = (BYTE)((Victim->Ept.Gva - Victim->Object.BaseAddress) /
1040  break;
1041  }
1042 
1044  {
1045  WIN_PROCESS_MODULE *pModule = Victim->Object.Library.Module;
1046 
1047  if (pModule != NULL)
1048  {
1049  IntAlertFillWinUmModule(pModule, &EptViolation->Victim.Module);
1050  }
1051 
1052  if (NULL != pModule && NULL == Victim->Object.Library.Export)
1053  {
1054  WINUM_CACHE_EXPORT *pExport = IntWinUmCacheGetExportFromRange(pModule, Victim->Ept.Gva, 0x20);
1055  if (pExport != NULL)
1056  {
1057  for (DWORD export = 0; export < MIN(ALERT_MAX_FUNCTIONS, pExport->NumberOfOffsets); export++)
1058  {
1059  strlcpy(EptViolation->Export.Name[export],
1060  pExport->Names[export],
1061  MIN(ALERT_MAX_FUNCTION_NAME_LEN, pExport->NameLens[export] + 1));
1062 
1063  EptViolation->Export.Hash[export] = Crc32String(pExport->Names[export], INITIAL_CRC_VALUE);
1064  }
1065 
1066  EptViolation->Export.Delta = (DWORD)(Victim->Ept.Gva - pModule->VirtualBase - pExport->Rva);
1067 
1068  strlcpy(EptViolation->FunctionName, pExport->Names[0],
1069  MIN(ALERT_MAX_FUNCTION_NAME_LEN, pExport->NameLens[0] + 1));
1070  EptViolation->Delta = (DWORD)(Victim->Ept.Gva - pModule->VirtualBase - pExport->Rva);
1071  EptViolation->FunctionNameHash = Crc32String(pExport->Names[0], INITIAL_CRC_VALUE);
1072  }
1073  }
1074  else if (Victim->Object.Library.Export != NULL)
1075  {
1076  WINUM_CACHE_EXPORT *pExport = Victim->Object.Library.Export;
1077 
1078  for (DWORD export = 0; export < MIN(ALERT_MAX_FUNCTIONS, pExport->NumberOfOffsets); export++)
1079  {
1080  strlcpy(EptViolation->Export.Name[export], pExport->Names[export],
1081  MIN(ALERT_MAX_FUNCTION_NAME_LEN, pExport->NameLens[export] + 1));
1082  EptViolation->Export.Hash[export] = Crc32String(pExport->Names[export], INITIAL_CRC_VALUE);
1083  }
1084 
1085  strlcpy(EptViolation->FunctionName,
1086  pExport->Names[0],
1087  MIN(ALERT_MAX_FUNCTION_NAME_LEN, pExport->NameLens[0] + 1));
1088 
1089  EptViolation->FunctionNameHash = Crc32String(pExport->Names[0], INITIAL_CRC_VALUE);
1090 
1091  if (pModule != NULL)
1092  {
1093  EptViolation->Export.Delta = (DWORD)(Victim->Ept.Gva - pModule->VirtualBase - pExport->Rva);
1094  EptViolation->Delta =
1095  (DWORD)(Victim->Ept.Gva - pModule->VirtualBase - Victim->Object.Library.Export->Rva);
1096  }
1097  }
1098 
1099  if (0 == EptViolation->FunctionName[0] && !IntWinUmCacheIsExportDirRead(pModule))
1100  {
1101  strlcpy(EptViolation->FunctionName, "<not_read>", sizeof(EptViolation->FunctionName));
1102  }
1103 
1104  break;
1105  }
1106 
1108  break;
1109 
1110  default:
1111  WARNING("[WARNING] Shouldn't reach here (for now). Type is %d...\n", Victim->Object.Type);
1112  return;
1113  }
1114 
1115  EptViolation->Victim.Type = Victim->Object.Type;
1116 
1117  EptViolation->Offset = Victim->Ept.Gva & PAGE_OFFSET;
1118  EptViolation->VirtualPage = Victim->Ept.Gva & PAGE_MASK;
1119  EptViolation->PhysicalPage = Victim->Ept.Gpa & PHYS_PAGE_MASK;
1120  EptViolation->HookStartVirtual = Victim->Object.BaseAddress;
1121 
1122  IntTranslateVirtualAddress(EptViolation->HookStartVirtual,
1123  gVcpu->Regs.Cr3,
1124  &EptViolation->HookStartPhysical);
1125 
1126  EptViolation->ZoneTypes = Victim->ZoneFlags;
1127 
1128  if (Victim->ZoneFlags & ZONE_EXECUTE)
1129  {
1130  EptViolation->Violation = IG_EPT_HOOK_EXECUTE;
1131 
1132  IntAlertFillExecInfo(Victim, &EptViolation->ExecInfo);
1133  }
1134  else if (Victim->ZoneFlags & ZONE_WRITE)
1135  {
1136  EptViolation->Violation = IG_EPT_HOOK_WRITE;
1137 
1138  IntAlertFillWriteInfo(Victim, &EptViolation->WriteInfo);
1139  }
1140  else if (Victim->ZoneFlags & ZONE_READ)
1141  {
1142  EptViolation->Violation = IG_EPT_HOOK_READ;
1143 
1144  IntAlertFillReadInfo(Victim, &EptViolation->ReadInfo);
1145  }
1146 }
1147 
1148 
1149 void
1151  _In_ const EXCEPTION_VICTIM_ZONE *Victim,
1152  _In_ const EXCEPTION_KM_ORIGINATOR *Originator,
1153  _Out_ EVENT_MSR_VIOLATION *MsrViolation
1154  )
1165 {
1166  MsrViolation->Victim.Msr = Victim->Msr.Msr;
1167 
1168  IntAlertFillWriteInfo(Victim, &MsrViolation->WriteInfo);
1169 
1170  IntAlertFillWinKmModule(Originator->Original.Driver, &MsrViolation->Originator.Module);
1171  IntAlertFillWinKmModule(Originator->Return.Driver, &MsrViolation->Originator.ReturnModule);
1172 }
1173 
1174 
1175 void
1177  _In_ const EXCEPTION_VICTIM_ZONE *Victim,
1178  _In_ const EXCEPTION_KM_ORIGINATOR *Originator,
1179  _Out_ EVENT_DTR_VIOLATION *DtrViolation
1180  )
1191 {
1192  DtrViolation->Victim.Type = Victim->Dtr.Type;
1193 
1194  IntAlertFillWriteInfo(Victim, &DtrViolation->WriteInfo);
1195 
1197  {
1198  IntAlertFillWinKmModule(Originator->Original.Driver, &DtrViolation->Originator.Module);
1199  IntAlertFillWinKmModule(Originator->Return.Driver, &DtrViolation->Originator.ReturnModule);
1200  }
1201  else if (gGuest.OSType == introGuestLinux)
1202  {
1203  IntAlertFillLixKmModule(Originator->Original.Driver, &DtrViolation->Originator.Module);
1204  IntAlertFillLixKmModule(Originator->Return.Driver, &DtrViolation->Originator.ReturnModule);
1205  }
1206 }
1207 
1208 
1209 void
1211  _In_ const EXCEPTION_VICTIM_ZONE *Victim,
1212  _In_ const EXCEPTION_KM_ORIGINATOR *Originator,
1213  _Out_ EVENT_CR_VIOLATION *CrViolation
1214  )
1225 {
1226  CrViolation->Victim.Cr = Victim->Cr.Cr;
1227  IntAlertFillWriteInfo(Victim, &CrViolation->WriteInfo);
1228 
1229  IntAlertFillWinKmModule(Originator->Original.Driver, &CrViolation->Originator.Module);
1230  IntAlertFillWinKmModule(Originator->Return.Driver, &CrViolation->Originator.ReturnModule);
1231 }
1232 
1233 
1234 void
1236  _In_ const KERNEL_DRIVER *Driver,
1237  _Out_ INTRO_MODULE *EventModule
1238  )
1245 {
1246  if (NULL == Driver)
1247  {
1248  return;
1249  }
1250 
1251  if (Driver->NameLength > 0 && *(char *)Driver->Name)
1252  {
1253  utf8toutf16(EventModule->Name, Driver->Name, ARRAYSIZE(EventModule->Name));
1254  }
1255 
1256  EventModule->Base = Driver->BaseVa;
1257  EventModule->Size = (DWORD)Driver->Size;
1258 
1259  EventModule->Valid = TRUE;
1260 }
1261 
1262 
1263 void
1265  _In_ const LIX_TASK_OBJECT *Task,
1266  _Out_ INTRO_PROCESS *EventProcess
1267  )
1274 {
1275  if (NULL == Task)
1276  {
1277  return;
1278  }
1279 
1280  EventProcess->Valid = TRUE;
1281  EventProcess->Cr3 = Task->Cr3;
1282  EventProcess->CreationTime = Task->CreationTime;
1283  EventProcess->Pid = Task->Pid;
1284 
1285  // NOTE: If this is really invalid, something critical happened
1286  if (Task->Comm[0] != 0)
1287  {
1288  strlcpy(EventProcess->ImageName, Task->Comm, sizeof(EventProcess->ImageName));
1289  }
1290  else if (Task->Path)
1291  {
1292  strlcpy(EventProcess->ImageName, Task->Path->Name, sizeof(EventProcess->ImageName));
1293  }
1294 
1295  if (Task->CmdLine)
1296  {
1297  strlcpy(EventProcess->CmdLine, Task->CmdLine, sizeof(EventProcess->CmdLine));
1298  }
1299 
1300  if (Task->Path)
1301  {
1302  utf8toutf16(EventProcess->Path, Task->Path->Path, ARRAYSIZE(EventProcess->Path));
1303  }
1304 
1305  EventProcess->Context = Task->Context;
1306 }
1307 
1308 
1309 void
1311  _Out_ INTRO_PROCESS *EventProcess
1312  )
1318 {
1320  if (NULL == pTask)
1321  {
1322  EventProcess->Valid = FALSE;
1323  return;
1324  }
1325 
1326  IntAlertFillLixProcess(pTask, EventProcess);
1327 }
1328 
1329 
1330 void
1332  _In_ const INTRONET_ENDPOINT *Connection,
1334  )
1341 {
1342  if (NULL == Connection)
1343  {
1344  return;
1345  }
1346 
1347  memzero(Event, sizeof(*Event));
1348 
1349  Event->Family = Connection->AddressFamily;
1350  Event->State = Connection->State;
1351 
1352  Event->LocalPort = Connection->LocalPort;
1353  Event->RemotePort = Connection->RemotePort;
1354 
1355  memcpy(&Event->LocalAddress, &Connection->LocalAddress, sizeof(Event->LocalAddress));
1356 
1357  memcpy(&Event->RemoteAddress, &Connection->RemoteAddress, sizeof(Event->RemoteAddress));
1358 
1360  {
1361  IntAlertFillWinProcess(Connection->OwnerProcess, &Event->Owner);
1362  }
1363  else if (introGuestLinux == gGuest.OSType)
1364  {
1365  IntAlertFillLixProcess(Connection->OwnerTask, &Event->Owner);
1366  }
1367 }
1368 
1369 
1370 INTSTATUS
1372  _In_ DPI_EXTRA_INFO *CollectedExtraInfo,
1374  _In_ WIN_PROCESS_OBJECT *VictimProcess,
1375  _Out_ INTRO_DPI_EXTRA_INFO *ExtraInfo
1376  )
1385 {
1386  if (NULL == CollectedExtraInfo)
1387  {
1389  }
1390 
1391  if (NULL == VictimProcess)
1392  {
1394  }
1395 
1396  if (PcType == INT_PC_VIOLATION_DPI_DEBUG_FLAG)
1397  {
1398  WIN_PROCESS_OBJECT *pDebugger = IntWinProcFindObjectByEprocess(VictimProcess->CreationInfo.DebuggerEprocess);
1399 
1400  IntAlertFillWinProcess(pDebugger, &ExtraInfo->DpiDebugFlag.Debugger);
1401  }
1402  else if (PcType == INT_PC_VIOLATION_DPI_PIVOTED_STACK)
1403  {
1404  DWORD sz = gGuest.Guest64 ? sizeof(KTRAP_FRAME64) : sizeof(KTRAP_FRAME32);
1405 
1406  ExtraInfo->DpiPivotedStack.CurrentStack = CollectedExtraInfo->DpiPivotedStackExtraInfo.CurrentStack;
1407  ExtraInfo->DpiPivotedStack.StackBase = CollectedExtraInfo->DpiPivotedStackExtraInfo.StackBase;
1408  ExtraInfo->DpiPivotedStack.StackLimit = CollectedExtraInfo->DpiPivotedStackExtraInfo.StackLimit;
1409  ExtraInfo->DpiPivotedStack.Wow64CurrentStack = CollectedExtraInfo->DpiPivotedStackExtraInfo.CurrentWow64Stack;
1410  ExtraInfo->DpiPivotedStack.Wow64StackBase = CollectedExtraInfo->DpiPivotedStackExtraInfo.Wow64StackBase;
1411  ExtraInfo->DpiPivotedStack.Wow64StackLimit = CollectedExtraInfo->DpiPivotedStackExtraInfo.Wow64StackLimit;
1412 
1413  IntVirtMemRead(CollectedExtraInfo->DpiPivotedStackExtraInfo.TrapFrameAddress,
1414  MIN(sz, sizeof(ExtraInfo->DpiPivotedStack.TrapFrameContent)),
1416  ExtraInfo->DpiPivotedStack.TrapFrameContent,
1417  NULL);
1418  }
1419  else if (PcType == INT_PC_VIOLATION_DPI_STOLEN_TOKEN)
1420  {
1422  CollectedExtraInfo->DpiStolenTokenExtraInfo.StolenFromEprocess);
1423 
1424  IntAlertFillWinProcess(pStolenFrom, &ExtraInfo->DpiStolenToken.StolenFrom);
1425  }
1426  else if (PcType == INT_PC_VIOLATION_DPI_HEAP_SPRAY)
1427  {
1428  WORD maxNumberOfHeapVals = 0;
1429  DWORD detectedPage = 0, maxPageHeapVals = 0;
1430 
1431  ExtraInfo->DpiHeapSpray.ShellcodeFlags = CollectedExtraInfo->DpiHeapSprayExtraInfo.ShellcodeFlags;
1432 
1433  for (DWORD val = 1; val <= HEAP_SPRAY_NR_PAGES; val++)
1434  {
1435  DWORD checkedPage = ((val << 24) | (val << 16) | (val << 8) | val) & PAGE_MASK;
1436 
1437  ExtraInfo->DpiHeapSpray.HeapPages[val - 1].Mapped =
1438  CollectedExtraInfo->DpiHeapSprayExtraInfo.HeapPages[val - 1].Mapped;
1439  ExtraInfo->DpiHeapSpray.HeapPages[val - 1].Detected =
1440  CollectedExtraInfo->DpiHeapSprayExtraInfo.HeapPages[val - 1].Detected;
1441  ExtraInfo->DpiHeapSpray.HeapPages[val - 1].HeapValCount =
1442  CollectedExtraInfo->DpiHeapSprayExtraInfo.HeapPages[val - 1].HeapValCount;
1443  ExtraInfo->DpiHeapSpray.HeapPages[val - 1].Offset =
1444  CollectedExtraInfo->DpiHeapSprayExtraInfo.HeapPages[val - 1].Offset;
1445  ExtraInfo->DpiHeapSpray.HeapPages[val - 1].Executable =
1446  CollectedExtraInfo->DpiHeapSprayExtraInfo.HeapPages[val - 1].Executable;
1447 
1448  if (CollectedExtraInfo->DpiHeapSprayExtraInfo.HeapPages[val - 1].Detected)
1449  {
1450  detectedPage = checkedPage;
1451  }
1452 
1453  // Use >= so that we are sure that we will get at least one page even if there are no heap values.
1454  if (CollectedExtraInfo->DpiHeapSprayExtraInfo.HeapPages[val - 1].HeapValCount >= maxNumberOfHeapVals &&
1455  CollectedExtraInfo->DpiHeapSprayExtraInfo.HeapPages[val - 1].Mapped)
1456  {
1457  maxNumberOfHeapVals = (WORD)CollectedExtraInfo->DpiHeapSprayExtraInfo.HeapPages[val - 1].HeapValCount;
1458  maxPageHeapVals = checkedPage;
1459  }
1460  }
1461 
1462  // At this point we might not have any detected page, but only pages exceeding the max heap values heuristic,
1463  // so don't bother to complete it if not needed.
1464  if (0 != detectedPage)
1465  {
1466  IntVirtMemRead(detectedPage, PAGE_SIZE, VictimProcess->Cr3, ExtraInfo->DpiHeapSpray.DetectedPage, NULL);
1467  }
1468 
1469  IntVirtMemRead(maxPageHeapVals,
1470  PAGE_SIZE,
1471  VictimProcess->Cr3,
1472  ExtraInfo->DpiHeapSpray.MaxHeapValPageContent,
1473  NULL);
1474  }
1475  else if (PcType == INT_PC_VIOLATION_DPI_TOKEN_PRIVS)
1476  {
1477  ExtraInfo->DpiTokenPrivs.OldEnabled = CollectedExtraInfo->DpiTokenPrivsExtraInfo.OldEnabled;
1478  ExtraInfo->DpiTokenPrivs.OldPresent = CollectedExtraInfo->DpiTokenPrivsExtraInfo.OldPresent;
1479  ExtraInfo->DpiTokenPrivs.NewEnabled = CollectedExtraInfo->DpiTokenPrivsExtraInfo.NewEnabled;
1480  ExtraInfo->DpiTokenPrivs.NewPresent = CollectedExtraInfo->DpiTokenPrivsExtraInfo.NewPresent;
1481  }
1482  else if (PcType == INT_PC_VIOLATION_DPI_THREAD_START)
1483  {
1484  ExtraInfo->DpiThreadStart.ShellcodeFlags = CollectedExtraInfo->DpiThreadStartExtraInfo.ShellcodeFlags;
1485  ExtraInfo->DpiThreadStart.StartAddress = CollectedExtraInfo->DpiThreadStartExtraInfo.StartAddress;
1486 
1487  IntVirtMemRead(CollectedExtraInfo->DpiThreadStartExtraInfo.StartAddress & PAGE_MASK,
1488  PAGE_SIZE,
1489  VictimProcess->Cr3,
1490  ExtraInfo->DpiThreadStart.StartPage,
1491  NULL);
1492  }
1493  else if (PcType == INT_PC_VIOLATION_DPI_SEC_DESC ||
1495  {
1496  if (PcType == INT_PC_VIOLATION_DPI_SEC_DESC)
1497  {
1499  CollectedExtraInfo->DpiSecDescAclExtraInfo.SecDescStolenFromEproc),
1500  &ExtraInfo->DpiSecDescAcl.SecDescStolenFrom);
1501 
1502  ExtraInfo->DpiSecDescAcl.NewPointerValue = CollectedExtraInfo->DpiSecDescAclExtraInfo.NewPtrValue;
1503  ExtraInfo->DpiSecDescAcl.OldPointerValue = CollectedExtraInfo->DpiSecDescAclExtraInfo.OldPtrValue;
1504  }
1505 
1506  COPY_ACL_TO_INTRO_ACL(CollectedExtraInfo->DpiSecDescAclExtraInfo.NewSacl,
1507  ExtraInfo->DpiSecDescAcl.NewSacl);
1508 
1509  COPY_ACL_TO_INTRO_ACL(CollectedExtraInfo->DpiSecDescAclExtraInfo.NewDacl,
1510  ExtraInfo->DpiSecDescAcl.NewDacl);
1511 
1512  COPY_ACL_TO_INTRO_ACL(CollectedExtraInfo->DpiSecDescAclExtraInfo.OldSacl,
1513  ExtraInfo->DpiSecDescAcl.OldSacl);
1514 
1515  COPY_ACL_TO_INTRO_ACL(CollectedExtraInfo->DpiSecDescAclExtraInfo.OldDacl,
1516  ExtraInfo->DpiSecDescAcl.OldDacl);
1517  }
1518  else
1519  {
1521  }
1522 
1523  return INT_STATUS_SUCCESS;
1524 }
uint16_t * PWCHAR
Definition: intro_types.h:63
#define _In_opt_
Definition: intro_sal.h:16
#define DESCRIPTOR_SIZE_32
Definition: processor.h:101
enum _INTRO_ACTION_REASON INTRO_ACTION_REASON
The reason for which an INTRO_ACTION was taken.
#define ALERT_FLAG_ANTIVIRUS
If set, the alert is on anti virus object.
Definition: intro_types.h:672
_Bool BOOLEAN
Definition: intro_types.h:58
#define _Out_
Definition: intro_sal.h:22
INTSTATUS IntPeFindFunctionStart(QWORD ImageBase, BYTE *ImageBaseBuffer, DWORD Rva, DWORD *BeginAddress)
Find the start address of a function, given a Rva pointing inside of it.
Definition: winpe.c:3297
#define HEAP_SPRAY_NR_PAGES
Definition: windpi.h:22
void IntAlertEptFillFromVictimZone(const EXCEPTION_VICTIM_ZONE *Victim, EVENT_EPT_VIOLATION *EptViolation)
Fills the victim information inside an EPT alert.
Definition: alerts.c:868
INTSTATUS IntVirtMemUnmap(void **HostPtr)
Unmaps a memory range previously mapped with IntVirtMemMap.
Definition: introcore.c:2234
The creation of a process was attempted while the parent had its heap sprayed.
Definition: intro_types.h:1666
Event structure for CR violation.
Definition: intro_types.h:1346
void IntAlertFillExecInfo(const EXCEPTION_VICTIM_ZONE *Victim, INTRO_EXEC_INFO *ExecInfo)
Fills the execution information for an alert.
Definition: alerts.c:568
A mov using a segment:offset.
Definition: codeblocks.h:37
Kernel module (ntoskrnl.exe, hal.dll, etc.).
Definition: intro_types.h:238
uint8_t BYTE
Definition: intro_types.h:47
Read-access hook.
Definition: glueiface.h:298
INTSTATUS IntFragExtractCodePattern(PBYTE Buffer, DWORD StartOffset, DWORD MaxBufferSize, IG_CS_TYPE CsType, CB_EXTRACT_LEVEL ExtractLevel, DWORD PatternSize, CODE_BLOCK_PATTERN *Pattern, DWORD *TotalExtracted)
Extract a pattern of code-blocks from the given code buffer.
Definition: codeblocks.c:990
WINDOWS_GUEST * gWinGuest
Global variable holding the state of a Windows guest.
Definition: winguest.c:37
#define ALERT_MAX_FUNCTIONS
The maximum number of functions included in an alert structure.
Definition: intro_types.h:702
IG_ARCH_REGS Regs
The current state of the guest registers.
Definition: guests.h:95
DWORD Index
The VCPU number.
Definition: guests.h:172
DWORD Crc32Compute(const void *Buffer, size_t Size, DWORD InitialCrc)
Computes the CRC for a byte array.
Definition: crc32.c:103
#define _In_
Definition: intro_sal.h:21
struct _CODE_BLOCK_PATTERN CODE_BLOCK_PATTERN
BYTE PivotInstruction
Definition: codeblocks.h:56
QWORD SystemCr3
The Cr3 used to map the kernel.
Definition: guests.h:211
#define INT_STATUS_SUCCESS
Definition: introstatus.h:54
Fast IO Dispatch (Windows only).
Definition: intro_types.h:236
void IntAlertFillConnection(const INTRONET_ENDPOINT *Connection, EVENT_CONNECTION_EVENT *Event)
Saves information about a guest connection in an event.
Definition: alerts.c:1331
Infinity hook modifications of WMI_LOGGER_CONTEXT.GetCpuClock.
Definition: intro_types.h:264
uint16_t WORD
Definition: intro_types.h:48
Non-conditional jump, of any kind.
Definition: codeblocks.h:28
DWORD Build
Definition: exceptions.h:141
User-mode non executable zone.
Definition: intro_types.h:247
void IntAlertFillWinProcessByCr3(QWORD ProcessCr3, INTRO_PROCESS *EventProcess)
Saves information about a Windows process inside an alert. The process is searched by its kernel CR3...
Definition: alerts.c:756
DWORD OffsetStart
The start of the extracted codeblock (not actually relevant)
Definition: codeblocks.h:53
QWORD BaseVa
The guest virtual address of the kernel module that owns this driver object.
Definition: drivers.h:41
QWORD IntPolicyGetProcProt(const void *Process)
Gets the protection policy for a process.
Definition: introcore.c:2661
DWORD NumberOfOffsets
Number of symbols pointing to the exported RVA.
Definition: winumcache.h:27
void IntAlertFillWinProcessCurrent(INTRO_PROCESS *EventProcess)
Saves information about the current Windows process inside an alert.
Definition: alerts.c:781
#define INT_SUCCESS(Status)
Definition: introstatus.h:42
INTSTATUS IntWinThrGetCurrentThread(DWORD CpuNumber, QWORD *EthreadAddress)
Get the ETHREAD structure address of the thread currently running on the given CPU.
Definition: winthread.c:26
WORD Size
Code block size, in patterns.
Definition: codeblocks.h:55
INTRO_PC_VIOLATION_TYPE
Process creation violation flags.
Definition: intro_types.h:1651
Exposes the types, constants and functions used to describe protected Windows Kernel modules and driv...
#define PAGE_OFFSET
Definition: pgtable.h:32
#define ARRAYSIZE(A)
Definition: introdefs.h:101
Holds code block patterns information.
Definition: intro_types.h:1041
INTSTATUS IntWinGetAccesTokenFromThread(QWORD EthreadGva, INTRO_WIN_TOKEN *Token)
Reads the contents of a _TOKEN Windows structure assigned to a thread.
Definition: visibility.c:524
#define ERROR(fmt,...)
Definition: glue.h:62
#define CODE_BLOCK_CHUNKS_COUNT
Number of chunks (CODE_INS) per codeblock.
Definition: codeblocks.h:43
Describes a user-mode originator.
Definition: exceptions.h:994
INTSTATUS IntWinGetAccessTokenFromProcess(DWORD ProcessId, QWORD EprocessGva, INTRO_WIN_TOKEN *Token)
Reads the contents of a _TOKEN Windows structure assigned to a process.
Definition: visibility.c:458
#define PHYS_PAGE_MASK
Definition: pgtable.h:38
int INTSTATUS
The status data type.
Definition: introstatus.h:24
void IntAlertFillDriverObject(const WIN_DRIVER_OBJECT *DriverObject, INTRO_DRVOBJ *EventDrvObj)
Saves driver object information inside an alert. Available only for Windows guests.
Definition: alerts.c:592
DWORD OSVersion
Os version.
Definition: guests.h:281
void IntAlertFillWinProcess(const WIN_PROCESS_OBJECT *Process, INTRO_PROCESS *EventProcess)
Saves information about a windows process inside an alert.
Definition: alerts.c:689
void IntAlertFillWinUmModule(const WIN_PROCESS_MODULE *Module, INTRO_MODULE *EventModule)
Fills information about a user mode module inside an alert.
Definition: alerts.c:653
#define INT_STATUS_NOT_FOUND
Definition: introstatus.h:284
void IntAlertEptFillFromKmOriginator(const EXCEPTION_KM_ORIGINATOR *Originator, EVENT_EPT_VIOLATION *EptViolation)
Fills kernel mode originator information inside an EPT alert.
Definition: alerts.c:832
QWORD IntAlertCoreGetFlags(QWORD ProtectionFlag, INTRO_ACTION_REASON Reason)
Returns the flags for an alert.
Definition: alerts.c:366
#define ALERT_MAX_FUNCTION_NAME_LEN
The maximum size of a function name inside an alert structure.
Definition: intro_types.h:703
Describes a kernel-mode originator.
Definition: exceptions.h:943
INTSTATUS IntCamiGetVersion(DWORD *MajorVersion, DWORD *MinorVersion, DWORD *BuildNumber)
Get the version of the loaded CAMI support file.
#define ALERT_FLAG_LINUX
Definition: intro_types.h:676
#define ALERT_MAX_CODEBLOCKS
The maximum number of code blocks included in an alert structure.
Definition: intro_types.h:705
BOOLEAN IntPolicyIsCoreOptionFeedback(QWORD Flag)
Checks if a core protection option is in feedback-only mode.
Definition: introcore.c:2829
void IntAlertFillWinKmModule(const KERNEL_DRIVER *Driver, INTRO_MODULE *EventModule)
Saves kernel module information inside an alert.
Definition: alerts.c:617
INTRO_GUEST_TYPE OSType
The type of the guest.
Definition: guests.h:278
INSTRUX Instruction
The current instruction, pointed by the guest RIP.
Definition: guests.h:88
QWORD VirtualBase
Guest virtual address of the loaded module.
Definition: winummodule.h:34
Process ACL (SACL/DACL) was modified.
Definition: intro_types.h:272
#define MIN(a, b)
Definition: introdefs.h:146
#define INTRO_OPT_PROT_UM_SYS_PROCS
Enable user-mode system processes protection (injection only).
Definition: intro_types.h:437
BOOLEAN IntPolicyProcIsBeta(const void *Process, QWORD Flag)
Checks if a process protection policy is in log-only mode.
Definition: introcore.c:2569
32-bit selector.
Definition: glueiface.h:187
Describes a kernel driver.
Definition: drivers.h:30
BYTE Chunks[CODE_BLOCK_CHUNKS_COUNT]
The actual CODE_INS values representing the instruction pattern.
Definition: codeblocks.h:58
void IntAlertFillCpuContext(BOOLEAN CopyInstruction, INTRO_CPUCTX *CpuContext)
Fills the current CPU context for an alert.
Definition: alerts.c:492
BOOLEAN IntPolicyCoreIsOptionBeta(QWORD Flag)
Checks if one of the kernel protection options is in log-only mode.
Definition: introcore.c:2603
void IntAlertFillLixKmModule(const KERNEL_DRIVER *Driver, INTRO_MODULE *EventModule)
Saves information about a kernel module inside an alert.
Definition: alerts.c:1235
Exposes the functions used to provide Windows Threads related support.
Token privileges.
Definition: intro_types.h:266
INTSTATUS IntGetCurrentMode(DWORD CpuNumber, DWORD *Mode)
Read the current CS type.
Definition: introcpu.c:977
#define ALERT_FLAG_BETA
If set, the alert is a BETA alert. No action was taken.
Definition: intro_types.h:671
void IntAlertFillVersionInfo(INTRO_VIOLATION_HEADER *Header)
Fills version information for an alert.
Definition: alerts.c:327
#define INITIAL_CRC_VALUE
Definition: introdefs.h:221
Hal interrupt controller.
Definition: intro_types.h:253
EXCEPTIONS * Exceptions
The exceptions that are currently loaded.
Definition: guests.h:392
static CODE_BLOCK gCodeBlocks[PAGE_SIZE/sizeof(CODE_BLOCK)]
Definition: serializers.c:622
#define IS_KERNEL_POINTER_LIX(p)
Definition: lixguest.h:11
#define EXCEPTION_CODEBLOCKS_OFFSET
The maximum offset for codeblocks extraction.
Definition: exceptions.h:53
GENERIC_ALERT gAlert
Global alert buffer.
Definition: alerts.c:27
#define IG_CURRENT_VCPU
For APIs that take a VCPU number as a parameter, this can be used to specify that the current VCPU sh...
Definition: glueiface.h:324
INTSTATUS IntPeGetExportNameByRva(QWORD ImageBase, BYTE *ImageBaseBuffer, DWORD Rva, DWORD ExportNameSize, CHAR *ExportName)
Find the export name a Rva lies in.
Definition: winpe.c:1312
struct _KTRAP_FRAME64 KTRAP_FRAME64
#define ZONE_EXECUTE
Used for execute violation.
Definition: exceptions.h:736
#define COPY_ACL_TO_INTRO_ACL(Acl, IntroAcl)
Converts an ACL to an INTRO_ACL.
Definition: winsecdesc.h:21
Holds information about a driver object.
Definition: windrvobj.h:13
The parent of a process has a stolen access token when it created the child.
Definition: intro_types.h:1663
#define memzero(a, s)
Definition: introcrt.h:35
Event structure for MSR violation.
Definition: intro_types.h:1316
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
An endpoint.
Definition: intronet.h:26
INTSTATUS IntTranslateVirtualAddress(QWORD Gva, QWORD Cr3, QWORD *PhysicalAddress)
Translates a guest virtual address to a guest physical address.
Definition: introcore.c:1999
The creation of a process was attempted with token privileges altered in a malicious way...
Definition: intro_types.h:1669
#define TRUE
Definition: intro_types.h:30
INTSTATUS IntPeGetExportNameByRvaInBuffer(QWORD ImageBase, BYTE *Buffer, DWORD BufferSize, DWORD Rva, DWORD ExportNameSize, CHAR *ExportName)
Find the export name a Rva lies in.
Definition: winpe.c:1457
#define IS_KERNEL_POINTER_WIN(is64, p)
Checks if a guest virtual address resides inside the Windows kernel address space.
Definition: wddefs.h:76
The parent of a process had a pivoted stack when it created the child.
Definition: intro_types.h:1660
This includes instructions until codeInsBt.
Definition: codeblocks.h:16
PWIN_PROCESS_OBJECT IntWinProcFindObjectByCr3(QWORD Cr3)
Finds a process by its kernel CR3.
Definition: winprocesshp.c:195
#define INT_STATUS_INVALID_INTERNAL_STATE
Definition: introstatus.h:272
struct _EXCEPTIONS::@26 Version
Loaded exceptions binary version.
Holds information about a memory read attempt.
Definition: intro_types.h:989
void * Name
The name of the driver.
Definition: drivers.h:54
QWORD KernelVa
The guest virtual address at which the kernel image.
Definition: guests.h:283
void IntAlertFillWriteInfo(const EXCEPTION_VICTIM_ZONE *Victim, INTRO_WRITE_INFO *WriteInfo)
Fills the write information for an alert.
Definition: alerts.c:521
void IntAlertFillReadInfo(const EXCEPTION_VICTIM_ZONE *Victim, INTRO_READ_INFO *ReadInfo)
Fills the read information for an alert.
Definition: alerts.c:545
Holds the context in which an execution attempt was detected.
Definition: intro_types.h:1116
Holds information about a memory write attempt.
Definition: intro_types.h:978
#define DESCRIPTOR_SIZE_64
Definition: processor.h:102
QWORD IntAlertProcGetFlags(QWORD ProtectionFlag, const void *Process, INTRO_ACTION_REASON Reason, QWORD AdditionalFlags)
Returns the flags for an alert.
Definition: alerts.c:425
size_t strlcpy(char *dst, const char *src, size_t dest_size)
Definition: introcrt.c:1093
void IntAlertDtrFill(const EXCEPTION_VICTIM_ZONE *Victim, const EXCEPTION_KM_ORIGINATOR *Originator, EVENT_DTR_VIOLATION *DtrViolation)
Saves information about a DTR write attempt in an event.
Definition: alerts.c:1176
#define WARNING(fmt,...)
Definition: glue.h:60
Event structure for GDTR/IDTR descriptor tables modifications.
Definition: intro_types.h:1625
#define ALERT_FLAG_NOT_RING0
If set, the alert was triggered in ring 1, 2 or 3.
Definition: intro_types.h:674
#define PAGE_SIZE
Definition: common.h:70
Holds all the alert types.
Definition: alerts.h:14
Describes the modified zone.
Definition: exceptions.h:893
Exception Table (Linux-only).
Definition: intro_types.h:258
This includes instructions until codeInsFlags.
Definition: codeblocks.h:17
#define INT_STATUS_DATA_BUFFER_TOO_SMALL
Definition: introstatus.h:194
DWORD Rva
The RVA of this export.
Definition: winumcache.h:23
uint16_t WCHAR
Definition: intro_types.h:63
Executions inside the SharedUserData region.
Definition: intro_types.h:267
The Virtualization exception agent injected inside the guest.
Definition: intro_types.h:259
BOOLEAN IntWinUmCacheIsExportDirRead(WIN_PROCESS_MODULE *Module)
Checks if the exports directory of the given module has been read.
Definition: winumcache.c:1063
uint32_t DWORD
Definition: intro_types.h:49
DWORD KernelBufferSize
The size of the KernelBuffer.
Definition: winguest.h:852
void IntAlertFillLixCurrentProcess(INTRO_PROCESS *EventProcess)
Saves the current Linux process inside an event.
Definition: alerts.c:1310
Common violation header.
Definition: intro_types.h:1189
User-mode library.
Definition: intro_types.h:248
void IntAlertCrFill(const EXCEPTION_VICTIM_ZONE *Victim, const EXCEPTION_KM_ORIGINATOR *Originator, EVENT_CR_VIOLATION *CrViolation)
Saves information about a CR write attempt in an event.
Definition: alerts.c:1210
PWCHAR Name
NULL-terminated wide-char string containing the name of the driver, as taken from the guest driver ob...
Definition: windrvobj.h:30
The action was allowed, but it has the BETA flag (Introcore is in log-only mode). ...
Definition: intro_types.h:185
Call, of any kind.
Definition: codeblocks.h:29
void IntAlertEptFillFromUmOriginator(const EXCEPTION_UM_ORIGINATOR *Originator, EVENT_EPT_VIOLATION *EptViolation)
Fills user mode originator information inside an EPT alert.
Definition: alerts.c:807
__must_check INTSTATUS IntVirtMemMap(QWORD Gva, DWORD Length, QWORD Cr3, DWORD Flags, void **HostPtr)
Maps a guest virtual memory range inside Introcore virtual address space.
Definition: introcore.c:2134
DWORD NameLens[MAX_OFFSETS_PER_NAME]
Length of each name pointing to this RVA.
Definition: winumcache.h:25
MM Mm
Guest memory information, such as paging mode, system Cr3 value, etc.
Definition: guests.h:374
#define ALERT_FLAG_SYSPROC
If set, the alert is on system process.
Definition: intro_types.h:673
Self mapping index in PDBR.
Definition: intro_types.h:254
The parent of a process tried to obtain debug privileges over the child.
Definition: intro_types.h:1657
The parent of a process has an altered security descriptor pointer.
Definition: intro_types.h:1675
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
#define INT_STATUS_INVALID_DATA_TYPE
Definition: introstatus.h:139
#define ALERT_FLAG_FEEDBACK_ONLY
If set, the alert is a feedback only alert.
Definition: intro_types.h:683
SSDT (Windows only).
Definition: intro_types.h:235
size_t wstrlcpy(WCHAR *dst, const WCHAR *src, size_t dest_size)
Definition: introcrt.c:1131
PWIN_PROCESS_OBJECT IntWinProcFindObjectByEprocess(QWORD Eprocess)
Finds a process by the address of its _EPROCESS structure.
Definition: winprocesshp.c:96
The thread which created the process has started execution on some suspicious code.
Definition: intro_types.h:1672
BOOLEAN IntPolicyProcIsFeedback(const void *Process, QWORD Flag)
Checks if a process protection policy is in feedback-only mode.
Definition: introcore.c:2627
KERNEL_DRIVER * IntDriverFindByAddress(QWORD Gva)
Returns the driver in which Gva resides.
Definition: drivers.c:164
struct _CODE_BLOCK CODE_BLOCK
#define ZONE_READ
Used for read violation.
Definition: exceptions.h:735
WINUM_CACHE_EXPORT * IntWinUmCacheGetExportFromRange(WIN_PROCESS_MODULE *Module, QWORD Gva, DWORD Length)
Tries to find an export in the range [Gva - Length, Gva].
Definition: winumcache.c:225
INTSTATUS IntAlertFillExecContext(QWORD Cr3, INTRO_EXEC_CONTEXT *ExecContext)
Fills the current execution context.
Definition: alerts.c:31
INTSTATUS IntCr3Read(DWORD CpuNumber, QWORD *Cr3Value)
Reads the value of the guest CR3.
Definition: introcpu.c:415
Holds information about an execution attempt.
Definition: intro_types.h:999
PCHAR Names[MAX_OFFSETS_PER_NAME]
The names pointing to this RVA. Each name will point inside the Names structure inside WINUM_CACHE_EX...
Definition: winumcache.h:31
INTSTATUS IntAlertFillDpiExtraInfo(DPI_EXTRA_INFO *CollectedExtraInfo, INTRO_PC_VIOLATION_TYPE PcType, WIN_PROCESS_OBJECT *VictimProcess, INTRO_DPI_EXTRA_INFO *ExtraInfo)
Fills the collected DPI extra information.
Definition: alerts.c:1371
BYTE * KernelBuffer
A buffer containing the entire kernel image.
Definition: winguest.h:851
#define INT_STATUS_INVALID_PARAMETER_1
Definition: introstatus.h:62
#define INT_STATUS_NOT_SUPPORTED
Definition: introstatus.h:287
Describes a driver object.
Definition: intro_types.h:945
VCPU_STATE * gVcpu
The state of the current VCPU.
Definition: guests.c:59
BOOLEAN IntWinDrvIsProtectedAv(const WCHAR *Driver)
Check wether a kernel driver is a known and protected antivirus.
LIX_TASK_OBJECT * IntLixTaskGetCurrent(DWORD CpuNumber)
Finds the task that is currently running on the given CPU.
Definition: lixprocess.c:858
DWORD Crc32String(const char *String, DWORD InitialCrc)
Computes the CRC for a NULL-terminated utf-8 string.
Definition: crc32.c:200
Event structure for connections.
Definition: intro_types.h:2006
64-bit selector.
Definition: glueiface.h:188
Holds the CPU context for an event.
Definition: intro_types.h:962
INTSTATUS IntPeFindFunctionStartInBuffer(QWORD ImageBase, BYTE *Buffer, DWORD BufferSize, DWORD Rva, DWORD *BeginAddress)
Find the start address of a function, given a Rva pointing inside of it.
Definition: winpe.c:3624
#define ZONE_LIB_IMPORTS
Used for the imports of a dll, driver, etc.
Definition: exceptions.h:721
Holds register state.
Definition: glueiface.h:30
Event structure for EPT violations.
Definition: intro_types.h:1215
INTSTATUS IntGetCurrentRing(DWORD CpuNumber, DWORD *Ring)
Read the current protection level.
Definition: introcpu.c:959
A mov involving memory (either as the destination or as the source).
Definition: codeblocks.h:35
Execute-access hook.
Definition: glueiface.h:300
void IntAlertMsrFill(const EXCEPTION_VICTIM_ZONE *Victim, const EXCEPTION_KM_ORIGINATOR *Originator, EVENT_MSR_VIOLATION *MsrViolation)
Saves information about a MSR write attempt in an event.
Definition: alerts.c:1150
The parent of a process has an altered access control entry (inside SACL or DACL).
Definition: intro_types.h:1678
#define INTRO_VIOLATION_VERSION
Violation header version.
Definition: intro_types.h:788
Structure for keeping the relevant DPI violation information.
Definition: intro_types.h:1685
Describes a user-mode or kernel-mode module.
Definition: intro_types.h:925
Describes a guest process.
Definition: intro_types.h:901
BOOLEAN IntWinDrvObjIsProtectedAv(const WCHAR *DrvObj)
Checks if a driver object belongs to a known and protected antivirus.
Process security descriptor pointer.
Definition: intro_types.h:271
Write-access hook.
Definition: glueiface.h:299
#define PAGE_MASK
Definition: pgtable.h:35
#define ZONE_WRITE
Used for write violation.
Definition: exceptions.h:734
WCHAR * utf8toutf16(WCHAR *Destination, const char *Source, DWORD DestinationMaxLength)
Definition: introcrt.c:507
void IntAlertFillLixProcess(const LIX_TASK_OBJECT *Task, INTRO_PROCESS *EventProcess)
Saves information about a Linux process inside an event.
Definition: alerts.c:1264
INTSTATUS IntAlertFillCodeBlocks(QWORD Rip, QWORD Cr3, BOOLEAN Execute, INTRO_CODEBLOCKS *CodeBlocks)
Fills the code blocks pattern for an alert.
Definition: alerts.c:71
#define FALSE
Definition: intro_types.h:34
This structure describes a running process inside the guest.
Definition: winprocess.h:83
#define INT_STATUS_INVALID_PARAMETER_3
Definition: introstatus.h:68