Exemplo n.º 1
0
 public DeviceSocket(ConfigService configService,
                     Uninstaller uninstaller,
                     CommandExecutor commandExecutor,
                     ScriptRunner scriptRunner,
                     AppLauncher appLauncher,
                     ChatClientService chatService)
 {
     ConfigService   = configService;
     Uninstaller     = uninstaller;
     CommandExecutor = commandExecutor;
     ScriptRunner    = scriptRunner;
     AppLauncher     = appLauncher;
     ChatService     = chatService;
 }
Exemplo n.º 2
0
 public AgentSocket(ConfigService configService,
                    Uninstaller uninstaller,
                    CommandExecutor commandExecutor,
                    ScriptRunner scriptRunner,
                    ChatHostService chatService,
                    IAppLauncher appLauncher,
                    IUpdater updater)
 {
     ConfigService   = configService;
     Uninstaller     = uninstaller;
     CommandExecutor = commandExecutor;
     ScriptRunner    = scriptRunner;
     AppLauncher     = appLauncher;
     ChatService     = chatService;
     Updater         = updater;
 }
Exemplo n.º 3
0
 public AgentSocket(ConfigService configService,
                    Uninstaller uninstaller,
                    ScriptExecutor scriptExecutor,
                    ChatClientService chatService,
                    IAppLauncher appLauncher,
                    IUpdater updater,
                    IDeviceInformationService deviceInfoService)
 {
     _configService     = configService;
     _uninstaller       = uninstaller;
     _scriptExecutor    = scriptExecutor;
     _appLauncher       = appLauncher;
     _chatService       = chatService;
     _updater           = updater;
     _deviceInfoService = deviceInfoService;
 }
