Beispiel #1
0
static int ip6_ext_quickstart(struct ip6_hdr *ip6,
			      const scamper_probe_ipopt_t *opt,
			      uint8_t *buf, size_t *len)
{
  size_t off = 1;

  if(*len < 16)
    {
      *len = 16;
      return -1;
    }

  buf[off++] = 1; /* length of hop-by-hop options : 16 bytes */

  /* two Pad1 options */
  buf[off++] = 0;
  buf[off++] = 0;

  /* quickstart option */
  buf[off++] = 0x26;
  buf[off++] = 6;
  buf[off++] = (opt->opt_qs_func << 4) | opt->opt_qs_rate;
  buf[off++] = opt->opt_qs_ttl;
  bytes_htonl(&buf[off], opt->opt_qs_nonce << 2);
  off += 4;

  /* PadN option, length 4 */
  buf[off++] = 1;
  buf[off++] = 2;
  buf[off++] = 0;
  buf[off++] = 0;

  *len = off;
  return 0;
}
Beispiel #2
0
static int ip6_ext_frag(struct ip6_hdr *ip6,
			const scamper_probe_ipopt_t *opt,
			uint8_t *buf, size_t *len)
{
  /* make sure the pktbuf has at least enough space left for this */
  if(*len < 8)
    {
      *len = 8;
      return -1;
    }

  /* the length of this header is set to zero since it is of fixed size */
  buf[1] = 0;

  /* copy in the fragmentation value */
  bytes_htons(buf+2, opt->opt_v6frag_off);
  bytes_htonl(buf+4, opt->opt_v6frag_id);

  *len = 8;
  return 0;
}
Beispiel #3
0
int scamper_ip4_build(scamper_probe_t *pr, uint8_t *buf, size_t *len)
{
    scamper_probe_ipopt_t *opt;
    struct ip *ip;
    size_t off, ip4hlen;
    int i, j;

    if(scamper_ip4_hlen(pr, &ip4hlen) != 0)
        return -1;

    if(ip4hlen > *len)
    {
        *len = ip4hlen;
        return -1;
    }

    ip  = (struct ip *)buf;
    off = sizeof(struct ip);

#ifndef _WIN32
    ip->ip_v   = 4;
    ip->ip_hl  = (ip4hlen / 4);
#else
    ip->ip_vhl = 0x40 | (ip4hlen / 4);
#endif

    if((pr->pr_ip_off & IP_OFFMASK) != 0 || pr->pr_no_trans)
        ip->ip_len = htons(ip4hlen + pr->pr_len);
    else if(pr->pr_ip_proto == IPPROTO_ICMP || pr->pr_ip_proto == IPPROTO_UDP)
        ip->ip_len = htons(ip4hlen + 8 + pr->pr_len);
    else if(pr->pr_ip_proto == IPPROTO_TCP)
        ip->ip_len = htons(ip4hlen + scamper_tcp4_hlen(pr) + pr->pr_len);
    else
    {
        scamper_debug(__func__, "unimplemented pr %d", pr->pr_ip_proto);
        return -1;
    }

    ip->ip_tos = pr->pr_ip_tos;
    ip->ip_id  = htons(pr->pr_ip_id);
    ip->ip_off = htons(pr->pr_ip_off);
    ip->ip_ttl = pr->pr_ip_ttl;
    ip->ip_p   = pr->pr_ip_proto;
    ip->ip_sum = 0;
    memcpy(&ip->ip_src, pr->pr_ip_src->addr, sizeof(ip->ip_src));
    memcpy(&ip->ip_dst, pr->pr_ip_dst->addr, sizeof(ip->ip_dst));

    for(i=0; i<pr->pr_ipoptc; i++)
    {
        opt = &pr->pr_ipopts[i];
        if(opt->type == SCAMPER_PROBE_IPOPTS_V4RR)
        {
            memset(buf+off+3, 0, 37);
            buf[off+0] = 7;
            buf[off+1] = 39;
            buf[off+2] = 4;
            off = 60;
        }
        else if(opt->type == SCAMPER_PROBE_IPOPTS_V4TSPS ||
                opt->type == SCAMPER_PROBE_IPOPTS_V4TSO  ||
                opt->type == SCAMPER_PROBE_IPOPTS_V4TSAA)
        {
            buf[off+0] = 68;
            buf[off+2] = 5;

            if(opt->type == SCAMPER_PROBE_IPOPTS_V4TSPS)
            {
                buf[off+1] = (opt->opt_v4tsps_ipc * 4 * 2) + 4;
                buf[off+3] = 3;
                off += 4;
                for(j=0; j<opt->opt_v4tsps_ipc; j++)
                {
                    memcpy(buf+off, &opt->opt_v4tsps_ips[j], 4);
                    off += 4;
                    memset(buf+off, 0, 4);
                    off += 4;
                }
            }
            else if(opt->type == SCAMPER_PROBE_IPOPTS_V4TSO)
            {
                buf[off+1] = 40;
                memset(buf+off+3, 0, 41);
                off += 40;
            }
            else if(opt->type == SCAMPER_PROBE_IPOPTS_V4TSAA)
            {
                buf[off+1] = 36;
                buf[off+3] = 1;
                memset(buf+off+4, 0, 36);
                off += 36;
            }
        }
        else if(opt->type == SCAMPER_PROBE_IPOPTS_QUICKSTART)
        {
            assert(opt->opt_qs_func <= 0xf);
            assert(opt->opt_qs_rate <= 0xf);
            buf[off+0] = 25;
            buf[off+1] = 8;
            buf[off+2] = (opt->opt_qs_func << 4) | opt->opt_qs_rate;
            buf[off+3] = opt->opt_qs_ttl;
            bytes_htonl(&buf[off+4], opt->opt_qs_nonce << 2);
            off += 8;
        }
        else return -1;
    }

    assert(off == ip4hlen);
    ip->ip_sum = in_cksum(ip, ip4hlen);

    *len = off;
    return 0;
}
Beispiel #4
0
/** Dump the given vector to the plugin output file in binary
 *
 * @param corsaro       The corsaro object associated with the vector
 * @param vector      The vector to dump
 * @return 0 if the vector is dumped successfully, -1 if an error occurs
 */
