Exemple #1
0
        public async Task <string> Kill(Grunt grunt, GruntCommand command, List <ParsedParameter> parameters)
        {
            if (parameters.Count() != 1)
            {
                StringBuilder toPrint = new StringBuilder();
                toPrint.Append(EliteConsole.PrintFormattedErrorLine("Usage: Kill"));
                return(toPrint.ToString());
            }
            GruntTask killTask = await _context.GetGruntTaskByName("Kill");

            await _context.CreateGruntTasking(new GruntTasking
            {
                Id             = 0,
                GruntId        = grunt.Id,
                GruntTaskId    = killTask.Id,
                GruntTask      = killTask,
                Name           = Guid.NewGuid().ToString().Replace("-", "").Substring(0, 10),
                Status         = GruntTaskingStatus.Uninitialized,
                Type           = GruntTaskingType.Kill,
                GruntCommand   = command,
                GruntCommandId = command.Id
            }, _grunthub);

            return("");
        }
Exemple #2
0
        public async Task <string> Connect(Grunt grunt, GruntCommand command, List <ParsedParameter> parameters)
        {
            string        Name    = "Connect";
            StringBuilder toPrint = new StringBuilder();

            if (parameters.Count < 2 || parameters.Count > 3 || !parameters[0].Value.Equals(Name, StringComparison.OrdinalIgnoreCase))
            {
                return(EliteConsole.PrintFormattedErrorLine("Usage: Connect <ComputerName> [ <PipeName> ]"));
            }
            GruntTask connectTask = await _context.GetGruntTaskByName("Connect");

            string PipeName = "gruntsvc";

            if (parameters.Count == 3)
            {
                PipeName = parameters[2].Value;
            }
            await _context.CreateGruntTasking(new GruntTasking
            {
                Id          = 0,
                GruntId     = grunt.Id,
                GruntTaskId = connectTask.Id,
                GruntTask   = connectTask,
                Name        = Guid.NewGuid().ToString().Replace("-", "").Substring(0, 10),
                Status      = GruntTaskingStatus.Uninitialized,
                Type        = GruntTaskingType.Connect,
                Parameters  = new List <string> {
                    parameters[1].Value, PipeName
                },
                GruntCommand   = command,
                GruntCommandId = command.Id
            }, _grunthub);

            return(toPrint.ToString());
        }
Exemple #3
0
        public async Task <string> History(Grunt grunt, List <ParsedParameter> parameters)
        {
            string Name = "History";

            if (parameters.Count() != 2 || !parameters[0].Value.Equals(Name, StringComparison.OrdinalIgnoreCase))
            {
                StringBuilder toPrint1 = new StringBuilder();
                toPrint1.Append(EliteConsole.PrintFormattedErrorLine("Usage: History <tasking_name>"));
                return(toPrint1.ToString());
            }
            StringBuilder toPrint = new StringBuilder();
            GruntTasking  tasking = await _context.GruntTaskings.FirstOrDefaultAsync(GT => GT.Name == parameters[1].Value);

            if (tasking == null)
            {
                toPrint.Append(EliteConsole.PrintFormattedErrorLine("Invalid History command, invalid tasking name. Usage is: History [ <tasking_name> ]"));
            }
            else
            {
                GruntCommand command = await _context.GruntCommands
                                       .Include(GC => GC.CommandOutput)
                                       .Include(GC => GC.User)
                                       .FirstOrDefaultAsync(GC => GC.Id == tasking.GruntCommandId);

                toPrint.Append(EliteConsole.PrintFormattedInfoLine("[" + tasking.CompletionTime + " UTC] Grunt: " + grunt.Name + " " + "GruntTasking: " + tasking.Name));
                toPrint.Append(EliteConsole.PrintInfoLine("(" + command.User.UserName + ") > " + command.Command));
                toPrint.Append(EliteConsole.PrintInfoLine(command.CommandOutput.Output));
            }
            return(toPrint.ToString());
        }
