예제 #1
0
        private async Task PostStage0(APIModels.Grunt egressGrunt, APIModels.Grunt targetGrunt, ModelUtilities.GruntEncryptedMessage gruntStage0Response, string guid)
        {
            if (targetGrunt == null || !gruntStage0Response.VerifyHMAC(Convert.FromBase64String(targetGrunt.GruntSharedSecretPassword)))
            {
                // Always return NotFound, don't give away unnecessary info
                this.PushCache(guid, new GruntMessageCacheInfo {
                    Status = GruntMessageCacheStatus.NotFound, Message = "", Tasking = null
                });
                return;
            }
            bool egressGruntExists = egressGrunt != null;

            if (targetGrunt.Status != APIModels.GruntStatus.Uninitialized)
            {
                // We create a new Grunt if this one is not uninitialized
                APIModels.Grunt tempModel = new APIModels.Grunt
                {
                    Id   = 0,
                    Name = Utilities.CreateShortGuid(),
                    Guid = guid,
                    OriginalServerGuid        = Utilities.CreateShortGuid(),
                    Status                    = APIModels.GruntStatus.Stage0,
                    ListenerId                = targetGrunt.ListenerId,
                    Listener                  = targetGrunt.Listener,
                    ImplantTemplateId         = targetGrunt.ImplantTemplateId,
                    ImplantTemplate           = targetGrunt.ImplantTemplate,
                    GruntSharedSecretPassword = targetGrunt.GruntSharedSecretPassword,
                    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      = APIModels.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
            using (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 <APIModels.GruntTasking> taskings = _client.ApiTaskingsGet().ToList();
                // TODO: Finding the connectTasking this way could cause race conditions, should fix w/ guid of some sort?
                APIModels.GruntTasking connectTasking = taskings.Where(GT => GT.Type == APIModels.GruntTaskingType.Connect && GT.Status == APIModels.GruntTaskingStatus.Progressed).Reverse().FirstOrDefault();
                if (connectTasking == null)
                {
                    this.PushCache(guid, new GruntMessageCacheInfo {
                        Status = GruntMessageCacheStatus.NotFound, Message = "", Tasking = null
                    });
                    return;
                }
                APIModels.GruntTaskingMessage tmessage = this.GetGruntTaskingMessage(connectTasking, targetGrunt.DotNetFrameworkVersion);
                targetGrunt.Hostname = tmessage.Message.Split(",")[0];
                await _client.ApiGruntsPutAsync(targetGrunt);

                connectTasking.Status = APIModels.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)
            {
                this.PushCache(guid, new GruntMessageCacheInfo {
                    Status = GruntMessageCacheStatus.NotFound, Message = "", Tasking = null
                });
                return;
            }
            // Transform response
            // Stage0Response: "Id,Name,Base64(IV),Base64(AES(RSA(SessionKey))),Base64(HMAC)"
            string transformed = this._utilities.ProfileTransform(_transform, Common.CovenantEncoding.GetBytes(JsonConvert.SerializeObject(message)));

            this.PushCache(guid, new GruntMessageCacheInfo {
                Status = GruntMessageCacheStatus.Ok, Message = transformed, Tasking = null
            });
            return;
        }
예제 #2
0
 // Data should be of format: IV (16 bytes) + EncryptedBytes
 public byte[] GruntSessionDecrypt(APIModels.Grunt grunt, byte[] data)
 {
     return(EncryptUtilities.AesDecrypt(data, Convert.FromBase64String(grunt.GruntNegotiatedSessionKey)));
 }