You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							193 lines
						
					
					
						
							4.7 KiB
						
					
					
				
			
		
		
	
	
							193 lines
						
					
					
						
							4.7 KiB
						
					
					
				| #include "afl-fuzz.h"
 | |
| #include "afl-mutations.h"
 | |
| 
 | |
| #include <unistd.h>
 | |
| #include <getopt.h>
 | |
| 
 | |
| static int            max_havoc = 16, verbose;
 | |
| static unsigned char *dict, *mh = "16";
 | |
| 
 | |
| extern int module_disabled;
 | |
| 
 | |
| void *afl_custom_init(afl_state_t *, unsigned int);
 | |
| 
 | |
| int main(int argc, char *argv[]) {
 | |
| 
 | |
|   if (argc > 1 && strncmp(argv[1], "-h", 2) == 0) {
 | |
| 
 | |
|     printf(
 | |
|         "Syntax: %s [-v] [-m maxmutations] [-x dict] [inputfile [outputfile "
 | |
|         "[splicefile]]]\n\n",
 | |
|         argv[0]);
 | |
|     printf("Reads a testcase from a file (not stdin!),\n");
 | |
|     printf("writes to stdout when '-' or\n");
 | |
|     printf(
 | |
|         "no output filename is given. As an optional third parameter you can "
 | |
|         "give a file\n");
 | |
|     printf("for splicing. Maximum input and output length is 1MB.\n");
 | |
|     printf("Options:\n");
 | |
|     printf("  -v      verbose debug output to stderr.\n");
 | |
|     printf("  -m val  max mutations (1-val, val default is 16)\n");
 | |
|     printf("  -x file dictionary file (AFL++ format)\n");
 | |
|     printf("You can set the following environment variable parameters:\n");
 | |
|     printf("AUTOTOKENS_COMMENT` - what character or string starts a comment which will be\n");
 | |
|     printf("                      removed. Default: \"/* ... */\"\n");
 | |
|     return 0;
 | |
| 
 | |
|   }
 | |
| 
 | |
|   FILE          *in = stdin, *out = stdout, *splice = NULL;
 | |
|   unsigned char *inbuf = malloc(1024 * 1024), *outbuf = NULL, *splicebuf = NULL;
 | |
|   int            splicelen = 0, opt;
 | |
| 
 | |
|   while ((opt = getopt(argc, argv, "vm:x:")) > 0) {
 | |
| 
 | |
|     switch (opt) {
 | |
| 
 | |
|       case 'm':
 | |
|         max_havoc = atoi(optarg);
 | |
|         mh = optarg;
 | |
|         break;
 | |
|       case 'v':
 | |
|         verbose = 1;
 | |
|         break;
 | |
|       case 'x':
 | |
|         dict = optarg;
 | |
|         break;
 | |
|       default:
 | |
|         fprintf(stderr, "Error: unknown parameter -%c\n", opt);
 | |
|         exit(-1);
 | |
| 
 | |
|     }
 | |
| 
 | |
|   }
 | |
| 
 | |
|   if (max_havoc < 1) {
 | |
| 
 | |
|     fprintf(stderr, "Error: illegal -m value\n");
 | |
|     exit(-1);
 | |
| 
 | |
|   }
 | |
| 
 | |
|   if (argc > optind && strcmp(argv[optind], "-") != 0) {
 | |
| 
 | |
|     if ((in = fopen(argv[optind], "r")) == NULL) {
 | |
| 
 | |
|       perror(argv[1]);
 | |
|       return -1;
 | |
| 
 | |
|     }
 | |
| 
 | |
|     if (verbose) fprintf(stderr, "Input: %s\n", argv[optind]);
 | |
| 
 | |
|   }
 | |
| 
 | |
|   size_t inlen = fread(inbuf, 1, 1024 * 1024, in);
 | |
| 
 | |
|   if (!inlen) {
 | |
| 
 | |
|     fprintf(stderr, "Error: empty file %s\n",
 | |
|             argv[optind] ? argv[optind] : "stdin");
 | |
|     return -1;
 | |
| 
 | |
|   }
 | |
| 
 | |
|   if (argc > optind + 1 && strcmp(argv[optind + 1], "-") != 0) {
 | |
| 
 | |
|     if ((out = fopen(argv[optind + 1], "w")) == NULL) {
 | |
| 
 | |
|       perror(argv[optind + 1]);
 | |
|       return -1;
 | |
| 
 | |
|     }
 | |
| 
 | |
|     if (verbose) fprintf(stderr, "Output: %s\n", argv[optind + 1]);
 | |
| 
 | |
|   }
 | |
| 
 | |
|   if (argc > optind + 2) {
 | |
| 
 | |
|     if ((splice = fopen(argv[optind + 2], "r")) == NULL) {
 | |
| 
 | |
|       perror(argv[optind + 2]);
 | |
|       return -1;
 | |
| 
 | |
|     }
 | |
| 
 | |
|     if (verbose) fprintf(stderr, "Splice: %s\n", argv[optind + 2]);
 | |
|     splicebuf = malloc(1024 * 1024);
 | |
|     size_t splicelen = fread(splicebuf, 1, 1024 * 1024, splice);
 | |
|     if (!splicelen) {
 | |
| 
 | |
|       fprintf(stderr, "Error: empty file %s\n", argv[optind + 2]);
 | |
|       return -1;
 | |
| 
 | |
|     }
 | |
| 
 | |
|     if (verbose) fprintf(stderr, "Mutation splice length: %zu\n", splicelen);
 | |
| 
 | |
|   }
 | |
| 
 | |
|   /* configure autotokens */
 | |
|   setenv("AUTOTOKENS_LEARN_DICT", "1", 0);
 | |
|   setenv("AUTOTOKENS_CREATE_FROM_THIN_AIR", "1", 0);
 | |
|   setenv("AUTOTOKENS_CHANGE_MAX", mh, 0);
 | |
| 
 | |
|   /* fake AFL++ state */
 | |
|   afl_state_t *afl = (afl_state_t *)calloc(1, sizeof(afl_state_t));
 | |
|   afl->queue_cycle = afl->havoc_div = afl->active_items = afl->queued_items = 1;
 | |
|   afl->shm.cmplog_mode = 0;
 | |
|   afl->fsrv.dev_urandom_fd = open("/dev/urandom", O_RDONLY);
 | |
|   if (afl->fsrv.dev_urandom_fd < 0) { PFATAL("Unable to open /dev/urandom"); }
 | |
| 
 | |
|   rand_set_seed(afl, getpid());
 | |
| 
 | |
|   if (dict) {
 | |
| 
 | |
|     load_extras(afl, dict);
 | |
|     if (verbose)
 | |
|       fprintf(stderr, "Loaded dictionary: %s (%u entries)\n", dict,
 | |
|               afl->extras_cnt);
 | |
| 
 | |
|   }
 | |
| 
 | |
|   // setup a fake queue entry
 | |
|   afl->queue_buf = malloc(64);
 | |
|   afl->queue_buf[0] = afl->queue_cur =
 | |
|       (struct queue_entry *)malloc(sizeof(struct queue_entry));
 | |
|   afl->queue_cur->testcase_buf = inbuf;
 | |
|   afl->queue_cur->fname = (u8 *)argv[optind];
 | |
|   afl->queue_cur->len = inlen;
 | |
|   afl->queue_cur->perf_score = 100;
 | |
|   afl->queue_cur->favored = afl->queue_cur->is_ascii = 1;
 | |
|   // afl->custom_only = 1;
 | |
| 
 | |
|   void *data = (void *)afl_custom_init(afl, (u32)0);
 | |
| 
 | |
|   u8 res = afl_custom_queue_get(inbuf, (u8 *)argv[optind]);
 | |
| 
 | |
|   if (verbose) fprintf(stderr, "Mutation input length: %zu\n", inlen);
 | |
|   unsigned int outlen = afl_custom_fuzz(data, inbuf, inlen, &outbuf, splicebuf,
 | |
|                                         splicelen, 1024 * 1024);
 | |
| 
 | |
|   if (outlen == 0 || !outbuf) {
 | |
| 
 | |
|     fprintf(stderr, "Error: no mutation data returned.\n");
 | |
|     return -1;
 | |
| 
 | |
|   }
 | |
| 
 | |
|   if (verbose) fprintf(stderr, "Mutation output length: %u\n", outlen);
 | |
| 
 | |
|   if (fwrite(outbuf, 1, outlen, out) != outlen) {
 | |
| 
 | |
|     fprintf(stderr, "Warning: incomplete write.\n");
 | |
|     return -1;
 | |
| 
 | |
|   }
 | |
| 
 | |
|   return 0;
 | |
| 
 | |
| }
 | |
| 
 |