Exemple #4
0
        public async Task <string> Jobs(Grunt grunt, GruntCommand command, List <ParsedParameter> parameters)
        {
            string Name = "Jobs";

            if (parameters.Count != 1 || !parameters[0].Value.Equals(Name, StringComparison.OrdinalIgnoreCase))
            {
                return(EliteConsole.PrintFormattedErrorLine("Usage: Jobs"));
            }
            GruntTask jobsTask = await _context.GetGruntTaskByName("Jobs");

            await _context.CreateGruntTasking(new GruntTasking
            {
                Id          = 0,
                GruntId     = grunt.Id,
                GruntTaskId = jobsTask.Id,
                GruntTask   = jobsTask,
                Name        = Guid.NewGuid().ToString().Replace("-", "").Substring(0, 10),
                Status      = GruntTaskingStatus.Uninitialized,
                Type        = GruntTaskingType.Jobs,
                Parameters  = new List <string> {
                    "Jobs"
                },
                GruntCommand   = command,
                GruntCommandId = command.Id
            }, _grunthub);

            return("");
        }
Exemple #5
0
        public static async void DoReceiveCommandEvent(string command, string taskingEvent)
        {
            try
            {
                JObject o  = JObject.Parse(taskingEvent);
                JObject o2 = JObject.Parse(command);

                // Because this call is not awaited, execution of the current method continues before the call is completed
                Task.Run(() =>
                {
                    GruntCommand comm = JsonConvert.DeserializeObject <GruntCommand>(command);
                    if (o["messageHeader"].ToString().Contains("completed") && !o["messageBody"].ToString().Contains("Grunts.CommandOutput"))
                    {
                        try
                        {
                            Program.tasks[Program.tasks.FindIndex(c => c.Id == comm.Id)] = comm;
                        }
                        catch
                        {
                            Console.WriteLine("[Forerunner] Returned tasks didn't originate from us. Handling via GlobalFunc");
                            string scriptCode = File.ReadAllText("Forerunner.lua");
                            Script script     = Common.GetScript(comm.Grunt, comm);
                            script.DoString(scriptCode);
                            Task.Run(() => { script.Call(script.Globals["OnGlobalOutput"], comm.CommandOutput.Output ?? ""); });
                        }
                    }
                });
            }
            catch (Exception e)
            {
                Console.WriteLine("[Forerunner] An error occured: {0}", e.Message);
            }
        }
Exemple #6
0
        // POST: /grunttasking/create
        public async Task <IActionResult> Create(GruntTasking tasking)
        {
            try
            {
                CovenantUser currentUser = await _context.GetCurrentUser(_userManager, HttpContext.User);

                tasking.Grunt = await _context.GetGrunt(tasking.GruntId);

                tasking.GruntTask = await _context.GetGruntTask(tasking.GruntTaskId);

                GruntCommand createdCommand = await _context.CreateGruntCommand(new GruntCommand
                {
                    Command         = GetCommand(tasking),
                    CommandTime     = DateTime.UtcNow,
                    CommandOutputId = 0,
                    CommandOutput   = new CommandOutput(),
                    User            = currentUser,
                    GruntId         = tasking.Grunt.Id,
                    Grunt           = tasking.Grunt
                }, _grunthub);

                tasking.GruntCommand   = createdCommand;
                tasking.GruntCommandId = createdCommand.Id;

                GruntTasking created = await _context.CreateGruntTasking(tasking);

                return(RedirectToAction(nameof(Interact), new { id = created.Id }));
            }
            catch (Exception e) when(e is ControllerNotFoundException || e is ControllerBadRequestException || e is ControllerUnauthorizedException)
            {
                return(RedirectToAction(nameof(Index)));
            }
        }
Exemple #7
0
        public async Task <string> SharpShell(Grunt grunt, GruntCommand command, List <ParsedParameter> parameters)
        {
            if (parameters.Count() < 2 || !parameters[0].Value.Equals("SharpShell", StringComparison.OrdinalIgnoreCase))
            {
                return(EliteConsole.PrintFormattedErrorLine("Usage: SharpShell <code>"));
            }
            string WrapperFunctionFormat =
                @"using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Security;
using System.Security.Principal;
using System.Collections.Generic;
using SharpSploit.Credentials;
using SharpSploit.Enumeration;
using SharpSploit.Execution;
using SharpSploit.Generic;
using SharpSploit.Misc;
public static class Task
{{
    public static string Execute()
    {{
        {0}
    }}
}}";

            string    csharpcode        = string.Join(" ", parameters.Skip(1).Select(P => P.Value).ToArray());
            GruntTask newSharpShellTask = await _context.CreateGruntTask(new GruntTask
            {
                Name           = "SharpShell-" + Utilities.CreateShortGuid(),
                AlternateNames = new List <string>(),
                Description    = "Execute custom c# code.",
                Code           = string.Format(WrapperFunctionFormat, csharpcode),
                Options        = new List <GruntTaskOption>()
            });

            await _context.AddAsync(new GruntTaskReferenceSourceLibrary
            {
                ReferenceSourceLibrary = await _context.GetReferenceSourceLibraryByName("SharpSploit"),
                GruntTask = newSharpShellTask
            });

            await _context.SaveChangesAsync();

            await _context.CreateGruntTasking(new GruntTasking
            {
                GruntId        = grunt.Id,
                GruntTaskId    = newSharpShellTask.Id,
                Type           = GruntTaskingType.Assembly,
                Status         = GruntTaskingStatus.Uninitialized,
                GruntCommandId = command.Id,
                GruntCommand   = command
            }, _grunthub);

            return("");
        }
