/* PFF (Php Fuzzing Framework) coded by calcite@setec.org shouts to "SpoofedEx" and dmk@setec.org http://setec.org/~calcite/ Version: (BETA-1) */ #include #include #include #include #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include //#define DEBUG 1 #define ERROR -1 #define PHPBINARY "/usr/bin/php" #define FMTSTR "%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n" #define UNKNOWN_DATA_TYPE "Error on line %d function %s param %d.\nUnknown Data type.....\n" struct types { char type_[32]; int numarg; struct types *subnext; }; struct phpfuzz{ char f_name[32]; struct phpfuzz *next; struct types *_subnext; }; char *genfilename(); void *usage(char *Pgname); struct phpfuzz *parse_file(char *f_file); void echo(struct phpfuzz *node); void *memAlloc(unsigned int size); int initfuzz(struct phpfuzz *x); void freestructs(struct phpfuzz *node); char *encode_base64(char *data_,unsigned int len); unsigned int getsd(); void grabenv(); extern int errno; char *phpbin = NULL; unsigned int MAXLEN = 0; char *tmpfolder = NULL; int main(int argc, char **argv) { char *f_file = NULL; struct phpfuzz *x; if(argc < 2) { usage(*argv+2); } f_file = argv[1]; phpbin = (argc == 3 ? argv[2] : NULL); /*verify legit arguments*/ if(access(f_file,F_OK) < 0) { fprintf(stderr,"File does not exist\n"); exit(ERROR); } if(phpbin != NULL) { if(access(phpbin,F_OK) < 0) { fprintf(stderr,"php binary absolute location non existant\n"); exit(ERROR); } } phpbin = (phpbin == NULL ? PHPBINARY : phpbin); x = parse_file(f_file); grabenv(); initfuzz(x); freestructs(x); return 0; } /* Parses the *.frame file and creates a data structure of function names and arguments --calcite */ struct phpfuzz *parse_file(char *f_file) { FILE *fp = NULL; int i,line_num=0,param=0,flag; char line[600],*ptr = NULL,funcname[60],type[32]; struct phpfuzz *head = NULL; struct phpfuzz *current = NULL; struct phpfuzz *new = NULL; struct types *subhead = NULL; struct types *subcurrent = NULL; struct types *subnew = NULL; if((fp = fopen(f_file,"r")) == NULL) { printf("ERROR: %s\n",strerror(errno)); exit(ERROR); } new = memAlloc(sizeof(struct phpfuzz)); head = new; current = head; current->_subnext = malloc(sizeof(struct types)); subnew = current->_subnext; subcurrent = subnew; subhead = subcurrent; subcurrent->subnext = NULL; startloop: while((fgets(line,sizeof(line)-1,fp)) != NULL) { i=0; line_num++; ptr = line; memset(funcname,0,sizeof(funcname)-1); if(*ptr != '\n') { if(*ptr == '#') { goto startloop; } //skip spaces while((*ptr == ' ' ) || (*ptr == '\t')) { *ptr++; } //grab function name to fuzz while((*ptr != '(') && (i <= 59) && (*ptr != 0x00)) { funcname[i++] = *ptr++; } funcname[++i]= 0x00; if(*ptr != '(') { fprintf(stderr,"Parsing error.... on line %d",line_num); exit(ERROR); } *ptr++; strncpy(current->f_name,funcname,31); param = 0; while((*ptr != ')') && (*ptr != 0x00)) { i=0; flag = 0; param++; while(((*ptr == ',') || (*ptr == '[')) && *ptr != 0x00) { *ptr++; } while((*ptr != ']') && (i <= 31) && (*ptr != 0x00)) { type[i++] = *ptr++; } *ptr++; type[i++] = 0x00; if((strcasecmp(type,"int") == 0) || (strcasecmp(type,"integer") == 0)) { subcurrent->numarg = param; strncpy(subcurrent->type_,type,31); flag++; } if((strcasecmp(type,"string") == 0) || (strcasecmp(type,"chars") == 0)) { subcurrent->numarg = param; strncpy(subcurrent->type_,type,31); flag++; } if((strcasecmp(type,"rand") == 0) || (strcasecmp(type,"random") == 0)) { subcurrent->numarg = param; strncpy(subcurrent->type_,type,31); flag++; } if(flag == 0) { fprintf(stderr,UNKNOWN_DATA_TYPE,line_num,funcname,param); exit(ERROR); } subnew->subnext = memAlloc(sizeof(struct types)); subnew = subnew->subnext; subcurrent = subnew; subcurrent->subnext = NULL; } new->next = memAlloc(sizeof(struct phpfuzz)); new = new->next; current = new; current->next = NULL; current->_subnext = memAlloc(sizeof(struct types)); subnew = current->_subnext; subcurrent = subnew; subcurrent->subnext = NULL; } subcurrent->subnext = NULL; current->next=NULL; } new ->next = NULL; echo(head); return head; } int initfuzz(struct phpfuzz *x) { FILE *fp = NULL; int rnum = 0; unsigned int i = 0,len2 = 0,rlen = 0; struct types *subnode = NULL; char *file = NULL,*rdata = NULL,*base64 = NULL,*arg[2]; file = genfilename(); if((fp = fopen(file,"w+")) == NULL) { fprintf(stderr,"%s\n",strerror(errno)); exit(ERROR); } fprintf(fp,"next != NULL) { fprintf(fp,"%s(",x->f_name); subnode = x->_subnext; begining: rnum = 0; while(subnode->subnext != NULL) { if((strcasecmp(subnode->type_,"int") == 0) || (strcasecmp(subnode->type_,"integer") == 0)) { switch(rand() % 2) { case 0: rnum = rand() % 100000; break; case 1: rnum = rand() % 100000; rnum = -rnum; break; } rnum++; } if((strcasecmp(subnode->type_,"string") == 0) || (strcasecmp(subnode->type_,"chars") == 0)) { rlen = (MAXLEN == 0 ? ((rand() % 1200) + 50) : ((rand() % MAXLEN) + 50)); printf("USING LEN %d\n",rlen); rdata = memAlloc(rlen+1); switch(rand() % 2) { case 0: for(i = 0;i < rlen; i++) { rdata[i] = rand() % 256; } rdata[i] = 0x00; break; case 1: strncpy(rdata,FMTSTR,rlen); len2 = strlen(rdata); for(i = len2; i < (rlen - len2); i++) { rdata[i] = rand() % 256; } rdata[i] = 0x00; break; } } if((strcasecmp(subnode->type_,"rand") == 0) || (strcasecmp(subnode->type_,"random") == 0)) { switch(rand() % 2) { case 0: strncpy(subnode->type_,"string",31); break; case 1: strncpy(subnode->type_,"integer",31); break; } goto begining; } subnode = subnode->subnext; if((subnode->subnext == NULL) && (rnum == 0)) { base64 = encode_base64(rdata,rlen - 1); fprintf(fp,"base64_decode(\"%s\")",base64); } if((subnode->subnext == NULL) && (rnum != 0)) { fprintf(fp,"%d",rnum); } if((rnum != 0) && (subnode->subnext != NULL)) { fprintf(fp,"%d,",rnum); } if((subnode->subnext != NULL) && (rnum == 0)) { base64 = encode_base64(rdata,rlen - 1); fprintf(fp,"base64_decode(\"%s\"),",base64); } free(rdata);rdata = NULL; free(base64); base64 = NULL; } fprintf(fp,");\n"); fflush(fp); x = x->next; } fprintf(fp,"\n?>"); fclose(fp); arg[0] = phpbin;arg[1] = file;arg[2] = NULL; execve(*arg,arg,NULL);free(file); return 0; } /* Encode the random data in base64,to elimate php parsing errors... --calcite */ char *encode_base64(char *data_,unsigned int len) { char *buf = NULL; BUF_MEM *bptr = NULL; BIO *bmem = NULL,*base64 = NULL; base64 = BIO_new(BIO_f_base64()); bmem = BIO_new(BIO_s_mem()); base64 = BIO_push(base64,bmem); BIO_write(base64,data_,len); BIO_flush(base64); BIO_get_mem_ptr(base64,&bptr); if((buf = malloc(bptr->length+1)) == NULL) { fprintf(stderr,"Error allocating memory\n"); exit(ERROR); } memcpy(buf,bptr->data,bptr->length); buf[bptr->length] = 0x00; BIO_free_all(base64); return buf; } /* get seed from /dev/random --calcite */ unsigned int getsd() { int fd; unsigned int sd; if((fd = open("/dev/random",O_RDONLY)) < 0) { perror("open"); exit(ERROR); } if(read(fd,&sd,sizeof(sd)) < 0) { perror("read"); exit(ERROR); } close(fd); return sd; } /* Generate our /tmp/"DIR"/fuzz%d.php --calcite */ char *genfilename() { int i=0; char *basedir = NULL,filename[1024],*name=NULL; basedir = (tmpfolder == NULL ? "/tmp/PFF/" : tmpfolder); if(access(basedir,F_OK) < 0) { mkdir(basedir,0744); } snprintf(filename,sizeof(filename)-1,"%s/fuzz%d.php",basedir,i); while(access(filename,F_OK) == 0) { snprintf(filename,sizeof(filename)-1,"%s/fuzz%d.php",basedir,i); i++; } if((name = strndup(filename,strlen(filename))) == NULL) { fprintf(stderr,"%s",strerror(errno)); exit(ERROR); } return name; } /* print out data structure.. --calcite */ void echo(struct phpfuzz *node) { struct types *subnode = NULL; while(node->next != NULL) { printf("Function: %s \n",node->f_name); subnode = node->_subnext; while(subnode->subnext != NULL) { printf("\tParameter type: %s : Param # %d \n",subnode->type_,subnode->numarg); subnode = subnode->subnext; } node = node->next; } } /* Grab environment variables if any is set.... -- calcite */ void grabenv() { if((tmpfolder = getenv("PFF_TEMPFOLDER")) != NULL) { printf("[+] Using temporary directory %s .\n",tmpfolder); } if(getenv("PFF_MAXLEN") != NULL) { MAXLEN = atoi(getenv("PFF_MAXLEN")); printf("[+] Using maximum random char length %d .\n",MAXLEN); } } /* Semi - free() wrapper --calcite */ void freestructs(struct phpfuzz *node) { struct types *subnode = NULL; while(node != NULL) { subnode = node->_subnext; while(subnode != NULL) { free(subnode); subnode = subnode->subnext; } free(node); node = node->next; } } /* Quick malloc wrapper.. Got tired of writing the same exception handling code for malloc() -- calcite */ void *memAlloc(unsigned int size) { void *memory = NULL; if((memory = malloc(size)) == NULL) { fprintf(stderr,"malloc() Error allocating %d bytes of memory using\n",size); exit(ERROR); } return memory; } /* self explanatory :) --calcite */ void *usage(char *Pgname) { fprintf(stderr,"\t\tTiny \"Php Framework Fuzzer\" (PFF) By calcite@setec.org\n"); fprintf(stderr,"\t\t\t-- %s \n",Pgname); fprintf(stderr,"\t\t\t-- The last argument is optional .\n"); exit(ERROR); }