Exemplo n.º 4
0
        private void RegisterMessageHandlers()
        {
            // TODO: Remove possibility for circular dependencies in the future
            // by emitting these events so other services can listen for them.

            HubConnection.On("Chat", async(string senderName, string message, string orgName, bool disconnected, string senderConnectionID) =>
            {
                try
                {
                    if (!IsServerVerified)
                    {
                        Logger.Write("Chat attempted before server was verified.", EventType.Warning);
                        return;
                    }

                    await ChatService.SendMessage(senderName, message, orgName, disconnected, senderConnectionID, HubConnection);
                }
                catch (Exception ex)
                {
                    Logger.Write(ex);
                }
            });
            HubConnection.On("DownloadFile", async(string filePath, string senderConnectionID) =>
            {
                try
                {
                    if (!IsServerVerified)
                    {
                        Logger.Write("File download attempted before server was verified.", EventType.Warning);
                        return;
                    }

                    filePath = filePath.Replace("\"", "");
                    if (!File.Exists(filePath))
                    {
                        await HubConnection.SendAsync("DisplayMessage", "File not found on remote device.", "File not found.", senderConnectionID);
                        return;
                    }

                    using var wc              = new WebClient();
                    var lastProgressPercent   = 0;
                    wc.UploadProgressChanged += async(sender, args) =>
                    {
                        if (args.ProgressPercentage > lastProgressPercent)
                        {
                            lastProgressPercent = args.ProgressPercentage;
                            await HubConnection.SendAsync("DownloadFileProgress", lastProgressPercent, senderConnectionID);
                        }
                    };

                    try
                    {
                        var response = await wc.UploadFileTaskAsync($"{ConnectionInfo.Host}/API/FileSharing/", filePath);
                        var fileIDs  = JsonSerializer.Deserialize <string[]>(Encoding.UTF8.GetString(response));
                        await HubConnection.SendAsync("DownloadFile", fileIDs[0], senderConnectionID);
                    }
                    catch (Exception ex)
                    {
                        Logger.Write(ex);
                        await HubConnection.SendAsync("DisplayMessage", "Error occurred while uploading file from remote computer.", "Upload error.", senderConnectionID);
                    }
                }
                catch (Exception ex)
                {
                    Logger.Write(ex);
                }
            });
            HubConnection.On("ChangeWindowsSession", async(string serviceID, string viewerID, int targetSessionID) =>
            {
                try
                {
                    if (!IsServerVerified)
                    {
                        Logger.Write("Session change attempted before server was verified.", EventType.Warning);
                        return;
                    }

                    await AppLauncher.RestartScreenCaster(new List <string>()
                    {
                        viewerID
                    }, serviceID, viewerID, HubConnection, targetSessionID);
                }
                catch (Exception ex)
                {
                    Logger.Write(ex);
                }
            });
            HubConnection.On("ExecuteCommand", (async(string mode, string command, string commandID, string senderConnectionID) =>
            {
                try
                {
                    if (!IsServerVerified)
                    {
                        Logger.Write($"Command attempted before server was verified.  Mode: {mode}.  Command: {command}.  Sender: {senderConnectionID}", EventType.Warning);
                        return;
                    }

                    await CommandExecutor.ExecuteCommand(mode, command, commandID, senderConnectionID, HubConnection);
                }
                catch (Exception ex)
                {
                    Logger.Write(ex);
                }
            }));
            HubConnection.On("ExecuteCommandFromApi", (async(string mode, string requestID, string command, string commandID, string senderUserName) =>
            {
                try
                {
                    if (!IsServerVerified)
                    {
                        Logger.Write($"Command attempted before server was verified.  Mode: {mode}.  Command: {command}.  Sender: {senderUserName}", EventType.Warning);
                        return;
                    }

                    await CommandExecutor.ExecuteCommandFromApi(mode, requestID, command, commandID, senderUserName, HubConnection);
                }
                catch (Exception ex)
                {
                    Logger.Write(ex);
                }
            }));
            HubConnection.On("UploadFiles", async(string transferID, List <string> fileIDs, string requesterID) =>
            {
                try
                {
                    if (!IsServerVerified)
                    {
                        Logger.Write("File upload attempted before server was verified.", EventType.Warning);
                        return;
                    }

                    Logger.Write($"File upload started by {requesterID}.");
                    var sharedFilePath = Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), "RemotelySharedFiles")).FullName;

                    foreach (var fileID in fileIDs)
                    {
                        var url            = $"{ConnectionInfo.Host}/API/FileSharing/{fileID}";
                        var wr             = WebRequest.CreateHttp(url);
                        using var response = await wr.GetResponseAsync();
                        var cd             = response.Headers["Content-Disposition"];
                        var filename       = cd
                                             .Split(";")
                                             .FirstOrDefault(x => x.Trim()
                                                             .StartsWith("filename"))
                                             .Split("=")[1];

                        var legalChars = filename.ToCharArray().Where(x => !Path.GetInvalidFileNameChars().Any(y => x == y));

                        filename = new string(legalChars.ToArray());

                        using var rs = response.GetResponseStream();
                        using var fs = new FileStream(Path.Combine(sharedFilePath, filename), FileMode.Create);
                        rs.CopyTo(fs);
                    }
                    await HubConnection.SendAsync("TransferCompleted", transferID, requesterID);
                }
                catch (Exception ex)
                {
                    Logger.Write(ex);
                }
            });
            HubConnection.On("DeployScript", async(string mode, string fileID, string commandResultID, string requesterID) =>
            {
                try
                {
                    if (!IsServerVerified)
                    {
                        Logger.Write($"Script deploy attempted before server was verified.  Mode: {mode}.  File ID: {fileID}.  Sender: {requesterID}", EventType.Warning);
                        return;
                    }

                    await ScriptRunner.RunScript(mode, fileID, commandResultID, requesterID, HubConnection);
                }
                catch (Exception ex)
                {
                    Logger.Write(ex);
                }
            });

            HubConnection.On("ReinstallAgent", async() =>
            {
                try
                {
                    await Updater.InstallLatestVersion();
                }
                catch (Exception ex)
                {
                    Logger.Write(ex);
                }
            });

            HubConnection.On("UninstallAgent", () =>
            {
                try
                {
                    Uninstaller.UninstallAgent();
                }
                catch (Exception ex)
                {
                    Logger.Write(ex);
                }
            });

            HubConnection.On("RemoteControl", async(string requesterID, string serviceID) =>
            {
                try
                {
                    if (!IsServerVerified)
                    {
                        Logger.Write("Remote control attempted before server was verified.", EventType.Warning);
                        return;
                    }
                    await AppLauncher.LaunchRemoteControl(-1, requesterID, serviceID, HubConnection);
                }
                catch (Exception ex)
                {
                    Logger.Write(ex);
                }
            });
            HubConnection.On("RestartScreenCaster", async(List <string> viewerIDs, string serviceID, string requesterID) =>
            {
                try
                {
                    if (!IsServerVerified)
                    {
                        Logger.Write("Remote control attempted before server was verified.", EventType.Warning);
                        return;
                    }
                    await AppLauncher.RestartScreenCaster(viewerIDs, serviceID, requesterID, HubConnection);
                }
                catch (Exception ex)
                {
                    Logger.Write(ex);
                }
            });
            HubConnection.On("CtrlAltDel", () =>
            {
                if (!IsServerVerified)
                {
                    Logger.Write("CtrlAltDel attempted before server was verified.", EventType.Warning);
                    return;
                }
                User32.SendSAS(false);
            });

            HubConnection.On("TriggerHeartbeat", async() =>
            {
                await SendHeartbeat();
            });

            HubConnection.On("ServerVerificationToken", (string verificationToken) =>
            {
                if (verificationToken == ConnectionInfo.ServerVerificationToken)
                {
                    IsServerVerified = true;
                }
                else
                {
                    Logger.Write($"Server sent an incorrect verification token.  Token Sent: {verificationToken}.", EventType.Warning);
                    return;
                }
            });
        }
Exemplo n.º 5
0
        private static async Task ExecuteCommand(string mode, string command, string commandID, string senderConnectionID)
        {
            if (!IsServerVerified)
            {
                Logger.Write($"Command attempted before server was verified.  Mode: {mode}.  Command: {command}.  Sender: {senderConnectionID}");
                Uninstaller.UninstallAgent();
                return;
            }
            try
            {
                switch (mode.ToLower())
                {
                case "pscore":
                {
                    var psCoreResult     = PSCore.GetCurrent(senderConnectionID).WriteInput(command, commandID);
                    var serializedResult = JsonConvert.SerializeObject(psCoreResult);
                    if (Encoding.UTF8.GetBytes(serializedResult).Length > 400000)
                    {
                        SendResultsViaAjax("PSCore", psCoreResult);
                        await HubConnection.InvokeAsync("PSCoreResultViaAjax", commandID);
                    }
                    else
                    {
                        await HubConnection.InvokeAsync("PSCoreResult", psCoreResult);
                    }
                    break;
                }

                case "winps":
                    if (OSUtils.IsWindows)
                    {
                        var result           = WindowsPS.GetCurrent(senderConnectionID).WriteInput(command, commandID);
                        var serializedResult = JsonConvert.SerializeObject(result);
                        if (Encoding.UTF8.GetBytes(serializedResult).Length > 400000)
                        {
                            SendResultsViaAjax("WinPS", result);
                            await HubConnection.InvokeAsync("WinPSResultViaAjax", commandID);
                        }
                        else
                        {
                            await HubConnection.InvokeAsync("CommandResult", result);
                        }
                    }
                    break;

                case "cmd":
                    if (OSUtils.IsWindows)
                    {
                        var result           = CMD.GetCurrent(senderConnectionID).WriteInput(command, commandID);
                        var serializedResult = JsonConvert.SerializeObject(result);
                        if (Encoding.UTF8.GetBytes(serializedResult).Length > 400000)
                        {
                            SendResultsViaAjax("CMD", result);
                            await HubConnection.InvokeAsync("CMDResultViaAjax", commandID);
                        }
                        else
                        {
                            await HubConnection.InvokeAsync("CommandResult", result);
                        }
                    }
                    break;

                case "bash":
                    if (OSUtils.IsLinux)
                    {
                        var result           = Bash.GetCurrent(senderConnectionID).WriteInput(command, commandID);
                        var serializedResult = JsonConvert.SerializeObject(result);
                        if (Encoding.UTF8.GetBytes(serializedResult).Length > 400000)
                        {
                            SendResultsViaAjax("Bash", result);
                        }
                        else
                        {
                            await HubConnection.InvokeAsync("CommandResult", result);
                        }
                    }
                    break;

                default:
                    break;
                }
            }
            catch (Exception ex)
            {
                Logger.Write(ex);
                await HubConnection.InvokeAsync("DisplayConsoleMessage", $"There was an error executing the command.  It has been logged on the client device.", senderConnectionID);
            }
        }
