insight/src/Agent/Insight.Agent/Network/Handlers/SystemInfoHandler.cs
2023-09-21 18:58:32 +02:00

175 lines
No EOL
6.6 KiB
C#

using Insight.Agent.Interfaces;
using Insight.Agent.Messages;
using Microsoft.Win32;
using System.Collections;
using System.Management;
using System.Runtime.Versioning;
namespace Insight.Agent.Network.Handlers
{
[SupportedOSPlatform("windows")]
public class SystemInfoHandler : IAgentMessageHandler<AgentSession>
{
public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IAgentMessage
{
if (message is GetInventory)
{
await sender.SendAsync(GetSystem(), cancellationToken);
}
}
private static SystemInfo GetSystem()
{
using var searcher = new ManagementObjectSearcher
{
Scope = new ManagementScope(@"root\cimv2"),
Query = new ObjectQuery("select lastbootuptime, localdatetime, numberofprocesses from win32_operatingsystem")
};
if (searcher.TryGet(out var collection) is false)
{
searcher.Query = new ObjectQuery("select * from win32_operatingsystem");
if (searcher.TryGet(out collection) is false) throw new InvalidOperationException("WMI Collection NULL");
}
var system = new SystemInfo();
using (collection)
{
foreach (ManagementObject @object in collection.Cast<ManagementObject>())
{
var properties = @object.GetPropertyHashes();
if (@object.TryGetValue<object>(properties, "lastbootuptime", out var lastbootuptime))
{
system.LastBootUpTime = ManagementDateTimeConverter.ToDateTime(lastbootuptime?.ToString());
}
if (@object.TryGetValue<object>(properties, "localdatetime", out var localdatetime))
{
system.LocalDateTime = ManagementDateTimeConverter.ToDateTime(localdatetime?.ToString());
}
system.Processes = @object.GetValue<uint>(properties, "numberofprocesses");
break;
}
}
system.License = GetWindowsProductKeyFromRegistry();
return system;
}
private static string GetWindowsProductKeyFromRegistry()
{
var localKey =
RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, Environment.Is64BitOperatingSystem
? RegistryView.Registry64
: RegistryView.Registry32);
var registryKeyValue = localKey.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion")?.GetValue("DigitalProductId");
if (registryKeyValue == null)
return "Failed to get DigitalProductId from registry";
var digitalProductId = (byte[])registryKeyValue;
localKey.Close();
var isWin8OrUp =
Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Minor >= 2
||
Environment.OSVersion.Version.Major > 6;
return GetWindowsProductKeyFromDigitalProductId(digitalProductId,
isWin8OrUp ? DigitalProductIdVersion.Windows8AndUp : DigitalProductIdVersion.UpToWindows7);
}
private static string GetWindowsProductKeyFromDigitalProductId(byte[] digitalProductId, DigitalProductIdVersion digitalProductIdVersion)
{
var productKey = digitalProductIdVersion == DigitalProductIdVersion.Windows8AndUp
? DecodeProductKeyWin8AndUp(digitalProductId)
: DecodeProductKey(digitalProductId);
return productKey;
}
private static string DecodeProductKey(byte[] digitalProductId)
{
const int keyStartIndex = 52;
const int keyEndIndex = keyStartIndex + 15;
var digits = new[]
{
'B', 'C', 'D', 'F', 'G', 'H', 'J', 'K', 'M', 'P', 'Q', 'R',
'T', 'V', 'W', 'X', 'Y', '2', '3', '4', '6', '7', '8', '9',
};
const int decodeLength = 29;
const int decodeStringLength = 15;
var decodedChars = new char[decodeLength];
var hexPid = new ArrayList();
for (var i = keyStartIndex; i <= keyEndIndex; i++)
{
hexPid.Add(digitalProductId[i]);
}
for (var i = decodeLength - 1; i >= 0; i--)
{
// Every sixth char is a separator.
if ((i + 1) % 6 == 0)
{
decodedChars[i] = '-';
}
else
{
// Do the actual decoding.
var digitMapIndex = 0;
for (var j = decodeStringLength - 1; j >= 0; j--)
{
var byteValue = digitMapIndex << 8 | (byte)hexPid[j];
hexPid[j] = (byte)(byteValue / 24);
digitMapIndex = byteValue % 24;
decodedChars[i] = digits[digitMapIndex];
}
}
}
return new string(decodedChars);
}
private static string DecodeProductKeyWin8AndUp(byte[] digitalProductId)
{
var key = string.Empty;
const int keyOffset = 52;
var isWin8 = (byte)(digitalProductId[66] / 6 & 1);
digitalProductId[66] = (byte)(digitalProductId[66] & 0xf7 | (isWin8 & 2) * 4);
const string digits = "BCDFGHJKMPQRTVWXY2346789";
var last = 0;
for (var i = 24; i >= 0; i--)
{
var current = 0;
for (var j = 14; j >= 0; j--)
{
current = current * 256;
current = digitalProductId[j + keyOffset] + current;
digitalProductId[j + keyOffset] = (byte)(current / 24);
current = current % 24;
last = current;
}
key = digits[current] + key;
}
var keypart1 = key.Substring(1, last);
var keypart2 = key.Substring(last + 1, key.Length - (last + 1));
key = keypart1 + "N" + keypart2;
for (var i = 5; i < key.Length; i += 6)
{
key = key.Insert(i, "-");
}
return key;
}
private enum DigitalProductIdVersion
{
UpToWindows7,
Windows8AndUp
}
}
}