private static GruntEncryptedMessage Create(string GUID, byte[] message, byte[] key, GruntEncryptedMessageType Type = GruntEncryptedMessageType.Tasking) { byte[] encryptedMessagePacket = EncryptUtilities.AesEncrypt(message, key); byte[] encryptionIV = encryptedMessagePacket.Take(Common.AesIVLength).ToArray(); byte[] encryptedMessage = encryptedMessagePacket.TakeLast(encryptedMessagePacket.Length - Common.AesIVLength).ToArray(); byte[] hmac = EncryptUtilities.ComputeHMAC(encryptedMessage, key); return(new GruntEncryptedMessage { GUID = GUID, Type = Type, EncryptedMessage = Convert.ToBase64String(encryptedMessage), IV = Convert.ToBase64String(encryptionIV), HMAC = Convert.ToBase64String(hmac) }); }
public bool VerifyHMAC(byte[] Key) { if (IV == "" || EncryptedMessage == "" || HMAC == "" || Key.Length == 0) { return(false); } try { var hashedBytes = Convert.FromBase64String(this.EncryptedMessage); return(EncryptUtilities.VerifyHMAC(hashedBytes, Convert.FromBase64String(this.HMAC), Key)); } catch { return(false); } }
public static byte[] GruntRSAEncrypt(Grunt grunt, byte[] toEncrypt) { return(EncryptUtilities.RSAEncrypt(toEncrypt, Common.CovenantEncoding.GetString(Convert.FromBase64String(grunt.GruntRSAPublicKey)))); }
private async Task <ActionResult> PostStage0(Grunt egressGrunt, Grunt targetGrunt, ModelUtilities.GruntEncryptedMessage gruntStage0Response) { if (targetGrunt == null || !gruntStage0Response.VerifyHMAC(Convert.FromBase64String(targetGrunt.GruntSharedSecretPassword))) { // Always return NotFound, don't give away unnecessary info return(NotFound()); } bool egressGruntExists = egressGrunt != null; string guid = gruntStage0Response.GUID.Substring(10); if (targetGrunt.Status != GruntStatus.Uninitialized) { // We create a new Grunt if this one is not uninitialized Grunt tempModel = new Grunt { Id = 0, Name = Utilities.CreateShortGuid(), Guid = guid, OriginalServerGuid = Utilities.CreateShortGuid(), Status = GruntStatus.Stage0, ListenerId = targetGrunt.ListenerId, Listener = targetGrunt.Listener, GruntSharedSecretPassword = targetGrunt.GruntSharedSecretPassword, CommType = targetGrunt.CommType, SmbPipeName = targetGrunt.SmbPipeName, Delay = targetGrunt.Delay, JitterPercent = targetGrunt.JitterPercent, KillDate = targetGrunt.KillDate, ConnectAttempts = targetGrunt.ConnectAttempts, DotNetFrameworkVersion = targetGrunt.DotNetFrameworkVersion, LastCheckIn = DateTime.UtcNow }; targetGrunt = await _client.ApiGruntsPostAsync(tempModel); } else { targetGrunt.Status = GruntStatus.Stage0; targetGrunt.Guid = guid; targetGrunt.LastCheckIn = DateTime.UtcNow; targetGrunt = await _client.ApiGruntsPutAsync(targetGrunt); } if (!egressGruntExists) { egressGrunt = targetGrunt; } // EncryptedMessage is the RSA Public Key targetGrunt.GruntRSAPublicKey = Convert.ToBase64String(EncryptUtilities.AesDecrypt( gruntStage0Response, Convert.FromBase64String(targetGrunt.GruntSharedSecretPassword) )); // Generate negotiated session key Aes newAesKey = Aes.Create(); newAesKey.GenerateKey(); targetGrunt.GruntNegotiatedSessionKey = Convert.ToBase64String(newAesKey.Key); await _client.ApiGruntsPutAsync(targetGrunt); if (egressGruntExists) { // Add this as Child grunt to Grunt that connects it List <GruntTasking> taskings = _client.ApiTaskingsGet().ToList(); // TODO: Finding the connectTasking this way could cause race conditions, should fix w/ guid of some sort? GruntTasking connectTasking = taskings.Where(GT => GT.Type == GruntTaskingType.Connect && GT.Status == GruntTaskingStatus.Progressed).Reverse().FirstOrDefault(); if (connectTasking == null) { return(NotFound()); } GruntTaskingMessage tmessage = this.GetGruntTaskingMessage(connectTasking, targetGrunt.DotNetFrameworkVersion); targetGrunt.Hostname = tmessage.Message.Split(",")[0]; await _client.ApiGruntsPutAsync(targetGrunt); connectTasking.Status = GruntTaskingStatus.Completed; await _client.ApiTaskingsPutAsync(connectTasking); } byte[] rsaEncryptedBytes = EncryptUtilities.GruntRSAEncrypt(targetGrunt, Convert.FromBase64String(targetGrunt.GruntNegotiatedSessionKey)); ModelUtilities.GruntEncryptedMessage message = null; try { message = this.CreateMessageForGrunt(egressGrunt, targetGrunt, rsaEncryptedBytes); } catch (HttpOperationException) { return(NotFound()); } // Transform response string transformed = this._utilities.ProfileTransform(_context.HttpProfile.First(), Common.CovenantEncoding.GetBytes(JsonConvert.SerializeObject(message))); // Format transformed response string response = String.Format(_context.HttpProfile.First().HttpPostResponse, transformed); // Stage0Response: "Id,Name,Base64(IV),Base64(AES(RSA(SessionKey))),Base64(HMAC)" return(Ok(response)); }
// Data should be of format: IV (16 bytes) + EncryptedBytes public byte[] GruntSessionDecrypt(Grunt grunt, byte[] data) { return(EncryptUtilities.AesDecrypt(data, Convert.FromBase64String(grunt.GruntNegotiatedSessionKey))); }