Advertisement
DeaD_EyE

botnet_example_no_threading

Jul 14th, 2017
273
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.66 KB | None | 0 0
  1. #!/usr/bin/env python3
  2.  
  3. """
  4. This program connects to the provieded ssh connections
  5. and executes the commnd to all successful open connections
  6. and print the output to the stdout.
  7. After all commands has been executed, it cloeses all connections.
  8. """
  9.  
  10.  
  11. import logging
  12. from pexpect import pxssh
  13. # here you should work with argparse
  14. # docopts is cool, but then you've an aditional
  15. # depencency
  16.  
  17. # stipped out the cool colourful terminal stuff
  18. # it's just to explain a little bit the magic
  19. # and oo style
  20.  
  21.  
  22. class ClientError(Exception):
  23.     # just a class for an exception to be
  24.     # more concrete
  25.     pass
  26.  
  27.  
  28. class Client:
  29.     """
  30.    This class is a wrapper around pxssh.
  31.    """
  32.     def __init__(self, host, port, user, password):
  33.         """
  34.        host: ip address or domain name of the host you want to connect to
  35.        port: int, port number of ssh
  36.        user: username to login
  37.        password: password to login
  38.        """
  39.         self.host = host
  40.         self.port = port
  41.         self.user = user
  42.         self.password = password
  43.         options = {"StrictHostKeyChecking": "no", "UserKnownHostsFile": "/dev/null"}
  44.         # StrictHostKeyChecking saves you from errors, when host is unknown
  45.         # the second argument is to prevent saving the host in der knownhostsfile
  46.         # echo = False prevents repeating the command when accessing session.before
  47.         self.session = pxssh.pxssh(echo=False, options=options)
  48.  
  49.  
  50.     def connect(self):
  51.         """
  52.        Connects to the client
  53.        """
  54.         try:
  55.             self.session.login(self.host, self.user, self.password, port=self.port)
  56.         except Exception as e:
  57.             # this will raise the clieht error and
  58.             # will forward the error message to
  59.             # the more concrete class
  60.             # client error
  61.             raise ClientError(e)
  62.  
  63.  
  64.     def send_command(self, cmd):
  65.         """
  66.        Send a command to the client and returns the output without repeating the command.
  67.        """
  68.         self.session.sendline(cmd)
  69.         self.session.prompt()
  70.         # session.before are bytes. encoding depends on the target system
  71.         # I think. Calling decode without arguments is interpreted as utf-8
  72.         # this raise an error if the encoding is a different.
  73.         # The __init__ method of the class pxssh takes also a keyword argument for encoding
  74.         # look into the documentation
  75.         return self.session.before.decode()
  76.  
  77.  
  78. class Botnet:
  79.     """
  80.    This class handles many ssh connections.
  81.    """
  82.     def __init__(self, clients):
  83.         """
  84.        clients: (host: str, port: int, user: str, password: str)
  85.        """
  86.         self.clients = []
  87.         for host, port, username, password in clients:
  88.             client = Client(host, port, username, password)
  89.             try:
  90.                 client.connect()
  91.             except ClientError as e:
  92.                 #log.error(e) there is the host missing
  93.                 log.error('Could not establish connection to host {}:{}'.format(client.host, client.port))                
  94.             else:
  95.                 log.info('Connected to: {}:{}'.format(client.host, client.port))
  96.                 self.clients.append(client)
  97.  
  98.  
  99.     def __enter__(self):
  100.         """
  101.        Returns a Botnet object, where all connections are
  102.        closed when leaving the context manager
  103.        """
  104.         # just making a context manager
  105.         return self
  106.  
  107.  
  108.     def __exit__(self, *args):
  109.         # is called, when the with block has been left
  110.         # is also called when sys.exit() is called somewhere
  111.         # also called when an exeption has been raised inside the with block
  112.         # or the called method of the class itself, when it's not catched
  113.         for client in self.clients:
  114.             log.info('Closing client session of host: {}:{}'.format(client.host, client.port))
  115.             client.session.logout()
  116.  
  117.  
  118.     def command(self, command):
  119.         """
  120.        Sends a command to all connections.
  121.        Prints the returned text to stdout.
  122.        """
  123.         # changed the method name to command
  124.         # botnet.command sounds better as botnet.botnet_command
  125.         for client in self.clients:
  126.             output = client.send_command(command)
  127.             print('Client: {}:{}\nCommand: {}\n{}\n'.format(client.host, client.port, command, output))
  128.             # data should go to stdout, here is print ok, but you
  129.             # can also yield the content
  130.             # In the case of using a yield statement inside a
  131.             # function, makes a generator
  132.             # then you've to iterate over the generator
  133.  
  134.  
  135. def main():
  136.     """
  137.    Description of main function
  138.    But not needed......
  139.    """
  140.     # just as an example
  141.     # later you should learn how to put this information
  142.     # into a txt file for example
  143.     # it can be for example a csv file
  144.     # don't use pickle for it
  145.     clients = [('localhost', 22, 'username', 'passwort'), ('localhost', 22, 'username', 'passwort')]
  146.     with Botnet(clients) as botnet:
  147.         # makes a instance botnet of class Botnet
  148.         # block of the
  149.         # context manager
  150.         # very powerful
  151.         botnet.command('whoami')
  152.         botnet.command('ip addr show')
  153.     # leaving the block call the __exit__ method
  154.     # in this case, it will logout all clients
  155.  
  156. if __name__ == '__main__':
  157.     # good shell citizens are using logging.
  158.     # Logs are going to stderr
  159.     logging.basicConfig()
  160.     log = logging.getLogger(__file__)
  161.     # normally __name__, but this will give you __main__ back
  162.     log.setLevel(logging.INFO) # here you can set the logging setLevel
  163.     #log.setLevel(logging.ERROR)
  164.     main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement