From c185f6b0a459e4eccbd1b6e605fc7df47c0e567b Mon Sep 17 00:00:00 2001 From: Eric Date: Sat, 31 Aug 2013 15:57:15 -0400 Subject: [PATCH] Fake an ethernet header rather than expose vulns There is probably a slight performance hit, but if you're scanning with ZMap through a VPN, you probably don't care THAT much about performance anyway...(also we only add a memcpy for all accepted packets) --- src/recv.c | 38 +++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/src/recv.c b/src/recv.c index 990762c..7f15765 100644 --- a/src/recv.c +++ b/src/recv.c @@ -59,6 +59,8 @@ static inline void set_ip(uint32_t ip) ip_seen[ip >> 6] |= (uint64_t)1 << (ip & 0x3F); } +static u_char fake_eth_hdr[65535]; + void packet_cb(u_char __attribute__((__unused__)) *user, const struct pcap_pkthdr *p, const u_char *bytes) { @@ -97,18 +99,19 @@ void packet_cb(u_char __attribute__((__unused__)) *user, fieldset_t *fs = fs_new_fieldset(); fs_add_ip_fields(fs, ip_hdr); - // HACK !!! FIXME !!! TODO !!! BAD BAD BAD - // probe modules for whatever reason expect the full ethernet frame - // in process_packet. For VPN, we only get back an IP frame - // so we COULD malloc a fake ethernet frame and copy over this payload - // but waaaaaaahhhh performanceeee. - // so instead, we will ASSUME (!) that the probe module will only care about - // the IP header, and do ip_hdr = &packet[sizeof(struct ethhdr)] the first thing - // in their function (tcp, icmp and udp probe modules all do). - // - // !!!IF YOUR PROBE MODULE USES THE ETH PACKET, AND YOU USE THE --vpn OPTION, YOU _WILL_ BE OWNED!!!! - // - zconf.probe_module->process_packet(bytes - (zconf.send_ip_pkts * sizeof(struct ethhdr)), buflen + (zconf.send_ip_pkts * sizeof(struct ethhdr)), fs); + // HACK: + // probe modules (for whatever reason) expect the full ethernet frame + // in process_packet. For VPN, we only get back an IP frame. + // Here, we fake an ethernet frame (which is initialized to + // have ETH_P_IP proto and 00s for dest/src). + if (zconf.send_ip_pkts) { + if (buflen > sizeof(fake_eth_hdr)) { + buflen = sizeof(fake_eth_hdr); + } + memcpy(&fake_eth_hdr[sizeof(struct ethhdr)], bytes, buflen); + bytes = fake_eth_hdr; + } + zconf.probe_module->process_packet(bytes, buflen, fs); fs_add_system_fields(fs, is_repeat, zsend.complete); int success_index = zconf.fsconf.success_index; assert(success_index < fs->len); @@ -133,18 +136,18 @@ void packet_cb(u_char __attribute__((__unused__)) *user, // we need to translate the data provided by the probe module // into a fieldset that can be used by the output module if (!is_success && zconf.filter_unsuccessful) { - goto cleanup; + goto cleanup; } if (is_repeat && zconf.filter_duplicates) { goto cleanup; } - o = translate_fieldset(fs, &zconf.fsconf.translation); + o = translate_fieldset(fs, &zconf.fsconf.translation); if (zconf.output_module && zconf.output_module->process_ip) { zconf.output_module->process_ip(o); } cleanup: fs_free(fs); - free(o); + free(o); if (zconf.output_module && zconf.output_module->update && !(zrecv.success_unique % zconf.output_module->update_interval)) { zconf.output_module->update(&zconf, &zsend, &zrecv); @@ -194,6 +197,11 @@ int recv_run(pthread_mutex_t *recv_ready_mutex) log_fatal("recv", "couldn't install filter"); } } + if (zconf.send_ip_pkts) { + struct ethhdr *eth = (struct ethhdr *)fake_eth_hdr; + memset(fake_eth_hdr, 0, sizeof(fake_eth_hdr)); + eth->h_proto = htons(ETH_P_IP); + } log_debug("recv", "receiver ready"); if (zconf.filter_duplicates) { log_debug("recv", "duplicate responses will be excluded from output");