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->WriteInfo.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 
1031  break;
1032 
1033  case introObjectTypeIdt:
1034  {
1035  EptViolation->Victim.IdtEntry = (BYTE)((Victim->Ept.Gva - Victim->Object.BaseAddress) /
1037  break;
1038  }
1039 
1041  {
1042  WIN_PROCESS_MODULE *pModule = Victim->Object.Library.Module;
1043 
1044  if (pModule != NULL)
1045  {
1046  IntAlertFillWinUmModule(pModule, &EptViolation->Victim.Module);
1047  }
1048 
1049  if (NULL != pModule && NULL == Victim->Object.Library.Export)
1050  {
1051  WINUM_CACHE_EXPORT *pExport = IntWinUmCacheGetExportFromRange(pModule, Victim->Ept.Gva, 0x20);
1052  if (pExport != NULL)
1053  {
1054  for (DWORD export = 0; export < MIN(ALERT_MAX_FUNCTIONS, pExport->NumberOfOffsets); export++)
1055  {
1056  strlcpy(EptViolation->Export.Name[export],
1057  pExport->Names[export],
1058  MIN(ALERT_MAX_FUNCTION_NAME_LEN, pExport->NameLens[export] + 1));
1059 
1060  EptViolation->Export.Hash[export] = Crc32String(pExport->Names[export], INITIAL_CRC_VALUE);
1061  }
1062 
1063  EptViolation->Export.Delta = (DWORD)(Victim->Ept.Gva - pModule->VirtualBase - pExport->Rva);
1064 
1065  strlcpy(EptViolation->FunctionName, pExport->Names[0],
1066  MIN(ALERT_MAX_FUNCTION_NAME_LEN, pExport->NameLens[0] + 1));
1067  EptViolation->Delta = (DWORD)(Victim->Ept.Gva - pModule->VirtualBase - pExport->Rva);
1068  EptViolation->FunctionNameHash = Crc32String(pExport->Names[0], INITIAL_CRC_VALUE);
1069  }
1070  }
1071  else if (Victim->Object.Library.Export != NULL)
1072  {
1073  WINUM_CACHE_EXPORT *pExport = Victim->Object.Library.Export;
1074 
1075  for (DWORD export = 0; export < MIN(ALERT_MAX_FUNCTIONS, pExport->NumberOfOffsets); export++)
1076  {
1077  strlcpy(EptViolation->Export.Name[export], pExport->Names[export],
1078  MIN(ALERT_MAX_FUNCTION_NAME_LEN, pExport->NameLens[export] + 1));
1079  EptViolation->Export.Hash[export] = Crc32String(pExport->Names[export], INITIAL_CRC_VALUE);
1080  }
1081 
1082  strlcpy(EptViolation->FunctionName,
1083  pExport->Names[0],
1084  MIN(ALERT_MAX_FUNCTION_NAME_LEN, pExport->NameLens[0] + 1));
1085 
1086  EptViolation->FunctionNameHash = Crc32String(pExport->Names[0], INITIAL_CRC_VALUE);
1087 
1088  if (pModule != NULL)
1089  {
1090  EptViolation->Export.Delta = (DWORD)(Victim->Ept.Gva - pModule->VirtualBase - pExport->Rva);
1091  EptViolation->Delta =
1092  (DWORD)(Victim->Ept.Gva - pModule->VirtualBase - Victim->Object.Library.Export->Rva);
1093  }
1094  }
1095 
1096  if (0 == EptViolation->FunctionName[0] && !IntWinUmCacheIsExportDirRead(pModule))
1097  {
1098  strlcpy(EptViolation->FunctionName, "<not_read>", sizeof(EptViolation->FunctionName));
1099  }
1100 
1101  break;
1102  }
1103 
1105  break;
1106 
1107  default:
1108  WARNING("[WARNING] Shouldn't reach here (for now). Type is %d...\n", Victim->Object.Type);
1109  return;
1110  }
1111 
1112  EptViolation->Victim.Type = Victim->Object.Type;
1113 
1114  EptViolation->Offset = Victim->Ept.Gva & PAGE_OFFSET;
1115  EptViolation->VirtualPage = Victim->Ept.Gva & PAGE_MASK;
1116  EptViolation->PhysicalPage = Victim->Ept.Gpa & PHYS_PAGE_MASK;
1117  EptViolation->HookStartVirtual = Victim->Object.BaseAddress;
1118 
1119  IntTranslateVirtualAddress(EptViolation->HookStartVirtual,
1120  gVcpu->Regs.Cr3,
1121  &EptViolation->HookStartPhysical);
1122 
1123  EptViolation->ZoneTypes = Victim->ZoneFlags;
1124 
1125  if (Victim->ZoneFlags & ZONE_EXECUTE)
1126  {
1127  EptViolation->Violation = IG_EPT_HOOK_EXECUTE;
1128 
1129  IntAlertFillExecInfo(Victim, &EptViolation->ExecInfo);
1130  }
1131  else if (Victim->ZoneFlags & ZONE_WRITE)
1132  {
1133  EptViolation->Violation = IG_EPT_HOOK_WRITE;
1134 
1135  IntAlertFillWriteInfo(Victim, &EptViolation->WriteInfo);
1136  }
1137  else if (Victim->ZoneFlags & ZONE_READ)
1138  {
1139  EptViolation->Violation = IG_EPT_HOOK_READ;
1140 
1141  IntAlertFillReadInfo(Victim, &EptViolation->ReadInfo);
1142  }
1143 }
1144 
1145 
1146 void
1148  _In_ const EXCEPTION_VICTIM_ZONE *Victim,
1149  _In_ const EXCEPTION_KM_ORIGINATOR *Originator,
1150  _Out_ EVENT_MSR_VIOLATION *MsrViolation
1151  )
1162 {
1163  MsrViolation->Victim.Msr = Victim->Msr.Msr;
1164 
1165  IntAlertFillWriteInfo(Victim, &MsrViolation->WriteInfo);
1166 
1167  IntAlertFillWinKmModule(Originator->Original.Driver, &MsrViolation->Originator.Module);
1168  IntAlertFillWinKmModule(Originator->Return.Driver, &MsrViolation->Originator.ReturnModule);
1169 }
1170 
1171 
1172 void
1174  _In_ const EXCEPTION_VICTIM_ZONE *Victim,
1175  _In_ const EXCEPTION_KM_ORIGINATOR *Originator,
1176  _Out_ EVENT_DTR_VIOLATION *DtrViolation
1177  )
1188 {
1189  DtrViolation->Victim.Type = Victim->Dtr.Type;
1190 
1191  IntAlertFillWriteInfo(Victim, &DtrViolation->WriteInfo);
1192 
1194  {
1195  IntAlertFillWinKmModule(Originator->Original.Driver, &DtrViolation->Originator.Module);
1196  IntAlertFillWinKmModule(Originator->Return.Driver, &DtrViolation->Originator.ReturnModule);
1197  }
1198  else if (gGuest.OSType == introGuestLinux)
1199  {
1200  IntAlertFillLixKmModule(Originator->Original.Driver, &DtrViolation->Originator.Module);
1201  IntAlertFillLixKmModule(Originator->Return.Driver, &DtrViolation->Originator.ReturnModule);
1202  }
1203 }
1204 
1205 
1206 void
1208  _In_ const EXCEPTION_VICTIM_ZONE *Victim,
1209  _In_ const EXCEPTION_KM_ORIGINATOR *Originator,
1210  _Out_ EVENT_CR_VIOLATION *CrViolation
1211  )
1222 {
1223  CrViolation->Victim.Cr = Victim->Cr.Cr;
1224  IntAlertFillWriteInfo(Victim, &CrViolation->WriteInfo);
1225 
1226  IntAlertFillWinKmModule(Originator->Original.Driver, &CrViolation->Originator.Module);
1227  IntAlertFillWinKmModule(Originator->Return.Driver, &CrViolation->Originator.ReturnModule);
1228 }
1229 
1230 
1231 void
1233  _In_ const KERNEL_DRIVER *Driver,
1234  _Out_ INTRO_MODULE *EventModule
1235  )
1242 {
1243  if (NULL == Driver)
1244  {
1245  return;
1246  }
1247 
1248  if (Driver->NameLength > 0 && *(char *)Driver->Name)
1249  {
1250  utf8toutf16(EventModule->Name, Driver->Name, ARRAYSIZE(EventModule->Name));
1251  }
1252 
1253  EventModule->Base = Driver->BaseVa;
1254  EventModule->Size = (DWORD)Driver->Size;
1255 
1256  EventModule->Valid = TRUE;
1257 }
1258 
1259 
1260 void
1262  _In_ const LIX_TASK_OBJECT *Task,
1263  _Out_ INTRO_PROCESS *EventProcess
1264  )
1271 {
1272  if (NULL == Task)
1273  {
1274  return;
1275  }
1276 
1277  EventProcess->Valid = TRUE;
1278  EventProcess->Cr3 = Task->Cr3;
1279  EventProcess->CreationTime = Task->CreationTime;
1280  EventProcess->Pid = Task->Pid;
1281 
1282  // NOTE: If this is really invalid, something critical happened
1283  if (Task->Comm[0] != 0)
1284  {
1285  strlcpy(EventProcess->ImageName, Task->Comm, sizeof(EventProcess->ImageName));
1286  }
1287  else if (Task->Path)
1288  {
1289  strlcpy(EventProcess->ImageName, Task->Path->Name, sizeof(EventProcess->ImageName));
1290  }
1291 
1292  if (Task->CmdLine)
1293  {
1294  strlcpy(EventProcess->CmdLine, Task->CmdLine, sizeof(EventProcess->CmdLine));
1295  }
1296 
1297  if (Task->Path)
1298  {
1299  utf8toutf16(EventProcess->Path, Task->Path->Path, ARRAYSIZE(EventProcess->Path));
1300  }
1301 
1302  EventProcess->Context = Task->Context;
1303 }
1304 
1305 
1306 void
1308  _Out_ INTRO_PROCESS *EventProcess
1309  )
1315 {
1317  if (NULL == pTask)
1318  {
1319  EventProcess->Valid = FALSE;
1320  return;
1321  }
1322 
1323  IntAlertFillLixProcess(pTask, EventProcess);
1324 }
1325 
1326 
1327 void
1329  _In_ const INTRONET_ENDPOINT *Connection,
1331  )
1338 {
1339  if (NULL == Connection)
1340  {
1341  return;
1342  }
1343 
1344  memzero(Event, sizeof(*Event));
1345 
1346  Event->Family = Connection->AddressFamily;
1347  Event->State = Connection->State;
1348 
1349  Event->LocalPort = Connection->LocalPort;
1350  Event->RemotePort = Connection->RemotePort;
1351 
1352  memcpy(&Event->LocalAddress, &Connection->LocalAddress, sizeof(Event->LocalAddress));
1353 
1354  memcpy(&Event->RemoteAddress, &Connection->RemoteAddress, sizeof(Event->RemoteAddress));
1355 
1357  {
1358  IntAlertFillWinProcess(Connection->OwnerProcess, &Event->Owner);
1359  }
1360  else if (introGuestLinux == gGuest.OSType)
1361  {
1362  IntAlertFillLixProcess(Connection->OwnerTask, &Event->Owner);
1363  }
1364 }
1365 
1366 
1367 INTSTATUS
1369  _In_ DPI_EXTRA_INFO *CollectedExtraInfo,
1371  _In_ WIN_PROCESS_OBJECT *VictimProcess,
1372  _Out_ INTRO_DPI_EXTRA_INFO *ExtraInfo
1373  )
1382 {
1383  if (NULL == CollectedExtraInfo)
1384  {
1386  }
1387 
1388  if (NULL == VictimProcess)
1389  {
1391  }
1392 
1393  if (PcType == INT_PC_VIOLATION_DPI_DEBUG_FLAG)
1394  {
1395  WIN_PROCESS_OBJECT *pDebugger = IntWinProcFindObjectByEprocess(VictimProcess->CreationInfo.DebuggerEprocess);
1396 
1397  IntAlertFillWinProcess(pDebugger, &ExtraInfo->DpiDebugFlag.Debugger);
1398  }
1399  else if (PcType == INT_PC_VIOLATION_DPI_PIVOTED_STACK)
1400  {
1401  DWORD sz = gGuest.Guest64 ? sizeof(KTRAP_FRAME64) : sizeof(KTRAP_FRAME32);
1402 
1403  ExtraInfo->DpiPivotedStack.CurrentStack = CollectedExtraInfo->DpiPivotedStackExtraInfo.CurrentStack;
1404  ExtraInfo->DpiPivotedStack.StackBase = CollectedExtraInfo->DpiPivotedStackExtraInfo.StackBase;
1405  ExtraInfo->DpiPivotedStack.StackLimit = CollectedExtraInfo->DpiPivotedStackExtraInfo.StackLimit;
1406  ExtraInfo->DpiPivotedStack.Wow64CurrentStack = CollectedExtraInfo->DpiPivotedStackExtraInfo.CurrentWow64Stack;
1407  ExtraInfo->DpiPivotedStack.Wow64StackBase = CollectedExtraInfo->DpiPivotedStackExtraInfo.Wow64StackBase;
1408  ExtraInfo->DpiPivotedStack.Wow64StackLimit = CollectedExtraInfo->DpiPivotedStackExtraInfo.Wow64StackLimit;
1409 
1410  IntVirtMemRead(CollectedExtraInfo->DpiPivotedStackExtraInfo.TrapFrameAddress,
1411  MIN(sz, sizeof(ExtraInfo->DpiPivotedStack.TrapFrameContent)),
1413  ExtraInfo->DpiPivotedStack.TrapFrameContent,
1414  NULL);
1415  }
1416  else if (PcType == INT_PC_VIOLATION_DPI_STOLEN_TOKEN)
1417  {
1419  CollectedExtraInfo->DpiStolenTokenExtraInfo.StolenFromEprocess);
1420 
1421  IntAlertFillWinProcess(pStolenFrom, &ExtraInfo->DpiStolenToken.StolenFrom);
1422  }
1423  else if (PcType == INT_PC_VIOLATION_DPI_HEAP_SPRAY)
1424  {
1425  WORD maxNumberOfHeapVals = 0;
1426  DWORD detectedPage = 0, maxPageHeapVals = 0;
1427 
1428  ExtraInfo->DpiHeapSpray.ShellcodeFlags = CollectedExtraInfo->DpiHeapSprayExtraInfo.ShellcodeFlags;
1429 
1430  for (DWORD val = 1; val <= HEAP_SPRAY_NR_PAGES; val++)
1431  {
1432  DWORD checkedPage = ((val << 24) | (val << 16) | (val << 8) | val) & PAGE_MASK;
1433 
1434  ExtraInfo->DpiHeapSpray.HeapPages[val - 1].Mapped =
1435  CollectedExtraInfo->DpiHeapSprayExtraInfo.HeapPages[val - 1].Mapped;
1436  ExtraInfo->DpiHeapSpray.HeapPages[val - 1].Detected =
1437  CollectedExtraInfo->DpiHeapSprayExtraInfo.HeapPages[val - 1].Detected;
1438  ExtraInfo->DpiHeapSpray.HeapPages[val - 1].HeapValCount =
1439  CollectedExtraInfo->DpiHeapSprayExtraInfo.HeapPages[val - 1].HeapValCount;
1440  ExtraInfo->DpiHeapSpray.HeapPages[val - 1].Offset =
1441  CollectedExtraInfo->DpiHeapSprayExtraInfo.HeapPages[val - 1].Offset;
1442  ExtraInfo->DpiHeapSpray.HeapPages[val - 1].Executable =
1443  CollectedExtraInfo->DpiHeapSprayExtraInfo.HeapPages[val - 1].Executable;
1444 
1445  if (CollectedExtraInfo->DpiHeapSprayExtraInfo.HeapPages[val - 1].Detected)
1446  {
1447  detectedPage = checkedPage;
1448  }
1449 
1450  // Use >= so that we are sure that we will get at least one page even if there are no heap values.
1451  if (CollectedExtraInfo->DpiHeapSprayExtraInfo.HeapPages[val - 1].HeapValCount >= maxNumberOfHeapVals &&
1452  CollectedExtraInfo->DpiHeapSprayExtraInfo.HeapPages[val - 1].Mapped)
1453  {
1454  maxNumberOfHeapVals = (WORD)CollectedExtraInfo->DpiHeapSprayExtraInfo.HeapPages[val - 1].HeapValCount;
1455  maxPageHeapVals = checkedPage;
1456  }
1457  }
1458 
1459  // At this point we might not have any detected page, but only pages exceeding the max heap values heuristic,
1460  // so don't bother to complete it if not needed.
1461  if (0 != detectedPage)
1462  {
1463  IntVirtMemRead(detectedPage, PAGE_SIZE, VictimProcess->Cr3, ExtraInfo->DpiHeapSpray.DetectedPage, NULL);
1464  }
1465 
1466  IntVirtMemRead(maxPageHeapVals,
1467  PAGE_SIZE,
1468  VictimProcess->Cr3,
1469  ExtraInfo->DpiHeapSpray.MaxHeapValPageContent,
1470  NULL);
1471  }
1472  else if (PcType == INT_PC_VIOLATION_DPI_TOKEN_PRIVS)
1473  {
1474  ExtraInfo->DpiTokenPrivs.OldEnabled = CollectedExtraInfo->DpiTokenPrivsExtraInfo.OldEnabled;
1475  ExtraInfo->DpiTokenPrivs.OldPresent = CollectedExtraInfo->DpiTokenPrivsExtraInfo.OldPresent;
1476  ExtraInfo->DpiTokenPrivs.NewEnabled = CollectedExtraInfo->DpiTokenPrivsExtraInfo.NewEnabled;
1477  ExtraInfo->DpiTokenPrivs.NewPresent = CollectedExtraInfo->DpiTokenPrivsExtraInfo.NewPresent;
1478  }
1479  else if (PcType == INT_PC_VIOLATION_DPI_THREAD_START)
1480  {
1481  ExtraInfo->DpiThreadStart.ShellcodeFlags = CollectedExtraInfo->DpiThreadStartExtraInfo.ShellcodeFlags;
1482  ExtraInfo->DpiThreadStart.StartAddress = CollectedExtraInfo->DpiThreadStartExtraInfo.StartAddress;
1483 
1484  IntVirtMemRead(CollectedExtraInfo->DpiThreadStartExtraInfo.StartAddress & PAGE_MASK,
1485  PAGE_SIZE,
1486  VictimProcess->Cr3,
1487  ExtraInfo->DpiThreadStart.StartPage,
1488  NULL);
1489  }
1490  else
1491  {
1493  }
1494 
1495  return INT_STATUS_SUCCESS;
1496 }
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:634
_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:3265
#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:1531
Event structure for CR violation.
Definition: intro_types.h:1228
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:235
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:35
#define ALERT_MAX_FUNCTIONS
The maximum number of functions included in an alert structure.
Definition: intro_types.h:664
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:207
#define INT_STATUS_SUCCESS
Definition: introstatus.h:54
Fast IO Dispatch (Windows only)
Definition: intro_types.h:233
void IntAlertFillConnection(const INTRONET_ENDPOINT *Connection, EVENT_CONNECTION_EVENT *Event)
Saves information about a guest connection in an event.
Definition: alerts.c:1328
Infinity hook modifications of WMI_LOGGER_CONTEXT.GetCpuClock.
Definition: intro_types.h:261
uint16_t WORD
Definition: intro_types.h:48
Non-conditional jump, of any kind.
Definition: codeblocks.h:28
DWORD Build
Definition: exceptions.h:142
User-mode non executable zone.
Definition: intro_types.h:244
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:1516
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:930
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:933
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:277
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:665
Describes a kernel-mode originator.
Definition: exceptions.h:897
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:638
#define ALERT_MAX_CODEBLOCKS
The maximum number of code blocks included in an alert structure.
Definition: intro_types.h:667
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:274
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
#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:421
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:1232
Exposes the functions used to provide Windows Threads related support.
Token privileges.
Definition: intro_types.h:263
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:633
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:250
EXCEPTIONS * Exceptions
The exceptions that are currently loaded.
Definition: guests.h:388
static CODE_BLOCK gCodeBlocks[PAGE_SIZE/sizeof(CODE_BLOCK)]
Definition: serializers.c:587
#define IS_KERNEL_POINTER_LIX(p)
Definition: lixguest.h:11
#define EXCEPTION_CODEBLOCKS_OFFSET
The maximum offset for codeblocks extraction.
Definition: exceptions.h:54
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:1287
struct _KTRAP_FRAME64 KTRAP_FRAME64
#define ZONE_EXECUTE
Used for execute violation.
Definition: exceptions.h:700
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:1528
#define memzero(a, s)
Definition: introcrt.h:35
Event structure for MSR violation.
Definition: intro_types.h:1198
BOOLEAN Guest64
True if this is a 64-bit guest, False if it is a 32-bit guest.
Definition: guests.h:286
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:1534
#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:1432
#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:1525
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:122
Executions inside the SharedUserData region.
Definition: intro_types.h:264
#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:903
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:279
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:1005
Holds information about a memory write attempt.
Definition: intro_types.h:892
#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:1173
#define WARNING(fmt,...)
Definition: glue.h:60
Event structure for GDTR/IDTR descriptor tables modifications.
Definition: intro_types.h:1490
#define ALERT_FLAG_NOT_RING0
If set, the alert was triggered in ring 1, 2 or 3.
Definition: intro_types.h:636
#define PAGE_SIZE
Definition: common.h:53
Holds all the alert types.
Definition: alerts.h:14
Describes the modified zone.
Definition: exceptions.h:847
Exception Table (Linux-only)
Definition: intro_types.h:255
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
The Virtualization exception agent injected inside the guest.
Definition: intro_types.h:256
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:838
void IntAlertFillLixCurrentProcess(INTRO_PROCESS *EventProcess)
Saves the current Linux process inside an event.
Definition: alerts.c:1307
Common violation header.
Definition: intro_types.h:1078
User-mode library.
Definition: intro_types.h:245
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:1207
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:370
#define ALERT_FLAG_SYSPROC
If set, the alert is on system process.
Definition: intro_types.h:635
Self mapping index in PDBR.
Definition: intro_types.h:251
The parent of a process tried to obtain debug privileges over the child.
Definition: intro_types.h:1522
GUEST_STATE gGuest
The current guest state.
Definition: guests.c:48
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:645
SSDT (Windows only)
Definition: intro_types.h:232
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:23
The thread which created the process has started execution on some suspicious code.
Definition: intro_types.h:1537
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:699
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:913
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:1368
BYTE * KernelBuffer
A buffer containing the entire kernel image.
Definition: winguest.h:837
#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:859
VCPU_STATE * gVcpu
The state of the current VCPU.
Definition: guests.c:57
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:856
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:1843
64-bit selector.
Definition: glueiface.h:188
Holds the CPU context for an event.
Definition: intro_types.h:876
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:3592
#define ZONE_LIB_IMPORTS
Used for the imports of a dll, driver, etc.
Definition: exceptions.h:686
Holds register state.
Definition: glueiface.h:30
Event structure for EPT violations.
Definition: intro_types.h:1104
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:1147
#define INTRO_VIOLATION_VERSION
Violation header version.
Definition: intro_types.h:713
Structure for keeping the relevant DPI violation information.
Definition: intro_types.h:1544
Describes a user-mode or kernel-mode module.
Definition: intro_types.h:839
Describes a guest process.
Definition: intro_types.h:815
BOOLEAN IntWinDrvObjIsProtectedAv(const WCHAR *DrvObj)
Checks if a driver object belongs to a known and protected antivirus.
Write-access hook.
Definition: glueiface.h:299
#define PAGE_MASK
Definition: pgtable.h:35
#define ZONE_WRITE
Used for write violation.
Definition: exceptions.h:698
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:1261
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:81
#define INT_STATUS_INVALID_PARAMETER_3
Definition: introstatus.h:68