/**************************************************************************** Program: $Id: net.c,v 1.5 2006/11/19 21:01:17 rbeverly Exp $ Author: Rob Beverly Date: $Date: 2006/11/19 21:01:17 $ Description: Spoofer utility routines ****************************************************************************/ #include "spoof.h" #ifdef _WIN32 static int rawsock = 1; #endif /* Fill buffer with the spoofed packet */ int craftPacket(char *buf, char *payload, int payloadlen, struct sockaddr_in *src, struct sockaddr_in *dst, u_char ttl) { struct udpiphdr *ui; struct ip *ip; int packetlen; memset(buf, 0, BUFSIZE); ip = (struct ip *)buf; ui = (struct udpiphdr *)buf; packetlen = payloadlen + sizeof(struct udpiphdr); /* Copy payload */ memcpy((buf + sizeof(struct udpiphdr)), payload, payloadlen); /* Create Pseudo-Header First */ ui->ui_pr = IPPROTO_UDP; ui->ui_len = htons(payloadlen + sizeof(struct udphdr)); ui->ui_src = src->sin_addr; ui->ui_dst = dst->sin_addr; ui->ui_sport = src->sin_port; ui->ui_dport = dst->sin_port; ui->ui_ulen = ui->ui_len; if ((ui->ui_sum = in_cksum((u_short *) ui, packetlen)) == 0) ui->ui_sum = 0xffff; ip->ip_v = IPVERSION; ip->ip_hl = sizeof(struct ip) >> 2; ip->ip_tos = 0; /* FreeBSD raw sockets expect host not network order */ #ifdef _FBSD ip->ip_len = packetlen; ip->ip_off = IP_DF; #else ip->ip_len = htons(packetlen); ip->ip_off = htons(IP_DF); #endif ip->ip_id = rand() % 32768; ip->ip_sum = 0; ip->ip_ttl = ttl; if (DEBUG) { printf("Complete packet:\n"); dumpPacket((unsigned char *)ip, packetlen); } return (packetlen); } /* Build Spoofer Report */ void craftReport(spoof_t *report, unsigned short unused, unsigned long addr, char *seqno) { #ifdef SPOOFER_BIG_ENDIAN report->ver = byte16Swap(VERSION); report->unused = byte16Swap(unused); #else report->ver = VERSION; report->unused = unused; #endif report->addr = addr; strncpy((char *) report->seqno, seqno, SEQNOSIZE); } unsigned short in_cksum(unsigned short *addr, int len) { int nleft = len; int sum = 0; unsigned short *w = addr; unsigned short answer = 0; /* * Our algorithm is simple, using a 32 bit accumulator (sum), we add * sequential 16 bit words to it, and at the end, fold back all the * carry bits from the top 16 bits into the lower 16 bits. */ while (nleft > 1) { sum += *w++; nleft -= 2; } /* 4mop up an odd byte, if necessary */ if (nleft == 1) { *(unsigned char *)(&answer) = *(unsigned char *)w ; sum += answer; } /* 4add back carry outs from top 16 bits to low 16 bits */ sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ sum += (sum >> 16); /* add carry */ answer = ~sum; /* truncate to 16 bits */ return(answer); } /* Debug routine for examining raw packets */ void dumpPacket(unsigned char *pkt, int len) { int i; for (i=1;i<=len;i++) { printf("%02x ", *pkt); pkt++; if (i%4 == 0) printf("\n"); } printf("\n"); } /* Generate a random ASCII sequence */ void genSequence(unsigned char *buf, int len) { int i; int byte; rand(); for (i=0;i= 48 && byte <= 57) { *buf = byte; buf++; } else if (byte >= 97 && byte <= 122) { *buf = byte; buf++; } else { i--; } } *buf = '\0'; } /* Ugly and inefficient, but at least it's readable and endian-safe */ int checkRFC1918(struct in_addr *in) { in_addr_t a1, a2; a1 = inet_addr("10.0.0.0"); a2 = inet_addr("10.255.255.255"); if ( (ntohl(in->s_addr) >= ntohl(a1)) && (ntohl(in->s_addr) <= ntohl(a2)) ) return 1; a1 = inet_addr("172.16.0.0"); a2 = inet_addr("172.31.255.255"); if ( (ntohl(in->s_addr) >= ntohl(a1)) && (ntohl(in->s_addr) <= ntohl(a2)) ) return 1; a1 = inet_addr("192.168.0.0"); a2 = inet_addr("192.168.255.255"); if ( (ntohl(in->s_addr) >= ntohl(a1)) && (ntohl(in->s_addr) <= ntohl(a2)) ) return 1; return 0; } /* Handy routines that follow taken directly from R. Stevens UNP */ ssize_t /* Read "n" bytes from a descriptor. */ readn(int fd, void *vptr, size_t n) { size_t nleft; ssize_t nread; char *ptr; ptr = vptr; nleft = n; while (nleft > 0) { if ( (nread = read(fd, ptr, nleft)) < 0) { if (errno == EINTR) nread = 0; /* and call read() again */ else return(-1); } else if (nread == 0) break; /* EOF */ nleft -= nread; ptr += nread; } return(n - nleft); /* return >= 0 */ } /* end readn */ ssize_t Readn(int fd, void *ptr, size_t nbytes) { ssize_t n; if ( (n = readn(fd, ptr, nbytes)) < 0) perror("readn error"); return(n); } ssize_t /* Write "n" bytes to a descriptor. */ writen(int fd, const void *vptr, size_t n) { size_t nleft; ssize_t nwritten; const char *ptr; ptr = vptr; nleft = n; while (nleft > 0) { #if _WIN32 if ( (nwritten = send(fd, ptr, nleft, 0)) <= 0) { #else if ( (nwritten = write(fd, ptr, nleft)) <= 0) { #endif if (errno == EINTR) nwritten = 0; /* and call write() again */ else return(-1); /* error */ } nleft -= nwritten; ptr += nwritten; } return(n); } /* end writen */ void Writen(int fd, void *ptr, size_t nbytes) { if (writen(fd, ptr, nbytes) != nbytes) perror("writen error"); } static ssize_t my_read(int fd, char *ptr) { static int read_cnt = 0; static char *read_ptr; static char read_buf[MAXLINE]; if (read_cnt <= 0) { again: #if _WIN32 if ( (read_cnt = recv(fd, read_buf, sizeof(read_buf), 0)) < 0) { #else if ( (read_cnt = read(fd, read_buf, sizeof(read_buf))) < 0) { #endif if (errno == EINTR) goto again; return(-1); } else if (read_cnt == 0) return(0); read_ptr = read_buf; } read_cnt--; *ptr = *read_ptr++; return(1); } ssize_t readline(int fd, void *vptr, size_t maxlen) { int n, rc; char c, *ptr; ptr = vptr; for (n = 1; n < maxlen; n++) { if ( (rc = my_read(fd, &c)) == 1) { *ptr++ = c; if (c == '\n') break; /* newline is stored, like fgets() */ } else if (rc == 0) { if (n == 1) return(0); /* EOF, no data read */ else break; /* EOF, some data was read */ } else return(-1); /* error, errno set by read() */ } *ptr = 0; /* null terminate like fgets() */ return(n); } /* end readline */ ssize_t Readline(int fd, void *ptr, size_t maxlen) { ssize_t n; if ( (n = readline(fd, ptr, maxlen)) < 0) perror("readline error"); if (n == 0) printf("** server terminated prematurely"); return(n); } /* New socket wrapper */ int newSocket(int type, int proto) { int sock = 0; #ifdef _WIN32 sock = socket(AF_INET, type, proto); if (sock == INVALID_SOCKET) winfatal("** WSASocket() failed: %d\n", WSAGetLastError()); #else if ((sock = socket(AF_INET, type, proto)) < 0) pfatal("create socket"); #endif return (sock); } int connectSock(int sock, struct sockaddr_in *dst, int len) { #ifdef _WIN32 int ret; ret = connect(sock, (SOCKADDR *) dst, len); if (ret == SOCKET_ERROR) winfatal("** connect failed: %d\n", WSAGetLastError()); #else if ((connect(sock, (struct sockaddr *) dst, len)) < 0) pfatal("connect"); #endif return (1); } int optSocketTTL(int sock, int val) { #ifdef _WIN32 BOOL on = TRUE; int ret; #else int on = 1; #endif on = val; #ifdef _WIN32 ret = setsockopt(sock, IPPROTO_IP, IP_TTL, (char *)&on, sizeof(on)); if (ret == SOCKET_ERROR) winfatal("** setsockopt(IP_TTL) failed: %d\n", WSAGetLastError()); #else if ((setsockopt(sock, IPPROTO_IP, IP_TTL, (char *)&on, sizeof(on))) < 0) pfatal("setsockopt IP_TTL"); #endif return (1); } int optSocketHDRINCL(int sock) { #ifdef _WIN32 BOOL on = TRUE; int ret; #else int on = 1; #endif #ifdef _WIN32 ret = setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (char *)&on, sizeof(on)); if (ret == SOCKET_ERROR) winfatal("** setsockopt(IP_HDRINCL) failed: %d\n", WSAGetLastError()); #else if ((setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (char *)&on, sizeof(on))) < 0) pfatal("setsockopt IP_HDRINCL"); #endif return (1); } int socketSend(int sock, void *msg, int len, struct sockaddr_in *dst, int tolen) { #ifdef _WIN32 int ret; ret = sendto(sock, (unsigned char *)msg, len, 0, (SOCKADDR *) dst, tolen); if (ret == SOCKET_ERROR) { printf("** sendto() failed: %d\n", WSAGetLastError()); return (SOCKET_ERROR); } #else if ((sendto(sock, (unsigned char *)msg, len, 0, (struct sockaddr *) dst, tolen)) < 0) { perror("sendto"); return (SENDTO_ERROR); } #endif return (1); } int socketSendSpoof(int sock, void *msg, int len, struct sockaddr_in *dst, int tolen) { #ifdef _WIN32 int ret; if (rawsock) { ret = sendto(sock, (unsigned char *)msg, len, 0, (SOCKADDR *) dst, tolen); if (ret == SOCKET_ERROR) { if (WSAGetLastError() == 10004) { printf("%s", WIN_SEND_ERR); rawsock = 0; return (WINRAWSOCK_ERROR); } else { printf("** sendto() failed: %d\n", WSAGetLastError()); } return (SOCKET_ERROR); } } else { ret = etherSend(msg, len); } #else if ((sendto(sock, (unsigned char *)msg, len, 0, (struct sockaddr *) dst, tolen)) < 0) { perror("sendto"); return (SENDTO_ERROR); } #endif return (1); }