Exemple #8
0
 public async Task <GruntTasking> StartTask(Grunt grunt, GruntTask task, GruntCommand command)
 {
     return(await _context.CreateGruntTasking(new GruntTasking
     {
         GruntTaskId = task.Id,
         GruntId = grunt.Id,
         Type = GruntTaskingType.Assembly,
         Status = GruntTaskingStatus.Uninitialized,
         GruntCommandId = command.Id,
         GruntCommand = command
     }, _grunthub));
 }
Exemple #9
0
        public async Task GetInteract(string gruntName, string input)
        {
            CovenantUser user = await _service.GetUser(this.Context.UserIdentifier);

            Grunt grunt = await _service.GetGruntByName(gruntName);

            GruntCommand command = await _service.InteractGrunt(grunt.Id, user.Id, input);

            if (!string.IsNullOrWhiteSpace(command.CommandOutput.Output))
            {
                await this.Clients.Caller.SendAsync("ReceiveCommandOutput", command);
            }
        }
Exemple #10
0
        public async Task GetInteract(string gruntName, string input)
        {
            CovenantUser user = await _context.GetUserByUsername(this.Context.User.Identity.Name);

            Grunt grunt = await _context.GetGruntByName(gruntName);

            GruntCommand command = await interact.Input(user, grunt, input);

            if (!string.IsNullOrWhiteSpace(command.CommandOutput.Output))
            {
                await this.Clients.Caller.SendAsync("ReceiveCommandOutput", command);
            }
        }
Exemple #11
0
        // POST: /grunttasking/create
        public async Task <IActionResult> Create(GruntTasking tasking)
        {
            try
            {
                CovenantUser currentUser = await _context.GetCurrentUser(_userManager, HttpContext.User);

                tasking.Grunt = await _context.GetGrunt(tasking.GruntId);

                tasking.GruntTask = await _context.GetGruntTask(tasking.GruntTaskId);

                tasking.Type = tasking.GruntTask.TaskingType;
                for (int i = 0; i < Math.Min(tasking.Parameters.Count, tasking.GruntTask.Options.Count); i++)
                {
                    if (tasking.Parameters[i] == null)
                    {
                        tasking.Parameters[i] = "";
                        tasking.GruntTask.Options[i].Value = "";
                    }
                    else
                    {
                        tasking.GruntTask.Options[i].Value = tasking.Parameters[i];
                    }
                }
                for (int i = tasking.Parameters.Count; i < tasking.GruntTask.Options.Count; i++)
                {
                    tasking.GruntTask.Options[i].Value = "";
                }
                GruntCommand createdCommand = await _context.CreateGruntCommand(new GruntCommand
                {
                    Command         = GetCommand(tasking),
                    CommandTime     = DateTime.UtcNow,
                    CommandOutputId = 0,
                    CommandOutput   = new CommandOutput(),
                    User            = currentUser,
                    GruntId         = tasking.Grunt.Id,
                    Grunt           = tasking.Grunt
                }, _grunthub, _eventhub);

                tasking.GruntCommand   = createdCommand;
                tasking.GruntCommandId = createdCommand.Id;

                GruntTasking created = await _context.CreateGruntTasking(tasking, _grunthub);

                return(RedirectToAction(nameof(Interact), new { id = created.Id }));
            }
            catch (Exception e) when(e is ControllerNotFoundException || e is ControllerBadRequestException || e is ControllerUnauthorizedException)
            {
                return(RedirectToAction(nameof(Index)));
            }
        }