Exemplo n.º 6
0
        private static void RegisterMessageHandlers(HubConnection hubConnection)
        {
            hubConnection.On("ExecuteCommand", (async(string mode, string command, string commandID, string senderConnectionID) =>
            {
                await ExecuteCommand(mode, command, commandID, senderConnectionID);
            }));
            hubConnection.On("TransferFiles", async(string transferID, List <string> fileIDs, string requesterID) =>
            {
                Logger.Write($"File transfer started by {requesterID}.");
                var connectionInfo = Utilities.GetConnectionInfo();
                var sharedFilePath = Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), "RemotelySharedFiles")).FullName;

                foreach (var fileID in fileIDs)
                {
                    var url      = $"{connectionInfo.Host}/API/FileSharing/{fileID}";
                    var wr       = WebRequest.CreateHttp(url);
                    var response = await wr.GetResponseAsync();
                    var cd       = response.Headers["Content-Disposition"];
                    var filename = cd
                                   .Split(";")
                                   .FirstOrDefault(x => x.Trim()
                                                   .StartsWith("filename"))
                                   .Split("=")[1];

                    var legalChars = filename.ToCharArray().Where(x => !Path.GetInvalidFileNameChars().Any(y => x == y));

                    filename = new string(legalChars.ToArray());

                    using (var rs = response.GetResponseStream())
                    {
                        using (var fs = new FileStream(Path.Combine(sharedFilePath, filename), FileMode.Create))
                        {
                            rs.CopyTo(fs);
                        }
                    }
                }
                await HubConnection.InvokeAsync("TransferCompleted", transferID, requesterID);
            });
            hubConnection.On("DeployScript", async(string mode, string fileID, string commandContextID, string requesterID) => {
                var connectionInfo = Utilities.GetConnectionInfo();
                var sharedFilePath = Directory.CreateDirectory(Path.Combine(
                                                                   Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData),
                                                                   "Remotely",
                                                                   "SharedFiles"
                                                                   )).FullName;
                var webClient = new WebClient();

                var url      = $"{connectionInfo.Host}/API/FileSharing/{fileID}";
                var wr       = WebRequest.CreateHttp(url);
                var response = await wr.GetResponseAsync();
                var cd       = response.Headers["Content-Disposition"];
                var filename = cd.Split(";").FirstOrDefault(x => x.Trim().StartsWith("filename")).Split("=")[1];
                using (var rs = response.GetResponseStream())
                {
                    using (var sr = new StreamReader(rs))
                    {
                        var result = await sr.ReadToEndAsync();
                        await ExecuteCommand(mode, result, commandContextID, requesterID);
                    }
                }
            });
            hubConnection.On("UninstallClient", () =>
            {
                Uninstaller.UninstallAgent();
            });

            hubConnection.On("RemoteControl", async(string requesterID, string serviceID) =>
            {
                if (!IsServerVerified)
                {
                    Logger.Write("Remote control attempted before server was verified.");
                    Uninstaller.UninstallAgent();
                    return;
                }
                try
                {
                    var rcBinaryPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "ScreenCast", OSUtils.ScreenCastExecutableFileName);
                    if (!File.Exists(rcBinaryPath))
                    {
                        await hubConnection.InvokeAsync("DisplayConsoleMessage", "Remote control executable not found on target device.", requesterID);
                        return;
                    }


                    // Start ScreenCast.
                    await hubConnection.InvokeAsync("DisplayConsoleMessage", $"Starting remote control...", requesterID);
                    if (OSUtils.IsWindows)
                    {
                        if (Program.IsDebug)
                        {
                            Process.Start(rcBinaryPath, $"-mode Unattended -requester {requesterID} -serviceid {serviceID} -deviceid {ConnectionInfo.DeviceID} -host {Utilities.GetConnectionInfo().Host} -desktop default");
                        }
                        else
                        {
                            var result = Win32Interop.OpenInteractiveProcess(rcBinaryPath + $" -mode Unattended -requester {requesterID} -serviceid {serviceID} -deviceid {ConnectionInfo.DeviceID} -host {Utilities.GetConnectionInfo().Host} -desktop default", "default", true, out _);
                            if (!result)
                            {
                                await hubConnection.InvokeAsync("DisplayConsoleMessage", "Remote control failed to start on target device.", requesterID);
                            }
                        }
                    }
                    else if (OSUtils.IsLinux)
                    {
                        var users    = OSUtils.StartProcessWithResults("users", "");
                        var username = users?.Split()?.FirstOrDefault()?.Trim();
                        var homeDir  = OSUtils.StartProcessWithResults("sudo", $"-u {username} env | grep HOME")?.Split('=')?.Last();
                        var psi      = new ProcessStartInfo()
                        {
                            FileName  = "sudo",
                            Arguments = $"-u {username} {rcBinaryPath} -mode Unattended -requester {requesterID} -serviceid {serviceID} -deviceid {ConnectionInfo.DeviceID} -host {Utilities.GetConnectionInfo().Host} -desktop default & disown"
                        };
                        psi.Environment.Add("DISPLAY", ":0");
                        psi.Environment.Add("XAUTHORITY", $"{homeDir}/.Xauthority");
                        var casterProc = Process.Start(psi);
                        casterProc.WaitForExit();
                    }
                }
                catch (Exception ex)
                {
                    Logger.Write(ex);
                    await hubConnection.InvokeAsync("DisplayConsoleMessage", "Remote control failed to start on target device.", requesterID);
                    throw;
                }
            });
            hubConnection.On("RestartScreenCaster", async(List <string> viewerIDs, string serviceID, string requesterID) =>
            {
                if (!IsServerVerified)
                {
                    Logger.Write("Remote control attempted before server was verified.");
                    Uninstaller.UninstallAgent();
                    return;
                }
                try
                {
                    var rcBinaryPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "ScreenCast", OSUtils.ScreenCastExecutableFileName);
                    // Start ScreenCast.
                    if (OSUtils.IsWindows)
                    {
                        Logger.Write("Restarting screen caster.");
                        if (Program.IsDebug)
                        {
                            var proc      = Process.Start(rcBinaryPath, $"-mode Unattended -requester {requesterID} -serviceid {serviceID} -deviceid {ConnectionInfo.DeviceID} -host {Utilities.GetConnectionInfo().Host} -relaunch true -desktop default -viewers {String.Join(",", viewerIDs)}");
                            var stopwatch = Stopwatch.StartNew();
                            while (stopwatch.Elapsed.TotalSeconds < 10)
                            {
                                await Task.Delay(250);
                                if (Process.GetProcessesByName(Path.GetFileNameWithoutExtension(rcBinaryPath))?.Where(x => x.Id == proc.Id)?.Count() > 0 != true)
                                {
                                    Logger.Write("Restarting screen caster after failed relaunch.");
                                }
                            }
                        }
                        else
                        {
                            var result = Win32Interop.OpenInteractiveProcess(rcBinaryPath + $" -mode Unattended -requester {requesterID} -serviceid {serviceID} -deviceid {ConnectionInfo.DeviceID} -host {Utilities.GetConnectionInfo().Host} -relaunch true -desktop default -viewers {String.Join(",", viewerIDs)}", "default", true, out var procInfo);

                            if (result)
                            {
                                // This relaunch might have been prompted by a user logging out, which would close
                                // the screencaster process.  In that scenario, the relaunched process can get closed again
                                // while the Windows sign-out process is still occurring.  We'll wait a bit to make sure the
                                // relaunched process is still running.  If not, launch again.
                                var stopwatch = Stopwatch.StartNew();
                                while (stopwatch.Elapsed.TotalSeconds < 10)
                                {
                                    await Task.Delay(250);
                                    if (Process.GetProcessesByName(Path.GetFileNameWithoutExtension(rcBinaryPath))?.Where(x => x.Id == procInfo.dwProcessId)?.Count() > 0 != true)
                                    {
                                        Logger.Write("Restarting screen caster after failed relaunch.");
                                        result = Win32Interop.OpenInteractiveProcess(rcBinaryPath + $" -mode Unattended -requester {requesterID} -serviceid {serviceID} -deviceid {ConnectionInfo.DeviceID} -host {Utilities.GetConnectionInfo().Host} -relaunch true -desktop default -viewers {String.Join(",", viewerIDs)}", "default", true, out procInfo);
                                    }
                                }
                            }

                            if (!result)
                            {
                                Logger.Write("Failed to relaunch screen caster.");
                                await hubConnection.InvokeAsync("SendConnectionFailedToViewers", viewerIDs);
                                await hubConnection.InvokeAsync("DisplayConsoleMessage", "Remote control failed to start on target device.", requesterID);
                            }
                        }
                    }
                    else if (OSUtils.IsLinux)
                    {
                        var users    = OSUtils.StartProcessWithResults("users", "");
                        var username = users?.Split()?.FirstOrDefault()?.Trim();
                        var homeDir  = OSUtils.StartProcessWithResults("sudo", $"-u {username} env | grep HOME")?.Split('=')?.Last();
                        var psi      = new ProcessStartInfo()
                        {
                            FileName  = "sudo",
                            Arguments = $"-u {username} {rcBinaryPath} -mode Unattended -requester {requesterID} -serviceid {serviceID} -deviceid {ConnectionInfo.DeviceID} -host {Utilities.GetConnectionInfo().Host} -relaunch true -desktop default -viewers {String.Join(",", viewerIDs)} & disown"
                        };
                        psi.Environment.Add("DISPLAY", ":0");
                        psi.Environment.Add("XAUTHORITY", $"{homeDir}/.Xauthority");
                        var casterProc = Process.Start(psi);
                        casterProc.WaitForExit();
                    }
                }
                catch (Exception ex)
                {
                    await hubConnection.InvokeAsync("SendConnectionFailedToViewers", viewerIDs);
                    Logger.Write(ex);
                    throw;
                }
            });
            hubConnection.On("CtrlAltDel", () =>
            {
                User32.SendSAS(false);
            });

            hubConnection.On("ServerVerificationToken", (string verificationToken) =>
            {
                if (verificationToken == Utilities.GetConnectionInfo().ServerVerificationToken)
                {
                    IsServerVerified = true;
                    if (!Program.IsDebug)
                    {
                        Updater.CheckForCoreUpdates();
                    }
                }
                else
                {
                    Logger.Write($"Server sent an incorrect verification token.  Token Sent: {verificationToken}.");
                    Uninstaller.UninstallAgent();
                    return;
                }
            });
        }
