Exemplo n.º 1
0
void destroy_config() {

  if (fargc == 0) return;

  while (fargc-- != 0)
    ck_free(fargv[fargc]);
  ck_free(fargv);

}
Exemplo n.º 2
0
static void find_obj(u8* argv0) {

  u8 *afl_path = getenv("AFL_PATH");
  u8 *slash, *tmp;

  if (afl_path) {

    tmp = alloc_printf("%s/afl-llvm-rt.o", afl_path);

    if (!access(tmp, R_OK)) {
      obj_path = afl_path;
      ck_free(tmp);
      return;
    }

    ck_free(tmp);

  }

  slash = strrchr(argv0, '/');

  if (slash) {

    u8 *dir;

    *slash = 0;
    dir = ck_strdup(argv0);
    *slash = '/';

    tmp = alloc_printf("%s/afl-llvm-rt.o", dir);

    if (!access(tmp, R_OK)) {
      obj_path = dir;
      ck_free(tmp);
      return;
    }

    ck_free(tmp);
    ck_free(dir);

  }

  if (!access(AFL_PATH "/afl-llvm-rt.o", R_OK)) {
    obj_path = AFL_PATH;
    return;
  }

  FATAL("Unable to find 'afl-llvm-rt.o' or 'afl-llvm-pass.so'. Please set AFL_PATH");
 
}
Exemplo n.º 3
0
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);

  }

}
Exemplo n.º 4
0
static void setup_shm(void) {

  u8* shm_str;

  shm_id = shmget(IPC_PRIVATE, MAP_SIZE, IPC_CREAT | IPC_EXCL | 0600);

  if (shm_id < 0) PFATAL("shmget() failed");

  atexit(remove_shm);

  shm_str = alloc_printf("%d", shm_id);

  setenv(SHM_ENV_VAR, shm_str, 1);

  ck_free(shm_str);

  trace_bits = shmat(shm_id, NULL, 0);
  
  if (!trace_bits) PFATAL("shmat() failed");

}
Exemplo n.º 5
0
static void detect_file_args(char** argv) {

  u32 i = 0;
  u8* cwd = getcwd(NULL, 0);

  if (!cwd) PFATAL("getcwd() failed");

  while (argv[i]) {

    u8* aa_loc = strstr(argv[i], "@@");

    if (aa_loc) {

      u8 *aa_subst, *n_arg;

      if (!at_file) FATAL("@@ syntax is not supported by this tool.");

      /* Be sure that we're always using fully-qualified paths. */

      if (at_file[0] == '/') aa_subst = at_file;
      else aa_subst = alloc_printf("%s/%s", cwd, at_file);

      /* Construct a replacement argv value. */

      *aa_loc = 0;
      n_arg = alloc_printf("%s%s%s", argv[i], aa_subst, aa_loc + 2);
      argv[i] = n_arg;
      *aa_loc = '@';

      if (at_file[0] != '/') ck_free(aa_subst);

    }

    i++;

  }

  free(cwd); /* not tracked */

}
Exemplo n.º 6
0
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.");

}
Exemplo n.º 7
0
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);

    }

}
Exemplo n.º 8
0
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);

}
Exemplo n.º 9
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;

}