static void edit_params(int argc, char** argv) { u8* tmp_dir = getenv("TMPDIR"); if (!tmp_dir) tmp_dir = "/tmp"; as_params = ck_alloc((argc + 1) * sizeof(u8*)); memcpy(as_params, argv, argc * sizeof(u8*)); as_params[0] = "as"; as_params[argc] = 0; input_file = as_params[argc - 1]; if (input_file[0] == '-') { if (input_file[1]) FATAL("Incorrect use (not called through afl-gcc?)"); else input_file = NULL; } modified_file = alloc_printf("%s/.afl-%u-%u.s", tmp_dir, getpid(), (u32)time(NULL)); as_params[argc - 1] = modified_file; }
static void find_binary(u8* fname) { u8* env_path = 0; struct stat st; if (strchr(fname, '/') || !(env_path = getenv("PATH"))) { target_path = ck_strdup(fname); if (stat(target_path, &st) || !S_ISREG(st.st_mode) || !(st.st_mode & 0111) || st.st_size < 4) FATAL("Program '%s' not found or not executable", fname); } else { while (env_path) { u8 *cur_elem, *delim = strchr(env_path, ':'); if (delim) { cur_elem = ck_alloc(delim - env_path + 1); memcpy(cur_elem, env_path, delim - env_path); delim++; } else cur_elem = ck_strdup(env_path); env_path = delim; if (cur_elem[0]) target_path = alloc_printf("%s/%s", cur_elem, fname); else target_path = ck_strdup(fname); ck_free(cur_elem); if (!stat(target_path, &st) && S_ISREG(st.st_mode) && (st.st_mode & 0111) && st.st_size >= 4) break; ck_free(target_path); target_path = 0; } if (!target_path) FATAL("Program '%s' not found or not executable", fname); } }
void parse_opts(int argc, char** argv){ int longIndex; int mode=MODE_ATTACK; int i; unsigned int f; int t=0; int recent=0; int code=0; int query_all=0; char *post_key=NULL; char *url=NULL; char *mime=NULL; char *trigger=NULL; char *feature=NULL; char *description=""; char *upload_file=NULL; unsigned int flags=0; struct option long_options[] = { /* long options array. Items are all caSe SensiTivE! */ { "add-url", no_argument, &mode, MODE_ADD_URL }, { "add-trigger", no_argument, &mode, MODE_ADD_TRIGGER}, { "brute-backup", required_argument, NULL, MODE_BRUTE_BACKUP}, { "brute-backup-days", required_argument, NULL, BRUTE_BACKUP_DAYS}, { "brute-backup-pattern", required_argument, NULL, BRUTE_BACKUP_PATTERN}, { "brute-backup-no-stop", no_argument, &backup_bruteforce_stop, 0}, { "brute-backup-no-slash", no_argument, &backup_bruteforce_slash, 0}, { "store-successes", no_argument, NULL, 'S'}, { "query", no_argument, &mode, MODE_QUERY}, { "all", no_argument, &query_all, 1}, { "code", required_argument, NULL, CODE}, { "post-key", required_argument, NULL, POST_KEY}, { "mime-type", required_argument, NULL, MIME}, { "recent", required_argument, NULL, RECENT}, { "no-async-resolve", no_argument, &async_dns, 0}, { "trigger", required_argument,NULL, TRIGGER}, { "max-hosts", required_argument,NULL, 'n'}, { "idle-timeout", required_argument,NULL, RESP_TIMEOUT}, { "rw-timeout", required_argument,NULL, RW_TIMEOUT}, { "conn-timeout", required_argument,NULL, CONN_TIMEOUT}, { "max-connections", required_argument,NULL, 'c'}, { "max-requests", required_argument,NULL, 'r'}, { "max-time", required_argument,NULL, MAX_TIME}, { "progress", required_argument, NULL, 'P' }, { "file", required_argument, NULL, 'f' }, { "statistics", no_argument, NULL, STATISTICS }, { "browser", required_argument, NULL, 'B' }, { "train", optional_argument, NULL, 'T' }, { "feature", required_argument,NULL, FEATURE}, { "url", required_argument, NULL, URL }, { "flags", required_argument, NULL, FLAGS }, { "help", required_argument, NULL, 'h' }, { "skip-sig", no_argument, &skip_sig, 1}, { "skip-other-probes", no_argument, &skip_other_probes, 1}, { "skip-blacklist-success", no_argument, &blacklist_success, 0}, { "force-save", no_argument, &force_save, 1}, { "analyze", no_argument, &mode, MODE_ANALYZE}, { "find-uploaded-file", required_argument, NULL, MODE_FIND_UPLOAD }, { 0, 0, 0, 0 } /* terminating -0 item */ }; int opt; struct t_list *target; while((opt=getopt_long( argc, argv, "-n:Sf:P:c:B:h:r:T::", long_options, &longIndex ))!=-1){ switch(opt){ case 1: target=calloc(sizeof(struct t_list),1); target->host=(unsigned char *) optarg; unqueued_hosts++; LL_APPEND(target_list,target); t++; break; case MODE_BRUTE_BACKUP: backup_bruteforce_url=optarg; mode=MODE_BRUTE_BACKUP; break; case BRUTE_BACKUP_DAYS: backup_bruteforce_days_back=atoi(optarg); break; case RESP_TIMEOUT: resp_tmout=atoi(optarg); break; case RW_TIMEOUT: rw_tmout=atoi(optarg); break; case MAX_TIME: max_time=atoi(optarg); break; case CONN_TIMEOUT: idle_tmout=atoi(optarg); break; case BRUTE_BACKUP_PATTERN: backup_bruteforce_pattern=optarg; break; case 'B': if (!strcasecmp("metal",optarg)) browser_type=BROWSER_METAL; else if (!strcasecmp("minimal",optarg)) browser_type=BROWSER_FAST; else if (!strcasecmp("firefox",optarg)) browser_type=BROWSER_FFOX; else if (!strcasecmp("explorer",optarg)) browser_type=BROWSER_MSIE; else if (!strcasecmp("iphone",optarg)) browser_type=BROWSER_PHONE; else { printf("ERROR: Browser type '%s' is not supported.\n",optarg); exit(1); } break; case 'h': usage(); exit(0); case 'S': store_successes=1; break; case URL: url=optarg; break; case 'c': max_conn_host=atoi(optarg); break; case 'f': if(!strcmp("-",optarg)) file=stdin; else{ if(!(file=fopen(optarg,"r"))){ printf("Can't open '%s' for reading!",optarg); exit(1); } } int fd = fileno(file); int fflags = fcntl(fd, F_GETFL, 0); fflags |= O_NONBLOCK; fcntl(fd, F_SETFL, fflags); t++; case 'r': max_requests=atoi(optarg); break; case 'P': progress=atoi(optarg); break; case STATISTICS: load_tests(); load_features(); show_feature_predictive_values(); exit(0); break; case 'T': train=1; if(optarg) max_train_count=atoi(optarg); break; case 'n': max_hosts=atoi(optarg); break; case FEATURE: feature=optarg; break; case POST_KEY: post_key=optarg; break; case MIME: mime=optarg; break; case CODE: code=atoi(optarg); break; case RECENT: recent=atoi(optarg); break; case TRIGGER: trigger=optarg; break; case FLAGS: for(i=0; i<strlen(optarg); i++){ f=tolower(optarg[i]); switch(f){ case 'c': flags|=F_CRITICAL; break; case 'i': flags|=F_INFO; break; case 'd': flags|=F_DIRECTORY; break; case 'g': flags|=F_CGI; break; default: fprintf (stderr, "Unknown flag: '%c'",f ); exit(1); } } break; case MODE_FIND_UPLOAD: mode=MODE_FIND_UPLOAD; upload_file=optarg; break; } } if(train){ /* force aggressive 404 pruning */ max_requests=0; blacklist_success=1; skip_other_probes=0; } switch(mode){ case MODE_FIND_UPLOAD: do { struct target *tar; if(!t){ fprintf(stderr, "You must specify a host\n"); exit(1); } skip_other_probes=1; tar=add_target(target_list->host) ; /* first target only */ no_add_from_queue=1; if(!tar){ fprintf(stderr,"Couldn't create target '%s'\n",target_list->host); exit(1); } tar->upload_file=upload_file; tar->after_probes=start_find_uploaded_file; do_scan(); } while(0); break; case MODE_ADD_URL: add_or_update_url(url, description, flags); exit(0); break; case MODE_ATTACK: if(!t){ usage(); exit(0); } max_connections=max_hosts * max_conn_host; scan_flags=flags; do_scan(); exit(0); break; case MODE_ADD_TRIGGER: add_aho_corasick_trigger(trigger, feature); exit(0); break; case MODE_QUERY: do { if(!url && !code && !mime && !flags && !recent && !post_key && !query_all){ fprintf(stderr,"You must specify at least one attribute to search on (or --all)\n"); exit(1); } struct query *q=ck_alloc(sizeof(struct query)); q->url=url; q->code=code; q->mime=mime; q->flags=flags; q->recent=recent; q->post_key=post_key; store_successes=0; do_query(q); exit(0); break; } while(0); case MODE_ANALYZE: load_tests(); load_features(); info("performing feature selection..."); do_feature_selection(); exit(0); case MODE_BRUTE_BACKUP: do { struct target *tar; skip_other_probes=1; tar=add_target(backup_bruteforce_url); if(!tar) exit(1); tar->after_probes=start_bruteforce_backup; do_scan(); } while(0); break; } }
static void live_event_loop(void) { #ifndef __CYGWIN__ /* The huge problem with winpcap on cygwin is that you can't get a file descriptor suitable for poll() / select() out of it: http://www.winpcap.org/pipermail/winpcap-users/2009-April/003179.html The only alternatives seem to be additional processes / threads, a nasty busy loop, or a ton of Windows-specific code. If you need APi queries on Windows, you are welcome to fix this :-) */ struct pollfd *pfds; struct api_client** ctable; u32 pfd_count; /* We need room for pcap, and possibly api_fd + api_clients. */ pfds = ck_alloc((1 + (api_sock ? (1 + api_max_conn) : 0)) * sizeof(struct pollfd)); ctable = ck_alloc((1 + (api_sock ? (1 + api_max_conn) : 0)) * sizeof(struct api_client*)); pfd_count = regen_pfds(pfds, ctable); if (!daemon_mode) SAYF("[+] Entered main event loop.\n\n"); while (!stop_soon) { s32 pret, i; u32 cur; /* We use a 250 ms timeout to keep Ctrl-C responsive without resortng to silly sigaction hackery or unsafe signal handler code. */ poll_again: pret = poll(pfds, pfd_count, 250); if (pret < 0) { if (errno == EINTR) break; printf("\n FATAL: poll() failed."); } if (!pret) { if (log_file) fflush(lf); continue; } /* Examine pfds... */ for (cur = 0; cur < pfd_count; cur++) { if (pfds[cur].revents & POLLOUT) switch (cur) { case 0: case 1: printf("\n FATAL: Unexpected POLLOUT on fd %d.\n", cur); default: /* Write API response, restart state when complete. */ if (ctable[cur]->in_off < sizeof(struct p0f_api_query)) printf("\n FATAL: Inconsistent p0f_api_response state.\n"); i = write(pfds[cur].fd, ((char*)&ctable[cur]->out_data) + ctable[cur]->out_off, sizeof(struct p0f_api_response) - ctable[cur]->out_off); if (i <= 0) printf("\n FATAL: write() on API socket fails despite POLLOUT."); ctable[cur]->out_off += i; /* All done? Back to square zero then! */ if (ctable[cur]->out_off == sizeof(struct p0f_api_response)) { ctable[cur]->in_off = ctable[cur]->out_off = 0; pfds[cur].events = (POLLIN | POLLERR | POLLHUP); } } if (pfds[cur].revents & POLLIN) switch (cur) { case 0: /* Process traffic on the capture interface. */ if (pcap_dispatch(pt, -1, (pcap_handler)parse_packet, 0) < 0) printf("\n FATAL: Packet capture interface is down."); break; case 1: /* Accept new API connection, limits permitting. */ if (!api_sock) printf("\n FATAL: Unexpected API connection."); if (pfd_count - 2 < api_max_conn) { for (i = 0; i < api_max_conn && api_cl[i].fd >= 0; i++); if (i == api_max_conn) printf("\n FATAL: Inconsistent API connection data."); api_cl[i].fd = accept(api_fd, NULL, NULL); if (api_cl[i].fd < 0) { WARN("Unable to handle API connection: accept() fails."); } else { if (fcntl(api_cl[i].fd, F_SETFL, O_NONBLOCK)) printf("\n FATAL: fcntl() to set O_NONBLOCK on API connection fails."); api_cl[i].in_off = api_cl[i].out_off = 0; pfd_count = regen_pfds(pfds, ctable); DEBUG("[#] Accepted new API connection, fd %d.\n", api_cl[i].fd); goto poll_again; } } else WARN("Too many API connections (use -S to adjust).\n"); break; default: /* Receive API query, dispatch when complete. */ if (ctable[cur]->in_off >= sizeof(struct p0f_api_query)) printf("\n FATAL: Inconsistent p0f_api_query state.\n"); i = read(pfds[cur].fd, ((char*)&ctable[cur]->in_data) + ctable[cur]->in_off, sizeof(struct p0f_api_query) - ctable[cur]->in_off); if (i < 0) printf("\n FATAL: read() on API socket fails despite POLLIN."); ctable[cur]->in_off += i; /* Query in place? Compute response and prepare to send it back. */ if (ctable[cur]->in_off == sizeof(struct p0f_api_query)) { handle_query(&ctable[cur]->in_data, &ctable[cur]->out_data); pfds[cur].events = (POLLOUT | POLLERR | POLLHUP); } } if (pfds[cur].revents & (POLLERR | POLLHUP)) switch (cur) { case 0: printf("\n FATAL: Packet capture interface is down."); case 1: printf("\n FATAL: API socket is down."); default: /* Shut down API connection and free its state. */ DEBUG("[#] API connection on fd %d closed.\n", pfds[cur].fd); close(pfds[cur].fd); ctable[cur]->fd = -1; pfd_count = regen_pfds(pfds, ctable); goto poll_again; } /* Processed all reported updates already? If so, bail out early. */ if (pfds[cur].revents && !--pret) break; } } ck_free(ctable); ck_free(pfds); #else if (!daemon_mode) SAYF("[+] Entered main event loop.\n\n"); /* Ugh. The only way to keep SIGINT and other signals working is to have this funny loop with dummy I/O every 250 ms. Signal handlers don't get called in pcap_dispatch() or pcap_loop() unless there's I/O. */ while (!stop_soon) { s32 ret = pcap_dispatch(pt, -1, (pcap_handler)parse_packet, 0); if (ret < 0) return; if (log_file && !ret) fflush(lf); write(2, NULL, 0); } #endif /* ^!__CYGWIN__ */ WARN("User-initiated shutdown."); }
static void prepare_bpf(void) { struct bpf_program flt; u8* final_rule; u8 vlan_support; /* VLAN matching is somewhat brain-dead: you need to request it explicitly, and it alters the semantics of the remainder of the expression. */ vlan_support = (pcap_datalink(pt) == DLT_EN10MB); retry_no_vlan: if (!orig_rule) { if (vlan_support) { final_rule = (u8*)"tcp or (vlan and tcp)"; } else { final_rule = (u8*)"tcp"; } } else { if (vlan_support) { final_rule = ck_alloc(strlen((char*)orig_rule) * 2 + 64); sprintf((char*)final_rule, "(tcp and (%s)) or (vlan and tcp and (%s))", orig_rule, orig_rule); } else { final_rule = ck_alloc(strlen((char*)orig_rule) + 16); sprintf((char*)final_rule, "tcp and (%s)", orig_rule); } } DEBUG("[#] Computed rule: %s\n", final_rule); if (pcap_compile(pt, &flt, (char*)final_rule, 1, 0)) { if (vlan_support) { if (orig_rule) ck_free(final_rule); vlan_support = 0; goto retry_no_vlan; } pcap_perror(pt, "[-] pcap_compile"); if (!orig_rule) printf("\n FATAL: pcap_compile() didn't work, strange"); else printf("\n FATAL: Syntax error! See 'man tcpdump' for help on filters."); } if (pcap_setfilter(pt, &flt)) printf("\n FATAL: pcap_setfilter() didn't work, strange."); pcap_freecode(&flt); if (!orig_rule) { SAYF("[+] Default packet filtering configured%s.\n", vlan_support ? " [+VLAN]" : ""); } else { SAYF("[+] Custom filtering rule enabled: %s%s\n", orig_rule ? orig_rule : (u8*)"tcp", vlan_support ? " [+VLAN]" : ""); ck_free(final_rule); } }
int main(int argc, char** argv) { s32 opt; u32 loop_cnt = 0, purge_age = 0, seed; u8 sig_loaded = 0, show_once = 0, no_statistics = 0, display_mode = 0, has_fake = 0; s32 oindex = 0; u8 *wordlist = NULL, *output_dir = NULL; u8 *sig_list_strg = NULL; u8 *gtimeout_str = NULL; u32 gtimeout = 0; struct termios term; struct timeval tv; u64 st_time, en_time; signal(SIGINT, ctrlc_handler); signal(SIGWINCH, resize_handler); signal(SIGPIPE, SIG_IGN); SSL_library_init(); /* Options, options, and options */ static struct option long_options[] = { {"auth", required_argument, 0, 'A' }, {"host", required_argument, 0, 'F' }, {"cookie", required_argument, 0, 'C' }, {"reject-cookies", required_argument, 0, 'N' }, {"header", required_argument, 0, 'H' }, {"user-agent", required_argument, 0, 'b' }, #ifdef PROXY_SUPPORT {"proxy", required_argument, 0, 'J' }, #endif /* PROXY_SUPPORT */ {"max-depth", required_argument, 0, 'd' }, {"max-child", required_argument, 0, 'c' }, {"max-descendants", required_argument, 0, 'x' }, {"max-requests", required_argument, 0, 'r' }, {"max-rate", required_argument, 0, 'l'}, {"probability", required_argument, 0, 'p' }, {"seed", required_argument, 0, 'q' }, {"include", required_argument, 0, 'I' }, {"exclude", required_argument, 0, 'X' }, {"skip-param", required_argument, 0, 'K' }, {"skip-forms", no_argument, 0, 'O' }, {"include-domain", required_argument, 0, 'D' }, {"ignore-links", no_argument, 0, 'P' }, {"no-ext-fuzzing", no_argument, 0, 'Y' }, {"log-mixed-content", no_argument, 0, 'M' }, {"skip-error-pages", no_argument, 0, 'Z' }, {"log-external-urls", no_argument, 0, 'U' }, {"log-cache-mismatches", no_argument, 0, 'E' }, {"form-value", no_argument, 0, 'T' }, {"rw-wordlist", required_argument, 0, 'W' }, {"no-keyword-learning", no_argument, 0, 'L' }, {"mode", required_argument, 0, 'J' }, {"wordlist", required_argument, 0, 'S'}, {"trust-domain", required_argument, 0, 'B' }, {"max-connections", required_argument, 0, 'g' }, {"max-host-connections", required_argument, 0, 'm' }, {"max-fail", required_argument, 0, 'f' }, {"request-timeout", required_argument, 0, 't' }, {"network-timeout", required_argument, 0, 'w' }, {"idle-timeout", required_argument, 0, 'i' }, {"response-size", required_argument, 0, 's' }, {"discard-binary", required_argument, 0, 'e' }, {"output", required_argument, 0, 'o' }, {"help", no_argument, 0, 'h' }, {"quiet", no_argument, 0, 'u' }, {"verbose", no_argument, 0, 'v' }, {"scan-timeout", required_argument, 0, 'k'}, {"signatures", required_argument, 0, 'z'}, {"checks", no_argument, 0, 0}, {"checks-toggle", required_argument, 0, 0}, {"no-checks", no_argument, 0, 0}, {"fast", no_argument, 0, 0}, {"auth-form", required_argument, 0, 0}, {"auth-form-target", required_argument, 0, 0}, {"auth-user", required_argument, 0, 0}, {"auth-user-field", required_argument, 0, 0}, {"auth-pass", required_argument, 0, 0}, {"auth-pass-field", required_argument, 0, 0}, {"auth-verify-url", required_argument, 0, 0}, {0, 0, 0, 0 } }; /* Come up with a quasi-decent random seed. */ gettimeofday(&tv, NULL); seed = tv.tv_usec ^ (tv.tv_sec << 16) ^ getpid(); SAY("skipfish version " VERSION " by <*****@*****.**>\n"); while ((opt = getopt_long(argc, argv, "+A:B:C:D:EF:G:H:I:J:K:LMNOPQR:S:T:UW:X:YZ" "b:c:d:ef:g:hi:k:l:m:o:p:q:r:s:t:uvw:x:z:", long_options, &oindex)) >= 0) switch (opt) { case 'A': { u8* x = (u8*)strchr(optarg, ':'); if (!x) FATAL("Credentials must be in 'user:pass' form."); *(x++) = 0; auth_user = (u8*)optarg; auth_pass = x; auth_type = AUTH_BASIC; break; } #ifdef PROXY_SUPPORT case 'J': { u8* x = (u8*)strchr(optarg, ':'); if (!x) FATAL("Proxy data must be in 'host:port' form."); *(x++) = 0; use_proxy = (u8*)optarg; use_proxy_port = atoi((char*)x); if (!use_proxy_port) FATAL("Incorrect proxy port number."); break; } #endif /* PROXY_SUPPORT */ case 'F': { u8* x = (u8*)strchr(optarg, '='); u32 fake_addr; if (!x) FATAL("Fake mappings must be in 'host=IP' form."); *x = 0; fake_addr = inet_addr((char*)x + 1); if (fake_addr == (u32)-1) FATAL("Could not parse IP address '%s'.", x + 1); fake_host((u8*)optarg, fake_addr); has_fake = 1; break; } case 'H': { u8* x = (u8*)strchr(optarg, '='); if (!x) FATAL("Extra headers must be in 'name=value' form."); *x = 0; if (!strcasecmp(optarg, "Cookie")) FATAL("Do not use -H to set cookies (try -C instead)."); SET_HDR((u8*)optarg, x + 1, &global_http_par); break; } case 'C': { u8* x = (u8*)strchr(optarg, '='); if (!x) FATAL("Cookies must be in 'name=value' form."); if (strchr(optarg, ';')) FATAL("Split multiple cookies into separate -C options."); *x = 0; SET_CK((u8*)optarg, x + 1, &global_http_par); break; } case 'D': if (*optarg == '*') optarg++; APPEND_FILTER(allow_domains, num_allow_domains, optarg); break; case 'K': APPEND_FILTER(skip_params, num_skip_params, optarg); break; case 'B': if (*optarg == '*') optarg++; APPEND_FILTER(trust_domains, num_trust_domains, optarg); break; case 'I': if (*optarg == '*') optarg++; APPEND_FILTER(allow_urls, num_allow_urls, optarg); break; case 'X': if (*optarg == '*') optarg++; APPEND_FILTER(deny_urls, num_deny_urls, optarg); break; case 'T': { u8* x = (u8*)strchr(optarg, '='); if (!x) FATAL("Rules must be in 'name=value' form."); *x = 0; add_form_hint((u8*)optarg, x + 1); break; } case 'N': ignore_cookies = 1; break; case 'Y': no_fuzz_ext = 1; break; case 'q': if (sscanf(optarg, "0x%08x", &seed) != 1) FATAL("Invalid seed format."); srandom(seed); break; case 'Q': suppress_dupes = 1; break; case 'P': no_parse = 1; break; case 'M': warn_mixed = 1; break; case 'U': log_ext_urls = 1; break; case 'L': dont_add_words = 1; break; case 'E': pedantic_cache = 1; break; case 'O': no_forms = 1; break; case 'R': purge_age = atoi(optarg); if (purge_age < 3) FATAL("Purge age invalid or too low (min 3)."); break; case 'd': max_depth = atoi(optarg); if (max_depth < 2) FATAL("Invalid value '%s'.", optarg); break; case 'c': max_children = atoi(optarg); if (!max_children) FATAL("Invalid value '%s'.", optarg); break; case 'x': max_descendants = atoi(optarg); if (!max_descendants) FATAL("Invalid value '%s'.", optarg); break; case 'p': crawl_prob = atoi(optarg); if (!crawl_prob) FATAL("Invalid value '%s'.", optarg); break; case 'W': if (wordlist) FATAL("Only one -W parameter permitted (use -S to load supplemental dictionaries)."); if (!strcmp(optarg, "-")) wordlist = (u8*)"/dev/null"; else wordlist = (u8*)optarg; break; case 'S': load_keywords((u8*)optarg, 1, 0); break; case 'z': load_signatures((u8*)optarg); sig_loaded = 1; break; case 'b': if (optarg[0] == 'i') browser_type = BROWSER_MSIE; else if (optarg[0] == 'f') browser_type = BROWSER_FFOX; else if (optarg[0] == 'p') browser_type = BROWSER_PHONE; else usage(argv[0]); break; case 'g': max_connections = atoi(optarg); if (!max_connections) FATAL("Invalid value '%s'.", optarg); break; case 'm': max_conn_host = atoi(optarg); if (!max_conn_host) FATAL("Invalid value '%s'.", optarg); break; case 'G': max_guesses = atoi(optarg); if (!max_guesses) FATAL("Invalid value '%s'.", optarg); break; case 'r': max_requests = atoi(optarg); if (!max_requests) FATAL("Invalid value '%s'.", optarg); break; case 'l': max_requests_sec = atof(optarg); if (!max_requests_sec) FATAL("Invalid value '%s'.", optarg); break; case 'f': max_fail = atoi(optarg); if (!max_fail) FATAL("Invalid value '%s'.", optarg); break; case 't': resp_tmout = atoi(optarg); if (!resp_tmout) FATAL("Invalid value '%s'.", optarg); break; case 'w': rw_tmout = atoi(optarg); if (!rw_tmout) FATAL("Invalid value '%s'.", optarg); break; case 'i': idle_tmout = atoi(optarg); if (!idle_tmout) FATAL("Invalid value '%s'.", optarg); break; case 's': size_limit = atoi(optarg); if (!size_limit) FATAL("Invalid value '%s'.", optarg); break; case 'o': if (output_dir) FATAL("Multiple -o options not allowed."); output_dir = (u8*)optarg; rmdir(optarg); if (mkdir(optarg, 0755)) PFATAL("Unable to create '%s'.", output_dir); break; case 'u': no_statistics = 1; break; case 'v': verbosity++; break; case 'e': delete_bin = 1; break; case 'k': if (gtimeout_str) FATAL("Multiple -k options not allowed."); gtimeout_str = (u8*)optarg; break; case 'Z': no_500_dir = 1; break; case 0: if (!strcmp("checks", long_options[oindex].name )) display_injection_checks(); if (!strcmp("checks-toggle", long_options[oindex].name )) toggle_injection_checks((u8*)optarg, 1, 1); if (!strcmp("no-checks", long_options[oindex].name )) no_checks = 1; if (!strcmp("signatures", long_options[oindex].name )) load_signatures((u8*)optarg); if(!strcmp("fast", long_options[oindex].name )) toggle_injection_checks((u8*)"2,4,5,13,14,15,16", 0, 0); if (!strcmp("auth-form", long_options[oindex].name )) auth_form = (u8*)optarg; if (!strcmp("auth-user", long_options[oindex].name )) auth_user = (u8*)optarg; if (!strcmp("auth-pass", long_options[oindex].name )) auth_pass = (u8*)optarg; if (!strcmp("auth-pass-field", long_options[oindex].name )) auth_pass_field = (u8*)optarg; if (!strcmp("auth-user-field", long_options[oindex].name )) auth_user_field = (u8*)optarg; if (!strcmp("auth-form-target", long_options[oindex].name )) auth_form_target = (u8*)optarg; if (!strcmp("auth-verify-url", long_options[oindex].name )) auth_verify_url = (u8*)optarg; break; default: usage(argv[0]); } #ifdef PROXY_SUPPORT if (has_fake && use_proxy) FATAL("-F and -J should not be used together."); #endif /* PROXY_SUPPORT */ if (access(ASSETS_DIR "/index.html", R_OK)) PFATAL("Unable to access '%s/index.html' - wrong directory?", ASSETS_DIR); srandom(seed); if (optind == argc) FATAL("Scan target not specified (try -h for help)."); if (!output_dir) FATAL("Output directory not specified (try -h for help)."); if(verbosity && !no_statistics && isatty(2)) FATAL("Please use -v in combination with the -u flag or, " "run skipfish while redirecting stderr to a file. "); if (resp_tmout < rw_tmout) resp_tmout = rw_tmout; if (max_connections < max_conn_host) max_connections = max_conn_host; /* Parse the timeout string - format h:m:s */ if (gtimeout_str) { int i = 0; int m[3] = { 1, 60, 3600 }; u8* tok = (u8*)strtok((char*)gtimeout_str, ":"); while(tok && i <= 2) { gtimeout += atoi((char*)tok) * m[i]; tok = (u8*)strtok(NULL, ":"); i++; } if(!gtimeout) FATAL("Wrong timeout format, please use h:m:s (hours, minutes, seconds)"); DEBUG("* Scan timeout is set to %d seconds\n", gtimeout); } if (!wordlist) { wordlist = (u8*)"/dev/null"; DEBUG("* No wordlist specified with -W: defaulting to /dev/null\n"); } /* If no signature files have been specified via command-line: load the default file */ if (!sig_loaded) load_signatures((u8*)SIG_FILE); load_keywords(wordlist, 0, purge_age); /* Load the signatures list for the matching */ if (sig_list_strg) load_signatures(sig_list_strg); /* Try to authenticate when the auth_user and auth_pass fields are set. */ if (auth_user && auth_pass) { authenticate(); while (next_from_queue()) { usleep(1000); } switch (auth_state) { case ASTATE_DONE: DEBUGC(L1, "*- Authentication succeeded!\n"); break; default: DEBUG("Auth state: %d\n", auth_state); FATAL("Authentication failed (use -uv for more info)\n"); break; } } /* Schedule all URLs in the command line for scanning. */ while (optind < argc) { struct http_request *req; /* Support @ notation for reading URL lists from files. */ if (argv[optind][0] == '@') { read_urls((u8*)argv[optind++] + 1); continue; } req = ck_alloc(sizeof(struct http_request)); if (parse_url((u8*)argv[optind], req, NULL)) FATAL("Scan target '%s' is not a valid absolute URL.", argv[optind]); if (!url_allowed_host(req)) APPEND_FILTER(allow_domains, num_allow_domains, __DFL_ck_strdup(req->host)); if (!url_allowed(req)) FATAL("URL '%s' explicitly excluded by -I / -X rules.", argv[optind]); maybe_add_pivot(req, NULL, 2); destroy_request(req); optind++; } /* Char-by char stdin. */ tcgetattr(0, &term); term.c_lflag &= ~ICANON; tcsetattr(0, TCSANOW, &term); fcntl(0, F_SETFL, O_NONBLOCK); gettimeofday(&tv, NULL); st_time = tv.tv_sec * 1000LL + tv.tv_usec / 1000; #ifdef SHOW_SPLASH if (!no_statistics) splash_screen(); #endif /* SHOW_SPLASH */ if (!no_statistics) SAY("\x1b[H\x1b[J"); else SAY(cLGN "[*] " cBRI "Scan in progress, please stay tuned...\n"); u64 refresh_time = 0; /* Enter the crawler loop */ while ((next_from_queue() && !stop_soon) || (!show_once++)) { u8 keybuf[8]; u64 end_time; u64 run_time; struct timeval tv_tmp; gettimeofday(&tv_tmp, NULL); end_time = tv_tmp.tv_sec * 1000LL + tv_tmp.tv_usec / 1000; run_time = end_time - st_time; if (gtimeout > 0 && run_time && run_time/1000 > gtimeout) { DEBUG("* Stopping scan due to timeout\n"); stop_soon = 1; } req_sec = (req_count - queue_cur / 1.15) * 1000 / (run_time + 1); if (no_statistics || ((loop_cnt++ % 100) && !show_once && idle == 0)) continue; if (end_time > refresh_time) { refresh_time = (end_time + 10); if (clear_screen) { SAY("\x1b[H\x1b[2J"); clear_screen = 0; } SAY(cYEL "\x1b[H" "skipfish version " VERSION " by [email protected]\n\n" cBRI " -" cPIN " %s " cBRI "-\n\n" cNOR, allow_domains[0]); if (!display_mode) { http_stats(st_time); SAY("\n"); database_stats(); } else { http_req_list(); } SAY(" \r"); } if (fread(keybuf, 1, sizeof(keybuf), stdin) > 0) { display_mode ^= 1; clear_screen = 1; } } gettimeofday(&tv, NULL); en_time = tv.tv_sec * 1000LL + tv.tv_usec / 1000; SAY("\n"); if (stop_soon) SAY(cYEL "[!] " cBRI "Scan aborted by user, bailing out!" cNOR "\n"); term.c_lflag |= ICANON; tcsetattr(0, TCSANOW, &term); fcntl(0, F_SETFL, O_SYNC); save_keywords((u8*)wordlist); write_report(output_dir, en_time - st_time, seed); #ifdef LOG_STDERR SAY("\n== PIVOT DEBUG ==\n"); dump_pivots(0, 0); SAY("\n== END OF DUMP ==\n\n"); #endif /* LOG_STDERR */ SAY(cLGN "[+] " cBRI "This was a great day for science!" cRST "\n\n"); #ifdef DEBUG_ALLOCATOR if (!stop_soon) { destroy_database(); destroy_signature_lists(); destroy_http(); destroy_signatures(); __TRK_report(); } #endif /* DEBUG_ALLOCATOR */ fflush(0); EVP_cleanup(); CRYPTO_cleanup_all_ex_data(); return 0; }
static void read_urls(u8* fn) { FILE* f = fopen((char*)fn, "r"); u8 tmp[MAX_URL_LEN]; u32 loaded = 0; if (!f) FATAL("Unable to open '%s'.", fn); while (fgets((char*)tmp, MAX_URL_LEN, f)) { struct http_request *req; u8* url = tmp; u8* ptr; u32 l; while (isspace(*url)) url++; /* Check if we're reading a pivots.txt file and grab the URL */ if(!strncmp((char*)url,"GET ", 4) || !strncmp((char*)url,"POST ", 4)) { url += 4; /* If the server response code is a 404, than we'll skip the URL to avoid wasting time on things that are likely not to exist. */ if(inl_findstr(url, (u8*)"code=404", MAX_URL_LEN)) continue; ptr = url; /* Find the next space to terminate the URL */ while(ptr && !isspace(*ptr)) ptr++; if(!ptr) FATAL("URL parsing failed at line: %s", tmp); *ptr = 0; /* Else we expect a simple flat file with URLs */ } else { l = strlen((char*)url); while (l && isspace(url[l-1])) l--; url[l] = 0; } if (*url == '#' || !*url) continue; req = ck_alloc(sizeof(struct http_request)); if (parse_url(url, req, NULL)) FATAL("Scan target '%s' in file '%s' is not a valid absolute URL.", url, fn); if (!url_allowed_host(req)) APPEND_FILTER(allow_domains, num_allow_domains, __DFL_ck_strdup(req->host)); if (!url_allowed(req)) FATAL("URL '%s' in file '%s' explicitly excluded by -I / -X rules.", url, fn); maybe_add_pivot(req, NULL, 2); destroy_request(req); loaded++; } fclose(f); if (!loaded) FATAL("No valid URLs found in '%s'.", fn); }
static void edit_params(int argc, char** argv) { u8 *tmp_dir = getenv("TMPDIR"), *afl_as = getenv("AFL_AS"); u32 i; #ifdef __APPLE__ u8 use_clang_as = 0; /* On MacOS X, the Xcode cctool 'as' driver is a bit stale and does not work with the code generated by newer versions of clang that are hand-built by the user. See the thread here: http://goo.gl/HBWDtn. To work around this, when using clang and running without AFL_AS specified, we will actually call 'clang -c' instead of 'as -q' to compile the assembly file. The tools aren't cmdline-compatible, but at least for now, we can seemingly get away with this by making only very minor tweaks. Thanks to Nico Weber for the idea. */ if (clang_mode && !afl_as) { use_clang_as = 1; afl_as = getenv("AFL_CC"); if (!afl_as) afl_as = getenv("AFL_CXX"); if (!afl_as) afl_as = "clang"; } #endif /* __APPLE__ */ if (!tmp_dir) tmp_dir = "/tmp"; as_params = ck_alloc((argc + 32) * sizeof(u8*)); as_params[0] = afl_as ? afl_as : (u8*)"as"; as_params[argc] = 0; for (i = 1; i < argc - 1; i++) { if (!strcmp(argv[i], "--64")) use_64bit = 1; else if (!strcmp(argv[i], "--32")) use_64bit = 0; #ifdef __APPLE__ /* The Apple case is a bit different... */ if (!strcmp(argv[i], "-arch") && i + 1 < argc) { if (!strcmp(argv[i + 1], "x86_64")) use_64bit = 1; else if (!strcmp(argv[i + 1], "i386")) FATAL("Sorry, 32-bit Apple platforms are not supported."); } /* Strip options that set the preference for a particular upstream assembler in Xcode. */ if (clang_mode && (!strcmp(argv[i], "-q") || !strcmp(argv[i], "-Q"))) continue; #endif /* __APPLE__ */ as_params[as_par_cnt++] = argv[i]; } #ifdef __APPLE__ /* When calling clang as the upstream assembler, append -c -x assembler and hope for the best. */ if (use_clang_as) { as_params[as_par_cnt++] = "-c"; as_params[as_par_cnt++] = "-x"; as_params[as_par_cnt++] = "assembler"; } #endif /* __APPLE__ */ input_file = argv[argc - 1]; if (input_file[0] == '-') { if (!strcmp(input_file + 1, "-version")) { just_version = 1; modified_file = input_file; goto wrap_things_up; } if (input_file[1]) FATAL("Incorrect use (not called through afl-gcc?)"); else input_file = NULL; } else { /* Check if this looks like a standard invocation as a part of an attempt to compile a program, rather than using gcc on an ad-hoc .s file in a format we may not understand. This works around an issue compiling NSS. */ if (strncmp(input_file, tmp_dir, strlen(tmp_dir)) && strncmp(input_file, "/var/tmp/", 9) && strncmp(input_file, "/tmp/", 5)) pass_thru = 1; } modified_file = alloc_printf("%s/.afl-%u-%u.s", tmp_dir, getpid(), (u32)time(NULL)); wrap_things_up: as_params[as_par_cnt++] = modified_file; as_params[as_par_cnt] = NULL; }
static void edit_params(u32 argc, char** argv) { u8 fortify_set = 0, asan_set = 0, x_set = 0, maybe_linking = 1; u8 *name; cc_params = ck_alloc((argc + 64) * sizeof(u8*)); name = strrchr(argv[0], '/'); if (!name) name = argv[0]; else name++; if (!strcmp(name, "afl-clang-fast++")) { u8* alt_cxx = getenv("AFL_CXX"); cc_params[0] = alt_cxx ? alt_cxx : (u8*)"clang++"; } else { u8* alt_cc = getenv("AFL_CC"); cc_params[0] = alt_cc ? alt_cc : (u8*)"clang"; } cc_params[cc_par_cnt++] = "-Xclang"; cc_params[cc_par_cnt++] = "-load"; cc_params[cc_par_cnt++] = "-Xclang"; cc_params[cc_par_cnt++] = alloc_printf("%s/afl-llvm-pass.so", obj_path); cc_params[cc_par_cnt++] = "-Qunused-arguments"; while (--argc) { u8* cur = *(++argv); #if defined(__x86_64__) if (!strcmp(cur, "-m32")) FATAL("-m32 is not supported"); #endif if (!strcmp(cur, "-x")) x_set = 1; if (!strcmp(cur, "-c") || !strcmp(cur, "-S") || !strcmp(cur, "-E") || !strcmp(cur, "-v")) maybe_linking = 0; if (!strcmp(cur, "-fsanitize=address") || !strcmp(cur, "-fsanitize=memory")) asan_set = 1; if (strstr(cur, "FORTIFY_SOURCE")) fortify_set = 1; cc_params[cc_par_cnt++] = cur; } if (getenv("AFL_HARDEN")) { cc_params[cc_par_cnt++] = "-fstack-protector-all"; if (!fortify_set) cc_params[cc_par_cnt++] = "-D_FORTIFY_SOURCE=2"; } if (!asan_set) { if (getenv("AFL_USE_ASAN")) { cc_params[cc_par_cnt++] = "-fsanitize=address"; if (getenv("AFL_USE_MSAN")) FATAL("ASAN and MSAN are mutually exclusive"); } else if (getenv("AFL_USE_MSAN")) { cc_params[cc_par_cnt++] = "-fsanitize=memory"; if (getenv("AFL_USE_ASAN")) FATAL("ASAN and MSAN are mutually exclusive"); } } if (!getenv("AFL_DONT_OPTIMIZE")) { cc_params[cc_par_cnt++] = "-g"; cc_params[cc_par_cnt++] = "-O3"; cc_params[cc_par_cnt++] = "-funroll-loops"; } cc_params[cc_par_cnt++] = "-D__AFL_HAVE_MANUAL_CONTROL=1"; /* When the user tries to use persistent or deferred forkserver modes by appending a single line to the program, we want to reliably inject a signature into the binary (to be picked up by afl-fuzz) and we want to call a function from the runtime .o file. This is unnecessarily painful for three reasons: 1) We need to convince the compiler not to optimize out the signature. This is done with __attribute__((used)). 2) We need to convince the linker, when called with -Wl,--gc-sections, not to do the same. This is done by forcing an assignment to a 'volatile' pointer. 3) We need to declare __afl_persistent_loop() in the global namespace, but doing this within a method in a class is hard - :: and extern "C" are forbidden and __attribute__((alias(...))) doesn't work. Hence the __asm__ aliasing trick. */ cc_params[cc_par_cnt++] = "-D__AFL_LOOP(_A)=" "({ static volatile char *_B __attribute__((used)); " " _B = (char*)\"" PERSIST_SIG "\"; " #ifdef __APPLE__ "int _L(unsigned int) __asm__(\"___afl_persistent_loop\"); " #else "int _L(unsigned int) __asm__(\"__afl_persistent_loop\"); " #endif /* ^__APPLE__ */ "_L(_A); })"; cc_params[cc_par_cnt++] = "-D__AFL_INIT()=" "do { static volatile char *_A __attribute__((used)); " " _A = (char*)\"" DEFER_SIG "\"; " #ifdef __APPLE__ "void _I(void) __asm__(\"___afl_manual_init\"); " #else "void _I(void) __asm__(\"__afl_manual_init\"); " #endif /* ^__APPLE__ */ "_I(); } while (0)"; if (maybe_linking) { if (x_set) { cc_params[cc_par_cnt++] = "-x"; cc_params[cc_par_cnt++] = "none"; } cc_params[cc_par_cnt++] = alloc_printf("%s/afl-llvm-rt.o", obj_path); } cc_params[cc_par_cnt] = NULL; }
static void edit_params(u32 argc, char** argv) { u8 fortify_set = 0, asan_set = 0, x_set = 0, maybe_linking = 1, bit_mode = 0; u8 *name; cc_params = ck_alloc((argc + 128) * sizeof(u8*)); name = strrchr(argv[0], '/'); if (!name) name = argv[0]; else name++; if (!strcmp(name, "afl-clang-fast++")) { u8* alt_cxx = getenv("AFL_CXX"); cc_params[0] = alt_cxx ? alt_cxx : (u8*)"clang++"; } else { u8* alt_cc = getenv("AFL_CC"); cc_params[0] = alt_cc ? alt_cc : (u8*)"clang"; } /* There are two ways to compile afl-clang-fast. In the traditional mode, we use afl-llvm-pass.so to inject instrumentation. In the experimental 'trace-pc-guard' mode, we use native LLVM instrumentation callbacks instead. The latter is a very recent addition - see: http://clang.llvm.org/docs/SanitizerCoverage.html#tracing-pcs-with-guards */ #ifdef USE_TRACE_PC cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard"; cc_params[cc_par_cnt++] = "-mllvm"; cc_params[cc_par_cnt++] = "-sanitizer-coverage-block-threshold=0"; #else cc_params[cc_par_cnt++] = "-Xclang"; cc_params[cc_par_cnt++] = "-load"; cc_params[cc_par_cnt++] = "-Xclang"; cc_params[cc_par_cnt++] = alloc_printf("%s/afl-llvm-pass.so", obj_path); #endif /* ^USE_TRACE_PC */ cc_params[cc_par_cnt++] = "-Qunused-arguments"; /* Detect stray -v calls from ./configure scripts. */ if (argc == 1 && !strcmp(argv[1], "-v")) maybe_linking = 0; while (--argc) { u8* cur = *(++argv); if (!strcmp(cur, "-m32")) bit_mode = 32; if (!strcmp(cur, "-m64")) bit_mode = 64; if (!strcmp(cur, "-x")) x_set = 1; if (!strcmp(cur, "-c") || !strcmp(cur, "-S") || !strcmp(cur, "-E")) maybe_linking = 0; if (!strcmp(cur, "-fsanitize=address") || !strcmp(cur, "-fsanitize=memory")) asan_set = 1; if (strstr(cur, "FORTIFY_SOURCE")) fortify_set = 1; if (!strcmp(cur, "-shared")) maybe_linking = 0; if (!strcmp(cur, "-Wl,-z,defs") || !strcmp(cur, "-Wl,--no-undefined")) continue; cc_params[cc_par_cnt++] = cur; } if (getenv("AFL_HARDEN")) { cc_params[cc_par_cnt++] = "-fstack-protector-all"; if (!fortify_set) cc_params[cc_par_cnt++] = "-D_FORTIFY_SOURCE=2"; } if (!asan_set) { if (getenv("AFL_USE_ASAN")) { if (getenv("AFL_USE_MSAN")) FATAL("ASAN and MSAN are mutually exclusive"); if (getenv("AFL_HARDEN")) FATAL("ASAN and AFL_HARDEN are mutually exclusive"); cc_params[cc_par_cnt++] = "-U_FORTIFY_SOURCE"; cc_params[cc_par_cnt++] = "-fsanitize=address"; } else if (getenv("AFL_USE_MSAN")) { if (getenv("AFL_USE_ASAN")) FATAL("ASAN and MSAN are mutually exclusive"); if (getenv("AFL_HARDEN")) FATAL("MSAN and AFL_HARDEN are mutually exclusive"); cc_params[cc_par_cnt++] = "-U_FORTIFY_SOURCE"; cc_params[cc_par_cnt++] = "-fsanitize=memory"; } } #ifdef USE_TRACE_PC if (getenv("AFL_INST_RATIO")) FATAL("AFL_INST_RATIO not available at compile time with 'trace-pc'."); #endif /* USE_TRACE_PC */ if (!getenv("AFL_DONT_OPTIMIZE")) { cc_params[cc_par_cnt++] = "-g"; cc_params[cc_par_cnt++] = "-O3"; cc_params[cc_par_cnt++] = "-funroll-loops"; } if (getenv("AFL_NO_BUILTIN")) { cc_params[cc_par_cnt++] = "-fno-builtin-strcmp"; cc_params[cc_par_cnt++] = "-fno-builtin-strncmp"; cc_params[cc_par_cnt++] = "-fno-builtin-strcasecmp"; cc_params[cc_par_cnt++] = "-fno-builtin-strncasecmp"; cc_params[cc_par_cnt++] = "-fno-builtin-memcmp"; } cc_params[cc_par_cnt++] = "-D__AFL_HAVE_MANUAL_CONTROL=1"; cc_params[cc_par_cnt++] = "-D__AFL_COMPILER=1"; cc_params[cc_par_cnt++] = "-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION=1"; /* When the user tries to use persistent or deferred forkserver modes by appending a single line to the program, we want to reliably inject a signature into the binary (to be picked up by afl-fuzz) and we want to call a function from the runtime .o file. This is unnecessarily painful for three reasons: 1) We need to convince the compiler not to optimize out the signature. This is done with __attribute__((used)). 2) We need to convince the linker, when called with -Wl,--gc-sections, not to do the same. This is done by forcing an assignment to a 'volatile' pointer. 3) We need to declare __afl_persistent_loop() in the global namespace, but doing this within a method in a class is hard - :: and extern "C" are forbidden and __attribute__((alias(...))) doesn't work. Hence the __asm__ aliasing trick. */ cc_params[cc_par_cnt++] = "-D__AFL_LOOP(_A)=" "({ static volatile char *_B __attribute__((used)); " " _B = (char*)\"" PERSIST_SIG "\"; " #ifdef __APPLE__ "__attribute__((visibility(\"default\"))) " "int _L(unsigned int) __asm__(\"___afl_persistent_loop\"); " #else "__attribute__((visibility(\"default\"))) " "int _L(unsigned int) __asm__(\"__afl_persistent_loop\"); " #endif /* ^__APPLE__ */ "_L(_A); })"; cc_params[cc_par_cnt++] = "-D__AFL_INIT()=" "do { static volatile char *_A __attribute__((used)); " " _A = (char*)\"" DEFER_SIG "\"; " #ifdef __APPLE__ "__attribute__((visibility(\"default\"))) " "void _I(void) __asm__(\"___afl_manual_init\"); " #else "__attribute__((visibility(\"default\"))) " "void _I(void) __asm__(\"__afl_manual_init\"); " #endif /* ^__APPLE__ */ "_I(); } while (0)"; if (maybe_linking) { if (x_set) { cc_params[cc_par_cnt++] = "-x"; cc_params[cc_par_cnt++] = "none"; } switch (bit_mode) { case 0: cc_params[cc_par_cnt++] = alloc_printf("%s/afl-llvm-rt.o", obj_path); break; case 32: cc_params[cc_par_cnt++] = alloc_printf("%s/afl-llvm-rt-32.o", obj_path); if (access(cc_params[cc_par_cnt - 1], R_OK)) FATAL("-m32 is not supported by your compiler"); break; case 64: cc_params[cc_par_cnt++] = alloc_printf("%s/afl-llvm-rt-64.o", obj_path); if (access(cc_params[cc_par_cnt - 1], R_OK)) FATAL("-m64 is not supported by your compiler"); break; } } cc_params[cc_par_cnt] = NULL; }
void read_config(u8* fname) { s32 f; struct stat st; u8 *data, *cur; f = open((char*)fname, O_RDONLY); if (f < 0) PFATAL("Cannot open '%s' for reading.", fname); if (fstat(f, &st)) PFATAL("fstat() on '%s' failed.", fname); if (!st.st_size) { close(f); goto end_fp_read; } cur = data = ck_alloc(st.st_size + 1); if (read(f, data, st.st_size) != st.st_size) FATAL("Short read from '%s'.", fname); data[st.st_size] = 0; close(f); /* If you put NUL in your p0f.fp... Well, sucks to be you. */ while (1) { u8 *eol; line_no++; while (isblank(*cur)) cur++; eol = cur; while (*eol && *eol != '\n') eol++; if (*cur != ';' && cur != eol) { u8* line = ck_memdup_str(cur, eol - cur); config_parse_line(line); ck_free(line); } if (!*eol) break; cur = eol + 1; } ck_free(data); end_fp_read: if (!sig_cnt) SAYF("[!] No signatures found in '%s'.\n", fname); else SAYF("[+] Loaded %u signature%s from '%s'.\n", sig_cnt, sig_cnt == 1 ? "" : "s", fname); }
int read_config_file(const char *filename, int *_argc, char ***_argv) { FILE *fh; char line[MAX_LINE_LEN + 1]; char *val, *ptr; u8 *tmp; u32 idx, i; APPEND_STRING(fargv, fargc, ck_strdup((u8*)*_argv[0])); fh = fopen(filename, "r"); if (!fh) PFATAL("Unable to read config from: %s", filename); while (!feof(fh) && fargc < MAX_ARGS && fgets(line, MAX_LINE_LEN, fh)) { /* Skip comments and empty lines */ if (line[0] == '\n' || line[0] == '\r' || line[0] == '#') continue; /* NULL terminate the key */ idx = strcspn(line, " \t="); if (idx == strlen(line)) FATAL("Config key error at line: %s", line); line[idx] = '\0'; /* Find the beginning of the value. */ val = line + (idx + 1); idx = strspn(val, " \t="); if (idx == strlen(val)) FATAL("Config value error at line: %s", line); val = val + idx; /* Trim the unwanted characters from the value */ ptr = val + (strlen(val) - 1); while(*ptr && *ptr < 0x21) { *ptr = 0; ptr--; } /* Done! Now we have a key/value pair. If the flag is set to 'false' we will disregard this line. If the value is 'true', we will set the flag without a value. In any other case, we will set the flag and value */ if (val[0] == '\0') FATAL("Empty value in config line: %s", line); if (strcasecmp("false", val) == 0) continue; tmp = ck_alloc(strlen(line) + 3); sprintf((char*)tmp, "--%s", line); APPEND_STRING(fargv, fargc, tmp); if (strncasecmp("true", val, 3) != 0) APPEND_STRING(fargv, fargc, ck_strdup((u8*)val)); } /* Copy arguments from command line into our array */ for (i=1; i<*_argc && fargc < MAX_ARGS; ++i) APPEND_STRING(fargv, fargc, ck_strdup((u8*)(*_argv)[i])); /* Replace original flags */ *_argc = fargc; *_argv = (char **)fargv; fclose(fh); return 0; }
struct tcp_sig* fingerprint_tcp(u8 to_srv, struct packet_data* pk, struct packet_flow* f) { struct tcp_sig* sig; struct tcp_sig_record* m; sig = ck_alloc(sizeof(struct tcp_sig)); packet_to_sig(pk, sig); /* Detect packets generated by p0f-sendsyn; they require special handling to provide the user with response fingerprints, but not interfere with NAT scores and such. */ if (pk->tcp_type == TCP_SYN && pk->win == SPECIAL_WIN && pk->mss == SPECIAL_MSS) f->sendsyn = 1; if (to_srv) start_observation(f->sendsyn ? "sendsyn probe" : "syn", 4, 1, f); else start_observation(f->sendsyn ? "sendsyn response" : "syn+ack", 4, 0, f); tcp_find_match(to_srv, sig, 0, f->syn_mss); if ((m = sig->matched)) { OBSERVF((m->class_id == -1 || f->sendsyn) ? "app" : "os", "%s%s%s", fp_os_names[m->name_id], m->flavor ? " " : "", m->flavor ? m->flavor : (u8*)""); } else { add_observation_field("os", NULL); } if (m && m->bad_ttl) { OBSERVF("dist", "<= %u", sig->dist); } else { if (to_srv) f->client->distance = sig->dist; else f->server->distance = sig->dist; OBSERVF("dist", "%u", sig->dist); } add_observation_field("params", dump_flags(pk, sig)); add_observation_field("raw_sig", dump_sig(pk, sig, f->syn_mss)); if (pk->tcp_type == TCP_SYN) f->syn_mss = pk->mss; /* That's about as far as we go with non-OS signatures. */ if (m && m->class_id == -1) { verify_tool_class(to_srv, f, m->sys, m->sys_cnt); ck_free(sig); return NULL; } if (f->sendsyn) { ck_free(sig); return NULL; } score_nat(to_srv, sig, f); return sig; }
static void edit_params(int argc, char** argv) { u8 *tmp_dir = getenv("TMPDIR"), *afl_as = getenv("AFL_AS"); u32 i; if (!tmp_dir) tmp_dir = "/tmp"; as_params = ck_alloc((argc + 1) * sizeof(u8*)); memcpy(as_params, argv, argc * sizeof(u8*)); as_params[0] = afl_as ? afl_as : (u8*)"as"; as_params[argc] = 0; for (i = 1; i < argc; i++) { if (!strcmp(as_params[i], "--64")) use_64bit = 1; else if (!strcmp(as_params[i], "--32")) use_64bit = 0; #ifdef __APPLE__ /* The Apple case is a bit different... */ if (!strcmp(as_params[i], "-arch") && i + 1 < argc) { if (!strcmp(as_params[i + 1], "x86_64")) use_64bit = 1; else if (!strcmp(as_params[i + 1], "i386")) FATAL("Sorry, 32-bit Apple platforms are not supported."); } #endif /* __APPLE__ */ } input_file = as_params[argc - 1]; if (input_file[0] == '-') { if (input_file[1]) FATAL("Incorrect use (not called through afl-gcc?)"); else input_file = NULL; } else { /* Check if this looks like a standard invocation as a part of an attempt to compile a program, rather than using gcc on an ad-hoc .s file in a format we may not understand. This works around an issue compiling NSS. */ if (strncmp(input_file, tmp_dir, strlen(tmp_dir)) && strncmp(input_file, "/var/tmp/", 9) && strncmp(input_file, "/tmp/", 5)) pass_thru = 1; } modified_file = alloc_printf("%s/.afl-%u-%u.s", tmp_dir, getpid(), (u32)time(NULL)); as_params[argc - 1] = modified_file; }