Exemple #1
0
/***************************************************************************
 * Test the banner1 detection system by throwing random frames at it
 ***************************************************************************/
void
banner1_test(const char *filename)
{
    struct PcapFile *cap;
    unsigned link_type;

    cap = pcapfile_openread(filename);
    if (cap == NULL) {
        fprintf(stderr, "%s: can't open capture file\n", filename);
        return;
    }

    link_type = pcapfile_datalink(cap);

    for (;;) {
        int packets_read;
        unsigned secs;
        unsigned usecs;
        unsigned origlength;
        unsigned length;
        unsigned char px[65536];
        struct PreprocessedInfo parsed;
        unsigned x;


        packets_read = pcapfile_readframe(
                    cap,    /* capture dump file */
                    &secs, &usecs,
                    &origlength, &length,
                    px, sizeof(px));
        if (packets_read == 0)
            break;


        x = preprocess_frame(px, length, link_type, &parsed);
        if (x == 0)
            continue;

    }

    pcapfile_close(cap);
}
Exemple #2
0
int
pcap2zone(int argc, char *argv[])
{
    struct Pcap2Zone pcap2zone[1];
    struct Catalog *catalog;
    int i;

    /*
     * Create a catalog/database
     */
    catalog = catalog_create();
    pcap2zone->db = catalog;

    /* 
     * Initialize it with a pseudo-SOA record for the root zone
     */
    {
        static const struct DomainPointer root = {(const unsigned char*)"\0",1};
    	struct ZoneFileParser *parser;
        parser = zonefile_begin(
                    root,           /* origin */
                    60,             /* TTL */
                    10000,          /* filesize */
                    "<pcap2zone>",  /* filename */
                    zonefile_load,  /* callback */
                    catalog         /* callback data */
                    );
        LOAD("$TTL 60\r\n"
             "@    IN    SOA   ns hostmaster (\r\n"
             "                     2003080800 ; sn = serial number\r\n"
             "                     172800     ; ref = refresh = 2d\r\n"
             "                     15m        ; ret = update retry = 15m\r\n"
             "                     1209600    ; ex = expiry = 2w\r\n"
             "                     1H         ; nx = nxdomain ttl = 1h\r\n"
             "                     )\r\n", parser);
        zonefile_end(parser);

    }

    
    
    for (i=2; i<argc; i++) {
        const char *filename = argv[i];
        struct Tracker tracker[1];
        struct PcapFile *p;
        //uint64_t filesize;

        memset(tracker, 0, sizeof(tracker[0]));
        //filesize = 
            tracker_get_filesize(tracker, filename);

        p = pcapfile_openread(filename);
        if (p == NULL) {
            perror(filename);
            continue;
        }
               

        for (;;) {
            unsigned char buf[65536];
            int x;
            unsigned secs;
            unsigned usecs;
            unsigned original_length;
            unsigned bytes_read;

            x = pcapfile_readframe(
	            p,
                &secs, &usecs,
                &original_length, &bytes_read,
                buf, 
                sizeof(buf)
	            );
            if (x <= 0)
                break;


            {
                struct PreprocessedInfo info;
                unsigned x;

                
                x = preprocess_frame(
                    buf, 
                    bytes_read,
                    1,
                    &info);


                if (x && info.found == FOUND_DNS && info.port_src == 53)
                    grab_dns_response(catalog, buf, info.found_offset, bytes_read);

            }

            tracker_report(tracker, bytes_read);
        }

        pcapfile_close(p);
    }


    return Success;
}
Exemple #3
0
/***************************************************************************
 * 
 * Asynchronous receive thread
 *
 * The transmit and receive threads run independently of each other. There
 * is no record what was transmitted. Instead, the transmit thread sets a 
 * "SYN-cookie" in transmitted packets, which the receive thread will then
 * use to match up requests with responses.
 ***************************************************************************/