static int binary_dump(corsaro_t *corsaro, attack_vector_t *vector)
{
  uint8_t av_bytes[CORSARO_DOS_ATTACK_VECTOR_BYTECNT];
  uint8_t *ptr = &av_bytes[0];

  /*
  uint8_t *pkt_buf = NULL;
  libtrace_linktype_t linktype;
  uint32_t pkt_length;
  */

  /* dump the attack vector details */

  bytes_htonl(ptr, vector->target_ip);
  ptr+=4;

  bytes_htonl(ptr, kh_size(vector->attack_ip_hash));
  ptr+=4;

  bytes_htonl(ptr, kh_size(vector->attack_ip_hash)-vector->attack_ip_cnt);
  ptr+=4;

  bytes_htonl(ptr, kh_size(vector->attack_port_hash));
  ptr+=4;

  bytes_htonl(ptr, kh_size(vector->target_port_hash));
  ptr+=4;

  bytes_htonll(ptr, vector->packet_cnt);
  ptr+=8;

  bytes_htonl(ptr, vector->interval_packet_cnt);
  ptr+=4;

  bytes_htonll(ptr, vector->byte_cnt);
  ptr+=8;

  bytes_htonl(ptr, vector->interval_byte_cnt);
  ptr+=4;

  bytes_htonll(ptr, vector->ppm_window.max_ppm);
  ptr+=8;

  bytes_htonl(ptr, vector->start_time.tv_sec);
  ptr+=4;

  bytes_htonl(ptr, vector->start_time.tv_usec);
  ptr+=4;

  bytes_htonl(ptr, vector->latest_time.tv_sec);
  ptr+=4;

  bytes_htonl(ptr, vector->latest_time.tv_usec);
  ptr+=4;

  /* dump the initial packet using trace_get_packet_buffer */
  /*
  if((pkt_buf = trace_get_packet_buffer(vector->initial_packet,
					&linktype, NULL)) == NULL ||
     (pkt_length = trace_get_capture_length(vector->initial_packet)) == 0)
    {
      corsaro_log(__func__, "could not get packet buffer");
      return -1;
    }
  */

  /* add the size of the packet to the byte array before we dump it */
  bytes_htonl(ptr, vector->initial_packet_len);

  if(corsaro_file_write(corsaro, STATE(corsaro)->outfile, &av_bytes[0],
		      CORSARO_DOS_ATTACK_VECTOR_BYTECNT) !=
     CORSARO_DOS_ATTACK_VECTOR_BYTECNT)
    {
      corsaro_log(__func__, corsaro, "could not dump vector byte array to file");
      return -1;
    }

  if(corsaro_file_write(corsaro, STATE(corsaro)->outfile, vector->initial_packet,
		      vector->initial_packet_len) !=
     vector->initial_packet_len)
    {
      corsaro_log(__func__, corsaro, "could not dump packet to file");
      return -1;
    }

  return 0;
}
Beispiel #5
0
/** Implements the end_interval function of the plugin API */
int corsaro_dos_end_interval(corsaro_t *corsaro, corsaro_interval_t *int_end)
{
  int this_interval = int_end->time-STATE(corsaro)->first_interval;

  khiter_t i;
  attack_vector_t *vector;
  attack_vector_t **attack_arr = NULL;
  int attack_arr_cnt = 0;

  uint8_t gbuf[12];
  uint8_t cntbuf[4];

  if(this_interval < CORSARO_DOS_INTERVAL)
    {
      /* we haven't run for long enough to dump */
      return 0;
    }
  else
    {
      /* we either have hit exactly the right amount of time,
	 or we have gone for too long, dump now and reset the counter */
      STATE(corsaro)->first_interval = int_end->time;
      /* fall through and continue to dump */
    }

  /* this is an interval we care about */

  /* malloc an array big enough to hold the entire hash even though we wont
     need it to be that big */
  if((attack_arr =
      malloc(sizeof(attack_vector_t *)*
	     kh_size(STATE(corsaro)->attack_hash))) == NULL)
    {
      corsaro_log(__func__, corsaro,
		  "could not malloc array for attack vectors");
      return -1;
    }

  /* classify the flows and dump the attack ones */

  for(i = kh_begin(STATE(corsaro)->attack_hash);
      i != kh_end(STATE(corsaro)->attack_hash); ++i)
    {
      if(kh_exist(STATE(corsaro)->attack_hash, i))
	{
	  vector = kh_key(STATE(corsaro)->attack_hash, i);

	  if(attack_vector_is_expired(vector, int_end->time) != 0)
	    {
	      kh_del(av, STATE(corsaro)->attack_hash, i);
	      attack_vector_free(vector);
	      vector = NULL;
	    }
	  else if(attack_vector_is_attack(corsaro, vector, int_end->time) != 0)
	    {
	      /* this is an attack */
	      /* add it to the attack array so we can know how many
		 before we dump it */
	      attack_arr[attack_arr_cnt] = vector;
	      attack_arr_cnt++;
	    }
	  else
	    {
	      attack_vector_reset(vector);
	    }
	}
    }

  corsaro_io_write_interval_start(corsaro, STATE(corsaro)->outfile,
				  &corsaro->interval_start);
  if(corsaro->global_file != NULL)
    {
      corsaro_io_write_plugin_start(corsaro, corsaro->global_file,
				    PLUGIN(corsaro));
    }
  if(CORSARO_FILE_MODE(STATE(corsaro)->outfile) == CORSARO_FILE_MODE_ASCII)
    {
      if(corsaro->global_file != NULL)
	{
	  /* global stats */
	  /* dump the number of mismatched packets and vectors */
	  corsaro_file_printf(corsaro, corsaro->global_file,
			      "mismatch: %"PRIu32"\n"
			      "attack_vectors: %"PRIu32"\n"
			      "non-attack_vectors: %"PRIu32"\n",
			      STATE(corsaro)->number_mismatched_packets,
			      attack_arr_cnt,
			      kh_size(STATE(corsaro)->attack_hash)
			      -attack_arr_cnt);
	}

      /* dump the number of vectors */
      corsaro_file_printf(corsaro, STATE(corsaro)->outfile, "%"PRIu32"\n",
			attack_arr_cnt);
      /* dump the vectors */
      for(i = 0; i < attack_arr_cnt; i++)
	{
	  if(ascii_dump(corsaro, attack_arr[i]) != 0)
	    {
	      corsaro_log(__func__, corsaro, "could not dump hash");
	      return -1;
	    }
	  /* reset the interval stats */
	  attack_vector_reset(attack_arr[i]);
	}
    }
  else if(CORSARO_FILE_MODE(STATE(corsaro)->outfile) == CORSARO_FILE_MODE_BINARY)
      {
	if(corsaro->global_file != NULL)
	  {
	    /* global stats */
	    bytes_htonl(&gbuf[0], STATE(corsaro)->number_mismatched_packets);
	    bytes_htonl(&gbuf[4], attack_arr_cnt);
	    bytes_htonl(&gbuf[8],
			kh_size(STATE(corsaro)->attack_hash)-attack_arr_cnt);
	    if(corsaro_file_write(corsaro, corsaro->global_file,
				  &gbuf[0], 12) != 12)
	      {
		corsaro_log(__func__, corsaro,
			    "could not dump global stats to file");
		return -1;
	      }
	  }

	/* dump the number of vectors */
	bytes_htonl(&cntbuf[0], attack_arr_cnt);
	if(corsaro_file_write(corsaro, STATE(corsaro)->outfile,
			    &cntbuf[0], 4) != 4)
	  {
	    corsaro_log(__func__, corsaro,
			"could not dump vector count to file");
	    return -1;
	  }
	/* dump the vectors */
	for(i = 0; i < attack_arr_cnt; i++)
	  {
	    if(binary_dump(corsaro, attack_arr[i]) != 0)
	      {
		corsaro_log(__func__, corsaro, "could not dump hash");
		return -1;
	      }
	    attack_vector_reset(attack_arr[i]);
	  }
      }
  else
    {
      corsaro_log(__func__, corsaro, "invalid mode");
      return -1;
    }
  if(corsaro->global_file != NULL)
    {
      corsaro_io_write_plugin_end(corsaro, corsaro->global_file,
				  PLUGIN(corsaro));
    }
  corsaro_io_write_interval_end(corsaro, STATE(corsaro)->outfile, int_end);

  STATE(corsaro)->number_mismatched_packets = 0;

  free(attack_arr);

  /* if we are rotating, now is when we should do it */
  if(corsaro_is_rotate_interval(corsaro))
    {
      /* close the current file */
      if(STATE(corsaro)->outfile != NULL)
	{
	  corsaro_file_close(corsaro, STATE(corsaro)->outfile);
	  STATE(corsaro)->outfile = NULL;
	}
    }

  return 0;
}