Ejemplo n.º 1
0
class PalevoCcBot(AbuseCHFeedBot):
    feed_malware = "palevo"
    feed_type = "c&c"
    feed_name = "palevo c&c"

    feeds = bot.ListParam(default=["https://palevotracker.abuse.ch/?rssfeed"])

    def parse_link(self, link):
        # The source seems to provice invalid links, which can
        # be fixed by changing the URL scheme from http to https.
        split = urlparse.urlparse(link)
        if split[0].lower() == "http":
            link = urlparse.urlunparse(["https"] + list(split[1:]))
        yield "description url", link

    def parse_title(self, title):
        yield host_or_ip(title.split()[0])

    def parse_description(self, description):
        for key, value in split_description(description):
            if key == "status":
                yield key, value
            elif key == "sbl" and value.lower() != "not listed":
                yield key + " id", value
            elif key == "ip address":
                yield "ip", value
Ejemplo n.º 2
0
class ZeusCcBot(AbuseCHFeedBot):
    feed_malware = "zeus"
    feed_type = "c&c"

    feeds = bot.ListParam(default=["https://zeustracker.abuse.ch/rss.php"])

    def parse_title(self, title):
        pieces = title.split(None, 1)

        yield host_or_ip(pieces[0])

        if len(pieces) > 1:
            date = pieces[1]
            date = re.sub("[()]", "", date)
            yield "source time", date + "Z"

    def parse_description(self, description):
        for key, value in split_description(description):
            if key == "status":
                yield key, value
            elif key == "level":
                yield "description", resolve_level(value)
            elif key == "sbl" and value.lower() != "not listed":
                yield key + " id", value
            elif key == "ip address":
                yield "ip", value
Ejemplo n.º 3
0
class CSVArchiveBot(archivebot.ArchiveBot):
    csv_columns = bot.ListParam()

    def archive_path(self, *args, **keys):
        path = archivebot.ArchiveBot.archive_path(self, *args, **keys)
        path += ".csv"
        return path

    def archive_open(self, archive_path):
        archive = open(archive_path, "ab")
        try:
            csvfile = csv.writer(archive)

            if archive.tell() == 0:
                csvfile.writerow([x.encode("utf-8") for x in self.csv_columns])
        except:
            archive.close()
            raise

        return archive, csvfile

    def archive_write(self, (_, csvfile), timestamp, room_name, event):
        row = list()
        for column in self.csv_columns:
            value = event.value(column, u"").encode("utf-8")
            row.append(value)
        csvfile.writerow(row)
Ejemplo n.º 4
0
class FeodoCcBot(AbuseCHFeedBot):
    feed_type = "c&c"
    feed_name = "feodo c&c"

    feeds = bot.ListParam(
        default=["https://feodotracker.abuse.ch/feodotracker.rss"])

    # The timestamp in the title appears to be the firstseen timestamp,
    # skip including it as the "source time".
    parse_title = None

    def parse_description(self, description):
        got_version = False

        for key, value in split_description(description):
            if key == "version":
                yield "malware family", "feodo." + value.strip().lower()
                got_version = True
            elif key == "status":
                yield "status", value
            elif key == "host":
                yield host_or_ip(value)

        if not got_version:
            yield "malware family", "feodo"
Ejemplo n.º 5
0
class Malc0deBot(RSSBot):
    feeds = bot.ListParam(default=["https://malc0de.com/rss/"])

    def is_ip(self, string):
        for addr_type in (socket.AF_INET, socket.AF_INET6):
            try:
                socket.inet_pton(addr_type, string)
            except (ValueError, socket.error):
                pass
            else:
                return True
        return False

    def create_event(self, **keys):
        description = keys.get("description", None)
        if description is None:
            return None

        event = events.Event()
        event.add("feeder", "malc0de.com")
        event.add("feed", "malc0de")
        event.add("type", "malware url")

        link = keys.get("link", None)
        if link:
            event.add("description url", link)

        for part in description.split(","):
            pair = part.split(":", 1)
            if len(pair) < 2:
                continue

            key = pair[0].strip()
            value = pair[1].strip()
            if not key or not value:
                continue

            if key in ["URL", "MD5"]:
                if key == "URL":
                    value = "hxxp://" + value
                event.add(key.lower(), value)
            elif key == "IP Address":
                event.add("ip", value)

        host = keys.get("title", None)
        if not self.is_ip(host):
            event.add("domain name", host)

        event.add("description",
                  "This host is most likely hosting a malware URL.")

        return event
Ejemplo n.º 6
0
class ZeusDropzoneBot(AbuseCHFeedBot):
    feed_malware = "zeus"
    feed_type = "dropzone"

    feeds = bot.ListParam(
        default=["https://zeustracker.abuse.ch/monitor.php?urlfeed=dropzones"])

    def parse_description(self, description):
        for key, value in split_description(description):
            if key == "status":
                yield key, value
            elif key == "url":
                yield "url", value
                yield host_or_ip_from_url(value)
Ejemplo n.º 7
0
class SpamhausDropBot(bot.PollingBot):
    use_cymru_whois = bot.BoolParam()
    http_headers = bot.ListParam("a list of http header (k, v) tuples",
                                 default=[])

    @idiokit.stream
    def poll(self, url="https://www.spamhaus.org/drop/drop.lasso"):
        request = urllib2.Request(url)
        for key, value in self.http_headers:
            request.add_header(key, value)

        self.log.info("Downloading %s" % url)
        try:
            info, fileobj = yield utils.fetch_url(request)
        except utils.FetchUrlFailed as fuf:
            self.log.error("Download failed: %r", fuf)
            idiokit.stop(False)
        self.log.info("Downloaded")

        for line in fileobj.readlines():
            if line.startswith(';'):
                continue
            data = line.split(';')
            if not data:
                continue

            netblock_sbl = [x.strip() for x in data]
            if len(netblock_sbl) != 2:
                continue

            netblock, sbl = netblock_sbl
            if not len(netblock.split('/')) == 2:
                continue

            new = events.Event()
            new.add('netblock', netblock)
            new.add('description url',
                    "http://www.spamhaus.org/sbl/query/" + sbl)
            new.add('feeder', 'spamhaus')
            new.add('feed', 'spamhaus drop list')
            new.add('type', 'hijacked network')

            if self.use_cymru_whois:
                values = yield cymruwhois.lookup(netblock.split('/')[0])
                for key, value in values:
                    new.add(key, value)

            yield idiokit.send(new)
Ejemplo n.º 8
0
class ZeusConfigBot(AbuseCHFeedBot):
    feed_malware = "zeus"
    feed_type = "malware configuration"
    feed_name = "zeus malware configurations"

    feeds = bot.ListParam(default=["https://zeustracker.abuse.ch/monitor.php?urlfeed=configs"])

    def parse_description(self, description):
        for key, value in split_description(description):
            if key in ["status", "version"]:
                yield key, value
            elif key == "md5 hash":
                yield "md5", value
            elif key == "url":
                yield "url", value
                yield host_or_ip_from_url(value)
Ejemplo n.º 9
0
class SpyEyeConfigBot(AbuseCHFeedBot):
    feed_malware = "spyeye"
    feed_type = "malware configuration"

    feeds = bot.ListParam(default=[
        "https://spyeyetracker.abuse.ch/monitor.php?rssfeed=configurls"
    ])

    def parse_description(self, description):
        for key, value in split_description(description):
            if key == "status":
                yield key, value
            if key == "spyeye configurl":
                yield "url", value
                yield host_or_ip_from_url(value)
            elif key == "md5 hash":
                yield "md5", value
Ejemplo n.º 10
0
class ZeusBinaryBot(AbuseCHFeedBot):
    feed_malware = "zeus"
    feed_type = "malware"

    feeds = bot.ListParam(
        default=["https://zeustracker.abuse.ch/monitor.php?urlfeed=binaries"])

    def parse_description(self, description):
        for key, value in split_description(description):
            if key == "url":
                yield "url", sanitize_url(value)
                yield host_or_ip_from_url(value)
            elif key == "virustotal" and value.lower() != "n/a":
                yield "virustotal", value
            elif key == "status":
                yield "status", value
            elif key == "md5 hash":
                yield "md5", value
Ejemplo n.º 11
0
class Info112Bot(RSSBot):
    feeds = bot.ListParam(default=["http://www.peto-media.fi/tiedotteet/rss.xml"])

    def create_event(self, **keys):
        description = keys.get("description", None)
        title = keys.get("title", None)
        if None in [description, title]:
            return None

        event = events.Event()
        event.add("feed", "112Info")

        url = keys.get("source", None)
        if url:
            event.add("source", url)

        date = " ".join(description.split()[:2])
        event.add("date", date)

        location = title.split(",")[0].split("/")[0]
        event.add("location", location)

        latitude, longitude = municipalities.get(location, (None, None))
        if latitude and longitude:
            event.add("latitude", latitude)
            event.add("longitude", longitude)

        definition = title.split(",")[1].strip()
        event.add("description", definition)

        for event_type in types:
            if definition.startswith(event_type):
                event.add("type", event_type)
                break

        for severity in severities:
            if definition.endswith(" %s" % severity):
                event.add("severity", severities[severity])
                break

        return event
Ejemplo n.º 12
0
class TrainBot(RSSBot):
    feeds = bot.ListParam("RSS feed urls.")

    def create_event(self, **keys):
        id = keys.get("guid", None)
        location = keys.get("{http://www.georss.org/georss}point", None)
        if None in [id, location]:
            return None

        event = events.Event()
        event.add("feed", "VR")
        event.add("id", id)

        url = keys.get("source", None)
        if url:
            event.add("source", url)

        location = location.split(" ")
        latitude = location[0]
        longitude = location[1]
        event.add("latitude", latitude)
        event.add("longitude", longitude)

        description = "Train %s" % id
        _from = keys.get("from", None)
        if _from:
            event.add("from", _from)
            description += " from %s" % _from

        to = keys.get("to", None)
        if to:
            event.add("to", to)
            description += " to %s" % to

        event.add("description", description)

        direction = keys.get("dir", None)
        if direction:
            event.add("direction", direction)

        return event
Ejemplo n.º 13
0
class RSSBot(bot.PollingBot):
    feeds = bot.ListParam("a list of RSS feed URLs")
    use_cymru_whois = bot.BoolParam()
    http_headers = bot.ListParam("a list of http header (k,v) tuples",
                                 default=[])

    def __init__(self, *args, **keys):
        bot.PollingBot.__init__(self, *args, **keys)

    def feed_keys(self, **_):
        for feed in self.feeds:
            yield (feed, )

    def poll(self, url):
        if self.use_cymru_whois:
            return self._poll(url) | cymruwhois.augment()
        return self._poll(url)

    @idiokit.stream
    def _poll(self, url):
        request = urllib2.Request(url)
        for key, value in self.http_headers:
            request.add_header(key, value)

        try:
            self.log.info('Downloading feed from: "%s"', url)
            _, fileobj = yield utils.fetch_url(request)
        except utils.FetchUrlFailed as e:
            self.log.error('Failed to download feed "%s": %r', url, e)
            idiokit.stop(False)

        self.log.info("Finished downloading the feed.")

        byte = fileobj.read(1)
        while byte and byte != "<":
            byte = fileobj.read(1)

        if byte == "<":
            fileobj.seek(-1, 1)
            try:
                for _, elem in etree.iterparse(fileobj):
                    for event in self._parse(elem, url):
                        if event:
                            yield idiokit.send(event)
            except ParseError as e:
                self.log.error('Invalid format on feed: "%s", "%r"', url, e)

    def _parse(self, elem, url):
        items = elem.findall("item")
        if not items:
            return

        for item in items:
            args = {"source": url}
            for element in list(item):
                if element.text and element.tag:
                    args[element.tag] = element.text

            event = self.create_event(**args)
            yield event

    def create_event(self, **keys):
        event = events.Event()
        for key, value in keys.iteritems():
            if value:
                event.add(key, value)
        return event
Ejemplo n.º 14
0
class Roomreader(bot.XMPPBot):
    bot_name = "roomreader"
    xmpp_rooms = bot.ListParam("""
        comma separated list of XMPP rooms roomreader should watch.
        (e.g. [email protected], [email protected])
        """)
    show_events = bot.BoolParam("print out events from channels")

    @idiokit.stream
    def main(self):
        try:
            xmpp = yield self.xmpp_connect()

            rooms = list()
            for name in self.xmpp_rooms:
                room = yield xmpp.muc.join(name, self.bot_name)
                rooms.append(
                    room | self.xmpp_to_log(room.jid, room.participants))
            yield idiokit.pipe(*rooms)
        except idiokit.Signal:
            pass

    @idiokit.stream
    def xmpp_to_log(self, own_jid, participants):
        in_room = set()
        for participant in participants:
            in_room.add(participant.name.resource)

        while True:
            elements = yield idiokit.next()

            for message in elements.with_attrs("from"):
                sender = JID(elements.get_attr("from"))
                if sender == own_jid or sender.resource is None:
                    continue

                resource = sender.resource.encode("unicode-escape")
                bare = unicode(sender.bare()).encode("unicode-escape")

                type_ = message.get_attr("type", None)
                if type_ == "unavailable":
                    if sender.resource in in_room:
                        in_room.discard(sender.resource)
                        self.log.info("* {0} left the room {1}.".format(
                            resource, bare))
                else:
                    if sender.resource not in in_room:
                        in_room.add(sender.resource)
                        self.log.info("* {0} entered the room {1}.".format(
                            resource, bare))

                for body in message.children("body"):
                    self.log.info("<{0}> {1}".format(
                        unicode(sender).encode("unicode-escape"),
                        body.text.encode("unicode-escape")))

                if self.show_events:
                    for event in events.Event.from_elements(message):
                        self.log.info("<{0}> {1}".format(
                            unicode(sender).encode("unicode-escape"),
                            event))