Bitdefender Hypervisor Memory Introspection
hnd_loggather.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_loggather.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 RBX 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_LGT_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 != LGT_EVENT_VERSION)
86  {
87  ERROR("[ERROR] Version mismatch: %x (read) vs %x (known).\n", header.Version, LGT_EVENT_VERSION);
88  status = INT_STATUS_NOT_SUPPORTED;
89  goto resume_and_exit;
90  }
91 
92  if (header.Size != LGT_EVENT_SIZE)
93  {
94  ERROR("[ERROR] Size mismatch: %d (read) vs %lu (known).\n", header.Size, LGT_EVENT_SIZE);
95  status = INT_STATUS_NOT_SUPPORTED;
96  goto resume_and_exit;
97  }
98 
99  status = IntVirtMemRead(dataAddr, sizeof(AGENT_LGT_EVENT), Registers->Cr3, &agentEvent->LogGatherEvent, &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_LGT_EVENT))
107  {
108  ERROR("[ERROR] Read only %d bytes, needed %zu!\n", retLen, sizeof(AGENT_LGT_EVENT));
110  goto resume_and_exit;
111  }
112 
113  // Log
114  switch (header.EventType)
115  {
116  case lgtEventData:
117  TRACE("[LOGTOOL] Data from %s: %d bytes\n",
118  utf16_for_log(agentEvent->LogGatherEvent.DataEvent.FileName),
119  agentEvent->LogGatherEvent.DataEvent.DataSize);
120  break;
121  case lgtEventError:
122  TRACE("[LOGTOOL] Error: 0x%08x\n", agentEvent->LogGatherEvent.ErrorEvent.ErrorCode);
123  break;
124  }
125 
126  status = INT_STATUS_SUCCESS;
127 
128 resume_and_exit:
129  IntResumeVcpus();
130 
131  if (INT_SUCCESS(status))
132  {
133  status = IntNotifyIntroEvent(introEventAgentEvent, agentEvent, sizeof(*agentEvent));
134  if (!INT_SUCCESS(status))
135  {
136  ERROR("[ERROR] IntNotifyIntroEvent failed: 0x%08x\n", status);
137  return status;
138  }
139  }
140 
141  return status;
142 }
#define _In_opt_
Definition: intro_sal.h:16
struct _AGENT_LGT_EVENT::@333::@335 DataEvent
Collected data.
#define _In_
Definition: intro_sal.h:21
Error event.
Definition: intro_types.h:2241
#define INT_STATUS_SUCCESS
Definition: introstatus.h:54
AGENT_EVENT_TYPE Event
The type of the agent.
Definition: intro_types.h:2347
Data gather event.
Definition: intro_types.h:2242
#define INT_SUCCESS(Status)
Definition: introstatus.h:42
Describes an event sent by the log gathering tool.
Definition: intro_types.h:2272
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
INTSTATUS IntAgentHandleLogGatherVmcall(void *Reserved, PIG_ARCH_REGS Registers)
Handle a VMCALL issued by a log gather agent.
Definition: hnd_loggather.c:11
#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
GENERIC_ALERT gAlert
Global alert buffer.
Definition: alerts.c:27
#define LGT_EVENT_SIZE
Log gather agent event size.
Definition: intro_types.h:2251
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
struct _AGENT_LGT_EVENT::@333::@336 ErrorEvent
Error report.
unsigned long long QWORD
Definition: intro_types.h:53
#define LGT_EVENT_VERSION
Log gather agent event version.
Definition: intro_types.h:2249
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
#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
The log gathering agent.
Definition: glueiface.h:347
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 EventType
Event type.
Definition: intro_types.h:2264
DWORD Size
Event size. Should match LGT_EVENT_SIZE/.
Definition: intro_types.h:2262
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
void IntAlertFillLixCurrentProcess(INTRO_PROCESS *EventProcess)
Saves the current Linux process inside an event.
Definition: alerts.c:1310
AGENT_LGT_EVENT LogGatherEvent
Log gather tool event.
Definition: intro_types.h:2369
#define INT_STATUS_INVALID_PARAMETER_2
Definition: introstatus.h:65
Common header for all log gather tool events.
Definition: intro_types.h:2259
#define INT_STATUS_INVALID_DATA_SIZE
Definition: introstatus.h:142
DWORD Version
Event version. Should match LGT_EVENT_VERSION.
Definition: intro_types.h:2261