Bitdefender Hypervisor Memory Introspection
winummodule.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020 Bitdefender
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 #include "winummodule.h"
6 #include "alerts.h"
7 #include "hook.h"
8 #include "swapmem.h"
9 #include "unpacker.h"
10 #include "winprocesshp.h"
11 #include "winummoduleblock.h"
12 #include "winumdoubleagent.h"
13 
14 
20 {
21  { u"ntdll.dll", NAMEHASH_NTDLL },
22  { u"kernel32.dll", NAMEHASH_KERNEL32 },
23  { u"kernelbase.dll", NAMEHASH_KERNELBASE },
24  { u"user32.dll", NAMEHASH_USER32 },
25  // Add any other modules here.
26 };
27 
28 
33 {
34  { u"ws2_32.dll", NAMEHASH_WS2_32 },
35  { u"wininet.dll", NAMEHASH_WININET },
36 };
37 
38 
43 {
44  { u"ntdll.dll", NAMEHASH_NTDLL },
45  { u"wow64.dll", NAMEHASH_WOW64 },
46  { u"wow64win.dll", NAMEHASH_WOW64WIN },
47  { u"wow64cpu.dll", NAMEHASH_WOW64CPU },
48 
49  // Add any other modules here.
50 };
51 
52 
53 static INTSTATUS
56  );
57 
58 
59 static BOOLEAN
61  _In_ const WIN_PROCESS_MODULE *Module,
62  _In_ const PROTECTED_DLL_INFO *ProtectedList,
63  _In_ size_t ProtectedCount
64  )
74 {
75  for (DWORD i = 0; i < ProtectedCount; i++)
76  {
77  if (MODULE_MATCH(Module, &ProtectedList[i]))
78  {
79  return TRUE;
80  }
81  }
82 
83  return FALSE;
84 }
85 
86 
87 static INTSTATUS
90  _In_ BOOLEAN Loaded
91  )
105 {
106  INTSTATUS status;
107  PEVENT_MODULE_EVENT pModEvent;
108 
110  {
112  }
113 
115  {
117  }
118 
119  if (Loaded && Module->LoadEventSent)
120  {
122  }
123 
124  if (!Loaded && Module->UnloadEventSent)
125  {
127  }
128 
129  if ((NULL == Module->Path) || (0 == Module->VirtualBase) || (0 == Module->Size))
130  {
132  }
133 
134  pModEvent = &gAlert.Module;
135  memzero(pModEvent, sizeof(*pModEvent));
136 
137  pModEvent->Loaded = Loaded;
138  pModEvent->Protected = Module->ShouldProtHooks || Module->ShouldProtUnpack;
139  pModEvent->UserMode = TRUE;
140 
141  IntAlertFillWinUmModule(Module, &pModEvent->Module);
142 
143  IntAlertFillWinProcess(Module->Subsystem->Process, &pModEvent->CurrentProcess);
144 
145  status = IntNotifyIntroEvent(introEventModuleEvent, pModEvent, sizeof(*pModEvent));
146  if (!INT_SUCCESS(status))
147  {
148  WARNING("[WARNING] IntNotifyIntroEvent failed: 0x%08x\n", status);
149  }
150 
151  if (Loaded)
152  {
153  Module->LoadEventSent = TRUE;
154  }
155  else
156  {
157  Module->UnloadEventSent = TRUE;
158  }
159 
160  return status;
161 }
162 
163 
164 static INTSTATUS
166  _In_ PWIN_PROCESS_SUBSYSTEM Subsystem
167  )
178 {
179  LIST_ENTRY *list;
180  PWIN_PROCESS_MODULE pMod;
181 
182  list = Subsystem->ProcessModules.Flink;
183  while (list != &Subsystem->ProcessModules)
184  {
185  pMod = CONTAINING_RECORD(list, WIN_PROCESS_MODULE, Link);
186 
187  list = list->Flink;
188 
190  }
191 
192  return INT_STATUS_SUCCESS;
193 }
194 
195 
196 INTSTATUS
198  _In_ PWIN_PROCESS_OBJECT Process
199  )
207 {
208  if (NULL != Process->Subsystemx86)
209  {
210  IntWinProcSendAllDllEventsForSubsystem(Process->Subsystemx86);
211  }
212 
213  if (NULL != Process->Subsystemx64)
214  {
215  IntWinProcSendAllDllEventsForSubsystem(Process->Subsystemx64);
216  }
217 
218  return INT_STATUS_SUCCESS;
219 }
220 
221 
222 static void
225  )
234 {
235  PWIN_PROCESS_OBJECT pProc = Module->Subsystem->Process;
236 
237  // If the j9jit.dll is loaded and we are in a Java process, we may be in the Java IBM case
238  // where certain VADs must be excepted at execution
239  if (strstr_utf16(Module->Path->Name, u"j9jit") &&
240  strstr(pProc->Name, "java"))
241  {
242  pProc->IsDominoJava = TRUE;
243  pProc->FirstDominoJavaIgnored = FALSE;
244  }
245 }
246 
247 
248 static INTSTATUS
250  _In_ void *Context,
251  _In_ QWORD Cr3,
252  _In_ QWORD ModuleBase,
253  _In_ QWORD PhysicalAddress,
254  _In_reads_bytes_(DataSize) PBYTE Data,
255  _In_ DWORD DataSize,
256  _In_ DWORD Flags
257  )
275 {
276  INTSTATUS status;
277  PWIN_PROCESS_MODULE pMod;
279  PWIN_PROCESS_OBJECT pProc;
280 
282  UNREFERENCED_PARAMETER(DataSize);
283  UNREFERENCED_PARAMETER(Flags);
284 
285  if (NULL == Context)
286  {
288  }
289 
290  if (NULL == Data)
291  {
293  }
294 
295  status = INT_STATUS_SUCCESS;
296 
297  pMod = (PWIN_PROCESS_MODULE)Context;
298 
299  pMod->HeadersSwapHandle = NULL;
300 
301  pSubs = pMod->Subsystem;
302  if (NULL == pSubs)
303  {
305  }
306 
307  pProc = pSubs->Process;
308  if (NULL == pProc)
309  {
311  }
312 
313  if ((Data[0] != 'M') || (Data[1] != 'Z'))
314  {
315  ERROR("[ERROR] Module is not a valid MZ image: %x%x, 0x%016llx:0x%016llx\n", Data[0], Data[1], ModuleBase,
316  PhysicalAddress);
318  }
319 
320  TRACE("[MODULE] Main module for process %llx (subsystem %d) has loaded!\n",
321  pProc->EprocessAddress, pSubs->SubsystemType);
322 
323  if (pMod->ShouldProtUnpack)
324  {
325  TRACE("[MODULE] Protecting module with base 0x%016llx -> 0x%016llx against unpacking.\n", ModuleBase, Cr3);
326 
327  status = IntWinModHookPoly(pMod);
328  if (!INT_SUCCESS(status))
329  {
330  ERROR("[ERROR] IntWinModHookPoly failed: 0x%08x\n", status);
331  }
332 
333  pProc->UnpackProtected = TRUE;
334  }
335 
336  return status;
337 }
338 
339 
340 static int
342  _In_ const WIN_PROCESS_MODULE *Module,
343  _In_ const WCHAR *SystemDirPath,
344  _In_ const WCHAR *TestModule
345  )
355 {
356  WCHAR targetPath[MAX_PATH];
357  size_t k, l;
358 
359  // Copy the directory path. They're both the same size, so it's safe to copy it entirely.
360  memcpy(targetPath,
361  SystemDirPath,
362  MIN(sizeof(targetPath) - sizeof(WCHAR), (wstrlen(SystemDirPath) + 1) * sizeof(WCHAR)));
363 
364  // In case the memcpy didn't copy it
365  targetPath[MAX_PATH - 1] = 0;
366 
367  // Append the module name.
368  k = 0;
369  while ((k < MAX_PATH) && (0 != targetPath[k]))
370  {
371  k++;
372  }
373 
374  l = 0;
375  while ((k + 1 < MAX_PATH) && (0 != TestModule[l]))
376  {
377  targetPath[k] = TestModule[l];
378 
379  k++, l++;
380  }
381 
382  // Append the null terminator.
383  targetPath[k] = 0;
384 
385  return wstrncasecmp_len(targetPath, Module->Path->Path, k, Module->Path->PathSize / 2);
386 }
387 
388 
389 static QWORD
391  _In_ WIN_PROCESS_MODULE *Module
392  )
400 {
401  for (DWORD i = 0; i < ARRAYSIZE(gProtectedModules); i++)
402  {
403  if (MODULE_MATCH(Module, &gProtectedModules[i]))
404  {
406  }
407  }
408 
409  for (DWORD i = 0; i < ARRAYSIZE(gProtectedWowModules); i++)
410  {
411  if (MODULE_MATCH(Module, &gProtectedWowModules[i]))
412  {
414  }
415  }
416 
417  for (DWORD i = 0; i < ARRAYSIZE(gProtectedNetModules); i++)
418  {
419  if (MODULE_MATCH(Module, &gProtectedNetModules[i]))
420  {
422  }
423  }
424 
425  return 0;
426 }
427 
428 
429 static INTSTATUS
431  _In_ void *Context,
432  _In_ void *Hook,
433  _In_ QWORD Address,
434  _Out_ INTRO_ACTION *Action
435  )
446 {
447  INTSTATUS status = INT_STATUS_SUCCESS;
448  EXCEPTION_KM_ORIGINATOR originator = { 0 };
449  EXCEPTION_VICTIM_ZONE victim = { 0 };
451  BOOLEAN informationOnly = FALSE;
452  WIN_PROCESS_MODULE *pModule = (WIN_PROCESS_MODULE *)Context;
453  WIN_PROCESS_OBJECT *pProcess = pModule->Subsystem->Process;
454 
455  *Action = introGuestNotAllowed;
456 
458 
459  status = IntExceptKernelGetOriginator(&originator, 0);
460  if (!INT_SUCCESS(status))
461  {
462  ERROR("[ERROR] IntExceptKernelGetOriginator failed with status: 0x%08x\n", status);
463 
464  reason = introReasonInternalError;
465  informationOnly = TRUE;
466  }
467 
468  status = IntExceptGetVictimEpt(Context,
469  Address,
470  IntHookGetGlaFromGpaHook(Hook, Address),
472  ZONE_WRITE,
473  &victim);
474  if (!INT_SUCCESS(status))
475  {
476  ERROR("[ERROR] IntExceptGetVictimEpt failed with status: 0x%08x\n", status);
477 
478  reason = introReasonInternalError;
479  informationOnly = TRUE;
480  }
481 
482  if (informationOnly)
483  {
484  IntExceptKernelUserLogInformation(&victim, &originator, *Action, reason);
485  }
486  else
487  {
488  IntExcept(&victim, &originator, exceptionTypeKmUm, Action, &reason, introEventEptViolation);
489  }
490 
492 
493  if (IntPolicyProcTakeAction(IntWinModGetProtectionOptionForModule(pModule), pProcess, Action, &reason))
494  {
495  EVENT_EPT_VIOLATION *pEptViol = &gAlert.Ept;
496 
497  memzero(pEptViol, sizeof(*pEptViol));
498 
499  pEptViol->Header.Action = *Action;
500  pEptViol->Header.Reason = reason;
501  pEptViol->Header.MitreID = idHooking;
502 
504 
505  IntAlertEptFillFromKmOriginator(&originator, pEptViol);
506  IntAlertEptFillFromVictimZone(&victim, pEptViol);
507 
509  pModule->Subsystem->Process, reason, ALERT_FLAG_KM_UM);
510 
512 
513  IntAlertFillCodeBlocks(originator.Original.Rip, gVcpu->Regs.Cr3, FALSE, &pEptViol->CodeBlocks);
514  IntAlertFillExecContext(0, &pEptViol->ExecContext);
515 
516  IntAlertFillVersionInfo(&pEptViol->Header);
517 
518  status = IntNotifyIntroEvent(introEventEptViolation, pEptViol, sizeof(*pEptViol));
519  if (!INT_SUCCESS(status))
520  {
521  WARNING("[WARNING] IntNotifyIntroEvent failed: 0x%08x\n", status);
522  }
523 
524  status = INT_STATUS_SUCCESS;
525  }
526 
528 
529  return status;
530 }
531 
532 
533 static INTSTATUS
535  _In_ void *Context,
536  _In_ void *Hook,
537  _In_ QWORD Address,
538  _Out_ INTRO_ACTION *Action
539  )
558 {
559  INTSTATUS status;
560  PWIN_PROCESS_MODULE pMod;
561  PWIN_PROCESS_OBJECT pOriginatorProc;
562  INTRO_ACTION_REASON reason;
563  PIG_ARCH_REGS regs;
564  EXCEPTION_UM_ORIGINATOR originator;
565  EXCEPTION_VICTIM_ZONE victim;
566  DWORD iatidx, iatesz;
567 
568  status = INT_STATUS_SUCCESS;
569 
570  pMod = (PWIN_PROCESS_MODULE)Context;
571 
572  regs = &gVcpu->Regs;
573 
574  *Action = introGuestNotAllowed;
575  reason = introReasonInternalError;
576 
577  if (regs->Cr3 != pMod->Subsystem->Process->Cr3)
578  {
579  const WIN_PROCESS_OBJECT *p = pMod->Subsystem->Process;
581 
582  WARNING("[WARNING] [SPECIAL-CASE] Process (pid: %d, eproc %llx, cr3 %llx, usercr3 %llx, name %s) "
583  "is not the current one (current cr3 %llx, gva %llx, gpa %llx, ac %d)\n",
584  p->Pid, p->EprocessAddress, p->Cr3, p->UserCr3, p->Name, regs->Cr3,
586  if (NULL != p2)
587  {
588  WARNING("[WARNING] [SPECIAL-CASE] Process (pid: %d, eproc %llx, cr3 %llx, usercr3 %llx, name %s) "
589  "is the current one!\n", p2->Pid, p2->EprocessAddress, p2->Cr3, p2->UserCr3, p2->Name);
590  }
591  }
592 
593  // Whitelist for ntdll!LdrpTouchPageForWrite.
594  if ((gVcpu->AccessSize == 1) &&
595  (gVcpu->Instruction.Instruction == ND_INS_OR) &&
596  (gVcpu->Instruction.HasImm1) &&
597  (gVcpu->Instruction.Immediate1 == 0))
598  {
599  *Action = introGuestAllowed;
600  reason = introReasonAllowed;
601 
602  goto _cleanup_and_exit;
603  }
604 
605  iatesz = (pMod->Is64BitModule ? 8 : 4);
606 
607  // White listing for IAT writes - we allow the first write that takes place in each IAT entry
608  // if it is done from ntdll
609  if ((pMod->IATBitmap != NULL) && (gVcpu->Gla >= pMod->VirtualBase + pMod->Cache->Info.IatRva) &&
610  (gVcpu->Gla < pMod->VirtualBase + pMod->Cache->Info.IatRva + (QWORD)pMod->IATEntries * iatesz) &&
611  (gVcpu->Regs.Rip >= pMod->Subsystem->NtdllBase &&
612  gVcpu->Regs.Rip < pMod->Subsystem->NtdllBase + pMod->Subsystem->NtdllSize))
613  {
614  iatidx = (DWORD)(gVcpu->Gla - (pMod->VirtualBase + pMod->Cache->Info.IatRva)) / iatesz;
615 
616  if (pMod->IATBitmap[iatidx] == 0)
617  {
618  pMod->IATBitmap[iatidx]++;
619 
620  *Action = introGuestAllowed;
621  reason = introReasonAllowed;
622 
623  goto _cleanup_and_exit;
624  }
625  }
626 
628 
629  memzero(&originator, sizeof(originator));
630  memzero(&victim, sizeof(victim));
631 
632  pOriginatorProc = pMod->Subsystem->Process;
633 
634  status = IntExceptUserGetOriginator(pOriginatorProc, TRUE, regs->Rip, &gVcpu->Instruction, &originator);
635  if (!INT_SUCCESS(status))
636  {
637  reason = introReasonInternalError;
638  *Action = introGuestNotAllowed;
639 
640  ERROR("[ERROR] Failed getting originator: 0x%08x\n", status);
641  goto _send_notification;
642  }
643 
644  status = IntExceptGetVictimEpt(pMod,
645  Address,
646  IntHookGetGlaFromGpaHook(Hook, Address),
648  ZONE_WRITE,
649  &victim);
650  if (!INT_SUCCESS(status))
651  {
652  reason = introReasonInternalError;
653  *Action = introGuestNotAllowed;
654 
655  ERROR("[ERROR] Failed getting modified zone: 0x%08x\n", status);
656  goto _send_notification;
657  }
658 
659  IntExcept(&victim, &originator, exceptionTypeUm, Action, &reason, introEventEptViolation);
660 
661 _send_notification:
663 
665  {
666  PEVENT_EPT_VIOLATION pEptViol = &gAlert.Ept;
667 
668  // First of all, send ALL the dll events.
669  IntWinProcSendAllDllEventsForProcess(pOriginatorProc);
670 
671  memzero(pEptViol, sizeof(*pEptViol));
672 
673  pEptViol->Header.Action = *Action;
674  pEptViol->Header.Reason = reason;
675  pEptViol->Header.MitreID = idHooking;
676 
678 
679  IntAlertEptFillFromUmOriginator(&originator, pEptViol);
680  IntAlertEptFillFromVictimZone(&victim, pEptViol);
681 
683  pMod->Subsystem->Process, reason, 0);
684 
686 
687  IntAlertFillCodeBlocks(regs->Rip, regs->Cr3, FALSE, &pEptViol->CodeBlocks);
688  IntAlertFillExecContext(0, &pEptViol->ExecContext);
689 
690  IntAlertFillVersionInfo(&pEptViol->Header);
691 
692  status = IntNotifyIntroEvent(introEventEptViolation, pEptViol, sizeof(*pEptViol));
693  if (!INT_SUCCESS(status))
694  {
695  WARNING("[WARNING] IntNotifyIntroEvent failed: 0x%08x\n", status);
696  }
697 
698  status = INT_STATUS_SUCCESS;
699  }
700 
701 _cleanup_and_exit:
703 
704  return status;
705 }
706 
707 
708 INTSTATUS
710  _In_opt_ void *Context,
711  _In_ void *Hook,
712  _In_ QWORD Address,
713  _Out_ INTRO_ACTION *Action
714  )
727 {
728  if (NULL == Context)
729  {
731  }
732 
733  if (NULL == Action)
734  {
736  }
737 
738  *Action = introGuestNotAllowed;
739 
741  {
742  return IntWinModHandleKernelWrite(Context, Hook, Address, Action);
743  }
744  else
745  {
746  return IntWinModHandleUserWrite(Context, Hook, Address, Action);
747  }
748 }
749 
750 
751 static INTSTATUS
754  )
768 {
769  INTSTATUS status;
770  DWORD sectionRva = 0;
771  DWORD sectionCount = 0;
772  DWORD i;
773  PWIN_PROCESS_OBJECT pProc;
775 
776  pProc = Module->Subsystem->Process;
777 
778  if (NULL == Module->Cache || NULL == Module->Cache->Headers)
779  {
780  ERROR("[ERROR] Invalid state where module doesn't has cache (%p) or headers!\n", Module->Cache);
782  }
783 
784 #define MAX_IAT_ENTRIES 4096
785 
786  Module->IATEntries = Module->Cache->Info.IatSize / (Module->Is64BitModule ? 8 : 4);
787  if (Module->IATEntries > MAX_IAT_ENTRIES)
788  {
789  WARNING("[WARNING] Module `%s` has %d IAT entries. Will use MAX_IAT_ENTRIES.",
790  utf16_for_log(Module->Path->Name), Module->IATEntries);
791  Module->IATEntries = MAX_IAT_ENTRIES;
792  }
793 
794 
795  if (Module->IATEntries != 0)
796  {
797  // Each entry will be initialized when that IAT entry will be written by the loader. The first write will be
798  // allowed without checking the exceptions, all the other writes will go through the exceptions mechanism.
799  Module->IATBitmap = HpAllocWithTag(Module->IATEntries, IC_TAG_IATB);
800  if (NULL == Module->IATBitmap)
801  {
803  }
804  }
805 
806  status = IntHookObjectCreate(0, pProc->Cr3, &Module->HookObject);
807  if (!INT_SUCCESS(status))
808  {
809  ERROR("[ERROR] IntHookObjectCreate failed: 0x%08x\n", status);
810  return status;
811  }
812 
813  // At this point, there is no point in doing any verification, since they were already done
814  // in the previous step (pre-hooking). The MzPeHeaders won't be present if they were invalid.
815  status = IntPeListSectionsHeaders(Module->VirtualBase,
816  Module->Cache->Headers,
817  PAGE_SIZE,
818  &sectionRva,
819  &sectionCount);
820  if (!INT_SUCCESS(status))
821  {
822  ERROR("[ERROR] IntPeListSectionsHeaders failed with status: 0x%08x\n", status);
823  return status;
824  }
825 
826  TRACE("[MODULE] Protecting module '%s' loaded at 0x%016llx\n",
827  utf16_for_log(Module->Path->Path), Module->VirtualBase);
828 
829  sec = (IMAGE_SECTION_HEADER *)(Module->Cache->Headers + sectionRva);
830  for (i = 0; i < sectionCount; i++, sec++)
831  {
833  {
834  continue;
835  }
836 
837  if ((QWORD)sec->VirtualAddress + sec->Misc.VirtualSize > Module->Vad->PageCount * PAGE_SIZE)
838  {
839  INFO("[INFO] Skipping section from VA 0x%08x, size 0x%08x, which is larger than VadSize 0x%016llx\n",
840  sec->VirtualAddress, sec->Misc.VirtualSize, Module->Vad->PageCount * PAGE_SIZE);
841  continue;
842  }
843 
844 #ifdef DEBUG
845  // The name of the section isn't always NULL terminated, let's make sure it is
846  CHAR name[sizeof(sec->Name) + 1];
847  memcpy(name, sec->Name, sizeof(sec->Name));
848  name[sizeof(sec->Name)] = 0;
849 
850  TRACE("[MODULE] Protecting pageable region: 0x%016llx, VA space 0x%016llx, length %x Name `%s`\n",
851  Module->VirtualBase + sec->VirtualAddress, pProc->Cr3, sec->Misc.VirtualSize, name);
852 #endif
853 
854  status = IntHookObjectHookRegion(Module->HookObject,
855  pProc->Cr3,
856  Module->VirtualBase + sec->VirtualAddress,
860  Module,
861  0,
862  NULL);
863  if (!INT_SUCCESS(status))
864  {
865  ERROR("[ERROR] IntHookObjectHookRegion failed: 0x%08x\n", status);
866  }
867  }
868 
869  Module->IsProtected = TRUE;
870 
871  Module->Subsystem->ProtectedModulesCount++;
872 
873  return INT_STATUS_SUCCESS;
874 }
875 
876 
877 INTSTATUS
880  )
889 {
890  INTSTATUS status;
891 
892  if (NULL == Module)
893  {
895  }
896 
897  // Remove the unpacker, if active.
898  if (Module->ShouldProtUnpack && Module->Subsystem->Process->UnpackProtected)
899  {
900  status = IntUnpUnWatchVaSpacePages(Module->Subsystem->Process->Cr3);
901  if (!INT_SUCCESS(status))
902  {
903  ERROR("[ERROR] IntUnpUnWatchVaSpacePages failed: 0x%08x\n", status);
904  }
905  }
906 
907  // Remove the protection, if any.
908  if (NULL != Module->HookObject)
909  {
910  status = IntHookObjectDestroy((HOOK_OBJECT_DESCRIPTOR **)&Module->HookObject, 0);
911  if (!INT_SUCCESS(status))
912  {
913  ERROR("[ERROR] IntHookObjectDestroy failed: 0x%08x\n", status);
914  }
915  }
916 
917  if (NULL != Module->ModBlockObject)
918  {
919  status = IntWinModBlockRemoveBlockObject(Module->ModBlockObject);
920  if (!INT_SUCCESS(status))
921  {
922  ERROR("[ERROR] IntWinModBlockRemoveBlockObject failed: 0x%08x\n", status);
923  }
924  }
925 
926  if (Module->IsProtected)
927  {
928  Module->Subsystem->ProtectedModulesCount--;
929  }
930 
931  Module->IsProtected = FALSE;
932 
933  return INT_STATUS_SUCCESS;
934 }
935 
936 
937 INTSTATUS
939  _In_ void *Context,
940  _In_ QWORD Cr3,
941  _In_ QWORD VirtualAddress
942  )
958 {
960  UNREFERENCED_PARAMETER(VirtualAddress);
961 
963  if (NULL == pMod)
964  {
966  }
967 
968  // We try to inject a #PF on this module. We have to make sure that the VAD corresponding to this module is already
969  // inserted in the RB tree inside the guest! If we inject a #PF but the VAD is not queued yet, we will end up
970  // crashing the process, because it would receive a #PF for an address which is still invalid (because the VAD
971  // is not inserted in the tree yet!)
972  if (!IntWinVadIsInTree(pMod->Vad))
973  {
974  LOG("[WINMODULE] The VAD 0x%016llx belonging to module %s seems to not be inside the tree yet, "
975  "will postpone #PF...\n", pMod->Vad->VadGva, utf16_for_log(pMod->Path->Path));
976 
978  }
979 
980  return INT_STATUS_SUCCESS;
981 }
982 
983 
984 static INTSTATUS
986  _In_ void *Context,
987  _In_ QWORD Cr3,
988  _In_ QWORD VirtualAddress,
989  _In_ QWORD PhysicalAddress,
990  _In_reads_bytes_(DataSize) PBYTE Data,
991  _In_ DWORD DataSize,
992  _In_ DWORD Flags
993  )
1013 {
1014  INTSTATUS status;
1015  PWIN_PROCESS_MODULE pMod;
1016  PWIN_PROCESS_SUBSYSTEM pSubs;
1017  PWIN_PROCESS_OBJECT pProc;
1018 
1020  UNREFERENCED_PARAMETER(VirtualAddress);
1021  UNREFERENCED_PARAMETER(DataSize);
1022  UNREFERENCED_PARAMETER(PhysicalAddress);
1023  UNREFERENCED_PARAMETER(Flags);
1024 
1025  if (NULL == Context)
1026  {
1028  }
1029 
1030  if (NULL == Data)
1031  {
1033  }
1034 
1035  pMod = (PWIN_PROCESS_MODULE)Context;
1036  pMod->HeadersSwapHandle = NULL;
1037 
1038  pSubs = pMod->Subsystem;
1039  if (NULL == pSubs)
1040  {
1042  }
1043 
1044  pProc = pSubs->Process;
1045  if (NULL == pProc)
1046  {
1048  }
1049 
1050  status = IntWinUmModCacheSetHeaders(pMod, Data);
1051 
1052  if (INT_SUCCESS(status) && pProc->Protected && pMod->ShouldProtHooks)
1053  {
1054  TRACE("[MODULE] Protecting module with base 0x%016llx -> 0x%016llx against hooking.\n", VirtualAddress, Cr3);
1055 
1056  status = IntWinModHookModule(pMod);
1057  if (!INT_SUCCESS(status))
1058  {
1059  ERROR("[ERROR] IntWinModHookModule failed: 0x%08x\n", status);
1060  }
1061  }
1062 
1063  return INT_STATUS_SUCCESS;
1064 }
1065 
1066 
1067 static INTSTATUS
1069  _In_ WIN_PROCESS_MODULE *Module,
1070  _In_ WINUM_PATH *Path
1071  )
1088 {
1089  PWIN_PROCESS_SUBSYSTEM pSubs;
1090  PWIN_PROCESS_OBJECT pProc;
1091  INTSTATUS status;
1092 
1093  pSubs = Module->Subsystem;
1094  if (NULL == pSubs)
1095  {
1097  }
1098 
1099  pProc = pSubs->Process;
1100  if (NULL == pProc)
1101  {
1103  }
1104 
1105  Module->Path = IntWinUmPathReference(Path);
1106 
1107  if (gGuest.Guest64 && (Module->Subsystem->SubsystemType == winSubsys32Bit))
1108  {
1109  // OK, we don't compare the entire length, we just want to see if the first part of the path matches.
1110  if (wstrncasecmp(Module->Path->Path, u"\\windows\\syswow64\\", CWSTRLEN(u"\\windows\\syswow64\\")) == 0)
1111  {
1112  Module->IsSystemModule = TRUE;
1113  }
1114  }
1115  else
1116  {
1117  // OK, we don't compare the entire length, we just want to see if the first part of the path matches.
1118  if (wstrncasecmp(Module->Path->Path, u"\\windows\\system32\\", CWSTRLEN(u"\\windows\\system32\\")) == 0)
1119  {
1120  Module->IsSystemModule = TRUE;
1121  }
1122  }
1123 
1124  pSubs->LoadedModulesCount++;
1125 
1126  TRACE("[MODULE] Module '%s' (%08x) just loaded at 0x%016llx in process '%s' (pid = %d)\n",
1127  utf16_for_log(Module->Path->Path), Module->Path->NameHash, Module->VirtualBase, pProc->Name, pProc->Pid);
1128 
1130 
1131  if (Module->VirtualBase == pProc->MainModuleAddress)
1132  {
1133  Module->IsMainModule = TRUE;
1134 
1135  pSubs->MainModuleLoaded = TRUE;
1136 
1137  if (!pProc->MainModuleLoaded)
1138  {
1139  pProc->MainModuleLoaded = TRUE;
1140 
1141  pProc->Path = IntWinUmPathReference(Module->Path);
1142  }
1143  }
1144 
1145  if (Module->IsMainModule && !pProc->SystemProcess)
1146  {
1147  if (NULL == IntWinProcGetProtectedInfoEx(Module->Path->Path, !!pProc->SystemProcess))
1148  {
1149  TRACE("[INFO] Application '%s' was not found among the protected ones, will remove protection.\n",
1150  utf16_for_log(Module->Path->Path));
1151 
1152  status = IntWinProcUnprotect(pProc);
1153  if (!INT_SUCCESS(status))
1154  {
1155  ERROR("[ERROR] IntWinProcUnprotect failed: 0x%08x\n", status);
1156  }
1157 
1158  return status;
1159  }
1160  }
1161 
1162  if (Module->IsSystemModule)
1163  {
1164  if ((Module->Path->NameHash == NAMEHASH_NTDLL) &&
1165  (0 == wstrcasecmp(Module->Path->Name, u"ntdll.dll")))
1166  {
1167  Module->Subsystem->NtdllBase = Module->VirtualBase;
1168  Module->Subsystem->NtdllSize = Module->Size;
1169 
1170  Module->Subsystem->NtdllLoadCount++;
1171  }
1172  else if ((Module->Path->NameHash == NAMEHASH_KERNEL32) &&
1173  (0 == wstrcasecmp(Module->Path->Name, u"kernel32.dll")))
1174  {
1175  Module->Subsystem->Kernel32LoadCount++;
1176  }
1177 
1178  // For 32-bit processes on 64-bit guests we also need to check the WoW64 modules
1179  if ((winSubsys64Bit == pSubs->SubsystemType) && (pProc->Wow64Process))
1180  {
1181  if (IntWinModIsProtected(Module, gProtectedWowModules, ARRAYSIZE(gProtectedWowModules)))
1182  {
1183  Module->ShouldProtHooks = pSubs->Process->ProtCoreModules;
1184  Module->ShouldGetCache = TRUE;
1185  }
1186  }
1187  else
1188  {
1189  if (IntWinModIsProtected(Module, gProtectedModules, ARRAYSIZE(gProtectedModules)))
1190  {
1191  Module->ShouldProtHooks = pSubs->Process->ProtCoreModules;
1192  Module->ShouldGetCache = TRUE;
1193  }
1194  else if (IntWinModIsProtected(Module, gProtectedNetModules, ARRAYSIZE(gProtectedNetModules)))
1195  {
1196  Module->ShouldProtHooks = pSubs->Process->ProtWsockModules;
1197  Module->ShouldGetCache = TRUE;
1198  }
1199  }
1200  }
1201 
1202  if (pSubs->Process->ProtUnpack && Module->IsMainModule)
1203  {
1204  Module->ShouldProtUnpack = TRUE;
1205  }
1206 
1207  if (Module->ShouldGetCache)
1208  {
1209  IntWinUmModCacheGet(Module);
1210 
1211  if (NULL == Module->Cache)
1212  {
1213  ERROR("[ERROR] Module->Cache is NULL after IntWinUmModCacheGet!\n");
1214  }
1215  else
1216  {
1217  status = IntSwapMemReadData(pSubs->Process->Cr3,
1218  Module->VirtualBase,
1219  PAGE_SIZE,
1221  Module,
1222  0,
1225  &Module->HeadersSwapHandle);
1226  if (!INT_SUCCESS(status))
1227  {
1228  ERROR("[ERROR] IntSwapMemReadData failed: 0x%08x\n", status);
1229  return status;
1230  }
1231  }
1232  }
1233 
1234  if (Module->ShouldProtUnpack)
1235  {
1236  status = IntSwapMemReadData(pSubs->Process->Cr3,
1237  Module->VirtualBase,
1238  2,
1240  Module,
1241  0,
1244  &Module->HeadersSwapHandle);
1245  if (!INT_SUCCESS(status))
1246  {
1247  ERROR("[ERROR] IntSwapMemReadData failed: 0x%08x\n", status);
1248  return status;
1249  }
1250  }
1251 
1252  // Finally check if the current module might be loaded through double agent
1254 
1255  return INT_STATUS_SUCCESS;
1256 }
1257 
1258 
1259 INTSTATUS
1261  _In_ WIN_PROCESS_OBJECT *Process,
1262  _In_ const VAD *Vad
1263  )
1276 {
1277  INTSTATUS status;
1278  WIN_PROCESS_MODULE *pMod;
1279 
1280  if (Vad->PageCount * PAGE_SIZE > 0xFFFFFFFF)
1281  {
1282  ERROR("[ERROR] Module greater than 4GB!\n");
1283 
1285  }
1286 
1287  pMod = HpAllocWithTag(sizeof(*pMod), IC_TAG_MODU);
1288  if (NULL == pMod)
1289  {
1291  }
1292 
1293  pMod->VirtualBase = Vad->StartPage;
1294  pMod->Size = (DWORD)(Vad->PageCount * PAGE_SIZE);
1295  pMod->StaticScan = Vad->StaticScan;
1296  pMod->Vad = Vad;
1297 
1298  if (gGuest.Guest64)
1299  {
1300  if (!Process->Wow64Process)
1301  {
1302  pMod->Subsystem = Process->Subsystemx64;
1303  pMod->Is64BitModule = TRUE;
1304  }
1305  else
1306  {
1307  // We're on 64 bit with wow64 process. We determine the subsystem using the module name. Inside the 64 bit
1308  // subsystem, the following modules will be loaded and possibly unloaded:
1309  // - /windows/system32/ntdll.dll
1310  // - /windows/system32/wow64win.dll
1311  // - /windows/system32/wow64.dll
1312  // - /windows/system32/wow64cpu.dll
1313  // - /windows/system32/kernel32.dll
1314  // - /windows/system32/user32.dll
1315  // All other modules will be 32 bit modules.
1316  // OK, we don't compare the entire length, we just want to see if the first part of the path matches.
1317  if (wstrncasecmp(Vad->Path->Path, u"\\windows\\system32\\", wstrlen(u"\\windows\\system32\\")) == 0)
1318  {
1319  pMod->Subsystem = Process->Subsystemx64;
1320  pMod->Is64BitModule = TRUE;
1321  }
1322  else
1323  {
1324  pMod->Subsystem = Process->Subsystemx86;
1325  pMod->Is64BitModule = FALSE;
1326  }
1327  }
1328  }
1329  else
1330  {
1331  pMod->Subsystem = Process->Subsystemx86;
1332  pMod->Is64BitModule = FALSE;
1333  }
1334 
1335  InsertTailList(&pMod->Subsystem->ProcessModules, &pMod->Link);
1336 
1337  status = IntWinModHandleModulePathInMemory(pMod, Vad->Path);
1338  if (!INT_SUCCESS(status))
1339  {
1340  ERROR("[ERROR] IntWinModHandleModuleNameInMemory failed: 0x%08x\n", status);
1341  return status;
1342  }
1343 
1344  if (pMod->IsMainModule && Process->Wow64Process && (pMod->Subsystem == Process->Subsystemx86))
1345  {
1346  WIN_PROCESS_MODULE *pMod64;
1347 
1348  // If this was the main module, and we're inside a Wow64 process, we have to allocate a fresh entry
1349  // for the 64 bit subsystem.
1350 
1351  pMod64 = HpAllocWithTag(sizeof(*pMod64), IC_TAG_MODU);
1352  if (NULL == pMod64)
1353  {
1355  }
1356 
1357  pMod64->Subsystem = Process->Subsystemx64;
1358  pMod64->VirtualBase = Vad->StartPage;
1359  pMod64->Size = (DWORD)(Vad->PageCount * PAGE_SIZE);
1360  pMod64->Vad = Vad;
1361 
1362  InsertTailList(&pMod64->Subsystem->ProcessModules, &pMod64->Link);
1363 
1364  status = IntWinModHandleModulePathInMemory(pMod64, Vad->Path);
1365  if (!INT_SUCCESS(status))
1366  {
1367  ERROR("[ERROR] IntWinModHandleModuleNameInMemory failed: 0x%08x\n", status);
1368  return status;
1369  }
1370  }
1371 
1372  return INT_STATUS_SUCCESS;
1373 }
1374 
1375 
1376 static INTSTATUS
1378  _In_ PWIN_PROCESS_SUBSYSTEM Subsystem,
1379  _In_ QWORD VirtualBase
1380  )
1394 {
1395  LIST_ENTRY *list;
1396 
1397  list = Subsystem->ProcessModules.Flink;
1398  while (list != &Subsystem->ProcessModules)
1399  {
1401  list = list->Flink;
1402 
1403  if (pMod->VirtualBase == VirtualBase)
1404  {
1405  if ((pMod->Path->NameHash == NAMEHASH_NTDLL) &&
1406  (0 == wstrcasecmp(pMod->Path->Name, u"ntdll.dll")))
1407  {
1408  pMod->Subsystem->NtdllLoadCount--;
1409  }
1410  else if ((pMod->Path->NameHash == NAMEHASH_KERNEL32) &&
1411  (0 == wstrcasecmp(pMod->Path->Name, u"kernel32.dll")))
1412  {
1413  pMod->Subsystem->Kernel32LoadCount--;
1414  }
1415 
1416  pMod->Subsystem->LoadedModulesCount--;
1417 
1418  // Don't spam with the unload event.
1419 
1420  RemoveEntryList(&pMod->Link);
1421 
1422  IntWinModUnHookModule(pMod);
1423 
1424  IntWinModRemoveModule(pMod);
1425 
1426  return INT_STATUS_SUCCESS;
1427  }
1428  }
1429 
1431 }
1432 
1433 
1434 INTSTATUS
1436  _In_ PWIN_PROCESS_OBJECT Process,
1437  _In_ PVAD Vad
1438  )
1451 {
1453 
1454  if (NULL != Process->Subsystemx86)
1455  {
1456  status = IntWinModHandleUnload(Process->Subsystemx86, Vad->StartPage);
1457  if (INT_STATUS_SUCCESS == status)
1458  {
1459  return status;
1460  }
1461  }
1462 
1463  if (NULL != Process->Subsystemx64)
1464  {
1465  status = IntWinModHandleUnload(Process->Subsystemx64, Vad->StartPage);
1466  if (INT_STATUS_SUCCESS == status)
1467  {
1468  return status;
1469  }
1470  }
1471 
1472  return status;
1473 }
1474 
1475 
1476 static BOOLEAN
1478  _In_ QWORD Cr3,
1479  _In_ QWORD Address,
1480  _In_ void *Context
1481  )
1494 {
1495  PWIN_PROCESS_MODULE pMod;
1496 
1498 
1499  if (NULL == Context)
1500  {
1501  return FALSE;
1502  }
1503 
1504  pMod = (PWIN_PROCESS_MODULE)Context;
1505 
1506  // No cache, bail out, assuming the write is OK.
1507  if (NULL == pMod->Cache)
1508  {
1509  return TRUE;
1510  }
1511 
1512  if ((Address - pMod->VirtualBase >= pMod->Cache->Info.IatRva) &&
1513  (Address - pMod->VirtualBase < (QWORD)pMod->Cache->Info.IatRva + pMod->Cache->Info.IatSize))
1514  {
1515  // The write is inside the IAT, we can ignore it for now.
1516  return TRUE;
1517  }
1518 
1519  return FALSE;
1520 }
1521 
1522 
1523 static INTSTATUS
1525  _In_ PWIN_PROCESS_MODULE Module
1526  )
1537 {
1538  INTSTATUS status;
1539  PBYTE pPage;
1540  IMAGE_SECTION_HEADER *sec;
1541  DWORD i;
1542  PWIN_PROCESS_OBJECT pProc;
1543  INTRO_PE_INFO peInfo = { 0 };
1544 
1545  pPage = NULL;
1546 
1547  pProc = Module->Subsystem->Process;
1548 
1549  status = IntVirtMemMap(Module->VirtualBase, PAGE_SIZE, pProc->Cr3, 0, &pPage);
1550  if (!INT_SUCCESS(status))
1551  {
1552  ERROR("[ERROR] IntVirtMemMap failed: 0x%08x\n", status);
1553  return status;
1554  }
1555 
1556  status = IntPeValidateHeader(Module->VirtualBase, pPage, PAGE_SIZE, &peInfo, 0);
1557  if (!INT_SUCCESS(status))
1558  {
1559  ERROR("[ERROR] IntPeValidateHeader failed: 0x%08x\n", status);
1560  goto cleanup_and_exit;
1561  }
1562 
1563  Module->Size = peInfo.SizeOfImage;
1564 
1565  sec = (IMAGE_SECTION_HEADER *)(pPage + peInfo.SectionOffset);
1566  for (i = 0; i < peInfo.NumberOfSections; i++, sec++)
1567  {
1568  // Skip sections larger than 4 MB.
1569  if (sec->Misc.VirtualSize > 4 * ONE_MEGABYTE)
1570  {
1571  continue;
1572  }
1573 
1574  // Check if this is a code section.
1575  if ((sec->Characteristics & IMAGE_SCN_MEM_EXECUTE) ||
1578  {
1579  TRACE("[MODULE] Protecting pageable section: 0x%016llx, VA space 0x%016llx, length %x\n",
1580  Module->VirtualBase + sec->VirtualAddress, pProc->Cr3, sec->Misc.VirtualSize);
1581 
1582  for (DWORD j = 0; j < sec->Misc.VirtualSize; j += 0x1000)
1583  {
1584  status = IntUnpWatchPage(pProc->Cr3,
1585  Module->VirtualBase + sec->VirtualAddress + j,
1588  Module);
1589  if (!INT_SUCCESS(status))
1590  {
1591  ERROR("[ERROR] IntUnpWatchPage failed: 0x%08x\n", status);
1592  break;
1593  }
1594  }
1595  }
1596  }
1597 
1598 cleanup_and_exit:
1599  // The module may be partially protected against unpacking. This is not an issue, as the hooks will all be removed
1600  // when the process terminates (the unpacker works on a per/page basis). This only happens in case of errors.
1601  if (NULL != pPage)
1602  {
1603  IntVirtMemUnmap(&pPage);
1604  }
1605 
1606  return status;
1607 }
1608 
1609 
1610 INTSTATUS
1612  _In_ QWORD Cr3,
1613  _In_ QWORD VirtualAddress,
1614  _In_ PINSTRUX Instrux,
1615  _In_ void *Context
1616  )
1631 {
1632  INTSTATUS status;
1633  char text[ND_MIN_BUF_SIZE];
1634  PWIN_PROCESS_MODULE pMod;
1635 
1636  if (NULL == Instrux)
1637  {
1639  }
1640 
1641  if (NULL == Context)
1642  {
1644  }
1645 
1646  pMod = (PWIN_PROCESS_MODULE)Context;
1647 
1648  if (pMod->UnpackAlertSent)
1649  {
1650  return INT_STATUS_SUCCESS;
1651  }
1652 
1653  status = NdToText(Instrux, VirtualAddress, ND_MIN_BUF_SIZE, text);
1654  if (!INT_SUCCESS(status))
1655  {
1656  strlcpy(text, "INVALID", sizeof(text));
1657  }
1658 
1659  LOG("[ALERT] [UNPACK DETECTED] Unpacked/decrypted page detected @ 0x%016llx:0x%016llx: %s\n", VirtualAddress, Cr3,
1660  text);
1661 
1662  pMod->UnpackAlertSent = TRUE;
1663 
1664  // Send the unpacker notification
1665  if (TRUE)
1666  {
1667  PEVENT_EPT_VIOLATION pEptViol = &gAlert.Ept;
1668 
1669  memzero(pEptViol, sizeof(*pEptViol));
1670 
1671  pEptViol->Header.Action = introGuestAllowed;
1672  pEptViol->HookStartPhysical = 0;
1673  pEptViol->HookStartVirtual = VirtualAddress & PAGE_MASK;
1674  pEptViol->Offset = VirtualAddress & PAGE_OFFSET;
1675  pEptViol->Victim.Type = (Cr3 != 0) ? introObjectTypeUmUnpack : introObjectTypeKmUnpack;
1676  pEptViol->Violation = IG_EPT_HOOK_EXECUTE;
1677  pEptViol->VirtualPage = VirtualAddress & PAGE_MASK;
1678 
1679  pEptViol->Header.CpuContext.Cpu = gVcpu->Index;
1680  pEptViol->Header.CpuContext.Rip = VirtualAddress;
1681  pEptViol->Header.CpuContext.Cr3 = Cr3;
1682  memcpy(pEptViol->Header.CpuContext.Instruction, text, sizeof(pEptViol->Header.CpuContext.Instruction));
1683 
1684  pEptViol->ExecInfo.Length = Instrux->Length;
1685 
1687 
1688  pEptViol->Header.MitreID = idSoftwarePacking;
1689 
1691  pMod->Subsystem->Process, introReasonUnknown, 0);
1692 
1693  if (pMod->Subsystem->Process->SystemProcess)
1694  {
1695  pEptViol->Header.Flags |= ALERT_FLAG_SYSPROC;
1696  }
1697 
1698  IntAlertFillWinUmModule(pMod, &pEptViol->Victim.Module);
1699 
1700  IntAlertFillVersionInfo(&pEptViol->Header);
1701 
1702  status = IntNotifyIntroEvent(introEventEptViolation, pEptViol, sizeof(*pEptViol));
1703  if (!INT_SUCCESS(status))
1704  {
1705  WARNING("[WARNING] IntNotifyIntroEvent failed: 0x%08x\n", status);
1706  }
1707  }
1708 
1709  return INT_STATUS_SUCCESS;
1710 }
1711 
1712 
1713 INTSTATUS
1715  _In_ PWIN_PROCESS_MODULE Module
1716  )
1734 {
1735  INTSTATUS status;
1736 
1737  if (NULL == Module)
1738  {
1740  }
1741 
1742  // Remove any pending swap operation.
1743  if (NULL != Module->HeadersSwapHandle)
1744  {
1745  status = IntSwapMemRemoveTransaction(Module->HeadersSwapHandle);
1746  if (!INT_SUCCESS(status))
1747  {
1748  ERROR("[ERROR] IntSwapMemRemoveTransaction failed: 0x%08x\n", status);
1749  }
1750 
1751  Module->HeadersSwapHandle = NULL;
1752  }
1753 
1754  if (NULL != Module->ExportsSwapHandle)
1755  {
1756  status = IntSwapMemRemoveTransaction(Module->ExportsSwapHandle);
1757  if (!INT_SUCCESS(status))
1758  {
1759  ERROR("[ERROR] IntSwapMemRemoveTransaction failed: 0x%08x\n", status);
1760  }
1761 
1762  Module->ExportsSwapHandle = NULL;
1763  }
1764 
1765  if (NULL != Module->SlackSpaceSwapHandle)
1766  {
1767  status = IntSwapMemRemoveTransaction(Module->SlackSpaceSwapHandle);
1768  if (!INT_SUCCESS(status))
1769  {
1770  ERROR("[ERROR] IntSwapMemRemoveTransaction failed: 0x%08x\n", status);
1771  }
1772 
1773  Module->SlackSpaceSwapHandle = NULL;
1774  }
1775 
1776  if (NULL != Module->MainModHeadersSwapHandle)
1777  {
1778  status = IntSwapMemRemoveTransaction(Module->MainModHeadersSwapHandle);
1779  if (!INT_SUCCESS(status))
1780  {
1781  ERROR("[ERROR] IntSwapMemRemoveTransaction failed: 0x%08x\n", status);
1782  }
1783 
1784  Module->MainModHeadersSwapHandle = NULL;
1785  }
1786 
1787  IntWinUmModCacheRelease(Module->Cache);
1788 
1789  if (Module->IsMainModule)
1790  {
1791  IntWinUmPathDereference(&Module->Subsystem->Process->Path);
1792  Module->Subsystem->Process->MainModuleLoaded = FALSE;
1793  }
1794 
1795  IntWinUmPathDereference(&Module->Path);
1796 
1797  if (NULL != Module->IATBitmap)
1798  {
1799  HpFreeAndNullWithTag(&Module->IATBitmap, IC_TAG_IATB);
1800  }
1801 
1803 
1804  return INT_STATUS_SUCCESS;
1805 }
1806 
1807 
1808 void
1810  _In_ PWIN_PROCESS_SUBSYSTEM Subsystem
1811  )
1820 {
1821  PLIST_ENTRY pList;
1822 
1823  // we already have the list of modules, simply iterate it and change protection
1824  pList = Subsystem->ProcessModules.Flink;
1825  while (pList != &Subsystem->ProcessModules)
1826  {
1828 
1829  pList = pList->Flink;
1830 
1831  if (!pMod->IsSystemModule)
1832  {
1833  continue;
1834  }
1835 
1836  // If this is a 32-bit process on a 64-bit guest, we need to check if we have to update protection
1837  // for WoW64 modules
1838  if ((winSubsys64Bit == Subsystem->SubsystemType) && (Subsystem->Process->Wow64Process))
1839  {
1840  if (IntWinModIsProtected(pMod, gProtectedWowModules, ARRAYSIZE(gProtectedWowModules)))
1841  {
1842  if (pMod->ShouldProtHooks && !Subsystem->Process->ProtCoreModules)
1843  {
1844  TRACE("[WINMODULE] PROC_PROT_MASK_CORE_HOOKS enabled -> disabled for %s (Process %d)\n",
1845  utf16_for_log(pMod->Path->Path), Subsystem->Process->Pid);
1846  pMod->ShouldProtHooks = FALSE;
1847  }
1848  else if (!pMod->ShouldProtHooks && Subsystem->Process->ProtCoreModules)
1849  {
1850  TRACE("[WINMODULE] PROC_PROT_MASK_CORE_HOOKS disabled -> enabled for %s (Process %d)\n",
1851  utf16_for_log(pMod->Path->Path), Subsystem->Process->Pid);
1852  pMod->ShouldProtHooks = TRUE;
1853  }
1854  else
1855  {
1856  TRACE("[WINMODULE] PROC_PROT_MASK_CORE_HOOKS did not changed for %s (Process %d)\n",
1857  utf16_for_log(pMod->Path->Path), Subsystem->Process->Pid);
1858  }
1859  }
1860  }
1861  else
1862  {
1863  if (IntWinModIsProtected(pMod, gProtectedModules, ARRAYSIZE(gProtectedModules)))
1864  {
1865  if (pMod->ShouldProtHooks && !Subsystem->Process->ProtCoreModules)
1866  {
1867  TRACE("[WINMODULE] PROC_PROT_MASK_CORE_HOOKS enabled -> disabled for %s (Process %d)\n",
1868  utf16_for_log(pMod->Path->Path), Subsystem->Process->Pid);
1869  pMod->ShouldProtHooks = FALSE;
1870  }
1871  else if (!pMod->ShouldProtHooks && Subsystem->Process->ProtCoreModules)
1872  {
1873  TRACE("[WINMODULE] PROC_PROT_MASK_CORE_HOOKS disabled -> enabled for %s (Process %d)\n",
1874  utf16_for_log(pMod->Path->Path), Subsystem->Process->Pid);
1875  pMod->ShouldProtHooks = TRUE;
1876  }
1877  else
1878  {
1879  TRACE("[WINMODULE] PROC_PROT_MASK_CORE_HOOKS did not changed for %s (Process %d)\n",
1880  utf16_for_log(pMod->Path->Path), Subsystem->Process->Pid);
1881  }
1882  break;
1883  }
1884 
1885  if (IntWinModIsProtected(pMod, gProtectedNetModules, ARRAYSIZE(gProtectedNetModules)))
1886  {
1887  if (pMod->ShouldProtHooks && !Subsystem->Process->ProtWsockModules)
1888  {
1889  TRACE("[WINMODULE] PROC_PROT_MASK_WSOCK_HOOKS enabled -> disabled for %s (Process %d)\n",
1890  utf16_for_log(pMod->Path->Path), Subsystem->Process->Pid);
1891  pMod->ShouldProtHooks = FALSE;
1892  }
1893  else if (!pMod->ShouldProtHooks && Subsystem->Process->ProtWsockModules)
1894  {
1895  TRACE("[WINMODULE] PROC_PROT_MASK_WSOCK_HOOKS disabled -> enabled for %s (Process %d)\n",
1896  utf16_for_log(pMod->Path->Path), Subsystem->Process->Pid);
1897  pMod->ShouldProtHooks = TRUE;
1898  }
1899  else
1900  {
1901  TRACE("[WINMODULE] PROC_PROT_MASK_WSOCK_HOOKS did not changed for %s (Process %d)\n",
1902  utf16_for_log(pMod->Path->Path), Subsystem->Process->Pid);
1903  }
1904  break;
1905  }
1906  }
1907 
1908  // if this is the main module, check if unpack protection changed
1909  if (pMod->IsMainModule)
1910  {
1911  if (pMod->ShouldProtUnpack && !Subsystem->Process->ProtUnpack)
1912  {
1913  INTSTATUS status;
1914 
1915  TRACE("[WINMODULE] PROC_PROT_MASK_UNPACK enabled -> disabled for %s (Process %d). "
1916  "Unwatching VA space 0x%016llx...\n", utf16_for_log(pMod->Path->Path),
1917  Subsystem->Process->Pid, Subsystem->Process->Cr3);
1918 
1919  status = IntUnpUnWatchVaSpacePages(Subsystem->Process->Cr3);
1920  if (!INT_SUCCESS(status) && (INT_STATUS_NOT_FOUND != status))
1921  {
1922  ERROR("[ERROR] IntUnpUnWatchVaSpacePages failed: 0x%x\n", status);
1923  }
1924 
1925  pMod->ShouldProtUnpack = FALSE;
1926  }
1927  else if (!pMod->ShouldProtUnpack && Subsystem->Process->ProtUnpack)
1928  {
1929  INTSTATUS status;
1930 
1931  TRACE("[WINMODULE] PROC_PROT_MASK_UNPACK disabled -> enabled for %s (Process %d)\n",
1932  utf16_for_log(pMod->Path->Path), Subsystem->Process->Pid);
1933 
1934  status = IntWinModHookPoly(pMod);
1935  if (!INT_SUCCESS(status))
1936  {
1937  ERROR("[ERROR] IntWinModHookPoly failed: 0x%x\n", status);
1938  }
1939 
1940  pMod->ShouldProtUnpack = TRUE;
1941  }
1942  else
1943  {
1944  TRACE("[WINMODULE] PROC_PROT_MASK_UNPACK did not changed for %s (Process %d)\n",
1945  utf16_for_log(pMod->Path->Path), Subsystem->Process->Pid);
1946  }
1947  }
1948  // if this is not the main module, check it is hooked and should be unhooked (or the other way)
1949  else if ((pMod->ShouldProtHooks) && (!pMod->IsProtected))
1950  {
1951  INTSTATUS status;
1952 
1953  TRACE("[WINMODULE] Protecting module with base 0x%016llx -> 0x%016llx against hooking.\n",
1954  pMod->VirtualBase, Subsystem->Process->Cr3);
1955 
1956  status = IntWinModHookModule(pMod);
1957  if (!INT_SUCCESS(status))
1958  {
1959  ERROR("[ERROR] IntWinModHookModule failed for %s (Process %d): 0x%x\n",
1960  utf16_for_log(pMod->Path->Path), Subsystem->Process->Pid, status);
1961  }
1962  }
1963  else if ((!pMod->ShouldProtHooks) && (pMod->IsProtected))
1964  {
1965  TRACE("[WINMODULE] Removing protection for module with base 0x%016llx -> 0x%016llx\n",
1966  pMod->VirtualBase, Subsystem->Process->Cr3);
1967 
1968  IntWinModUnHookModule(pMod);
1969  }
1970  }
1971 }
1972 
1973 
1976  _In_ PWIN_PROCESS_OBJECT Process,
1977  _In_ QWORD Gva
1978  )
1989 {
1990  LIST_ENTRY *list;
1991 
1992  if (NULL != Process->Subsystemx64)
1993  {
1994  list = Process->Subsystemx64->ProcessModules.Flink;
1995  while (list != &Process->Subsystemx64->ProcessModules)
1996  {
1998  list = list->Flink;
1999 
2000  if (IN_RANGE_LEN(Gva, pMod->VirtualBase, pMod->Size))
2001  {
2002  return pMod;
2003  }
2004  }
2005  }
2006 
2007  if (NULL != Process->Subsystemx86)
2008  {
2009  list = Process->Subsystemx86->ProcessModules.Flink;
2010  while (list != &Process->Subsystemx86->ProcessModules)
2011  {
2013  list = list->Flink;
2014 
2015  if (IN_RANGE_LEN(Gva, pMod->VirtualBase, pMod->Size))
2016  {
2017  return pMod;
2018  }
2019  }
2020  }
2021 
2022  return NULL;
2023 }
WINUM_PATH * Path
Module path.
Definition: winummodule.h:62
#define IMAGE_SCN_MEM_EXECUTE
Definition: winpe.h:472
int wstrncasecmp(const WCHAR *buf1, const WCHAR *buf2, size_t len)
Definition: introcrt.c:146
DWORD Is64BitModule
TRUE if the module is 64 bit.
Definition: winummodule.h:45
#define _In_opt_
Definition: intro_sal.h:16
struct _EXCEPTION_KM_ORIGINATOR::@63 Original
PBYTE IATBitmap
A bitmap indicating which IAT entries have been initialized.
Definition: winummodule.h:66
enum _INTRO_ACTION_REASON INTRO_ACTION_REASON
The reason for which an INTRO_ACTION was taken.
INTRO_CODEBLOCKS CodeBlocks
Code blocks extracted for the alert.
Definition: intro_types.h:1145
#define _Out_
Definition: intro_sal.h:22
_Bool BOOLEAN
Definition: intro_types.h:58
#define CONTAINING_RECORD(List, Type, Member)
Definition: introlists.h:36
#define ROUND_UP(what, to)
Definition: introdefs.h:158
DWORD NtdllSize
The size of ntdll.dll.
Definition: winprocess.h:75
static INTSTATUS IntWinModHookModule(PWIN_PROCESS_MODULE Module)
Hook a user-mode module against attacks.
Definition: winummodule.c:752
INTSTATUS IntVirtMemUnmap(void **HostPtr)
Unmaps a memory range previously mapped with IntVirtMemMap.
Definition: introcore.c:2234
An internal error occurred (no memory, pages not present, etc.).
Definition: intro_types.h:195
INTSTATUS IntHookObjectDestroy(HOOK_OBJECT_DESCRIPTOR **Object, DWORD Flags)
Destroy an entire hook object. All regions belonging to this object will be removed.
Definition: hook_object.c:357
BYTE Violation
The type of the access. It must be one of the IG_EPT_HOOK_TYPE values.
Definition: intro_types.h:1147
#define NAMEHASH_KERNELBASE
Definition: winummodule.h:13
IG_ARCH_REGS Regs
The current state of the guest registers.
Definition: guests.h:95
DWORD IatSize
Size of the imports table.
Definition: winumcache.h:88
DWORD Index
The VCPU number.
Definition: guests.h:172
#define _In_
Definition: intro_sal.h:21
MITRE_ID MitreID
The Mitre ID that corresponds to this attack.
Definition: intro_types.h:1088
#define NAMEHASH_WOW64CPU
Definition: winummodule.h:18
#define INT_STATUS_SUCCESS
Definition: introstatus.h:54
const VAD * Vad
The VAD which describes this module.
Definition: winummodule.h:88
Measures user mode exceptions checks.
Definition: stats.h:50
DWORD ShouldProtHooks
TRUE if the module should be protected against hooks.
Definition: winummodule.h:42
#define IMAGE_SCN_MEM_READ
Definition: winpe.h:473
static INTSTATUS IntWinModHandleModulePathInMemory(WIN_PROCESS_MODULE *Module, WINUM_PATH *Path)
Handles a module path in memory.
Definition: winummodule.c:1068
#define STATS_EXIT(id)
Definition: stats.h:148
#define MODULE_MATCH(m, p)
Definition: winummodule.h:103
void IntAlertFillWinProcess(const WIN_PROCESS_OBJECT *Process, INTRO_PROCESS *EventProcess)
Saves information about a windows process inside an alert.
Definition: alerts.c:689
DWORD ProtCoreModules
Protect the core module loaded by the process.
Definition: winprocess.h:201
void IntWinUmModCacheRelease(WINUM_MODULE_CACHE *Cache)
Removes a module cache, if it was written (it&#39;s dirty).
Definition: winumcache.c:1000
User-mode exception.
Definition: exceptions.h:61
INTSTATUS IntSwapMemReadData(QWORD Cr3, QWORD VirtualAddress, DWORD Length, DWORD Options, void *Context, DWORD ContextTag, PFUNC_PagesReadCallback Callback, PFUNC_PreInjectCallback PreInject, void **SwapHandle)
Reads a region of guest virtual memory, and calls the indicated callback when all the data is availab...
Definition: swapmem.c:417
struct _LIST_ENTRY * Flink
Definition: introlists.h:20
INTSTATUS IntWinProcUnprotect(WIN_PROCESS_OBJECT *Process)
Remove a process from protection.
Definition: winprocess.c:3071
static INTSTATUS IntWinModHandleMainModuleInMemory(void *Context, QWORD Cr3, QWORD ModuleBase, QWORD PhysicalAddress, PBYTE Data, DWORD DataSize, DWORD Flags)
Callback called when the main module headers are present in physical memory.
Definition: winummodule.c:249
#define IC_TAG_MODU
Loaded module.
Definition: memtags.h:15
QWORD HookStartPhysical
The start of the monitored guest physical memory area for which this alert was generated.
Definition: intro_types.h:1152
struct _WINUM_MODULE_CACHE::@236 Info
#define IMAGE_SCN_MEM_WRITE
Definition: winpe.h:474
static int IntWinModComparePaths(const WIN_PROCESS_MODULE *Module, const WCHAR *SystemDirPath, const WCHAR *TestModule)
Tests whether the Module&#39;s path is the same as the TestModules&#39; path inside the provided SystemDirPat...
Definition: winummodule.c:341
#define INT_SUCCESS(Status)
Definition: introstatus.h:42
Event structure for module loading and unloading.
Definition: intro_types.h:1782
void IntWinModulesChangeProtectionFlags(PWIN_PROCESS_SUBSYSTEM Subsystem)
Change the protection flags applied to the process modules that are currently loaded.
Definition: winummodule.c:1809
struct _EVENT_EPT_VIOLATION::@277 Victim
QWORD Flags
A combination of ALERT_FLAG_* values describing the alert.
Definition: intro_types.h:1087
#define PROC_OPT_PROT_WSOCK_HOOKS
Blocks hooks being set on Wininet user-mode DLLs (Windows only).
Definition: intro_types.h:339
QWORD SectionOffset
Offset of the first section header.
Definition: winpe.h:602
#define PAGE_OFFSET
Definition: pgtable.h:32
The action was not allowed because there was no reason to allow it.
Definition: intro_types.h:183
#define ARRAYSIZE(A)
Definition: introdefs.h:101
CHAR Instruction[ALERT_MAX_INSTRUX_LEN]
The instruction found at RIP, in textual form.
Definition: intro_types.h:885
BOOLEAN FirstDominoJavaIgnored
TRUE if the first Domino Java execution VAD was ignored.
Definition: winprocess.h:191
EVENT_MODULE_EVENT Module
Definition: alerts.h:26
QWORD IntHookGetGlaFromGpaHook(HOOK_GPA const *Hook, QWORD Address)
Gets the GLA from a GPA hook.
Definition: hook.c:279
INTSTATUS IntWinModHandleWrite(void *Context, void *Hook, QWORD Address, INTRO_ACTION *Action)
Handle writes inside a protected user-mode module wrapper. Will dispatch appropriately to either the ...
Definition: winummodule.c:709
Windows process subsystem.
Definition: winprocess.h:52
DWORD UnpackProtected
TRUE if the main module has been protected against unpacks.
Definition: winprocess.h:131
Writes done from kernel mode over user mode.
Definition: stats.h:96
#define INT_STATUS_NOT_NEEDED_HINT
Definition: introstatus.h:317
#define ERROR(fmt,...)
Definition: glue.h:62
#define ONE_MEGABYTE
Definition: introdefs.h:90
Describes a user-mode originator.
Definition: exceptions.h:933
#define MAX_IAT_ENTRIES
#define HpAllocWithTag(Len, Tag)
Definition: glue.h:516
#define NAMEHASH_WININET
Definition: winummodule.h:21
int INTSTATUS
The status data type.
Definition: introstatus.h:24
INTSTATUS IntWinModPolyHandler(QWORD Cr3, QWORD VirtualAddress, PINSTRUX Instrux, void *Context)
Handle an unpack event for the indicated address.
Definition: winummodule.c:1611
void IntWinUmPathDereference(WINUM_PATH **Path)
Dereferences a WINUM_PATH object, releasing the resources if the reference count has reached 0...
Definition: winumpath.c:340
INTSTATUS IntWinModHandleLoadFromVad(WIN_PROCESS_OBJECT *Process, const VAD *Vad)
Handle a module load from a VAD.
Definition: winummodule.c:1260
#define INT_STATUS_NOT_FOUND
Definition: introstatus.h:284
static INTSTATUS IntWinModHookPoly(PWIN_PROCESS_MODULE Module)
Hooks the given module against unpacks.
Definition: winummodule.c:1524
DWORD IsProtected
TRUE if the module is actually hooked.
Definition: winummodule.h:46
#define MAX_PATH
The maximum size of a path (260 characters on windows).
Definition: winpe.h:579
void IntExceptKernelUserLogInformation(EXCEPTION_VICTIM_ZONE *Victim, EXCEPTION_KM_ORIGINATOR *Originator, INTRO_ACTION Action, INTRO_ACTION_REASON Reason)
Print the information about a kernel-user mode violation and dumps the code-blocks.
QWORD Rip
The value of the guest RIP register when the event was generated.
Definition: intro_types.h:882
struct _WIN_PROCESS_MODULE * PWIN_PROCESS_MODULE
INTSTATUS IntWinModRemoveModule(PWIN_PROCESS_MODULE Module)
Removes a Windows module.
Definition: winummodule.c:1714
Describes a kernel-mode originator.
Definition: exceptions.h:897
static INTSTATUS IntWinModHandleUserWrite(void *Context, void *Hook, QWORD Address, INTRO_ACTION *Action)
Handle user-mode writes inside a protected user-mode module.
Definition: winummodule.c:534
BOOLEAN UserMode
True if this is a user mode module, False if it is a kernel mode module.
Definition: intro_types.h:1789
void IntAlertFillCpuContext(BOOLEAN CopyInstruction, INTRO_CPUCTX *CpuContext)
Fills the current CPU context for an alert.
Definition: alerts.c:492
INSTRUX Instruction
The current instruction, pointed by the guest RIP.
Definition: guests.h:88
QWORD VirtualBase
Guest virtual address of the loaded module.
Definition: winummodule.h:34
QWORD VadGva
The guest virtual address at which the corresponding Windows _MMVAD structure is located.
Definition: winvad.h:108
#define MIN(a, b)
Definition: introdefs.h:146
QWORD MainModuleAddress
The address of the main module.
Definition: winprocess.h:104
BOOLEAN IsDominoJava
True if this is a Java IBM process and j9jit.dll is loaded.
Definition: winprocess.h:190
QWORD HookStartVirtual
The start of the monitored guest virtual memory area for which this alert was generated.
Definition: intro_types.h:1150
EVENT_EPT_VIOLATION Ept
Definition: alerts.h:16
INTSTATUS IntWinModUnHookModule(PWIN_PROCESS_MODULE Module)
Remove the protection from the indicated module.
Definition: winummodule.c:878
Process subsystem type 32 bit.
Definition: winprocess.h:33
DWORD Protected
TRUE if this is a protected process. If this is FALSE, most of the above fields aren&#39;t used at all...
Definition: winprocess.h:128
#define LOG(fmt,...)
Definition: glue.h:61
#define ALERT_FLAG_KM_UM
If set, the alert was generated by a kernel to user mode violation.
Definition: intro_types.h:649
void IntAlertFillVersionInfo(INTRO_VIOLATION_HEADER *Header)
Fills version information for an alert.
Definition: alerts.c:327
DWORD Wow64Process
TRUE if this is a 32 bit process on a 64 bit OS.
Definition: winprocess.h:123
DWORD AccessSize
The size of the memory access. Valid only for EPT exits.
Definition: guests.h:103
QWORD IntAlertProcGetFlags(QWORD ProtectionFlag, const void *Process, INTRO_ACTION_REASON Reason, QWORD AdditionalFlags)
Returns the flags for an alert.
Definition: alerts.c:425
INTRO_VIOLATION_HEADER Header
The alert header.
Definition: intro_types.h:1106
const PROTECTED_PROCESS_INFO * IntWinProcGetProtectedInfoEx(PWCHAR Path, BOOLEAN IsSystem)
Returns a pointer to the PROTECTED_PROCESS_INFO structure for the given process Path.
Definition: winprocess.c:1063
INTRO_ACTION_REASON Reason
The reason for which Action was taken.
Definition: intro_types.h:1084
INTSTATUS IntAlertFillCodeBlocks(QWORD Rip, QWORD Cr3, BOOLEAN Execute, INTRO_CODEBLOCKS *CodeBlocks)
Fills the code blocks pattern for an alert.
Definition: alerts.c:71
#define NAMEHASH_NTDLL
Definition: winummodule.h:11
QWORD NtdllBase
The base address for ntdll.dll.
Definition: winprocess.h:74
#define INFO(fmt,...)
Definition: glue.h:59
QWORD Cr3
Process PDBR. Includes PCID.
Definition: winprocess.h:96
DWORD MainModuleLoaded
TRUE if the main module has been loaded.
Definition: winprocess.h:130
BOOLEAN MainModuleLoaded
TRUE if the MainModule was loaded.
Definition: winprocess.h:70
Software Packing.
Definition: intro_types.h:1034
void IntAlertEptFillFromKmOriginator(const EXCEPTION_KM_ORIGINATOR *Originator, EVENT_EPT_VIOLATION *EptViolation)
Fills kernel mode originator information inside an EPT alert.
Definition: alerts.c:832
GENERIC_ALERT gAlert
Global alert buffer.
Definition: alerts.c:27
static INTSTATUS IntWinModHandleUnload(PWIN_PROCESS_SUBSYSTEM Subsystem, QWORD VirtualBase)
Handle a module unload from the given subsystem.
Definition: winummodule.c:1377
User-mode unpacker.
Definition: intro_types.h:241
INTSTATUS IntSwapMemRemoveTransaction(void *Transaction)
Remove a transaction.
Definition: swapmem.c:942
WINUM_PATH * Path
Will point inside the loaded modules list to the full process path.
Definition: winprocess.h:109
#define NAMEHASH_WS2_32
Definition: winummodule.h:20
BOOLEAN IntPolicyProcTakeAction(QWORD Flag, void const *Process, INTRO_ACTION *Action, INTRO_ACTION_REASON *Reason)
Returns the action that should be taken for a process protection option.
Definition: introcore.c:2732
void IntAlertEptFillFromVictimZone(const EXCEPTION_VICTIM_ZONE *Victim, EVENT_EPT_VIOLATION *EptViolation)
Fills the victim information inside an EPT alert.
Definition: alerts.c:868
Kernel unpacker.
Definition: intro_types.h:238
size_t wstrlen(const WCHAR *str)
Definition: introcrt.c:1080
#define STATS_ENTER(id)
Definition: stats.h:141
INTRO_CPUCTX CpuContext
The context of the CPU that triggered the alert.
Definition: intro_types.h:1085
uint8_t * PBYTE
Definition: intro_types.h:47
INTSTATUS IntWinProcSendAllDllEventsForProcess(PWIN_PROCESS_OBJECT Process)
Send DLL load events for all modules loaded in all subsystems of a process.
Definition: winummodule.c:197
static QWORD IntWinModGetProtectionOptionForModule(WIN_PROCESS_MODULE *Module)
Get the protection options for provided module.
Definition: winummodule.c:390
INTSTATUS IntNotifyIntroEvent(INTRO_EVENT_TYPE EventClass, void *Param, size_t EventSize)
Notifies the integrator about an introspection alert.
Definition: glue.c:1042
static BOOLEAN RemoveEntryList(LIST_ENTRY *Entry)
Definition: introlists.h:87
#define memzero(a, s)
Definition: introcrt.h:35
BOOLEAN Guest64
True if this is a 64-bit guest, False if it is a 32-bit guest.
Definition: guests.h:286
INTSTATUS IntExceptGetVictimEpt(void *Context, QWORD Gpa, QWORD Gva, INTRO_OBJECT_TYPE Type, DWORD ZoneFlags, EXCEPTION_VICTIM_ZONE *Victim)
Fills an EXCEPTION_VICTIM_ZONE with relevant information from an EPT violation.
Definition: exceptions.c:742
unsigned long long QWORD
Definition: intro_types.h:53
static INTSTATUS IntWinProcSendAllDllEventsForSubsystem(PWIN_PROCESS_SUBSYSTEM Subsystem)
Send a module load event for each loaded module inside a subsystem.
Definition: winummodule.c:165
CHAR Name[IMAGE_BASE_NAME_LEN]
Process base name.
Definition: winprocess.h:106
static void IntWinModCheckSpecialCases(PWIN_PROCESS_MODULE Module)
Check if the process is DominoJava process.
Definition: winummodule.c:223
QWORD Current
The currently used options.
Definition: guests.h:232
DWORD LoadedModulesCount
The number of modules that were loaded.
Definition: winprocess.h:60
static INTSTATUS IntWinModHandleModuleHeadersInMemory(void *Context, QWORD Cr3, QWORD VirtualAddress, QWORD PhysicalAddress, PBYTE Data, DWORD DataSize, DWORD Flags)
Called as soon as the module headers are swapped in memory.
Definition: winummodule.c:985
INTSTATUS IntPeListSectionsHeaders(QWORD ImageBase, BYTE *ImageBuffer, DWORD ImageBufferSize, DWORD *FirstSectionOffset, DWORD *SectionCount)
Will get the offset to the first section header and the number of sections from the given module...
Definition: winpe.c:448
union _IMAGE_SECTION_HEADER::@209 Misc
DWORD ShouldProtUnpack
TRUE if the module should be protected against unpack.
Definition: winummodule.h:43
QWORD UserCr3
Process user PDBR. Includes PCID.
Definition: winprocess.h:97
#define IN_RANGE_LEN(x, start, len)
Definition: introdefs.h:175
#define TRUE
Definition: intro_types.h:30
#define INT_STATUS_INVALID_PARAMETER_4
Definition: introstatus.h:71
BYTE NtdllLoadCount
Number of ntdll.dll loads.
Definition: winprocess.h:71
UINT32 VirtualAddress
Definition: winpe.h:85
#define IS_KERNEL_POINTER_WIN(is64, p)
Checks if a guest virtual address resides inside the Windows kernel address space.
Definition: wddefs.h:76
QWORD NumberOfSections
Number of sections.
Definition: winpe.h:603
QWORD Gpa
The accessed guest physical address. Valid only for EPT exits.
Definition: guests.h:101
#define HpFreeAndNullWithTag(Add, Tag)
Definition: glue.h:517
#define TRACE(fmt,...)
Definition: glue.h:58
PWIN_PROCESS_OBJECT IntWinProcFindObjectByCr3(QWORD Cr3)
Finds a process by its kernel CR3.
Definition: winprocesshp.c:122
BOOLEAN IntWinVadIsInTree(const VAD *Vad)
Checks if a VAD is inserted in a guest VAD tree.
Definition: winvad.c:3421
#define INT_STATUS_INVALID_PARAMETER_5
Definition: introstatus.h:74
#define INT_STATUS_INVALID_INTERNAL_STATE
Definition: introstatus.h:272
static INTSTATUS IntWinModHandleKernelWrite(void *Context, void *Hook, QWORD Address, INTRO_ACTION *Action)
Handle writes inside a protected user-mode module from kernel-mode.
Definition: winummodule.c:430
#define INTRO_OPT_EVENT_MODULES
Enable user mode and kernel mode module load and unload events (generates introEventModuleEvent event...
Definition: intro_types.h:429
INTSTATUS IntWinModHandleUnloadFromVad(PWIN_PROCESS_OBJECT Process, PVAD Vad)
Handle a module unload.
Definition: winummodule.c:1435
struct _WIN_PROCESS_OBJECT * Process
The process object related to this subsystem.
Definition: winprocess.h:54
static void InsertTailList(LIST_ENTRY *ListHead, LIST_ENTRY *Entry)
Definition: introlists.h:135
WINUM_PATH * IntWinUmPathReference(WINUM_PATH *Path)
Increases the reference count of the given WINUM_PATH object.
Definition: winumpath.c:292
INTRO_EXEC_CONTEXT ExecContext
Information about the instruction that triggered the alert.
Definition: intro_types.h:1191
BOOLEAN Loaded
True if the module was loaded, False if it was unloaded.
Definition: intro_types.h:1785
size_t strlcpy(char *dst, const char *src, size_t dest_size)
Definition: introcrt.c:1093
BYTE Kernel32LoadCount
Number of kernel32.dll loads.
Definition: winprocess.h:72
#define INT_STATUS_ALREADY_INITIALIZED_HINT
Definition: introstatus.h:323
BOOLEAN UninitPrepared
Definition: guests.h:316
#define WARNING(fmt,...)
Definition: glue.h:60
DWORD Pid
Process ID (the one used by Windows).
Definition: winprocess.h:98
Process subsystem type 64 bit.
Definition: winprocess.h:32
INTSTATUS IntExceptUserGetOriginator(void *Process, BOOLEAN ModuleWrite, QWORD Address, INSTRUX *Instrux, EXCEPTION_UM_ORIGINATOR *Originator)
This function is used to get the information about the user-mode originator.
Sent when an EPT violation triggers an alert. See EVENT_EPT_VIOLATION.
Definition: intro_types.h:84
Hooking.
Definition: intro_types.h:1043
#define PAGE_SIZE
Definition: common.h:53
Describes the modified zone.
Definition: exceptions.h:847
static BOOLEAN IntWinModWriteValidHandler(QWORD Cr3, QWORD Address, void *Context)
Checks if a write inside a code section is legitimate or not.
Definition: winummodule.c:1477
#define UNREFERENCED_PARAMETER(P)
Definition: introdefs.h:29
DWORD NameHash
The CRC32 hash of the name. Used for fast matching.
Definition: winumpath.h:23
void IntWinUmModCacheGet(WIN_PROCESS_MODULE *Module)
Initializes the cache for the provided module.
Definition: winumcache.c:936
const PROTECTED_DLL_INFO gProtectedWowModules[]
Definition: winummodule.c:42
uint16_t WCHAR
Definition: intro_types.h:63
uint32_t DWORD
Definition: intro_types.h:49
UINT32 VirtualSize
Definition: winpe.h:83
INTSTATUS IntUnpUnWatchVaSpacePages(QWORD Cr3)
Stop monitoring all pages belonging to a virtual address space.
Definition: unpacker.c:438
#define PROC_OPT_PROT_CORE_HOOKS
Blocks hooks being set on core user-mode DLLs.
Definition: intro_types.h:333
void IntAlertEptFillFromUmOriginator(const EXCEPTION_UM_ORIGINATOR *Originator, EVENT_EPT_VIOLATION *EptViolation)
Fills user mode originator information inside an EPT alert.
Definition: alerts.c:807
UINT32 Characteristics
Definition: winpe.h:92
INTRO_PROCESS CurrentProcess
The currently active process.
Definition: intro_types.h:1794
INTSTATUS IntPeValidateHeader(QWORD ImageBase, BYTE *ImageBaseBuffer, DWORD ImageBaseBufferSize, INTRO_PE_INFO *PeInfo, QWORD Cr3)
Validates a PE header.
Definition: winpe.c:131
LIST_ENTRY Link
List entry element.
Definition: winummodule.h:32
User-mode library.
Definition: intro_types.h:245
enum _INTRO_ACTION INTRO_ACTION
Event actions.
BOOLEAN IntPolicyProcForceBetaIfNeeded(QWORD Flag, void *Process, INTRO_ACTION *Action)
Checks if a forced action should be taken even if the process log-only mode is active.
Definition: introcore.c:2773
#define IMAGE_SCN_CNT_CODE
Definition: winpe.h:425
#define _In_reads_bytes_(expr)
Definition: intro_sal.h:25
QWORD Rip
The RIP from where the call to the exported function came.
Definition: exceptions.h:904
#define INT_STATUS_INVALID_OBJECT_TYPE
Definition: introstatus.h:145
INTRO_MODULE Module
The module for which this event was triggered.
Definition: intro_types.h:1797
DWORD UnpackAlertSent
TRUE if unpack alerts have been sent.
Definition: winummodule.h:44
#define NAMEHASH_WOW64
Definition: winummodule.h:16
WCHAR * Name
The name of the module contained in the path.
Definition: winumpath.h:18
LIST_HEAD ProcessModules
List of process modules.
Definition: winprocess.h:68
#define IC_TAG_IATB
IAT entries bitmap.
Definition: memtags.h:101
DWORD Offset
The offset inside the page where the violation took place.
Definition: intro_types.h:1156
__must_check INTSTATUS IntVirtMemMap(QWORD Gva, DWORD Length, QWORD Cr3, DWORD Flags, void **HostPtr)
Maps a guest virtual memory range inside Introcore virtual address space.
Definition: introcore.c:2134
void * HeadersSwapHandle
Swap handle for the headers.
Definition: winummodule.h:69
QWORD Cr3
The value of the guest CR3 register when the event was generated.
Definition: intro_types.h:884
INTSTATUS IntWinModHandlePreInjection(void *Context, QWORD Cr3, QWORD VirtualAddress)
Module base page-fault pre-injection callback.
Definition: winummodule.c:938
const PROTECTED_DLL_INFO gProtectedModules[]
Definition: winummodule.c:19
QWORD EprocessAddress
This will be the address of the ActiveProcess field.
Definition: winprocess.h:88
#define ALERT_FLAG_SYSPROC
If set, the alert is on system process.
Definition: intro_types.h:635
DWORD SystemProcess
TRUE if this is a system process.
Definition: winprocess.h:134
GUEST_STATE gGuest
The current guest state.
Definition: guests.c:48
WINUM_MODULE_CACHE * Cache
Module headers cache.
Definition: winummodule.h:63
void IntAlertFillWinProcessByCr3(QWORD ProcessCr3, INTRO_PROCESS *EventProcess)
Saves information about a Windows process inside an alert. The process is searched by its kernel CR3...
Definition: alerts.c:756
Exposes the types, constants and functions needed to block Windows module loads (used to block double...
#define IMAGE_SCN_MEM_DISCARDABLE
Definition: winpe.h:468
#define CWSTRLEN(Wstring)
Definition: introdefs.h:104
static INTSTATUS IntWinProcSendDllEvent(PWIN_PROCESS_MODULE Module, BOOLEAN Loaded)
Send a DLL load/unload event to the integrator.
Definition: winummodule.c:88
WIN_SUBSYTEM_TYPE SubsystemType
Process subsystem type.
Definition: winprocess.h:55
INTRO_ACTION Action
The action that was taken as the result of this alert.
Definition: intro_types.h:1083
int wstrcasecmp(const WCHAR *buf1, const WCHAR *buf2)
Definition: introcrt.c:98
PWIN_PROCESS_MODULE IntWinUmModFindByAddress(PWIN_PROCESS_OBJECT Process, QWORD Gva)
Searches for a user-mode module which contains the indicated guest virtual address.
Definition: winummodule.c:1975
INTSTATUS IntWinDagentCheckSuspiciousDllLoad(WIN_PROCESS_MODULE *Module)
Checks if the given module is suspicious of loading through the double agent technique and calls the ...
QWORD VirtualPage
The guest virtual page in which the access was made.
Definition: intro_types.h:1154
INTSTATUS IntHookObjectHookRegion(void *Object, QWORD Cr3, QWORD Gla, SIZE_T Length, BYTE Type, void *Callback, void *Context, DWORD Flags, HOOK_REGION_DESCRIPTOR **Region)
Hook a contiguous region of virtual memory inside the provided virtual address space.
Definition: hook_object.c:132
DWORD ProtUnpack
Protect process against unpacking attempts.
Definition: winprocess.h:202
DWORD IATEntries
Number of IAT entries.
Definition: winummodule.h:65
#define INT_STATUS_NOT_INITIALIZED_HINT
Definition: introstatus.h:320
char * utf16_for_log(const WCHAR *WString)
Converts a UTF-16 to a UTF-8 string to be used inside logging macros.
Definition: introcore.c:2845
#define NAMEHASH_USER32
Definition: winummodule.h:14
#define INT_STATUS_INVALID_PARAMETER_1
Definition: introstatus.h:62
DWORD StaticScan
TRUE if the module was found by statically enumerating process modules.
Definition: winummodule.h:54
INTRO_PROCESS CurrentProcess
The current process.
Definition: intro_types.h:1086
Kernel-User mode exception.
Definition: exceptions.h:64
VCPU_STATE * gVcpu
The state of the current VCPU.
Definition: guests.c:57
void IntAlertFillWinUmModule(const WIN_PROCESS_MODULE *Module, INTRO_MODULE *EventModule)
Fills information about a user mode module inside an alert.
Definition: alerts.c:653
static int wstrncasecmp_len(const WCHAR *buf1, const WCHAR *buf2, size_t len_buf1, size_t len_buf2)
Definition: introcrt.h:221
UINT8 Name[IMAGE_SIZEOF_SHORT_NAME]
Definition: winpe.h:79
INTRO_MODULE Module
The module that did the malicious access.
Definition: intro_types.h:1110
Holds register state.
Definition: glueiface.h:30
DWORD SizeOfImage
Size of the image.
Definition: winpe.h:599
INTRO_EXEC_INFO ExecInfo
Execution information. Valid only if Violation is IG_EPT_HOOK_EXECUTE.
Definition: intro_types.h:1142
Event structure for EPT violations.
Definition: intro_types.h:1104
Execute-access hook.
Definition: glueiface.h:300
DWORD ProtWsockModules
Protect the Windows Socket related modules.
Definition: winprocess.h:204
PWIN_PROCESS_SUBSYSTEM Subsystem
Module subsystem.
Definition: winummodule.h:60
INTSTATUS IntWinUmModCacheSetHeaders(WIN_PROCESS_MODULE *Module, BYTE *Headers)
Sets the MZ/PE headers in the cache of a given module.
Definition: winumcache.c:1025
DWORD Length
The length of the instruction.
Definition: intro_types.h:918
#define NAMEHASH_KERNEL32
Definition: winummodule.h:12
INTSTATUS IntUnpWatchPage(QWORD Cr3, QWORD VirtualAddress, PFUNC_PageUnpackedCallback UnpackCallback, PFUNC_PageIsWriteValid WriteCheckCallback, void *CallbackContext)
Monitor a page against unpacking.
Definition: unpacker.c:316
char CHAR
Definition: intro_types.h:56
DWORD IatRva
RVA of the imports table.
Definition: winumcache.h:87
static BOOLEAN IntWinModIsProtected(const WIN_PROCESS_MODULE *Module, const PROTECTED_DLL_INFO *ProtectedList, size_t ProtectedCount)
Check if the given module is in the provided list of protected modules.
Definition: winummodule.c:60
Write-access hook.
Definition: glueiface.h:299
A representation of a Windows VAD structure.
Definition: winvad.h:80
DWORD IsMainModule
TRUE if this is the main module.
Definition: winummodule.h:47
DWORD IsSystemModule
TRUE if this is a system module (loaded from system32 or syswow64).
Definition: winummodule.h:48
#define PAGE_MASK
Definition: pgtable.h:35
INTSTATUS IntExceptKernelGetOriginator(EXCEPTION_KM_ORIGINATOR *Originator, DWORD Options)
This function is used to get the information about the kernel-mode originator.
INTSTATUS IntAlertFillExecContext(QWORD Cr3, INTRO_EXEC_CONTEXT *ExecContext)
Fills the current execution context.
Definition: alerts.c:31
#define ZONE_WRITE
Used for write violation.
Definition: exceptions.h:698
#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:267
DWORD Size
Virtual size of the module.
Definition: winummodule.h:35
QWORD Gla
The accessed guest virtual address. Valid only for EPT exits.
Definition: guests.h:102
#define NAMEHASH_WOW64WIN
Definition: winummodule.h:17
INTSTATUS IntHookObjectCreate(DWORD ObjectType, QWORD Cr3, void **Object)
Create a new hook object.
Definition: hook_object.c:81
const WCHAR * strstr_utf16(const WCHAR *buf1, const WCHAR *buf2)
Definition: introcrt.c:195
#define SWAPMEM_OPT_UM_FAULT
If set, the PF must be injected only while in user-mode. Use it when reading user-mode memory...
Definition: swapmem.h:21
void IntExcept(EXCEPTION_VICTIM_ZONE *Victim, void *Originator, EXCEPTION_TYPE Type, INTRO_ACTION *Action, INTRO_ACTION_REASON *Reason, INTRO_EVENT_TYPE EventClass)
This function is the entry point for the exception mechanism.
Definition: exceptions.c:3317
BOOLEAN Protected
True if the module is protected.
Definition: intro_types.h:1787
INTSTATUS IntWinModBlockRemoveBlockObject(void *BlockObject)
This function is used in order to destroy a WIN_MOD_BLOCK_OBJECT structure.
size_t SIZE_T
Definition: intro_types.h:60
INTRO_OBJECT_TYPE Type
The type of the accessed memory area.
Definition: intro_types.h:1119
#define FALSE
Definition: intro_types.h:34
This structure describes a running process inside the guest.
Definition: winprocess.h:81
#define INT_STATUS_INSUFFICIENT_RESOURCES
Definition: introstatus.h:281
WCHAR * Path
The string which represents the user-mode module path.
Definition: winumpath.h:17
const PROTECTED_DLL_INFO gProtectedNetModules[]
Definition: winummodule.c:32