Example #1
0
        private async Task RegisterGrunt(APIModels.Grunt egressGrunt, APIModels.Grunt targetGrunt, ModelUtilities.GruntEncryptedMessage gruntMessage, string guid)
        {
            if (targetGrunt == null || targetGrunt.Status != APIModels.GruntStatus.Stage2 || !gruntMessage.VerifyHMAC(Convert.FromBase64String(targetGrunt.GruntNegotiatedSessionKey)))
            {
                // Always return NotFound, don't give away unnecessary info
                this.PushCache(guid, new GruntMessageCacheInfo {
                    Status = GruntMessageCacheStatus.NotFound, Message = "", Tasking = null
                });
                return;
            }
            if (egressGrunt == null)
            {
                egressGrunt = targetGrunt;
            }
            string message = Common.CovenantEncoding.GetString(_utilities.GruntSessionDecrypt(targetGrunt, gruntMessage));

            // todo: try/catch on deserialize?
            APIModels.Grunt grunt = JsonConvert.DeserializeObject <APIModels.Grunt>(message);
            targetGrunt.IpAddress       = grunt.IpAddress;
            targetGrunt.Hostname        = grunt.Hostname;
            targetGrunt.OperatingSystem = grunt.OperatingSystem;
            targetGrunt.UserDomainName  = grunt.UserDomainName;
            targetGrunt.UserName        = grunt.UserName;
            targetGrunt.Status          = APIModels.GruntStatus.Active;
            targetGrunt.Integrity       = grunt.Integrity;
            targetGrunt.Process         = grunt.Process;
            targetGrunt.LastCheckIn     = DateTime.UtcNow;

            await _client.ApiGruntsPutAsync(targetGrunt);

            APIModels.GruntTaskingMessage tasking = new APIModels.GruntTaskingMessage
            {
                Message = targetGrunt.Guid,
                Name    = Guid.NewGuid().ToString().Replace("-", "").Substring(0, 10),
                Type    = APIModels.GruntTaskingType.Jobs,
                Token   = false
            };

            ModelUtilities.GruntEncryptedMessage responseMessage;
            try
            {
                responseMessage = this.CreateMessageForGrunt(egressGrunt, targetGrunt, tasking);
            }
            catch (HttpOperationException)
            {
                this.PushCache(guid, new GruntMessageCacheInfo {
                    Status = GruntMessageCacheStatus.NotFound, Message = "", Tasking = null
                });
                return;
            }

            // Transform response
            string transformed = this._utilities.ProfileTransform(_transform, Common.CovenantEncoding.GetBytes(JsonConvert.SerializeObject(responseMessage)));

            this.PushCache(guid, new GruntMessageCacheInfo {
                Status = GruntMessageCacheStatus.Ok, Message = transformed, Tasking = null
            });
            return;
        }
Example #2
0
 private ModelUtilities.GruntEncryptedMessage CreateMessageForGrunt(APIModels.Grunt grunt, APIModels.Grunt targetGrunt, APIModels.GruntTaskingMessage taskingMessage)
 {
     return(this.CreateMessageForGrunt(grunt, targetGrunt, Common.CovenantEncoding.GetBytes(JsonConvert.SerializeObject(taskingMessage))));
 }
Example #3
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;
        }
Example #4
0
 /// <summary>
 /// Initializes a new instance of the GruntTasking class.
 /// </summary>
 /// <param name="status">Possible values include: 'Uninitialized',
 /// 'Tasked', 'Progressed', 'Completed'</param>
 /// <param name="type">Possible values include: 'Assembly', 'Set',
 /// 'Kill'</param>
 /// <param name="setType">Possible values include: 'Delay', 'Jitter',
 /// 'ConnectAttempts'</param>
 public GruntTasking(int?id = default(int?), string name = default(string), int?taskId = default(int?), int?gruntId = default(int?), GruntTaskingStatus?status = default(GruntTaskingStatus?), GruntTaskingType?type = default(GruntTaskingType?), string gruntTaskOutput = default(string), GruntTaskingMessage taskingMessage = default(GruntTaskingMessage), string gruntTaskingAssembly = default(string), GruntSetTaskingType?setType = default(GruntSetTaskingType?), string value = default(string))
 {
     Id                   = id;
     Name                 = name;
     TaskId               = taskId;
     GruntId              = gruntId;
     Status               = status;
     Type                 = type;
     GruntTaskOutput      = gruntTaskOutput;
     TaskingMessage       = taskingMessage;
     GruntTaskingAssembly = gruntTaskingAssembly;
     SetType              = setType;
     Value                = value;
     CustomInit();
 }