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 #include "winthread.h"
14 
15 
21 {
22  { u"ntdll.dll", NAMEHASH_NTDLL },
23  { u"kernel32.dll", NAMEHASH_KERNEL32 },
24  { u"kernelbase.dll", NAMEHASH_KERNELBASE },
25  { u"user32.dll", NAMEHASH_USER32 },
26  // Add any other modules here.
27 };
28 
29 
34 {
35  { u"ws2_32.dll", NAMEHASH_WS2_32 },
36  { u"wininet.dll", NAMEHASH_WININET },
37 };
38 
39 
44 {
45  { u"ntdll.dll", NAMEHASH_NTDLL },
46  { u"wow64.dll", NAMEHASH_WOW64 },
47  { u"wow64win.dll", NAMEHASH_WOW64WIN },
48  { u"wow64cpu.dll", NAMEHASH_WOW64CPU },
49 
50  // Add any other modules here.
51 };
52 
53 
54 static INTSTATUS
57  );
58 
59 
60 static BOOLEAN
62  _In_ const WIN_PROCESS_MODULE *Module,
63  _In_ const PROTECTED_DLL_INFO *ProtectedList,
64  _In_ size_t ProtectedCount
65  )
75 {
76  for (DWORD i = 0; i < ProtectedCount; i++)
77  {
78  if (MODULE_MATCH(Module, &ProtectedList[i]))
79  {
80  return TRUE;
81  }
82  }
83 
84  return FALSE;
85 }
86 
87 
88 static INTSTATUS
91  _In_ BOOLEAN Loaded
92  )
106 {
107  INTSTATUS status;
108  PEVENT_MODULE_EVENT pModEvent;
109 
111  {
113  }
114 
116  {
118  }
119 
120  if (Loaded && Module->LoadEventSent)
121  {
123  }
124 
125  if (!Loaded && Module->UnloadEventSent)
126  {
128  }
129 
130  if ((NULL == Module->Path) || (0 == Module->VirtualBase) || (0 == Module->Size))
131  {
133  }
134 
135  pModEvent = &gAlert.Module;
136  memzero(pModEvent, sizeof(*pModEvent));
137 
138  pModEvent->Loaded = Loaded;
139  pModEvent->Protected = Module->ShouldProtHooks || Module->ShouldProtUnpack;
140  pModEvent->UserMode = TRUE;
141 
142  IntAlertFillWinUmModule(Module, &pModEvent->Module);
143 
144  IntAlertFillWinProcess(Module->Subsystem->Process, &pModEvent->CurrentProcess);
145 
146  status = IntNotifyIntroEvent(introEventModuleEvent, pModEvent, sizeof(*pModEvent));
147  if (!INT_SUCCESS(status))
148  {
149  WARNING("[WARNING] IntNotifyIntroEvent failed: 0x%08x\n", status);
150  }
151 
152  if (Loaded)
153  {
154  Module->LoadEventSent = TRUE;
155  }
156  else
157  {
158  Module->UnloadEventSent = TRUE;
159  }
160 
161  return status;
162 }
163 
164 
165 static INTSTATUS
167  _In_ PWIN_PROCESS_SUBSYSTEM Subsystem
168  )
179 {
180  LIST_ENTRY *list;
181  PWIN_PROCESS_MODULE pMod;
182 
183  list = Subsystem->ProcessModules.Flink;
184  while (list != &Subsystem->ProcessModules)
185  {
186  pMod = CONTAINING_RECORD(list, WIN_PROCESS_MODULE, Link);
187 
188  list = list->Flink;
189 
191  }
192 
193  return INT_STATUS_SUCCESS;
194 }
195 
196 
197 INTSTATUS
199  _In_ PWIN_PROCESS_OBJECT Process
200  )
208 {
209  if (NULL != Process->Subsystemx86)
210  {
211  IntWinProcSendAllDllEventsForSubsystem(Process->Subsystemx86);
212  }
213 
214  if (NULL != Process->Subsystemx64)
215  {
216  IntWinProcSendAllDllEventsForSubsystem(Process->Subsystemx64);
217  }
218 
219  return INT_STATUS_SUCCESS;
220 }
221 
222 
223 static void
226  )
235 {
236  PWIN_PROCESS_OBJECT pProc = Module->Subsystem->Process;
237 
238  // If the j9jit.dll is loaded and we are in a Java process, we may be in the Java IBM case
239  // where certain VADs must be excepted at execution
240  if (strstr_utf16(Module->Path->Name, u"j9jit") &&
241  strstr(pProc->Name, "java"))
242  {
243  pProc->IsDominoJava = TRUE;
244  pProc->FirstDominoJavaIgnored = FALSE;
245  }
246 }
247 
248 
249 static INTSTATUS
251  _In_ void *Context,
252  _In_ QWORD Cr3,
253  _In_ QWORD ModuleBase,
254  _In_ QWORD PhysicalAddress,
255  _In_reads_bytes_(DataSize) PBYTE Data,
256  _In_ DWORD DataSize,
257  _In_ DWORD Flags
258  )
276 {
277  INTSTATUS status;
278  PWIN_PROCESS_MODULE pMod;
280  PWIN_PROCESS_OBJECT pProc;
281 
283  UNREFERENCED_PARAMETER(DataSize);
284  UNREFERENCED_PARAMETER(Flags);
285 
286  if (NULL == Context)
287  {
289  }
290 
291  if (NULL == Data)
292  {
294  }
295 
296  status = INT_STATUS_SUCCESS;
297 
298  pMod = (PWIN_PROCESS_MODULE)Context;
299 
300  pMod->HeadersSwapHandle = NULL;
301 
302  pSubs = pMod->Subsystem;
303  if (NULL == pSubs)
304  {
306  }
307 
308  pProc = pSubs->Process;
309  if (NULL == pProc)
310  {
312  }
313 
314  if ((Data[0] != 'M') || (Data[1] != 'Z'))
315  {
316  ERROR("[ERROR] Module is not a valid MZ image: %x%x, 0x%016llx:0x%016llx\n", Data[0], Data[1], ModuleBase,
317  PhysicalAddress);
319  }
320 
321  TRACE("[MODULE] Main module for process %llx (subsystem %d) has loaded!\n",
322  pProc->EprocessAddress, pSubs->SubsystemType);
323 
324  if (pMod->ShouldProtUnpack)
325  {
326  TRACE("[MODULE] Protecting module with base 0x%016llx -> 0x%016llx against unpacking.\n", ModuleBase, Cr3);
327 
328  status = IntWinModHookPoly(pMod);
329  if (!INT_SUCCESS(status))
330  {
331  ERROR("[ERROR] IntWinModHookPoly failed: 0x%08x\n", status);
332  }
333 
334  pProc->UnpackProtected = TRUE;
335  }
336 
337  return status;
338 }
339 
340 
341 static int
343  _In_ const WIN_PROCESS_MODULE *Module,
344  _In_ const WCHAR *SystemDirPath,
345  _In_ const WCHAR *TestModule
346  )
356 {
357  WCHAR targetPath[MAX_PATH];
358  size_t k, l;
359 
360  // Copy the directory path. They're both the same size, so it's safe to copy it entirely.
361  memcpy(targetPath,
362  SystemDirPath,
363  MIN(sizeof(targetPath) - sizeof(WCHAR), (wstrlen(SystemDirPath) + 1) * sizeof(WCHAR)));
364 
365  // In case the memcpy didn't copy it
366  targetPath[MAX_PATH - 1] = 0;
367 
368  // Append the module name.
369  k = 0;
370  while ((k < MAX_PATH) && (0 != targetPath[k]))
371  {
372  k++;
373  }
374 
375  l = 0;
376  while ((k + 1 < MAX_PATH) && (0 != TestModule[l]))
377  {
378  targetPath[k] = TestModule[l];
379 
380  k++, l++;
381  }
382 
383  // Append the null terminator.
384  targetPath[k] = 0;
385 
386  return wstrncasecmp_len(targetPath, Module->Path->Path, k, Module->Path->PathSize / 2);
387 }
388 
389 
390 static QWORD
392  _In_ WIN_PROCESS_MODULE *Module
393  )
401 {
402  for (DWORD i = 0; i < ARRAYSIZE(gProtectedModules); i++)
403  {
404  if (MODULE_MATCH(Module, &gProtectedModules[i]))
405  {
407  }
408  }
409 
410  for (DWORD i = 0; i < ARRAYSIZE(gProtectedWowModules); i++)
411  {
412  if (MODULE_MATCH(Module, &gProtectedWowModules[i]))
413  {
415  }
416  }
417 
418  for (DWORD i = 0; i < ARRAYSIZE(gProtectedNetModules); i++)
419  {
420  if (MODULE_MATCH(Module, &gProtectedNetModules[i]))
421  {
423  }
424  }
425 
426  return 0;
427 }
428 
429 
430 static INTSTATUS
432  _In_ EXCEPTION_KM_ORIGINATOR *Originator,
433  _Out_ BOOLEAN *IsInjection
434  )
447 {
448  INTSTATUS status;
449  QWORD copyMemFunc = 0;
450 
451  status = IntDetGetFunctionAddressByTag(detTagProcInject, &copyMemFunc);
452  if (!INT_SUCCESS(status))
453  {
454  return status;
455  }
456 
457  for (DWORD trace = 0; trace < Originator->StackTrace.NumberOfTraces; trace++)
458  {
459  if (Originator->StackTrace.Traces[trace].CalledAddress == copyMemFunc)
460  {
461  *IsInjection = TRUE;
462 
463  return INT_STATUS_SUCCESS;
464  }
465  }
466 
467  *IsInjection = FALSE;
468 
469  return INT_STATUS_SUCCESS;
470 }
471 
472 
473 static INTSTATUS
475  _In_ QWORD ReturnRip,
476  _Inout_ EXCEPTION_KM_ORIGINATOR *Originator
477  )
491 {
492  INTSTATUS status = INT_STATUS_SUCCESS;
493  KERNEL_DRIVER *pDrv;
494 
495  pDrv = IntDriverFindByAddress(ReturnRip);
496 
497  Originator->Injection.Kernel = TRUE;
498  Originator->Return.Driver = pDrv;
499  Originator->Return.Rip = ReturnRip;
500 
501  if (NULL != pDrv)
502  {
503  IMAGE_SECTION_HEADER sectionHeader = { 0 };
504 
505  Originator->Return.NameHash = pDrv->NameHash;
506  Originator->Return.PathHash = pDrv->Win.PathHash;
507 
508  status = IntPeGetSectionHeaderByRva(pDrv->BaseVa,
509  pDrv->Win.MzPeHeaders,
510  (DWORD)(Originator->Return.Rip - pDrv->BaseVa),
511  &sectionHeader);
512  if (!INT_SUCCESS(status))
513  {
514  WARNING("[WARNING] IntPeGetSectionHeaderByRva failed: 0x%08x\n", status);
515  return status;
516  }
517 
518  memcpy(Originator->Return.Section, sectionHeader.Name, sizeof(sectionHeader.Name));
519  }
520  else
521  {
522  Originator->Return.NameHash = INITIAL_CRC_VALUE;
523  Originator->Return.PathHash = INITIAL_CRC_VALUE;
524  }
525 
526  return status;
527 }
528 
529 
530 static INTSTATUS
532  _In_ QWORD CurrentThread,
533  _Inout_ EXCEPTION_KM_ORIGINATOR *Originator
534  )
550 {
551  QWORD eprocess = 0;
552  WIN_PROCESS_OBJECT *pProc = NULL;
553  INTSTATUS status;
554 
555  // The injected process is attached in the current thread, but thread.Process should contain the
556  // process that was performing the injection.
557  status = IntKernVirtMemFetchWordSize(CurrentThread + WIN_KM_FIELD(Thread, Process), &eprocess);
558  if (!INT_SUCCESS(status))
559  {
560  ERROR("[ERROR] IntKernVirtMemFetchWordSize failed: 0x%08x\n", status);
561  return status;
562  }
563 
564  pProc = IntWinProcFindObjectByEprocess(eprocess);
565  if (NULL == pProc)
566  {
567  ERROR("[ERROR] IntWinProcFindObjectByEprocess failed for 0x%016llx\n", eprocess);
568  return INT_STATUS_NOT_FOUND;
569  }
570 
571  Originator->Injection.User = TRUE;
572  Originator->Process.WinProc = pProc;
573 
574  return INT_STATUS_SUCCESS;
575 }
576 
577 
578 static INTSTATUS
580  _Inout_ EXCEPTION_KM_ORIGINATOR *Originator
581  )
598 {
599  INTSTATUS status;
600 
601  if (gGuest.Guest64)
602  {
603  QWORD ethread = 0;
604  BYTE previousMode = 0;
605 
606  status = IntWinThrGetCurrentThread(gVcpu->Index, &ethread);
607  if (!INT_SUCCESS(status))
608  {
609  ERROR("[ERROR] IntWinThrGetCurrentThread failed: 0x%08x\n", status);
610  return status;
611  }
612 
613  status = IntKernVirtMemRead(ethread + WIN_KM_FIELD(Thread, PreviousMode), 1, &previousMode, NULL);
614  if (!INT_SUCCESS(status))
615  {
616  ERROR("[ERROR] IntKernVirtMemRead failed: 0x%08x\n", status);
617  return status;
618  }
619 
620  if (previousMode == 0)
621  {
622  QWORD realRsp = 0, realRet = 0;
623 
624  // On x64 there is a fake trapframe at Zw* calls which is only kept on the stack and in KTHREAD
625  // is just another trapframe... This trapframe only contains some registers and the stack, so it
626  // can't be mapped over a KTRAP_FRAME64. It is constructed in KiServiceInternal. For our purpose
627  // it doesn't seem that Rbp is ever overwritten during a ZwWriteVirtualMemory, but maybe we should
628  // see if we can make it more generic somehow...
629  status = IntKernVirtMemFetchQword(gVcpu->Regs.Rbp + WIN_KM_FIELD(Ungrouped, RspOffsetOnZwCall), &realRsp);
630  if (!INT_SUCCESS(status))
631  {
632  ERROR("[ERROR] IntKernVirtMemFetchQword failed: 0x%08x\n", status);
633  return status;
634  }
635 
636  status = IntKernVirtMemFetchQword(realRsp, &realRet);
637  if (!INT_SUCCESS(status))
638  {
639  ERROR("[ERROR] IntKernVirtMemFetchQword failed: 0x%08x\n", status);
640  return status;
641  }
642 
643  status = IntWinModFillDriverInjectionData(realRet, Originator);
644  if (!INT_SUCCESS(status))
645  {
646  ERROR("[ERROR] IntWinModFillDriverInjectionData failed: 0x%08x\n", status);
647  }
648  }
649  else
650  {
651  status = IntWinModFillProcessInjectionData(ethread, Originator);
652  if (!INT_SUCCESS(status))
653  {
654  ERROR("[ERROR] IntWinModFillProcessInjectionData failed: 0x%08x\n", status);
655  }
656  }
657  }
658  else
659  {
660  KTRAP_FRAME32 trapFrame = { 0 };
661  QWORD ethread = 0;
662  DWORD trapFrameAddr;
663 
664  status = IntWinThrGetCurrentThread(gVcpu->Index, &ethread);
665  if (!INT_SUCCESS(status))
666  {
667  ERROR("[ERROR] IntWinThrGetCurrentThread failed: 0x%08x\n", status);
668  return status;
669  }
670 
671  status = IntKernVirtMemFetchDword(ethread + WIN_KM_FIELD(Thread, TrapFrame), &trapFrameAddr);
672  if (!INT_SUCCESS(status))
673  {
674  ERROR("[ERROR] IntKernVirtMemFetchDword failed: 0x%08x\n", status);
675  return status;
676  }
677 
678  status = IntKernVirtMemRead(trapFrameAddr, sizeof(trapFrame), &trapFrame, NULL);
679  if (!INT_SUCCESS(status))
680  {
681  ERROR("[ERROR] IntKernVirtMemRead failed: 0x%08x\n", status);
682  return status;
683  }
684 
685  if (IS_KERNEL_POINTER_WIN(gGuest.Guest64, trapFrame.Eip))
686  {
687  // It seems too easy, but the real return is always at trapFrame.HardwareEsp.
688  // This happens because of the following code at KiServiceExit:
689  // nt!KiServiceExit + 0x15b:
690  // 81b76439 8d6554 lea esp, [ebp + 54h]
691  // 81b7643c 5f pop edi
692  // 81b7643d 5e pop esi
693  // 81b7643e 5b pop ebx
694  // 81b7643f 5d pop ebp
695  // 81b76440 83c404 add esp, 4
696  // 81b76443 f744240401000000 test dword ptr[esp + 4], 1
697  // 81b7644b 7505 jne nt!KiSystemCallExit2 (81b76452) Branch
698  //
699  // nt!KiSystemCallExitBranch + 0x2:
700  // 81b7644d 5a pop edx
701  // 81b7644e 59 pop ecx
702  // 81b7644f 9d popfd
703  // 81b76450 ffe2 jmp edx
704 
705  // So it can be seen that the stack will remain pointing to TrapFrame.HardwareEsp. Jumping to
706  // the Zw* function, there will be a ret there, returning to the caller driver. So at HardwareEsp
707  // there is always the caller driver.
708  status = IntWinModFillDriverInjectionData(trapFrame.HardwareEsp, Originator);
709  if (!INT_SUCCESS(status))
710  {
711  ERROR("[ERROR] IntWinModFillDriverInjectionData failed: 0x%08x\n", status);
712  }
713  }
714  else
715  {
716  status = IntWinModFillProcessInjectionData(ethread, Originator);
717  if (!INT_SUCCESS(status))
718  {
719  ERROR("[ERROR] IntWinModFillProcessInjectionData failed: 0x%08x\n", status);
720  }
721  }
722  }
723 
724  return status;
725 }
726 
727 
728 
729 static INTSTATUS
731  _In_ void *Context,
732  _In_ void *Hook,
733  _In_ QWORD Address,
734  _Out_ INTRO_ACTION *Action
735  )
746 {
747  INTSTATUS status = INT_STATUS_SUCCESS;
748  EXCEPTION_KM_ORIGINATOR originator = { 0 };
749  EXCEPTION_VICTIM_ZONE victim = { 0 };
751  BOOLEAN informationOnly = FALSE;
752  WIN_PROCESS_MODULE *pModule = (WIN_PROCESS_MODULE *)Context;
753  WIN_PROCESS_OBJECT *pProcess = pModule->Subsystem->Process;
754  BOOLEAN isInjection = FALSE;
755 
756  *Action = introGuestNotAllowed;
757 
759 
761  if (!INT_SUCCESS(status))
762  {
763  ERROR("[ERROR] IntExceptKernelGetOriginator failed with status: 0x%08x\n", status);
764 
765  reason = introReasonInternalError;
766  informationOnly = TRUE;
767  }
768 
769  status = IntWinModIsKernelWriteInjection(&originator, &isInjection);
770  if (!INT_SUCCESS(status))
771  {
772  ERROR("[ERROR] IntWinModIsKernelWriteInjection failed: 0x%08x\n", status);
773  }
774 
775  if (isInjection)
776  {
777  status = IntWinModFillInjectionData(&originator);
778  if (!INT_SUCCESS(status))
779  {
780  ERROR("[ERROR] IntWinModFillInjectionData failed: 0x%08x\n", status);
781  }
782  }
783 
784  status = IntExceptGetVictimEpt(Context,
785  Address,
786  IntHookGetGlaFromGpaHook(Hook, Address),
788  ZONE_WRITE,
789  &victim);
790  if (!INT_SUCCESS(status))
791  {
792  ERROR("[ERROR] IntExceptGetVictimEpt failed with status: 0x%08x\n", status);
793 
794  reason = introReasonInternalError;
795  informationOnly = TRUE;
796  }
797 
798  if (informationOnly)
799  {
800  IntExceptKernelUserLogInformation(&victim, &originator, *Action, reason);
801  }
802  else
803  {
804  IntExcept(&victim, &originator, exceptionTypeKmUm, Action, &reason, introEventEptViolation);
805  }
806 
808 
809  if (IntPolicyProcTakeAction(IntWinModGetProtectionOptionForModule(pModule), pProcess, Action, &reason))
810  {
811  EVENT_EPT_VIOLATION *pEptViol = &gAlert.Ept;
812 
813  memzero(pEptViol, sizeof(*pEptViol));
814 
815  pEptViol->Header.Action = *Action;
816  pEptViol->Header.Reason = reason;
817  pEptViol->Header.MitreID = idHooking;
818 
820 
821  IntAlertEptFillFromKmOriginator(&originator, pEptViol);
822  IntAlertEptFillFromVictimZone(&victim, pEptViol);
823 
825  pModule->Subsystem->Process, reason, ALERT_FLAG_KM_UM);
826 
828 
829  IntAlertFillCodeBlocks(originator.Original.Rip, gVcpu->Regs.Cr3, FALSE, &pEptViol->CodeBlocks);
830  IntAlertFillExecContext(0, &pEptViol->ExecContext);
831 
832  IntAlertFillVersionInfo(&pEptViol->Header);
833 
834  pEptViol->Originator.Injection.User = originator.Injection.User;
835  pEptViol->Originator.Injection.Kernel = originator.Injection.Kernel;
836 
837  IntAlertFillWinProcess(originator.Process.WinProc, &pEptViol->Originator.Process);
838 
839  status = IntNotifyIntroEvent(introEventEptViolation, pEptViol, sizeof(*pEptViol));
840  if (!INT_SUCCESS(status))
841  {
842  WARNING("[WARNING] IntNotifyIntroEvent failed: 0x%08x\n", status);
843  }
844 
845  status = INT_STATUS_SUCCESS;
846  }
847 
849 
850  return status;
851 }
852 
853 
854 static INTSTATUS
856  _In_ void *Context,
857  _In_ void *Hook,
858  _In_ QWORD Address,
859  _Out_ INTRO_ACTION *Action
860  )
879 {
880  INTSTATUS status;
881  PWIN_PROCESS_MODULE pMod;
882  PWIN_PROCESS_OBJECT pOriginatorProc;
883  INTRO_ACTION_REASON reason;
884  PIG_ARCH_REGS regs;
885  EXCEPTION_UM_ORIGINATOR originator;
886  EXCEPTION_VICTIM_ZONE victim;
887  DWORD iatidx, iatesz;
888 
889  status = INT_STATUS_SUCCESS;
890 
891  pMod = (PWIN_PROCESS_MODULE)Context;
892 
893  regs = &gVcpu->Regs;
894 
895  *Action = introGuestNotAllowed;
896  reason = introReasonInternalError;
897 
898  if (regs->Cr3 != pMod->Subsystem->Process->Cr3)
899  {
900  const WIN_PROCESS_OBJECT *p = pMod->Subsystem->Process;
902 
903  WARNING("[WARNING] [SPECIAL-CASE] Process (pid: %d, eproc %llx, cr3 %llx, usercr3 %llx, name %s) "
904  "is not the current one (current cr3 %llx, gva %llx, gpa %llx, ac %d)\n",
905  p->Pid, p->EprocessAddress, p->Cr3, p->UserCr3, p->Name, regs->Cr3,
907  if (NULL != p2)
908  {
909  WARNING("[WARNING] [SPECIAL-CASE] Process (pid: %d, eproc %llx, cr3 %llx, usercr3 %llx, name %s) "
910  "is the current one!\n", p2->Pid, p2->EprocessAddress, p2->Cr3, p2->UserCr3, p2->Name);
911  }
912  }
913 
914  // Whitelist for ntdll!LdrpTouchPageForWrite.
915  if ((gVcpu->AccessSize == 1) &&
916  (gVcpu->Instruction.Instruction == ND_INS_OR) &&
917  (gVcpu->Instruction.HasImm1) &&
918  (gVcpu->Instruction.Immediate1 == 0))
919  {
920  *Action = introGuestAllowed;
921  reason = introReasonAllowed;
922 
923  goto _cleanup_and_exit;
924  }
925 
926  iatesz = (pMod->Is64BitModule ? 8 : 4);
927 
928  // White listing for IAT writes - we allow the first write that takes place in each IAT entry
929  // if it is done from ntdll
930  if ((pMod->IATBitmap != NULL) && (gVcpu->Gla >= pMod->VirtualBase + pMod->Cache->Info.IatRva) &&
931  (gVcpu->Gla < pMod->VirtualBase + pMod->Cache->Info.IatRva + (QWORD)pMod->IATEntries * iatesz) &&
932  (gVcpu->Regs.Rip >= pMod->Subsystem->NtdllBase &&
933  gVcpu->Regs.Rip < pMod->Subsystem->NtdllBase + pMod->Subsystem->NtdllSize))
934  {
935  iatidx = (DWORD)(gVcpu->Gla - (pMod->VirtualBase + pMod->Cache->Info.IatRva)) / iatesz;
936 
937  if (pMod->IATBitmap[iatidx] == 0)
938  {
939  pMod->IATBitmap[iatidx]++;
940 
941  *Action = introGuestAllowed;
942  reason = introReasonAllowed;
943 
944  goto _cleanup_and_exit;
945  }
946  }
947 
949 
950  memzero(&originator, sizeof(originator));
951  memzero(&victim, sizeof(victim));
952 
953  pOriginatorProc = pMod->Subsystem->Process;
954 
955  status = IntExceptUserGetOriginator(pOriginatorProc, TRUE, regs->Rip, &gVcpu->Instruction, &originator);
956  if (status == INT_STATUS_STACK_SWAPPED_OUT)
957  {
958  *Action = introGuestRetry;
959  status = INT_STATUS_SUCCESS;
960  goto _send_notification;
961  }
962  else if (!INT_SUCCESS(status))
963  {
964  reason = introReasonInternalError;
965  *Action = introGuestNotAllowed;
966 
967  ERROR("[ERROR] Failed getting originator: 0x%08x\n", status);
968  goto _send_notification;
969  }
970 
971  status = IntExceptGetVictimEpt(pMod,
972  Address,
973  IntHookGetGlaFromGpaHook(Hook, Address),
975  ZONE_WRITE,
976  &victim);
977  if (!INT_SUCCESS(status))
978  {
979  reason = introReasonInternalError;
980  *Action = introGuestNotAllowed;
981 
982  ERROR("[ERROR] Failed getting modified zone: 0x%08x\n", status);
983  goto _send_notification;
984  }
985 
986  IntExcept(&victim, &originator, exceptionTypeUm, Action, &reason, introEventEptViolation);
987 
988 _send_notification:
990 
992  {
993  PEVENT_EPT_VIOLATION pEptViol = &gAlert.Ept;
994 
995  // First of all, send ALL the dll events.
996  IntWinProcSendAllDllEventsForProcess(pOriginatorProc);
997 
998  memzero(pEptViol, sizeof(*pEptViol));
999 
1000  pEptViol->Header.Action = *Action;
1001  pEptViol->Header.Reason = reason;
1002  pEptViol->Header.MitreID = idHooking;
1003 
1005 
1006  IntAlertEptFillFromUmOriginator(&originator, pEptViol);
1007  IntAlertEptFillFromVictimZone(&victim, pEptViol);
1008 
1010  pMod->Subsystem->Process, reason, 0);
1011 
1013 
1014  IntAlertFillCodeBlocks(regs->Rip, regs->Cr3, FALSE, &pEptViol->CodeBlocks);
1015  IntAlertFillExecContext(0, &pEptViol->ExecContext);
1016 
1017  IntAlertFillVersionInfo(&pEptViol->Header);
1018 
1019  status = IntNotifyIntroEvent(introEventEptViolation, pEptViol, sizeof(*pEptViol));
1020  if (!INT_SUCCESS(status))
1021  {
1022  WARNING("[WARNING] IntNotifyIntroEvent failed: 0x%08x\n", status);
1023  }
1024 
1025  status = INT_STATUS_SUCCESS;
1026  }
1027 
1028 _cleanup_and_exit:
1030 
1031  return status;
1032 }
1033 
1034 
1035 INTSTATUS
1037  _In_opt_ void *Context,
1038  _In_ void *Hook,
1039  _In_ QWORD Address,
1040  _Out_ INTRO_ACTION *Action
1041  )
1054 {
1055  if (NULL == Context)
1056  {
1058  }
1059 
1060  if (NULL == Action)
1061  {
1063  }
1064 
1065  *Action = introGuestNotAllowed;
1066 
1068  {
1069  return IntWinModHandleKernelWrite(Context, Hook, Address, Action);
1070  }
1071  else
1072  {
1073  return IntWinModHandleUserWrite(Context, Hook, Address, Action);
1074  }
1075 }
1076 
1077 
1078 static INTSTATUS
1080  _In_ PWIN_PROCESS_MODULE Module
1081  )
1095 {
1096  INTSTATUS status;
1097  DWORD sectionRva = 0;
1098  DWORD sectionCount = 0;
1099  DWORD i;
1100  PWIN_PROCESS_OBJECT pProc;
1101  IMAGE_SECTION_HEADER *sec;
1102 
1103  pProc = Module->Subsystem->Process;
1104 
1105  if (NULL == Module->Cache || NULL == Module->Cache->Headers)
1106  {
1107  ERROR("[ERROR] Invalid state where module doesn't has cache (%p) or headers!\n", Module->Cache);
1109  }
1110 
1111 #define MAX_IAT_ENTRIES 4096
1112 
1113  Module->IATEntries = Module->Cache->Info.IatSize / (Module->Is64BitModule ? 8 : 4);
1114  if (Module->IATEntries > MAX_IAT_ENTRIES)
1115  {
1116  WARNING("[WARNING] Module `%s` has %d IAT entries. Will use MAX_IAT_ENTRIES.",
1117  utf16_for_log(Module->Path->Name), Module->IATEntries);
1118  Module->IATEntries = MAX_IAT_ENTRIES;
1119  }
1120 
1121 
1122  if (Module->IATEntries != 0)
1123  {
1124  // Each entry will be initialized when that IAT entry will be written by the loader. The first write will be
1125  // allowed without checking the exceptions, all the other writes will go through the exceptions mechanism.
1126  Module->IATBitmap = HpAllocWithTag(Module->IATEntries, IC_TAG_IATB);
1127  if (NULL == Module->IATBitmap)
1128  {
1130  }
1131  }
1132 
1133  status = IntHookObjectCreate(0, pProc->Cr3, &Module->HookObject);
1134  if (!INT_SUCCESS(status))
1135  {
1136  ERROR("[ERROR] IntHookObjectCreate failed: 0x%08x\n", status);
1137  return status;
1138  }
1139 
1140  // At this point, there is no point in doing any verification, since they were already done
1141  // in the previous step (pre-hooking). The MzPeHeaders won't be present if they were invalid.
1142  status = IntPeListSectionsHeaders(Module->VirtualBase,
1143  Module->Cache->Headers,
1144  PAGE_SIZE,
1145  &sectionRva,
1146  &sectionCount);
1147  if (!INT_SUCCESS(status))
1148  {
1149  ERROR("[ERROR] IntPeListSectionsHeaders failed with status: 0x%08x\n", status);
1150  return status;
1151  }
1152 
1153  TRACE("[MODULE] Protecting module '%s' loaded at 0x%016llx\n",
1154  utf16_for_log(Module->Path->Path), Module->VirtualBase);
1155 
1156  sec = (IMAGE_SECTION_HEADER *)(Module->Cache->Headers + sectionRva);
1157  for (i = 0; i < sectionCount; i++, sec++)
1158  {
1160  {
1161  continue;
1162  }
1163 
1164  if ((QWORD)sec->VirtualAddress + sec->Misc.VirtualSize > Module->Vad->PageCount * PAGE_SIZE)
1165  {
1166  INFO("[INFO] Skipping section from VA 0x%08x, size 0x%08x, which is larger than VadSize 0x%016llx\n",
1167  sec->VirtualAddress, sec->Misc.VirtualSize, Module->Vad->PageCount * PAGE_SIZE);
1168  continue;
1169  }
1170 
1171 #ifdef DEBUG
1172  // The name of the section isn't always NULL terminated, let's make sure it is
1173  CHAR name[sizeof(sec->Name) + 1];
1174  memcpy(name, sec->Name, sizeof(sec->Name));
1175  name[sizeof(sec->Name)] = 0;
1176 
1177  TRACE("[MODULE] Protecting pageable region: 0x%016llx, VA space 0x%016llx, length %x Name `%s`\n",
1178  Module->VirtualBase + sec->VirtualAddress, pProc->Cr3, sec->Misc.VirtualSize, name);
1179 #endif
1180 
1181  status = IntHookObjectHookRegion(Module->HookObject,
1182  pProc->Cr3,
1183  Module->VirtualBase + sec->VirtualAddress,
1187  Module,
1188  0,
1189  NULL);
1190  if (!INT_SUCCESS(status))
1191  {
1192  ERROR("[ERROR] IntHookObjectHookRegion failed: 0x%08x\n", status);
1193  }
1194  }
1195 
1196  Module->IsProtected = TRUE;
1197 
1198  Module->Subsystem->ProtectedModulesCount++;
1199 
1200  return INT_STATUS_SUCCESS;
1201 }
1202 
1203 
1204 INTSTATUS
1206  _In_ PWIN_PROCESS_MODULE Module
1207  )
1216 {
1217  INTSTATUS status;
1218 
1219  if (NULL == Module)
1220  {
1222  }
1223 
1224  // Remove the unpacker, if active.
1225  if (Module->ShouldProtUnpack && Module->Subsystem->Process->UnpackProtected)
1226  {
1227  status = IntUnpUnWatchVaSpacePages(Module->Subsystem->Process->Cr3);
1228  if (!INT_SUCCESS(status))
1229  {
1230  ERROR("[ERROR] IntUnpUnWatchVaSpacePages failed: 0x%08x\n", status);
1231  }
1232  }
1233 
1234  // Remove the protection, if any.
1235  if (NULL != Module->HookObject)
1236  {
1237  status = IntHookObjectDestroy((HOOK_OBJECT_DESCRIPTOR **)&Module->HookObject, 0);
1238  if (!INT_SUCCESS(status))
1239  {
1240  ERROR("[ERROR] IntHookObjectDestroy failed: 0x%08x\n", status);
1241  }
1242  }
1243 
1244  if (NULL != Module->ModBlockObject)
1245  {
1246  status = IntWinModBlockRemoveBlockObject(Module->ModBlockObject);
1247  if (!INT_SUCCESS(status))
1248  {
1249  ERROR("[ERROR] IntWinModBlockRemoveBlockObject failed: 0x%08x\n", status);
1250  }
1251  }
1252 
1253  if (Module->IsProtected)
1254  {
1255  Module->Subsystem->ProtectedModulesCount--;
1256  }
1257 
1258  Module->IsProtected = FALSE;
1259 
1260  return INT_STATUS_SUCCESS;
1261 }
1262 
1263 
1264 INTSTATUS
1266  _In_ void *Context,
1267  _In_ QWORD Cr3,
1268  _In_ QWORD VirtualAddress
1269  )
1285 {
1287  UNREFERENCED_PARAMETER(VirtualAddress);
1288 
1289  PWIN_PROCESS_MODULE pMod = (PWIN_PROCESS_MODULE)Context;
1290  if (NULL == pMod)
1291  {
1293  }
1294 
1295  // We try to inject a #PF on this module. We have to make sure that the VAD corresponding to this module is already
1296  // inserted in the RB tree inside the guest! If we inject a #PF but the VAD is not queued yet, we will end up
1297  // crashing the process, because it would receive a #PF for an address which is still invalid (because the VAD
1298  // is not inserted in the tree yet!)
1299  if (!IntWinVadIsInTree(pMod->Vad))
1300  {
1301  LOG("[WINMODULE] The VAD 0x%016llx belonging to module %s seems to not be inside the tree yet, "
1302  "will postpone #PF...\n", pMod->Vad->VadGva, utf16_for_log(pMod->Path->Path));
1303 
1305  }
1306 
1307  return INT_STATUS_SUCCESS;
1308 }
1309 
1310 
1311 static INTSTATUS
1313  _In_ void *Context,
1314  _In_ QWORD Cr3,
1315  _In_ QWORD VirtualAddress,
1316  _In_ QWORD PhysicalAddress,
1317  _In_reads_bytes_(DataSize) PBYTE Data,
1318  _In_ DWORD DataSize,
1319  _In_ DWORD Flags
1320  )
1340 {
1341  INTSTATUS status;
1342  PWIN_PROCESS_MODULE pMod;
1343  PWIN_PROCESS_SUBSYSTEM pSubs;
1344  PWIN_PROCESS_OBJECT pProc;
1345 
1347  UNREFERENCED_PARAMETER(VirtualAddress);
1348  UNREFERENCED_PARAMETER(DataSize);
1349  UNREFERENCED_PARAMETER(PhysicalAddress);
1350  UNREFERENCED_PARAMETER(Flags);
1351 
1352  if (NULL == Context)
1353  {
1355  }
1356 
1357  if (NULL == Data)
1358  {
1360  }
1361 
1362  pMod = (PWIN_PROCESS_MODULE)Context;
1363  pMod->HeadersSwapHandle = NULL;
1364 
1365  pSubs = pMod->Subsystem;
1366  if (NULL == pSubs)
1367  {
1369  }
1370 
1371  pProc = pSubs->Process;
1372  if (NULL == pProc)
1373  {
1375  }
1376 
1377  status = IntWinUmModCacheSetHeaders(pMod, Data);
1378 
1379  if (INT_SUCCESS(status) && pProc->Protected && pMod->ShouldProtHooks)
1380  {
1381  TRACE("[MODULE] Protecting module with base 0x%016llx -> 0x%016llx against hooking.\n", VirtualAddress, Cr3);
1382 
1383  status = IntWinModHookModule(pMod);
1384  if (!INT_SUCCESS(status))
1385  {
1386  ERROR("[ERROR] IntWinModHookModule failed: 0x%08x\n", status);
1387  }
1388  }
1389 
1390  return INT_STATUS_SUCCESS;
1391 }
1392 
1393 
1394 static INTSTATUS
1396  _In_ WIN_PROCESS_MODULE *Module,
1397  _In_ WINUM_PATH *Path
1398  )
1415 {
1416  PWIN_PROCESS_SUBSYSTEM pSubs;
1417  PWIN_PROCESS_OBJECT pProc;
1418  INTSTATUS status;
1419 
1420  pSubs = Module->Subsystem;
1421  if (NULL == pSubs)
1422  {
1424  }
1425 
1426  pProc = pSubs->Process;
1427  if (NULL == pProc)
1428  {
1430  }
1431 
1432  Module->Path = IntWinUmPathReference(Path);
1433 
1434  if (gGuest.Guest64 && (Module->Subsystem->SubsystemType == winSubsys32Bit))
1435  {
1436  // OK, we don't compare the entire length, we just want to see if the first part of the path matches.
1437  if (wstrncasecmp(Module->Path->Path, u"\\windows\\syswow64\\", CWSTRLEN(u"\\windows\\syswow64\\")) == 0)
1438  {
1439  Module->IsSystemModule = TRUE;
1440  }
1441  }
1442  else
1443  {
1444  // OK, we don't compare the entire length, we just want to see if the first part of the path matches.
1445  if (wstrncasecmp(Module->Path->Path, u"\\windows\\system32\\", CWSTRLEN(u"\\windows\\system32\\")) == 0)
1446  {
1447  Module->IsSystemModule = TRUE;
1448  }
1449  }
1450 
1451  pSubs->LoadedModulesCount++;
1452 
1453  TRACE("[MODULE] Module '%s' (%08x) just loaded at 0x%016llx in process '%s' (pid = %d)\n",
1454  utf16_for_log(Module->Path->Path), Module->Path->NameHash, Module->VirtualBase, pProc->Name, pProc->Pid);
1455 
1457 
1458  if (Module->VirtualBase == pProc->MainModuleAddress)
1459  {
1460  Module->IsMainModule = TRUE;
1461 
1462  pSubs->MainModuleLoaded = TRUE;
1463 
1464  if (!pProc->MainModuleLoaded)
1465  {
1466  pProc->MainModuleLoaded = TRUE;
1467 
1468  pProc->Path = IntWinUmPathReference(Module->Path);
1469  }
1470  }
1471 
1472  if (Module->IsMainModule && !pProc->SystemProcess)
1473  {
1474  if (NULL == IntWinProcGetProtectedInfoEx(Module->Path->Path, !!pProc->SystemProcess))
1475  {
1476  TRACE("[INFO] Application '%s' was not found among the protected ones, will remove protection.\n",
1477  utf16_for_log(Module->Path->Path));
1478 
1479  status = IntWinProcUnprotect(pProc);
1480  if (!INT_SUCCESS(status))
1481  {
1482  ERROR("[ERROR] IntWinProcUnprotect failed: 0x%08x\n", status);
1483  }
1484 
1485  return status;
1486  }
1487  }
1488 
1489  if (Module->IsSystemModule)
1490  {
1491  if ((Module->Path->NameHash == NAMEHASH_NTDLL) &&
1492  (0 == wstrcasecmp(Module->Path->Name, u"ntdll.dll")))
1493  {
1494  Module->Subsystem->NtdllBase = Module->VirtualBase;
1495  Module->Subsystem->NtdllSize = Module->Size;
1496 
1497  Module->Subsystem->NtdllLoadCount++;
1498  }
1499  else if ((Module->Path->NameHash == NAMEHASH_KERNEL32) &&
1500  (0 == wstrcasecmp(Module->Path->Name, u"kernel32.dll")))
1501  {
1502  Module->Subsystem->Kernel32LoadCount++;
1503  }
1504 
1505  // For 32-bit processes on 64-bit guests we also need to check the WoW64 modules
1506  if ((winSubsys64Bit == pSubs->SubsystemType) && (pProc->Wow64Process))
1507  {
1508  if (IntWinModIsProtected(Module, gProtectedWowModules, ARRAYSIZE(gProtectedWowModules)))
1509  {
1510  Module->ShouldProtHooks = pSubs->Process->ProtCoreModules;
1511  Module->ShouldGetCache = TRUE;
1512  }
1513  }
1514  else
1515  {
1516  if (IntWinModIsProtected(Module, gProtectedModules, ARRAYSIZE(gProtectedModules)))
1517  {
1518  Module->ShouldProtHooks = pSubs->Process->ProtCoreModules;
1519  Module->ShouldGetCache = TRUE;
1520  }
1521  else if (IntWinModIsProtected(Module, gProtectedNetModules, ARRAYSIZE(gProtectedNetModules)))
1522  {
1523  Module->ShouldProtHooks = pSubs->Process->ProtWsockModules;
1524  Module->ShouldGetCache = TRUE;
1525  }
1526  }
1527  }
1528 
1529  if (pSubs->Process->ProtUnpack && Module->IsMainModule)
1530  {
1531  Module->ShouldProtUnpack = TRUE;
1532  }
1533 
1534  if (Module->ShouldGetCache)
1535  {
1536  IntWinUmModCacheGet(Module);
1537 
1538  if (NULL == Module->Cache)
1539  {
1540  ERROR("[ERROR] Module->Cache is NULL after IntWinUmModCacheGet!\n");
1541  }
1542  else
1543  {
1544  status = IntSwapMemReadData(pSubs->Process->Cr3,
1545  Module->VirtualBase,
1546  PAGE_SIZE,
1548  Module,
1549  0,
1552  &Module->HeadersSwapHandle);
1553  if (!INT_SUCCESS(status))
1554  {
1555  ERROR("[ERROR] IntSwapMemReadData failed: 0x%08x\n", status);
1556  return status;
1557  }
1558  }
1559  }
1560 
1561  if (Module->ShouldProtUnpack)
1562  {
1563  status = IntSwapMemReadData(pSubs->Process->Cr3,
1564  Module->VirtualBase,
1565  2,
1567  Module,
1568  0,
1571  &Module->HeadersSwapHandle);
1572  if (!INT_SUCCESS(status))
1573  {
1574  ERROR("[ERROR] IntSwapMemReadData failed: 0x%08x\n", status);
1575  return status;
1576  }
1577  }
1578 
1579  // Finally check if the current module might be loaded through double agent
1581 
1582  return INT_STATUS_SUCCESS;
1583 }
1584 
1585 
1586 INTSTATUS
1588  _In_ WIN_PROCESS_OBJECT *Process,
1589  _In_ const VAD *Vad
1590  )
1603 {
1604  INTSTATUS status;
1605  WIN_PROCESS_MODULE *pMod;
1606 
1607  if (Vad->PageCount * PAGE_SIZE > 0xFFFFFFFF)
1608  {
1609  ERROR("[ERROR] Module greater than 4GB!\n");
1610 
1612  }
1613 
1614  pMod = HpAllocWithTag(sizeof(*pMod), IC_TAG_MODU);
1615  if (NULL == pMod)
1616  {
1618  }
1619 
1620  pMod->VirtualBase = Vad->StartPage;
1621  pMod->Size = (DWORD)(Vad->PageCount * PAGE_SIZE);
1622  pMod->StaticScan = Vad->StaticScan;
1623  pMod->Vad = Vad;
1624 
1625  if (gGuest.Guest64)
1626  {
1627  if (!Process->Wow64Process)
1628  {
1629  pMod->Subsystem = Process->Subsystemx64;
1630  pMod->Is64BitModule = TRUE;
1631  }
1632  else
1633  {
1634  // We're on 64 bit with wow64 process. We determine the subsystem using the module name. Inside the 64 bit
1635  // subsystem, the following modules will be loaded and possibly unloaded:
1636  // - /windows/system32/ntdll.dll
1637  // - /windows/system32/wow64win.dll
1638  // - /windows/system32/wow64.dll
1639  // - /windows/system32/wow64cpu.dll
1640  // - /windows/system32/kernel32.dll
1641  // - /windows/system32/user32.dll
1642  // All other modules will be 32 bit modules.
1643  // OK, we don't compare the entire length, we just want to see if the first part of the path matches.
1644  if (wstrncasecmp(Vad->Path->Path, u"\\windows\\system32\\", wstrlen(u"\\windows\\system32\\")) == 0)
1645  {
1646  pMod->Subsystem = Process->Subsystemx64;
1647  pMod->Is64BitModule = TRUE;
1648  }
1649  else
1650  {
1651  pMod->Subsystem = Process->Subsystemx86;
1652  pMod->Is64BitModule = FALSE;
1653  }
1654  }
1655  }
1656  else
1657  {
1658  pMod->Subsystem = Process->Subsystemx86;
1659  pMod->Is64BitModule = FALSE;
1660  }
1661 
1662  InsertTailList(&pMod->Subsystem->ProcessModules, &pMod->Link);
1663 
1664  status = IntWinModHandleModulePathInMemory(pMod, Vad->Path);
1665  if (!INT_SUCCESS(status))
1666  {
1667  ERROR("[ERROR] IntWinModHandleModuleNameInMemory failed: 0x%08x\n", status);
1668  return status;
1669  }
1670 
1671  if (pMod->IsMainModule && Process->Wow64Process && (pMod->Subsystem == Process->Subsystemx86))
1672  {
1673  WIN_PROCESS_MODULE *pMod64;
1674 
1675  // If this was the main module, and we're inside a Wow64 process, we have to allocate a fresh entry
1676  // for the 64 bit subsystem.
1677 
1678  pMod64 = HpAllocWithTag(sizeof(*pMod64), IC_TAG_MODU);
1679  if (NULL == pMod64)
1680  {
1682  }
1683 
1684  pMod64->Subsystem = Process->Subsystemx64;
1685  pMod64->VirtualBase = Vad->StartPage;
1686  pMod64->Size = (DWORD)(Vad->PageCount * PAGE_SIZE);
1687  pMod64->Vad = Vad;
1688 
1689  InsertTailList(&pMod64->Subsystem->ProcessModules, &pMod64->Link);
1690 
1691  status = IntWinModHandleModulePathInMemory(pMod64, Vad->Path);
1692  if (!INT_SUCCESS(status))
1693  {
1694  ERROR("[ERROR] IntWinModHandleModuleNameInMemory failed: 0x%08x\n", status);
1695  return status;
1696  }
1697  }
1698 
1699  return INT_STATUS_SUCCESS;
1700 }
1701 
1702 
1703 static INTSTATUS
1705  _In_ PWIN_PROCESS_SUBSYSTEM Subsystem,
1706  _In_ QWORD VirtualBase
1707  )
1721 {
1722  LIST_ENTRY *list;
1723 
1724  list = Subsystem->ProcessModules.Flink;
1725  while (list != &Subsystem->ProcessModules)
1726  {
1728  list = list->Flink;
1729 
1730  if (pMod->VirtualBase == VirtualBase)
1731  {
1732  if ((pMod->Path->NameHash == NAMEHASH_NTDLL) &&
1733  (0 == wstrcasecmp(pMod->Path->Name, u"ntdll.dll")))
1734  {
1735  pMod->Subsystem->NtdllLoadCount--;
1736  }
1737  else if ((pMod->Path->NameHash == NAMEHASH_KERNEL32) &&
1738  (0 == wstrcasecmp(pMod->Path->Name, u"kernel32.dll")))
1739  {
1740  pMod->Subsystem->Kernel32LoadCount--;
1741  }
1742 
1743  pMod->Subsystem->LoadedModulesCount--;
1744 
1745  // Don't spam with the unload event.
1746 
1747  RemoveEntryList(&pMod->Link);
1748 
1749  IntWinModUnHookModule(pMod);
1750 
1751  IntWinModRemoveModule(pMod);
1752 
1753  return INT_STATUS_SUCCESS;
1754  }
1755  }
1756 
1758 }
1759 
1760 
1761 INTSTATUS
1763  _In_ PWIN_PROCESS_OBJECT Process,
1764  _In_ PVAD Vad
1765  )
1778 {
1780 
1781  if (NULL != Process->Subsystemx86)
1782  {
1783  status = IntWinModHandleUnload(Process->Subsystemx86, Vad->StartPage);
1784  if (INT_STATUS_SUCCESS == status)
1785  {
1786  return status;
1787  }
1788  }
1789 
1790  if (NULL != Process->Subsystemx64)
1791  {
1792  status = IntWinModHandleUnload(Process->Subsystemx64, Vad->StartPage);
1793  if (INT_STATUS_SUCCESS == status)
1794  {
1795  return status;
1796  }
1797  }
1798 
1799  return status;
1800 }
1801 
1802 
1803 static BOOLEAN
1805  _In_ QWORD Cr3,
1806  _In_ QWORD Address,
1807  _In_ void *Context
1808  )
1821 {
1822  PWIN_PROCESS_MODULE pMod;
1823 
1825 
1826  if (NULL == Context)
1827  {
1828  return FALSE;
1829  }
1830 
1831  pMod = (PWIN_PROCESS_MODULE)Context;
1832 
1833  // No cache, bail out, assuming the write is OK.
1834  if (NULL == pMod->Cache)
1835  {
1836  return TRUE;
1837  }
1838 
1839  if ((Address - pMod->VirtualBase >= pMod->Cache->Info.IatRva) &&
1840  (Address - pMod->VirtualBase < (QWORD)pMod->Cache->Info.IatRva + pMod->Cache->Info.IatSize))
1841  {
1842  // The write is inside the IAT, we can ignore it for now.
1843  return TRUE;
1844  }
1845 
1846  return FALSE;
1847 }
1848 
1849 
1850 static INTSTATUS
1852  _In_ PWIN_PROCESS_MODULE Module
1853  )
1864 {
1865  INTSTATUS status;
1866  PBYTE pPage;
1867  IMAGE_SECTION_HEADER *sec;
1868  DWORD i;
1869  PWIN_PROCESS_OBJECT pProc;
1870  INTRO_PE_INFO peInfo = { 0 };
1871 
1872  pPage = NULL;
1873 
1874  pProc = Module->Subsystem->Process;
1875 
1876  status = IntVirtMemMap(Module->VirtualBase, PAGE_SIZE, pProc->Cr3, 0, &pPage);
1877  if (!INT_SUCCESS(status))
1878  {
1879  ERROR("[ERROR] IntVirtMemMap failed: 0x%08x\n", status);
1880  return status;
1881  }
1882 
1883  status = IntPeValidateHeader(Module->VirtualBase, pPage, PAGE_SIZE, &peInfo, 0);
1884  if (!INT_SUCCESS(status))
1885  {
1886  ERROR("[ERROR] IntPeValidateHeader failed: 0x%08x\n", status);
1887  goto cleanup_and_exit;
1888  }
1889 
1890  Module->Size = peInfo.SizeOfImage;
1891 
1892  sec = (IMAGE_SECTION_HEADER *)(pPage + peInfo.SectionOffset);
1893  for (i = 0; i < peInfo.NumberOfSections; i++, sec++)
1894  {
1895  DWORD secsize = sec->Misc.VirtualSize;
1896 
1897  // Skip sections larger than 4 MB.
1898  if (secsize > 4 * ONE_MEGABYTE)
1899  {
1900  continue;
1901  }
1902 
1903  // Check if this is a code section.
1904  if ((sec->Characteristics & IMAGE_SCN_MEM_EXECUTE) ||
1907  {
1908  TRACE("[MODULE] Protecting pageable section: 0x%016llx, VA space 0x%016llx, length %x\n",
1909  Module->VirtualBase + sec->VirtualAddress, pProc->Cr3, secsize);
1910 
1911  for (DWORD j = 0; j < secsize; j += 0x1000)
1912  {
1913  status = IntUnpWatchPage(pProc->Cr3,
1914  Module->VirtualBase + sec->VirtualAddress + j,
1917  Module);
1918  if (!INT_SUCCESS(status))
1919  {
1920  ERROR("[ERROR] IntUnpWatchPage failed: 0x%08x\n", status);
1921  break;
1922  }
1923  }
1924  }
1925  }
1926 
1927 cleanup_and_exit:
1928  // The module may be partially protected against unpacking. This is not an issue, as the hooks will all be removed
1929  // when the process terminates (the unpacker works on a per/page basis). This only happens in case of errors.
1930  if (NULL != pPage)
1931  {
1932  IntVirtMemUnmap(&pPage);
1933  }
1934 
1935  return status;
1936 }
1937 
1938 
1939 INTSTATUS
1941  _In_ QWORD Cr3,
1942  _In_ QWORD VirtualAddress,
1943  _In_ PINSTRUX Instrux,
1944  _In_ void *Context
1945  )
1960 {
1961  INTSTATUS status;
1962  char text[ND_MIN_BUF_SIZE];
1963  PWIN_PROCESS_MODULE pMod;
1964 
1965  if (NULL == Instrux)
1966  {
1968  }
1969 
1970  if (NULL == Context)
1971  {
1973  }
1974 
1975  pMod = (PWIN_PROCESS_MODULE)Context;
1976 
1977  if (pMod->UnpackAlertSent)
1978  {
1979  return INT_STATUS_SUCCESS;
1980  }
1981 
1982  status = NdToText(Instrux, VirtualAddress, ND_MIN_BUF_SIZE, text);
1983  if (!INT_SUCCESS(status))
1984  {
1985  strlcpy(text, "INVALID", sizeof(text));
1986  }
1987 
1988  LOG("[ALERT] [UNPACK DETECTED] Unpacked/decrypted page detected @ 0x%016llx:0x%016llx: %s\n", VirtualAddress, Cr3,
1989  text);
1990 
1991  pMod->UnpackAlertSent = TRUE;
1992 
1993  // Send the unpacker notification
1994  if (TRUE)
1995  {
1996  PEVENT_EPT_VIOLATION pEptViol = &gAlert.Ept;
1997 
1998  memzero(pEptViol, sizeof(*pEptViol));
1999 
2000  pEptViol->Header.Action = introGuestAllowed;
2001  pEptViol->HookStartPhysical = 0;
2002  pEptViol->HookStartVirtual = VirtualAddress & PAGE_MASK;
2003  pEptViol->Offset = VirtualAddress & PAGE_OFFSET;
2004  pEptViol->Victim.Type = (Cr3 != 0) ? introObjectTypeUmUnpack : introObjectTypeKmUnpack;
2005  pEptViol->Violation = IG_EPT_HOOK_EXECUTE;
2006  pEptViol->VirtualPage = VirtualAddress & PAGE_MASK;
2007 
2008  pEptViol->Header.CpuContext.Cpu = gVcpu->Index;
2009  pEptViol->Header.CpuContext.Rip = VirtualAddress;
2010  pEptViol->Header.CpuContext.Cr3 = Cr3;
2011  memcpy(pEptViol->Header.CpuContext.Instruction, text, sizeof(pEptViol->Header.CpuContext.Instruction));
2012 
2013  pEptViol->ExecInfo.Length = Instrux->Length;
2014 
2016 
2017  pEptViol->Header.MitreID = idSoftwarePacking;
2018 
2020  pMod->Subsystem->Process, introReasonUnknown, 0);
2021 
2022  if (pMod->Subsystem->Process->SystemProcess)
2023  {
2024  pEptViol->Header.Flags |= ALERT_FLAG_SYSPROC;
2025  }
2026 
2027  IntAlertFillWinUmModule(pMod, &pEptViol->Victim.Module);
2028 
2029  IntAlertFillVersionInfo(&pEptViol->Header);
2030 
2031  status = IntNotifyIntroEvent(introEventEptViolation, pEptViol, sizeof(*pEptViol));
2032  if (!INT_SUCCESS(status))
2033  {
2034  WARNING("[WARNING] IntNotifyIntroEvent failed: 0x%08x\n", status);
2035  }
2036  }
2037 
2038  return INT_STATUS_SUCCESS;
2039 }
2040 
2041 
2042 INTSTATUS
2044  _In_ PWIN_PROCESS_MODULE Module
2045  )
2063 {
2064  INTSTATUS status;
2065 
2066  if (NULL == Module)
2067  {
2069  }
2070 
2071  // Remove any pending swap operation.
2072  if (NULL != Module->HeadersSwapHandle)
2073  {
2074  status = IntSwapMemRemoveTransaction(Module->HeadersSwapHandle);
2075  if (!INT_SUCCESS(status))
2076  {
2077  ERROR("[ERROR] IntSwapMemRemoveTransaction failed: 0x%08x\n", status);
2078  }
2079 
2080  Module->HeadersSwapHandle = NULL;
2081  }
2082 
2083  if (NULL != Module->ExportsSwapHandle)
2084  {
2085  status = IntSwapMemRemoveTransaction(Module->ExportsSwapHandle);
2086  if (!INT_SUCCESS(status))
2087  {
2088  ERROR("[ERROR] IntSwapMemRemoveTransaction failed: 0x%08x\n", status);
2089  }
2090 
2091  Module->ExportsSwapHandle = NULL;
2092  }
2093 
2094  if (NULL != Module->SlackSpaceSwapHandle)
2095  {
2096  status = IntSwapMemRemoveTransaction(Module->SlackSpaceSwapHandle);
2097  if (!INT_SUCCESS(status))
2098  {
2099  ERROR("[ERROR] IntSwapMemRemoveTransaction failed: 0x%08x\n", status);
2100  }
2101 
2102  Module->SlackSpaceSwapHandle = NULL;
2103  }
2104 
2105  if (NULL != Module->MainModHeadersSwapHandle)
2106  {
2107  status = IntSwapMemRemoveTransaction(Module->MainModHeadersSwapHandle);
2108  if (!INT_SUCCESS(status))
2109  {
2110  ERROR("[ERROR] IntSwapMemRemoveTransaction failed: 0x%08x\n", status);
2111  }
2112 
2113  Module->MainModHeadersSwapHandle = NULL;
2114  }
2115 
2116  IntWinUmModCacheRelease(Module->Cache);
2117 
2118  if (Module->IsMainModule)
2119  {
2120  IntWinUmPathDereference(&Module->Subsystem->Process->Path);
2121  Module->Subsystem->Process->MainModuleLoaded = FALSE;
2122  }
2123 
2124  IntWinUmPathDereference(&Module->Path);
2125 
2126  if (NULL != Module->IATBitmap)
2127  {
2128  HpFreeAndNullWithTag(&Module->IATBitmap, IC_TAG_IATB);
2129  }
2130 
2132 
2133  return INT_STATUS_SUCCESS;
2134 }
2135 
2136 
2137 void
2139  _In_ PWIN_PROCESS_SUBSYSTEM Subsystem
2140  )
2149 {
2150  PLIST_ENTRY pList;
2151 
2152  // we already have the list of modules, simply iterate it and change protection
2153  pList = Subsystem->ProcessModules.Flink;
2154  while (pList != &Subsystem->ProcessModules)
2155  {
2157 
2158  pList = pList->Flink;
2159 
2160  if (!pMod->IsSystemModule)
2161  {
2162  continue;
2163  }
2164 
2165  // If this is a 32-bit process on a 64-bit guest, we need to check if we have to update protection
2166  // for WoW64 modules
2167  if ((winSubsys64Bit == Subsystem->SubsystemType) && (Subsystem->Process->Wow64Process))
2168  {
2169  if (IntWinModIsProtected(pMod, gProtectedWowModules, ARRAYSIZE(gProtectedWowModules)))
2170  {
2171  if (pMod->ShouldProtHooks && !Subsystem->Process->ProtCoreModules)
2172  {
2173  TRACE("[WINMODULE] PROC_PROT_MASK_CORE_HOOKS enabled -> disabled for %s (Process %d)\n",
2174  utf16_for_log(pMod->Path->Path), Subsystem->Process->Pid);
2175  pMod->ShouldProtHooks = FALSE;
2176  }
2177  else if (!pMod->ShouldProtHooks && Subsystem->Process->ProtCoreModules)
2178  {
2179  TRACE("[WINMODULE] PROC_PROT_MASK_CORE_HOOKS disabled -> enabled for %s (Process %d)\n",
2180  utf16_for_log(pMod->Path->Path), Subsystem->Process->Pid);
2181  pMod->ShouldProtHooks = TRUE;
2182  }
2183  else
2184  {
2185  TRACE("[WINMODULE] PROC_PROT_MASK_CORE_HOOKS did not changed for %s (Process %d)\n",
2186  utf16_for_log(pMod->Path->Path), Subsystem->Process->Pid);
2187  }
2188  }
2189  }
2190  else
2191  {
2192  if (IntWinModIsProtected(pMod, gProtectedModules, ARRAYSIZE(gProtectedModules)))
2193  {
2194  if (pMod->ShouldProtHooks && !Subsystem->Process->ProtCoreModules)
2195  {
2196  TRACE("[WINMODULE] PROC_PROT_MASK_CORE_HOOKS enabled -> disabled for %s (Process %d)\n",
2197  utf16_for_log(pMod->Path->Path), Subsystem->Process->Pid);
2198  pMod->ShouldProtHooks = FALSE;
2199  }
2200  else if (!pMod->ShouldProtHooks && Subsystem->Process->ProtCoreModules)
2201  {
2202  TRACE("[WINMODULE] PROC_PROT_MASK_CORE_HOOKS disabled -> enabled for %s (Process %d)\n",
2203  utf16_for_log(pMod->Path->Path), Subsystem->Process->Pid);
2204  pMod->ShouldProtHooks = TRUE;
2205  }
2206  else
2207  {
2208  TRACE("[WINMODULE] PROC_PROT_MASK_CORE_HOOKS did not changed for %s (Process %d)\n",
2209  utf16_for_log(pMod->Path->Path), Subsystem->Process->Pid);
2210  }
2211  break;
2212  }
2213 
2214  if (IntWinModIsProtected(pMod, gProtectedNetModules, ARRAYSIZE(gProtectedNetModules)))
2215  {
2216  if (pMod->ShouldProtHooks && !Subsystem->Process->ProtWsockModules)
2217  {
2218  TRACE("[WINMODULE] PROC_PROT_MASK_WSOCK_HOOKS enabled -> disabled for %s (Process %d)\n",
2219  utf16_for_log(pMod->Path->Path), Subsystem->Process->Pid);
2220  pMod->ShouldProtHooks = FALSE;
2221  }
2222  else if (!pMod->ShouldProtHooks && Subsystem->Process->ProtWsockModules)
2223  {
2224  TRACE("[WINMODULE] PROC_PROT_MASK_WSOCK_HOOKS disabled -> enabled for %s (Process %d)\n",
2225  utf16_for_log(pMod->Path->Path), Subsystem->Process->Pid);
2226  pMod->ShouldProtHooks = TRUE;
2227  }
2228  else
2229  {
2230  TRACE("[WINMODULE] PROC_PROT_MASK_WSOCK_HOOKS did not changed for %s (Process %d)\n",
2231  utf16_for_log(pMod->Path->Path), Subsystem->Process->Pid);
2232  }
2233  break;
2234  }
2235  }
2236 
2237  // if this is the main module, check if unpack protection changed
2238  if (pMod->IsMainModule)
2239  {
2240  if (pMod->ShouldProtUnpack && !Subsystem->Process->ProtUnpack)
2241  {
2242  INTSTATUS status;
2243 
2244  TRACE("[WINMODULE] PROC_PROT_MASK_UNPACK enabled -> disabled for %s (Process %d). "
2245  "Unwatching VA space 0x%016llx...\n", utf16_for_log(pMod->Path->Path),
2246  Subsystem->Process->Pid, Subsystem->Process->Cr3);
2247 
2248  status = IntUnpUnWatchVaSpacePages(Subsystem->Process->Cr3);
2249  if (!INT_SUCCESS(status) && (INT_STATUS_NOT_FOUND != status))
2250  {
2251  ERROR("[ERROR] IntUnpUnWatchVaSpacePages failed: 0x%x\n", status);
2252  }
2253 
2254  pMod->ShouldProtUnpack = FALSE;
2255  }
2256  else if (!pMod->ShouldProtUnpack && Subsystem->Process->ProtUnpack)
2257  {
2258  INTSTATUS status;
2259 
2260  TRACE("[WINMODULE] PROC_PROT_MASK_UNPACK disabled -> enabled for %s (Process %d)\n",
2261  utf16_for_log(pMod->Path->Path), Subsystem->Process->Pid);
2262 
2263  status = IntWinModHookPoly(pMod);
2264  if (!INT_SUCCESS(status))
2265  {
2266  ERROR("[ERROR] IntWinModHookPoly failed: 0x%x\n", status);
2267  }
2268 
2269  pMod->ShouldProtUnpack = TRUE;
2270  }
2271  else
2272  {
2273  TRACE("[WINMODULE] PROC_PROT_MASK_UNPACK did not changed for %s (Process %d)\n",
2274  utf16_for_log(pMod->Path->Path), Subsystem->Process->Pid);
2275  }
2276  }
2277  // if this is not the main module, check it is hooked and should be unhooked (or the other way)
2278  else if ((pMod->ShouldProtHooks) && (!pMod->IsProtected))
2279  {
2280  INTSTATUS status;
2281 
2282  TRACE("[WINMODULE] Protecting module with base 0x%016llx -> 0x%016llx against hooking.\n",
2283  pMod->VirtualBase, Subsystem->Process->Cr3);
2284 
2285  status = IntWinModHookModule(pMod);
2286  if (!INT_SUCCESS(status))
2287  {
2288  ERROR("[ERROR] IntWinModHookModule failed for %s (Process %d): 0x%x\n",
2289  utf16_for_log(pMod->Path->Path), Subsystem->Process->Pid, status);
2290  }
2291  }
2292  else if ((!pMod->ShouldProtHooks) && (pMod->IsProtected))
2293  {
2294  TRACE("[WINMODULE] Removing protection for module with base 0x%016llx -> 0x%016llx\n",
2295  pMod->VirtualBase, Subsystem->Process->Cr3);
2296 
2297  IntWinModUnHookModule(pMod);
2298  }
2299  }
2300 }
2301 
2302 
2305  _In_ PWIN_PROCESS_OBJECT Process,
2306  _In_ QWORD Gva
2307  )
2318 {
2319  LIST_ENTRY *list;
2320 
2321  if (NULL != Process->Subsystemx64)
2322  {
2323  list = Process->Subsystemx64->ProcessModules.Flink;
2324  while (list != &Process->Subsystemx64->ProcessModules)
2325  {
2327  list = list->Flink;
2328 
2329  if (IN_RANGE_LEN(Gva, pMod->VirtualBase, pMod->Size))
2330  {
2331  return pMod;
2332  }
2333  }
2334  }
2335 
2336  if (NULL != Process->Subsystemx86)
2337  {
2338  list = Process->Subsystemx86->ProcessModules.Flink;
2339  while (list != &Process->Subsystemx86->ProcessModules)
2340  {
2342  list = list->Flink;
2343 
2344  if (IN_RANGE_LEN(Gva, pMod->VirtualBase, pMod->Size))
2345  {
2346  return pMod;
2347  }
2348  }
2349  }
2350 
2351  return NULL;
2352 }
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
PBYTE IATBitmap
A bitmap indicating which IAT entries have been initialized.
Definition: winummodule.h:66
struct _EVENT_EPT_VIOLATION::@284 Victim
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:1263
INTSTATUS IntPeGetSectionHeaderByRva(QWORD ImageBase, BYTE *ImageBaseBuffer, DWORD GuestRva, IMAGE_SECTION_HEADER *SectionHeader)
Given a relative virtual address, return the section header which describes the section the RVA lies ...
Definition: winpe.c:707
#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:77
static INTSTATUS IntWinModHookModule(PWIN_PROCESS_MODULE Module)
Hook a user-mode module against attacks.
Definition: winummodule.c:1079
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
uint8_t BYTE
Definition: intro_types.h:47
static INTSTATUS IntWinModFillDriverInjectionData(QWORD ReturnRip, EXCEPTION_KM_ORIGINATOR *Originator)
Fills the return driver data in the Originator when the write is caused by an injection which was mad...
Definition: winummodule.c:474
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:1265
#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:1199
#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
static INTSTATUS IntWinModFillInjectionData(EXCEPTION_KM_ORIGINATOR *Originator)
Fills the originating caller which led to the detected injection and respectively the current KM-UM w...
Definition: winummodule.c:579
DWORD ShouldProtHooks
TRUE if the module should be protected against hooks.
Definition: winummodule.h:42
WIN_KERNEL_DRIVER Win
Valid only for Windows guests.
Definition: drivers.h:70
#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:1395
DWORD HardwareEsp
Definition: wddefs.h:980
#define STATS_EXIT(id)
Definition: stats.h:160
#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:205
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:60
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:3247
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:250
#define IC_TAG_MODU
Loaded module.
Definition: memtags.h:15
QWORD BaseVa
The guest virtual address of the kernel module that owns this driver object.
Definition: drivers.h:41
QWORD HookStartPhysical
The start of the monitored guest physical memory area for which this alert was generated.
Definition: intro_types.h:1270
#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:342
#define INT_SUCCESS(Status)
Definition: introstatus.h:42
INTSTATUS IntWinThrGetCurrentThread(DWORD CpuNumber, QWORD *EthreadAddress)
Get the ETHREAD structure address of the thread currently running on the given CPU.
Definition: winthread.c:26
Event structure for module loading and unloading.
Definition: intro_types.h:1945
void IntWinModulesChangeProtectionFlags(PWIN_PROCESS_SUBSYSTEM Subsystem)
Change the protection flags applied to the process modules that are currently loaded.
Definition: winummodule.c:2138
QWORD Flags
A combination of ALERT_FLAG_* values describing the alert.
Definition: intro_types.h:1198
#define PROC_OPT_PROT_WSOCK_HOOKS
Blocks hooks being set on Wininet user-mode DLLs (Windows only).
Definition: intro_types.h:350
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:971
BOOLEAN FirstDominoJavaIgnored
TRUE if the first Domino Java execution VAD was ignored.
Definition: winprocess.h:195
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:1036
Windows process subsystem.
Definition: winprocess.h:54
DWORD UnpackProtected
TRUE if the main module has been protected against unpacks.
Definition: winprocess.h:133
PBYTE MzPeHeaders
The driver`s MZ/PE headers (cached internally).
Definition: windriver.h:34
Writes done from kernel mode over user mode.
Definition: stats.h:99
#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:994
#define MAX_IAT_ENTRIES
struct _EVENT_EPT_VIOLATION::@283 Originator
#define HpAllocWithTag(Len, Tag)
Definition: glue.h:516
INTSTATUS IntKernVirtMemFetchWordSize(QWORD GuestVirtualAddress, void *Data)
Reads a guest pointer from the guest kernel memory.
Definition: introcore.c:847
#define NAMEHASH_WININET
Definition: winummodule.h:21
int INTSTATUS
The status data type.
Definition: introstatus.h:24
struct _WINUM_MODULE_CACHE::@242 Info
INTSTATUS IntWinModPolyHandler(QWORD Cr3, QWORD VirtualAddress, PINSTRUX Instrux, void *Context)
Handle an unpack event for the indicated address.
Definition: winummodule.c:1940
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:1587
#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:1851
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:968
struct _WIN_PROCESS_MODULE * PWIN_PROCESS_MODULE
INTSTATUS IntWinModRemoveModule(PWIN_PROCESS_MODULE Module)
Removes a Windows module.
Definition: winummodule.c:2043
Describes a kernel-mode originator.
Definition: exceptions.h:943
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:855
DWORD Eip
Definition: wddefs.h:977
BOOLEAN UserMode
True if this is a user mode module, False if it is a kernel mode module.
Definition: intro_types.h:1952
BOOLEAN Kernel
This field is set to TRUE for a write due to an injection from kernel-mode.
Definition: exceptions.h:986
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:106
BOOLEAN IsDominoJava
True if this is a Java IBM process and j9jit.dll is loaded.
Definition: winprocess.h:194
QWORD HookStartVirtual
The start of the monitored guest virtual memory area for which this alert was generated.
Definition: intro_types.h:1268
EVENT_EPT_VIOLATION Ept
Definition: alerts.h:16
INTSTATUS IntWinModUnHookModule(PWIN_PROCESS_MODULE Module)
Remove the protection from the indicated module.
Definition: winummodule.c:1205
Process subsystem type 32 bit.
Definition: winprocess.h:34
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:130
#define LOG(fmt,...)
Definition: glue.h:61
Describes a kernel driver.
Definition: drivers.h:30
#define ALERT_FLAG_KM_UM
If set, the alert was generated by a kernel to user mode violation.
Definition: intro_types.h:687
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:125
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:1217
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:1070
DWORD NameHash
The hash of the name.
Definition: drivers.h:59
INTRO_ACTION_REASON Reason
The reason for which Action was taken.
Definition: intro_types.h:1195
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:76
#define INFO(fmt,...)
Definition: glue.h:59
Exposes the functions used to provide Windows Threads related support.
QWORD Cr3
Process PDBR. Includes PCID.
Definition: winprocess.h:98
DWORD MainModuleLoaded
TRUE if the main module has been loaded.
Definition: winprocess.h:132
BOOLEAN MainModuleLoaded
TRUE if the MainModule was loaded.
Definition: winprocess.h:72
Software Packing.
Definition: intro_types.h:1145
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:1704
#define _Inout_
Definition: intro_sal.h:20
User-mode unpacker.
Definition: intro_types.h:244
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:111
INTSTATUS IntKernVirtMemFetchDword(QWORD GuestVirtualAddress, DWORD *Data)
Reads 4 bytes from the guest kernel memory.
Definition: introcore.c:829
#define NAMEHASH_WS2_32
Definition: winummodule.h:20
#define INITIAL_CRC_VALUE
Definition: introdefs.h:221
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
BOOLEAN User
This field is set to TRUE for a write due to an injection from user-mode.
Definition: exceptions.h:985
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:241
size_t wstrlen(const WCHAR *str)
Definition: introcrt.c:1080
INTSTATUS IntKernVirtMemFetchQword(QWORD GuestVirtualAddress, QWORD *Data)
Reads 8 bytes from the guest kernel memory.
Definition: introcore.c:811
#define STATS_ENTER(id)
Definition: stats.h:153
INTRO_CPUCTX CpuContext
The context of the CPU that triggered the alert.
Definition: intro_types.h:1196
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:198
static QWORD IntWinModGetProtectionOptionForModule(WIN_PROCESS_MODULE *Module)
Get the protection options for provided module.
Definition: winummodule.c:391
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:290
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:166
CHAR Name[IMAGE_BASE_NAME_LEN]
Process base name.
Definition: winprocess.h:108
static void IntWinModCheckSpecialCases(PWIN_PROCESS_MODULE Module)
Check if the process is DominoJava process.
Definition: winummodule.c:224
QWORD Current
The currently used options.
Definition: guests.h:236
DWORD LoadedModulesCount
The number of modules that were loaded.
Definition: winprocess.h:62
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:1312
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:473
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:99
#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:73
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
#define EXCEPTION_KM_ORIGINATOR_OPT_FULL_STACK
Flag that can be passed to IntExceptKernelGetOriginator when the full stack is needed.
Definition: exceptions.h:1060
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:195
BOOLEAN IntWinVadIsInTree(const VAD *Vad)
Checks if a VAD is inserted in a guest VAD tree.
Definition: winvad.c:3437
#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:730
#define INTRO_OPT_EVENT_MODULES
Enable user mode and kernel mode module load and unload events (generates introEventModuleEvent event...
Definition: intro_types.h:445
INTSTATUS IntWinModHandleUnloadFromVad(PWIN_PROCESS_OBJECT Process, PVAD Vad)
Handle a module unload.
Definition: winummodule.c:1762
struct _WIN_PROCESS_OBJECT * Process
The process object related to this subsystem.
Definition: winprocess.h:56
union _IMAGE_SECTION_HEADER::@214 Misc
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:1309
BOOLEAN Loaded
True if the module was loaded, False if it was unloaded.
Definition: intro_types.h:1948
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:74
#define INT_STATUS_ALREADY_INITIALIZED_HINT
Definition: introstatus.h:323
BOOLEAN UninitPrepared
Definition: guests.h:320
#define WARNING(fmt,...)
Definition: glue.h:60
DWORD Pid
Process ID (the one used by Windows).
Definition: winprocess.h:100
Process subsystem type 64 bit.
Definition: winprocess.h:33
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:1154
#define PAGE_SIZE
Definition: common.h:70
Describes the modified zone.
Definition: exceptions.h:893
static BOOLEAN IntWinModWriteValidHandler(QWORD Cr3, QWORD Address, void *Context)
Checks if a write inside a code section is legitimate or not.
Definition: winummodule.c:1804
struct _EXCEPTION_KM_ORIGINATOR::@66 Injection
#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:43
uint16_t WCHAR
Definition: intro_types.h:63
#define WIN_KM_FIELD(Structure, Field)
Macro used to access kernel mode fields inside the WIN_OPAQUE_FIELDS structure.
Definition: winguest.h:740
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:344
static INTSTATUS IntWinModFillProcessInjectionData(QWORD CurrentThread, EXCEPTION_KM_ORIGINATOR *Originator)
Fills the originating process data in the Originator when the write is caused by an injection which w...
Definition: winummodule.c:531
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:1957
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:248
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:950
static INTSTATUS IntWinModIsKernelWriteInjection(EXCEPTION_KM_ORIGINATOR *Originator, BOOLEAN *IsInjection)
Verifies if the current KM-UM write is due to an injection.
Definition: winummodule.c:431
#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:1960
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:70
#define IC_TAG_IATB
IAT entries bitmap.
Definition: memtags.h:103
DWORD Offset
The offset inside the page where the violation took place.
Definition: intro_types.h:1274
__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:970
INTSTATUS IntWinModHandlePreInjection(void *Context, QWORD Cr3, QWORD VirtualAddress)
Module base page-fault pre-injection callback.
Definition: winummodule.c:1265
const PROTECTED_DLL_INFO gProtectedModules[]
Definition: winummodule.c:20
QWORD EprocessAddress
This will be the address of the ActiveProcess field.
Definition: winprocess.h:90
#define ALERT_FLAG_SYSPROC
If set, the alert is on system process.
Definition: intro_types.h:673
DWORD SystemProcess
TRUE if this is a system process.
Definition: winprocess.h:136
GUEST_STATE gGuest
The current guest state.
Definition: guests.c:50
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
INTRO_PROCESS Process
The process that did the malicious access.
Definition: intro_types.h:1223
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:89
#define INT_STATUS_STACK_SWAPPED_OUT
Indicates that the stack was needed in order to match the exceptions, but it is swapped out...
Definition: introstatus.h:465
PWIN_PROCESS_OBJECT IntWinProcFindObjectByEprocess(QWORD Eprocess)
Finds a process by the address of its _EPROCESS structure.
Definition: winprocesshp.c:96
WIN_SUBSYTEM_TYPE SubsystemType
Process subsystem type.
Definition: winprocess.h:57
struct _EXCEPTION_KM_ORIGINATOR::@64 Original
INTRO_ACTION Action
The action that was taken as the result of this alert.
Definition: intro_types.h:1194
int wstrcasecmp(const WCHAR *buf1, const WCHAR *buf2)
Definition: introcrt.c:98
INTSTATUS IntKernVirtMemRead(QWORD KernelGva, DWORD Length, void *Buffer, DWORD *RetLength)
Reads data from a guest kernel virtual memory range.
Definition: introcore.c:674
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:2304
KERNEL_DRIVER * IntDriverFindByAddress(QWORD Gva)
Returns the driver in which Gva resides.
Definition: drivers.c:164
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:1272
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:206
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:1197
Kernel-User mode exception.
Definition: exceptions.h:63
VCPU_STATE * gVcpu
The state of the current VCPU.
Definition: guests.c:59
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:1221
struct _EVENT_EPT_VIOLATION::@283::@288 Injection
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:1260
Event structure for EPT violations.
Definition: intro_types.h:1215
Execute-access hook.
Definition: glueiface.h:300
DWORD ProtWsockModules
Protect the Windows Socket related modules.
Definition: winprocess.h:208
INTSTATUS IntDetGetFunctionAddressByTag(DETOUR_TAG Tag, QWORD *FunctionAddress)
Get a detour function address by its tag.
Definition: detours.c:2144
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:1004
#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 PathHash
CRC32 hash value for the driver`s path.
Definition: windriver.h:25
DWORD IatRva
RVA of the imports table.
Definition: winumcache.h:87
void * Process
The process object from which the write originates. Valid only for KM-UM writes due to an injection o...
Definition: exceptions.h:971
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:61
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:734
#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
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:3357
BOOLEAN Protected
True if the module is protected.
Definition: intro_types.h:1950
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:1237
#define FALSE
Definition: intro_types.h:34
This structure describes a running process inside the guest.
Definition: winprocess.h:83
#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:33