Exemple #12
0
        public async Task GetCommandOutput(int id)
        {
            GruntCommand command = await _context.GruntCommands
                                   .Where(GC => GC.Id == id)
                                   .Include(GC => GC.User)
                                   .Include(GC => GC.CommandOutput)
                                   .Include(GC => GC.GruntTasking)
                                   .ThenInclude(GC => GC.GruntTask)
                                   .FirstOrDefaultAsync();

            if (!string.IsNullOrWhiteSpace(command.CommandOutput.Output))
            {
                await this.Clients.Caller.SendAsync("ReceiveCommandOutput", command);
            }
        }
Exemple #13
0
        public async Task GetCommandOutput(int id)
        {
            GruntCommand command = await _service.GetGruntCommand(id);

            command.CommandOutput = command.CommandOutput ?? await _service.GetCommandOutput(command.CommandOutputId);

            command.User = command.User ?? await _service.GetUser(command.UserId);

            command.GruntTasking = command.GruntTasking ?? await _service.GetGruntTasking(command.GruntTaskingId ?? default);

            if (!string.IsNullOrWhiteSpace(command.CommandOutput.Output))
            {
                await this.Clients.Caller.SendAsync("ReceiveCommandOutput", command);
            }
        }
Exemple #14
0
 public async Task <ActionResult <GruntCommand> > EditGruntCommand([FromBody] GruntCommand gruntCommand)
 {
     try
     {
         return(await _context.EditGruntCommand(gruntCommand, _grunthub, _eventhub));
     }
     catch (ControllerNotFoundException e)
     {
         return(NotFound(e.Message));
     }
     catch (ControllerBadRequestException e)
     {
         return(BadRequest(e.Message));
     }
 }
Exemple #15
0
        public async Task <string> Disconnect(Grunt grunt, GruntCommand command, List <ParsedParameter> parameters)
        {
            string        Name    = "Disconnect";
            StringBuilder toPrint = new StringBuilder();

            if (parameters.Count != 2 || !parameters[0].Value.Equals(Name, StringComparison.OrdinalIgnoreCase))
            {
                return(EliteConsole.PrintFormattedErrorLine("Usage: Disconnect <grunt_name>"));
            }
            Grunt disconnectGrunt = await _context.Grunts.FirstOrDefaultAsync(G => G.GUID.Equals(parameters[1].Value, StringComparison.OrdinalIgnoreCase));

            if (disconnectGrunt == null)
            {
                toPrint.Append(EliteConsole.PrintFormattedErrorLine("Invalid GruntName selected: " + parameters[1].Value));
                toPrint.Append(EliteConsole.PrintFormattedErrorLine("Usage: Disconnect <grunt_name>"));
                return(toPrint.ToString());
            }
            List <string> childrenGruntGuids = grunt.Children.ToList();

            if (!childrenGruntGuids.Contains(disconnectGrunt.GUID, StringComparer.OrdinalIgnoreCase))
            {
                toPrint.Append(EliteConsole.PrintFormattedErrorLine("Grunt: \"" + parameters[1].Value + "\" is not a child Grunt"));
                toPrint.Append(EliteConsole.PrintFormattedErrorLine("Usage: Disconnect <grunt_name>"));
                return(toPrint.ToString());
            }
            GruntTask disconnectTask = await _context.GetGruntTaskByName("Disconnect");

            await _context.CreateGruntTasking(new GruntTasking
            {
                Id          = 0,
                GruntId     = grunt.Id,
                GruntTaskId = disconnectTask.Id,
                GruntTask   = disconnectTask,
                Name        = Guid.NewGuid().ToString().Replace("-", "").Substring(0, 10),
                Status      = GruntTaskingStatus.Uninitialized,
                Type        = GruntTaskingType.Disconnect,
                Parameters  = new List <string> {
                    disconnectGrunt.GUID
                },
                GruntCommand   = command,
                GruntCommandId = command.Id
            }, _grunthub);

            return(toPrint.ToString());
        }
Exemple #16
0
        public static string GruntExec(string gruntName, string command)
        {
            Grunt        g   = Program.covenantConnection.ApiGruntsByNameGet(gruntName);
            GruntCommand res = Program.covenantConnection.ApiGruntsByIdInteractPost((int)g.Id, command);

            Program.tasks.Add(res);

            int      index       = Program.tasks.FindIndex(c => c.Id == res.Id);
            DateTime timeoutTime = DateTime.UtcNow.AddMinutes(60);

            while (String.IsNullOrEmpty(Program.tasks[index].CommandOutput.Output))
            {
                if (DateTime.Compare(DateTime.UtcNow, timeoutTime) > 0)
                {
                    return("[Forerunner] Task Failed: No Response");
                }
            }
            return(Program.tasks[index].CommandOutput.Output);
        }
