Detection, Download, and Installation Framework Completed

This commit is contained in:
GraceSolutions
2026-04-30 20:30:01 -04:00
parent 0f88d07876
commit cd982938d3
10 changed files with 3070 additions and 189 deletions
+216 -1
View File
@@ -1189,7 +1189,222 @@ Try
}
#endregion
#region This should always be the last command of the toolkit
#region Get Current User Session Information
$CurrentUserSessionDefinition = @"
using System;
using System.Runtime.InteropServices;
using System.Security.Principal;
using FILETIME = System.Runtime.InteropServices.ComTypes.FILETIME;
public class CurrentUserSession
{
[DllImport("wtsapi32.dll", SetLastError = true)]
static extern bool WTSQuerySessionInformation(IntPtr hServer, int sessionId, int wtsInfoClass, out IntPtr ppBuffer, out int pBytesReturned);
[DllImport("wtsapi32.dll")]
static extern void WTSFreeMemory(IntPtr pMemory);
[DllImport("kernel32.dll")]
static extern int GetCurrentProcessId();
[DllImport("kernel32.dll")]
static extern bool ProcessIdToSessionId(int processId, out int sessionId);
[DllImport("winsta.dll", SetLastError = true)]
static extern int WinStationQueryInformation(IntPtr hServer, int sessionId, int information, ref WINSTATIONINFO buffer, int bufferLength, ref int returnedLength);
[StructLayout(LayoutKind.Sequential)]
struct WINSTATIONINFO
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 70)] public byte[] Reserved1;
public int SessionId;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[] Reserved2;
public FILETIME ConnectTime;
public FILETIME DisconnectTime;
public FILETIME LastInputTime;
public FILETIME LoginTime;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1096)] public byte[] Reserved3;
public FILETIME CurrentTime;
}
const int WTSSessionId = 4;
const int WTSUserName = 5;
const int WTSSessionName = 6;
const int WTSDomainName = 7;
const int WTSConnectState = 8;
const int WTSClientBuildNumber = 9;
const int WTSClientName = 10;
const int WTSClientProtocolType = 16;
static readonly string[] ConnectStates = { "Active", "Connected", "ConnectQuery", "Shadow", "Disconnected", "Idle", "Listen", "Reset", "Down", "Init" };
public string UserName { get; private set; }
public string DomainName { get; private set; }
public string NTAccount { get; private set; }
public string SID { get; private set; }
public int SessionId { get; private set; }
public string SessionName { get; private set; }
public string ConnectState { get; private set; }
public bool IsConsoleSession { get; private set; }
public bool IsRdpSession { get; private set; }
public bool IsActiveSession { get; private set; }
public string ClientName { get; private set; }
public string ClientProtocol { get; private set; }
public DateTime? LogonTime { get; private set; }
public DateTime? DisconnectTime { get; private set; }
public TimeSpan? IdleTime { get; private set; }
public System.IO.DirectoryInfo ProfilePath { get; private set; }
public System.IO.DirectoryInfo Desktop { get; private set; }
public System.IO.DirectoryInfo Documents { get; private set; }
public System.IO.DirectoryInfo Downloads { get; private set; }
public System.IO.DirectoryInfo AppDataLocal { get; private set; }
public System.IO.DirectoryInfo AppDataRoaming { get; private set; }
public System.IO.DirectoryInfo StartMenu { get; private set; }
public System.IO.DirectoryInfo Startup { get; private set; }
public System.IO.DirectoryInfo Temp { get; private set; }
static DateTime? FileTimeToDateTime(FILETIME ft)
{
if (ft.dwHighDateTime == 0 && ft.dwLowDateTime == 0) return null;
long hFT = (((long)ft.dwHighDateTime) << 32) + ft.dwLowDateTime;
return DateTime.FromFileTime(hFT);
}
static string QueryString(int sessionId, int infoClass)
{
IntPtr buffer; int len;
if (WTSQuerySessionInformation(IntPtr.Zero, sessionId, infoClass, out buffer, out len))
{
string result = Marshal.PtrToStringAnsi(buffer);
WTSFreeMemory(buffer);
return result ?? string.Empty;
}
return string.Empty;
}
static int QueryInt(int sessionId, int infoClass)
{
IntPtr buffer; int len;
if (WTSQuerySessionInformation(IntPtr.Zero, sessionId, infoClass, out buffer, out len))
{
int result = Marshal.ReadInt32(buffer);
WTSFreeMemory(buffer);
return result;
}
return -1;
}
static short QueryShort(int sessionId, int infoClass)
{
IntPtr buffer; int len;
if (WTSQuerySessionInformation(IntPtr.Zero, sessionId, infoClass, out buffer, out len))
{
short result = Marshal.ReadInt16(buffer);
WTSFreeMemory(buffer);
return result;
}
return -1;
}
public CurrentUserSession()
{
int sessionId;
ProcessIdToSessionId(GetCurrentProcessId(), out sessionId);
SessionId = sessionId;
UserName = QueryString(sessionId, WTSUserName);
DomainName = QueryString(sessionId, WTSDomainName);
SessionName = QueryString(sessionId, WTSSessionName);
ClientName = QueryString(sessionId, WTSClientName);
int state = QueryInt(sessionId, WTSConnectState);
ConnectState = (state >= 0 && state < ConnectStates.Length) ? ConnectStates[state] : "Unknown";
IsActiveSession = (state == 0);
short protocol = QueryShort(sessionId, WTSClientProtocolType);
IsRdpSession = (protocol == 2);
ClientProtocol = IsRdpSession ? "RDP" : "Console";
IsConsoleSession = SessionName.Equals("Console", StringComparison.OrdinalIgnoreCase);
if (!string.IsNullOrEmpty(DomainName) && !string.IsNullOrEmpty(UserName))
{
NTAccount = DomainName + "\\" + UserName;
try { SID = new NTAccount(NTAccount).Translate(typeof(SecurityIdentifier)).Value; }
catch { SID = string.Empty; }
}
// Get session timing info - use registry as fallback for LogonTime
try
{
int retLen = 0;
WINSTATIONINFO wsInfo = new WINSTATIONINFO();
int result = WinStationQueryInformation(IntPtr.Zero, sessionId, 8, ref wsInfo, Marshal.SizeOf(typeof(WINSTATIONINFO)), ref retLen);
if (result != 0)
{
LogonTime = FileTimeToDateTime(wsInfo.LoginTime);
DisconnectTime = FileTimeToDateTime(wsInfo.DisconnectTime);
DateTime? lastInput = FileTimeToDateTime(wsInfo.LastInputTime);
DateTime? current = FileTimeToDateTime(wsInfo.CurrentTime);
if (lastInput.HasValue && current.HasValue) IdleTime = current.Value - lastInput.Value;
}
}
catch { }
// Fallback: get logon time from user profile registry
if (!LogonTime.HasValue && !string.IsNullOrEmpty(SID))
{
try
{
using (var key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\" + SID))
{
if (key != null)
{
var localLow = key.GetValue("LocalProfileLoadTimeLow");
var localHigh = key.GetValue("LocalProfileLoadTimeHigh");
if (localLow != null && localHigh != null)
{
long ft = (((long)(int)localHigh) << 32) | ((uint)(int)localLow);
LogonTime = DateTime.FromFileTime(ft);
}
}
}
}
catch { }
}
string profilePath = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
ProfilePath = new System.IO.DirectoryInfo(profilePath);
Desktop = new System.IO.DirectoryInfo(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory));
Documents = new System.IO.DirectoryInfo(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments));
Downloads = new System.IO.DirectoryInfo(System.IO.Path.Combine(profilePath, "Downloads"));
AppDataLocal = new System.IO.DirectoryInfo(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData));
AppDataRoaming = new System.IO.DirectoryInfo(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData));
StartMenu = new System.IO.DirectoryInfo(Environment.GetFolderPath(Environment.SpecialFolder.StartMenu));
Startup = new System.IO.DirectoryInfo(Environment.GetFolderPath(Environment.SpecialFolder.Startup));
Temp = new System.IO.DirectoryInfo(System.IO.Path.GetTempPath().TrimEnd('\\'));
}
}
"@
Try
{
If (-not ([System.Management.Automation.PSTypeName]'CurrentUserSession').Type)
{
Add-Type -TypeDefinition $CurrentUserSessionDefinition -Language CSharp -ErrorAction Stop
}
$CurrentUserSession = New-Object -TypeName 'CurrentUserSession'
$WriteLogMessage.Invoke(0, @("Current User Session: [NTAccount: $($CurrentUserSession.NTAccount)] [IsConsoleSession: $($CurrentUserSession.IsConsoleSession)] [IsRdpSession: $($CurrentUserSession.IsRdpSession)] [IsActiveSession: $($CurrentUserSession.IsActiveSession)] [Profile Path: $($CurrentUserSession.ProfilePath)]"))
}
Catch
{
$WriteLogMessage.Invoke(2, @("Unable to load CurrentUserSession type definition. $($_.Exception.Message)"))
}
#endregion
#region This should always be the last command of the toolkit
$WriteLogMessage.Invoke(0, @("All required functions, modules, libraries, and variables have been loaded from the toolkit successfully."))
#endregion
}