Bitdefender Hypervisor Memory Introspection
hnd_remediation.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020 Bitdefender
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 #include "hnd_remediation.h"
6 #include "alerts.h"
7 #include "guests.h"
8 
9 
12  _In_opt_ void *Reserved,
13  _In_ PIG_ARCH_REGS Registers
14  )
29 {
30  INTSTATUS status;
31  QWORD dataAddr;
32  DWORD retLen;
33  PEVENT_AGENT_EVENT agentEvent;
35 
36  UNREFERENCED_PARAMETER(Reserved);
37 
38  if (NULL == Registers)
39  {
41  }
42 
43  retLen = 0;
44  agentEvent = &gAlert.Agent;
45  memset(agentEvent, 0, sizeof(*agentEvent));
46  memset(&header, 0, sizeof(header));
47 
48  // Data address will be in RCX on x64 and ESI on x86.
49  dataAddr = gGuest.Guest64 ? Registers->Rbx : (Registers->Rsi & 0xFFFFFFFF);
50 
51  if (0 == dataAddr)
52  {
53  ERROR("[ERROR] Data address is 0!\n");
54  return INT_STATUS_NOT_FOUND;
55  }
56 
57  // Read the event structure.
59  agentEvent->Event = agentMessage;
60  agentEvent->ErrorCode = 0;
61 
63  {
65  }
66  else if (gGuest.OSType == introGuestLinux)
67  {
69  }
70  else
71  {
73  }
74 
75  // Pause the VCPUs while we read.
76  IntPauseVcpus();
77 
78  status = IntVirtMemRead(dataAddr, sizeof(AGENT_REM_EVENT_HEADER), Registers->Cr3, &header, &retLen);
79  if (!INT_SUCCESS(status))
80  {
81  ERROR("[ERROR] IntVirtMemRead failed: 0x%08x\n", status);
82  goto resume_and_exit;
83  }
84 
85  if (header.Version != REM_EVENT_VERSION)
86  {
87  ERROR("[ERROR] Version mismatch: %x (read) vs %x (known).\n", header.Version, REM_EVENT_VERSION);
88  status = INT_STATUS_NOT_SUPPORTED;
89  goto resume_and_exit;
90  }
91 
92  if (header.Size != REM_EVENT_SIZE)
93  {
94  ERROR("[ERROR] Size mismatch: %d (read) vs %lu (known).\n", header.Size, REM_EVENT_SIZE);
95  status = INT_STATUS_NOT_SUPPORTED;
96  goto resume_and_exit;
97  }
98 
99  status = IntVirtMemRead(dataAddr, sizeof(AGENT_REM_EVENT), Registers->Cr3, &agentEvent->RemediationEvent, &retLen);
100  if (!INT_SUCCESS(status))
101  {
102  ERROR("[ERROR] IntVirtMemRead failed: 0x%08x\n", status);
103  goto resume_and_exit;
104  }
105 
106  if (retLen != sizeof(AGENT_REM_EVENT))
107  {
108  ERROR("[ERROR] Read only %d bytes, needed %zu!\n", retLen, sizeof(AGENT_REM_EVENT));
110  goto resume_and_exit;
111  }
112 
113  // Log
114  switch (agentEvent->RemediationEvent.Header.EventType)
115  {
116  case remEventDetection:
117  TRACE("[REMTOOL] Detection: %s infected with %s, flags %d\n",
118  utf16_for_log(agentEvent->RemediationEvent.DetectionEvent.ObjectPath),
119  utf16_for_log(agentEvent->RemediationEvent.DetectionEvent.Detection),
120  agentEvent->RemediationEvent.DetectionEvent.DetectionFlag);
121  break;
123  TRACE("[REMTOOL] Disinfection: %s infected with %s, status %d\n",
124  utf16_for_log(agentEvent->RemediationEvent.DetectionEvent.ObjectPath),
125  utf16_for_log(agentEvent->RemediationEvent.DetectionEvent.Detection),
126  agentEvent->RemediationEvent.DetectionEvent.ActionResult);
127  break;
128  case remEventStart:
129  TRACE("[REMTOOL] Scan start: %d\n",
130  agentEvent->RemediationEvent.StartEvent.ScanStatus);
131  break;
132  case remEventFinish:
133  TRACE("[REMTOOL] Scan finish: %d\n",
134  agentEvent->RemediationEvent.FinishEvent.ScanResult);
135  break;
136  case remEventProgress:
137  TRACE("[REMTOOL] Progress: %d\n",
138  agentEvent->RemediationEvent.ProgressEvent.Progress);
139  break;
140  case remEventReboot:
141  TRACE("[REMTOOL] Reboot: %d\n",
142  agentEvent->RemediationEvent.RebootEvent.RebootNeeded);
143  break;
144  default:
145  TRACE("Unknown event: %d\n", agentEvent->RemediationEvent.Header.EventType);
146  }
147 
148  status = INT_STATUS_SUCCESS;
149 
150 resume_and_exit:
151  IntResumeVcpus();
152 
153  if (INT_SUCCESS(status))
154  {
155  status = IntNotifyIntroEvent(introEventAgentEvent, agentEvent, sizeof(*agentEvent));
156  if (!INT_SUCCESS(status))
157  {
158  ERROR("[ERROR] IntNotifyIntroEvent failed: 0x%08x\n", status);
159  return status;
160  }
161  }
162 
163  return status;
164 }
#define _In_opt_
Definition: intro_sal.h:16
DWORD Version
Event version. Must match REM_EVENT_VERSION.
Definition: intro_types.h:2160
Start event.
Definition: intro_types.h:2136
Disinfection event.
Definition: intro_types.h:2138
#define _In_
Definition: intro_sal.h:21
#define INT_STATUS_SUCCESS
Definition: introstatus.h:54
Detection event.
Definition: intro_types.h:2137
Stop event.
Definition: intro_types.h:2141
Reboot event.
Definition: intro_types.h:2140
AGENT_EVENT_TYPE Event
The type of the agent.
Definition: intro_types.h:2347
#define REM_EVENT_SIZE
Remediation event size.
Definition: intro_types.h:2152
#define INT_SUCCESS(Status)
Definition: introstatus.h:42
struct _AGENT_REM_EVENT::@325::@328 FinishEvent
Finish event. Valid if Header.EventType is remEventFinish.
INTSTATUS IntResumeVcpus(void)
Resumes the VCPUs previously paused with IntPauseVcpus.
Definition: introcore.c:2355
Event structure for agent injection and termination.
Definition: intro_types.h:2345
The remediation tool agent.
Definition: glueiface.h:341
#define ERROR(fmt,...)
Definition: glue.h:62
int INTSTATUS
The status data type.
Definition: introstatus.h:24
#define INT_STATUS_NOT_FOUND
Definition: introstatus.h:284
INTRO_PROCESS CurrentProcess
The agent process.
Definition: intro_types.h:2355
INTSTATUS IntPauseVcpus(void)
Pauses all the guest VCPUs.
Definition: introcore.c:2320
INTRO_GUEST_TYPE OSType
The type of the guest.
Definition: guests.h:278
DWORD ErrorCode
The error code of the event. Success is 0.
Definition: intro_types.h:2349
INTSTATUS IntAgentHandleRemediationVmcall(void *Reserved, PIG_ARCH_REGS Registers)
Handle a VMCALL issued by a remediation agent.
GENERIC_ALERT gAlert
Global alert buffer.
Definition: alerts.c:27
A remediation tool event.
Definition: intro_types.h:2172
#define REM_EVENT_VERSION
Remediation event version.
Definition: intro_types.h:2150
INTSTATUS IntNotifyIntroEvent(INTRO_EVENT_TYPE EventClass, void *Param, size_t EventSize)
Notifies the integrator about an introspection alert.
Definition: glue.c:1042
BOOLEAN Guest64
True if this is a 64-bit guest, False if it is a 32-bit guest.
Definition: guests.h:290
unsigned long long QWORD
Definition: intro_types.h:53
struct _AGENT_REM_EVENT::@325::@331 DetectionEvent
Detection event. Valid if Header.EventType is remEventDetection.
Informational event sent when the remediation tool is injected or terminated. See EVENT_AGENT_EVENT...
Definition: intro_types.h:104
#define TRACE(fmt,...)
Definition: glue.h:58
DWORD AgentTag
Unique agent tag. See INTRO_DEP_AG_TAGS.
Definition: intro_types.h:2348
void IntAlertFillWinProcessCurrent(INTRO_PROCESS *EventProcess)
Saves information about the current Windows process inside an alert.
Definition: alerts.c:781
struct _AGENT_REM_EVENT::@325::@330 RebootEvent
Reboot event. Valid if Header.EventType is remEventReboot.
#define UNREFERENCED_PARAMETER(P)
Definition: introdefs.h:29
The agent sent a message.
Definition: intro_types.h:2103
EVENT_AGENT_EVENT Agent
Definition: alerts.h:29
uint32_t DWORD
Definition: intro_types.h:49
struct _AGENT_REM_EVENT::@325::@329 ProgressEvent
Progress event. Valid if Header.EventType is remEventProgress.
Common header for all remediation tool events.
Definition: intro_types.h:2158
GUEST_STATE gGuest
The current guest state.
Definition: guests.c:50
INTSTATUS IntVirtMemRead(QWORD Gva, DWORD Length, QWORD Cr3, void *Buffer, DWORD *RetLength)
Reads data from a guest virtual memory range.
Definition: introcore.c:627
DWORD Size
Event size. Must match REM_EVENT_SIZE.
Definition: intro_types.h:2161
Progress report event.
Definition: intro_types.h:2139
AGENT_REM_EVENT_HEADER Header
Event header.
Definition: intro_types.h:2174
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 INT_STATUS_NOT_SUPPORTED
Definition: introstatus.h:287
Holds register state.
Definition: glueiface.h:30
struct _AGENT_REM_EVENT::@325::@327 StartEvent
Start event. Valid if Header.EventType is remEventStart.
void IntAlertFillLixCurrentProcess(INTRO_PROCESS *EventProcess)
Saves the current Linux process inside an event.
Definition: alerts.c:1310
AGENT_REM_EVENT RemediationEvent
Remediation tool event.
Definition: intro_types.h:2365
AGENT_REM_EVENT_TYPE EventType
Event type.
Definition: intro_types.h:2163
#define INT_STATUS_INVALID_DATA_SIZE
Definition: introstatus.h:142
#define INT_STATUS_INVALID_PARAMETER_3
Definition: introstatus.h:68