Bitdefender Hypervisor Memory Introspection
update_exceptions.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020 Bitdefender
3  * SPDX-License-Identifier: Apache-2.0
4  */
10 
11 #include "update_exceptions.h"
12 #include "alert_exceptions.h"
13 #include "guests.h"
14 #include "utils.h"
15 
17 #define UPDATE_VALIDATE_FILE_SIZE 0x1
18 #define UPDATE_VALIDATE_HEADER_SIZE 0x2
20 #define UPDATE_VALIDATE_ALL (UPDATE_VALIDATE_FILE_SIZE | UPDATE_VALIDATE_HEADER_SIZE)
22 
24 static EXCEPTION_SIGNATURE_ID gCurrentSignatureId = { .Field = { .Value = BIT(22) / 2, .Type = 0} };
25 
30 typedef struct _UPDATE_ITEM_SIZE
31 {
35 
36 
39  _Out_ WORD *MajorVersion,
40  _Out_ WORD *MinorVersion,
41  _Out_ DWORD *BuildNumber
42  )
56 {
57  if (NULL == MajorVersion)
58  {
60  }
61 
62  if (NULL == MinorVersion)
63  {
65  }
66 
67  if (NULL == BuildNumber)
68  {
70  }
71 
72  if (NULL == gGuest.Exceptions || !gGuest.Exceptions->Loaded)
73  {
75  }
76 
77  *MajorVersion = gGuest.Exceptions->Version.Major;
78  *MinorVersion = gGuest.Exceptions->Version.Minor;
79  *BuildNumber = gGuest.Exceptions->Version.Build;
80 
81  return INT_STATUS_SUCCESS;
82 }
83 
84 
88  )
96 {
97  gCurrentSignatureId.Field.Value++;
98  gCurrentSignatureId.Field.Type = Type;
99 
100  return gCurrentSignatureId;
101 }
102 
103 
104 static BOOLEAN
106  _In_ DWORD Size,
107  _In_ UPDATE_ITEM_SIZE *Item,
108  _In_ DWORD Flags
109  )
119 {
120  if (Flags & UPDATE_VALIDATE_HEADER_SIZE)
121  {
122  if (Size != Item->EntrySize)
123  {
124  ERROR("[ERROR] The exceptions file is corrupted. The size of the entry (%d) is different from the size "
125  "provided by the header (%d)\n", Size, Item->EntrySize);
126  return FALSE;
127  }
128  }
129 
130  if (Flags & UPDATE_VALIDATE_FILE_SIZE)
131  {
132  if (Size > Item->RemainingFileSize)
133  {
134  ERROR("[ERROR] The exceptions file is corrupted. The size of the entry (%d) exceed the remaining size "
135  "of the exceptions file (%d)\n", Size, Item->RemainingFileSize);
136  return FALSE;
137  }
138  }
139 
140  return TRUE;
141 }
142 
143 
144 static INTSTATUS
146  _In_ UPDATE_KM_EXCEPTION *UpdateException,
147  _In_ UPDATE_ITEM_SIZE *Item
148  )
165 {
166  DWORD extraSize;
167  KM_EXCEPTION *pException;
168  LIST_HEAD *head;
169 
170  if (!IntUpdateIsValidEntry(sizeof(*UpdateException), Item, UPDATE_VALIDATE_FILE_SIZE))
171  {
173  }
174 
175  extraSize = UpdateException->SigCount * sizeof(EXCEPTION_SIGNATURE_ID);
176 
177  if (!IntUpdateIsValidEntry(sizeof(*UpdateException) + extraSize, Item, UPDATE_VALIDATE_ALL))
178  {
180  }
181 
182  if ((gGuest.OSType == introGuestWindows && (UpdateException->Flags & EXCEPTION_FLG_LINUX)) ||
183  (gGuest.OSType == introGuestLinux && !(UpdateException->Flags & EXCEPTION_FLG_LINUX)))
184  {
186  }
187 
188  if (UpdateException->Flags & EXCEPTION_FLG_IGNORE)
189  {
190  TRACE("[UPDATE] Dropped an ignored KM exception. No problem here!\n");
192  }
193 
194  // SigCount is a WORD, multiplied by sizeof(EXCEPTION_SIGNATURE_ID), so the size won't overflow.
195  pException = HpAllocWithTag(sizeof(*pException) + extraSize, IC_TAG_EXKM);
196  if (NULL == pException)
197  {
199  }
200 
201  pException->OriginatorNameHash = UpdateException->Originator.NameHash;
202  pException->VictimNameHash = UpdateException->VictimNameHash;
203  pException->Flags = UpdateException->Flags;
204  pException->Type = UpdateException->Type;
205  pException->SigCount = UpdateException->SigCount;
206 
207  // This is an old exceptions.bin, so add the write flag manually
208  if (0 == (pException->Flags & (EXCEPTION_FLG_READ | EXCEPTION_FLG_WRITE | EXCEPTION_FLG_EXECUTE)))
209  {
210  pException->Flags |= EXCEPTION_FLG_WRITE;
211  }
212 
213  // Only copy if we have signatures
214  if (UpdateException->SigCount > 0)
215  {
216  memcpy(&pException->Signatures[0], &UpdateException->SigIds[0],
217  UpdateException->SigCount * sizeof(EXCEPTION_SIGNATURE_ID));
218  }
219 
220  //
221  // Now, let's find in which list this exception is
222  //
223  if (pException->OriginatorNameHash == kmExcNameAny)
224  {
225  if (UpdateException->Flags & EXCEPTION_FLG_FEEDBACK)
226  {
228  }
229  else
230  {
232  }
233  }
234  else if (pException->OriginatorNameHash == kmExcNameNone)
235  {
236  if (UpdateException->Flags & EXCEPTION_FLG_FEEDBACK)
237  {
239  }
240  else
241  {
243  }
244  }
245  else
246  {
247  if (UpdateException->Flags & EXCEPTION_FLG_FEEDBACK)
248  {
250  }
251  else
252  {
253  DWORD id = EXCEPTION_TABLE_ID(pException->OriginatorNameHash);
254  head = &gGuest.Exceptions->KernelExceptions[id];
255  }
256  }
257 
258  InsertTailList(head, &pException->Link);
259 
260  return INT_STATUS_SUCCESS;
261 }
262 
263 
264 static INTSTATUS
266  _In_ UPDATE_KUM_EXCEPTION *UpdateException,
267  _In_ UPDATE_ITEM_SIZE *Item
268  )
285 {
286  DWORD extraSize;
287  KUM_EXCEPTION *pException;
288  LIST_HEAD *head;
289 
290  if (!IntUpdateIsValidEntry(sizeof(*UpdateException), Item, UPDATE_VALIDATE_FILE_SIZE))
291  {
293  }
294 
295  extraSize = UpdateException->SigCount * sizeof(EXCEPTION_SIGNATURE_ID);
296 
297  if (!IntUpdateIsValidEntry(sizeof(*UpdateException) + extraSize, Item, UPDATE_VALIDATE_ALL))
298  {
300  }
301 
302  if ((gGuest.OSType == introGuestWindows && (UpdateException->Flags & EXCEPTION_FLG_LINUX)) ||
303  (gGuest.OSType == introGuestLinux && !(UpdateException->Flags & EXCEPTION_FLG_LINUX)))
304  {
306  }
307 
308  if (UpdateException->Flags & EXCEPTION_FLG_IGNORE)
309  {
310  TRACE("[UPDATE] Dropped an ignored KM exception. No problem here!\n");
312  }
313 
314  // SigCount is a WORD, multiplied by sizeof(EXCEPTION_SIGNATURE_ID), so the size won't overflow.
315  pException = HpAllocWithTag(sizeof(*pException) + extraSize, IC_TAG_EXKU);
316  if (NULL == pException)
317  {
319  }
320 
321  pException->OriginatorNameHash = UpdateException->OriginatorNameHash;
322  pException->Victim.NameHash = UpdateException->Victim.NameHash;
323  pException->Victim.ProcessHash = UpdateException->Victim.ProcessHash;
324  pException->Flags = UpdateException->Flags;
325  pException->Type = UpdateException->Type;
326  pException->SigCount = UpdateException->SigCount;
327 
328  // Only copy if we have signatures
329  if (UpdateException->SigCount > 0)
330  {
331  memcpy(&pException->Signatures[0], &UpdateException->SigIds[0],
332  UpdateException->SigCount * sizeof(EXCEPTION_SIGNATURE_ID));
333  }
334 
335  //
336  // Now, let's find in which list this exception is
337  //
338  if (pException->OriginatorNameHash == kmExcNameAny)
339  {
340  if (UpdateException->Flags & EXCEPTION_FLG_FEEDBACK)
341  {
343  }
344  else
345  {
347  }
348  }
349  else if (pException->OriginatorNameHash == kmExcNameNone)
350  {
351  if (UpdateException->Flags & EXCEPTION_FLG_FEEDBACK)
352  {
354  }
355  else
356  {
358  }
359  }
360  else
361  {
362  if (UpdateException->Flags & EXCEPTION_FLG_FEEDBACK)
363  {
365  }
366  else
367  {
368  DWORD id = EXCEPTION_TABLE_ID(pException->OriginatorNameHash);
370  }
371  }
372 
373  InsertTailList(head, &pException->Link);
374 
375  return INT_STATUS_SUCCESS;
376 }
377 
378 
379 static INTSTATUS
381  _In_ UPDATE_UM_EXCEPTION *UpdateException,
382  _In_ UPDATE_ITEM_SIZE *Item
383  )
402 {
403  DWORD extraSize;
404  UM_EXCEPTION *pException;
405  LIST_HEAD *head;
406 
407  if (!IntUpdateIsValidEntry(sizeof(*UpdateException), Item, UPDATE_VALIDATE_FILE_SIZE))
408  {
410  }
411 
412  extraSize = UpdateException->SigCount * sizeof(EXCEPTION_SIGNATURE_ID);
413 
414  if (!IntUpdateIsValidEntry(sizeof(*UpdateException) + extraSize, Item, UPDATE_VALIDATE_ALL))
415  {
417  }
418 
419  if ((gGuest.OSType == introGuestWindows && (UpdateException->Flags & EXCEPTION_FLG_LINUX)) ||
420  (gGuest.OSType == introGuestLinux && !(UpdateException->Flags & EXCEPTION_FLG_LINUX)))
421  {
423  }
424 
425  if (UpdateException->Flags & EXCEPTION_FLG_IGNORE)
426  {
427  TRACE("[UPDATE] Dropped an ignored UM exception. No problem here!\n");
429  }
430 
431  pException = HpAllocWithTag(sizeof(*pException) + extraSize, IC_TAG_EXUM);
432  if (NULL == pException)
433  {
435  }
436 
437  pException->OriginatorNameHash = UpdateException->OriginatorNameHash;
438  pException->Victim.NameHash = UpdateException->Victim.NameHash;
439  pException->Victim.ProcessHash = UpdateException->Victim.ProcessHash;
440  pException->Flags = UpdateException->Flags;
441  pException->Type = UpdateException->Type;
442  pException->SigCount = UpdateException->SigCount;
443 
444  // This is an old exceptions.bin, so add the write/exec flag manually
445  if (0 == (pException->Flags & (EXCEPTION_FLG_READ | EXCEPTION_FLG_WRITE | EXCEPTION_FLG_EXECUTE)))
446  {
447  if (pException->Type == umObjNxZone)
448  {
449  pException->Flags |= EXCEPTION_FLG_EXECUTE;
450  }
451  else
452  {
453  pException->Flags |= EXCEPTION_FLG_WRITE;
454  }
455  }
456 
457  if (UpdateException->SigCount > 0)
458  {
459  // We have calculated the size occupied by the exception, so it's safe to use memcpy for signatures
460  memcpy(pException->Signatures, UpdateException->SigIds,
461  UpdateException->SigCount * sizeof(EXCEPTION_SIGNATURE_ID));
462  }
463 
464  // Now, let's find in which list this exception is
465  if (pException->Type == umObjProcessCreation)
466  {
467  if (UpdateException->Flags & EXCEPTION_FLG_FEEDBACK)
468  {
470  }
471  else
472  {
474  }
475  }
476  else if (pException->OriginatorNameHash == umExcNameAny)
477  {
478  if (UpdateException->Flags & EXCEPTION_FLG_FEEDBACK)
479  {
481  }
482  else
483  {
485  }
486  }
487  else if (pException->OriginatorNameHash == umExcNameNone)
488  {
489  if (UpdateException->Flags & EXCEPTION_FLG_FEEDBACK)
490  {
492  }
493  else
494  {
496  }
497  }
498  else
499  {
500  if (UpdateException->Flags & EXCEPTION_FLG_FEEDBACK)
501  {
503  }
504  else
505  {
506  DWORD id = EXCEPTION_TABLE_ID(pException->OriginatorNameHash);
507  head = &gGuest.Exceptions->UserExceptions[id];
508  }
509  }
510 
511  InsertTailList(head, &pException->Link);
512 
513  return INT_STATUS_SUCCESS;
514 }
515 
516 
517 static INTSTATUS
519  _In_ UPDATE_UM_EXCEPTION_GLOB *UpdateException,
520  _In_ UPDATE_ITEM_SIZE *Item
521  )
535 {
536  DWORD extraSize = 0;
537  DWORD size = 0;
538  DWORD remainingSize = Item->RemainingFileSize;
539  char *pOriginatorName = NULL;
540  size_t originatorNameLen = 0;
541  char *pVictimName = NULL;
542  size_t victimNameLen = 0;
543  char *pProcName = NULL;
544  size_t procNameLen = 0;
545  UM_EXCEPTION_GLOB *pException;
546 
547  if (!IntUpdateIsValidEntry(sizeof(*UpdateException), Item, UPDATE_VALIDATE_FILE_SIZE))
548  {
550  }
551 
552  size = sizeof(UpdateException->Flags) + sizeof(UpdateException->Type) + sizeof(UpdateException->_Reserved)
553  + sizeof(UpdateException->SigCount);
554  remainingSize -= size;
555 
556  if (UpdateException->Flags & EXCEPTION_FLG_IGNORE)
557  {
558  TRACE("[UPDATE] Dropped an ignored UM exception. No problem here!\n");
560  }
561 
562  pOriginatorName = UpdateException->OriginatorNameGlob;
563  originatorNameLen = strlen_s(pOriginatorName, MIN((DWORD)EXCEPTION_UM_GLOB_LENGTH, remainingSize)) + 1;
564  size += (DWORD)originatorNameLen;
565  remainingSize -= (DWORD)originatorNameLen;
566 
567  if (originatorNameLen <= 1)
568  {
569  ERROR("[ERROR] The originator name length is invalid (%zu)\n", originatorNameLen);
571  }
572 
573  if (!IntUpdateIsValidEntry(sizeof(*UpdateException) + size, Item, UPDATE_VALIDATE_FILE_SIZE))
574  {
576  }
577 
578  if (originatorNameLen > EXCEPTION_UM_GLOB_LENGTH)
579  {
580  ERROR("[ERROR] Originator Name length is longer than the supported one (%d)\n", EXCEPTION_UM_GLOB_LENGTH);
582  }
583 
584  pVictimName = pOriginatorName + originatorNameLen;
585  victimNameLen = strlen_s(pVictimName, MIN((DWORD)EXCEPTION_UM_GLOB_LENGTH, remainingSize)) + 1;
586  size += (DWORD)victimNameLen;
587  remainingSize -= (DWORD)victimNameLen;
588 
589  if (victimNameLen <= 1)
590  {
591  ERROR("[ERROR] The victim name length is invalid (%zu)\n", victimNameLen);
593  }
594 
595  if (!IntUpdateIsValidEntry(sizeof(*UpdateException) + size, Item, UPDATE_VALIDATE_FILE_SIZE))
596  {
598  }
599 
600  if (victimNameLen > EXCEPTION_UM_GLOB_LENGTH)
601  {
602  ERROR("[ERROR] Victim Name length is longer than the supported one (%d)\n", EXCEPTION_UM_GLOB_LENGTH);
604  }
605 
606  pProcName = pVictimName + victimNameLen;
607  procNameLen = strlen_s(pProcName, MIN((DWORD)EXCEPTION_UM_GLOB_LENGTH, remainingSize)) + 1;
608  size += (DWORD)procNameLen;
609 
610  if (procNameLen <= 1)
611  {
612  ERROR("[ERROR] The process name length is invalid (%zu)\n", procNameLen);
614  }
615 
616 
617  if (!IntUpdateIsValidEntry(sizeof(*UpdateException) + size, Item, UPDATE_VALIDATE_FILE_SIZE))
618  {
620  }
621 
622  if (procNameLen > EXCEPTION_UM_GLOB_LENGTH)
623  {
624  ERROR("[ERROR] Victim Process length is longer than the supported one (%d)\n", EXCEPTION_UM_GLOB_LENGTH);
626  }
627 
628  extraSize = UpdateException->SigCount * sizeof(EXCEPTION_SIGNATURE_ID);
629  size += extraSize;
630 
631  if (!IntUpdateIsValidEntry(size, Item, UPDATE_VALIDATE_ALL))
632  {
634  }
635 
636  if ((gGuest.OSType == introGuestWindows && (UpdateException->Flags & EXCEPTION_FLG_LINUX)) ||
637  (gGuest.OSType == introGuestLinux && !(UpdateException->Flags & EXCEPTION_FLG_LINUX)))
638  {
640  }
641 
642  pException = HpAllocWithTag(sizeof(*pException) + extraSize, IC_TAG_EXUM);
643  if (NULL == pException)
644  {
646  }
647 
648  pException->Flags = UpdateException->Flags;
649  pException->Type = UpdateException->Type;
650  pException->SigCount = UpdateException->SigCount;
651 
652  if (originatorNameLen > 1)
653  {
654  strlcpy(pException->OriginatorNameGlob, pOriginatorName, sizeof(pException->OriginatorNameGlob));
655  }
656 
657  if (victimNameLen > 1)
658  {
659  strlcpy(pException->Victim.NameGlob, pVictimName, sizeof(pException->Victim.NameGlob));
660  }
661 
662  if (procNameLen > 1)
663  {
664  strlcpy(pException->Victim.ProcessGlob, pProcName, sizeof(pException->Victim.ProcessGlob));
665  }
666 
667  if (UpdateException->SigCount > 0)
668  {
669  // We have calculated the size occupied by the exception, so it's safe to use memcpy for signatures
670  void *pSigStart = pProcName + procNameLen;
671  memcpy(pException->Signatures, pSigStart, UpdateException->SigCount * sizeof(EXCEPTION_SIGNATURE_ID));
672  }
673 
675 
676  return INT_STATUS_SUCCESS;
677 }
678 
679 
680 static INTSTATUS
682  _In_ UPDATE_CB_SIGNATURE *UpdateSignature,
683  _In_ UPDATE_ITEM_SIZE *Item
684  )
695 {
696  DWORD extraSize = 0;
697  DWORD size = 0;
698  UPDATE_CB_HASH *pHashList;
699  SIG_CODEBLOCKS *pSignature;
700  SIG_CODEBLOCK_HASH *pSigHash;
701 
702  // Now see how many hashes we have in each signature
703  if (!IntUpdateIsValidEntry(sizeof(*UpdateSignature) + sizeof(UPDATE_CB_HASH), Item, UPDATE_VALIDATE_FILE_SIZE))
704  {
706  }
707 
708  pHashList = (PUPDATE_CB_HASH)UpdateSignature->HashesList;
709  for (DWORD i = 0; i < UpdateSignature->ListsCount; i++)
710  {
711  DWORD updateHashSize;
712  DWORD hashSize;
713 
714  // Make sure that we can actually use pHashList
715  if (!IntUpdateIsValidEntry(sizeof(*UpdateSignature) + size + sizeof(*pHashList),
717  {
719  }
720 
721  // The sizes are not the same due to alignment
722  updateHashSize = sizeof(UPDATE_CB_HASH) + pHashList->Count * sizeof(DWORD);
723  hashSize = sizeof(SIG_CODEBLOCK_HASH) + pHashList->Count * sizeof(DWORD);
724 
725  extraSize += hashSize;
726  size += updateHashSize;
727 
728  // This will check that the hashes up to this point (size) + the size of the signature structure don't spill
729  // outside the file
730  if (!IntUpdateIsValidEntry(sizeof(*UpdateSignature) + size, Item, UPDATE_VALIDATE_FILE_SIZE))
731  {
733  }
734 
735  // advance to the next hash list
736  pHashList = (UPDATE_CB_HASH *)((BYTE *)pHashList + updateHashSize);
737  }
738 
739  if (!IntUpdateIsValidEntry(sizeof(*UpdateSignature) + size, Item, UPDATE_VALIDATE_ALL))
740  {
742  }
743 
744  if ((gGuest.OSType == introGuestWindows && (UpdateSignature->Flags & SIGNATURE_FLG_LINUX)) ||
745  (gGuest.OSType == introGuestLinux && !(UpdateSignature->Flags & SIGNATURE_FLG_LINUX)))
746  {
748  }
749 
750  pSignature = HpAllocWithTag(sizeof(*pSignature) + extraSize, IC_TAG_ESIG);
751  if (NULL == pSignature)
752  {
754  }
755 
756  pSignature->Id.Value = UpdateSignature->Id;
757  pSignature->Flags = UpdateSignature->Flags;
758  pSignature->Score = UpdateSignature->Score;
759  pSignature->ListsCount = UpdateSignature->ListsCount;
760  pSignature->AlertSignature = FALSE;
761 
762  // Now copy the hashes lists
763  pHashList = (UPDATE_CB_HASH *)UpdateSignature->HashesList;
764  pSigHash = (SIG_CODEBLOCK_HASH *)pSignature->Object;
765  for (DWORD i = 0; i < UpdateSignature->ListsCount; i++)
766  {
767  // The sizes are not the same due to alignment
768  DWORD updateHashSize = sizeof(*pHashList) + pHashList->Count * sizeof(DWORD);
769  DWORD hashSize = sizeof(*pSigHash) + pHashList->Count * sizeof(DWORD);
770 
771  pSigHash->Count = pHashList->Count;
772  for (DWORD j = 0; j < pHashList->Count; j++)
773  {
774  pSigHash->Hashes[j] = pHashList->Hashes[j];
775  }
776 
777  // advance to the next hash list
778  pHashList = (UPDATE_CB_HASH *)((BYTE *)pHashList + updateHashSize);
779  pSigHash = (SIG_CODEBLOCK_HASH *)((BYTE *)pSigHash + hashSize);
780  }
781 
783 
784  return INT_STATUS_SUCCESS;
785 }
786 
787 
788 static INTSTATUS
790  _In_ UPDATE_VALUE_SIGNATURE *UpdateSignature,
791  _In_ UPDATE_ITEM_SIZE *Item
792  )
803 {
804  DWORD size;
805  DWORD extraSize;
806  SIG_VALUE *pSignature;
807  UPDATE_VALUE_HASH *pHashList;
808  SIG_VALUE_HASH *pSigHash;
809 
810  if (!IntUpdateIsValidEntry(sizeof(*UpdateSignature), Item, UPDATE_VALIDATE_FILE_SIZE))
811  {
813  }
814 
815  size = UpdateSignature->ListsCount * sizeof(UPDATE_VALUE_HASH);
816  if (!IntUpdateIsValidEntry(sizeof(*UpdateSignature) + size, Item, UPDATE_VALIDATE_ALL))
817  {
819  }
820 
821  if ((gGuest.OSType == introGuestWindows && (UpdateSignature->Flags & SIGNATURE_FLG_LINUX)) ||
822  (gGuest.OSType == introGuestLinux && !(UpdateSignature->Flags & SIGNATURE_FLG_LINUX)))
823  {
825  }
826 
827  extraSize = UpdateSignature->ListsCount * sizeof(SIG_VALUE_HASH);
828 
829  pSignature = HpAllocWithTag(sizeof(*pSignature) + extraSize, IC_TAG_ESIG);
830  if (NULL == pSignature)
831  {
833  }
834 
835  pSignature->Id.Value = UpdateSignature->Id;
836  pSignature->Flags = UpdateSignature->Flags;
837  pSignature->Score = UpdateSignature->Score;
838  pSignature->ListsCount = UpdateSignature->ListsCount;
839  pSignature->AlertSignature = FALSE;
840 
841  // Now copy the hashes lists
842  pHashList = (UPDATE_VALUE_HASH *)UpdateSignature->HashesList;
843  pSigHash = (SIG_VALUE_HASH *)pSignature->Object;
844 
845  for (DWORD i = 0; i < UpdateSignature->ListsCount; i++)
846  {
847  pSigHash[i].Offset = pHashList[i].Offset;
848  pSigHash[i].Size = pHashList[i].Size;
849  pSigHash[i].Hash = pHashList[i].Hash;
850  }
851 
853 
854  return INT_STATUS_SUCCESS;
855 }
856 
857 
858 static INTSTATUS
860  _In_ UPDATE_IDT_SIGNATURE *UpdateSignature,
861  _In_ UPDATE_ITEM_SIZE *Item
862  )
873 {
874  SIG_IDT *pSignature;
875 
876  if (!IntUpdateIsValidEntry(sizeof(*UpdateSignature), Item, UPDATE_VALIDATE_ALL))
877  {
879  }
880 
881  if ((gGuest.OSType == introGuestWindows && (UpdateSignature->Flags & SIGNATURE_FLG_LINUX)) ||
882  (gGuest.OSType == introGuestLinux && !(UpdateSignature->Flags & SIGNATURE_FLG_LINUX)))
883  {
885  }
886 
887  pSignature = HpAllocWithTag(sizeof(*pSignature), IC_TAG_ESIG);
888  if (NULL == pSignature)
889  {
891  }
892 
893  pSignature->Id.Value = UpdateSignature->Id;
894  pSignature->Flags = UpdateSignature->Flags;
895  pSignature->Entry = UpdateSignature->Entry;
896  pSignature->AlertSignature = FALSE;
897 
899 
900  return INT_STATUS_SUCCESS;
901 }
902 
903 
904 static INTSTATUS
906  _In_ UPDATE_VALUE_CODE_SIGNATURE *UpdateSignature,
907  _In_ UPDATE_ITEM_SIZE *Item
908  )
919 {
920  DWORD size;
921  SIG_VALUE_CODE *pSignature;
922  WORD *pUpdatePattern;
923  WORD *pExceptionPattern;
924 
925  if (!IntUpdateIsValidEntry(sizeof(*UpdateSignature), Item, UPDATE_VALIDATE_FILE_SIZE))
926  {
928  }
929 
930  size = UpdateSignature->Length * sizeof(WORD);
931 
932  if (!IntUpdateIsValidEntry(sizeof(*UpdateSignature) + size, Item, UPDATE_VALIDATE_ALL))
933  {
935  }
936 
937  if ((gGuest.OSType == introGuestWindows && (UpdateSignature->Flags & SIGNATURE_FLG_LINUX)) ||
938  (gGuest.OSType == introGuestLinux && !(UpdateSignature->Flags & SIGNATURE_FLG_LINUX)))
939  {
941  }
942 
943  pSignature = HpAllocWithTag(sizeof(*pSignature) + size, IC_TAG_ESIG);
944  if (NULL == pSignature)
945  {
947  }
948 
949  pSignature->Id.Value = UpdateSignature->Id;
950  pSignature->Offset = UpdateSignature->Offset;
951  pSignature->Flags = UpdateSignature->Flags;
952  pSignature->Length = UpdateSignature->Length;
953  pSignature->AlertSignature = FALSE;
954 
955  pUpdatePattern = &UpdateSignature->Pattern[0];
956  pExceptionPattern = &pSignature->Object[0];
957 
958  // We have only one pattern for each signature
959  for (DWORD i = 0; i < UpdateSignature->Length; i++)
960  {
961  pExceptionPattern[i] = pUpdatePattern[i];
962  }
963 
965 
966  return INT_STATUS_SUCCESS;
967 }
968 
969 
970 static INTSTATUS
972  _In_ UPDATE_VERSION_OS_SIGNATURE *UpdateSignature,
973  _In_ UPDATE_ITEM_SIZE *Item
974  )
985 {
986  if (!IntUpdateIsValidEntry(sizeof(*UpdateSignature), Item, UPDATE_VALIDATE_ALL))
987  {
989  }
990 
991  if ((gGuest.OSType == introGuestWindows && (UpdateSignature->Flags & SIGNATURE_FLG_LINUX)) ||
992  (gGuest.OSType == introGuestLinux && !(UpdateSignature->Flags & SIGNATURE_FLG_LINUX)))
993  {
995  }
996 
997  SIG_VERSION_OS *pSignature = HpAllocWithTag(sizeof(*pSignature), IC_TAG_ESIG);
998  if (pSignature == NULL)
999  {
1001  }
1002 
1003  pSignature->Id.Value = UpdateSignature->Id;
1004  pSignature->Flags = UpdateSignature->Flags;
1005  pSignature->AlertSignature = FALSE;
1006  pSignature->Minimum.Value = UpdateSignature->Minimum.Value;
1007  pSignature->Maximum.Value = UpdateSignature->Maximum.Value;
1008 
1010 
1011  return INT_STATUS_SUCCESS;
1012 }
1013 
1014 
1015 static INTSTATUS
1017  _In_ UPDATE_VERSION_INTRO_SIGNATURE *UpdateSignature,
1018  _In_ UPDATE_ITEM_SIZE *Item
1019  )
1030 {
1031  if (!IntUpdateIsValidEntry(sizeof(*UpdateSignature), Item, UPDATE_VALIDATE_ALL))
1032  {
1034  }
1035 
1036  if ((gGuest.OSType == introGuestWindows && (UpdateSignature->Flags & SIGNATURE_FLG_LINUX)) ||
1037  (gGuest.OSType == introGuestLinux && !(UpdateSignature->Flags & SIGNATURE_FLG_LINUX)))
1038  {
1040  }
1041 
1042  SIG_VERSION_INTRO *pSignature = HpAllocWithTag(sizeof(*pSignature), IC_TAG_ESIG);
1043  if (pSignature == NULL)
1044  {
1046  }
1047 
1048  pSignature->Id.Value = UpdateSignature->Id;
1049  pSignature->Flags = UpdateSignature->Flags;
1050  pSignature->AlertSignature = FALSE;
1051  pSignature->Minimum.Raw = UpdateSignature->Minimum.Raw;
1052  pSignature->Maximum.Raw = UpdateSignature->Maximum.Raw;
1053 
1055 
1056  return INT_STATUS_SUCCESS;
1057 }
1058 
1059 
1060 static INTSTATUS
1062  _In_ UPDATE_EXPORT_SIGNATURE *UpdateSignature,
1063  _In_ UPDATE_ITEM_SIZE *Item
1064  )
1075 {
1076  if (!IntUpdateIsValidEntry(sizeof(*UpdateSignature), Item, UPDATE_VALIDATE_FILE_SIZE))
1077  {
1079  }
1080 
1081  DWORD size = UpdateSignature->ListsCount * sizeof(UPDATE_EXPORT_HASH);
1082  if (!IntUpdateIsValidEntry(sizeof(*UpdateSignature) + size, Item, UPDATE_VALIDATE_ALL))
1083  {
1085  }
1086 
1087  if ((gGuest.OSType == introGuestWindows && (UpdateSignature->Flags & SIGNATURE_FLG_LINUX)) ||
1088  (gGuest.OSType == introGuestLinux && !(UpdateSignature->Flags & SIGNATURE_FLG_LINUX)))
1089  {
1091  }
1092 
1093  DWORD extraSize = UpdateSignature->ListsCount * sizeof(SIG_EXPORT_HASH);
1094 
1095  SIG_EXPORT *pSignature = HpAllocWithTag(sizeof(*pSignature) + extraSize, IC_TAG_ESIG);
1096  if (NULL == pSignature)
1097  {
1099  }
1100 
1101  pSignature->Id.Value = UpdateSignature->Id;
1102  pSignature->Flags = UpdateSignature->Flags;
1103  pSignature->ListsCount = UpdateSignature->ListsCount;
1104  pSignature->AlertSignature = FALSE;
1105 
1106  // Now copy the hashes lists
1107  UPDATE_EXPORT_HASH *pHashList = (UPDATE_EXPORT_HASH *)UpdateSignature->HashesList;
1108  SIG_EXPORT_HASH *pSigHash = (SIG_EXPORT_HASH *)pSignature->Object;
1109 
1110  for (DWORD i = 0; i < UpdateSignature->ListsCount; i++)
1111  {
1112  pSigHash[i].Hash = pHashList[i].Hash;
1113  pSigHash[i].Delta = pHashList[i].Delta;
1114  }
1115 
1117 
1118  return INT_STATUS_SUCCESS;
1119 }
1120 
1121 
1122 static INTSTATUS
1124  _In_ UPDATE_PROCESS_CREATION_SIGNATURE *UpdateSignature,
1125  _In_ UPDATE_ITEM_SIZE *Item
1126  )
1137 {
1138  if (!IntUpdateIsValidEntry(sizeof(*UpdateSignature), Item, UPDATE_VALIDATE_ALL))
1139  {
1141  }
1142 
1143  if ((gGuest.OSType == introGuestWindows && (UpdateSignature->Flags & SIGNATURE_FLG_LINUX)) ||
1144  (gGuest.OSType == introGuestLinux && !(UpdateSignature->Flags & SIGNATURE_FLG_LINUX)))
1145  {
1147  }
1148 
1149  SIG_PROCESS_CREATION *pSignature = HpAllocWithTag(sizeof(*pSignature), IC_TAG_ESIG);
1150  if (pSignature == NULL)
1151  {
1153  }
1154 
1155  pSignature->Id.Value = UpdateSignature->Id;
1156  pSignature->Flags = UpdateSignature->Flags;
1157  pSignature->AlertSignature = FALSE;
1158  pSignature->CreateMask = UpdateSignature->CreateMask;
1159 
1161 
1162  return INT_STATUS_SUCCESS;
1163 }
1164 
1165 
1166 static void
1168  _In_ EXCEPTION_SIGNATURE_ID *Signatures,
1169  _In_ DWORD Count
1170  )
1180 {
1181  for (DWORD i = 0; i < Count; i++)
1182  {
1183  switch (Signatures[i].Field.Type)
1184  {
1185  case signatureTypeExport :
1186  {
1188  {
1189  if (pSignature->AlertSignature && pSignature->Id.Value == Signatures[i].Value)
1190  {
1191  pSignature->Id = IntUpdateGetUniqueSigId(pSignature->Id.Field.Type);
1192  Signatures[i] = pSignature->Id;
1193 
1194  break;
1195  }
1196  }
1197 
1198  break;
1199  }
1200 
1202  {
1204  {
1205  if (pSignature->AlertSignature && pSignature->Id.Value == Signatures[i].Value)
1206  {
1207  pSignature->Id = IntUpdateGetUniqueSigId(pSignature->Id.Field.Type);
1208  Signatures[i] = pSignature->Id;
1209 
1210  break;
1211  }
1212  }
1213 
1214  break;
1215  }
1216 
1217  case signatureTypeIdt:
1218  {
1220  {
1221  if (pSignature->AlertSignature && pSignature->Id.Value == Signatures[i].Value)
1222  {
1223  pSignature->Id = IntUpdateGetUniqueSigId(pSignature->Id.Field.Type);
1224  Signatures[i] = pSignature->Id;
1225 
1226  break;
1227  }
1228  }
1229 
1230  break;
1231  }
1232 
1233  default:
1234  {
1235  ERROR("[ERROR] Should not reach here. Type is '%d'n", Signatures[i].Field.Type);
1236  return;
1237  }
1238  }
1239  }
1240 }
1241 
1242 
1243 void
1245  void
1246  )
1250 {
1252  {
1253  IntUpdateSetIdForException(pException->Signatures, pException->SigCount);
1254  }
1255 
1257  {
1258  IntUpdateSetIdForException(pException->Signatures, pException->SigCount);
1259  }
1260 
1262  {
1263  IntUpdateSetIdForException(pException->Signatures, pException->SigCount);
1264  }
1265 }
1266 
1267 
1268 INTSTATUS
1270  _In_ void *Buffer,
1271  _In_ DWORD Length,
1272  _In_ DWORD Flags
1273  )
1288 {
1289  INTSTATUS status;
1290  BYTE *address;
1291  UPDATE_FILE_HEADER *fileHeader;
1292 
1293  UNREFERENCED_PARAMETER(Flags);
1294 
1295  if (NULL == Buffer)
1296  {
1298  }
1299 
1300  if (Length <= sizeof(UPDATE_FILE_HEADER))
1301  {
1303  }
1304 
1305  address = Buffer;
1306  fileHeader = Buffer;
1307 
1308  LOG("[UPDATE] Requested to update the intro exceptions...\n");
1309 
1310  if (fileHeader->Magic != UPDATE_MAGIC_WORD)
1311  {
1312  ERROR("[ERROR] Exception file header doesn't have the right magic word (%c%c%c%c)\n",
1313  (fileHeader->Magic & 0xff000000) >> 24, (fileHeader->Magic & 0xff0000) >> 16,
1314  (fileHeader->Magic & 0xff00) >> 8, fileHeader->Magic & 0xff);
1315 
1317  }
1318 
1319  if (fileHeader->Version.Major != UPDATE_EXCEPTIONS_MIN_VER_MAJOR)
1320  {
1321  ERROR("[ERROR] Update's file major (%d.%d) version is different form ours (%d.%d)\n",
1322  fileHeader->Version.Major, fileHeader->Version.Minor, UPDATE_EXCEPTIONS_MIN_VER_MAJOR,
1324 
1325  return INT_STATUS_NOT_SUPPORTED;
1326  }
1327 
1328  if (fileHeader->Version.Minor > UPDATE_EXCEPTIONS_MIN_VER_MINOR)
1329  {
1330  WARNING("[WARNING] Update's file minor (%d.%d) version is newer than ours (%d.%d). "
1331  "Not all features will be available!\n", fileHeader->Version.Major, fileHeader->Version.Minor,
1333  }
1334  else if (fileHeader->Version.Minor < UPDATE_EXCEPTIONS_MIN_VER_MINOR)
1335  {
1336  ERROR("[ERROR] Update's file minor (%d.%d) version is older than ours (%d.%d). "
1337  "Will not update the exceptions.\n", fileHeader->Version.Major, fileHeader->Version.Minor,
1339 
1340  return INT_STATUS_NOT_SUPPORTED;
1341  }
1342 
1343  if (fileHeader->KernelExceptionsCount == 0 &&
1344  fileHeader->UserExceptionsCount == 0 &&
1345  fileHeader->KernelUserExceptionsCount == 0 &&
1346  fileHeader->UserExceptionsGlobCount == 0)
1347  {
1348  WARNING("[WARNING] Requested update with 0 kernel exceptions and 0 user exceptions. We cannot do that...\n");
1349 
1351  }
1352 
1353  if (NULL == gGuest.Exceptions)
1354  {
1356  }
1357 
1358  status = IntExceptRemove();
1359  if (!INT_SUCCESS(status))
1360  {
1361  ERROR("[ERROR] IntExceptRemove failed: 0x%08x\n", status);
1362  return status;
1363  }
1364 
1365  // Reset the last signature ID (will be updated again when adding signatures)
1366  gCurrentSignatureId.Field.Value = BIT(22) / 2;
1367 
1368  // skip over the file header
1369  address += sizeof(UPDATE_FILE_HEADER);
1370 
1371  while (address < (PBYTE)(size_t)Buffer + Length)
1372  {
1373  if ((QWORD)(address + sizeof(UPDATE_HEADER)) > ((QWORD)Buffer + Length))
1374  {
1375  ERROR("[ERROR] The address of 'UPDATE_HEADER' structure exceeds the exception buffer "
1376  "(0x%016llx/0x%016llx)\n", (QWORD)(address + sizeof(UPDATE_HEADER)), ((QWORD)Buffer + Length));
1378  }
1379 
1380  UPDATE_HEADER *header = (UPDATE_HEADER *)address;
1381  PBYTE structure = address + sizeof(UPDATE_HEADER);
1382  UPDATE_ITEM_SIZE item = { 0 };
1383 
1384  item.EntrySize = header->Size;
1385  item.RemainingFileSize = (DWORD)((QWORD)((QWORD)(Buffer) + Length) - (QWORD)structure);
1386 
1387  address += sizeof(UPDATE_HEADER) + header->Size;
1388 
1389  switch (header->Type)
1390  {
1392  status = IntUpdateAddKernelException((UPDATE_KM_EXCEPTION *)structure, &item);
1393  break;
1394 
1396  status = IntUpdateAddUserException((UPDATE_UM_EXCEPTION *)structure, &item);
1397  break;
1398 
1400  status = IntUpdateAddUserExceptionGlob((UPDATE_UM_EXCEPTION_GLOB *)structure, &item);
1401  break;
1402 
1404  status = IntUpdateAddCbSignature((UPDATE_CB_SIGNATURE *)structure, &item);
1405  break;
1406 
1408  status = IntUpdateAddExportSignature((UPDATE_EXPORT_SIGNATURE *)structure, &item);
1409  break;
1410 
1412  status = IntUpdateAddValueSignature((UPDATE_VALUE_SIGNATURE *)structure, &item);
1413  break;
1414 
1416  status = IntUpdateAddValueCodeSignature((UPDATE_VALUE_CODE_SIGNATURE *)structure, &item);
1417  break;
1418 
1420  status = IntUpdateAddIdtSignature((UPDATE_IDT_SIGNATURE *)structure, &item);
1421  break;
1422 
1424  status = IntUpdateAddVersionOsSignature((UPDATE_VERSION_OS_SIGNATURE *)structure, &item);
1425  break;
1426 
1429  break;
1430 
1432  status = IntUpdateAddUserException((UPDATE_UM_EXCEPTION *)structure, &item);
1433  break;
1434 
1437  break;
1438 
1440  status = IntUpdateAddKernelUserException((UPDATE_KUM_EXCEPTION *)structure, &item);
1441  break;
1442 
1443  default:
1444  // For future versions: ignore unknown types
1445  WARNING("[WARNING] Unknown exception/signature type '%d'. Will ignore ...\n", header->Type);
1446  status = INT_STATUS_NOT_NEEDED_HINT;
1447  break;
1448  }
1449 
1450  if (!INT_SUCCESS(status))
1451  {
1452  ERROR("[ERROR] Failed adding exception/signature. Will abort the update. Reason=0x%08x\n", status);
1453  return status;
1454  }
1455  }
1456 
1458 
1459  gGuest.Exceptions->Version.Build = fileHeader->BuildNumber;
1460  gGuest.Exceptions->Version.Major = fileHeader->Version.Major;
1461  gGuest.Exceptions->Version.Minor = fileHeader->Version.Minor;
1462 
1464 
1465  LOG("[UPDATE] Updated exceptions to version %d.%d.%d\n",
1466  fileHeader->Version.Major, fileHeader->Version.Minor, fileHeader->BuildNumber);
1467 
1468  return INT_STATUS_SUCCESS;
1469 }
1470 
1471 
1472 static void
1474  _In_ UM_EXCEPTION *Exception
1475  )
1484 {
1485  LIST_HEAD *head;
1486 
1487  TRACE("[UPDATE] Add exception %08x -> %08x, %08x, %d, %08x\n",
1488  Exception->OriginatorNameHash, Exception->Victim.ProcessHash, Exception->Victim.NameHash,
1489  Exception->Type, Exception->Flags);
1490 
1491  if (Exception->SigCount == 1)
1492  {
1493  TRACE("[UPDATE] sig: 0x%08x\n", Exception->Signatures[0].Value);
1494  }
1495  else if (Exception->SigCount > 0)
1496  {
1497  TRACE("[UPDATE] sig: %d signatures\n", Exception->SigCount);
1498  }
1499 
1500  if (Exception->Type == umObjProcessCreation)
1501  {
1503  }
1504  else
1505  {
1507  }
1508 
1509  for_each_um_exception((*head), pEx)
1510  {
1511  // Every list is ordered, so break when we got to a hash bigger than ours
1512  if (pEx->OriginatorNameHash > Exception->OriginatorNameHash)
1513  {
1514  pEx = CONTAINING_RECORD(pEx->Link.Blink, UM_EXCEPTION, Link);
1515 
1516  InsertAfterList(&pEx->Link, &Exception->Link);
1517 
1518  return;
1519  }
1520  }
1521 
1522  // We didn't found an exception that has a hash bigger than ours. Insert at the end of the list!
1523  InsertTailList(head, &Exception->Link);
1524 }
1525 
1526 
1527 static void
1529  _In_ KM_EXCEPTION *Exception
1530  )
1538 {
1539  TRACE("[UPDATE] Add exception %08x -> %08x, %d, %08x\n",
1540  Exception->OriginatorNameHash, Exception->VictimNameHash,
1541  Exception->Type, Exception->Flags);
1542 
1543  if (Exception->SigCount == 1)
1544  {
1545  TRACE("[UPDATE] sig: %d\n", Exception->Signatures[0].Value);
1546  }
1547  else if (Exception->SigCount > 0)
1548  {
1549  TRACE("[UPDATE] sig: %d signatures\n", Exception->SigCount);
1550  }
1551 
1553  {
1554  // Every list is ordered, so break when we got to a hash bigger than ours
1555  if (pEx->OriginatorNameHash > Exception->OriginatorNameHash)
1556  {
1557  pEx = CONTAINING_RECORD(pEx->Link.Blink, KM_EXCEPTION, Link);
1558 
1559  InsertAfterList(&pEx->Link, &Exception->Link);
1560 
1561  return;
1562  }
1563  }
1564 
1565  // We didn't found an exception that has a hash bigger than ours. Insert at the end of the list!
1567 }
1568 
1569 
1570 static void
1572  _In_ KUM_EXCEPTION *Exception
1573  )
1581 {
1582  TRACE("[UPDATE] Add exception %08x -> %08x %08x, %d, %08x\n",
1583  Exception->OriginatorNameHash, Exception->Victim.NameHash, Exception->Victim.ProcessHash,
1584  Exception->Type, Exception->Flags);
1585 
1586  TRACE("[UPDATE] Signatures = %d \n", Exception->SigCount);
1587 
1589  {
1590  // Every list is ordered, so break when we got to a hash bigger than ours
1591  if (pEx->OriginatorNameHash > Exception->OriginatorNameHash)
1592  {
1593  pEx = CONTAINING_RECORD(pEx->Link.Blink, KUM_EXCEPTION, Link);
1594 
1595  InsertAfterList(&pEx->Link, &Exception->Link);
1596 
1597  return;
1598  }
1599  }
1600 
1601  // We didn't found an exception that has a hash bigger than ours. Insert at the end of the list!
1603 }
1604 
1605 
1606 static INTSTATUS
1608  _In_ const ALERT_EXPORT_SIGNATURE *AlertSig,
1609  _Out_ SIG_EXPORT **Signature
1610  )
1621 {
1622  if (AlertSig->Header.Version != ALERT_EXPORT_SIGNATURE_VERSION)
1623  {
1624  ERROR("[ERROR] Unsupported export signature version: %d. We have %d\n",
1625  AlertSig->Header.Version, ALERT_EXPORT_SIGNATURE_VERSION);
1627  }
1628 
1629  SIG_EXPORT *pSig = HpAllocWithTag(sizeof(*pSig) + sizeof(SIG_EXPORT_HASH), IC_TAG_ESIG);
1630  if (NULL == pSig)
1631  {
1633  }
1634 
1636  pSig->LibraryNameHash = AlertSig->Library;
1637  pSig->Flags = AlertSig->Flags;
1638  pSig->ListsCount = 1;
1639  pSig->AlertSignature = TRUE;
1640 
1641  SIG_EXPORT_HASH *pSigHash = (SIG_EXPORT_HASH *)pSig->Object;
1642 
1643  pSigHash->Hash = AlertSig->Function;
1644  pSigHash->Delta = (WORD)(AlertSig->Delta + AlertSig->WriteSize);
1645 
1646  TRACE("[INFO] Add Export signature on 0x%08x (0x%08x) with delta %d\n",
1647  AlertSig->Function, AlertSig->Library, pSigHash->Delta);
1648 
1649  *Signature = pSig;
1650 
1651  return INT_STATUS_SUCCESS;
1652 }
1653 
1654 
1655 static INTSTATUS
1657  _In_ const ALERT_IDT_SIGNATURE *AlertSig,
1658  _Out_ SIG_IDT **Signature
1659  )
1670 
1671 {
1672  if (AlertSig->Header.Version != ALERT_IDT_SIGNATURE_VERSION)
1673  {
1674  ERROR("[ERROR] Unsupported idt signature version: %d. We have %d\n",
1675  AlertSig->Header.Version, ALERT_IDT_SIGNATURE_VERSION);
1677  }
1678 
1679  SIG_IDT *pSignature = HpAllocWithTag(sizeof(*pSignature), IC_TAG_ESIG);
1680  if (NULL == pSignature)
1681  {
1683  }
1684 
1686  pSignature->Entry = AlertSig->Entry;
1687  pSignature->Flags = AlertSig->Flags;
1688  pSignature->AlertSignature = TRUE;
1689 
1690  TRACE("[INFO] Add Idt Signature on %d entry.", pSignature->Entry);
1691 
1692  *Signature = pSignature;
1693 
1694  return INT_STATUS_SUCCESS;
1695 }
1696 
1697 
1698 static INTSTATUS
1700  _In_ const ALERT_CB_SIGNATURE *AlertSig,
1701  _Out_ SIG_CODEBLOCKS **Signature
1702  )
1713 
1714 {
1715  if (AlertSig->Header.Version != ALERT_CB_SIGNATURE_VERSION)
1716  {
1717  WARNING("[WARNING] Unsupported cb signature version: %d. We have %d\n",
1718  AlertSig->Header.Version, ALERT_CB_SIGNATURE_VERSION);
1720  }
1721 
1722  if (AlertSig->Count > ALERT_HASH_COUNT)
1723  {
1725  }
1726 
1727  SIG_CODEBLOCKS *pSignature;
1728  SIG_CODEBLOCK_HASH *pSigHash;
1729 
1730  DWORD totalSize = sizeof(*pSignature) + sizeof(*pSigHash) + AlertSig->Count * sizeof(DWORD);
1731 
1732  pSignature = HpAllocWithTag(totalSize, IC_TAG_ESIG);
1733  if (NULL == pSignature)
1734  {
1736  }
1737 
1739 
1740  pSignature->Score = AlertSig->Score;
1741  pSignature->ListsCount = 1;
1742  pSignature->AlertSignature = TRUE;
1743  pSignature->Flags = AlertSig->Flags;
1744 
1745  pSigHash = (SIG_CODEBLOCK_HASH *)pSignature->Object;
1746 
1747  pSigHash->Count = AlertSig->Count;
1748  for (DWORD i = 0; i < pSigHash->Count; i++)
1749  {
1750  pSigHash->Hashes[i] = AlertSig->CodeBlocks[i];
1751  }
1752 
1753  // The code blocks are already sorted (see IntAlertCreateCbSignature), but considering that the exception buffer is
1754  // an external data, we should sort them again.
1755  UtilQuickSort(pSigHash->Hashes, pSigHash->Count, sizeof(pSigHash->Hashes[0]));
1756 
1757  *Signature = pSignature;
1758 
1759  return INT_STATUS_SUCCESS;
1760 }
1761 
1762 
1763 static INTSTATUS
1765  _In_ const ALERT_PROCESS_CREATION_SIGNATURE *AlertSig,
1766  _Out_ SIG_PROCESS_CREATION **Signature
1767  )
1778 {
1779  if (AlertSig->Header.Version != ALERT_PROCESS_CREATION_SIGNATURE_VERSION)
1780  {
1781  ERROR("[ERROR] Unsupported process-creation signature version: %d. We have %d\n",
1782  AlertSig->Header.Version, ALERT_PROCESS_CREATION_SIGNATURE_VERSION);
1784  }
1785 
1786  SIG_PROCESS_CREATION *pSignature;
1787 
1788  pSignature = HpAllocWithTag(sizeof(SIG_PROCESS_CREATION), IC_TAG_ESIG);
1789  if (NULL == pSignature)
1790  {
1792  }
1793 
1795 
1796  pSignature->AlertSignature = TRUE;
1797  pSignature->Flags = AlertSig->Flags;
1798  pSignature->CreateMask = AlertSig->CreateMask;
1799 
1800  *Signature = pSignature;
1801 
1802  return INT_STATUS_SUCCESS;
1803 }
1804 
1805 
1806 __nonnull() static BOOLEAN
1808  _In_ const ALERT_CB_SIGNATURE *Signature,
1809  _In_ const EXCEPTION_SIGNATURE_ID *SigIds,
1810  _In_ DWORD SigCount
1811  )
1821 {
1822  if (!Signature->Valid)
1823  {
1824  return FALSE;
1825  }
1826 
1828  {
1829  DWORD sigSize = 0;
1830 
1831  for (DWORD i = 0; i < SigCount; i++)
1832  {
1833  if (pSig->Id.Value != SigIds[i].Value)
1834  {
1835  continue;
1836  }
1837 
1838  for (DWORD j = 0; j < pSig->ListsCount; j++)
1839  {
1840  const SIG_CODEBLOCK_HASH *pHash = (const SIG_CODEBLOCK_HASH *)(pSig->Object + sigSize);
1841  sigSize += pHash->Count * sizeof(DWORD) + sizeof(*pHash);
1842 
1843  if (pHash->Count != Signature->Count)
1844  {
1845  continue;
1846  }
1847 
1848  if (0 == memcmp(pHash->Hashes, Signature->CodeBlocks, sizeof(DWORD) * pHash->Count))
1849  {
1850  return TRUE;
1851  }
1852  }
1853  }
1854  }
1855 
1856  return FALSE;
1857 }
1858 
1859 
1860 static BOOLEAN
1862  _In_ const ALERT_IDT_SIGNATURE *Signature,
1863  _In_ const EXCEPTION_SIGNATURE_ID *SigIds,
1864  _In_ DWORD SigCount
1865  )
1875 {
1876  if (!Signature->Valid)
1877  {
1878  return FALSE;
1879  }
1880 
1882  {
1883  for (DWORD iSig = 0; iSig < SigCount; iSig++)
1884  {
1885  if (pSignature->Id.Value != SigIds[iSig].Value)
1886  {
1887  continue;
1888  }
1889 
1890  if (Signature->Entry == pSignature->Entry)
1891  {
1892  return TRUE;
1893  }
1894  }
1895  }
1896 
1897  return FALSE;
1898 }
1899 
1900 
1901 static BOOLEAN
1903  _In_ const ALERT_EXPORT_SIGNATURE *Signature,
1904  _In_ const EXCEPTION_SIGNATURE_ID *SigIds,
1905  _In_ DWORD SigCount
1906  )
1916 {
1917  if (!Signature->Valid)
1918  {
1919  return FALSE;
1920  }
1921 
1922  for (DWORD i = 0; i < SigCount; i++)
1923  {
1925  {
1926  SIG_EXPORT_HASH *pSigHash = (SIG_EXPORT_HASH *)pSig->Object;
1927 
1928  if (pSig->Id.Value != SigIds[i].Value)
1929  {
1930  continue;
1931  }
1932 
1933  if (pSig->LibraryNameHash != Signature->Library)
1934  {
1935  continue;
1936  }
1937 
1938  for (DWORD j = 0; j < pSig->ListsCount; j++)
1939  {
1940  if (pSigHash[j].Hash == Signature->Function && pSigHash[j].Delta >= Signature->Delta)
1941  {
1942  return TRUE;
1943  }
1944  }
1945  }
1946  }
1947 
1948  return FALSE;
1949 }
1950 
1951 
1952 static BOOLEAN
1954  _In_ const ALERT_KM_EXCEPTION *Exception
1955  )
1965 {
1967  {
1968  if (Exception->Originator == pEx->OriginatorNameHash &&
1969  Exception->Victim == pEx->VictimNameHash &&
1970  Exception->Flags == pEx->Flags &&
1971  Exception->Type == pEx->Type)
1972  {
1973  if (pEx->SigCount != 0)
1974  {
1975  BOOLEAN isCbDuplicate = FALSE;
1976  BOOLEAN isIdtDuplicate = FALSE;
1977 
1978  if (IntUpdateIsDuplicateCbSignature(&Exception->CodeBlocks, pEx->Signatures, pEx->SigCount))
1979  {
1980  isCbDuplicate = TRUE;
1981  }
1982 
1983  if (IntUpdateIsDuplicateIdtSignature(&Exception->Idt, pEx->Signatures, pEx->SigCount))
1984  {
1985  isIdtDuplicate = TRUE;
1986  }
1987 
1988  if ((isIdtDuplicate && isCbDuplicate) ||
1989  (isCbDuplicate && !Exception->Idt.Valid) ||
1990  (isIdtDuplicate && !Exception->CodeBlocks.Valid))
1991  {
1992  TRACE("[UPDATE] Ignoring duplicate exception with signature: %08x -> %08x, %d, %08x\n",
1993  pEx->OriginatorNameHash, pEx->VictimNameHash, pEx->Type, pEx->Flags);
1994 
1995  return TRUE;
1996  }
1997  }
1998  else if (!Exception->CodeBlocks.Valid && !Exception->Idt.Valid)
1999  {
2000  // We didn't give a signature, nor we have one in the current exception
2001  TRACE("[UPDATE] Ignoring duplicate exception: %08x -> %08x, %d, %08x\n",
2002  pEx->OriginatorNameHash, pEx->VictimNameHash, pEx->Type, pEx->Flags);
2003 
2004  return TRUE;
2005  }
2006  }
2007 
2008  // Every list is ordered, so break when we got to a hash bigger than ours
2009  if (pEx->OriginatorNameHash > Exception->Originator)
2010  {
2011  break;
2012  }
2013  }
2014 
2015  return FALSE;
2016 }
2017 
2018 static BOOLEAN
2020  _In_ const ALERT_KUM_EXCEPTION *Exception
2021  )
2031 {
2033  {
2034  if (Exception->Originator == pEx->OriginatorNameHash &&
2035  Exception->Victim == pEx->Victim.NameHash &&
2036  Exception->Process == pEx->Victim.ProcessHash &&
2037  Exception->Flags == pEx->Flags &&
2038  Exception->Type == pEx->Type)
2039  {
2040  if (pEx->SigCount != 0)
2041  {
2042  if (IntUpdateIsDuplicateCbSignature(&Exception->CodeBlocks, pEx->Signatures, pEx->SigCount))
2043  {
2044  TRACE("[UPDATE] Ignoring duplicate exception with signature: %08x -> %08x - %08x, %d, %08x\n",
2045  pEx->OriginatorNameHash, pEx->Victim.NameHash, pEx->Victim.ProcessHash, pEx->Type, pEx->Flags);
2046 
2047  return TRUE;
2048  }
2049  }
2050  else if (!Exception->CodeBlocks.Valid)
2051  {
2052  // We didn't give a signature, nor we have one in the current exception
2053  TRACE("[UPDATE] Ignoring duplicate exception: %08x -> %08x %08x, %d, %08x\n",
2054  pEx->OriginatorNameHash, pEx->Victim.NameHash, pEx->Victim.ProcessHash, pEx->Type, pEx->Flags);
2055  return TRUE;
2056  }
2057  }
2058 
2059  // Every list is ordered, so break when we got to a hash bigger than ours
2060  if (pEx->OriginatorNameHash > Exception->Originator)
2061  {
2062  break;
2063  }
2064  }
2065 
2066  return FALSE;
2067 }
2068 
2069 
2070 static BOOLEAN
2072  _In_ const ALERT_UM_EXCEPTION *Exception
2073  )
2083 {
2084  LIST_HEAD *head;
2085 
2086  if (Exception->Type == umObjProcessCreation)
2087  {
2089  }
2090  else
2091  {
2093  }
2094 
2095  for_each_um_exception((*head), pEx)
2096  {
2097  if (Exception->Originator == pEx->OriginatorNameHash &&
2098  Exception->Victim == pEx->Victim.NameHash &&
2099  Exception->Process == pEx->Victim.ProcessHash &&
2100  Exception->Type == pEx->Type)
2101  {
2102  if (pEx->SigCount != 0)
2103  {
2104  BOOLEAN isCbDuplicate = FALSE;
2105  BOOLEAN isExportDuplicate = FALSE;
2106 
2107  if (IntUpdateIsDuplicateCbSignature(&Exception->CodeBlocks, pEx->Signatures, pEx->SigCount))
2108  {
2109  isCbDuplicate = TRUE;
2110  }
2111 
2112  if (IntUpdateIsDuplicateExportSignature(&Exception->Export, pEx->Signatures, pEx->SigCount))
2113  {
2114  isExportDuplicate = TRUE;
2115  }
2116 
2117  if ((isExportDuplicate && isCbDuplicate) ||
2118  (isCbDuplicate && !Exception->Export.Valid) ||
2119  (isExportDuplicate && !Exception->CodeBlocks.Valid))
2120  {
2121  TRACE("[UPDATE] Ignoring duplicate exception with signature: %08x -> %08x, %08x, %d, %08x\n",
2122  pEx->OriginatorNameHash, pEx->Victim.ProcessHash,
2123  pEx->Victim.NameHash, pEx->Type, pEx->Flags);
2124 
2125  return TRUE;
2126  }
2127  }
2128  else if (!Exception->CodeBlocks.Valid && !Exception->Export.Valid)
2129  {
2130  // We didn't give a signature, nor we have one in the current exception
2131  TRACE("[UPDATE] Ignoring duplicate exception: %08x -> %08x, %08x, %d, %08x\n",
2132  pEx->OriginatorNameHash, pEx->Victim.ProcessHash, pEx->Victim.NameHash,
2133  pEx->Type, pEx->Flags);
2134 
2135  return TRUE;
2136  }
2137  }
2138 
2139  // Every list is ordered, so break when we got to a hash bigger than ours
2140  if (pEx->OriginatorNameHash > Exception->Originator)
2141  {
2142  break;
2143  }
2144  }
2145 
2146  return FALSE;
2147 }
2148 
2149 
2150 static INTSTATUS
2152  _In_ const ALERT_UM_EXCEPTION *Exception,
2153  _In_ QWORD Context
2154  )
2170 {
2171  INTSTATUS status;
2172  DWORD sigCount = (Exception->CodeBlocks.Valid != 0) +
2173  (Exception->Export.Valid != 0) + (Exception->ProcessCreation.Valid);
2174  SIG_EXPORT *pExpSignature = NULL;
2175  SIG_CODEBLOCKS *pCbSignature = NULL;
2176  SIG_PROCESS_CREATION *pProcessCreationSignature = NULL;
2177 
2178  if (Exception->Header.Version != ALERT_UM_EXCEPTION_VERSION)
2179  {
2180  ERROR("[ERROR] Unsupported um exception version: %d. We have %d\n",
2181  Exception->Header.Version, ALERT_UM_EXCEPTION_VERSION);
2183  }
2184 
2185  if (IntUpdateIsDuplicateUserException(Exception))
2186  {
2188  }
2189 
2190  UM_EXCEPTION *pUmException = HpAllocWithTag(sizeof(*pUmException) + sigCount * sizeof(DWORD), IC_TAG_EXUM);
2191  if (NULL == pUmException)
2192  {
2194  }
2195 
2196  pUmException->Context = Context;
2197 
2198  pUmException->OriginatorNameHash = Exception->Originator;
2199  pUmException->Victim.NameHash = Exception->Victim;
2200  pUmException->Victim.ProcessHash = Exception->Process;
2201  pUmException->Flags = Exception->Flags;
2202  pUmException->Type = Exception->Type;
2203 
2204  if (Exception->CodeBlocks.Valid)
2205  {
2206  status = IntUpdateCreateCbSignatureFromAlert(&Exception->CodeBlocks, &pCbSignature);
2207  if (!INT_SUCCESS(status))
2208  {
2209  ERROR("[ERROR] IntUpdateCreateCbSignatureFromAlert failed with status: 0x%08x\n", status);
2210  goto _exit;
2211  }
2212  else
2213  {
2214  pUmException->Signatures[pUmException->SigCount] = pCbSignature->Id;
2215  pUmException->SigCount++;
2216 
2217  InsertTailList(&gGuest.Exceptions->CbSignatures, &pCbSignature->Link);
2218  }
2219  }
2220 
2221  if (Exception->Export.Valid)
2222  {
2223  status = IntUpdateCreateExportSignatureFromAlert(&Exception->Export, &pExpSignature);
2224  if (!INT_SUCCESS(status))
2225  {
2226  WARNING("[WARNING] IntUpdateCreateExportSignatureFromAlert failed with status: 0x%08x.\n", status);
2227  goto _exit;
2228  }
2229  else
2230  {
2231  pUmException->Signatures[pUmException->SigCount] = pExpSignature->Id;
2232  pUmException->SigCount++;
2233 
2235  }
2236  }
2237 
2238  if (Exception->ProcessCreation.Valid)
2239  {
2240  status = IntUpdateCreateProcessCreationSignatureFromAlert(&Exception->ProcessCreation,
2241  &pProcessCreationSignature);
2242  if (!INT_SUCCESS(status))
2243  {
2244  ERROR("[ERROR] IntUpdateCreateProcessCreationSignatureFromAlert failed with status: 0x%08x.\n", status);
2245  goto _exit;
2246  }
2247  else
2248  {
2249  pUmException->Signatures[pUmException->SigCount] = pProcessCreationSignature->Id;
2250  pUmException->SigCount++;
2251 
2252  InsertTailList(&gGuest.Exceptions->ProcessCreationSignatures, &pProcessCreationSignature->Link);
2253  }
2254  }
2255 
2256  IntUpdateAddUserExceptionInOrder(pUmException);
2257 
2258  return INT_STATUS_SUCCESS;
2259 
2260 _exit:
2261  if (pCbSignature != NULL)
2262  {
2263  IntExceptErase(pCbSignature, IC_TAG_ESIG);
2264  }
2265 
2266  if (pProcessCreationSignature != NULL)
2267  {
2268  IntExceptErase(pProcessCreationSignature, IC_TAG_ESIG);
2269  }
2270 
2271  if (pExpSignature != NULL)
2272  {
2273  IntExceptErase(pExpSignature, IC_TAG_ESIG);
2274  }
2275 
2276  HpFreeAndNullWithTag(&pUmException, IC_TAG_EXUM);
2277 
2278  return status;
2279 }
2280 
2281 
2282 static INTSTATUS
2284  _In_ const ALERT_KM_EXCEPTION *Exception,
2285  _In_ QWORD Context
2286  )
2302 {
2303  INTSTATUS status;
2304 
2305  DWORD sigCount = (Exception->Idt.Valid != 0) + (Exception->CodeBlocks.Valid != 0);
2306  SIG_CODEBLOCKS *pCbSignature = NULL;
2307  SIG_IDT *pIdtSignature = NULL;
2308 
2309  if (Exception->Header.Version != ALERT_KM_EXCEPTION_VERSION)
2310  {
2311  ERROR("[ERROR] Unsupported km exception version: %d. We have %d\n",
2312  Exception->Header.Version, ALERT_KM_EXCEPTION_VERSION);
2314  }
2315 
2316  if (IntUpdateIsDuplicateKernelException(Exception))
2317  {
2319  }
2320 
2321  KM_EXCEPTION *pKmException = HpAllocWithTag(sizeof(*pKmException) + sigCount * sizeof(DWORD), IC_TAG_EXKM);
2322  if (NULL == pKmException)
2323  {
2325  }
2326 
2327  pKmException->Context = Context;
2328  pKmException->OriginatorNameHash = Exception->Originator;
2329  pKmException->VictimNameHash = Exception->Victim;
2330  pKmException->Flags = Exception->Flags;
2331  pKmException->Type = Exception->Type;
2332 
2333  if (Exception->Idt.Valid)
2334  {
2335  status = IntUpdateCreateIdtSignatureFromAlert(&Exception->Idt, &pIdtSignature);
2336  if (!INT_SUCCESS(status))
2337  {
2338  ERROR("[ERROR] IntUpdateCreateIdtSignatureFromAlert failed with status: 0x%08x.\n", status);
2339  goto _exit;
2340  }
2341  else
2342  {
2343  pKmException->Signatures[pKmException->SigCount] = pIdtSignature->Id;
2344  pKmException->SigCount++;
2345 
2346  InsertTailList(&gGuest.Exceptions->IdtSignatures, &pIdtSignature->Link);
2347  }
2348  }
2349 
2350  if (Exception->CodeBlocks.Valid)
2351  {
2352  status = IntUpdateCreateCbSignatureFromAlert(&Exception->CodeBlocks, &pCbSignature);
2353  if (!INT_SUCCESS(status))
2354  {
2355  ERROR("[ERROR] IntUpdateCreateCbSignatureFromAlert failed with status: 0x%08x.\n", status);
2356  goto _exit;
2357  }
2358  else
2359  {
2360  pKmException->Signatures[pKmException->SigCount] = pCbSignature->Id;
2361  pKmException->SigCount++;
2362 
2363  InsertTailList(&gGuest.Exceptions->CbSignatures, &pCbSignature->Link);
2364  }
2365  }
2366 
2367  IntUpdateAddKernelExceptionInOrder(pKmException);
2368 
2369  return INT_STATUS_SUCCESS;
2370 
2371 _exit:
2372  if (pCbSignature != NULL)
2373  {
2374  IntExceptErase(pCbSignature, IC_TAG_ESIG);
2375  }
2376 
2377  if (pIdtSignature != NULL)
2378  {
2379  IntExceptErase(pIdtSignature, IC_TAG_ESIG);
2380  }
2381 
2382  HpFreeAndNullWithTag(&pKmException, IC_TAG_EXKM);
2383 
2384  return status;
2385 }
2386 
2387 
2388 static INTSTATUS
2390  _In_ const ALERT_KUM_EXCEPTION *Exception,
2391  _In_ QWORD Context
2392  )
2408 {
2409  INTSTATUS status;
2410  DWORD sigCount = (Exception->CodeBlocks.Valid != 0);
2411  SIG_CODEBLOCKS *pCbSignature = NULL;
2412 
2413  if (Exception->Header.Version != ALERT_KM_EXCEPTION_VERSION)
2414  {
2415  ERROR("[ERROR] Unsupported km exception version: %d. We have %d\n",
2416  Exception->Header.Version, ALERT_KM_EXCEPTION_VERSION);
2418  }
2419 
2421  {
2423  }
2424 
2425  KUM_EXCEPTION *pException = HpAllocWithTag(sizeof(*pException) + sigCount * sizeof(DWORD), IC_TAG_EXKU);
2426  if (NULL == pException)
2427  {
2429  }
2430 
2431  pException->Context = Context;
2432  pException->OriginatorNameHash = Exception->Originator;
2433  pException->Victim.NameHash = Exception->Victim;
2434  pException->Victim.ProcessHash = Exception->Process;
2435  pException->Flags = Exception->Flags;
2436  pException->Type = Exception->Type;
2437 
2438  if (Exception->CodeBlocks.Valid)
2439  {
2440  status = IntUpdateCreateCbSignatureFromAlert(&Exception->CodeBlocks, &pCbSignature);
2441  if (!INT_SUCCESS(status))
2442  {
2443  ERROR("[ERROR] IntUpdateCreateCbSignatureFromAlert failed with status: 0x%08x.\n", status);
2444  goto _exit;
2445  }
2446  else
2447  {
2448  pException->Signatures[pException->SigCount] = pCbSignature->Id;
2449  pException->SigCount++;
2450 
2451  InsertTailList(&gGuest.Exceptions->CbSignatures, &pCbSignature->Link);
2452  }
2453  }
2454 
2456 
2457  return INT_STATUS_SUCCESS;
2458 
2459 _exit:
2460  if (pCbSignature != NULL)
2461  {
2462  IntExceptErase(pCbSignature, IC_TAG_ESIG);
2463  }
2464 
2465  HpFreeAndNullWithTag(&pException, IC_TAG_EXKU);
2466 
2467  return status;
2468 }
2469 
2470 
2471 INTSTATUS
2473  _In_ const void *Event,
2474  _In_ INTRO_EVENT_TYPE Type,
2475  _In_ BOOLEAN Exception,
2476  _In_ QWORD Context
2477  )
2498 {
2499  INTSTATUS status;
2500  const void *pException;
2501  QWORD violationFlags;
2502  BYTE pBuff[ALERT_EXCEPTION_SIZE] = { 0 };
2503 
2504  if (NULL == Event)
2505  {
2507  }
2508 
2509  if (!IntAlertIsEventTypeViolation(Type))
2510  {
2511  ERROR("[ERROR] Failed to add exception of type %d!\n", Type);
2512  return INT_STATUS_NOT_SUPPORTED;
2513  }
2514 
2515  if (Exception)
2516  {
2517  const INTRO_ALERT_EXCEPTION_HEADER *header = Event;
2518 
2519  pException = Event;
2520  violationFlags = header->ViolationFlags;
2521 
2522  if (!header->Valid)
2523  {
2524  ERROR("[ERROR] Exception of type %d is invalid!\n", Type);
2526  }
2527  }
2528  else
2529  {
2530  const INTRO_VIOLATION_HEADER *header = Event;
2531 
2532  violationFlags = header->Flags;
2533 
2534  status = IntAlertCreateException(Event, Type, TRUE, pBuff);
2535  if (!INT_SUCCESS(status))
2536  {
2537  ERROR("[ERROR] IntAlertCreateException failed: %08x\n", status);
2538  return status;
2539  }
2540 
2541  pException = (const void *)pBuff;
2542  }
2543 
2544  if (NULL == gGuest.Exceptions)
2545  {
2546  status = IntExceptInit();
2547  if (!INT_SUCCESS(status))
2548  {
2549  ERROR("[ERROR] IntExceptInit failed: 0x%08x\n", status);
2550  return status;
2551  }
2552  }
2553 
2554  if (Type == introEventEptViolation)
2555  {
2556  if (violationFlags & ALERT_FLAG_KM_UM)
2557  {
2558  status = IntUpdateAddKmUmException(pException, Context);
2559  }
2560  else if (violationFlags & ALERT_FLAG_NOT_RING0)
2561  {
2562  status = IntUpdateAddUmException(pException, Context);
2563  }
2564  else
2565  {
2566  status = IntUpdateAddKmException(pException, Context);
2567  }
2568  }
2569  else if (introEventMsrViolation == Type ||
2570  introEventCrViolation == Type ||
2571  introEventDtrViolation == Type ||
2573  {
2574  status = IntUpdateAddKmException(pException, Context);
2575  }
2576  else if (introEventInjectionViolation == Type ||
2579  {
2580  status = IntUpdateAddUmException(pException, Context);
2581  }
2582  else
2583  {
2584  status = INT_STATUS_NOT_SUPPORTED;
2585  }
2586 
2587  if (!INT_SUCCESS(status))
2588  {
2589  ERROR("[ERROR] Failed to add exception of type %d: 0x%08x\n", Type, status);
2590  }
2591 
2592  return status;
2593 }
2594 
2595 
2596 static void
2598  _In_ EXCEPTION_SIGNATURE_ID *Signatures,
2599  _In_ DWORD Count
2600  )
2607 {
2608  for (DWORD i = 0; i < Count; i++)
2609  {
2610  switch (Signatures[i].Field.Type)
2611  {
2612  case signatureTypeExport :
2613  {
2615  {
2616  if (pSignature->AlertSignature && pSignature->Id.Value == Signatures[i].Value)
2617  {
2618  IntExceptErase(pSignature, IC_TAG_ESIG);
2619  break;
2620  }
2621  }
2622 
2623  break;
2624  }
2625 
2627  {
2629  {
2630  if (pSignature->AlertSignature && pSignature->Id.Value == Signatures[i].Value)
2631  {
2632  IntExceptErase(pSignature, IC_TAG_ESIG);
2633  break;
2634  }
2635  }
2636 
2637  break;
2638  }
2639 
2640  case signatureTypeIdt :
2641  {
2643  {
2644  if (pSignature->AlertSignature && pSignature->Id.Value == Signatures[i].Value)
2645  {
2646  IntExceptErase(pSignature, IC_TAG_ESIG);
2647  break;
2648  }
2649  }
2650 
2651  break;
2652  }
2653 
2654  default:
2655  {
2656  ERROR("[ERROR] Should not reach here. Type is %d\n", Signatures[i].Field.Type);
2657  return;
2658  }
2659  }
2660  }
2661 }
2662 
2663 
2664 INTSTATUS
2666  _In_opt_ QWORD Context
2667  )
2679 {
2680  if (NULL == gGuest.Exceptions)
2681  {
2683  }
2684 
2686  {
2687  if (pException->Context == Context)
2688  {
2689  IntUpdateRemoveSignaturesForException(pException->Signatures, pException->SigCount);
2690  IntExceptErase(pException, IC_TAG_EXUM);
2691  return INT_STATUS_SUCCESS;
2692  }
2693  }
2694 
2696  {
2697  if (pException->Context == Context)
2698  {
2699  IntUpdateRemoveSignaturesForException(pException->Signatures, pException->SigCount);
2700  IntExceptErase(pException, IC_TAG_EXUM);
2701  return INT_STATUS_SUCCESS;
2702  }
2703  }
2704 
2706  {
2707  if (pException->Context == Context)
2708  {
2709  IntUpdateRemoveSignaturesForException(pException->Signatures, pException->SigCount);
2710  IntExceptErase(pException, IC_TAG_EXUM);
2711  return INT_STATUS_SUCCESS;
2712  }
2713  }
2714 
2715  return INT_STATUS_NOT_FOUND;
2716 }
2717 
2718 
2719 INTSTATUS
2721  void
2722  )
2729 {
2730  INTSTATUS status;
2731 
2732  if (NULL == gGuest.Exceptions)
2733  {
2735  }
2736 
2737  TRACE("[INFO] Requesting to flush alert exceptions!\n");
2738 
2739  status = IntExceptAlertRemove();
2740  if (!INT_SUCCESS(status))
2741  {
2742  return status;
2743  }
2744 
2745  return INT_STATUS_SUCCESS;
2746 }
2747 
2748 
2749 BOOLEAN
2751  void
2752  )
2758 {
2760 }
QWORD ViolationFlags
A combination of Alert flags values describing the alert.
Definition: intro_types.h:1064
BOOLEAN Valid
Set to True if the information in the structure is valid, False otherwise.
Definition: intro_types.h:1065
EXCEPTION_SIGNATURE_ID Id
An unique id (EXCEPTION_SIGNATURE_ID).
Definition: exceptions.h:409
#define _In_opt_
Definition: intro_sal.h:16
WORD SigCount
Contains the number of signatures.
Definition: exceptions.h:262
QWORD Context
Contains the context given by the integrator.
Definition: exceptions.h:316
The header of an exception or a signature.
_Bool BOOLEAN
Definition: intro_types.h:58
#define _Out_
Definition: intro_sal.h:22
#define CONTAINING_RECORD(List, Type, Member)
Definition: introlists.h:36
static INTSTATUS IntUpdateCreateCbSignatureFromAlert(const ALERT_CB_SIGNATURE *AlertSig, SIG_CODEBLOCKS **Signature)
Creates a new code-blocks signature from an /ref ALERT_CB_SIGNATURE.
Sent for unauthorized process creation alerts. See EVENT_PROCESS_CREATION_VIOLATION.
Definition: intro_types.h:115
BOOLEAN AlertSignature
True if the signature is added from alert.
Definition: exceptions.h:396
static void IntUpdateRemoveSignaturesForException(EXCEPTION_SIGNATURE_ID *Signatures, DWORD Count)
This function removes and frees all signature from the provided array.
#define UPDATE_TYPE_KUM_EXCEPTION
DWORD RemainingFileSize
The remaining bytes for the exceptions file.
The exception ID. The layout consists of the exception type and the unique identifier of the exceptio...
Definition: exceptions.h:233
uint8_t BYTE
Definition: intro_types.h:47
static INTSTATUS IntUpdateAddIdtSignature(UPDATE_IDT_SIGNATURE *UpdateSignature, UPDATE_ITEM_SIZE *Item)
Creates a new IDT signature and adds it to our internal list.
Describe a export signature hash.
Definition: exceptions.h:377
#define UPDATE_TYPE_EXPORT_SIGNATURE
Describes a process-creation signature.
Definition: exceptions.h:564
LIST_HEAD KernelUserExceptions[EXCEPTION_TABLE_SIZE]
Array of linked lists used for kernel-user mode exceptions.
Definition: exceptions.h:109
DWORD EntrySize
The size of the current exception/signature.
LIST_HEAD ValueCodeSignatures
Linked list used for value-code signatures.
Definition: exceptions.h:134
#define _In_
Definition: intro_sal.h:21
Describe a kernel-user mode exception.
Definition: exceptions.h:270
#define INT_STATUS_SUCCESS
Definition: introstatus.h:54
static INTSTATUS IntUpdateAddVersionIntroSignature(UPDATE_VERSION_INTRO_SIGNATURE *UpdateSignature, UPDATE_ITEM_SIZE *Item)
Creates a new introspection version signature and adds it to our internal list.
#define ALERT_IDT_SIGNATURE_VERSION
BYTE Score
The number of (minimum) hashes from a list that need to match.
Definition: exceptions.h:394
#define BIT(x)
Definition: common.h:51
QWORD Context
Contains the context given by the integrator.
Definition: exceptions.h:287
static EXCEPTION_SIGNATURE_ID gCurrentSignatureId
The current signature ID. Changes every time a new ID is generated.
WORD Offset
The displacement from the beginning of the modified zone.
Definition: exceptions.h:368
LIST_HEAD NoNameKernelExceptions
Linked list used for kernel-mode exceptions that don&#39;t have a valid originator (-).
Definition: exceptions.h:98
The name can be any string.
Definition: exceptions.h:626
#define UPDATE_TYPE_APC_UM_EXCEPTION
uint16_t WORD
Definition: intro_types.h:48
Describes a value signature.
Definition: exceptions.h:405
Describe a code-blocks hash in binary format.
WORD Delta
The number of bytes that are modified.
Definition: exceptions.h:379
struct _UM_EXCEPTION::@29 Victim
Describes a kernel-mode alert-exception.
Describe a kernel-mode exception in binary format.
#define UPDATE_EXCEPTIONS_MIN_VER_MAJOR
DWORD Build
Definition: exceptions.h:142
#define UPDATE_TYPE_IDT_SIGNATURE
#define UPDATE_VALIDATE_FILE_SIZE
Validate that an object fits inside the exception buffer.
Sent when a DTR violation triggers an alert. See EVENT_DTR_VIOLATION.
Definition: intro_types.h:98
LIST_HEAD GenericUserExceptions
Linked list used for user-mode exceptions that have a generic originator(*).
Definition: exceptions.h:92
INTSTATUS IntUpdateFlushAlertExceptions(void)
This function removes all exceptions that were added from alerts.
char OriginatorNameGlob[EXCEPTION_UM_GLOB_LENGTH]
Contains the name (a string that can contain glob items) of the originator.
Definition: exceptions.h:331
INTSTATUS IntUpdateLoadExceptions(void *Buffer, DWORD Length, DWORD Flags)
Handles the exceptions coming from the integrator.
QWORD Context
Contains the context given by the integrator.
Definition: exceptions.h:260
LIST_HEAD ExportSignatures
Linked list used for export signatures.
Definition: exceptions.h:132
union _EXCEPTION_SIGNATURE_ID EXCEPTION_SIGNATURE_ID
The exception ID. The layout consists of the exception type and the unique identifier of the exceptio...
LIST_HEAD ProcessCreationAlertExceptions
Linked list used for process-creation exceptions that are added from alert.
Definition: exceptions.h:123
WORD Object[]
Contains list of opcodes.
Definition: exceptions.h:416
#define UPDATE_TYPE_UM_EXCEPTION_GLOB_MATCH
The exception sends a feedback alert.
Definition: exceptions.h:585
struct _SIG_CODEBLOCK_HASH SIG_CODEBLOCK_HASH
Describe a codeblocks signature hash.
static INTSTATUS IntUpdateAddUserExceptionGlob(UPDATE_UM_EXCEPTION_GLOB *UpdateException, UPDATE_ITEM_SIZE *Item)
Creates a new glob user-exception and adds it to our internal list.
KM_EXCEPTION_OBJECT Type
Contains the type of the exception (KM_EXCEPTION_OBJECT).
Definition: exceptions.h:258
#define INT_SUCCESS(Status)
Definition: introstatus.h:42
Describe a export hash in binary format.
Sent when a CR violation triggers an alert. See EVENT_CR_VIOLATION.
Definition: intro_types.h:88
EXCEPTION_SIGNATURE_ID Id
An unique id (_EXCEPTION_SIGNATURE_ID).
Definition: exceptions.h:391
QWORD Flags
A combination of ALERT_FLAG_* values describing the alert.
Definition: intro_types.h:1087
DWORD OriginatorNameHash
Contains the originator name-hash.
Definition: exceptions.h:252
Describe a version OS signature in binary format.
#define UPDATE_MAGIC_WORD
EXCEPTION_SIGNATURE_ID Id
An unique id (EXCEPTION_SIGNATURE_ID).
Definition: exceptions.h:568
Describe a process-creation signature in binary format.
LIST_HEAD VersionIntroSignatures
Linked list used for introspection version signatures.
Definition: exceptions.h:137
Describe a user-mode glob exception.
Definition: exceptions.h:326
LIST_HEAD ProcessCreationSignatures
Linked list used for process-creation signatures.
Definition: exceptions.h:138
BYTE ListsCount
The number of the list of hashes.
Definition: exceptions.h:432
The exception is valid only for read violation.
Definition: exceptions.h:595
static BOOLEAN IntUpdateIsDuplicateUserException(const ALERT_UM_EXCEPTION *Exception)
Checks if the provided user-mode exception already exists in out list.
struct _UPDATE_VALUE_HASH UPDATE_VALUE_HASH
Describe a value hash in binary format.
LIST_HEAD IdtSignatures
Linked list used for IDT signatures.
Definition: exceptions.h:135
BOOLEAN AlertSignature
True if the signature is added from alert.
Definition: exceptions.h:451
EXCEPTION_SIGNATURE_ID Id
An unique id (EXCEPTION_SIGNATURE_ID).
Definition: exceptions.h:427
#define INT_STATUS_NOT_NEEDED_HINT
Definition: introstatus.h:317
BOOLEAN IntAlertIsEventTypeViolation(INTRO_EVENT_TYPE Type)
#define IntExceptErase(Ptr, Tag)
Frees an exception or a signature buffer and removes it from the list it is currently in...
Definition: exceptions.h:1316
#define ERROR(fmt,...)
Definition: glue.h:62
BYTE Entry
The number of the IDT entry.
Definition: exceptions.h:467
LIST_HEAD UserAlertExceptions
Linked list used for user-mode exceptions that are added from alert.
Definition: exceptions.h:125
LIST_ENTRY Link
Definition: exceptions.h:425
#define for_each_um_exception(_ex_head, _var_name)
Definition: exceptions.h:1002
struct _SIG_VALUE_HASH SIG_VALUE_HASH
Describe a value signature hash.
#define HpAllocWithTag(Len, Tag)
Definition: glue.h:516
static BOOLEAN IntUpdateIsValidEntry(DWORD Size, UPDATE_ITEM_SIZE *Item, DWORD Flags)
Checks if the provided Size can be read from the exceptions file without exceeding its size...
The name can be any string.
Definition: exceptions.h:652
The range-identifier used for idt signature.
Definition: exceptions.h:78
LIST_HEAD UserExceptions[EXCEPTION_TABLE_SIZE]
Array of linked lists used for user-mode exceptions.
Definition: exceptions.h:110
int INTSTATUS
The status data type.
Definition: introstatus.h:24
BOOLEAN Loaded
True if the exceptions are loaded.
Definition: exceptions.h:147
WORD Minor
The minor version of the exceptions binary file.
Contains the information about the sizes of an entry (exception/signature) and about the size of the ...
#define INT_STATUS_NOT_FOUND
Definition: introstatus.h:284
KUM_EXCEPTION_OBJECT Type
Contains the type of the exception (KM_EXCEPTION_OBJECT).
Definition: exceptions.h:285
The exception is valid only for Linux.
Definition: exceptions.h:593
INTSTATUS IntExceptAlertRemove(void)
This function removes and frees all exceptions and signatures that have been added from alert...
Definition: exceptions.c:382
EXCEPTION_SIGNATURE_ID Id
An unique id (EXCEPTION_SIGNATURE_ID).
Definition: exceptions.h:446
INTSTATUS IntUpdateRemoveException(QWORD Context)
This function removes an exception for a given context.
DWORD NameHash
Definition: exceptions.h:306
LIST_HEAD KernelAlertExceptions
Linked list used for kernel-mode exceptions that are added from alert.
Definition: exceptions.h:127
The name is missing.
Definition: exceptions.h:630
Sent for code/data injection alerts. See EVENT_MEMCOPY_VIOLATION.
Definition: intro_types.h:96
WORD Size
The size of of the modified zone.
Definition: exceptions.h:369
#define IC_TAG_ESIG
Exception signatures structures.
Definition: memtags.h:26
#define for_each_idt_signature(_ex_head, _var_name)
Definition: exceptions.h:1014
INTRO_GUEST_TYPE OSType
The type of the guest.
Definition: guests.h:274
#define ALERT_EXPORT_SIGNATURE_VERSION
static BOOLEAN IntUpdateIsDuplicateKernelException(const ALERT_KM_EXCEPTION *Exception)
Checks if the provided kernel-mode exception already exists in out list.
BOOLEAN AlertSignature
True if the signature is added from alert.
Definition: exceptions.h:528
Describe a value hash in binary format.
The exception is valid only for write violation.
Definition: exceptions.h:596
The range-identifier used for process creation signature.
Definition: exceptions.h:75
Describe an IDT signature in binary format.
#define MIN(a, b)
Definition: introdefs.h:146
DWORD Flags
Contains any flags from EXCEPTION_FLG.
Definition: exceptions.h:256
struct _KUM_EXCEPTION::@28 Victim
BYTE ListsCount
The number of the list of hashes.
Definition: exceptions.h:450
Describe a value-code signature in binary format.
static INTSTATUS IntUpdateCreateProcessCreationSignatureFromAlert(const ALERT_PROCESS_CREATION_SIGNATURE *AlertSig, SIG_PROCESS_CREATION **Signature)
Creates a new process-creation signature from an /ref ALERT_PROCESS_CREATION_SIGNATURE.
WORD Size
The size of the exception/signature.
static INTSTATUS IntUpdateAddValueSignature(UPDATE_VALUE_SIGNATURE *UpdateSignature, UPDATE_ITEM_SIZE *Item)
Creates a new value signature and adds it to our internal list.
#define UPDATE_TYPE_PROCESS_CREATION_SIGNATURE
#define LOG(fmt,...)
Definition: glue.h:61
The name is missing.
Definition: exceptions.h:657
Describes a value signature.
Definition: exceptions.h:442
#define ALERT_FLAG_KM_UM
If set, the alert was generated by a kernel to user mode violation.
Definition: intro_types.h:649
Describes a user-mode alert-exception.
static INTSTATUS IntUpdateAddKernelUserException(UPDATE_KUM_EXCEPTION *UpdateException, UPDATE_ITEM_SIZE *Item)
Creates a new kernel-user mode exception and adds it to our internal list.
union _SIG_VERSION_INTRO::@37 Minimum
DWORD BuildNumber
The build number of the exceptions binary file.
DWORD ProcessHash
Contains the name-hash of the process in which the modification takes place.
Definition: exceptions.h:280
DWORD Flags
Contains any flags from SIGNATURE_FLG.
Definition: exceptions.h:569
static INTSTATUS IntUpdateAddKernelException(UPDATE_KM_EXCEPTION *UpdateException, UPDATE_ITEM_SIZE *Item)
Creates a new kernel-exception and adds it to our internal list.
BOOLEAN AlertSignature
True if the signature is added from alert.
Definition: exceptions.h:414
static BOOLEAN IntUpdateIsDuplicateExportSignature(const ALERT_EXPORT_SIGNATURE *Signature, const EXCEPTION_SIGNATURE_ID *SigIds, DWORD SigCount)
Checks if the provided export alert-signature already exists in our list.
LIST_HEAD CbSignatures
Linked list used for codeblocks signatures.
Definition: exceptions.h:131
static INTSTATUS IntUpdateCreateIdtSignatureFromAlert(const ALERT_IDT_SIGNATURE *AlertSig, SIG_IDT **Signature)
Creates a new IDT signature from an /ref ALERT_IDT_SIGNATURE.
void IntUpdateAssignAlertSignatureIds(void)
Generates IDs for exceptions that were added from alert.
#define EXCEPTION_UM_GLOB_LENGTH
Definition: exceptions.h:36
The range-identifier used for export signature.
Definition: exceptions.h:76
DWORD Flags
Contains any flags from EXCEPTION_FLG.
Definition: exceptions.h:342
static INTSTATUS IntUpdateAddUserException(UPDATE_UM_EXCEPTION *UpdateException, UPDATE_ITEM_SIZE *Item)
Creates a new user-exception and adds it to our internal list.
BOOLEAN IntUpdateAreExceptionsLoaded(void)
Checks if the exceptions are loaded.
struct _UPDATE_ITEM_SIZE UPDATE_ITEM_SIZE
Contains the information about the sizes of an entry (exception/signature) and about the size of the ...
LIST_HEAD KernelUserAlertExceptions
Linked list used for kernel-user mode exceptions that are added from alert.
Definition: exceptions.h:129
Describe a process-creation alert-signature.
EXCEPTIONS * Exceptions
The exceptions that are currently loaded.
Definition: guests.h:388
#define INT_STATUS_NOT_INITIALIZED
Definition: introstatus.h:266
struct _UPDATE_FILE_HEADER UPDATE_FILE_HEADER
The header of the exceptions binary file.
static EXCEPTION_SIGNATURE_ID IntUpdateGetUniqueSigId(EXCEPTION_SIGNATURE_TYPE Type)
Get an unique signature ID for a given type.
#define UPDATE_VALIDATE_HEADER_SIZE
Validate the size of the exception header.
EXCEPTION_SIGNATURE_ID Signatures[]
Contains a array of signatures ID.
Definition: exceptions.h:290
struct _UPDATE_FILE_HEADER::@138 Version
DWORD LibraryNameHash
The name-hash of the modified library.
Definition: exceptions.h:430
static INTSTATUS IntUpdateAddValueCodeSignature(UPDATE_VALUE_CODE_SIGNATURE *UpdateSignature, UPDATE_ITEM_SIZE *Item)
Creates a new value-code signature and adds it to our internal list.
DWORD Hash
The hash of the modified zone.
Definition: exceptions.h:370
uint8_t * PBYTE
Definition: intro_types.h:47
DWORD Flags
Contains any flags from _EXCEPTION_FLG.
Definition: exceptions.h:312
WORD SigCount
Contains the number of signatures.
Definition: exceptions.h:289
DWORD Flags
Contains any flags from SIGNATURE_FLG.
Definition: exceptions.h:465
LIST_HEAD KernelFeedbackExceptions
Linked list used for kernel-mode exceptions that have the feedback flag.
Definition: exceptions.h:116
#define IC_TAG_EXKM
Kernel exceptions structures.
Definition: memtags.h:23
LIST_ENTRY Link
Definition: exceptions.h:300
The exception is valid only for execute violation.
Definition: exceptions.h:597
DWORD Hash
The hash of the modified zone.
DWORD VictimNameHash
Contains the victim name-hash.
Definition: exceptions.h:254
CHAR Object[]
Contains lists of (SIG_EXPORT_HASH).
Definition: exceptions.h:435
unsigned long long QWORD
Definition: intro_types.h:53
The common header used by exception information.
Definition: intro_types.h:1061
Describes an idt alert-signature.
CHAR NameGlob[EXCEPTION_UM_GLOB_LENGTH]
Contains the name (a string that can contain glob items) of the modified process. ...
Definition: exceptions.h:336
Describes a kernel-mode alert-exception.
static void IntUpdateAddKernelExceptionInOrder(KM_EXCEPTION *Exception)
Adds a kernel-mode exceptions from alert in the sorted list.
DWORD OriginatorNameHash
Contains the originator name-hash.
Definition: exceptions.h:274
The header of the exceptions binary file.
EXCEPTION_SIGNATURE_ID Id
An unique id (EXCEPTION_SIGNATURE_ID).
Definition: exceptions.h:464
static void IntUpdateAddUserExceptionInOrder(UM_EXCEPTION *Exception)
Adds a user-mode exceptions from alert in the sorted list.
CHAR ProcessGlob[EXCEPTION_UM_GLOB_LENGTH]
Contains the name of the process(a string that can contain glob items) in which the modification take...
Definition: exceptions.h:339
static INTSTATUS IntUpdateAddCbSignature(UPDATE_CB_SIGNATURE *UpdateSignature, UPDATE_ITEM_SIZE *Item)
Creates a new code-blocks signature and adds it to our internal list.
union _SIG_VERSION_INTRO::@38 Maximum
Sent for suspicious module loads alerts. See EVENT_MODULE_LOAD_VIOLATION.
Definition: intro_types.h:117
#define TRUE
Definition: intro_types.h:30
LIST_ENTRY Link
Definition: exceptions.h:272
Describe a value signature hash.
Definition: exceptions.h:366
Describes a introspection version signature.
Definition: exceptions.h:521
BOOLEAN AlertSignature
True if the signature is added from alert.
Definition: exceptions.h:483
#define HpFreeAndNullWithTag(Add, Tag)
Definition: glue.h:517
#define TRACE(fmt,...)
Definition: glue.h:58
#define INT_STATUS_INVALID_DATA_STATE
Definition: introstatus.h:183
#define INT_STATUS_INVALID_INTERNAL_STATE
Definition: introstatus.h:272
struct _EXCEPTIONS::@26 Version
Loaded exceptions binary version.
BYTE Type
The type of the exception/signature.
#define for_each_kum_exception(_ex_head, _var_name)
Definition: exceptions.h:1000
DWORD Flags
Contains any flags from SIGNATURE_FLG.
Definition: exceptions.h:428
EXCEPTION_SIGNATURE_ID Id
An unique id (EXCEPTION_SIGNATURE_ID).
Definition: exceptions.h:480
static void InsertAfterList(LIST_ENTRY *Pivot, LIST_ENTRY *Item)
Definition: introlists.h:169
static INTSTATUS IntUpdateAddVersionOsSignature(UPDATE_VERSION_OS_SIGNATURE *UpdateSignature, UPDATE_ITEM_SIZE *Item)
Creates a new operating system version signature and adds it to our internal list.
LIST_ENTRY Link
Definition: exceptions.h:462
Describe a value signature in binary format.
LIST_ENTRY Link
Definition: exceptions.h:250
static INTSTATUS IntUpdateAddKmException(const ALERT_KM_EXCEPTION *Exception, QWORD Context)
Creates a new kernel-mode exception from an alert-exception structure ALERT_UM_EXCEPTION and adds it ...
#define UPDATE_TYPE_VERSION_INTRO_SIGNATURE
Describes a export signature.
Definition: exceptions.h:423
static void InsertTailList(LIST_ENTRY *ListHead, LIST_ENTRY *Entry)
Definition: introlists.h:135
INTSTATUS IntExceptInit(void)
This function allocates the exceptions data and initialize the exception lists and the signature list...
Definition: exceptions.c:441
LIST_HEAD KernelUserFeedbackExceptions
Linked list used for kernel-user mode exceptions that have the feedback flag.
Definition: exceptions.h:118
Describe a kernel-user mode exception in binary format.
size_t strlcpy(char *dst, const char *src, size_t dest_size)
Definition: introcrt.c:1093
#define UPDATE_TYPE_CB_SIGNATURE
static INTSTATUS IntUpdateCreateExportSignatureFromAlert(const ALERT_EXPORT_SIGNATURE *AlertSig, SIG_EXPORT **Signature)
Creates a new export signature from an ALERT_EXPORT_SIGNATURE.
union _SIG_VERSION_OS::@32 Maximum
DWORD Flags
Contains any flags from SIGNATURE_FLG.
Definition: exceptions.h:410
#define WARNING(fmt,...)
Definition: glue.h:60
Sent when an EPT violation triggers an alert. See EVENT_EPT_VIOLATION.
Definition: intro_types.h:84
#define ALERT_FLAG_NOT_RING0
If set, the alert was triggered in ring 1, 2 or 3.
Definition: intro_types.h:636
DWORD Flags
Contains any flags from EXCEPTION_FLG.
Definition: exceptions.h:283
#define IC_TAG_EXUM
User exceptions structures.
Definition: memtags.h:25
#define UNREFERENCED_PARAMETER(P)
Definition: introdefs.h:29
This exception will be ignored.
Definition: exceptions.h:599
#define ALERT_CB_SIGNATURE_VERSION
INTSTATUS IntAlertCreateException(const void *Event, INTRO_EVENT_TYPE Type, BOOLEAN LogErrors, void *Exception)
This function will dispatch the exception creation to the appropriate function, depending on the even...
Describe a kernel-mode exception.
Definition: exceptions.h:248
#define for_each_km_exception(_ex_head, _var_name)
Definition: exceptions.h:998
DWORD Magic
The magic value; must be UPDATE_MAGIC_WORD.
#define __forceinline
Definition: introtypes.h:61
Describe a user-mode exception.
Definition: exceptions.h:298
struct _UPDATE_HEADER UPDATE_HEADER
The header of an exception or a signature.
DWORD UserExceptionsCount
The number of the user-mode exceptions.
#define UPDATE_TYPE_VALUE_CODE_SIGNATURE
uint32_t DWORD
Definition: intro_types.h:49
#define ALERT_KM_EXCEPTION_VERSION
BYTE Count
The number of hashes from the list.
Common violation header.
Definition: intro_types.h:1078
DWORD Hashes[]
The list of hashes.
Definition: exceptions.h:359
static INTSTATUS IntUpdateAddKmUmException(const ALERT_KUM_EXCEPTION *Exception, QWORD Context)
Creates a new kernel-user mode exception from an alert-exception structure ALERT_KUM_EXCEPTION and ad...
#define strlen_s(s, n)
Definition: introcrt.h:34
LIST_ENTRY Link
Definition: exceptions.h:523
LIST_HEAD GlobUserExceptions
Linked list used for user-mode exceptions that contains glob content.
Definition: exceptions.h:106
#define UPDATE_EXCEPTIONS_MIN_VER_MINOR
DWORD Hash
The hash of the modified function name.
Definition: exceptions.h:380
BYTE Count
The number of hashes from the list.
Definition: exceptions.h:358
#define ALERT_HASH_COUNT
LIST_HEAD ProcessCreationExceptions
Linked list used for process creations exceptions.
Definition: exceptions.h:111
struct _UM_EXCEPTION_GLOB::@30 Victim
#define INT_STATUS_INVALID_OBJECT_TYPE
Definition: introstatus.h:145
LIST_HEAD GenericKernelExceptions
Linked list used for kernel-mode exceptions that have a generic originator (*).
Definition: exceptions.h:90
UM_EXCEPTION_OBJECT Type
Contains the type of the exception (UM_EXCEPTION_OBJECT).
Definition: exceptions.h:314
UM_EXCEPTION_OBJECT Type
Contains the type of the exception (UM_EXCEPTION_OBJECT).
Definition: exceptions.h:344
LIST_HEAD ValueSignatures
Linked list used for value signatures.
Definition: exceptions.h:133
DWORD Flags
Contains any flags from SIGNATURE_FLG.
Definition: exceptions.h:447
DWORD Flags
Contains any flags from SIGNATURE_FLG.
Definition: exceptions.h:481
static INTSTATUS IntUpdateAddProcessCreationSignature(UPDATE_PROCESS_CREATION_SIGNATURE *UpdateSignature, UPDATE_ITEM_SIZE *Item)
Creates a new process-creation signature and adds it to our internal list.
#define ALERT_EXCEPTION_SIZE
Definition: intro_types.h:669
GUEST_STATE gGuest
The current guest state.
Definition: guests.c:48
DWORD OriginatorNameHash
Contains the originator name-hash.
Definition: exceptions.h:302
DWORD UserExceptionsGlobCount
The number of the user-mode exceptions that contains glob items.
The signature is valid only on Linux.
Definition: exceptions.h:678
LIST_ENTRY Link
Definition: exceptions.h:407
union _SIG_VERSION_OS::@31 Minimum
Describe a version introspection signature in binary format.
WORD SigCount
Contains the number of signatures.
Definition: exceptions.h:348
DWORD KernelExceptionsCount
The number of the kernel-mode exceptions.
Describe an export signature in binary format.
WORD Offset
The displacement from the beginning of the modified zone.
#define for_each_cb_signature(_ex_head, _var_name)
Definition: exceptions.h:1006
DWORD Type
Contains a type of signature (EXCEPTION_SIGNATURE_TYPE).
Definition: exceptions.h:238
LIST_HEAD ProcessCreationFeedbackExceptions
Linked list used for process-creation exceptions that have the feedback flag.
Definition: exceptions.h:120
#define EXCEPTION_TABLE_ID(H)
Definition: exceptions.h:51
#define INT_STATUS_UNSUPPORTED_DATA_VALUE
Definition: introstatus.h:225
#define ALERT_PROCESS_CREATION_SIGNATURE_VERSION
BOOLEAN AlertSignature
True if the signature is added from alert.
Definition: exceptions.h:571
BYTE Score
The number of (minimum) hashes from a list that need to match.
Definition: exceptions.h:449
DWORD Flags
Contains any flags from SIGNATURE_FLG.
Definition: exceptions.h:526
LIST_HEAD UserFeedbackExceptions
Linked list used for user-mode exceptions that have the feedback flag.
Definition: exceptions.h:114
Describe a code-blocks signature in binary format.
DWORD ProcessHash
Contains the name-hash of the process in which the modification takes place (missing for injections)...
Definition: exceptions.h:309
WORD Length
The length of the opcode pattern.
Definition: exceptions.h:413
static BOOLEAN IntUpdateIsDuplicateIdtSignature(const ALERT_IDT_SIGNATURE *Signature, const EXCEPTION_SIGNATURE_ID *SigIds, DWORD SigCount)
Checks if the provided IDT alert-signature already exists in our list.
LIST_HEAD KernelExceptions[EXCEPTION_TABLE_SIZE]
Array of linked lists used for kernel-mode exceptions.
Definition: exceptions.h:108
BYTE ListsCount
The number of the list of hashes.
Definition: exceptions.h:395
static INTSTATUS IntUpdateAddUmException(const ALERT_UM_EXCEPTION *Exception, QWORD Context)
Creates a new user-mode exception from an alert-exception structure ALERT_UM_EXCEPTION and adds it to...
struct _EXCEPTION_SIGNATURE_ID::@27 Field
#define IC_TAG_EXKU
Kernel-User mode exceptions structures.
Definition: memtags.h:24
#define UPDATE_TYPE_VERSION_OS_SIGNATURE
#define UPDATE_TYPE_VALUE_SIGNATURE
EXCEPTION_SIGNATURE_ID Signatures[]
Contains an array of signatures ID.
Definition: exceptions.h:349
BOOLEAN AlertSignature
True if the signature is added from alert.
Definition: exceptions.h:469
static void IntUpdateAddKernelUserExceptionInOrder(KUM_EXCEPTION *Exception)
Adds a kernel-user mode exceptions from alert in the sorted list.
INTSTATUS IntUpdateGetVersion(WORD *MajorVersion, WORD *MinorVersion, DWORD *BuildNumber)
Get the version of the loaded exceptions binary file.
QWORD Value
Contains the minimum build number of the operating system (used for windows).
Definition: exceptions.h:497
DWORD Hashes[]
The hashes list.
The range-identifier used for codeblocks signature.
Definition: exceptions.h:80
LIST_HEAD GenericKernelUserExceptions
Linked list used for kernel-user mode exceptions that have a generic originator(*).
Definition: exceptions.h:95
Describes a idt signature.
Definition: exceptions.h:460
struct _UPDATE_CB_HASH * PUPDATE_CB_HASH
DWORD Value
Contains an unique value.
Definition: exceptions.h:237
#define INT_STATUS_INVALID_PARAMETER_1
Definition: introstatus.h:62
#define INT_STATUS_NOT_SUPPORTED
Definition: introstatus.h:287
#define ALERT_UM_EXCEPTION_VERSION
EXCEPTION_SIGNATURE_ID Signatures[]
Contains a array of signatures ID.
Definition: exceptions.h:263
Describe a user-mode-glob exception in binary format.
#define UPDATE_TYPE_UM_EXCEPTION
WORD Major
The major version of the exceptions binary file.
enum _INTRO_EVENT_TYPE INTRO_EVENT_TYPE
Event classes.
Sent for integrity violation alerts. See EVENT_INTEGRITY_VIOLATION.
Definition: intro_types.h:92
DWORD CreateMask
Contains the DPI mask.
Definition: exceptions.h:573
LIST_ENTRY Link
Definition: exceptions.h:444
static BOOLEAN IntUpdateIsDuplicateCbSignature(const ALERT_CB_SIGNATURE *Signature, const EXCEPTION_SIGNATURE_ID *SigIds, DWORD SigCount)
Checks if the provided code-blocks alert-signature already exists in our list.
DWORD Hash
The hash of the modified function name.
WORD SigCount
Contains the number of signatures.
Definition: exceptions.h:318
struct _UPDATE_EXPORT_HASH UPDATE_EXPORT_HASH
Describe a export hash in binary format.
INT16 Offset
The displacement from the beginning of the modified zone.
Definition: exceptions.h:412
#define UPDATE_VALIDATE_ALL
All exception validation options.
Sent when a MSR violation triggers an alert.See EVENT_MSR_VIOLATION.
Definition: intro_types.h:86
CHAR Object[]
Contains list of (SIG_CODEBLOCK_HASH).
Definition: exceptions.h:398
static void IntUpdateSetIdForException(EXCEPTION_SIGNATURE_ID *Signatures, DWORD Count)
Generate a new ID for each signature.
struct _UPDATE_ITEM_SIZE * PUPDATE_ITEM_SIZE
struct _UPDATE_CB_HASH UPDATE_CB_HASH
Describe a code-blocks hash in binary format.
static INTSTATUS IntUpdateAddExportSignature(UPDATE_EXPORT_SIGNATURE *UpdateSignature, UPDATE_ITEM_SIZE *Item)
Creates a new export signature and adds it to our internal list.
WORD Size
The size of of the modified zone.
static BOOLEAN IntUpdateIsDuplicateKernelUserException(const ALERT_KUM_EXCEPTION *Exception)
Checks if the provided kernel-user mode exception already exists in out list.
CHAR Object[]
Contains lists of (SIG_VALUE_HASH).
Definition: exceptions.h:453
EXCEPTION_SIGNATURE_ID Id
An unique id (EXCEPTION_SIGNATURE_ID).
Definition: exceptions.h:525
EXCEPTION_SIGNATURE_ID Signatures[]
Contains an array of signatures ID.
Definition: exceptions.h:319
Describes a codeblocks signature.
Definition: exceptions.h:387
DWORD Flags
Contains any flags from _SIGNATURE_FLG.
Definition: exceptions.h:392
LIST_ENTRY Link
Definition: exceptions.h:328
DWORD KernelUserExceptionsCount
The number of the kernel-user mode exceptions.
Describe a user-mode exception in binary format.
#define UPDATE_TYPE_KM_EXCEPTION
#define INT_STATUS_INVALID_PARAMETER_2
Definition: introstatus.h:65
BOOLEAN AlertSignature
True if the signature is added from alert.
Definition: exceptions.h:433
LIST_HEAD NoNameUserExceptions
Linked list used for user-mode exceptions that don&#39;t have a valid originator (-). ...
Definition: exceptions.h:100
Describe a codeblocks signature hash.
Definition: exceptions.h:356
void UtilQuickSort(void *Array, const DWORD NumberOfElements, const BYTE ElementSize)
Definition: utils.c:267
Describes a operating system version signature.
Definition: exceptions.h:476
WORD Delta
The number of bytes that are modified.
The object that has a NX zone is executed.
Definition: exceptions.h:208
INTSTATUS IntUpdateAddExceptionFromAlert(const void *Event, INTRO_EVENT_TYPE Type, BOOLEAN Exception, QWORD Context)
Handles all types of supported exceptions that can be added from alerts.
#define INT_STATUS_INVALID_DATA_SIZE
Definition: introstatus.h:142
INTSTATUS IntExceptRemove(void)
This function removes and frees all exceptions and signatures that have been added from exception bin...
Definition: exceptions.c:257
LIST_ENTRY Link
Definition: exceptions.h:478
#define for_each_export_signature(_ex_head, _var_name)
Definition: exceptions.h:1008
struct _SIG_EXPORT_HASH SIG_EXPORT_HASH
Describe a export signature hash.
#define FALSE
Definition: intro_types.h:34
#define INT_STATUS_INSUFFICIENT_RESOURCES
Definition: introstatus.h:281
enum _EXCEPTION_SIGNATURE_TYPE EXCEPTION_SIGNATURE_TYPE
The identifier that describes a range of signatures.
#define INT_STATUS_INVALID_PARAMETER_3
Definition: introstatus.h:68
LIST_HEAD VersionOsSignatures
Linked list used for operating system version signatures.
Definition: exceptions.h:136