A:剩余代码提交

This commit is contained in:
jimmy committed 2025-06-09 13:43:07 +08:00
1 parent 50f50cb604
commit 117a6d783a
18 files changed
+1793 -1

No files matched your search

+1
View File
@@ -19,6 +19,7 @@
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AMonitor_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F211e6f3b24fa438a92f1815153647ce2c8f908_003Fb5_003F0c446809_003FMonitor_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ANetworkInterface_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F9c72a65889eb40ae9d8e0f130d1572e0268a0_003F34_003F49f5e6ff_003FNetworkInterface_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AProcess_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F4a26a752ec6249c4a090905d31c0cdfa528a0_003F8f_003F7037e590_003FProcess_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AQueue_00601_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F211e6f3b24fa438a92f1815153647ce2c8f908_003Fa1_003F352e385c_003FQueue_00601_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AReaderWriterLockSlim_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F211e6f3b24fa438a92f1815153647ce2c8f908_003Fb5_003Fa78f431c_003FReaderWriterLockSlim_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AReadOnlyCollectionBase_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F4c1fd115dbe5414db1b4da1de3e96c5819910_003F04_003Fcae9fe22_003FReadOnlyCollectionBase_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ASemaphoreSlim_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F211e6f3b24fa438a92f1815153647ce2c8f908_003Fe9_003F4d4110fd_003FSemaphoreSlim_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
+7 -1
View File
@@ -36,8 +36,14 @@ public partial class WebPanel : UserControl
webSocketManager.RegisterHandler("etwNetworkManger", async (cmd, socket) =>
{
Console.WriteLine("开始测试");
// 创建监听实例
var etwNetworkManger = new EtwNetworkManger();
etwNetworkManger.SetupETWHandlers();
// 设置 ETW 监听
etwNetworkManger.SetupEtwHandlers();
// 开始监听
etwNetworkManger.StartCapture();
});
}
+15
View File
@@ -0,0 +1,15 @@
namespace Utils.ETW.Test;
public class Tests
{
[SetUp]
public void Setup()
{
}
[Test]
public void Test1()
{
Class1.Main();
}
}
+28
View File
@@ -0,0 +1,28 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.0"/>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0"/>
<PackageReference Include="NUnit" Version="3.14.0"/>
<PackageReference Include="NUnit.Analyzers" Version="3.9.0"/>
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0"/>
</ItemGroup>
<ItemGroup>
<Using Include="NUnit.Framework"/>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Utils.ETW\Utils.ETW.csproj" />
</ItemGroup>
</Project>
+119
View File
@@ -0,0 +1,119 @@
using Microsoft.Diagnostics.Tracing.Parsers;
using Microsoft.Diagnostics.Tracing.Session;
namespace Utils.ETW;
public static class Class1
{
public static void Main()
{
Console.WriteLine($"这是ue安徽委会aweifawejiofawoi");
// if (TraceEventSession.IsElevated() == true)
// {
// Console.WriteLine("请以管理员身份运行此程序!");
// return;
// }
using (var session = new TraceEventSession("MyNetSession"))
{
// 启用网络内核事件(包括 TCP/UDP)
session.EnableKernelProvider(KernelTraceEventParser.Keywords.NetworkTCPIP);
session.Source.Kernel.TcpIpRecv += data =>
{
Console.WriteLine(
$"[RECV] PID: {data.ProcessID} {data.saddr}:{data.sport} → {data.daddr}:{data.dport} {data.size} bytes");
};
session.Source.Kernel.TcpIpSend += data =>
{
Console.WriteLine(
$"[SEND] PID: {data.ProcessID} {data.saddr}:{data.sport} → {data.daddr}:{data.dport} {data.size} bytes");
};
Console.WriteLine("监听中... 按 Ctrl+C 退出");
session.Source.Process(); // 开始监听事件(阻塞)
}
}
public static void Main2()
{
// Create real-time user session
using (var session = new TraceEventSession("MyKernelSession"))
{
// Enable Kernel Network events
session.EnableKernelProvider(
KernelTraceEventParser.Keywords.NetworkTCPIP |
KernelTraceEventParser.Keywords.Process |
KernelTraceEventParser.Keywords.ImageLoad);
// Hook into real-time events
session.Source.Kernel.TcpIpRecv += data =>
{
Console.WriteLine(
$">>> TCP RECV: {data.ProcessID} -> {data.daddr}:{data.dport} [{data.size} bytes]");
};
session.Source.Kernel.TcpIpSend += data =>
{
Console.WriteLine(
$">>> TCP SEND: {data.ProcessID} -> {data.daddr}:{data.dport} [{data.size} bytes]");
};
session.Source.Kernel.UdpIpRecv += data =>
{
Console.WriteLine(
$">>> UDP RECV: {data.ProcessID} -> {data.daddr}:{data.dport} [{data.size} bytes]");
};
session.Source.Kernel.UdpIpSend += data =>
{
Console.WriteLine(
$">>> UDP SEND: {data.ProcessID} -> {data.daddr}:{data.dport} [{data.size} bytes]");
};
/*
* 当 新进程启动 时触发。
🔧 事件信息:
data.ProcessID:启动的进程 ID。
data.ImageFileName:可执行文件的名称(例如 chrome.exe)。
data.CommandLine:启动进程时使用的完整命令行参数。
*/
session.Source.Kernel.ProcessStart += data =>
{
Console.WriteLine(
$"[PROCESS START] PID={data.ProcessID} Name={data.ImageFileName} Cmd={data.CommandLine}");
};
/*
* 当 进程结束 时触发。
🔧 事件信息:
data.ProcessID:终止的进程 ID。
data.ImageFileName:进程对应的可执行文件名。
✅ 应用场景:
用于记录进程的退出事件,可以用来做进程生命周期分析。
*/
session.Source.Kernel.ProcessStop += data =>
{
Console.WriteLine($"[PROCESS STOP] PID={data.ProcessID} Name={data.ImageFileName}");
};
/*
当某个模块(例如 DLL 或 EXE)被加载到某个进程时触发。
🔧 事件信息:
data.ProcessID:加载模块的进程 ID。
data.FileName:被加载的模块路径(例如 C:\Windows\System32\kernel32.dll)。
✅ 应用场景:
可以监控某些敏感模块是否被加载,如某些反调试或注入行为。
*/
session.Source.Kernel.ImageLoad += data =>
{
Console.WriteLine($"[MODULE LOAD] PID={data.ProcessID} Image={data.FileName}");
};
Console.CancelKeyPress += (o, e) => session.Dispose();
session.Source.Process();
}
}
}
+463
View File
@@ -0,0 +1,463 @@
using Microsoft.Diagnostics.Tracing;
using Microsoft.Diagnostics.Tracing.Parsers;
using Microsoft.Diagnostics.Tracing.Session;
using Utils.ETW.Models;
namespace Utils.ETW.Core;
// ETW网络事件处理器
public class EtwNetworkCapture(string sessionName = "NetworkETWSession") : IDisposable
{
private readonly TraceEventSession _session = new(sessionName);
private readonly ETWTraceEventSource _source = new(sessionName, TraceEventSourceType.Session);
/// <summary>
/// 是否正在监听
/// </summary>
private bool _isCapturing = false;
// 事件处理委托
public delegate void NetworkEventHandler(NetworkEventData eventData);
public delegate void TcpConnectionEventHandler(TcpConnectionEventData eventData);
public delegate void UdpPacketEventHandler(UdpPacketEventData eventData);
public delegate void DnsEventHandler(DnsEventData eventData);
public delegate void HttpEventHandler(HttpEventData eventData);
public delegate void NetworkInterfaceEventHandler(NetworkInterfaceEventData eventData);
public delegate void NetworkErrorEventHandler(NetworkErrorEventData eventData);
// 事件处理器
/// <summary>
/// 通用网络事件处理,所有的网络事件都会进入该函数
/// </summary>
public event NetworkEventHandler? OnNetworkEvent;
public event TcpConnectionEventHandler? OnTcpConnectionEvent;
public event UdpPacketEventHandler? OnUdpPacketEvent;
public event DnsEventHandler? OnDnsEvent;
public event HttpEventHandler? OnHttpEvent;
public event NetworkInterfaceEventHandler? OnNetworkInterfaceEvent;
public event NetworkErrorEventHandler? OnNetworkErrorEvent;
/// <summary>
/// 开始监听
/// </summary>
public void StartCapture()
{
if (_isCapturing) return;
try
{
// 启用网络相关的ETW提供程序
EnableNetworkProviders();
// 设置事件处理器
SetupEventHandlers();
_isCapturing = true;
// 开始处理事件(这是阻塞调用)
Task.Run(() => { _source.Process(); });
Console.WriteLine("ETW网络捕获已启动...");
}
catch (Exception ex)
{
Console.WriteLine($"启动ETW捕获失败: {ex.Message}");
throw;
}
}
/// <summary>
/// 设置监听的 Providers
/// </summary>
private void EnableNetworkProviders()
{
// 启用内核网络事件
_session.EnableKernelProvider(
KernelTraceEventParser.Keywords.NetworkTCPIP
);
// 启用TCP/IP提供程序
_session.EnableProvider("Microsoft-Windows-TCPIP",
TraceEventLevel.Informational);
// 启用Winsock AFD提供程序
/*
*哪个进程创建了 socket
每个 socket 的本地/远程地址、端口
Socket 错误、阻塞、超时
发送/接收的字节数
使用了什么协议(TCP/UDP)
*
*/
_session.EnableProvider("Microsoft-Windows-Winsock-AFD",
TraceEventLevel.Informational);
// 启用DNS客户端提供程序
_session.EnableProvider("Microsoft-Windows-DNS-Client",
TraceEventLevel.Informational);
// 启用HTTP服务提供程序
_session.EnableProvider("Microsoft-Windows-HttpService",
TraceEventLevel.Informational);
// 启用网络配置文件提供程序
_session.EnableProvider("Microsoft-Windows-NetworkProfile",
TraceEventLevel.Informational);
// 监控 DNS 查询行为
_session.EnableProvider("Microsoft-Windows-DNS-Client",
TraceEventLevel.Informational);
}
/// <summary>
/// 设置监听事件
/// </summary>
private void SetupEventHandlers()
{
var parser = new KernelTraceEventParser(_source);
// TCP连接事件
parser.TcpIpConnect += data =>
{
var tcpEvent = new TcpConnectionEventData
{
Timestamp = data.TimeStamp,
EventType = "TcpConnect",
ProcessId = data.ProcessID,
ThreadId = data.ThreadID,
ProcessName = data.ProcessName,
SourceIp = data.saddr,
DestinationIp = data.daddr,
SourcePort = data.sport,
DestinationPort = data.dport,
Protocol = "TCP",
ConnectionState = "ESTABLISHED",
Direction = TrafficDirection.Outbound
};
OnTcpConnectionEvent?.Invoke(tcpEvent);
OnNetworkEvent?.Invoke(tcpEvent);
};
// TCP断开连接事件
parser.TcpIpDisconnect += data =>
{
var tcpEvent = new TcpConnectionEventData
{
Timestamp = data.TimeStamp,
EventType = "TcpDisconnect",
ProcessId = data.ProcessID,
ThreadId = data.ThreadID,
ProcessName = data.ProcessName,
SourceIp = data.saddr,
DestinationIp = data.daddr,
SourcePort = data.sport,
DestinationPort = data.dport,
Protocol = "TCP",
ConnectionState = "CLOSED",
Direction = TrafficDirection.Outbound
};
OnTcpConnectionEvent?.Invoke(tcpEvent);
OnNetworkEvent?.Invoke(tcpEvent);
};
// TCP数据发送事件
parser.TcpIpSend += data =>
{
var tcpEvent = new TcpConnectionEventData
{
Timestamp = data.TimeStamp,
EventType = "TcpSend",
ProcessId = data.ProcessID,
ThreadId = data.ThreadID,
ProcessName = data.ProcessName,
SourceIp = data.saddr,
DestinationIp = data.daddr,
SourcePort = data.sport,
DestinationPort = data.dport,
Protocol = "TCP",
DataLength = data.size,
SequenceNumber = data.seqnum,
Direction = TrafficDirection.Outbound
};
OnTcpConnectionEvent?.Invoke(tcpEvent);
OnNetworkEvent?.Invoke(tcpEvent);
};
// TCP数据接收事件
parser.TcpIpRecv += data =>
{
var tcpEvent = new TcpConnectionEventData
{
Timestamp = data.TimeStamp,
EventType = "TcpReceive",
ProcessId = data.ProcessID,
ThreadId = data.ThreadID,
ProcessName = data.ProcessName,
SourceIp = data.saddr,
DestinationIp = data.daddr,
SourcePort = data.sport,
DestinationPort = data.dport,
Protocol = "TCP",
DataLength = data.size,
SequenceNumber = data.seqnum,
Direction = TrafficDirection.Inbound
};
OnTcpConnectionEvent?.Invoke(tcpEvent);
OnNetworkEvent?.Invoke(tcpEvent);
};
// UDP发送事件
parser.UdpIpSend += data =>
{
var udpEvent = new UdpPacketEventData
{
Timestamp = data.TimeStamp,
EventType = "UdpSend",
ProcessId = data.ProcessID,
ThreadId = data.ThreadID,
ProcessName = data.ProcessName,
SourceIp = data.saddr,
DestinationIp = data.daddr,
SourcePort = data.sport,
DestinationPort = data.dport,
Protocol = "UDP",
DataLength = data.size,
UdpLength = data.size,
Direction = TrafficDirection.Outbound
};
OnUdpPacketEvent?.Invoke(udpEvent);
OnNetworkEvent?.Invoke(udpEvent);
};
// UDP接收事件
parser.UdpIpRecv += data =>
{
var udpEvent = new UdpPacketEventData
{
Timestamp = data.TimeStamp,
EventType = "UdpReceive",
ProcessId = data.ProcessID,
ThreadId = data.ThreadID,
ProcessName = data.ProcessName,
SourceIp = data.saddr,
DestinationIp = data.daddr,
SourcePort = data.sport,
DestinationPort = data.dport,
Protocol = "UDP",
DataLength = data.size,
UdpLength = data.size,
Direction = TrafficDirection.Inbound
};
OnUdpPacketEvent?.Invoke(udpEvent);
OnNetworkEvent?.Invoke(udpEvent);
};
// 通用事件处理器,用于其他网络事件
_source.Dynamic.All += data =>
{
// 处理DNS、HTTP等其他网络事件
ProcessDynamicEvent(data);
};
}
/// <summary>
/// 通用事件处理器,用于其他网络事件
/// </summary>
/// <param name="data"></param>
private void ProcessDynamicEvent(TraceEvent data)
{
// 根据提供程序名称和事件ID处理不同类型的网络事件
switch (data.ProviderName)
{
case "Microsoft-Windows-DNS-Client":
ProcessDnsEvent(data);
break;
case "Microsoft-Windows-HttpService":
ProcessHttpEvent(data);
break;
case "Microsoft-Windows-NetworkProfile":
ProcessNetworkInterfaceEvent(data);
break;
// 负责 TCP/IP 协议栈事件,如连接、发送、接收、断开、重传等
// 用于监控 TCP 会话生命周期,是连接追踪的核心
case "Microsoft-Windows-TCPIP":
// AFD(Ancillary Function Driver for WinSock)是 Winsock API 的核心内核模块
// 常用于检测哪一个进程创建了 socket,socket 和 TCP 会话的关联
case "Microsoft-Windows-Winsock-AFD":
// 也叫 Kernel-Network
case "MSNT_SystemTrace":
break;
default:
// 处理其他网络事件
ProcessGenericNetworkEvent(data);
break;
}
}
private void ProcessDnsEvent(TraceEvent data)
{
try
{
var dnsEvent = new DnsEventData
{
Timestamp = data.TimeStamp,
EventType = "DnsQuery",
ProcessId = data.ProcessID,
ThreadId = data.ThreadID,
ProcessName = data.ProcessName,
Protocol = "DNS"
};
// 从事件数据中提取DNS特定信息
if (data.PayloadNames.Contains("QueryName"))
dnsEvent.QueryName = data.PayloadStringByName("QueryName");
if (data.PayloadNames.Contains("QueryType"))
dnsEvent.QueryType = data.PayloadStringByName("QueryType");
OnDnsEvent?.Invoke(dnsEvent);
OnNetworkEvent?.Invoke(dnsEvent);
}
catch (Exception ex)
{
Console.WriteLine($"处理DNS事件时出错: {ex.Message}");
}
}
private void ProcessHttpEvent(TraceEvent data)
{
try
{
var httpEvent = new HttpEventData
{
Timestamp = data.TimeStamp,
EventType = "HttpRequest",
ProcessId = data.ProcessID,
ThreadId = data.ThreadID,
ProcessName = data.ProcessName,
Protocol = "HTTP"
};
// 从事件数据中提取HTTP特定信息
if (data.PayloadNames.Contains("Url"))
httpEvent.Url = data.PayloadStringByName("Url");
if (data.PayloadNames.Contains("Method"))
httpEvent.HttpMethod = data.PayloadStringByName("Method");
OnHttpEvent?.Invoke(httpEvent);
OnNetworkEvent?.Invoke(httpEvent);
}
catch (Exception ex)
{
Console.WriteLine($"处理HTTP事件时出错: {ex.Message}");
}
}
/// <summary>
/// 网络配置发生变化
/// </summary>
/// <param name="data"></param>
private void ProcessNetworkInterfaceEvent(TraceEvent data)
{
try
{
var interfaceEvent = new NetworkInterfaceEventData
{
Timestamp = data.TimeStamp,
EventType = "NetworkInterface",
ProcessId = data.ProcessID,
ThreadId = data.ThreadID,
ProcessName = data.ProcessName
};
// 从事件数据中提取网络接口信息
if (data.PayloadNames.Contains("InterfaceName"))
interfaceEvent.InterfaceName = data.PayloadStringByName("InterfaceName");
OnNetworkInterfaceEvent?.Invoke(interfaceEvent);
OnNetworkEvent?.Invoke(interfaceEvent);
}
catch (Exception ex)
{
Console.WriteLine($"处理网络接口事件时出错: {ex.Message}");
}
}
/// <summary>
/// 处理其他网络事件
/// </summary>
/// <param name="data"></param>
private void ProcessGenericNetworkEvent(TraceEvent data)
{
try
{
var networkEvent = new NetworkEventData
{
Timestamp = data.TimeStamp,
EventType = data.EventName,
ProcessId = data.ProcessID,
ThreadId = data.ThreadID,
ProcessName = data.ProcessName
};
Console.WriteLine($"data.PayloadName :=> {data.ProviderName}");
// 提取通用网络信息
foreach (var payloadName in data.PayloadNames)
{
try
{
var value = data.PayloadByName(payloadName);
networkEvent.AdditionalProperties[payloadName] = value;
}
catch
{
// 忽略无法获取的字段
}
}
OnNetworkEvent?.Invoke(networkEvent);
}
catch (Exception ex)
{
Console.WriteLine($"处理通用网络事件时出错: {ex.Message}");
}
}
public void StopCapture()
{
if (!_isCapturing) return;
try
{
_isCapturing = false;
_session.Stop();
_source.Dispose();
Console.WriteLine("ETW网络捕获已停止");
}
catch (Exception ex)
{
Console.WriteLine($"停止ETW捕获时出错: {ex.Message}");
}
}
public void Dispose()
{
StopCapture();
_session.Dispose();
_source.Dispose();
}
}
+87
View File
@@ -0,0 +1,87 @@
using System.Collections.Concurrent;
using Utils.ETW.EtwTracker;
using Utils.ETW.Models;
namespace Utils.ETW.Core;
public class DnsTracker : INetTracker
{
public void SetupEtwHandlers(EtwNetworkCapture networkCapture)
{
networkCapture.OnDnsEvent += dnsEvent =>
{
Console.WriteLine($"[DNS] 查询: {dnsEvent.QueryName} ({dnsEvent.QueryType})");
};
}
}
public class HttpTracker : INetTracker
{
public void SetupEtwHandlers(EtwNetworkCapture networkCapture)
{
networkCapture.OnHttpEvent += httpEvent =>
{
Console.WriteLine($"[HTTP] {httpEvent.HttpMethod} {httpEvent.Url}");
};
}
}
public class NetworkProfileTracker : INetTracker
{
public void SetupEtwHandlers(EtwNetworkCapture networkCapture)
{
networkCapture.OnNetworkInterfaceEvent += interfaceEvent =>
{
Console.WriteLine($"[Interface] {interfaceEvent.InterfaceName}: {interfaceEvent.InterfaceState}");
};
}
}
public class NetworkTracker : INetTracker
{
/// <summary>
/// 捕获的事件量
/// </summary>
private List<NetworkEventData> capturedEvents = new List<NetworkEventData>();
public void SetupEtwHandlers(EtwNetworkCapture networkCapture)
{
networkCapture.OnNetworkEvent += networkEvent => { capturedEvents.Add(networkEvent); };
}
}
public class EtwNetworkManger
{
private UdpTracker udpTracker = new UdpTracker();
private DnsTracker dnsTracker = new DnsTracker();
private HttpTracker httpTracker = new HttpTracker();
private NetworkProfileTracker networkProfileTracker = new NetworkProfileTracker();
private NetworkTracker networkTracker = new NetworkTracker();
private readonly TcpTracker _tcpTracker = new TcpTracker();
private EtwNetworkCapture networkCapture = new EtwNetworkCapture();
/// <summary>
/// 设置信息处理器
/// </summary>
public void SetupEtwHandlers()
{
udpTracker.SetupEtwHandlers(networkCapture);
// dnsTracker.SetupEtwHandlers(networkCapture);
// httpTracker.SetupEtwHandlers(networkCapture);
// networkProfileTracker.SetupEtwHandlers(networkCapture);
// networkTracker.SetupEtwHandlers(networkCapture);
// _tcpTracker.SetupEtwHandlers(networkCapture);
}
public void StartCapture()
{
networkCapture.StartCapture();
}
public void Dispose()
{
networkCapture.Dispose();
}
}
+55
View File
@@ -0,0 +1,55 @@
using Utils.ETW.Models;
namespace Utils.ETW.Core;
/// <summary>
/// 网络信息缓存【全局 TCP、UDP 等连接信息存储】
/// </summary>
public sealed class NetworkCache
{
private static readonly Lazy<NetworkCache> _instance = new(() => new NetworkCache());
public static NetworkCache Instance => _instance.Value;
/// <summary>
/// 初始化字典大小 避免频繁扩容
/// </summary>
private static readonly int InitCapacity = 1_000;
// 私有构造函数,禁止外部创建实例
private NetworkCache()
{
// 初始化缓存等操作
}
/// <summary>
/// 缓存字典
/// </summary>
private readonly Dictionary<string, NetworkModel> _cache = new(InitCapacity);
// 设置缓存
public void Set(string key, NetworkModel value)
{
lock (_cache)
{
_cache[key] = value;
}
}
public NetworkModel? Get(string key)
{
lock (_cache)
{
return _cache.GetValueOrDefault(key);
}
}
// 移除缓存
public void Remove(string key)
{
lock (_cache)
{
_cache.Remove(key);
}
}
}
+117
View File
@@ -0,0 +1,117 @@
using System.Collections.Concurrent;
using System.Net;
using Utils.ETW.Models;
namespace Utils.ETW.Core;
/// <summary>
/// 网络信息管理【网络活动记录】
/// </summary>
public sealed class NetworkInfoManger
{
/// <summary>
/// 网络日志
/// </summary>
Queue<string> networkEvents = new();
/// <summary>
/// 最大日志记录条数
/// </summary>
public int NetworkEventsMaxSize = 1_000;
/// <summary>
/// 活跃的 TCP 连接
/// </summary>
private readonly ConcurrentDictionary<string, NetworkModel> _activeTcpSessions = new();
/// <summary>
/// 活跃的 UDP 连接
/// </summary>
private readonly ConcurrentDictionary<string, NetworkModel> _activeUdpSessions = new();
private static readonly Lazy<NetworkInfoManger> _instance = new(() => new NetworkInfoManger());
/// <summary>
/// 端口流量记录
/// </summary>
public readonly Dictionary<int, ulong> PortTrafficSent = new();
public readonly Dictionary<int, ulong> PortTrafficReceived = new();
/// <summary>
/// IP 流量记录
/// </summary>
public readonly Dictionary<IPAddress, ulong> SourceTrafficSent = new();
public readonly Dictionary<IPAddress, ulong> SourceTrafficReceived = new();
public static NetworkInfoManger Instance => _instance.Value;
private NetworkInfoManger()
{
}
#region TCP 缓存信息
public void SetTcpCache(string key, NetworkModel value)
{
_activeTcpSessions[key] = value;
}
public void SetTcpCache(NetworkModel value)
{
_activeTcpSessions[value.GetKey()] = value;
}
public (bool tryRemove, NetworkModel? session) RemoveTcpCache(NetworkModel value)
{
return RemoveTcpCache(value.GetKey());
}
public (bool tryRemove, NetworkModel? session) RemoveTcpCache(string str)
{
var tryRemove = _activeTcpSessions.TryRemove(str, out var session);
return (tryRemove, session);
}
public int GetTcpSize()
=> _activeTcpSessions.Count;
#endregion
#region UDP 缓存信息
public void SetUdpCache(string key, NetworkModel value)
{
_activeUdpSessions[key] = value;
}
public void SetUdpCache(NetworkModel value)
{
_activeUdpSessions[value.GetKey()] = value;
}
public (bool tryRemove, NetworkModel? session) RemoveUdpCache(NetworkModel value)
{
return RemoveUdpCache(value.GetKey());
}
public (bool tryRemove, NetworkModel? session) RemoveUdpCache(string str)
{
var tryRemove = _activeUdpSessions.TryRemove(str, out var session);
return (tryRemove, session);
}
public int GetUdpSize()
=> _activeUdpSessions.Count;
#endregion
/// <summary>
/// 记录动作
/// </summary>
/// <param name="eventStr"></param>
public void RecordEvent(string eventStr)
{
if (networkEvents.Count >= NetworkEventsMaxSize)
networkEvents.Dequeue(); // 超出最大长度时,移除旧数据
networkEvents.Enqueue(eventStr);
}
// todo: 2025年6月2日 22点00分 统计每个连接的时长、流量 (检测是否是僵尸进程【长连接,但低流量】);统计当前活跃连接
// todo: 2025年6月2日 22点01分 按照 端口、IP 统计流量
}
+150
View File
@@ -0,0 +1,150 @@
using System.Net;
using Utils.ETW.EtwTracker;
using Utils.ETW.Models;
namespace Utils.ETW.Core;
public class UdpTracker : INetTracker
{
private Dictionary<int, int> portTraffic = new();
private Dictionary<IPAddress, int> sourceTraffic = new();
public void SetupEtwHandlers(EtwNetworkCapture networkCapture)
{
networkCapture.OnUdpPacketEvent += (udpEvent) =>
{
Console.WriteLine($"[UDP] {udpEvent.EventType}: {udpEvent.SourceIp}:{udpEvent.SourcePort} -> " +
$"{udpEvent.DestinationIp}:{udpEvent.DestinationPort} ({udpEvent.DataLength} bytes)");
// UDP处理主要关注数据包本身,而不是连接状态
UpdateTrafficStats(udpEvent);
// 根据端口进行专门处理
switch (udpEvent.DestinationPort)
{
case 53: // DNS
ProcessDnsPacket(udpEvent);
break;
case 123: // NTP
ProcessNtpPacket(udpEvent);
break;
case 67:
case 68: // DHCP
ProcessDhcpPacket(udpEvent);
break;
default:
ProcessGenericUdpPacket(udpEvent);
break;
}
};
}
private void UpdateTrafficStats(UdpPacketEventData udpEvent)
{
// 统计端口流量
if (!portTraffic.ContainsKey(udpEvent.DestinationPort))
portTraffic[udpEvent.DestinationPort] = 0;
portTraffic[udpEvent.DestinationPort] += udpEvent.DataLength;
// 统计源IP流量
if (!sourceTraffic.ContainsKey(udpEvent.SourceIp))
sourceTraffic[udpEvent.SourceIp] = 0;
sourceTraffic[udpEvent.SourceIp] += udpEvent.DataLength;
}
private void ProcessDnsPacket(UdpPacketEventData udpEvent)
{
// 连接建立时间
var lastSeenTime = DateTime.Now;
var networkModel = new NetworkModel
{
ConnectType = ProtocolType.UDP,
ProcessId = udpEvent.ProcessId,
ThreadId = udpEvent.ThreadId,
ProcessName = udpEvent.ProcessName,
SourceIp = udpEvent.SourceIp,
DestinationIp = udpEvent.DestinationIp,
LastSeenTime = lastSeenTime,
BytesSent = 0,
BytesReceived = 0,
State = ConnectionState.Connecting,
SourcePort = udpEvent.SourcePort,
DestinationPort = udpEvent.DestinationPort,
StartTime = lastSeenTime,
Direction = udpEvent.Direction,
RecordTime = lastSeenTime,
IsPartialConnection = true,
};
NetworkInfoManger.Instance.SetUdpCache(networkModel);
string str = $"连接建立: {networkModel.DestinationIp}:{networkModel.DestinationPort} ," +
$"地址: {networkModel.SourceIp}:{networkModel.SourcePort}";
NetworkInfoManger.Instance.RecordEvent(str);
}
private void ProcessNtpPacket(UdpPacketEventData udpEvent)
{
// 连接建立时间
var lastSeenTime = DateTime.Now;
var networkModel = new NetworkModel
{
ConnectType = ProtocolType.UDP,
ProcessId = udpEvent.ProcessId,
ThreadId = udpEvent.ThreadId,
ProcessName = udpEvent.ProcessName,
SourceIp = udpEvent.SourceIp,
DestinationIp = udpEvent.DestinationIp,
LastSeenTime = lastSeenTime,
BytesSent = 0,
BytesReceived = 0,
State = ConnectionState.Connecting,
SourcePort = udpEvent.SourcePort,
DestinationPort = udpEvent.DestinationPort,
StartTime = lastSeenTime,
Direction = udpEvent.Direction,
RecordTime = lastSeenTime,
IsPartialConnection = true,
};
NetworkInfoManger.Instance.SetUdpCache(networkModel);
string str = $"连接建立: {networkModel.DestinationIp}:{networkModel.DestinationPort} ," +
$"地址: {networkModel.SourceIp}:{networkModel.SourcePort}";
NetworkInfoManger.Instance.RecordEvent(str);
}
private void ProcessDhcpPacket(UdpPacketEventData udpEvent)
{
Console.WriteLine($"[DHCP] DHCP通信: {udpEvent.SourceIp} <-> {udpEvent.DestinationIp}");
}
private void ProcessGenericUdpPacket(UdpPacketEventData udpEvent)
{
// 对于未知UDP流量,主要进行安全检查
if (udpEvent.DataLength > 1024 * 64) // 64KB
{
Console.WriteLine($"[UDP警告] 大型UDP数据包: {udpEvent.ProcessName} " +
$"发送 {udpEvent.DataLength} 字节到 {udpEvent.DestinationIp}:{udpEvent.DestinationPort}");
}
}
public void PrintTrafficSummary()
{
Console.WriteLine("\n=== UDP流量统计 ===");
Console.WriteLine("端口流量TOP 10:");
foreach (var item in portTraffic.OrderByDescending(x => x.Value).Take(10))
{
Console.WriteLine($" 端口 {item.Key}: {item.Value / 1024}KB");
}
Console.WriteLine("\n源IP流量TOP 10:");
foreach (var item in sourceTraffic.OrderByDescending(x => x.Value).Take(10))
{
Console.WriteLine($" {item.Key}: {item.Value / 1024}KB");
}
}
}
+14
View File
@@ -0,0 +1,14 @@
namespace Utils.ETW;
public enum Enums
{
TcpConnect,
TcpDisconnect,
TcpSend,
TcpReceive,
UdpSend,
UdpReceive,
DnsQuery,
HttpRequest,
NetworkInterface,
}
+12
View File
@@ -0,0 +1,12 @@
using Utils.ETW.Core;
namespace Utils.ETW.EtwTracker;
public interface INetTracker
{
/// <summary>
/// 设置处理方式
/// </summary>
/// <param name="networkCapture">ETW 连接对象</param>
void SetupEtwHandlers(EtwNetworkCapture networkCapture);
}
+347
View File
@@ -0,0 +1,347 @@
using System.Collections.Concurrent;
using System.Net;
using Common.Logger;
using Utils.ETW.Core;
using Utils.ETW.Models;
namespace Utils.ETW.EtwTracker;
/// <summary>
/// TCP连接追踪器
/// </summary>
public class TcpTracker : INetTracker
{
/// <summary>
/// 最大连接数
/// </summary>
private readonly int _maxConnections = 10_000;
/// <summary>
/// 活跃会话
/// </summary>
private readonly ConcurrentDictionary<long, TcpConnectionSession> _activeSessions = new();
public void SetupEtwHandlers(EtwNetworkCapture networkCapture)
{
// TCP事件需要单独详细处理
networkCapture.OnTcpConnectionEvent += tcpEvent =>
{
ProcessTcpEvent(tcpEvent);
// 额外的TCP特定检查
CheckTcpSecurity(tcpEvent);
MonitorTcpPerformance(tcpEvent);
};
}
/// <summary>
/// 安全性检查
/// </summary>
/// <param name="tcpEvent"></param>
private void CheckTcpSecurity(TcpConnectionEventData tcpEvent)
{
// TCP安全检查
if (tcpEvent.EventType == "TcpConnect")
{
// 检测端口扫描
// 检测恶意外连
// 检测异常连接模式
}
}
/// <summary>
/// 性能监视
/// </summary>
/// <param name="tcpEvent"></param>
private void MonitorTcpPerformance(TcpConnectionEventData tcpEvent)
{
// TCP性能监控
// 重传检测
// 窗口大小分析
// 连接建立延迟
}
/// <summary>
/// 不同连接状态事件
/// </summary>
/// <param name="tcpEvent"></param>
public void ProcessTcpEvent(TcpConnectionEventData tcpEvent)
{
Console.WriteLine($"[TCP] {tcpEvent.EventType}: {tcpEvent.SourceIp}:{tcpEvent.SourcePort} -> " +
$"{tcpEvent.DestinationIp}:{tcpEvent.DestinationPort} ({tcpEvent.ProcessName})");
switch (tcpEvent.EventType)
{
// 连接建立 - 需要记录连接开始时间
case "TcpConnect":
StartSession(tcpEvent);
break;
// 连接断开 - 计算连接持续时间,统计传输数据量
case "TcpDisconnect":
EndSession(tcpEvent);
break;
// 数据传输 - 累计传输字节数,检测异常流量
case "TcpSend":
UpdateSentData(tcpEvent);
break;
case "TcpReceive":
UpdateReceivedData(tcpEvent);
break;
}
}
/// <summary>
/// 开始监听
/// </summary>
/// <param name="tcpEvent"></param>
private void StartSession(TcpConnectionEventData tcpEvent)
{
// 连接建立时间
var lastSeenTime = DateTime.Now;
var networkModel = new NetworkModel
{
ConnectType = ProtocolType.TCP,
ProcessId = tcpEvent.ProcessId,
ThreadId = tcpEvent.ThreadId,
ProcessName = tcpEvent.ProcessName,
SourceIp = tcpEvent.SourceIp,
DestinationIp = tcpEvent.DestinationIp,
LastSeenTime = lastSeenTime,
BytesSent = 0,
BytesReceived = 0,
State = ConnectionState.Connecting,
SourcePort = tcpEvent.SourcePort,
DestinationPort = tcpEvent.DestinationPort,
StartTime = lastSeenTime,
Direction = tcpEvent.Direction,
RecordTime = lastSeenTime,
IsPartialConnection = true,
};
var session = new TcpConnectionSession
{
ConnectionId = tcpEvent.ConnectionId,
StartTime = tcpEvent.Timestamp,
SourceIp = tcpEvent.SourceIp,
DestinationIp = tcpEvent.DestinationIp,
SourcePort = tcpEvent.SourcePort,
DestinationPort = tcpEvent.DestinationPort,
ProcessName = tcpEvent.ProcessName
};
NetworkInfoManger.Instance.SetTcpCache(networkModel);
string str = $"连接建立: {networkModel.DestinationIp}:{networkModel.DestinationPort} ," +
$"地址: {networkModel.SourceIp}:{networkModel.SourcePort}";
NetworkInfoManger.Instance.RecordEvent(str);
// 业务逻辑处理
AnalyzeNewConnection(session);
}
/// <summary>
/// 结束会话
/// </summary>
/// <param name="tcpEvent"></param>
private void EndSession(TcpConnectionEventData tcpEvent)
{
var key = NetworkModel.GetKey(
tcpEvent.SourceIp,
tcpEvent.SourcePort,
tcpEvent.DestinationIp,
tcpEvent.DestinationPort,
tcpEvent.ProcessId,
ProtocolType.TCP,
tcpEvent.Timestamp
);
var removeTcpCache = NetworkInfoManger.Instance.RemoveTcpCache(key);
if (removeTcpCache.tryRemove)
{
if (removeTcpCache.session == null)
{
Log.Warning("移除成功,但获取数据为 Null !");
return;
}
removeTcpCache.session.EndTime = tcpEvent.Timestamp;
removeTcpCache.session.State = ConnectionState.Disconnected;
string str = $"连接断开: {removeTcpCache.session.DestinationIp}:{removeTcpCache.session.DestinationPort} ," +
$"地址: {removeTcpCache.session.SourceIp}:{removeTcpCache.session.SourcePort}";
NetworkInfoManger.Instance.RecordEvent(str);
// 连接结束时的分析
// AnalyzeCompletedConnection(session);
}
}
/// <summary>
/// 更新发送的数据量
/// </summary>
/// <param name="tcpEvent"></param>
private void UpdateSentData(TcpConnectionEventData tcpEvent)
{
var key = NetworkModel.GetKey(
tcpEvent.SourceIp,
tcpEvent.SourcePort,
tcpEvent.DestinationIp,
tcpEvent.DestinationPort,
tcpEvent.ProcessId,
ProtocolType.TCP,
tcpEvent.Timestamp
);
var (tryRemove, networkModel) = NetworkInfoManger.Instance.RemoveTcpCache(key);
if (tcpEvent.DataLength < 0)
{
throw new Exception("数据长度不可能为 0 !!");
}
// 统计端口流量
NetworkInfoManger.Instance.PortTrafficSent.TryAdd(tcpEvent.DestinationPort, 0);
NetworkInfoManger.Instance.PortTrafficSent[tcpEvent.DestinationPort] += (ulong)tcpEvent.DataLength;
NetworkInfoManger.Instance.SourceTrafficSent.TryAdd(tcpEvent.SourceIp, 0);
NetworkInfoManger.Instance.SourceTrafficSent[tcpEvent.SourceIp] += (ulong)tcpEvent.DataLength;
if (tryRemove)
{
if (networkModel == null)
{
Log.Warning("发送新数据, 但是数据获取为空 !");
return;
}
networkModel.BytesSent += tcpEvent.DataLength;
networkModel.State = ConnectionState.Connected;
networkModel.LastSeenTime = DateTime.Now;
// todo: 检测 1 分钟、10 分钟的数据传输量;统计 1 分钟、10 分钟平均速率
string str = $"发送: {networkModel.SourceIp}:{networkModel.SourcePort} {tcpEvent.DataLength} 字节";
NetworkInfoManger.Instance.RecordEvent(str);
}
}
/// <summary>
/// 更新接收的数据量
/// </summary>
/// <param name="tcpEvent"></param>
private void UpdateReceivedData(TcpConnectionEventData tcpEvent)
{
var key = NetworkModel.GetKey(
tcpEvent.SourceIp,
tcpEvent.SourcePort,
tcpEvent.DestinationIp,
tcpEvent.DestinationPort,
tcpEvent.ProcessId,
ProtocolType.TCP,
tcpEvent.Timestamp
);
var (tryRemove, networkModel) = NetworkInfoManger.Instance.RemoveTcpCache(key);
if (tcpEvent.DataLength < 0)
{
throw new Exception("数据长度不可能为 0 !!");
}
// 统计端口流量
NetworkInfoManger.Instance.PortTrafficReceived.TryAdd(tcpEvent.DestinationPort, 0);
NetworkInfoManger.Instance.PortTrafficReceived[tcpEvent.DestinationPort] += (ulong)tcpEvent.DataLength;
NetworkInfoManger.Instance.SourceTrafficReceived.TryAdd(tcpEvent.SourceIp, 0);
NetworkInfoManger.Instance.SourceTrafficReceived[tcpEvent.SourceIp] += (ulong)tcpEvent.DataLength;
if (tryRemove)
{
if (networkModel == null)
{
Log.Warning("发送新数据, 但是数据获取为空 !");
return;
}
networkModel.BytesReceived += tcpEvent.DataLength;
networkModel.State = ConnectionState.Connected;
networkModel.LastSeenTime = DateTime.Now;
string str = $"接收: {networkModel.SourceIp}:{networkModel.SourcePort} {tcpEvent.DataLength} 字节";
NetworkInfoManger.Instance.RecordEvent(str);
}
}
/// <summary>
/// 分析新连接
/// </summary>
/// <param name="session"></param>
private void AnalyzeNewConnection(TcpConnectionSession session)
{
// 1. 安全检查
// if (IsExternalConnection(session.DestinationIp))
// {
// Console.WriteLine(
// $"[SECURITY] 外部连接警告: {session.ProcessName} -> {session.DestinationIp}:{session.DestinationPort}");
// }
// 2. 业务监控
// if (IsBusinessCriticalPort(session.DestinationPort))
// {
// Console.WriteLine($"[BUSINESS] 关键业务连接: {session.ProcessName} -> {session.DestinationPort}");
// }
// 3. 性能监控
var tcpSize = NetworkInfoManger.Instance.GetTcpSize();
if (tcpSize > 1000)
{
Console.WriteLine($"[PERFORMANCE] 连接数量警告: 当前活跃连接 {tcpSize}");
}
}
/// <summary>
/// 是否是连接到外部
/// </summary>
/// <param name="ip"></param>
/// <returns></returns>
private bool IsExternalConnection(IPAddress ip)
{
// 简单检查是否为外部IP(实际应用中需要更复杂的逻辑)
return !ip.ToString().StartsWith("192.168.") &&
!ip.ToString().StartsWith("10.") &&
!ip.ToString().StartsWith("172.") &&
!IPAddress.IsLoopback(ip);
}
/// <summary>
/// 是否是业务端口
/// </summary>
/// <param name="port">要监测的端口号</param>
/// <returns></returns>
private bool IsBusinessCriticalPort(int port)
{
var businessPorts = new[]
{ 80, 443, 3306, 5432, 1433, 6379 }; // HTTP, HTTPS, MySQL, PostgreSQL, SQL Server, Redis
return businessPorts.Contains(port);
}
/// <summary>
/// 获取活跃连接
/// </summary>
/// <returns></returns>
public List<TcpConnectionSession> GetActiveSessions()
{
return _activeSessions.Values.ToList();
}
/// <summary>
/// 获取长连接的会话
/// </summary>
/// <param name="threshold">连接时长</param>
/// <returns></returns>
public List<TcpConnectionSession> GetLongRunningSessions(TimeSpan threshold)
{
return _activeSessions.Values
.Where(s => s.Duration > threshold)
.ToList();
}
}
+18
View File
@@ -0,0 +1,18 @@
namespace Utils.ETW;
/// <summary>
/// 全局网络信息
/// </summary>
public sealed class GlobalNet
{
private static readonly Lazy<GlobalNet> _instance = new Lazy<GlobalNet>(() => new GlobalNet());
public static GlobalNet Instance => _instance.Value;
// 私有构造函数,防止外部实例化
private GlobalNet()
{
}
}
+150
View File
@@ -0,0 +1,150 @@
using System.Net;
namespace Utils.ETW.Models;
// 网络事件数据结构定义
public class NetworkEventData
{
/// <summary>
/// 记录产生时间
/// </summary>
public DateTime Timestamp { get; set; }
/// <summary>
/// 事件类型
/// </summary>
public string EventType { get; set; }
/// <summary>
/// 进程 ID
/// </summary>
public int ProcessId { get; set; }
public int ThreadId { get; set; }
public string ProcessName { get; set; }
public IPAddress SourceIp { get; set; }
public IPAddress DestinationIp { get; set; }
/// <summary>
/// 源端口
/// </summary>
public int SourcePort { get; set; }
/// <summary>
/// 目标端口
/// </summary>
public int DestinationPort { get; set; }
public string Protocol { get; set; }
public int DataLength { get; set; }
public TrafficDirection Direction { get; set; } // Inbound/Outbound
public Dictionary<string, object> AdditionalProperties { get; set; }
public NetworkEventData()
{
AdditionalProperties = new Dictionary<string, object>();
}
}
public class TcpConnectionSession : NetworkEventData
{
public long ConnectionId { get; set; }
/// <summary>
/// 开始时间
/// </summary>
public DateTime StartTime { get; set; }
public DateTime? EndTime { get; set; }
/// <summary>
/// 发送的字节数
/// </summary>
public long BytesSent { get; set; }
public long BytesReceived { get; set; }
/// <summary>
/// 持续时间
/// </summary>
public TimeSpan Duration => (EndTime ?? DateTime.Now) - StartTime;
public List<string> Events { get; set; } = new List<string>();
}
// TCP连接事件数据
public class TcpConnectionEventData : NetworkEventData
{
/// <summary>
/// 连接状态
/// </summary>
public string ConnectionState { get; set; } // ESTABLISHED, CLOSED, LISTEN等
public long ConnectionId { get; set; }
/// <summary>
/// 顺序
/// </summary>
public int SequenceNumber { get; set; }
public int AcknowledgmentNumber { get; set; }
public int WindowSize { get; set; }
public string TcpFlags { get; set; }
}
// UDP数据包事件数据
public class UdpPacketEventData : NetworkEventData
{
public int UdpLength { get; set; }
public int Checksum { get; set; }
}
// DNS查询事件数据
public class DnsEventData : NetworkEventData
{
public string QueryName { get; set; }
public string QueryType { get; set; }
public string ResponseCode { get; set; }
public List<string> ResolvedAddresses { get; set; }
public int QueryId { get; set; }
public DnsEventData()
{
ResolvedAddresses = new List<string>();
}
}
// HTTP事件数据
public class HttpEventData : NetworkEventData
{
public string HttpMethod { get; set; }
public string Url { get; set; }
public int StatusCode { get; set; }
public string UserAgent { get; set; }
public string Host { get; set; }
public Dictionary<string, string> Headers { get; set; }
public long ContentLength { get; set; }
public HttpEventData()
{
Headers = new Dictionary<string, string>();
}
}
// 网络接口事件数据
public class NetworkInterfaceEventData : NetworkEventData
{
public string InterfaceName { get; set; }
public string InterfaceType { get; set; }
public string MacAddress { get; set; }
public string InterfaceState { get; set; } // Up/Down
public long BytesSent { get; set; }
public long BytesReceived { get; set; }
public long PacketsSent { get; set; }
public long PacketsReceived { get; set; }
}
// 网络错误事件数据
public class NetworkErrorEventData : NetworkEventData
{
public int ErrorCode { get; set; }
public string ErrorDescription { get; set; }
public string ErrorCategory { get; set; }
}
+177
View File
@@ -0,0 +1,177 @@
using System.Net;
namespace Utils.ETW.Models;
/// <summary>
/// 网络连接模型
/// </summary>
public class NetworkModel
{
// RemoteCountry 地理位置归属地,供安全分析
/// <summary>
/// 进程 ID
/// </summary>
public required int ProcessId { get; set; }
/// <summary>
/// 线程 ID
/// </summary>
public required int ThreadId { get; set; }
/// <summary>
/// 进程名称
/// </summary>
public required string ProcessName { get; set; }
/// <summary>
/// 源地址
/// </summary>
public required IPAddress SourceIp { get; set; }
public required IPAddress DestinationIp { get; set; }
/// <summary>
/// 最新活动时间
/// </summary>
public required DateTime LastSeenTime { get; set; }
/// <summary>
/// 记录产生时间
/// </summary>
public required DateTime RecordTime { get; set; }
/// <summary>
/// 发送的数据量
/// </summary>
public long BytesSent { get; set; }
public long BytesReceived { get; set; }
/// <summary>
/// 连接状态
/// </summary>
public required ConnectionState State { get; set; } // 如 ESTABLISHED, CLOSED, TIME_WAIT, 或 UDP/Unknown
/// <summary>
/// 源端口
/// </summary>
public required int SourcePort { get; set; }
/// <summary>
/// 目标端口
/// </summary>
public required int DestinationPort { get; set; }
/// <summary>
/// 连接类型
/// </summary>
public required ProtocolType ConnectType { get; set; }
/// <summary>
/// 开始时间
/// </summary>
public DateTime? StartTime { get; set; }
/// <summary>
/// 进站或是出站
/// </summary>
public TrafficDirection Direction { get; set; }
/// <summary>
/// 结束时间
/// </summary>
public DateTime? EndTime { get; set; }
/// <summary>
/// 是否是完整会话【如果在软件打开前会话已经创建则不认为是完整会话】
/// </summary>
public required bool IsPartialConnection { get; set; }
/// <summary>
/// 会话持续时间
/// </summary>
public TimeSpan Duration => (EndTime ?? DateTime.Now) - (StartTime ?? RecordTime);
// 近 1 分钟平均网速
// 近 1 分钟流量统计
// 近 10 分钟流量统计
public string GetKey()
{
return GetKey(this);
}
/// <summary>
/// 获取唯一 ID
/// </summary>
/// <returns></returns>
public static string GetKey(NetworkModel networkModel)
{
return GetKey(networkModel.SourceIp,
networkModel.SourcePort,
networkModel.DestinationIp,
networkModel.DestinationPort,
networkModel.ProcessId,
networkModel.ConnectType,
networkModel.RecordTime);
}
/// <summary>
/// 获取唯一 ID
/// </summary>
/// <param name="sourceIp">源 Ip</param>
/// <param name="sourcePort">源端口</param>
/// <param name="destinationIp">目标 Ip</param>
/// <param name="destinationPort">目标端口</param>
/// <param name="processId">进程 ID</param>
/// <param name="connectType">连接类型</param>
/// <param name="recordTime">记录时间</param>
/// <returns></returns>
public static string GetKey(
IPAddress sourceIp,
int sourcePort,
IPAddress destinationIp,
int destinationPort,
int processId,
ProtocolType connectType,
DateTime recordTime)
{
var key =
$"{sourceIp}:{sourcePort}-{destinationIp}:" +
$"{destinationPort}-{processId}-{connectType}-" +
$"{recordTime:yyyyMMddHHmmss}";
return key;
}
}
public enum ConnectionState
{
/// <summary>
/// 正在尝试连接
/// </summary>
Connecting,
Connected, // 当前连接活跃(发送/接收中)
Disconnected, // 已断开或未活跃
Listening, // 监听状态(如本地服务器)
Unknown // 无法判断状态
}
public enum ProtocolType
{
TCP,
UDP,
ICMP, // 可选
Unknown
}
/// <summary>
/// 进出站类型
/// </summary>
public enum TrafficDirection
{
Inbound,
Outbound,
// Unknown
}
+17
View File
@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Diagnostics.Tracing.TraceEvent" Version="3.1.21" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Common\Common.csproj" />
</ItemGroup>
</Project>
+16
View File
@@ -0,0 +1,16 @@
namespace Utils.ETW.Utils;
public static class SystemInfoHelper
{
/// <summary>
/// 检查是否是管理员权限
/// </summary>
/// <returns></returns>
public static bool IsRunAsAdministrator()
{
var identity = System.Security.Principal.WindowsIdentity.GetCurrent();
var principal = new System.Security.Principal.WindowsPrincipal(identity);
return principal.IsInRole(System.Security.Principal.WindowsBuiltInRole.Administrator);
}
}