Bitdefender Hypervisor Memory Introspection
introapi.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020 Bitdefender
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 #include "introapi.h"
6 #include "debugger.h"
7 #include "decoder.h"
8 #include "deployer.h"
9 #include "gpacache.h"
10 #include "guests.h"
11 #include "kernvm.h"
12 #include "ptfilter.h"
13 #include "update_exceptions.h"
14 #include "vecore.h"
15 
24 
25 
26 static void
28  _In_ BOOLEAN Async
29  )
38 {
39  INTSTATUS status;
40 
42  if (!INT_SUCCESS(status))
43  {
44  ERROR("[ERROR] IntGuestPreReturnCallback failed: 0x%08x\n", status);
46  }
47 }
48 
49 
50 static void
52  _In_ DWORD CpuNumber
53  )
64 {
65  if (CpuNumber == IG_CURRENT_VCPU)
66  {
67 #ifdef USER_MODE
68  CpuNumber = 0;
69 #else
70  CpuNumber = IntGetCurrentCpu();
71 #endif // USER_MODE
72  }
73 
74  gVcpu = &gGuest.VcpuArray[CpuNumber];
75 
76  gEventId++;
77 }
78 
79 
82  _In_ void *GuestHandle,
83  _In_ QWORD Options,
84  _In_reads_(BufferLength) PBYTE UpdateBuffer,
85  _In_ DWORD BufferLength
86  )
114 {
115  INTSTATUS status;
116 
117  if (GuestHandle == NULL)
118  {
120  }
121 
123 
124  if (gGuest.Initialized)
125  {
126  WARNING("[WARNING] Introspection is already active, ignoring activation request\n");
128  goto release_and_exit;
129  }
130 
131  gIntHandle = GuestHandle;
132 
133  TRACE("[INTRO-INIT] New guest notification, handle = %p\n", gIntHandle);
134 
135  LOG("[INTRO-INIT] Will use options: 0x%016llx\n", Options);
136 
138  {
139  TRACE("[INTRO-INIT] INTRO_OPT_ENABLE_KM_BETA_DETECTIONS flag set, everything will be allowed in KM.\n");
140  }
141 
142  gEventId++;
143 
144  status = IntCamiSetUpdateBuffer(UpdateBuffer, BufferLength);
145  if (!INT_SUCCESS(status))
146  {
147  ERROR("[ERROR] IntCamiSetUpdateBuffer failed: 0x%08x\n", status);
148 
150 
151  goto release_and_exit;
152  }
153 
154  status = IntGuestInit(Options);
155  if (!INT_SUCCESS(status))
156  {
157  ERROR("[ERROR] Failed initializing guest state: 0x%08x\n", status);
158  goto release_and_exit;
159  }
160 
161 release_and_exit:
162  if (!INT_SUCCESS(status))
163  {
165 
166  IntGuestUninit();
167  }
168 
170 
171  return status;
172 }
173 
174 
175 INTSTATUS
177  _In_ void *GuestHandle,
178  _In_ QWORD Flags
179  )
195 {
196  INTSTATUS status;
197 
198  UNREFERENCED_PARAMETER(GuestHandle);
199 
201 
202  IntPauseVcpus();
203 
204  if (!gGuest.Initialized)
205  {
207  goto resume_and_exit;
208  }
209 
211 
212  status = IntGetGprs(IG_CURRENT_VCPU, &gVcpu->Regs);
213  if (!INT_SUCCESS(status))
214  {
215  ERROR("[ERROR] IntGetGprs failed: 0x%08x\n", status);
216  goto resume_and_exit;
217  }
218 
219  status = IntGuestDisableIntro(Flags);
220 
221 resume_and_exit:
222  IntResumeVcpus();
223 
225 
226  return status;
227 }
228 
229 
230 INTSTATUS
232  _In_ void *GuestHandle,
233  _In_ IG_GUEST_POWER_STATE PowerState
234  )
249 {
250  UNREFERENCED_PARAMETER(GuestHandle);
251 
252  switch (PowerState)
253  {
255  {
257  return INT_STATUS_SUCCESS;
258  }
259 
261  {
262  // We already disabled pt filtering on sleep on NtSetSystemPowerState callback
264 
265  // We already disabled #VE on sleep on NtSetSystemPowerState callback
267 
269  return INT_STATUS_SUCCESS;
270  }
271 
273  {
275 
276  gGuest.ShutDown = TRUE;
277 
279  return INT_STATUS_SUCCESS;
280  }
281 
283 
285 
287 
289  return INT_STATUS_SUCCESS;
290 
291  default:
292  ERROR("[ERROR] Invalid power state: %d\n", PowerState);
294  }
295 }
296 
297 
298 INTSTATUS
300  _In_ void *GuestHandle,
301  _In_z_ const CHAR *FullPath,
302  _In_ DWORD ProtectionMask,
303  _In_ BOOLEAN Add,
304  _In_ QWORD Context
305  )
313 {
314  INTSTATUS status;
315  size_t len, i;
316 
317  if (NULL == GuestHandle)
318  {
320  }
321 
322  if (NULL == FullPath)
323  {
325  }
326 
328 
330  {
331  ERROR("[ERROR] Introspection is not initialized!\n");
333  goto release_and_exit;
334  }
335 
337  {
339  goto release_and_exit;
340  }
341 
343 
345  {
346  WARNING("[WARNING] The uninit has been called, cannot modify the protected process list!\n");
347  status = INT_STATUS_NOT_SUPPORTED;
348  goto release_and_exit;
349  }
350 
351  IntPauseVcpus();
352 
354  {
355  PWCHAR wPath = NULL;
356 
357  len = strlen(FullPath);
358 
359  if (len >= 0x10000)
360  {
362  goto resume_and_exit;
363  }
364 
365  // len + 1 OK: len is not longer than 64K.
366  wPath = HpAllocWithTag((len + 1) * 2, IC_TAG_ALLOC);
367  if (NULL == wPath)
368  {
370  goto resume_and_exit;
371  }
372 
373  // Copy from CHAR to WCHAR - no explicit conversion.
374  for (i = 0; i < len; i++)
375  {
376  wPath[i] = (WCHAR)FullPath[i];
377  }
378 
379  wPath[i] = 0;
380 
381  if (Add)
382  {
383  status = IntWinProcAddProtectedProcess(wPath, ProtectionMask, Context);
384  if (!INT_SUCCESS(status))
385  {
386  ERROR("[ERROR] IntWinProcAddProtectedProcess failed: 0x%08x\n", status);
387  }
388  }
389  else
390  {
391  status = IntWinProcRemoveProtectedProcess(wPath);
392  if (!INT_SUCCESS(status))
393  {
394  ERROR("[ERROR] IntWinProcRemoveProtectedProcess failed: 0x%08x\n", status);
395  }
396  }
397 
399  }
400  else if (gGuest.OSType == introGuestLinux)
401  {
402  if (Add)
403  {
404  status = IntLixTaskAddProtected(FullPath, ProtectionMask, Context);
405  if (!INT_SUCCESS(status))
406  {
407  ERROR("[ERROR] IntLixTaskAddProtected failed: 0x%08x\n", status);
408  }
409  }
410  else
411  {
412  status = IntLixTaskRemoveProtected(FullPath);
413  if (!INT_SUCCESS(status))
414  {
415  ERROR("[ERROR] IntLixTaskRemoveProtected failed: 0x%08x\n", status);
416  }
417  }
418  }
419  else
420  {
421  status = INT_STATUS_NOT_SUPPORTED;
422  }
423 
424 resume_and_exit:
425  IntResumeVcpus();
426 
427 release_and_exit:
429 
430  return status;
431 }
432 
433 
434 INTSTATUS
436  _In_ void *GuestHandle,
437  _In_z_ const WCHAR *FullPath,
438  _In_ DWORD ProtectionMask,
439  _In_ BOOLEAN Add,
440  _In_ QWORD Context
441  )
449 {
450  INTSTATUS status;
451 
452  if (NULL == GuestHandle)
453  {
455  }
456 
457  if (NULL == FullPath)
458  {
460  }
461 
463 
465  {
466  ERROR("[ERROR] Introspection is not initialized!\n");
468  goto release_and_exit;
469  }
470 
472  {
474  goto release_and_exit;
475  }
476 
478 
480  {
481  ERROR("[ERROR] The uninit has been called, cannot modify the protected process list!\n");
482  status = INT_STATUS_NOT_SUPPORTED;
483  goto release_and_exit;
484  }
485 
486  IntPauseVcpus();
487 
489  {
490  if (Add)
491  {
492  status = IntWinProcAddProtectedProcess(FullPath, ProtectionMask, Context);
493  if (!INT_SUCCESS(status))
494  {
495  ERROR("[ERROR] IntWinProcAddProtectedProcess failed: 0x%08x\n", status);
496  }
497  }
498  else
499  {
500  status = IntWinProcRemoveProtectedProcess(FullPath);
501  if (!INT_SUCCESS(status))
502  {
503  ERROR("[ERROR] IntWinProcRemoveProtectedProcess failed: 0x%08x\n", status);
504  }
505  }
506  }
507  else
508  {
509  status = INT_STATUS_NOT_SUPPORTED;
510  }
511 
512  IntResumeVcpus();
513 
514 release_and_exit:
516 
517  return status;
518 }
519 
520 
521 INTSTATUS
523  _In_ void *GuestHandle
524  )
532 {
533  INTSTATUS status;
534 
535  if (NULL == GuestHandle)
536  {
538  }
539 
541 
543  {
544  ERROR("[ERROR] Introspection is not initialized!\n");
546  goto release_and_exit;
547  }
548 
550  {
552  goto release_and_exit;
553  }
554 
556 
558  {
559  ERROR("[ERROR] The uninit has been called, cannot modify the protected process list!\n");
560  status = INT_STATUS_NOT_SUPPORTED;
561  goto release_and_exit;
562  }
563 
565  {
567  if (!INT_SUCCESS(status))
568  {
569  ERROR("[ERROR] IntWinProcRemoveAllProtectedProcesses failed: 0x%08x\n", status);
570  }
571  }
572  else
573  {
575  }
576 
577 release_and_exit:
579 
580  return status;
581 }
582 
583 
584 INTSTATUS
586  _In_ void *GuestHandle,
587  _In_ DWORD AgentTag,
588  _In_opt_ PBYTE AgentContent,
589  _In_opt_ DWORD AgentSize,
590  _In_z_ const CHAR *Name,
591  _In_opt_ const CHAR *Args
592  )
600 {
601  INTSTATUS status;
602 
603  UNREFERENCED_PARAMETER(GuestHandle);
604 
606 
608  {
610  goto release_and_exit;
611  }
612 
614  {
615  ERROR("[ERROR] Agent injection called when guest has bugcheck in progress!\n");
617  goto release_and_exit;
618  }
619 
621  {
622  WARNING("[WARNING] Agent %s will not be deployed as the guest is NOT initialized!\n", Name);
624  goto cleanup_and_exit;
625  }
626 
628  {
629  WARNING("[WARNING] The uninit has been called, cannot inject agents anymore!\n");
630  status = INT_STATUS_NOT_SUPPORTED;
631  goto cleanup_and_exit;
632  }
633 
635 
637  {
638  status = IntDepInjectProcess(AgentTag, AgentContent, AgentSize, Name, Args);
639  }
640  else
641  {
642  WARNING("[WARNING] Requested to inject agents but INTRO_OPT_AGENT_INJECTION is not set!\n");
643 
644  status = INT_STATUS_NOT_SUPPORTED;
645  }
646 
647 cleanup_and_exit:
648  IntApiLeave(TRUE);
649 
650 release_and_exit:
652 
653  return status;
654 }
655 
656 
657 INTSTATUS
659  _In_ void *GuestHandle,
660  _In_ PBYTE AgentContent,
661  _In_ DWORD AgentSize,
662  _In_z_ const CHAR *Name
663  )
671 {
672  INTSTATUS status;
673 
674  UNREFERENCED_PARAMETER(GuestHandle);
675 
677 
679  {
680  ERROR("[ERROR] Introspection is not initialized!\n");
682  goto release_and_exit;
683  }
684 
686  {
688  goto release_and_exit;
689  }
690 
692  {
693  ERROR("[ERROR] Agent injection called when guest has bugcheck in progress!\n");
695  goto release_and_exit;
696  }
697 
699 
701  {
702  ERROR("[ERROR] The uninit has been called, cannot inject agents anymore!\n");
703  status = INT_STATUS_NOT_SUPPORTED;
704  goto cleanup_and_exit;
705  }
706 
708  {
709  status = IntDepInjectFile(AgentContent, AgentSize, Name);
710  }
711  else
712  {
713  WARNING("[WARNING] Requested to inject a file but INTRO_OPT_AGENT_INJECTION is not set!\n");
714 
715  status = INT_STATUS_NOT_SUPPORTED;
716  }
717 
718 cleanup_and_exit:
719  IntApiLeave(TRUE);
720 
721 release_and_exit:
723 
724  return status;
725 }
726 
727 
728 INTSTATUS
730  _In_ void *GuestHandle,
731  _In_ DWORD CpuNumber,
732  _Out_ BYTE *Length
733  )
741 {
742  INTSTATUS status;
743  INSTRUX instrux;
744 
745  if (NULL == GuestHandle)
746  {
748  }
749 
750  if (NULL == Length)
751  {
753  }
754 
756 
757  if (!gGuest.Initialized)
758  {
759  ERROR("[ERROR] Introspection is not initialized!\n");
761  goto release_and_exit;
762  }
763 
765  {
767  goto release_and_exit;
768  }
769 
771 
772  gVcpu = &gGuest.VcpuArray[CpuNumber];
773 
774  status = IntGetGprs(CpuNumber, &gVcpu->Regs);
775  if (!INT_SUCCESS(status))
776  {
777  ERROR("[ERROR] IntGetGprs failed: 0x%08x\n", status);
778  goto cleanup_and_exit;
779  }
780 
782  &gVcpu->Regs, &instrux, DEC_OPT_NO_CACHE, NULL, NULL);
783  if (!INT_SUCCESS(status) && ((INT_STATUS_PAGE_NOT_PRESENT != status) &&
785  {
786  ERROR("[ERROR] IntDecDecodeInstructionAtRipWithCache failed: 0x%08x\n", status);
787  goto cleanup_and_exit;
788  }
789 
790  if (INT_SUCCESS(status))
791  {
792  *Length = instrux.Length;
793  }
794 
795 cleanup_and_exit:
796  IntApiLeave(TRUE);
797 
798 release_and_exit:
800 
801  return status;
802 }
803 
804 
805 INTSTATUS
807  _In_ void *GuestHandle,
808  _In_ DWORD CpuNumber,
809  _Out_ CHAR *Mnemonic
810  )
818 {
819  INTSTATUS status;
820  INSTRUX instrux;
821 
822  if (NULL == GuestHandle)
823  {
825  }
826 
827  if (NULL == Mnemonic)
828  {
830  }
831 
833 
834  if (!gGuest.Initialized)
835  {
836  ERROR("[ERROR] Introspection is not initialized!\n");
838  goto release_and_exit;
839  }
840 
842  {
844  goto release_and_exit;
845  }
846 
847  IntApiEnter(CpuNumber);
848 
849  status = IntGetGprs(CpuNumber, &gVcpu->Regs);
850  if (!INT_SUCCESS(status))
851  {
852  ERROR("[ERROR] IntGetGprs failed: 0x%08x\n", status);
853  goto cleanup_and_exit;
854  }
855 
857  &gVcpu->Regs, &instrux, DEC_OPT_NO_CACHE, NULL, NULL);
858  if (!INT_SUCCESS(status) && ((INT_STATUS_PAGE_NOT_PRESENT != status) &&
860  {
861  ERROR("[ERROR] IntDecDecodeInstructionAtRipWithCache failed: 0x%08x\n", status);
862  goto cleanup_and_exit;
863  }
864 
865  if (INT_SUCCESS(status))
866  {
867  strlcpy(Mnemonic, instrux.Mnemonic, ND_MAX_MNEMONIC_LENGTH);
868  }
869 
870 cleanup_and_exit:
871  IntApiLeave(TRUE);
872 
873 release_and_exit:
875 
876  return status;
877 }
878 
879 
880 INTSTATUS
882  _In_ void *GuestHandle,
883  _In_ QWORD Cr3,
885  )
893 {
894  INTSTATUS status = INT_STATUS_SUCCESS;
895 
896  if (NULL == GuestHandle)
897  {
899  }
900 
901  if (NULL == Callback)
902  {
904  }
905 
907 
909  {
911  goto release_and_exit;
912  }
913 
915 
916  status = IntIterateVirtualAddressSpace(Cr3, Callback);
917  if (!INT_SUCCESS(status))
918  {
919  ERROR("[ERROR] IntIterateVirtualAddressSpace failed: 0x%x\n", status);
920  }
921 
922 release_and_exit:
924 
925  return status;
926 }
927 
928 
929 INTSTATUS
931  _In_ void *GuestHandle,
932  _Out_ GUEST_INFO *GuestInfo
933  )
941 {
942  INTSTATUS status = INT_STATUS_SUCCESS;
943 
944  if (NULL == GuestHandle)
945  {
947  }
948 
949  if (NULL == GuestInfo)
950  {
952  }
953 
955 
957  {
959  goto release_and_exit;
960  }
961 
963  {
965  goto release_and_exit;
966  }
967 
969 
970  status = IntGuestGetInfo(GuestInfo);
971 
972 release_and_exit:
974 
975  return status;
976 }
977 
978 
979 INTSTATUS
981  _In_ void *GuestHandle,
982  _In_ QWORD NewOptions
983  )
991 {
992  INTSTATUS status = INT_STATUS_SUCCESS;
993 
994  if (NULL == GuestHandle)
995  {
997  }
998 
1000 
1001  if (!gGuest.GuestInitialized)
1002  {
1003  ERROR("[ERROR] Introspection is not initialized!\n");
1004  status = INT_STATUS_NOT_INITIALIZED;
1005  goto release_and_exit;
1006  }
1007 
1008  if (gGuest.EnterHibernate)
1009  {
1011  goto release_and_exit;
1012  }
1013 
1014  gEventId++;
1015 
1016  IntGuestUpdateCoreOptions(NewOptions);
1017 
1018 release_and_exit:
1020 
1021  return status;
1022 }
1023 
1024 
1025 INTSTATUS
1027  _In_ void *GuestHandle
1028  )
1036 {
1037  INTSTATUS status;
1038 
1039  if (NULL == GuestHandle)
1040  {
1042  }
1043 
1045 
1046  if (!gGuest.Initialized)
1047  {
1048  ERROR("[ERROR] Introspection is not initialized!\n");
1049  status = INT_STATUS_NOT_INITIALIZED;
1050  goto release_and_exit;
1051  }
1052 
1053  if (gGuest.EnterHibernate)
1054  {
1056  goto release_and_exit;
1057  }
1058 
1059  if (NULL == gGuest.GpaCache)
1060  {
1061  status = INT_STATUS_NOT_NEEDED_HINT;
1062  goto release_and_exit;
1063  }
1064 
1066 
1067  status = IntGpaCacheFlush(gGuest.GpaCache);
1068 
1069 release_and_exit:
1071 
1072  return status;
1073 }
1074 
1075 
1076 INTSTATUS
1078  _In_ void *GuestHandle,
1079  _Out_ QWORD *IntroOptions
1080  )
1088 {
1089  INTSTATUS status = INT_STATUS_SUCCESS;
1090 
1091  if (NULL == GuestHandle)
1092  {
1094  }
1095 
1096  if (NULL == IntroOptions)
1097  {
1099  }
1100 
1102 
1103  if (!gGuest.Initialized)
1104  {
1105  ERROR("[ERROR] Introspection is not initialized!\n");
1106  status = INT_STATUS_NOT_INITIALIZED;
1107  goto release_and_exit;
1108  }
1109 
1110  if (gGuest.EnterHibernate)
1111  {
1113  goto release_and_exit;
1114  }
1115 
1116  gEventId++;
1117 
1118  *IntroOptions = gGuest.CoreOptions.Current;
1119 
1120 release_and_exit:
1122 
1123  return status;
1124 }
1125 
1126 
1127 INTSTATUS
1129  _In_ void *GuestHandle,
1130  _In_reads_bytes_(Length) PBYTE Buffer,
1131  _In_ DWORD Length
1132  )
1142 {
1143  INTSTATUS status;
1144  DWORD osType = 0;
1145 
1146  if (NULL == GuestHandle)
1147  {
1149  }
1150 
1152 
1154  {
1155  ERROR("[ERROR] Introspection is not initialized!\n");
1156  status = INT_STATUS_NOT_INITIALIZED;
1157  goto release_and_exit;
1158  }
1159 
1160  if (gGuest.EnterHibernate)
1161  {
1163  goto release_and_exit;
1164  }
1165 
1166  if (gGuest.UninitPrepared)
1167  {
1168  ERROR("[ERROR] The uninit has been called, won't load the update buffer!\n");
1169  status = INT_STATUS_NOT_SUPPORTED;
1170  goto release_and_exit;
1171  }
1172 
1174 
1175  // Notify the integrator that we no longer need the previous cami buffer
1177 
1178  status = IntCamiSetUpdateBuffer(Buffer, Length);
1179  if (!INT_SUCCESS(status))
1180  {
1181  ERROR("[ERROR] IntCamiSetUpdateBuffer failed: %08x\n", status);
1182  goto release_and_exit;
1183  }
1184 
1186  {
1187  osType = CAMI_SECTION_HINT_WINDOWS;
1188  }
1189  else if (gGuest.OSType == introGuestLinux)
1190  {
1191  osType = CAMI_SECTION_HINT_LINUX;
1192  }
1193 
1194  if (osType != 0)
1195  {
1197  if (!INT_SUCCESS(status))
1198  {
1199  ERROR("[ERROR] IntCamiLoadSection failed: %08x\n", status);
1200  goto release_and_exit;
1201  }
1202  }
1203 
1204 release_and_exit:
1206 
1207  return status;
1208 }
1209 
1210 
1211 INTSTATUS
1213  _In_ void *GuestHandle,
1214  _Out_ DWORD *MajorVersion,
1215  _Out_ DWORD *MinorVersion,
1216  _Out_ DWORD *BuildNumber
1217  )
1225 {
1226  INTSTATUS status;
1227 
1228  if (NULL == GuestHandle)
1229  {
1231  }
1232 
1234 
1235  if (!gGuest.Initialized)
1236  {
1237  ERROR("[ERROR] Introspection is not initialized!\n");
1238  status = INT_STATUS_NOT_INITIALIZED;
1239  goto release_and_exit;
1240  }
1241 
1242  if (gGuest.EnterHibernate)
1243  {
1245  goto release_and_exit;
1246  }
1247 
1248  gEventId++;
1249 
1250  status = IntCamiGetVersion(MajorVersion, MinorVersion, BuildNumber);
1251 
1252 release_and_exit:
1254 
1255  return status;
1256 }
1257 
1258 
1259 INTSTATUS
1261  _In_ void *GuestHandle,
1262  _In_ DWORD CpuNumber,
1263  _In_ DWORD Argc,
1264  _In_ CHAR *Argv[]
1265  )
1282 {
1283  void *oldVcpu;
1284 
1285  if (NULL == GuestHandle)
1286  {
1288  }
1289 
1290  oldVcpu = gVcpu;
1291 
1292  IntApiEnter(CpuNumber);
1293 
1294  IntDbgProcessCommand(Argc, Argv);
1295 
1296  gVcpu = oldVcpu;
1297 
1298  return INT_STATUS_SUCCESS;
1299 }
1300 
1301 
1302 INTSTATUS
1304  _In_ void *GuestHandle,
1305  _Out_ WORD *MajorVersion,
1306  _Out_ WORD *MinorVersion,
1307  _Out_ DWORD *BuildNumber
1308  )
1317 {
1318  INTSTATUS status;
1319 
1320  if (NULL == GuestHandle)
1321  {
1323  }
1324 
1326 
1327  if (!gGuest.Initialized)
1328  {
1329  ERROR("[ERROR] Introspection is not initialized!\n");
1330  status = INT_STATUS_NOT_INITIALIZED;
1331  goto release_and_exit;
1332  }
1333 
1334  if (gGuest.EnterHibernate)
1335  {
1337  goto release_and_exit;
1338  }
1339 
1340  gEventId++;
1341 
1342  status = IntUpdateGetVersion(MajorVersion, MinorVersion, BuildNumber);
1343 
1344 release_and_exit:
1346 
1347  return status;
1348 }
1349 
1350 
1351 INTSTATUS
1353  _In_ void *GuestHandle,
1354  _In_reads_bytes_(Length) PBYTE Buffer,
1355  _In_ DWORD Length,
1356  _In_ DWORD Flags
1357  )
1366 {
1367  INTSTATUS status;
1368 
1369  if (NULL == GuestHandle)
1370  {
1372  }
1373 
1374  // We must take this spinlock exclusive, so we don't process any event.
1375  // This way, we won't miss any events (there will be a small attack-window)
1376  // while we free the exceptions and load the new ones.
1378 
1379  if (!gGuest.Initialized)
1380  {
1381  ERROR("[ERROR] Introspection is not initialized!\n");
1382  status = INT_STATUS_NOT_INITIALIZED;
1383  goto release_and_exit;
1384  }
1385 
1386  if (gGuest.EnterHibernate)
1387  {
1389  goto release_and_exit;
1390  }
1391 
1392  status = IntUpdateLoadExceptions(Buffer, Length, Flags);
1393 
1394 release_and_exit:
1396 
1397  return status;
1398 }
1399 
1400 
1401 INTSTATUS
1403  _In_ void *GuestHandle,
1404  _In_ const void *Event,
1405  _In_ INTRO_EVENT_TYPE Type,
1406  _In_ BOOLEAN Exception,
1407  _In_ QWORD Context
1408  )
1417 {
1418  INTSTATUS status;
1419 
1420  if (NULL == GuestHandle)
1421  {
1423  }
1424 
1426 
1427  if (!gGuest.Initialized)
1428  {
1429  ERROR("[ERROR] Introspection is not initialized!\n");
1430  status = INT_STATUS_NOT_INITIALIZED;
1431  goto release_and_exit;
1432  }
1433 
1434  if (gGuest.EnterHibernate)
1435  {
1437  goto release_and_exit;
1438  }
1439 
1440  gEventId++;
1441 
1442  status = IntUpdateAddExceptionFromAlert(Event, Type, Exception, Context);
1443 
1444 release_and_exit:
1446 
1447  return status;
1448 }
1449 
1450 
1451 INTSTATUS
1453  _In_ void *GuestHandle,
1454  _In_opt_ QWORD Context
1455  )
1464 {
1465  INTSTATUS status;
1466 
1467  if (NULL == GuestHandle)
1468  {
1470  }
1471 
1473 
1474  if (!gGuest.Initialized)
1475  {
1476  ERROR("[ERROR] Introspection is not initialized!\n");
1477  status = INT_STATUS_NOT_INITIALIZED;
1478  goto release_and_exit;
1479  }
1480 
1481  if (gGuest.EnterHibernate)
1482  {
1484  goto release_and_exit;
1485  }
1486 
1487  gEventId++;
1488 
1489  status = IntUpdateRemoveException(Context);
1490 
1491 release_and_exit:
1493 
1494  return status;
1495 }
1496 
1497 
1498 INTSTATUS
1500  _In_ void *GuestHandle
1501  )
1510 {
1511  INTSTATUS status;
1512 
1513  if (NULL == GuestHandle)
1514  {
1516  }
1517 
1519 
1520  if (!gGuest.Initialized)
1521  {
1522  ERROR("[ERROR] Introspection is not initialized!\n");
1523  status = INT_STATUS_NOT_INITIALIZED;
1524  goto release_and_exit;
1525  }
1526 
1527  if (gGuest.EnterHibernate)
1528  {
1530  goto release_and_exit;
1531  }
1532 
1533  gEventId++;
1534 
1535  status = IntUpdateFlushAlertExceptions();
1536 
1537 release_and_exit:
1539 
1540  return status;
1541 }
1542 
1543 
1544 INTSTATUS
1546  _In_ void *GuestHandle,
1547  _In_ BOOLEAN Abort
1548  )
1556 {
1557  UNREFERENCED_PARAMETER(GuestHandle);
1558 
1559  if (gGuest.EnterHibernate)
1560  {
1562  }
1563 
1564  gAbortLoad = Abort;
1565 
1566  return INT_STATUS_SUCCESS;
1567 }
1568 
1569 
1570 INTSTATUS
1572  _In_ void *GuestHandle,
1573  _In_ IG_LOG_LEVEL LogLevel
1574  )
1582 {
1583  if (NULL == GuestHandle)
1584  {
1586  }
1587 
1589 
1590  gLogLevel = LogLevel;
1591 
1593 
1594  return INT_STATUS_SUCCESS;
1595 }
1596 
1597 
1598 INTSTATUS
1600  _In_ DWORD FullStringSize,
1601  _In_ DWORD VersionStringSize,
1602  _Out_ CHAR *FullString,
1603  _Out_ CHAR *VersionString
1604  )
1612 {
1613  INTSTATUS status = INT_STATUS_SUCCESS;
1614 
1615  if (NULL == FullString)
1616  {
1618  }
1619 
1620  if (NULL == VersionString)
1621  {
1623  }
1624 
1626 
1627  if (!gGuest.GuestInitialized)
1628  {
1629  WARNING("[WARNING] Introspection is not initialized!\n");
1630  status = INT_STATUS_NOT_INITIALIZED;
1631  goto release_and_exit;
1632  }
1633 
1634  if (gGuest.EnterHibernate)
1635  {
1637  goto release_and_exit;
1638  }
1639 
1640  gEventId++;
1641 
1643 
1644  if (gGuest.UninitPrepared)
1645  {
1646  WARNING("[WARNING] The uninit has been called, cannot send version strings!\n");
1647  status = INT_STATUS_NOT_SUPPORTED;
1648  goto release_and_exit;
1649  }
1650 
1651  if (introGuestLinux == gGuest.OSType)
1652  {
1653  status = IntGetVersionStringLinux(FullStringSize, VersionStringSize, FullString, VersionString);
1654  if (!INT_SUCCESS(status))
1655  {
1656  LOG("[ERROR] Could not get Linux version string: 0x%08x\n", status);
1657  }
1658  }
1659  else if (introGuestWindows == gGuest.OSType)
1660  {
1661  status = IntWinGetVersionString(FullStringSize, VersionStringSize, FullString, VersionString);
1662  if (!INT_SUCCESS(status))
1663  {
1664  LOG("[ERROR] Could not get Windows version string: 0x%08x\n", status);
1665  }
1666  }
1667  else
1668  {
1669  status = INT_STATUS_NOT_SUPPORTED;
1670  }
1671 
1672 release_and_exit:
1674 
1675  return status;
1676 }
uint16_t * PWCHAR
Definition: intro_types.h:63
#define _In_opt_
Definition: intro_sal.h:16
#define INT_STATUS_PAGE_NOT_PRESENT
Indicates that a virtual address is not present.
Definition: introstatus.h:438
#define DEC_OPT_NO_CACHE
Flag used to hint the instruction decoder to not use the instruction cache.
Definition: decoder.h:30
#define _Out_
Definition: intro_sal.h:22
_Bool BOOLEAN
Definition: intro_types.h:58
void IntCamiClearUpdateBuffer(void)
Uninitialize the update buffer and notify the integrator that we don&#39;t need it anymore.
void * gLock
A lock that ensures that all the events are serialized inside introcore.
Definition: introcore.c:24
INTSTATUS IntUpdateSupport(void *GuestHandle, PBYTE Buffer, DWORD Length)
Loads a new CAMI version.
Definition: introapi.c:1128
INTSTATUS IntGetVersionStringLinux(DWORD FullStringSize, DWORD VersionStringSize, CHAR *FullString, CHAR *VersionString)
Gets the version string for a Linux guest.
Definition: lixguest.c:2730
uint8_t BYTE
Definition: intro_types.h:47
BOOLEAN Terminating
Definition: guests.h:314
#define INTRO_OPT_AGENT_INJECTION
Enable agent injections.
Definition: intro_types.h:451
IG_ARCH_REGS Regs
The current state of the guest registers.
Definition: guests.h:95
#define _In_
Definition: intro_sal.h:21
INTSTATUS IntGuestDisableIntro(QWORD Flags)
Disables and unloads the introspection engine.
Definition: guests.c:1203
#define INT_STATUS_SUCCESS
Definition: introstatus.h:54
INTSTATUS IntWinProcRemoveAllProtectedProcesses(void)
This function removed all the processes from the protected process list.
Definition: winprocess.c:3880
uint16_t WORD
Definition: intro_types.h:48
INTSTATUS IntGetGprs(DWORD CpuNumber, PIG_ARCH_REGS Regs)
Get the current guest GPR state.
Definition: introcpu.c:827
INTSTATUS IntModifyDynamicOptions(void *GuestHandle, QWORD NewOptions)
Modifies the introcore options.
Definition: introapi.c:980
INTSTATUS IntGetExceptionsVersion(void *GuestHandle, WORD *MajorVersion, WORD *MinorVersion, DWORD *BuildNumber)
Get the current exceptions version.See PFUNC_IntGetExceptionsVersion for details. ...
Definition: introapi.c:1303
INTSTATUS IntAbortEnableIntro(void *GuestHandle, BOOLEAN Abort)
Abort the introcore loading process.
Definition: introapi.c:1545
void IntSpinLockRelease(void *SpinLock)
Definition: glue.c:848
INTSTATUS(* PFUNC_VirtualAddressSpaceCallback)(QWORD Cr3, QWORD VirtualAddress, QWORD Entry, QWORD PageSize)
The type of callback invoked by PFUNC_IntIterateVaSpace while iterating the guest virtual address spa...
Definition: glueiface.h:1814
DWORD IntGetCurrentCpu(void)
Returns the current CPU number.
Definition: introcpu.c:802
BOOLEAN Initialized
True if this structure was initialized and can be used.
Definition: guests.h:289
BOOLEAN ShutDown
True if the system process protection is in beta (log-only) mode.
Definition: guests.h:313
#define INT_SUCCESS(Status)
Definition: introstatus.h:42
enum _IG_GUEST_POWER_STATE IG_GUEST_POWER_STATE
The guest power state.
INTSTATUS IntResumeVcpus(void)
Resumes the VCPUs previously paused with IntPauseVcpus.
Definition: introcore.c:2355
INTSTATUS IntUpdateLoadExceptions(void *Buffer, DWORD Length, DWORD Flags)
Handles the exceptions coming from the integrator.
INTSTATUS IntDepInjectFile(BYTE *FileContent, DWORD FileSize, const CHAR *Name)
Inject a file inside the guest.
Definition: deployer.c:56
#define _In_reads_(expr)
Definition: intro_sal.h:27
INTSTATUS IntNewGuestNotification(void *GuestHandle, QWORD Options, PBYTE UpdateBuffer, DWORD BufferLength)
Handles a new guest. It is essentially the Introcore entry point.
Definition: introapi.c:81
IG_LOG_LEVEL gLogLevel
The currently used log level.
Definition: glue.c:68
BOOLEAN SafeToApplyOptions
True if the current options can be changed dynamically.
Definition: guests.h:294
INTSTATUS IntAddExceptionFromAlert(void *GuestHandle, const void *Event, INTRO_EVENT_TYPE Type, BOOLEAN Exception, QWORD Context)
Adds an exception for an alert reported by introcore.See PFUNC_IntAddExceptionFromAlert for details...
Definition: introapi.c:1402
void IntGuestPrepareUninit(void)
Prepares introcore to be unloaded.
Definition: guests.c:984
#define INT_STATUS_NOT_NEEDED_HINT
Definition: introstatus.h:317
Section will contain linux related information.
Definition: update_guests.h:48
#define ERROR(fmt,...)
Definition: glue.h:62
#define HpAllocWithTag(Len, Tag)
Definition: glue.h:516
int INTSTATUS
The status data type.
Definition: introstatus.h:24
INTSTATUS IntSetLogLevel(void *GuestHandle, IG_LOG_LEVEL LogLevel)
Sets the log level.
Definition: introapi.c:1571
QWORD gEventId
The ID of the current event.
Definition: glue.c:55
INTSTATUS IntCamiGetVersion(DWORD *MajorVersion, DWORD *MinorVersion, DWORD *BuildNumber)
Get the version of the loaded CAMI support file.
PVCPU_STATE VcpuArray
Array of the VCPUs assigned to this guest. The index in this array matches the VCPU number...
Definition: guests.h:372
INTSTATUS IntProcessDebugCommand(void *GuestHandle, DWORD CpuNumber, DWORD Argc, CHAR *Argv[])
Executes a debugger command.
Definition: introapi.c:1260
INTSTATUS IntRemoveAllProtectedProcesses(void *GuestHandle)
Removes the protection policies for all processes.
Definition: introapi.c:522
INTSTATUS IntPauseVcpus(void)
Pauses all the guest VCPUs.
Definition: introcore.c:2320
INTSTATUS IntIterateVaSpace(void *GuestHandle, QWORD Cr3, PFUNC_VirtualAddressSpaceCallback Callback)
Iterates over the guest virtual address space.
Definition: introapi.c:881
INTRO_GUEST_TYPE OSType
The type of the guest.
Definition: guests.h:278
Commit all the memory hooks.
Definition: guests.h:436
#define INT_STATUS_OPERATION_NOT_IMPLEMENTED
Definition: introstatus.h:125
void * gIntHandle
The guest handle provided by the integrator at initialization.
Definition: glue.c:49
INTSTATUS IntAddRemoveProtectedProcessUtf8(void *GuestHandle, const CHAR *FullPath, DWORD ProtectionMask, BOOLEAN Add, QWORD Context)
Toggles protection options for a process.
Definition: introapi.c:299
INTSTATUS IntIterateVirtualAddressSpace(QWORD Cr3, PFUNC_VirtualAddressSpaceCallback Callback)
Iterate an entire virtual address space.
Definition: kernvm.c:327
INTSTATUS IntFlushGpaCache(void *GuestHandle)
Flushed the introcore GPA cache.
Definition: introapi.c:1026
INTSTATUS IntCamiSetUpdateBuffer(const BYTE *UpdateBuffer, DWORD BufferLength)
Initialize the update buffer with the one from the integrator.
#define LOG(fmt,...)
Definition: glue.h:61
void IntVeHandleGuestResumeFromSleep(void)
Simply set the VeAgentWaiting variable to true if VE is enabled.
Definition: vecore.c:2787
BOOLEAN gAbortLoad
Set to True if introcore should abort the initialization process.
Definition: introcore.c:59
INTSTATUS IntGpaCacheFlush(PGPA_CACHE Cache)
Flush the entire GPA cache.
Definition: gpacache.c:776
INTSTATUS IntGetCurrentInstructionLength(void *GuestHandle, DWORD CpuNumber, BYTE *Length)
Returns the length of the instruction at which the current guest RIP points.
Definition: introapi.c:729
The guest is shutting down by force.
Definition: glueiface.h:382
The guest is resuming from hibernate or sleep.
Definition: glueiface.h:379
INTSTATUS IntUpdateExceptions(void *GuestHandle, PBYTE Buffer, DWORD Length, DWORD Flags)
Loads a new exceptions version.See PFUNC_IntUpdateExceptions for details.
Definition: introapi.c:1352
INTSTATUS IntGetCurrentInstructionMnemonic(void *GuestHandle, DWORD CpuNumber, CHAR *Mnemonic)
Returns the mnemonic of the instruction at which the current guest RIP points.
Definition: introapi.c:806
INTSTATUS IntWinGetVersionString(DWORD FullStringSize, DWORD VersionStringSize, CHAR *FullString, CHAR *VersionString)
Gets the version string for a Windows guest.
Definition: winguest.c:2650
INTSTATUS IntRemoveException(void *GuestHandle, QWORD Context)
Removes a custom exception added with GLUE_IFACE.AddExceptionFromAlert.See PFUNC_IntRemoveException f...
Definition: introapi.c:1452
#define INT_STATUS_NOT_INITIALIZED
Definition: introstatus.h:266
INTSTATUS IntGuestPreReturnCallback(DWORD Options)
Handles all the operations that must be done before returning from a VMEXIT event handler...
Definition: guests.c:1280
#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 IntWinProcAddProtectedProcess(const WCHAR *Path, DWORD ProtectionMask, QWORD Context)
This function adds the provided process to the protected process list.
Definition: winprocess.c:3712
uint8_t * PBYTE
Definition: intro_types.h:47
INTSTATUS IntDisableIntro(void *GuestHandle, QWORD Flags)
Disables and unloads the introspection engine.
Definition: introapi.c:176
unsigned long long QWORD
Definition: intro_types.h:53
QWORD Current
The currently used options.
Definition: guests.h:236
Section will contain protection flags.
Definition: update_guests.h:45
INTSTATUS IntFlushAlertExceptions(void *GuestHandle)
Removes all the custom exceptions added with GLUE_IFACE.AddExceptionFromAlert.See PFUNC_IntFlushAlert...
Definition: introapi.c:1499
INTSTATUS IntLixTaskAddProtected(const char *ProcessName, QWORD ProtectionMask, QWORD Context)
Adds a protected process name pattern.
Definition: lixprocess.c:4334
void * GpaCache
The currently used GPA cache.
Definition: guests.h:403
#define TRUE
Definition: intro_types.h:30
#define INT_STATUS_INVALID_PARAMETER_4
Definition: introstatus.h:71
BOOLEAN GuestInitialized
True if the OS-specific portion has been initialized.
Definition: guests.h:293
INTSTATUS IntDepInjectProcess(DWORD AgentTag, BYTE *AgentContent, DWORD AgentSize, const CHAR *Name, const CHAR *Args)
Injects a process inside the guest.
Definition: deployer.c:12
#define HpFreeAndNullWithTag(Add, Tag)
Definition: glue.h:517
#define TRACE(fmt,...)
Definition: glue.h:58
INTSTATUS IntGetCurrentIntroOptions(void *GuestHandle, QWORD *IntroOptions)
Get the currently used introcore options.
Definition: introapi.c:1077
INTSTATUS IntDbgProcessCommand(DWORD Argc, const char *Argv[])
Definition: debugger.c:2857
INTSTATUS IntGetSupportVersion(void *GuestHandle, DWORD *MajorVersion, DWORD *MinorVersion, DWORD *BuildNumber)
Get the current version of CAMI.
Definition: introapi.c:1212
size_t strlcpy(char *dst, const char *src, size_t dest_size)
Definition: introcrt.c:1093
#define INT_STATUS_ALREADY_INITIALIZED_HINT
Definition: introstatus.h:323
#define INT_STATUS_UNINIT_BUGCHECK
Indicates that the guest crashed and Introcore must be deactivated.
Definition: introstatus.h:430
BOOLEAN UninitPrepared
Definition: guests.h:320
#define WARNING(fmt,...)
Definition: glue.h:60
INTSTATUS IntLixTaskRemoveProtected(const char *ProcessName)
Removes a pattern of processes to be protected.
Definition: lixprocess.c:4439
The guest is entering sleep.
Definition: glueiface.h:380
void IntSpinLockAcquire(void *SpinLock)
Definition: glue.c:833
#define UNREFERENCED_PARAMETER(P)
Definition: introdefs.h:29
void * InstructionCache
The currently used instructions cache.
Definition: guests.h:404
uint16_t WCHAR
Definition: intro_types.h:63
uint32_t DWORD
Definition: intro_types.h:49
void IntGuestUninit(void)
Completely unloads the introspection engine.
Definition: guests.c:1036
static void IntApiEnter(DWORD CpuNumber)
Common API handler.
Definition: introapi.c:51
#define _In_reads_bytes_(expr)
Definition: intro_sal.h:25
BOOLEAN EnterHibernate
True if the guest is entering into hibernate.
Definition: guests.h:319
#define IntDbgEnterDebugger()
Definition: introcore.h:381
void IntPtiHandleGuestResumeFromSleep(void)
Sets PtFilterWaiting to true if PT filtering was enabled, or to false otherwise.
Definition: ptfilter.c:2064
GUEST_STATE gGuest
The current guest state.
Definition: guests.c:50
#define _In_z_
Definition: intro_sal.h:17
#define IC_TAG_ALLOC
Memory allocation.
Definition: memtags.h:28
enum _IG_LOG_LEVEL IG_LOG_LEVEL
Controls the verbosity of the logs.
Guest information.
Definition: intro_types.h:2377
INTSTATUS IntInjectProcessAgentInGuest(void *GuestHandle, DWORD AgentTag, PBYTE AgentContent, DWORD AgentSize, const CHAR *Name, const CHAR *Args)
Requests a process agent injection inside the guest.
Definition: introapi.c:585
Section will contain windows related information.
Definition: update_guests.h:47
#define INT_STATUS_NO_MAPPING_STRUCTURES
Indicates that not all mapping structures of a virtual address are present.
Definition: introstatus.h:434
INTSTATUS IntUpdateFlushAlertExceptions(void)
This function removes all exceptions that were added from alerts.
INTSTATUS IntNotifyGuestPowerStateChange(void *GuestHandle, IG_GUEST_POWER_STATE PowerState)
Handles guest power state transitions.
Definition: introapi.c:231
INTSTATUS IntGetVersionString(DWORD FullStringSize, DWORD VersionStringSize, CHAR *FullString, CHAR *VersionString)
Get the version string information for the current guest.
Definition: introapi.c:1599
The guest is shutting down.
Definition: glueiface.h:381
INTSTATUS IntInjectFileAgentInGuest(void *GuestHandle, PBYTE AgentContent, DWORD AgentSize, const CHAR *Name)
Drops a file on the guest hard disk.
Definition: introapi.c:658
#define INT_STATUS_INVALID_PARAMETER_1
Definition: introstatus.h:62
#define INT_STATUS_NOT_SUPPORTED
Definition: introstatus.h:287
VCPU_STATE * gVcpu
The state of the current VCPU.
Definition: guests.c:59
INTSTATUS IntNotifyIntroErrorState(INTRO_ERROR_STATE State, INTRO_ERROR_CONTEXT *Context)
Definition: glue.c:989
enum _INTRO_EVENT_TYPE INTRO_EVENT_TYPE
Event classes.
void IntGuestUpdateCoreOptions(QWORD NewOptions)
Updates Introcore options.
Definition: guests.c:1426
INTSTATUS IntDecDecodeInstructionAtRipWithCache(void *Cache, DWORD CpuNumber, PIG_ARCH_REGS Registers, PINSTRUX Instrux, DWORD Options, BOOLEAN *CacheHit, BOOLEAN *Added)
Decode an instruction using the cache.
Definition: decoder.c:449
INTSTATUS IntUpdateGetVersion(WORD *MajorVersion, WORD *MinorVersion, DWORD *BuildNumber)
Get the version of the loaded exceptions binary file.
#define INT_STATUS_POWER_STATE_BLOCK
Definition: introstatus.h:461
BOOLEAN BugCheckInProgress
Definition: guests.h:333
char CHAR
Definition: intro_types.h:56
The version of the provided CAMI file is not supported.
Definition: intro_types.h:2442
INTSTATUS IntGuestGetInfo(PGUEST_INFO GuestInfo)
Get basic information about the guest.
Definition: guests.c:350
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 INTRO_OPT_ENABLE_KM_BETA_DETECTIONS
Aggregates all the kernel log-only detection flags.
Definition: intro_types.h:591
#define INT_STATUS_INVALID_PARAMETER_2
Definition: introstatus.h:65
INTRO_PROT_OPTIONS CoreOptions
The activation and protection options for this guest.
Definition: guests.h:271
INTSTATUS IntGetGuestInfo(void *GuestHandle, GUEST_INFO *GuestInfo)
Get a description of the introspected guest.
Definition: introapi.c:930
INTSTATUS IntWinProcRemoveProtectedProcess(const WCHAR *Path)
This function removed the provided process from the protected process list.
Definition: winprocess.c:3826
INTSTATUS IntUpdateRemoveException(QWORD Context)
This function removes an exception for a given context.
INTSTATUS IntAddRemoveProtectedProcessUtf16(void *GuestHandle, const WCHAR *FullPath, DWORD ProtectionMask, BOOLEAN Add, QWORD Context)
Toggles protection options for a process.
Definition: introapi.c:435
Inject pending page faults.
Definition: guests.h:441
INTSTATUS IntCamiLoadSection(DWORD CamiSectionHint)
Load CAMI objects from section with given hint.
static void IntApiLeave(BOOLEAN Async)
Handles API exists.
Definition: introapi.c:27
INTSTATUS IntGuestInit(QWORD Options)
Initialize the given guest state.
Definition: guests.c:755
#define INT_STATUS_INSUFFICIENT_RESOURCES
Definition: introstatus.h:281
#define INT_STATUS_INVALID_PARAMETER_3
Definition: introstatus.h:68