Exemple #17
0
        public async Task <ActionResult <GruntCommand> > CreateGruntCommand([FromBody] GruntCommand gruntCommand)
        {
            try
            {
                gruntCommand.Grunt = await _context.GetGrunt(gruntCommand.GruntId);

                GruntCommand createdCommand = await _context.CreateGruntCommand(gruntCommand, _grunthub, _eventhub);

                return(CreatedAtRoute(nameof(GetGruntCommand), new { id = createdCommand.Id }, createdCommand));
            }
            catch (ControllerNotFoundException e)
            {
                return(NotFound(e.Message));
            }
            catch (ControllerBadRequestException e)
            {
                return(BadRequest(e.Message));
            }
        }
        public async Task <ActionResult <GruntCommand> > InteractGrunt(int id, [FromBody] string command)
        {
            try
            {
                CovenantUser user = await _service.GetCurrentUser(this.HttpContext.User);

                GruntCommand gruntCommand = await _service.InteractGrunt(id, user.Id, command);

                return(CreatedAtRoute("GetGruntCommand", new { id = gruntCommand.Id }, gruntCommand));
            }
            catch (ControllerNotFoundException e)
            {
                return(NotFound(e.Message));
            }
            catch (ControllerBadRequestException e)
            {
                return(BadRequest(e.Message));
            }
        }
