175 lines
6.6 KiB
C#
175 lines
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
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|