static void
receive_thread(void *v)
{
    struct ThreadPair *parms = (struct ThreadPair *)v;
    const struct Masscan *masscan = parms->masscan;

    struct Output *out;
    struct DedupTable *dedup;
    struct PcapFile *pcapfile = NULL;
    struct TCP_ConnectionTable *tcpcon = 0;


    LOG(1, "recv: start receive thread #%u\n", parms->nic_index);

    /* Lock this thread to a CPU. Transmit threads are on even CPUs,
     * receive threads on odd CPUs */
    if (pixie_cpu_get_count() > 1) {
        unsigned cpu_count = pixie_cpu_get_count();
        unsigned cpu = parms->nic_index * 2 + 1;
        while (cpu >= cpu_count) {
            cpu -= cpu_count;
            cpu++;
        }
        pixie_cpu_set_affinity(cpu);
    }

    /*
     * If configured, open a --pcap file for saving raw packets. This is
     * so that we can debug scans, but also so that we can look at the
     * strange things people send us. Note that we don't record transmitted
     * packets, just the packets we've received.
     */
    /*if (masscan->pcap_filename[0])
        pcapfile = pcapfile_openwrite(masscan->pcap_filename, 1);*/

    /*
     * Open output. This is where results are reported when saving
     * the --output-format to the --output-filename
     */
    out = output_create(masscan);

    /*
     * Create deduplication table. This is so when somebody sends us
     * multiple responses, we only record the first one.
     */
    dedup = dedup_create();

    /*
     * Create a TCP connection table for interacting with live
     * connections when doing --banners
     */
    if (masscan->is_banners) {
        tcpcon = tcpcon_create_table(
            (size_t)((masscan->max_rate/5) / masscan->nic_count), 
            parms->transmit_queue, 
            parms->packet_buffers,
            &parms->tmplset->pkts[Proto_TCP],
            output_report_banner,
            out,
            masscan->tcb.timeout
            );
    }

    if (masscan->is_offline) {
        while (!control_c_pressed_again)
            pixie_usleep(10000);
        parms->done_receiving = 1;
        return;
    }

    /*
     * Receive packets. This is where we catch any responses and print
     * them to the terminal.
     */
    LOG(1, "begin receive thread\n");
    while (!control_c_pressed_again) {
        int status;
        unsigned length;
        unsigned secs;
        unsigned usecs;
        const unsigned char *px;
        int err;
        unsigned x;
        struct PreprocessedInfo parsed;
        unsigned ip_me;
        unsigned ip_them;
        unsigned seqno_them;
        unsigned seqno_me;


        /*
         * RECIEVE
         *
         * This is the boring part of actually receiving a packet
         */
        err = rawsock_recv_packet(
                    parms->adapter,
                    &length,
                    &secs,
                    &usecs,
                    &px);

        if (err != 0)
            continue;
        

        /*
         * Do any TCP event timeouts based on the current timestamp from
         * the packet. For example, if the connection has been open for
         * around 10 seconds, we'll close the connection. (--banners)
         */
        if (tcpcon) {
            tcpcon_timeouts(tcpcon, secs, usecs);
        }

        if (length > 1514)
            continue;

        /*
         * "Preprocess" the response packet. This means to go through and
         * figure out where the TCP/IP headers are and the locations of
         * some fields, like IP address and port numbers.
         */
        x = preprocess_frame(px, length, 1, &parsed);
        if (!x)
            continue; /* corrupt packet */
        ip_me = parsed.ip_dst[0]<<24 | parsed.ip_dst[1]<<16
            | parsed.ip_dst[2]<< 8 | parsed.ip_dst[3]<<0;
        ip_them = parsed.ip_src[0]<<24 | parsed.ip_src[1]<<16
            | parsed.ip_src[2]<< 8 | parsed.ip_src[3]<<0;
        seqno_them = TCP_SEQNO(px, parsed.transport_offset);
        seqno_me = TCP_ACKNO(px, parsed.transport_offset);


        /* verify: my IP address */
        if (parms->adapter_ip != ip_me)
            continue;


        /*
         * Handle non-TCP protocols
         */
        switch (parsed.found) {
            case FOUND_ARP:
                /* OOPS: handle arp instead. Since we may completely bypass the TCP/IP
                 * stack, we may have to handle ARPs ourself, or the router will 
                 * lose track of us. */
                LOGip(2, ip_them, 0, "-> ARP [%u] \n", px[parsed.found_offset]);
                arp_response(   parms->adapter_ip,
                                parms->adapter_mac,
                                px, length,
                                parms->packet_buffers,
                                parms->transmit_queue);
                continue;
            case FOUND_UDP:
            case FOUND_DNS:
                if (!is_my_port(masscan, parsed.port_dst))
                    continue;
                handle_udp(out, px, length, &parsed);
                continue;
            case FOUND_ICMP:
                handle_icmp(out, px, length, &parsed);
                continue;
            case FOUND_TCP:
                /* fall down to below */
                break;
            default:
                continue;
        }


        /* verify: my port number */
        if (parms->adapter_port != parsed.port_dst)
            continue;

        /* Save raw packet in --pcap file */
        if (pcapfile) {
            pcapfile_writeframe(
                pcapfile,
                px,
                length,
                length,
                secs,
                usecs);
        }

        {
            char buf[64];
            LOGip(5, ip_them, parsed.port_src, "-> TCP ackno=0x%08x flags=0x%02x(%s)\n", 
                seqno_me, 
                TCP_FLAGS(px, parsed.transport_offset),
                reason_string(TCP_FLAGS(px, parsed.transport_offset), buf, sizeof(buf)));
        }

        /* If recording --banners, create a new "TCP Control Block (TCB)" */
        if (tcpcon) {
            struct TCP_Control_Block *tcb;

            /* does a TCB already exist for this connection? */
            tcb = tcpcon_lookup_tcb(tcpcon,
                            ip_me, ip_them,
                            parsed.port_dst, parsed.port_src);

            if (TCP_IS_SYNACK(px, parsed.transport_offset)) {
                if (syn_hash(ip_them, parsed.port_src) != seqno_me - 1) {
                    LOG(2, "%u.%u.%u.%u - bad cookie: ackno=0x%08x expected=0x%08x\n", 
                        (ip_them>>24)&0xff, (ip_them>>16)&0xff, (ip_them>>8)&0xff, (ip_them>>0)&0xff, 
                        seqno_me-1, syn_hash(ip_them, parsed.port_src));
                    continue;
                }

                if (tcb == NULL) {
                    tcb = tcpcon_create_tcb(tcpcon,
                                    ip_me, ip_them, 
                                    parsed.port_dst, 
                                    parsed.port_src, 
                                    seqno_me, seqno_them+1);
                }

                tcpcon_handle(tcpcon, tcb, TCP_WHAT_SYNACK, 
                    0, 0, secs, usecs, seqno_them+1);

            } else if (tcb) {
                /* If this is an ACK, then handle that first */
                if (TCP_IS_ACK(px, parsed.transport_offset)) {
                    tcpcon_handle(tcpcon, tcb, TCP_WHAT_ACK, 
                        0, seqno_me, secs, usecs, seqno_them);
                }

                /* If this contains payload, handle that */
                if (parsed.app_length) {
                    tcpcon_handle(tcpcon, tcb, TCP_WHAT_DATA, 
                        px + parsed.app_offset, parsed.app_length,
                        secs, usecs, seqno_them);
                }

                /* If this is a FIN, handle that. Note that ACK + 
                 * payload + FIN can come together */
                if (TCP_IS_FIN(px, parsed.transport_offset) 
                    && !TCP_IS_RST(px, parsed.transport_offset)) {
                    tcpcon_handle(tcpcon, tcb, TCP_WHAT_FIN, 
                        0, 0, secs, usecs, seqno_them);
                }

                /* If this is a RST, then we'll be closing the connection */
                if (TCP_IS_RST(px, parsed.transport_offset)) {
                    tcpcon_handle(tcpcon, tcb, TCP_WHAT_RST, 
                        0, 0, secs, usecs, seqno_them);
                }
            } else if (TCP_IS_FIN(px, parsed.transport_offset)) {
                /* 
                 * NO TCB!
                 *  This happens when we've sent a FIN, deleted our connection,
                 *  but the other side didn't get the packet.
                 */
                if (!TCP_IS_RST(px, parsed.transport_offset))
                tcpcon_send_FIN(
                    tcpcon,
                    ip_me, ip_them,
                    parsed.port_dst, parsed.port_src,
                    seqno_them, seqno_me);
            }

        }
Exemple #4
0
/***************************************************************************
 * Print packet info, when using nmap-style --packet-trace option
 ***************************************************************************/
void
packet_trace(FILE *fp, const unsigned char *px, size_t length, unsigned is_sent)
{
    unsigned x;
    struct PreprocessedInfo parsed;
    unsigned src_ip;
    unsigned dst_ip;
    char from[32];
    char to[32];
    char sz_type[32];
    unsigned type;
    double timestamp = 1.0 * pixie_gettime() / 1000000.0;
    unsigned offset;
    const char *direction;
    
    if (is_sent)
        direction = "SENT";
    else
        direction = "RCVD";

    /* parse the packet */
    x = preprocess_frame(px, (unsigned)length, 1, &parsed);
    if (!x)
        return;
    offset = parsed.found_offset;
    
    src_ip = parsed.ip_src[0] << 24
        | parsed.ip_src[1] << 16
        | parsed.ip_src[2] << 8
        | parsed.ip_src[3];
    dst_ip = parsed.ip_dst[0] << 24
        | parsed.ip_dst[1] << 16
        | parsed.ip_dst[2] << 8
        | parsed.ip_dst[3];

    /* format the IP addresses into fixed-width fields */
    sprintf_s(from, sizeof(from), "%u.%u.%u.%u:%u",
              (src_ip>>24)&0xFF, (src_ip>>16)&0xFF,
              (src_ip>>8)&0xFF, (src_ip>>0)&0xFF,
              parsed.port_src);
    
    sprintf_s(to, sizeof(to), "%u.%u.%u.%u:%u",
              (dst_ip>>24)&0xFF, (dst_ip>>16)&0xFF,
              (dst_ip>>8)&0xFF, (dst_ip>>0)&0xFF,
              parsed.port_dst);
    
    switch (parsed.found) {
        case FOUND_ARP:
            type = px[offset+6]<<8 | px[offset+7];
			*strchr(to, ':') = '\0';
			*strchr(from, ':') = '\0';
            switch (type) {
                case 1:strcpy_s(sz_type, sizeof(sz_type), "request"); break;
                case 2:strcpy_s(sz_type, sizeof(sz_type), "response"); break;
                default: sprintf_s(sz_type, sizeof(sz_type), "unknown(%u)", type); break;
            }
            fprintf(fp, "%s (%5.4f) ARP  %-21s > %-21s %s\n", direction,
                    timestamp - global_timestamp_start, from, to, sz_type);
            break;
        case FOUND_DNS:
        case FOUND_UDP:
            fprintf(fp, "%s (%5.4f) UDP  %-21s > %-21s \n", direction,
                    timestamp - global_timestamp_start, from, to);
            break;
        case FOUND_ICMP:
            fprintf(fp, "%s (%5.4f) ICMP %-21s > %-21s \n", direction,
                    timestamp - global_timestamp_start, from, to);
            break;
        case FOUND_TCP:
            type = px[offset+13];
            switch (type) {
                case 0x00: strcpy_s(sz_type, sizeof(sz_type), "NULL"); break;
                case 0x01: strcpy_s(sz_type, sizeof(sz_type), "FIN"); break;
                case 0x11: strcpy_s(sz_type, sizeof(sz_type), "FIN-ACK"); break;
                case 0x19: strcpy_s(sz_type, sizeof(sz_type), "FIN-ACK-PSH"); break;
                case 0x02: strcpy_s(sz_type, sizeof(sz_type), "SYN"); break;
                case 0x12: strcpy_s(sz_type, sizeof(sz_type), "SYN-ACK"); break;
                case 0x04: strcpy_s(sz_type, sizeof(sz_type), "RST"); break;
                case 0x14: strcpy_s(sz_type, sizeof(sz_type), "RST-ACK"); break;
                case 0x15: strcpy_s(sz_type, sizeof(sz_type), "RST-FIN-ACK"); break;
                case 0x10: strcpy_s(sz_type, sizeof(sz_type), "ACK"); break;
                case 0x18: strcpy_s(sz_type, sizeof(sz_type), "ACK-PSH"); break;
                default:
                    sprintf_s(sz_type, sizeof(sz_type),
                              "%s%s%s%s%s%s%s%s",
                              (type&0x01)?"FIN":"",
                              (type&0x02)?"SYN":"",
                              (type&0x04)?"RST":"",
                              (type&0x08)?"PSH":"",
                              (type&0x10)?"ACK":"",
                              (type&0x20)?"URG":"",
                              (type&0x40)?"ECE":"",
                              (type&0x80)?"CWR":""
                              );
                    break;
            }
            fprintf(fp, "%s (%5.4f) TCP  %-21s > %-21s %s\n", direction,
                    timestamp - global_timestamp_start, from, to, sz_type);
            break;
        case FOUND_IPV6:
            break;
        default:
            fprintf(fp, "%s (%5.4f) UNK  %-21s > %-21s [%u]\n", direction, 
                    timestamp - global_timestamp_start, from, to, parsed.found);
            break;
    }


}