Exemple #19
0
        public static Script GetScript(Grunt g, GruntCommand comm = null)
        {
            Script script = new Script();

            script.Globals["GruntExec"]             = (Func <string, string, string>)GruntHub.GruntExec;
            script.Globals["WriteToLog"]            = (Func <string, string>)WriteToLog;
            script.Globals["SendSlackNotification"] = (Func <string, string, string, string>)sendSlackNotification;
            if (!(g is null))
            {
                script.Globals["gruntName"] = g.Name ?? "";
                script.Globals["gruntID"]   = g.Id.ToString() ?? "";
                script.Globals["gruntGUID"] = g.Guid;
                //script.Globals["gruntListener"] = g.Listener.Name ?? "";
                script.Globals["gruntHostname"]    = g.Hostname ?? "";
                script.Globals["gruntIntegrity"]   = g.Integrity.ToString() ?? "";
                script.Globals["gruntIP"]          = g.IpAddress ?? "";
                script.Globals["gruntOS"]          = g.OperatingSystem ?? "";
                script.Globals["gruntProcess"]     = g.Process ?? "";
                script.Globals["gruntDomain"]      = g.UserDomainName ?? "";
                script.Globals["gruntUser"]        = g.UserName ?? "";
                script.Globals["gruntLastCheckIn"] = g.LastCheckIn.ToString() ?? "";
            }
Exemple #20
0
        public async static Task SendCommandEvent(IHubContext <GruntHub> context, Event taskingEvent, GruntCommand command)
        {
            await context.Clients.Group(taskingEvent.Context).SendAsync("ReceiveCommandEvent", command, taskingEvent);

            if (taskingEvent.Context != "*")
            {
                await context.Clients.Group("*").SendAsync("ReceiveCommandEvent", command, taskingEvent);
            }
        }
Exemple #21
0
 public async Task NotifyEditGruntCommand(object sender, GruntCommand command)
 {
     await Task.Run(() => this.OnEditGruntCommand(sender, command));
 }
Exemple #22
0
        public async Task <string> Set(Grunt grunt, GruntCommand command, List <ParsedParameter> parameters)
        {
            if (parameters.Count != 3)
            {
                return(EliteConsole.PrintFormattedErrorLine("Usage: Set (Delay | JitterPercent | ConnectAttempts) <value>"));
            }

            if (int.TryParse(parameters[2].Value, out int n))
            {
                GruntTask setTask = await _context.GetGruntTaskByName("Set");

                if (parameters[1].Value.Equals("delay", StringComparison.OrdinalIgnoreCase))
                {
                    grunt.Delay = n;
                    await _context.CreateGruntTasking(new GruntTasking
                    {
                        Id          = 0,
                        GruntId     = grunt.Id,
                        Grunt       = grunt,
                        GruntTaskId = setTask.Id,
                        GruntTask   = setTask,
                        Status      = GruntTaskingStatus.Uninitialized,
                        Type        = GruntTaskingType.SetDelay,
                        Parameters  = new List <string> {
                            grunt.Delay.ToString()
                        },
                        GruntCommand   = command,
                        GruntCommandId = command.Id
                    }, _grunthub);
                }
                else if (parameters[1].Value.Equals("jitterpercent", StringComparison.OrdinalIgnoreCase))
                {
                    grunt.JitterPercent = n;
                    await _context.CreateGruntTasking(new GruntTasking
                    {
                        Id          = 0,
                        GruntId     = grunt.Id,
                        Grunt       = grunt,
                        GruntTaskId = setTask.Id,
                        GruntTask   = setTask,
                        Status      = GruntTaskingStatus.Uninitialized,
                        Type        = GruntTaskingType.SetJitter,
                        Parameters  = new List <string> {
                            grunt.JitterPercent.ToString()
                        },
                        GruntCommand   = command,
                        GruntCommandId = command.Id
                    }, _grunthub);
                }
                else if (parameters[1].Value.Equals("connectattempts", StringComparison.OrdinalIgnoreCase))
                {
                    grunt.ConnectAttempts = n;
                    await _context.CreateGruntTasking(new GruntTasking
                    {
                        Id          = 0,
                        GruntId     = grunt.Id,
                        Grunt       = grunt,
                        GruntTaskId = setTask.Id,
                        GruntTask   = setTask,
                        Status      = GruntTaskingStatus.Uninitialized,
                        Type        = GruntTaskingType.SetConnectAttempts,
                        Parameters  = new List <string> {
                            grunt.ConnectAttempts.ToString()
                        },
                        GruntCommand   = command,
                        GruntCommandId = command.Id
                    }, _grunthub);
                }
                return("");
            }
            return(EliteConsole.PrintFormattedErrorLine("Usage: Set (Delay | JitterPercent | ConnectAttempts) <value>"));
        }
Exemple #23
0
 public Task <GruntCommand> CreateGruntCommand(GruntCommand command)
 {
     return(_connection.InvokeAsync <GruntCommand>("CreateGruntCommand", command));
 }
Exemple #24
0
 public Task <GruntCommand> EditGruntCommand(GruntCommand command)
 {
     return(_connection.InvokeAsync <GruntCommand>("EditGruntCommand", command));
 }
Exemple #25
0
        public async Task <GruntCommand> Input(CovenantUser user, Grunt grunt, string UserInput)
        {
            GruntCommand GruntCommand = await _context.CreateGruntCommand(new GruntCommand
            {
                Command         = GetCommandFromInput(UserInput),
                CommandTime     = DateTime.UtcNow,
                User            = user,
                GruntId         = grunt.Id,
                Grunt           = grunt,
                CommandOutputId = 0,
                CommandOutput   = new CommandOutput()
            }, _grunthub, _eventhub);

            List <ParsedParameter> parameters = ParseParameters(UserInput).ToList();
            GruntTask commandTask             = null;

            try
            {
                commandTask = await _context.GetGruntTaskByName(parameters.FirstOrDefault().Value);

                if (commandTask.Options.Count == 1 && new List <string> {
                    "Command", "ShellCommand", "PowerShellCommand", "Code"
                }.Contains(commandTask.Options[0].Name))
                {
                    parameters = new List <ParsedParameter>
                    {
                        new ParsedParameter
                        {
                            Value = commandTask.Name, Label = "", IsLabeled = false, Position = 0
                        },
                        new ParsedParameter
                        {
                            Value = UserInput.Substring(UserInput.IndexOf(" ", StringComparison.Ordinal) + 1).Trim('"'),
                            Label = "", IsLabeled = false, Position = 0
                        }
                    };
                }
            }
            catch (ControllerNotFoundException) { }

            string output = "";

            if (parameters.FirstOrDefault().Value.ToLower() == "show")
            {
                output = await Show(grunt);
            }
            else if (parameters.FirstOrDefault().Value.ToLower() == "help")
            {
                output = await Help(parameters);
            }
            else if (parameters.FirstOrDefault().Value.ToLower() == "sharpshell")
            {
                output = await SharpShell(grunt, GruntCommand, parameters);
            }
            else if (parameters.FirstOrDefault().Value.ToLower() == "kill")
            {
                output = await Kill(grunt, GruntCommand, parameters);
            }
            else if (parameters.FirstOrDefault().Value.ToLower() == "set")
            {
                output = await Set(grunt, GruntCommand, parameters);
            }
            else if (parameters.FirstOrDefault().Value.ToLower() == "history")
            {
                output = await History(grunt, parameters);
            }
            else if (parameters.FirstOrDefault().Value.ToLower() == "connect")
            {
                output = await Connect(grunt, GruntCommand, parameters);
            }
            else if (parameters.FirstOrDefault().Value.ToLower() == "disconnect")
            {
                output = await Disconnect(grunt, GruntCommand, parameters);
            }
            else if (parameters.FirstOrDefault().Value.ToLower() == "jobs")
            {
                output = await Jobs(grunt, GruntCommand, parameters);
            }
            else if (parameters.FirstOrDefault().Value.ToLower() == "note")
            {
                grunt.Note = string.Join(" ", parameters.Skip(1).Select(P => P.Value).ToArray());
                await _context.EditGrunt(grunt, user, _grunthub, _eventhub);

                output = "Note: " + grunt.Note;
            }
            else if (parameters.FirstOrDefault().Value.ToLower() == "powershellimport")
            {
                grunt.PowerShellImport = parameters.Count >= 2 ? parameters[1].Value : "";
                await _context.EditGrunt(grunt, user, _grunthub, _eventhub);

                output = "PowerShell Imported";
            }
            else if (commandTask != null)
            {
                parameters = parameters.Skip(1).ToList();
                if (parameters.Count() < commandTask.Options.Count(O => !O.Optional))
                {
                    _context.Entry(GruntCommand).State = EntityState.Detached;
                    GruntCommand.CommandOutput.Output  = EliteConsole.PrintFormattedErrorLine(GetUsage(commandTask));
                    return(await _context.EditGruntCommand(GruntCommand, _grunthub, _eventhub));
                }
                // All options begin unassigned
                List <bool> OptionAssignments = commandTask.Options.Select(O => false).ToList();
                commandTask.Options.ForEach(O => O.Value = "");
                for (int i = 0; i < parameters.Count; i++)
                {
                    if (parameters[i].IsLabeled)
                    {
                        var option = commandTask.Options.FirstOrDefault(O => O.Name.Equals(parameters[i].Label, StringComparison.OrdinalIgnoreCase));
                        option.Value = parameters[i].Value;
                        OptionAssignments[commandTask.Options.IndexOf(option)] = true;
                    }
                    else
                    {
                        GruntTaskOption nextOption = null;
                        // Find next unassigned option
                        for (int j = 0; j < commandTask.Options.Count; j++)
                        {
                            if (!OptionAssignments[j])
                            {
                                nextOption           = commandTask.Options[j];
                                OptionAssignments[j] = true;
                                break;
                            }
                        }
                        if (nextOption == null)
                        {
                            // This is an extra parameter
                            _context.Entry(GruntCommand).State = EntityState.Detached;
                            GruntCommand.CommandOutput.Output  = EliteConsole.PrintFormattedErrorLine(GetUsage(commandTask));
                            return(await _context.EditGruntCommand(GruntCommand, _grunthub, _eventhub));
                        }
                        nextOption.Value = parameters[i].Value;
                    }
                }

                // Check for unassigned required options
                for (int i = 0; i < commandTask.Options.Count; i++)
                {
                    if (!OptionAssignments[i] && !commandTask.Options[i].Optional)
                    {
                        // This is an extra parameter
                        StringBuilder toPrint = new StringBuilder();
                        toPrint.Append(EliteConsole.PrintFormattedErrorLine(commandTask.Options[i].Name + " is required."));
                        toPrint.Append(EliteConsole.PrintFormattedErrorLine(GetUsage(commandTask)));
                        _context.Entry(GruntCommand).State = EntityState.Detached;
                        GruntCommand.CommandOutput.Output  = toPrint.ToString();
                        return(await _context.EditGruntCommand(GruntCommand, _grunthub, _eventhub));
                    }
                }
                // Parameters have parsed successfully
                commandTask = await _context.EditGruntTask(commandTask);
                await StartTask(grunt, commandTask, GruntCommand);
            }
            else
            {
                output = EliteConsole.PrintFormattedErrorLine("Unrecognized command");
            }
            _context.Entry(GruntCommand).State = EntityState.Detached;
            GruntCommand.CommandOutput.Output  = output;
            return(await _context.EditGruntCommand(GruntCommand, _grunthub, _eventhub));
        }