Bitdefender Hypervisor Memory Introspection
winumdoubleagent.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 "winummoduleblock.h"
7 #include "alerts.h"
8 #include "guests.h"
9 #include "swapmem.h"
10 
11 
16 {
17  { u"ntdll.dll", NAMEHASH_NTDLL },
18  { u"kernel32.dll", NAMEHASH_KERNEL32 },
19  { u"verifier.dll", NAMEHASH_VERIFIER },
20  { u"apisetschema.dll", NAMEHASH_APISETSCHEMA },
21 };
22 
23 
24 static INTSTATUS
26  _In_ const WIN_PROCESS_MODULE *Module,
27  _In_opt_ const WIN_PROCESS_MODULE *ReturnModule,
28  _In_ INTRO_ACTION Action,
30  _In_ QWORD RetAddr
31  )
46 {
48  IMAGE_SECTION_HEADER sectionHeader;
50 
51  memzero(pModLoad, sizeof(*pModLoad));
52 
53  pModLoad->Header.Flags = IntAlertProcGetFlags(PROC_OPT_PROT_DOUBLE_AGENT, Module->Subsystem->Process, Reason, 0);
54  if (IntPolicyProcIsBeta(Module->Subsystem->Process, PROC_OPT_PROT_DOUBLE_AGENT))
55  {
56  pModLoad->Header.Flags |= ALERT_FLAG_BETA;
57  }
58 
59  pModLoad->Header.Action = Action;
60  pModLoad->Header.Reason = Reason;
61  pModLoad->Header.MitreID = idExecModLoad;
62 
65  IntAlertFillWinUmModule(Module, &pModLoad->Originator.Module);
66  IntAlertFillWinProcess(Module->Subsystem->Process, &pModLoad->Victim);
67  IntAlertFillWinUmModule(ReturnModule, &pModLoad->Originator.ReturnModule);
68 
69  pModLoad->ReturnRip = RetAddr;
70 
71  if (NULL != ReturnModule)
72  {
73  status = IntPeGetSectionHeaderByRva(ReturnModule->VirtualBase,
74  NULL,
75  (DWORD)(RetAddr - ReturnModule->VirtualBase),
76  &sectionHeader);
77  if (INT_SUCCESS(status))
78  {
79  memcpy(pModLoad->ReturnRipSectionName, sectionHeader.Name, sizeof(sectionHeader.Name));
80  }
81  }
82 
83  status = IntPeGetSectionHeaderByRva(Module->VirtualBase,
84  NULL,
85  (DWORD)(gVcpu->Regs.Rip - Module->VirtualBase),
86  &sectionHeader);
87  if (INT_SUCCESS(status))
88  {
89  memcpy(pModLoad->RipSectionName, sectionHeader.Name, sizeof(sectionHeader.Name));
90  }
91 
92  IntAlertFillVersionInfo(&pModLoad->Header);
93 
94  status = IntNotifyIntroEvent(introEventModuleLoadViolation, pModLoad, sizeof(*pModLoad));
95  if (!INT_SUCCESS(status))
96  {
97  ERROR("[ERROR] IntNotifyIntroEvent failed: 0x%08x\n", status);
98  }
99 
100  return status;
101 }
102 
103 
104 static INTSTATUS
106  _In_ WIN_PROCESS_MODULE *Module,
107  _In_opt_ const WIN_PROCESS_MODULE *ReturnModule,
108  _Out_ INTRO_ACTION *Action,
109  _In_ QWORD RetAddr
110  )
124 {
125  EXCEPTION_UM_ORIGINATOR originator = { 0 };
126  EXCEPTION_VICTIM_ZONE victim = { 0 };
127  INTSTATUS status;
128 
131 
133 
134  status = IntExceptUserGetOriginator(Module->Subsystem->Process,
135  TRUE,
136  Module->VirtualBase,
137  NULL,
138  &originator);
139  if (!INT_SUCCESS(status))
140  {
141  ERROR("[ERROR] Failed getting originator: 0x%08x\n", status);
142  goto _send_notification;
143  }
144 
145  status = IntExceptGetVictimProcess(Module->Subsystem->Process,
146  Module->VirtualBase,
147  1,
149  &victim);
150  if (!INT_SUCCESS(status))
151  {
152  ERROR("[ERROR] Failed getting modified zone: 0x%08x\n", status);
153  goto _send_notification;
154  }
155 
156  IntExcept(&victim, &originator, exceptionTypeUm, &action, &reason, introEventModuleLoadViolation);
157 
158 _send_notification:
160 
161  if (IntPolicyProcTakeAction(PROC_OPT_PROT_DOUBLE_AGENT, Module->Subsystem->Process, &action, &reason))
162  {
163  if (Module->DoubleAgentAlertSent)
164  {
165  goto _skip_send_nodification;
166  }
167 
168  IntWinProcSendAllDllEventsForProcess(Module->Subsystem->Process);
169 
170  LOG("[MODULE] Suspicious DLL '%s' loaded BEFORE kernel32 at %llx:%x!\n",
171  utf16_for_log(Module->Path->Path), Module->VirtualBase, Module->Size);
172 
173  status = IntWinDagentSendDoubleAgentAlert(Module, ReturnModule, action, reason, RetAddr);
174  if (!INT_SUCCESS(status))
175  {
176  WARNING("[WARNING] IntWinDagentSendDoubleAgentAlert failed: 0x%08x\n", status);
177  }
178 
179  Module->DoubleAgentAlertSent = TRUE;
180  }
181 
182 _skip_send_nodification:
183  *Action = action;
184 
185  IntPolicyProcForceBetaIfNeeded(PROC_OPT_PROT_DOUBLE_AGENT, Module->Subsystem->Process, Action);
186 
187  return status;
188 }
189 
190 
191 static INTSTATUS
193  _In_ void *Context,
194  _In_ QWORD Cr3,
195  _In_ QWORD VirtualAddress,
196  _In_ QWORD PhysicalAddress,
197  _In_reads_bytes_(DataSize) const BYTE *Data,
198  _In_ DWORD DataSize,
199  _In_ DWORD Flags
200  )
222 {
223  INTSTATUS status;
224  WIN_PROCESS_MODULE *pMod = Context;
225  DWORD addrSize;
226 
228  UNREFERENCED_PARAMETER(VirtualAddress);
229  UNREFERENCED_PARAMETER(PhysicalAddress);
231  UNREFERENCED_PARAMETER(DataSize);
232  UNREFERENCED_PARAMETER(Flags);
233 
235 
236  pMod->SlackSpaceSwapHandle = NULL;
237 
238  if (pMod->Subsystem->SubsystemType == winSubsys64Bit)
239  {
241  RTL_VERIFIER_DLL_DESCRIPTOR_64 atDlls = { 0 };
242  addrSize = 8;
243 
244  memzero(&tVpd, sizeof(tVpd));
245 
246  status = IntVirtMemWrite(pMod->SlackSpaceForVerifier,
248  pMod->Subsystem->Process->Cr3,
249  &atDlls);
250  if (!INT_SUCCESS(status))
251  {
252  ERROR("[ERROR] IntVirtMemWrite failed: 0x%08x\n", status);
253  goto _exit;
254  }
255 
258 
259  pMod->SlackSpaceForVerifier += sizeof(atDlls);
260 
261  status = IntVirtMemWrite(pMod->SlackSpaceForVerifier,
263  pMod->Subsystem->Process->Cr3,
264  &tVpd);
265  if (!INT_SUCCESS(status))
266  {
267  ERROR("[ERROR] IntVirtMemWrite failed: 0x%08x\n", status);
268  goto _exit;
269  }
270 
271  status = IntVirtMemWrite(pMod->AddressOfVerifierData,
272  addrSize,
273  pMod->Subsystem->Process->Cr3,
274  &pMod->SlackSpaceForVerifier);
275  if (!INT_SUCCESS(status))
276  {
277  ERROR("[ERROR] IntVirtMemWrite failed: 0x%08x\n", status);
278  goto _exit;
279  }
280  }
281  else
282  {
284  RTL_VERIFIER_DLL_DESCRIPTOR_32 atDlls = { 0 };
285  addrSize = 4;
286 
287  memzero(&tVpd, sizeof(tVpd));
288 
289  status = IntVirtMemWrite(pMod->SlackSpaceForVerifier,
291  pMod->Subsystem->Process->Cr3,
292  &atDlls);
293  if (!INT_SUCCESS(status))
294  {
295  ERROR("[ERROR] IntVirtMemWrite failed: 0x%08x\n", status);
296  goto _exit;
297  }
298 
301 
302  pMod->SlackSpaceForVerifier += sizeof(atDlls);
303 
304  status = IntVirtMemWrite(pMod->SlackSpaceForVerifier,
306  pMod->Subsystem->Process->Cr3,
307  &tVpd);
308  if (!INT_SUCCESS(status))
309  {
310  ERROR("[ERROR] IntVirtMemWrite failed: 0x%08x\n", status);
311  goto _exit;
312  }
313 
314  status = IntVirtMemWrite(pMod->AddressOfVerifierData,
315  addrSize,
316  pMod->Subsystem->Process->Cr3,
317  &pMod->SlackSpaceForVerifier);
318  if (!INT_SUCCESS(status))
319  {
320  ERROR("[ERROR] IntVirtMemWrite failed: 0x%08x\n", status);
321  }
322  }
323 
324 _exit:
326 
327  return INT_STATUS_SUCCESS;
328 }
329 
330 
331 static INTSTATUS
333  _In_ WIN_PROCESS_MODULE *Module,
334  _In_ void *BlockObject,
335  _In_ QWORD DllHandle,
336  _In_ QWORD Reason,
337  _In_ QWORD Reserved,
338  _In_ QWORD RetAddress,
339  _Inout_ INTRO_ACTION *Action
340  )
366 {
367  WIN_PROCESS_MODULE *pMod = Module;
368  WIN_PROCESS_MODULE *pReturnModule = NULL;
369  INTSTATUS status = INT_STATUS_SUCCESS;
370  INTSTATUS status2;
371 
372  UNREFERENCED_PARAMETER(BlockObject);
373 
374  // Skip processes with image from native subsystem
376  {
377  *Action = introGuestAllowed;
378  return INT_STATUS_SUCCESS;
379  }
380 
381  *Action = introGuestNotAllowed;
382 
383  pReturnModule = IntWinUmModFindByAddress(pMod->Subsystem->Process, RetAddress);
384  if (NULL == pReturnModule)
385  {
386  ERROR("[ERROR] Could not find a return module\n");
387  }
388 
389  if (!pMod->Subsystem->Process->IsVerifierLoaded)
390  {
391  pMod->SlackSpaceForVerifier = 0;
392  pMod->AddressOfVerifierData = 0;
393 
394  *Action = introGuestAllowed;
395 
396  return INT_STATUS_SUCCESS;
397  }
398 
399  // If all these are invalid, it means that something else than the entry point was called - just send alert
400  if (DllHandle == WINMODBLOCK_INVALID_VALUE &&
401  Reason == WINMODBLOCK_INVALID_VALUE &&
402  Reserved == WINMODBLOCK_INVALID_VALUE)
403  {
404  goto _check_exc_and_send_alert;
405  }
406 
407  LOG("[INFO] DllMain for %s called with Reason %lld\n", utf16_for_log(pMod->Path->Path), Reason);
408 
409  // Get the address of the structure which needs to be completed on verifier load
410  // (RTL_VERIFIER_PROVIDER_DESCRIPTOR, see Alex Ionescu's presentation "Esoteric Hooks"
411  // http://www.alex-ionescu.com/Estoteric%20Hooks.pdf for more details)
412  if (pMod->AddressOfVerifierData == 0 && Reason == DLL_VERIFIER_PROVIDER)
413  {
414  pMod->AddressOfVerifierData = Reserved;
415  }
416 
417  if (!Module->SlackSpaceForVerifier)
418  {
420  goto _check_exc_and_send_alert;
421  }
422 
423  if (NULL != pReturnModule &&
424  (pReturnModule->Path->NameHash != NAMEHASH_VERIFIER ||
425  0 != wstrcasecmp(pReturnModule->Path->Name, u"verifier.dll")) &&
427  {
428  TRACE("[INFO] Return module name for this exec: `%s` (%016llx) for process: `%s` PID: %d dll: `%s`\n",
429  utf16_for_log(pReturnModule->Path->Name),
430  RetAddress,
431  pMod->Subsystem->Process->Name,
432  pMod->Subsystem->Process->Pid,
433  utf16_for_log(pMod->Path->Path));
434  }
435 
436 _check_exc_and_send_alert:
437  if (!pMod->FirstDoubleAgentExecDone && Reason != DLL_VERIFIER_PROVIDER && !pMod->IsSuspicious)
438  {
439  *Action = introGuestAllowed;
440  return INT_STATUS_SUCCESS;
441  }
442 
443  status2 = IntWinDagentHandleDoubleAgent(Module, pReturnModule, Action, RetAddress);
444  if (!INT_SUCCESS(status2))
445  {
446  ERROR("[ERROR] IntWinDagentHandleDoubleAgent failed: 0x%08x\n", status2);
447  }
448 
449  return status;
450 }
451 
452 
453 static INTSTATUS
455  _Inout_ WIN_PROCESS_MODULE *Module,
456  _In_ BYTE *Headers
457  )
470 {
471  INTSTATUS status = INT_STATUS_SUCCESS;
472  const DWORD minRequiredSize = sizeof(RTL_VERIFIER_PROVIDER_DESCRIPTOR_64) + sizeof(RTL_VERIFIER_DLL_DESCRIPTOR_64);
473  const IMAGE_SECTION_HEADER *pSec = NULL;
474  const IMAGE_SECTION_HEADER *pNextSec = NULL;
475  DWORD sectionRva = 0;
476  DWORD sectionCount = 0;
477  BOOLEAN found = FALSE;
478 
480 
481  status = IntPeListSectionsHeaders(Module->VirtualBase, Headers, PAGE_SIZE, &sectionRva, &sectionCount);
482  if (!INT_SUCCESS(status))
483  {
484  ERROR("[ERROR] IntPeIterateSections failed with status: 0x%08x\n", status);
485  return status;
486  }
487 
488  pSec = (const IMAGE_SECTION_HEADER *)(Headers + sectionRva);
489  for (DWORD iSec = 0; iSec < sectionCount; iSec++, pSec++)
490  {
491  if ((QWORD)pSec->VirtualAddress + pSec->Misc.VirtualSize > Module->Vad->PageCount * PAGE_SIZE)
492  {
493  continue;
494  }
495 
496  if (!!(pSec->Characteristics & IMAGE_SCN_MEM_WRITE))
497  {
498  DWORD minSize = 0xFFFFFFFF;
499  BOOLEAN foundSec = FALSE;
500 
501  // We search for a section which has the most near RVA to our current RVA + size
502  // (considering it next section)
503  pNextSec = (const IMAGE_SECTION_HEADER *)(Headers + sectionRva);
504  for (DWORD iNextSec = 0; iNextSec < sectionCount; iNextSec++, pNextSec++)
505  {
506  if ((QWORD)pNextSec->VirtualAddress + pNextSec->Misc.VirtualSize > Module->Vad->PageCount * PAGE_SIZE)
507  {
508  continue;
509  }
510 
511  if ((pNextSec->VirtualAddress >= pSec->VirtualAddress + pSec->Misc.VirtualSize) &&
512  (pNextSec->VirtualAddress - pSec->VirtualAddress - pSec->Misc.VirtualSize) < minSize)
513  {
514  minSize = (pNextSec->VirtualAddress - pSec->VirtualAddress - pSec->Misc.VirtualSize);
515  foundSec = TRUE;
516  }
517  }
518 
519  // If we didn't find any section, we consider the space between end_section and end_module
520  if (!foundSec)
521  {
522  minSize = Module->Size - pSec->VirtualAddress - pSec->Misc.VirtualSize;
523  }
524 
525  if (minSize >= minRequiredSize)
526  {
527  found = TRUE;
528  break;
529  }
530  }
531  }
532 
533  if (found)
534  {
535  Module->SlackSpaceForVerifier = Module->VirtualBase + pSec->VirtualAddress + pSec->Misc.VirtualSize;
536  TRACE("[INFO] Found a good address 0x%016llx\n", Module->SlackSpaceForVerifier);
537  }
538 
539  if (!found && Module->IsSuspicious)
540  {
541  WARNING("[WARNING] Did not found a valid slack space for verifier address, "
542  "will kill process on first execution!\n");
543  }
544 
546 
547  return INT_STATUS_SUCCESS;
548 }
549 
550 
551 static INTSTATUS
553  _In_ WIN_PROCESS_MODULE *Module,
554  _In_ void *BlockObject,
555  _In_ QWORD DllHandle,
556  _In_ QWORD Reason,
557  _In_ QWORD Reserved,
558  _In_ QWORD RetAddress,
559  _In_ INTRO_ACTION *Action
560  )
589 {
590  INTSTATUS status = INT_STATUS_SUCCESS;
591 
592  UNREFERENCED_PARAMETER(BlockObject);
593  UNREFERENCED_PARAMETER(DllHandle);
594  UNREFERENCED_PARAMETER(Reserved);
595  UNREFERENCED_PARAMETER(RetAddress);
596 
597  if (Module->Subsystem->Process->ImageIsFromNativeSubsystem)
598  {
599  *Action = introGuestAllowed;
600  return INT_STATUS_SUCCESS;
601  }
602 
603  if (!Module->SlackSpaceForVerifier)
604  {
606  }
607 
608  // This is dll attach reason for verifier providers, where we have to trick verifier.dll that the suspicious dll
609  // loaded for that we write 2 structures in a well chosen place and then just return TRUE
610  if (DLL_VERIFIER_PROVIDER == Reason)
611  {
612  if (Module->FirstDoubleAgentExecDone)
613  {
614  // We have to retry execution as it is very possible that our swap-mem request didn't get handled on the
615  // last exit so retry until it is swapped in.
616  if (NULL != Module->SlackSpaceSwapHandle)
617  {
618  TRACE("[INFO] [DAGENT] Slack space not swapped-in yet, will retry.\n");
619  *Action = introGuestRetry;
620  }
621 
622  return status;
623  }
624 
625  Module->FirstDoubleAgentExecDone = TRUE;
626 
627  // Also put the flag SWAPMEM_OPT_RW_FAULT as we want to handle CoW on the slack space page
628  // Even if we have chosen a writable section, it can be copy on write - so before actually writing
629  // in that page, we force the copy on write by injecting a write page fault.
630  status = IntSwapMemReadData(Module->Subsystem->Process->Cr3,
631  Module->SlackSpaceForVerifier,
632  1,
634  Module,
635  0,
637  NULL,
638  &Module->SlackSpaceSwapHandle);
639  if (!INT_SUCCESS(status))
640  {
641  ERROR("[ERROR] IntSwapMemReadData failed: 0x%08x\n", status);
642  return status;
643  }
644 
645  *Action = introGuestRetry;
646  }
647  else
648  {
649  ERROR("[ERROR] IntWinDagentHandleVerifierReason called for reason %llu\n", Reason);
650  }
651 
652  return status;
653 }
654 
655 
656 static INTSTATUS
658  _In_ void *Context,
659  _In_ QWORD Cr3,
660  _In_ QWORD VirtualAddress,
661  _In_ QWORD PhysicalAddress,
662  _In_reads_bytes_(DataSize) BYTE *Data,
663  _In_ DWORD DataSize,
664  _In_ DWORD Flags
665  )
686 {
687  WIN_PROCESS_MODULE *pMod = Context;
688  INTRO_PE_INFO peInfo = { 0 };
689  INTSTATUS status = INT_STATUS_SUCCESS;
690 
692  UNREFERENCED_PARAMETER(VirtualAddress);
693  UNREFERENCED_PARAMETER(PhysicalAddress);
694  UNREFERENCED_PARAMETER(DataSize);
695  UNREFERENCED_PARAMETER(Flags);
696 
698 
699  pMod->MainModHeadersSwapHandle = NULL;
700 
701  status = IntPeValidateHeader(VirtualAddress, Data, DataSize, &peInfo, 0);
702  if (!INT_SUCCESS(status))
703  {
704  ERROR("[ERROR] IntPeValidateHeader failed: 0x%08x\n", status);
705  goto _exit;
706  }
707 
708  if (IMAGE_SUBSYSTEM_NATIVE == peInfo.Subsystem)
709  {
710  TRACE("[INFO] `%s` is from native subsystem, will skip double agent hooks\n", utf16_for_log(pMod->Path->Path));
712  }
713  else
714  {
715  TRACE("[INFO] `%s` is NOT from native subsystem. Subsystem flag = %d\n", utf16_for_log(pMod->Path->Path),
716  peInfo.Subsystem);
718  }
719 
720 _exit:
722 
723  return status;
724 }
725 
726 
727 static INTSTATUS
729  _Inout_ WIN_PROCESS_MODULE *Module,
730  _In_ const void *BlockObject
731  )
746 {
747  if (BlockObject != Module->ModBlockObject)
748  {
750  }
751 
752  Module->ModBlockObject = NULL;
753 
754  return INT_STATUS_SUCCESS;
755 }
756 
757 
758 static BOOLEAN
760  _In_ WIN_PROCESS_MODULE *Module
761  )
769 {
770  DWORD i;
771 
772  for (i = 0; i < ARRAYSIZE(gInitialDlls); i++)
773  {
774  if (Module->IsSystemModule && MODULE_MATCH(Module, &gInitialDlls[i]))
775  {
776  return TRUE;
777  }
778  }
779 
780  return FALSE;
781 }
782 
783 
784 INTSTATUS
786  _In_ WIN_PROCESS_MODULE *Module
787  )
811 {
812  INTSTATUS status;
813 
814  if (!Module->Subsystem->Process->ProtDoubleAgent)
815  {
817  }
818 
819  // Check if process image is from native subsystem
820  if (Module->IsMainModule)
821  {
822  status = IntSwapMemReadData(Module->Subsystem->Process->Cr3,
823  Module->VirtualBase,
824  PAGE_SIZE,
826  Module,
827  0,
830  &Module->MainModHeadersSwapHandle);
831  if (!INT_SUCCESS(status))
832  {
833  ERROR("[ERROR] IntSwapMemReadData failed: 0x%08x\n", status);
834  goto _clean_leave;
835  }
836  }
837 
838  if (Module->StaticScan)
839  {
841  }
842 
843  // we won't put our hooks if process image is from native subsystem
844  if (Module->Subsystem->Process->ImageIsFromNativeSubsystem)
845  {
847  }
848 
849  // We can skip 64 bit subsystem on wow processes.
850  if ((Module->Subsystem->SubsystemType == winSubsys64Bit) && Module->Subsystem->Process->Wow64Process)
851  {
853  }
854 
855  if ((0 == Module->VirtualBase) || (0 == Module->Size))
856  {
858  }
859 
860  if (Module->SuspChecked)
861  {
863  }
864 
865  if (Module->IsSystemModule && Module->Path->NameHash == NAMEHASH_VERIFIER)
866  {
867  Module->Subsystem->Process->IsVerifierLoaded = TRUE;
868  }
869 
870  // There is the case where gemmauf/other dependent kernel32 DLL
871  // are loaded before and we except them. They will load kernel32 just before the suspicious module is loaded.
872  // We will monitor all modules until DllMain is called and if the Reason is != 4 on the first call,
873  // we'll not consider them malicious.
874  // Also, we may have kernel32.dll with an incomplete path (so we can't verify it is a system
875  // module or not) thus the check for kernel32 load count becomes a bit problematic, as every DLL is marked as
876  // suspicious and is verified afterwards.
877  // We shall do the checks only if verifier is already loaded in the process, marking it as suspicious
878  // if there is no kernel32.dll loaded.
879  if (Module->Subsystem->Process->IsVerifierLoaded && !Module->IsMainModule && !IntWinDagentIsInitialDll(Module))
880  {
881  // We will monitor other modules if verifier is loaded
882  // but we'll consider them suspicious and "have a closer look" only if they are loaded before kernel32.dll
883  Module->IsSuspicious = !Module->Subsystem->Kernel32LoadCount;
884 
885  status = IntWinModBlockBlockModuleLoad(Module,
890  &Module->ModBlockObject);
891  if (!INT_SUCCESS(status))
892  {
893  ERROR("[ERROR] IntWinModBlockBlockModuleLoad failed: 0x%08x\n", status);
894  goto _clean_leave;
895  }
896 
897  status = IntWinModBlockRegisterCallbackForReason(Module->ModBlockObject,
900  if (!INT_SUCCESS(status))
901  {
902  ERROR("[ERROR] IntWinModBlockRegisterCallbackForReason failed: 0x%08x\n", status);
903 
904  status = IntWinModBlockRemoveBlockObject(Module->ModBlockObject);
905  if (!INT_SUCCESS(status))
906  {
907  ERROR("[ERROR] IntWinModBlockRemoveBlockObject failed: 0x%08x\n", status);
908  }
909  }
910  }
911 
912 _clean_leave:
913  Module->SuspChecked = TRUE;
914 
915  return INT_STATUS_SUCCESS;
916 }
WINUM_PATH * Path
Module path.
Definition: winummodule.h:62
#define _In_opt_
Definition: intro_sal.h:16
enum _INTRO_ACTION_REASON INTRO_ACTION_REASON
The reason for which an INTRO_ACTION was taken.
Execution through module load.
Definition: intro_types.h:1152
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
_Bool BOOLEAN
Definition: intro_types.h:58
#define _Out_
Definition: intro_sal.h:22
QWORD ReturnRip
The RIP from which the suspicious module was called.
Definition: intro_types.h:1853
static INTSTATUS IntWinModDagentSuspModCleanup(WIN_PROCESS_MODULE *Module, const void *BlockObject)
Callback which is called from module block mechanism before the object is destroyed.
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 IntWinDagentHandleSuspModExecution(WIN_PROCESS_MODULE *Module, void *BlockObject, QWORD DllHandle, QWORD Reason, QWORD Reserved, QWORD RetAddress, INTRO_ACTION *Action)
Callback for module block mechanism, being called whenever executions take place in the possible mali...
IG_ARCH_REGS Regs
The current state of the guest registers.
Definition: guests.h:95
#define _In_
Definition: intro_sal.h:21
MITRE_ID MitreID
The Mitre ID that corresponds to this attack.
Definition: intro_types.h:1199
#define INT_STATUS_SUCCESS
Definition: introstatus.h:54
Measures user mode exceptions checks.
Definition: stats.h:50
#define IMAGE_SUBSYSTEM_NATIVE
Definition: winpe.h:513
Do not unload the module.
static INTSTATUS IntWinDagentHandleDoubleAgent(WIN_PROCESS_MODULE *Module, const WIN_PROCESS_MODULE *ReturnModule, INTRO_ACTION *Action, QWORD RetAddr)
Handles a DoubleAgent module load.
#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
EVENT_MODULE_LOAD_VIOLATION ModuleLoad
Definition: alerts.h:32
User-mode exception.
Definition: exceptions.h:60
INTSTATUS IntWinModHandlePreInjection(void *Context, QWORD Cr3, QWORD VirtualAddress)
Module base page-fault pre-injection callback.
Definition: winummodule.c:1265
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
static BOOLEAN IntWinDagentIsInitialDll(WIN_PROCESS_MODULE *Module)
Check if a module is one of the modules listed in gInitialDlls.
#define IMAGE_SCN_MEM_WRITE
Definition: winpe.h:474
#define INT_SUCCESS(Status)
Definition: introstatus.h:42
DWORD IsSuspicious
TRUE if the module is suspicious.
Definition: winummodule.h:51
QWORD Flags
A combination of ALERT_FLAG_* values describing the alert.
Definition: intro_types.h:1198
#define WINMODBLOCK_INVALID_VALUE
DllHandle, Reason and Reserved can be equal to WINMODBLOCK_INVALID_VALUE when something that is not t...
#define ARRAYSIZE(A)
Definition: introdefs.h:101
INTSTATUS IntVirtMemWrite(QWORD Gva, DWORD Length, QWORD Cr3, void *Buffer)
Writes data to a guest virtual memory range.
Definition: introcore.c:652
INTRO_MODULE Module
The loaded module.
Definition: intro_types.h:1846
#define INT_STATUS_NOT_NEEDED_HINT
Definition: introstatus.h:317
#define ERROR(fmt,...)
Definition: glue.h:62
Describes a user-mode originator.
Definition: exceptions.h:994
WORD Subsystem
Subsystem.
Definition: winpe.h:597
int INTSTATUS
The status data type.
Definition: introstatus.h:24
BOOLEAN ImageIsFromNativeSubsystem
TRUE if the process image is from the native subsystem.
Definition: winprocess.h:268
BOOLEAN FirstDoubleAgentExecDone
A flag which is set in order to verify if the first execution (for init phase) is done on double agen...
Definition: winummodule.h:80
void IntAlertFillCpuContext(BOOLEAN CopyInstruction, INTRO_CPUCTX *CpuContext)
Fills the current CPU context for an alert.
Definition: alerts.c:492
Verifier provider initialization structures for 64-bit processes.
Definition: wddefs.h:1841
static INTSTATUS IntWinDagentHandleSlackWritable(void *Context, QWORD Cr3, QWORD VirtualAddress, QWORD PhysicalAddress, const BYTE *Data, DWORD DataSize, DWORD Flags)
Swapmem callback which is called when the desired area between suspicious module section was swapped-...
BOOLEAN IntPolicyProcIsBeta(const void *Process, QWORD Flag)
Checks if a process protection policy is in log-only mode.
Definition: introcore.c:2569
#define LOG(fmt,...)
Definition: glue.h:61
Verifier provider initialization structures for 64-bit processes.
Definition: wddefs.h:1870
void IntAlertFillVersionInfo(INTRO_VIOLATION_HEADER *Header)
Fills version information for an alert.
Definition: alerts.c:327
QWORD IntAlertProcGetFlags(QWORD ProtectionFlag, const void *Process, INTRO_ACTION_REASON Reason, QWORD AdditionalFlags)
Returns the flags for an alert.
Definition: alerts.c:425
INTRO_ACTION_REASON Reason
The reason for which Action was taken.
Definition: intro_types.h:1195
QWORD SlackSpaceForVerifier
The address between sections on which we put the needed verifier structure on double agent...
Definition: winummodule.h:75
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
#define NAMEHASH_NTDLL
Definition: winummodule.h:11
INTRO_PROCESS Victim
The process in which the module has loaded.
Definition: intro_types.h:1842
QWORD Cr3
Process PDBR. Includes PCID.
Definition: winprocess.h:98
#define ALERT_FLAG_BETA
If set, the alert is a BETA alert. No action was taken.
Definition: intro_types.h:671
INTSTATUS IntWinDagentCheckSuspiciousDllLoad(WIN_PROCESS_MODULE *Module)
Checks if the given module is suspicious of loading through the double agent technique and calls the ...
GENERIC_ALERT gAlert
Global alert buffer.
Definition: alerts.c:27
#define _Inout_
Definition: intro_sal.h:20
struct _RTL_VERIFIER_PROVIDER_DESCRIPTOR_32 RTL_VERIFIER_PROVIDER_DESCRIPTOR_32
Verifier provider initialization structures for 32-bit processes.
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
#define INT_STATUS_NOT_INITIALIZED
Definition: introstatus.h:266
#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
INTSTATUS IntNotifyIntroEvent(INTRO_EVENT_TYPE EventClass, void *Param, size_t EventSize)
Notifies the integrator about an introspection alert.
Definition: glue.c:1042
#define memzero(a, s)
Definition: introcrt.h:35
unsigned long long QWORD
Definition: intro_types.h:53
CHAR Name[IMAGE_BASE_NAME_LEN]
Process base name.
Definition: winprocess.h:108
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
Event structure for suspicious module load into processes.
Definition: intro_types.h:1838
Sent for suspicious module loads alerts. See EVENT_MODULE_LOAD_VIOLATION.
Definition: intro_types.h:117
#define SWAPMEM_OPT_RW_FAULT
If set, the PF will be generated with write access. Useful when CoW must be done. ...
Definition: swapmem.h:29
#define TRUE
Definition: intro_types.h:30
UINT32 VirtualAddress
Definition: winpe.h:85
void * SlackSpaceSwapHandle
Swap handle for the slack space page where we put verifier structures.
Definition: winummodule.h:82
#define TRACE(fmt,...)
Definition: glue.h:58
#define NAMEHASH_APISETSCHEMA
Definition: winummodule.h:24
const PROTECTED_DLL_INFO gInitialDlls[]
#define INT_STATUS_INVALID_INTERNAL_STATE
Definition: introstatus.h:272
CHAR RipSectionName[ALERT_MAX_SECTION_NAME_LEN]
The name of the section in which the function executed by the loaded module is found.
Definition: intro_types.h:1859
void IntAlertFillWinProcessCurrent(INTRO_PROCESS *EventProcess)
Saves information about the current Windows process inside an alert.
Definition: alerts.c:781
void * MainModHeadersSwapHandle
Needed for verifying if the process main module is from the Native subsystem or not (e...
Definition: winummodule.h:86
struct _WIN_PROCESS_OBJECT * Process
The process object related to this subsystem.
Definition: winprocess.h:56
union _IMAGE_SECTION_HEADER::@214 Misc
#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.
#define PAGE_SIZE
Definition: common.h:70
static INTSTATUS IntWinDagentHandleSuspModHeaders(WIN_PROCESS_MODULE *Module, BYTE *Headers)
Callback called through module block mechanism when the suspicious module headers are in memory...
Describes the modified zone.
Definition: exceptions.h:893
#define UNREFERENCED_PARAMETER(P)
Definition: introdefs.h:29
DWORD NameHash
The CRC32 hash of the name. Used for fast matching.
Definition: winumpath.h:23
uint32_t DWORD
Definition: intro_types.h:49
UINT32 VirtualSize
Definition: winpe.h:83
UINT32 Characteristics
Definition: winpe.h:92
INTSTATUS IntPeValidateHeader(QWORD ImageBase, BYTE *ImageBaseBuffer, DWORD ImageBaseBufferSize, INTRO_PE_INFO *PeInfo, QWORD Cr3)
Validates a PE header.
Definition: winpe.c:131
Verifier provider initialization structures for 32-bit processes.
Definition: wddefs.h:1830
enum _INTRO_ACTION INTRO_ACTION
Event actions.
INTSTATUS IntWinProcSendAllDllEventsForProcess(PWIN_PROCESS_OBJECT Process)
Send DLL load events for all modules loaded in all subsystems of a process.
Definition: winummodule.c:198
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 _In_reads_bytes_(expr)
Definition: intro_sal.h:25
#define NAMEHASH_VERIFIER
Definition: winummodule.h:23
#define PROC_OPT_PROT_DOUBLE_AGENT
Blocks double agent attacks (malicious DLL loading) (Windows only).
Definition: intro_types.h:362
struct _RTL_VERIFIER_PROVIDER_DESCRIPTOR_64 RTL_VERIFIER_PROVIDER_DESCRIPTOR_64
Verifier provider initialization structures for 64-bit processes.
WCHAR * Name
The name of the module contained in the path.
Definition: winumpath.h:18
INTRO_MODULE ReturnModule
The module which called the entry function of the suspicious module.
Definition: intro_types.h:1847
#define DLL_VERIFIER_PROVIDER
Definition: wddefs.h:1890
INTSTATUS IntExceptGetVictimProcess(void *Process, QWORD DestinationGva, DWORD Length, QWORD ZoneFlags, EXCEPTION_VICTIM_ZONE *Victim)
This function is used to get the information about the victim process for injection violations...
Exposes the types, constants and functions needed to block Windows module loads (used to block double...
WIN_SUBSYTEM_TYPE SubsystemType
Process subsystem type.
Definition: winprocess.h:57
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
Verifier provider initialization structures for 32-bit processes.
Definition: wddefs.h:1852
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
static INTSTATUS IntWinDagentCheckNativeSubsystem(void *Context, QWORD Cr3, QWORD VirtualAddress, QWORD PhysicalAddress, BYTE *Data, DWORD DataSize, DWORD Flags)
Swapmem callback for the main module headers of the possible affected process.
BOOLEAN IsVerifierLoaded
TRUE if app verifier is loaded.
Definition: winprocess.h:269
INTRO_PROCESS CurrentProcess
The current process.
Definition: intro_types.h:1197
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
UINT8 Name[IMAGE_SIZEOF_SHORT_NAME]
Definition: winpe.h:79
struct _EVENT_MODULE_LOAD_VIOLATION::@319 Originator
Measures module load violation handling.
Definition: stats.h:37
INTSTATUS IntWinModBlockBlockModuleLoad(WIN_PROCESS_MODULE *Module, WIN_MOD_BLOCK_FLAG Flags, PFUNC_IntWinModBlockCallback Callback, PFUNC_IntWinModBlockHeadersCallback HeadersCallback, PFUNC_IntWinModBlockCleanup CleanupCallback, void **BlockObject)
This function is invoked when a suspicious dll is loaded in order to analyze and block the dll load i...
PWIN_PROCESS_SUBSYSTEM Subsystem
Module subsystem.
Definition: winummodule.h:60
INTSTATUS IntWinModBlockRegisterCallbackForReason(void *BlockObject, DWORD Reason, PFUNC_IntWinModBlockCallback Callback)
Registers a callback that is invoked when the blocked module&#39;s DllMain function is called with a give...
#define NAMEHASH_KERNEL32
Definition: winummodule.h:12
CHAR ReturnRipSectionName[ALERT_MAX_SECTION_NAME_LEN]
The name of the section in which ReturnRip resides.
Definition: intro_types.h:1856
QWORD AddressOfVerifierData
The address received by DllMain where the pointer to verifier structure should be put...
Definition: winummodule.h:77
#define ZONE_MODULE_LOAD
Used for exceptions for double agent.
Definition: exceptions.h:731
#define ZONE_WRITE
Used for write violation.
Definition: exceptions.h:734
static INTSTATUS IntWinDagentHandleVerifierReason(WIN_PROCESS_MODULE *Module, void *BlockObject, QWORD DllHandle, QWORD Reason, QWORD Reserved, QWORD RetAddress, INTRO_ACTION *Action)
Called by the module block mechanism when DllMain was called with a specific Reason, DLL_VERIFIER_PROVIDER in this case.
#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
static INTSTATUS IntWinDagentSendDoubleAgentAlert(const WIN_PROCESS_MODULE *Module, const WIN_PROCESS_MODULE *ReturnModule, INTRO_ACTION Action, INTRO_ACTION_REASON Reason, QWORD RetAddr)
Sends a DoubleAgent alert.
INTRO_VIOLATION_HEADER Header
The alert header.
Definition: intro_types.h:1840
INTSTATUS IntWinModBlockRemoveBlockObject(void *BlockObject)
This function is used in order to destroy a WIN_MOD_BLOCK_OBJECT structure.
#define FALSE
Definition: intro_types.h:34
WCHAR * Path
The string which represents the user-mode module path.
Definition: winumpath.h:17