Example #1
0
class PastePwn(object):
    def __init__(self, database=None, proxies=None):
        self.logger = logging.getLogger(__name__)
        self.database = database
        self.paste_queue = Queue()
        self.action_queue = Queue()
        self.__exception_event = Event()
        self.__request = Request(proxies)  # initialize singleton

        # Usage of ipify to get the IP - Uses the X-Forwarded-For Header which might
        # lead to issues with proxies
        try:
            ip = self.__request.get("https://api.ipify.org")
            self.logger.info("Your public IP is {0}".format(ip))
        except Exception as e:
            self.logger.warning(
                "Could not fetch public IP via ipify: {0}".format(e))

        self.scraping_handler = ScrapingHandler(
            paste_queue=self.paste_queue,
            exception_event=self.__exception_event)
        self.paste_dispatcher = PasteDispatcher(
            paste_queue=self.paste_queue,
            action_queue=self.action_queue,
            exception_event=self.__exception_event)
        self.action_handler = ActionHandler(
            action_queue=self.action_queue,
            exception_event=self.__exception_event)

        if self.database is not None:
            # Save every paste to the database with the AlwaysTrueAnalyzer
            self.logger.info("Database provided! Storing pastes in there.")
            database_action = DatabaseAction(self.database)
            always_true = AlwaysTrueAnalyzer(database_action)
            self.add_analyzer(always_true)
        else:
            self.logger.info("No database provided!")

    def add_scraper(self, scraper):
        scraper.init_exception_event(self.__exception_event)
        self.scraping_handler.add_scraper(scraper)

    def add_analyzer(self, analyzer):
        self.paste_dispatcher.add_analyzer(analyzer)

    def start(self):
        if self.__exception_event.is_set():
            self.logger.error(
                "An exception occured. Aborting the start of PastePwn!")
            exit(1)

        self.scraping_handler.start()
        self.paste_dispatcher.start()
        self.action_handler.start()

    def stop(self):
        self.scraping_handler.stop()
        self.paste_dispatcher.stop()
        self.action_handler.stop()
Example #2
0
class PastePwn(object):
    """Represents an instance of the pastepwn core module"""
    def __init__(self, database=None, proxies=None, store_all_pastes=True):
        """
        Basic PastePwn object handling the connection to pastebin and all the analyzers and actions
        :param database: Database object extending AbstractDB
        :param proxies: Dict of proxies as defined in the requests documentation
        :param store_all_pastes: Bool to decide if all pastes should be stored into the db
        """
        self.logger = logging.getLogger(__name__)
        self.is_idle = False
        self.database = database
        self.paste_queue = Queue()
        self.action_queue = Queue()
        self.error_handlers = list()
        self.onstart_handlers = list()
        self.__exception_event = Event()
        self.__request = Request(proxies)  # initialize singleton

        # Usage of ipify to get the IP - Uses the X-Forwarded-For Header which might
        # lead to issues with proxies
        try:
            ip = self.__request.get("https://api.ipify.org")
            self.logger.info("Your public IP is {0}".format(ip))
        except Exception as e:
            self.logger.warning(
                "Could not fetch public IP via ipify: {0}".format(e))

        self.scraping_handler = ScrapingHandler(
            paste_queue=self.paste_queue,
            exception_event=self.__exception_event)
        self.paste_dispatcher = PasteDispatcher(
            paste_queue=self.paste_queue,
            action_queue=self.action_queue,
            exception_event=self.__exception_event)
        self.action_handler = ActionHandler(
            action_queue=self.action_queue,
            exception_event=self.__exception_event)

        if self.database is not None and store_all_pastes:
            # Save every paste to the database with the AlwaysTrueAnalyzer
            self.logger.info("Database provided! Storing pastes in there.")
            database_action = DatabaseAction(self.database)
            always_true = AlwaysTrueAnalyzer(database_action)
            self.add_analyzer(always_true)
        elif store_all_pastes:
            self.logger.info("No database provided!")
        else:
            self.logger.info("Not storing all pastes!")

    def add_scraper(self, scraper, restart_scraping=False):
        """
        Adds a scraper to the list of scrapers. Scraping handler must be restarted for this to take effect.
        :param scraper: Instance of a BasicScraper
        :param restart_scraping: Indicates if the scraping handler should be restarted. Not setting this option results in your scraper not being started.
        :return: None
         """
        scraper.init_exception_event(self.__exception_event)
        self.scraping_handler.add_scraper(scraper, restart_scraping)

    def add_analyzer(self, analyzer):
        """
        Adds a new analyzer to the list of analyzers
        :param analyzer: Instance of a BasicAnalyzer
        :return: None
        """

        self.paste_dispatcher.add_analyzer(analyzer)

    def add_error_handler(self, error_handler):
        """
        Adds an error handler which will be called when an error happens
        :param error_handler: Callable to be called when an error happens
        :return: None
        """
        if not callable(error_handler):
            self.logger.error(
                "The error handler you passed is not a function!")
            return

        self.error_handlers.append(error_handler)

    def add_onstart_handler(self, onstart_handler):
        """Add a function as onstart_handler"""
        if not callable(onstart_handler):
            self.logger.error(
                "The onstart handler you passed is not a function!")
            return

        self.onstart_handlers.append(onstart_handler)

    def start(self):
        """Starts the pastepwn instance"""
        if self.__exception_event.is_set():
            self.logger.error(
                "An exception occured. Aborting the start of PastePwn!")
            exit(1)
        if len(self.scraping_handler.scrapers) == 0:
            from pastepwn.scraping.pastebin import PastebinScraper
            pastebinscraper = PastebinScraper()
            self.add_scraper(pastebinscraper, True)
        self.scraping_handler.start()
        self.paste_dispatcher.start()
        self.action_handler.start()

        for onstart_handler in self.onstart_handlers:
            try:
                onstart_handler()
            except Exception as e:
                self.logger.error(
                    "Onstart handler %s failed with error: %s. Pastepwn is still running."
                    % (onstart_handler.__name__, e))

    def stop(self):
        """Stops the pastepwn instance"""
        self.scraping_handler.stop()
        self.paste_dispatcher.stop()
        self.action_handler.stop()
        self.is_idle = False

    def signal_handler(self, signum, frame):
        """Handler method to handle signals"""
        self.is_idle = False
        self.logger.info("Received signal {}, stopping...".format(signum))
        self.stop()

    def idle(self, stop_signals=(SIGINT, SIGTERM, SIGABRT)):
        """
        Blocks until one of the signals are received and stops the updater.
        Thanks to the python-telegram-bot developers - https://github.com/python-telegram-bot/python-telegram-bot/blob/2cde878d1e5e0bb552aaf41d5ab5df695ec4addb/telegram/ext/updater.py#L514-L529
        :param stop_signals: The signals to which the code reacts to
        """
        self.is_idle = True
        self.logger.info("In Idle!")

        for sig in stop_signals:
            signal(sig, self.signal_handler)

        while self.is_idle:
            if self.__exception_event.is_set():
                self.logger.warning(
                    "An exception occurred. Calling exception handlers and going down!"
                )
                for handler in self.error_handlers:
                    # call the error handlers in case of an exception
                    handler()
                self.is_idle = False
                self.stop()
                return

            sleep(1)