2024-08-12 03:47:19 +00:00
|
|
|
|
// FileEventMonitor.cs
|
2024-08-26 16:24:11 +00:00
|
|
|
|
// Namhyeon Go <abuse@catswords.net>
|
2024-08-12 03:47:19 +00:00
|
|
|
|
// https://github.com/gnh1201/welsonjs
|
|
|
|
|
using System;
|
|
|
|
|
using System.Diagnostics.Eventing.Reader;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using System.ServiceProcess;
|
|
|
|
|
|
|
|
|
|
namespace WelsonJS.Service
|
|
|
|
|
{
|
|
|
|
|
public class FileEventMonitor
|
|
|
|
|
{
|
|
|
|
|
private EventLogWatcher eventLogWatcher;
|
|
|
|
|
private ServiceMain parent;
|
2024-09-09 06:26:16 +00:00
|
|
|
|
private enum EventType: int
|
|
|
|
|
{
|
|
|
|
|
FileCreate = 11,
|
2024-09-09 08:09:31 +00:00
|
|
|
|
NetworkConnection = 3,
|
|
|
|
|
RegistryEvent_1 = 12,
|
|
|
|
|
RegistryEvent_2 = 13,
|
|
|
|
|
RegistryEvent_3 = 14
|
2024-09-09 06:26:16 +00:00
|
|
|
|
};
|
|
|
|
|
private enum FileCreateEvent: int {
|
2024-09-09 03:05:39 +00:00
|
|
|
|
RuleName,
|
|
|
|
|
UtcTime,
|
|
|
|
|
ProcessGuid,
|
|
|
|
|
ProcessId,
|
|
|
|
|
Image,
|
|
|
|
|
TargetFilename,
|
|
|
|
|
CreationUtcTime,
|
|
|
|
|
User
|
|
|
|
|
};
|
2024-09-09 06:26:16 +00:00
|
|
|
|
private enum NetworkConnectionEvent: int
|
|
|
|
|
{
|
|
|
|
|
RuleName,
|
|
|
|
|
UtcTime,
|
|
|
|
|
ProcessGuid,
|
|
|
|
|
ProcessId,
|
|
|
|
|
Image,
|
|
|
|
|
User,
|
|
|
|
|
Protocol,
|
|
|
|
|
Initiated,
|
|
|
|
|
SourceIsIpv6,
|
|
|
|
|
SourceIp,
|
|
|
|
|
SourceHostname,
|
|
|
|
|
SourcePort,
|
|
|
|
|
SourcePortName,
|
|
|
|
|
DestinationIsIpv6,
|
|
|
|
|
DestinationIp,
|
|
|
|
|
DestinationHostname,
|
|
|
|
|
DestinationPort,
|
|
|
|
|
DestinationPortName,
|
|
|
|
|
};
|
2024-09-09 08:09:31 +00:00
|
|
|
|
private enum RegistryEvent: int
|
|
|
|
|
{
|
|
|
|
|
RuleName,
|
|
|
|
|
EventType,
|
|
|
|
|
UtcTime,
|
|
|
|
|
ProcessGuid,
|
|
|
|
|
ProcessId,
|
|
|
|
|
Image,
|
|
|
|
|
TargetObject,
|
|
|
|
|
Details,
|
|
|
|
|
User
|
|
|
|
|
}
|
2024-08-12 03:47:19 +00:00
|
|
|
|
|
|
|
|
|
public FileEventMonitor(ServiceBase parent, string workingDirectory)
|
|
|
|
|
{
|
|
|
|
|
this.parent = (ServiceMain)parent;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Start()
|
|
|
|
|
{
|
2024-08-12 04:00:04 +00:00
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
string query = @"<QueryList>
|
|
|
|
|
<Query Id='0' Path='Microsoft-Windows-Sysmon/Operational'>
|
2024-09-09 06:26:16 +00:00
|
|
|
|
<Select Path='Microsoft-Windows-Sysmon/Operational'>*[System/EventID=11 or System/EventID=3]</Select>
|
2024-08-12 04:00:04 +00:00
|
|
|
|
</Query>
|
|
|
|
|
</QueryList>";
|
2024-08-12 03:47:19 +00:00
|
|
|
|
|
2024-08-12 04:00:04 +00:00
|
|
|
|
EventLogQuery eventLogQuery = new EventLogQuery("Microsoft-Windows-Sysmon/Operational", PathType.LogName, query);
|
|
|
|
|
eventLogWatcher = new EventLogWatcher(eventLogQuery);
|
2024-08-12 03:47:19 +00:00
|
|
|
|
|
2024-08-12 04:00:04 +00:00
|
|
|
|
eventLogWatcher.EventRecordWritten += new EventHandler<EventRecordWrittenEventArgs>(OnEventRecordWritten);
|
|
|
|
|
eventLogWatcher.Enabled = true;
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
2024-08-26 16:24:11 +00:00
|
|
|
|
parent.Log($"Failed to connect the Windows EventLog Service: {ex.Message}");
|
2024-08-12 04:00:04 +00:00
|
|
|
|
}
|
2024-08-12 03:47:19 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Stop()
|
|
|
|
|
{
|
|
|
|
|
if (eventLogWatcher != null)
|
|
|
|
|
{
|
2024-08-12 04:36:27 +00:00
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
eventLogWatcher.Dispose();
|
|
|
|
|
eventLogWatcher = null;
|
|
|
|
|
}
|
|
|
|
|
catch (Exception)
|
|
|
|
|
{
|
|
|
|
|
eventLogWatcher = null;
|
|
|
|
|
}
|
2024-08-12 03:47:19 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void OnEventRecordWritten(object sender, EventRecordWrittenEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
if (e.EventRecord != null)
|
|
|
|
|
{
|
2024-09-09 06:26:16 +00:00
|
|
|
|
int eventId = e.EventRecord.Id;
|
|
|
|
|
|
2024-08-12 03:47:19 +00:00
|
|
|
|
try
|
|
|
|
|
{
|
2024-09-09 08:09:31 +00:00
|
|
|
|
switch (eventId)
|
2024-09-09 03:05:39 +00:00
|
|
|
|
{
|
2024-09-09 08:09:31 +00:00
|
|
|
|
case (int)EventType.FileCreate:
|
|
|
|
|
{
|
|
|
|
|
string ruleName = e.EventRecord.Properties[(int)FileCreateEvent.RuleName]?.Value?.ToString();
|
|
|
|
|
string processId = e.EventRecord.Properties[(int)FileCreateEvent.ProcessId]?.Value?.ToString();
|
|
|
|
|
string image = e.EventRecord.Properties[(int)FileCreateEvent.Image]?.Value?.ToString();
|
|
|
|
|
string fileName = e.EventRecord.Properties[(int)FileCreateEvent.TargetFilename]?.Value?.ToString();
|
|
|
|
|
|
|
|
|
|
parent.Log($"> Detected the file creation: {fileName}");
|
|
|
|
|
parent.Log(parent.DispatchServiceEvent("fileCreated", new string[] {
|
|
|
|
|
ruleName,
|
|
|
|
|
processId,
|
|
|
|
|
image,
|
|
|
|
|
fileName
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case (int)EventType.NetworkConnection:
|
|
|
|
|
{
|
|
|
|
|
string ruleName = e.EventRecord.Properties[(int)NetworkConnectionEvent.RuleName]?.Value?.ToString();
|
|
|
|
|
string processId = e.EventRecord.Properties[(int)NetworkConnectionEvent.ProcessId]?.Value?.ToString();
|
|
|
|
|
string image = e.EventRecord.Properties[(int)NetworkConnectionEvent.Image]?.Value?.ToString();
|
|
|
|
|
string protocol = e.EventRecord.Properties[(int)NetworkConnectionEvent.Protocol]?.Value?.ToString();
|
|
|
|
|
string destinationIp = e.EventRecord.Properties[(int)NetworkConnectionEvent.DestinationIp]?.Value?.ToString();
|
|
|
|
|
string desinationPort = e.EventRecord.Properties[(int)NetworkConnectionEvent.DestinationPort]?.Value?.ToString();
|
|
|
|
|
string dstinationAddress = $"{protocol}://{destinationIp}:{desinationPort}";
|
|
|
|
|
|
|
|
|
|
parent.Log($"> Detected the network connection: {dstinationAddress}");
|
|
|
|
|
parent.Log(parent.DispatchServiceEvent("networkConnected", new string[] {
|
|
|
|
|
ruleName,
|
|
|
|
|
processId,
|
|
|
|
|
image,
|
|
|
|
|
dstinationAddress
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case (int)EventType.RegistryEvent_1:
|
|
|
|
|
case (int)EventType.RegistryEvent_2:
|
|
|
|
|
case (int)EventType.RegistryEvent_3:
|
|
|
|
|
{
|
|
|
|
|
string ruleName = e.EventRecord.Properties[(int)RegistryEvent.RuleName]?.Value?.ToString();
|
|
|
|
|
string processId = e.EventRecord.Properties[(int)RegistryEvent.ProcessId]?.Value?.ToString();
|
|
|
|
|
string image = e.EventRecord.Properties[(int)RegistryEvent.Image]?.Value?.ToString();
|
|
|
|
|
string eventType = e.EventRecord.Properties[(int)RegistryEvent.EventType]?.Value?.ToString();
|
|
|
|
|
string targetObject = e.EventRecord.Properties[(int)RegistryEvent.TargetObject]?.Value?.ToString();
|
|
|
|
|
|
|
|
|
|
parent.Log($"> Detected the registry modification: {targetObject}");
|
|
|
|
|
parent.Log(parent.DispatchServiceEvent("registryModified", new string[] {
|
|
|
|
|
ruleName,
|
|
|
|
|
processId,
|
|
|
|
|
image,
|
|
|
|
|
eventType,
|
|
|
|
|
targetObject
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
throw new ArgumentException("Not supported event type");
|
2024-08-12 03:47:19 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
parent.Log($"Error processing event: {ex.Message}");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
parent.Log("The event instance was null.");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|