Exemplo n.º 7
0
        private void RegisterMessageHandlers()
        {
            HubConnection.On("Chat", async(string message, string senderConnectionID) => {
                await ChatService.SendMessage(message, senderConnectionID, HubConnection);
            });
            HubConnection.On("ExecuteCommand", (async(string mode, string command, string commandID, string senderConnectionID) =>
            {
                if (!IsServerVerified)
                {
                    Logger.Write($"Command attempted before server was verified.  Mode: {mode}.  Command: {command}.  Sender: {senderConnectionID}");
                    Uninstaller.UninstallAgent();
                    return;
                }

                await CommandExecutor.ExecuteCommand(mode, command, commandID, senderConnectionID, HubConnection);
            }));
            HubConnection.On("TransferFiles", async(string transferID, List <string> fileIDs, string requesterID) =>
            {
                Logger.Write($"File transfer started by {requesterID}.");
                var sharedFilePath = Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), "RemotelySharedFiles")).FullName;

                foreach (var fileID in fileIDs)
                {
                    var url      = $"{ConnectionInfo.Host}/API/FileSharing/{fileID}";
                    var wr       = WebRequest.CreateHttp(url);
                    var response = await wr.GetResponseAsync();
                    var cd       = response.Headers["Content-Disposition"];
                    var filename = cd
                                   .Split(";")
                                   .FirstOrDefault(x => x.Trim()
                                                   .StartsWith("filename"))
                                   .Split("=")[1];

                    var legalChars = filename.ToCharArray().Where(x => !Path.GetInvalidFileNameChars().Any(y => x == y));

                    filename = new string(legalChars.ToArray());

                    using (var rs = response.GetResponseStream())
                    {
                        using (var fs = new FileStream(Path.Combine(sharedFilePath, filename), FileMode.Create))
                        {
                            rs.CopyTo(fs);
                        }
                    }
                }
                await this.HubConnection.InvokeAsync("TransferCompleted", transferID, requesterID);
            });
            HubConnection.On("DeployScript", async(string mode, string fileID, string commandContextID, string requesterID) => {
                if (!IsServerVerified)
                {
                    Logger.Write($"Script deploy attempted before server was verified.  Mode: {mode}.  File ID: {fileID}.  Sender: {requesterID}");
                    Uninstaller.UninstallAgent();
                    return;
                }

                await ScriptRunner.RunScript(mode, fileID, commandContextID, requesterID, HubConnection);
            });
            HubConnection.On("UninstallClient", () =>
            {
                Uninstaller.UninstallAgent();
            });

            HubConnection.On("RemoteControl", async(string requesterID, string serviceID) =>
            {
                if (!IsServerVerified)
                {
                    Logger.Write("Remote control attempted before server was verified.");
                    Uninstaller.UninstallAgent();
                    return;
                }
                await AppLauncher.LaunchRemoteControl(requesterID, serviceID, HubConnection);
            });
            HubConnection.On("RestartScreenCaster", async(List <string> viewerIDs, string serviceID, string requesterID) =>
            {
                if (!IsServerVerified)
                {
                    Logger.Write("Remote control attempted before server was verified.");
                    Uninstaller.UninstallAgent();
                    return;
                }
                await AppLauncher.RestartScreenCaster(viewerIDs, serviceID, requesterID, HubConnection);
            });
            HubConnection.On("CtrlAltDel", () =>
            {
                User32.SendSAS(false);
            });

            HubConnection.On("ServerVerificationToken", (string verificationToken) =>
            {
                if (verificationToken == ConnectionInfo.ServerVerificationToken)
                {
                    IsServerVerified = true;
                    if (!Program.IsDebug)
                    {
                        _ = Task.Run(Updater.CheckForUpdates);
                    }
                }
                else
                {
                    Logger.Write($"Server sent an incorrect verification token.  Token Sent: {verificationToken}.");
                    Uninstaller.UninstallAgent();
                    return;
                }
            });
        }