moriarty-project 0.1.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- moriarty/__init__.py +5 -0
- moriarty/adapters/__init__.py +0 -0
- moriarty/agent/__init__.py +0 -0
- moriarty/assets/modules/.gitkeep +0 -0
- moriarty/assets/modules/asia/douban.yaml +19 -0
- moriarty/assets/modules/asia/kakao.yaml +19 -0
- moriarty/assets/modules/asia/line.yaml +19 -0
- moriarty/assets/modules/asia/mixi.yaml +19 -0
- moriarty/assets/modules/asia/naver.yaml +19 -0
- moriarty/assets/modules/asia/qq.yaml +19 -0
- moriarty/assets/modules/asia/vk.yaml +19 -0
- moriarty/assets/modules/asia/wechat.yaml +19 -0
- moriarty/assets/modules/asia/weibo.yaml +19 -0
- moriarty/assets/modules/asia/xiaohongshu.yaml +19 -0
- moriarty/assets/modules/behance.yaml +47 -0
- moriarty/assets/modules/business/crunchbase.yaml +27 -0
- moriarty/assets/modules/business/fiverr.yaml +32 -0
- moriarty/assets/modules/business/freelancer.yaml +27 -0
- moriarty/assets/modules/business/glassdoor.yaml +27 -0
- moriarty/assets/modules/business/guru.yaml +26 -0
- moriarty/assets/modules/business/indeed.yaml +25 -0
- moriarty/assets/modules/business/monster.yaml +25 -0
- moriarty/assets/modules/business/peopleperhour.yaml +26 -0
- moriarty/assets/modules/business/toptal.yaml +28 -0
- moriarty/assets/modules/business/upwork.yaml +27 -0
- moriarty/assets/modules/business/ziprecruiter.yaml +25 -0
- moriarty/assets/modules/content/buymeacoffee.yaml +27 -0
- moriarty/assets/modules/content/gumroad.yaml +27 -0
- moriarty/assets/modules/content/ko-fi.yaml +32 -0
- moriarty/assets/modules/content/onlyfans.yaml +27 -0
- moriarty/assets/modules/content/patreon.yaml +33 -0
- moriarty/assets/modules/content/substack.yaml +32 -0
- moriarty/assets/modules/creative/500px.yaml +31 -0
- moriarty/assets/modules/creative/artstation.yaml +33 -0
- moriarty/assets/modules/creative/deviantart.yaml +32 -0
- moriarty/assets/modules/creative/flickr.yaml +31 -0
- moriarty/assets/modules/creative/pexels.yaml +26 -0
- moriarty/assets/modules/creative/unsplash.yaml +26 -0
- moriarty/assets/modules/creative/vimeo.yaml +31 -0
- moriarty/assets/modules/crypto/binance.yaml +27 -0
- moriarty/assets/modules/crypto/bitcointalk.yaml +33 -0
- moriarty/assets/modules/crypto/coinbase.yaml +26 -0
- moriarty/assets/modules/crypto/etherscan.yaml +32 -0
- moriarty/assets/modules/crypto/foundation.yaml +28 -0
- moriarty/assets/modules/crypto/kraken.yaml +27 -0
- moriarty/assets/modules/crypto/mirror.yaml +27 -0
- moriarty/assets/modules/crypto/niftygateway.yaml +26 -0
- moriarty/assets/modules/crypto/opensea.yaml +32 -0
- moriarty/assets/modules/crypto/rarible.yaml +27 -0
- moriarty/assets/modules/crypto/superrare.yaml +29 -0
- moriarty/assets/modules/dating/bumble.yaml +25 -0
- moriarty/assets/modules/dating/grindr.yaml +27 -0
- moriarty/assets/modules/dating/happn.yaml +25 -0
- moriarty/assets/modules/dating/her.yaml +27 -0
- moriarty/assets/modules/dating/hinge.yaml +25 -0
- moriarty/assets/modules/dating/match.yaml +25 -0
- moriarty/assets/modules/dating/meetme.yaml +27 -0
- moriarty/assets/modules/dating/okcupid.yaml +25 -0
- moriarty/assets/modules/dating/pof.yaml +25 -0
- moriarty/assets/modules/dating/tinder.yaml +25 -0
- moriarty/assets/modules/dating-nsfw/adultfriendfinder.yaml +28 -0
- moriarty/assets/modules/dating-nsfw/ashley-madison.yaml +26 -0
- moriarty/assets/modules/design/adobe-portfolio.yaml +27 -0
- moriarty/assets/modules/design/carbonmade.yaml +27 -0
- moriarty/assets/modules/design/cgsociety.yaml +27 -0
- moriarty/assets/modules/design/coroflot.yaml +27 -0
- moriarty/assets/modules/design/figma.yaml +27 -0
- moriarty/assets/modules/design/sketch.yaml +26 -0
- moriarty/assets/modules/dev/bitbucket.yaml +35 -0
- moriarty/assets/modules/dev/codeforces.yaml +32 -0
- moriarty/assets/modules/dev/codepen.yaml +34 -0
- moriarty/assets/modules/dev/hackerone.yaml +32 -0
- moriarty/assets/modules/dev/hackthebox.yaml +27 -0
- moriarty/assets/modules/dev/huggingface.yaml +27 -0
- moriarty/assets/modules/dev/kaggle.yaml +32 -0
- moriarty/assets/modules/dev/leetcode.yaml +32 -0
- moriarty/assets/modules/dev/replit.yaml +31 -0
- moriarty/assets/modules/dribbble.yaml +53 -0
- moriarty/assets/modules/ecommerce/etsy.yaml +32 -0
- moriarty/assets/modules/education/duolingo.yaml +32 -0
- moriarty/assets/modules/education/edx.yaml +26 -0
- moriarty/assets/modules/education/khanacademy.yaml +26 -0
- moriarty/assets/modules/education/lynda.yaml +27 -0
- moriarty/assets/modules/education/memrise.yaml +27 -0
- moriarty/assets/modules/education/pluralsight.yaml +27 -0
- moriarty/assets/modules/education/skillshare.yaml +27 -0
- moriarty/assets/modules/education/udacity.yaml +27 -0
- moriarty/assets/modules/email/github_email.yaml +40 -0
- moriarty/assets/modules/email/gravatar.yaml +23 -0
- moriarty/assets/modules/europe/badoo.yaml +19 -0
- moriarty/assets/modules/europe/lovoo.yaml +19 -0
- moriarty/assets/modules/europe/myspace.yaml +19 -0
- moriarty/assets/modules/europe/netlog.yaml +19 -0
- moriarty/assets/modules/europe/ok.yaml +19 -0
- moriarty/assets/modules/europe/skyrock.yaml +19 -0
- moriarty/assets/modules/europe/studivz.yaml +19 -0
- moriarty/assets/modules/europe/tuenti.yaml +19 -0
- moriarty/assets/modules/europe/viadeo.yaml +19 -0
- moriarty/assets/modules/europe/xing.yaml +19 -0
- moriarty/assets/modules/fitness/fitbit.yaml +27 -0
- moriarty/assets/modules/fitness/garmin.yaml +27 -0
- moriarty/assets/modules/fitness/myfitnesspal.yaml +27 -0
- moriarty/assets/modules/fitness/strava.yaml +33 -0
- moriarty/assets/modules/fitness/zwift.yaml +28 -0
- moriarty/assets/modules/food/allrecipes.yaml +27 -0
- moriarty/assets/modules/food/tasty.yaml +27 -0
- moriarty/assets/modules/food/yelp.yaml +32 -0
- moriarty/assets/modules/food/zomato.yaml +28 -0
- moriarty/assets/modules/forums/4chan.yaml +26 -0
- moriarty/assets/modules/forums/8kun.yaml +26 -0
- moriarty/assets/modules/forums/9gag.yaml +26 -0
- moriarty/assets/modules/forums/discourse.yaml +26 -0
- moriarty/assets/modules/forums/disqus.yaml +31 -0
- moriarty/assets/modules/forums/hackernews.yaml +32 -0
- moriarty/assets/modules/forums/launchpad.yaml +27 -0
- moriarty/assets/modules/forums/phpbb.yaml +25 -0
- moriarty/assets/modules/forums/quora.yaml +32 -0
- moriarty/assets/modules/forums/serverfault.yaml +27 -0
- moriarty/assets/modules/forums/slashdot.yaml +28 -0
- moriarty/assets/modules/forums/stackexchange.yaml +32 -0
- moriarty/assets/modules/forums/superuser.yaml +27 -0
- moriarty/assets/modules/forums/vbulletin.yaml +25 -0
- moriarty/assets/modules/forums/xenforo.yaml +25 -0
- moriarty/assets/modules/forums-nsfw/kiwifarms.yaml +25 -0
- moriarty/assets/modules/forums-nsfw/lolcow.yaml +26 -0
- moriarty/assets/modules/gaming/apextracker.yaml +27 -0
- moriarty/assets/modules/gaming/battlenet.yaml +26 -0
- moriarty/assets/modules/gaming/chess.yaml +30 -0
- moriarty/assets/modules/gaming/discord-public.yaml +27 -0
- moriarty/assets/modules/gaming/dotabuff.yaml +32 -0
- moriarty/assets/modules/gaming/epicgames.yaml +25 -0
- moriarty/assets/modules/gaming/faceit.yaml +33 -0
- moriarty/assets/modules/gaming/fortnitetracker.yaml +32 -0
- moriarty/assets/modules/gaming/gog.yaml +26 -0
- moriarty/assets/modules/gaming/itch.yaml +32 -0
- moriarty/assets/modules/gaming/kongregate.yaml +25 -0
- moriarty/assets/modules/gaming/minecraft.yaml +31 -0
- moriarty/assets/modules/gaming/opgg.yaml +32 -0
- moriarty/assets/modules/gaming/origin.yaml +26 -0
- moriarty/assets/modules/gaming/playstation.yaml +30 -0
- moriarty/assets/modules/gaming/roblox.yaml +31 -0
- moriarty/assets/modules/gaming/xbox.yaml +25 -0
- moriarty/assets/modules/github.yaml +68 -0
- moriarty/assets/modules/gitlab.yaml +60 -0
- moriarty/assets/modules/instagram.yaml +48 -0
- moriarty/assets/modules/latam/fotolog.yaml +27 -0
- moriarty/assets/modules/latam/orkut.yaml +26 -0
- moriarty/assets/modules/latam/taringa.yaml +27 -0
- moriarty/assets/modules/learning/coursera.yaml +26 -0
- moriarty/assets/modules/learning/udemy.yaml +26 -0
- moriarty/assets/modules/linkedin.yaml +40 -0
- moriarty/assets/modules/marketplaces/depop.yaml +28 -0
- moriarty/assets/modules/marketplaces/ebay.yaml +32 -0
- moriarty/assets/modules/marketplaces/grailed.yaml +27 -0
- moriarty/assets/modules/marketplaces/mercari.yaml +26 -0
- moriarty/assets/modules/marketplaces/poshmark.yaml +27 -0
- moriarty/assets/modules/marketplaces/reverb.yaml +27 -0
- moriarty/assets/modules/marketplaces/vinted.yaml +28 -0
- moriarty/assets/modules/medium.yaml +44 -0
- moriarty/assets/modules/music/audiomack.yaml +26 -0
- moriarty/assets/modules/music/bandcamp.yaml +30 -0
- moriarty/assets/modules/music/beatport.yaml +28 -0
- moriarty/assets/modules/music/deezer.yaml +26 -0
- moriarty/assets/modules/music/discogs.yaml +32 -0
- moriarty/assets/modules/music/genius.yaml +26 -0
- moriarty/assets/modules/music/lastfm.yaml +30 -0
- moriarty/assets/modules/music/mixcloud.yaml +26 -0
- moriarty/assets/modules/music/reverbnation.yaml +31 -0
- moriarty/assets/modules/music/soundcloud.yaml +31 -0
- moriarty/assets/modules/music/spotify.yaml +26 -0
- moriarty/assets/modules/music/tidal.yaml +26 -0
- moriarty/assets/modules/nsfw/adultwork.yaml +27 -0
- moriarty/assets/modules/nsfw/bongacams.yaml +28 -0
- moriarty/assets/modules/nsfw/cam4.yaml +28 -0
- moriarty/assets/modules/nsfw/chaturbate.yaml +28 -0
- moriarty/assets/modules/nsfw/clips4sale.yaml +27 -0
- moriarty/assets/modules/nsfw/extralunchmoney.yaml +27 -0
- moriarty/assets/modules/nsfw/fansly.yaml +28 -0
- moriarty/assets/modules/nsfw/fetlife.yaml +28 -0
- moriarty/assets/modules/nsfw/iwantclips.yaml +27 -0
- moriarty/assets/modules/nsfw/justforfans.yaml +28 -0
- moriarty/assets/modules/nsfw/loyalfans.yaml +28 -0
- moriarty/assets/modules/nsfw/manyvids.yaml +27 -0
- moriarty/assets/modules/nsfw/myfreecams.yaml +28 -0
- moriarty/assets/modules/nsfw/niteflirt.yaml +26 -0
- moriarty/assets/modules/nsfw/pornhub.yaml +32 -0
- moriarty/assets/modules/nsfw/redtube.yaml +27 -0
- moriarty/assets/modules/nsfw/stripchat.yaml +28 -0
- moriarty/assets/modules/nsfw/xhamster.yaml +27 -0
- moriarty/assets/modules/nsfw/xvideos.yaml +27 -0
- moriarty/assets/modules/nsfw/youporn.yaml +27 -0
- moriarty/assets/modules/photography/eyeem.yaml +25 -0
- moriarty/assets/modules/photography/fotki.yaml +25 -0
- moriarty/assets/modules/photography/photobucket.yaml +26 -0
- moriarty/assets/modules/photography/smugmug.yaml +25 -0
- moriarty/assets/modules/photography/vsco.yaml +27 -0
- moriarty/assets/modules/pinterest.yaml +40 -0
- moriarty/assets/modules/podcasts/anchor.yaml +26 -0
- moriarty/assets/modules/podcasts/castbox.yaml +26 -0
- moriarty/assets/modules/podcasts/podbean.yaml +26 -0
- moriarty/assets/modules/professional/about.yaml +31 -0
- moriarty/assets/modules/professional/academia.yaml +27 -0
- moriarty/assets/modules/professional/angellist.yaml +27 -0
- moriarty/assets/modules/professional/calendly.yaml +26 -0
- moriarty/assets/modules/professional/issuu.yaml +27 -0
- moriarty/assets/modules/professional/mendeley.yaml +27 -0
- moriarty/assets/modules/professional/notion.yaml +27 -0
- moriarty/assets/modules/professional/orcid.yaml +27 -0
- moriarty/assets/modules/professional/producthunt.yaml +31 -0
- moriarty/assets/modules/professional/researchgate.yaml +32 -0
- moriarty/assets/modules/professional/scribd.yaml +27 -0
- moriarty/assets/modules/professional/slideshare.yaml +31 -0
- moriarty/assets/modules/professional/trello.yaml +26 -0
- moriarty/assets/modules/professional/typeform.yaml +27 -0
- moriarty/assets/modules/reddit.yaml +46 -0
- moriarty/assets/modules/regional/amino.yaml +27 -0
- moriarty/assets/modules/regional/ask-fm.yaml +32 -0
- moriarty/assets/modules/regional/babycenter.yaml +26 -0
- moriarty/assets/modules/regional/cafemom.yaml +27 -0
- moriarty/assets/modules/regional/care2.yaml +27 -0
- moriarty/assets/modules/regional/diaspora.yaml +26 -0
- moriarty/assets/modules/regional/ello.yaml +27 -0
- moriarty/assets/modules/regional/gaia.yaml +27 -0
- moriarty/assets/modules/regional/habbo.yaml +27 -0
- moriarty/assets/modules/regional/imvu.yaml +27 -0
- moriarty/assets/modules/regional/lemmy.yaml +27 -0
- moriarty/assets/modules/regional/peertube.yaml +26 -0
- moriarty/assets/modules/regional/pixelfed.yaml +27 -0
- moriarty/assets/modules/regional/plurk.yaml +26 -0
- moriarty/assets/modules/regional/recroom.yaml +27 -0
- moriarty/assets/modules/regional/secondlife.yaml +26 -0
- moriarty/assets/modules/regional/vine-archive.yaml +27 -0
- moriarty/assets/modules/regional/vrchat.yaml +27 -0
- moriarty/assets/modules/regional/weheartit.yaml +27 -0
- moriarty/assets/modules/social/anilist.yaml +27 -0
- moriarty/assets/modules/social/beacons.yaml +26 -0
- moriarty/assets/modules/social/blogger.yaml +27 -0
- moriarty/assets/modules/social/crunchyroll.yaml +27 -0
- moriarty/assets/modules/social/discord.yaml +27 -0
- moriarty/assets/modules/social/dreamwidth.yaml +26 -0
- moriarty/assets/modules/social/facebook.yaml +34 -0
- moriarty/assets/modules/social/goodreads.yaml +32 -0
- moriarty/assets/modules/social/imdb.yaml +27 -0
- moriarty/assets/modules/social/kitsu.yaml +27 -0
- moriarty/assets/modules/social/letterboxd.yaml +32 -0
- moriarty/assets/modules/social/linktree.yaml +26 -0
- moriarty/assets/modules/social/livejournal.yaml +27 -0
- moriarty/assets/modules/social/mastodon.yaml +30 -0
- moriarty/assets/modules/social/minds.yaml +25 -0
- moriarty/assets/modules/social/myanimelist.yaml +32 -0
- moriarty/assets/modules/social/ravelry.yaml +27 -0
- moriarty/assets/modules/social/snapchat.yaml +25 -0
- moriarty/assets/modules/social/telegram.yaml +35 -0
- moriarty/assets/modules/social/tiktok.yaml +35 -0
- moriarty/assets/modules/social/trakt.yaml +28 -0
- moriarty/assets/modules/social/wattpad.yaml +32 -0
- moriarty/assets/modules/social/wordpress-com.yaml +26 -0
- moriarty/assets/modules/sports/espn.yaml +26 -0
- moriarty/assets/modules/sports/untappd.yaml +32 -0
- moriarty/assets/modules/stackoverflow.yaml +47 -0
- moriarty/assets/modules/steam.yaml +47 -0
- moriarty/assets/modules/streaming/caffeine.yaml +25 -0
- moriarty/assets/modules/streaming/dlive.yaml +27 -0
- moriarty/assets/modules/streaming/trovo.yaml +25 -0
- moriarty/assets/modules/travel/airbnb.yaml +26 -0
- moriarty/assets/modules/travel/booking.yaml +26 -0
- moriarty/assets/modules/travel/couchsurfing.yaml +27 -0
- moriarty/assets/modules/travel/tripadvisor.yaml +32 -0
- moriarty/assets/modules/tumblr.yaml +40 -0
- moriarty/assets/modules/twitch.yaml +48 -0
- moriarty/assets/modules/twitter.yaml +39 -0
- moriarty/assets/modules/youtube.yaml +42 -0
- moriarty/assets/templates/cves/CVE-2017-5638.yaml +27 -0
- moriarty/assets/templates/cves/CVE-2018-7600.yaml +30 -0
- moriarty/assets/templates/cves/CVE-2019-11510.yaml +27 -0
- moriarty/assets/templates/cves/CVE-2019-19781.yaml +28 -0
- moriarty/assets/templates/cves/CVE-2020-14882.yaml +28 -0
- moriarty/assets/templates/cves/CVE-2020-14883.yaml +29 -0
- moriarty/assets/templates/cves/CVE-2020-3452.yaml +28 -0
- moriarty/assets/templates/cves/CVE-2020-5902.yaml +28 -0
- moriarty/assets/templates/cves/CVE-2021-21972.yaml +31 -0
- moriarty/assets/templates/cves/CVE-2021-21985.yaml +28 -0
- moriarty/assets/templates/cves/CVE-2021-26084.yaml +30 -0
- moriarty/assets/templates/cves/CVE-2021-41773.yaml +25 -0
- moriarty/assets/templates/cves/CVE-2021-42013.yaml +28 -0
- moriarty/assets/templates/cves/CVE-2021-44228.yaml +27 -0
- moriarty/assets/templates/cves/CVE-2022-0185.yaml +21 -0
- moriarty/assets/templates/cves/CVE-2022-1388.yaml +36 -0
- moriarty/assets/templates/cves/CVE-2022-22954.yaml +28 -0
- moriarty/assets/templates/cves/CVE-2022-22965.yaml +31 -0
- moriarty/assets/templates/cves/CVE-2022-26134.yaml +27 -0
- moriarty/assets/templates/cves/CVE-2023-22515.yaml +27 -0
- moriarty/assets/templates/cves/CVE-2023-22527.yaml +29 -0
- moriarty/assets/templates/cves/CVE-2023-23752.yaml +33 -0
- moriarty/assets/templates/cves/CVE-2023-27350.yaml +27 -0
- moriarty/assets/templates/cves/CVE-2023-2868.yaml +27 -0
- moriarty/assets/templates/cves/CVE-2023-34362.yaml +27 -0
- moriarty/assets/templates/cves/CVE-2023-3519.yaml +28 -0
- moriarty/assets/templates/cves/CVE-2023-4966.yaml +27 -0
- moriarty/assets/templates/default-logins/admin-weak.yaml +40 -0
- moriarty/assets/templates/default-logins/wordpress-default.yaml +38 -0
- moriarty/assets/templates/exposures/aws-credentials.yaml +35 -0
- moriarty/assets/templates/exposures/backup-files.yaml +36 -0
- moriarty/assets/templates/exposures/database-files.yaml +34 -0
- moriarty/assets/templates/exposures/docker-exposed.yaml +31 -0
- moriarty/assets/templates/exposures/env-exposed.yaml +41 -0
- moriarty/assets/templates/exposures/git-exposed.yaml +41 -0
- moriarty/assets/templates/exposures/phpinfo.yaml +36 -0
- moriarty/assets/templates/exposures/svn-exposed.yaml +28 -0
- moriarty/assets/templates/fuzzing/api-endpoints.yaml +39 -0
- moriarty/assets/templates/fuzzing/common-files.yaml +37 -0
- moriarty/assets/templates/fuzzing/open-redirect-fuzz.yaml +35 -0
- moriarty/assets/templates/fuzzing/xss-search-fuzz.yaml +29 -0
- moriarty/assets/templates/git-config.yaml +18 -0
- moriarty/assets/templates/misconfigurations/cors-misconfiguration.yaml +30 -0
- moriarty/assets/templates/misconfigurations/debug-enabled.yaml +29 -0
- moriarty/assets/templates/misconfigurations/directory-listing.yaml +33 -0
- moriarty/assets/templates/misconfigurations/jwt-none-algo.yaml +30 -0
- moriarty/assets/templates/misconfigurations/ssl-tls-weak.yaml +23 -0
- moriarty/assets/templates/vulnerabilities/lfi-basic.yaml +31 -0
- moriarty/assets/templates/vulnerabilities/open-redirect.yaml +31 -0
- moriarty/assets/templates/vulnerabilities/rce-basic.yaml +34 -0
- moriarty/assets/templates/vulnerabilities/sqli-error.yaml +39 -0
- moriarty/assets/templates/vulnerabilities/ssrf-basic.yaml +31 -0
- moriarty/assets/templates/vulnerabilities/xss-reflected.yaml +38 -0
- moriarty/assets/templates/vulnerabilities/xxe-basic.yaml +30 -0
- moriarty/assets/wordlists/subdomains-1000.txt +1063 -0
- moriarty/cli/__init__.py +3 -0
- moriarty/cli/app.py +120 -0
- moriarty/cli/async_utils.py +19 -0
- moriarty/cli/dns.py +83 -0
- moriarty/cli/domain_cmd.py +572 -0
- moriarty/cli/email.py +383 -0
- moriarty/cli/email_investigate.py +224 -0
- moriarty/cli/intelligence.py +329 -0
- moriarty/cli/output.py +62 -0
- moriarty/cli/rdap.py +94 -0
- moriarty/cli/state.py +38 -0
- moriarty/cli/tls.py +91 -0
- moriarty/cli/user.py +227 -0
- moriarty/core/cache_backend.py +223 -0
- moriarty/core/config_manager.py +303 -0
- moriarty/correlator/__init__.py +0 -0
- moriarty/data/__init__.py +81 -0
- moriarty/data/ioc/__init__.py +142 -0
- moriarty/data/ioc/matcher.py +254 -0
- moriarty/data/ioc/types.py +267 -0
- moriarty/data/local_intelligence.py +507 -0
- moriarty/data/signature_loaders/__init__.py +103 -0
- moriarty/data/signature_loaders/base.py +54 -0
- moriarty/data/signature_loaders/ioc_feed.py +356 -0
- moriarty/data/signature_loaders/wappalyzer.py +112 -0
- moriarty/dsl/__init__.py +0 -0
- moriarty/dsl/loader.py +99 -0
- moriarty/dsl/schema.py +47 -0
- moriarty/export/__init__.py +0 -0
- moriarty/intelligence/__init__.py +27 -0
- moriarty/intelligence/__main__.py +150 -0
- moriarty/intelligence/config.py +395 -0
- moriarty/intelligence/ioc.py +267 -0
- moriarty/intelligence/signatures.py +550 -0
- moriarty/intelligence/storage.py +501 -0
- moriarty/interop/__init__.py +0 -0
- moriarty/logging/__init__.py +0 -0
- moriarty/logging/config.py +47 -0
- moriarty/models/__init__.py +16 -0
- moriarty/models/assertion.py +24 -0
- moriarty/models/entity.py +22 -0
- moriarty/models/evidence.py +37 -0
- moriarty/models/relation.py +24 -0
- moriarty/models/types.py +28 -0
- moriarty/modules/__init__.py +0 -0
- moriarty/modules/avatar_hash.py +184 -0
- moriarty/modules/directory_fuzzer.py +322 -0
- moriarty/modules/dns_scan.py +40 -0
- moriarty/modules/domain_scanner.py +620 -0
- moriarty/modules/email_check.py +98 -0
- moriarty/modules/email_investigate.py +267 -0
- moriarty/modules/email_security.py +274 -0
- moriarty/modules/googlemaps_lookup.py +106 -0
- moriarty/modules/headless_executor.py +201 -0
- moriarty/modules/orchestrator.py +60 -0
- moriarty/modules/passive_recon.py +444 -0
- moriarty/modules/phone_extractor.py +151 -0
- moriarty/modules/pipeline_orchestrator.py +726 -0
- moriarty/modules/port_scanner.py +129 -0
- moriarty/modules/rdap.py +61 -0
- moriarty/modules/rdap_extended.py +188 -0
- moriarty/modules/stealth_mode.py +610 -0
- moriarty/modules/subdomain_discovery.py +595 -0
- moriarty/modules/technology_profiler.py +361 -0
- moriarty/modules/template_executor.py +239 -0
- moriarty/modules/template_scanner.py +1048 -0
- moriarty/modules/tls_scan.py +46 -0
- moriarty/modules/tls_validator.py +188 -0
- moriarty/modules/vuln_scanner.py +483 -0
- moriarty/modules/waf_detector.py +585 -0
- moriarty/modules/wayback_discovery.py +234 -0
- moriarty/modules/web_crawler.py +163 -0
- moriarty/net/__init__.py +0 -0
- moriarty/net/dns_cache.py +175 -0
- moriarty/net/dns_client.py +188 -0
- moriarty/net/rdap_client.py +52 -0
- moriarty/net/smtp_client.py +114 -0
- moriarty/net/tls_client.py +111 -0
- moriarty/parsers/__init__.py +0 -0
- moriarty/parsers/html_parser.py +136 -0
- moriarty/tests/__init__.py +0 -0
- moriarty/tests/test_email_service.py +17 -0
- moriarty/tests/test_models.py +46 -0
- moriarty/tests/test_orchestrator.py +30 -0
- moriarty/tests/test_tls_client.py +18 -0
- moriarty_project-0.1.6.dist-info/METADATA +388 -0
- moriarty_project-0.1.6.dist-info/RECORD +418 -0
- moriarty_project-0.1.6.dist-info/WHEEL +4 -0
- moriarty_project-0.1.6.dist-info/entry_points.txt +2 -0
@@ -0,0 +1,507 @@
|
|
1
|
+
"""Módulo de inteligência local para coleta e análise de ameaças."""
|
2
|
+
from __future__ import annotations
|
3
|
+
|
4
|
+
import json
|
5
|
+
import logging
|
6
|
+
import sqlite3
|
7
|
+
from pathlib import Path
|
8
|
+
from typing import Dict, List, Optional, Any, Union, Set, Tuple
|
9
|
+
from datetime import datetime, timedelta
|
10
|
+
from dataclasses import asdict, dataclass, field
|
11
|
+
|
12
|
+
from .signature_loaders import (
|
13
|
+
SignatureManager, WappalyzerLoader, IOCFeedLoader,
|
14
|
+
create_loader, get_loader_class
|
15
|
+
)
|
16
|
+
from .ioc import (
|
17
|
+
IOC, IOCType, ThreatType, IOCMatcher,
|
18
|
+
load_iocs_from_file, save_iocs_to_file, merge_iocs
|
19
|
+
)
|
20
|
+
|
21
|
+
# Configuração de logging
|
22
|
+
logging.basicConfig(level=logging.INFO)
|
23
|
+
logger = logging.getLogger(__name__)
|
24
|
+
|
25
|
+
@dataclass
|
26
|
+
class LocalIntelligenceConfig:
|
27
|
+
"""Configuração para o módulo de inteligência local."""
|
28
|
+
# Diretório base para armazenamento de dados
|
29
|
+
data_dir: Path = Path("~/.moriarty/data").expanduser()
|
30
|
+
|
31
|
+
# Configuração do banco de dados
|
32
|
+
db_path: Path = field(init=False)
|
33
|
+
|
34
|
+
# Configuração de atualização
|
35
|
+
update_interval: int = 86400 # segundos (padrão: 24h)
|
36
|
+
|
37
|
+
# Fontes de assinaturas
|
38
|
+
signature_sources: List[Dict[str, Any]] = field(default_factory=lambda: [
|
39
|
+
{
|
40
|
+
'name': 'wappalyzer',
|
41
|
+
'url': 'https://raw.githubusercontent.com/wappalyzer/wappalyzer/master/src/technologies.json',
|
42
|
+
'format': 'wappalyzer',
|
43
|
+
'enabled': True
|
44
|
+
},
|
45
|
+
{
|
46
|
+
'name': 'otx-alienvault',
|
47
|
+
'url': 'https://otx.alienvault.com/otxapi',
|
48
|
+
'format': 'otx',
|
49
|
+
'enabled': True,
|
50
|
+
'api_key': '' # Deve ser configurado pelo usuário
|
51
|
+
},
|
52
|
+
# Adicione mais fontes conforme necessário
|
53
|
+
])
|
54
|
+
|
55
|
+
def __post_init__(self):
|
56
|
+
"""Inicializa os caminhos dos arquivos."""
|
57
|
+
self.data_dir = Path(self.data_dir).resolve()
|
58
|
+
self.data_dir.mkdir(parents=True, exist_ok=True)
|
59
|
+
|
60
|
+
# Caminhos dos bancos de dados
|
61
|
+
self.db_path = self.data_dir / 'intelligence.db'
|
62
|
+
|
63
|
+
# Cria os diretórios necessários
|
64
|
+
(self.data_dir / 'cache').mkdir(exist_ok=True)
|
65
|
+
(self.data_dir / 'signatures').mkdir(exist_ok=True)
|
66
|
+
(self.data_dir / 'iocs').mkdir(exist_ok=True)
|
67
|
+
|
68
|
+
class LocalIntelligence:
|
69
|
+
"""Classe principal para gerenciar inteligência local de ameaças."""
|
70
|
+
|
71
|
+
def __init__(self, config: Optional[LocalIntelligenceConfig] = None):
|
72
|
+
"""Inicializa o gerenciador de inteligência local."""
|
73
|
+
self.config = config or LocalIntelligenceConfig()
|
74
|
+
self.signature_manager = SignatureManager()
|
75
|
+
self.ioc_matcher = IOCMatcher()
|
76
|
+
|
77
|
+
# Inicializa o banco de dados
|
78
|
+
self._init_database()
|
79
|
+
|
80
|
+
# Carrega assinaturas e IOCs existentes
|
81
|
+
self._load_signatures()
|
82
|
+
self._load_iocs()
|
83
|
+
|
84
|
+
def _init_database(self) -> None:
|
85
|
+
"""Inicializa o banco de dados SQLite."""
|
86
|
+
with sqlite3.connect(str(self.config.db_path)) as conn:
|
87
|
+
# Tabela de assinaturas
|
88
|
+
conn.execute("""
|
89
|
+
CREATE TABLE IF NOT EXISTS signatures (
|
90
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
91
|
+
name TEXT NOT NULL,
|
92
|
+
category TEXT NOT NULL,
|
93
|
+
pattern_type TEXT NOT NULL,
|
94
|
+
pattern TEXT NOT NULL,
|
95
|
+
version_detection TEXT,
|
96
|
+
confidence INTEGER DEFAULT 80,
|
97
|
+
source TEXT NOT NULL,
|
98
|
+
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
99
|
+
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
100
|
+
UNIQUE(name, pattern_type, pattern)
|
101
|
+
)
|
102
|
+
""")
|
103
|
+
|
104
|
+
# Tabela de IOCs
|
105
|
+
conn.execute("""
|
106
|
+
CREATE TABLE IF NOT EXISTS iocs (
|
107
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
108
|
+
type TEXT NOT NULL,
|
109
|
+
value TEXT NOT NULL,
|
110
|
+
threat_type TEXT NOT NULL,
|
111
|
+
source TEXT NOT NULL,
|
112
|
+
first_seen TIMESTAMP,
|
113
|
+
last_seen TIMESTAMP,
|
114
|
+
confidence INTEGER DEFAULT 50,
|
115
|
+
tags TEXT, # JSON array
|
116
|
+
metadata TEXT, # JSON object
|
117
|
+
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
118
|
+
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
119
|
+
UNIQUE(type, value, source)
|
120
|
+
)
|
121
|
+
""")
|
122
|
+
|
123
|
+
# Tabela de atualizações
|
124
|
+
conn.execute("""
|
125
|
+
CREATE TABLE IF NOT EXISTS updates (
|
126
|
+
source TEXT PRIMARY KEY,
|
127
|
+
last_updated TIMESTAMP,
|
128
|
+
next_update TIMESTAMP,
|
129
|
+
status TEXT,
|
130
|
+
error TEXT
|
131
|
+
)
|
132
|
+
""")
|
133
|
+
|
134
|
+
# Índices para consultas rápidas
|
135
|
+
conn.execute("CREATE INDEX IF NOT EXISTS idx_signatures_name ON signatures(name)")
|
136
|
+
conn.execute("CREATE INDEX IF NOT EXISTS idx_signatures_category ON signatures(category)")
|
137
|
+
conn.execute("CREATE INDEX IF NOT EXISTS idx_iocs_type ON iocs(type)")
|
138
|
+
conn.execute("CREATE INDEX IF NOT EXISTS idx_iocs_value ON iocs(value)")
|
139
|
+
conn.execute("CREATE INDEX IF NOT EXISTS idx_iocs_threat_type ON iocs(threat_type)")
|
140
|
+
|
141
|
+
conn.commit()
|
142
|
+
|
143
|
+
def _load_signatures(self) -> None:
|
144
|
+
"""Carrega assinaturas do banco de dados."""
|
145
|
+
with sqlite3.connect(str(self.config.db_path)) as conn:
|
146
|
+
conn.row_factory = sqlite3.Row
|
147
|
+
cursor = conn.cursor()
|
148
|
+
|
149
|
+
# Carrega assinaturas de tecnologia
|
150
|
+
cursor.execute("SELECT * FROM signatures")
|
151
|
+
for row in cursor.fetchall():
|
152
|
+
signature = dict(row)
|
153
|
+
self.signature_manager.add_signature(signature)
|
154
|
+
|
155
|
+
logger.info(f"Carregadas {len(self.signature_manager.signatures)} assinaturas")
|
156
|
+
|
157
|
+
def _load_iocs(self) -> None:
|
158
|
+
"""Carrega IOCs do banco de dados."""
|
159
|
+
with sqlite3.connect(str(self.config.db_path)) as conn:
|
160
|
+
conn.row_factory = sqlite3.Row
|
161
|
+
cursor = conn.cursor()
|
162
|
+
|
163
|
+
# Carrega IOCs
|
164
|
+
cursor.execute("SELECT * FROM iocs")
|
165
|
+
for row in cursor.fetchall():
|
166
|
+
ioc_dict = dict(row)
|
167
|
+
|
168
|
+
# Converte campos JSON
|
169
|
+
for field in ('tags', 'metadata'):
|
170
|
+
if ioc_dict[field]:
|
171
|
+
ioc_dict[field] = json.loads(ioc_dict[field])
|
172
|
+
|
173
|
+
try:
|
174
|
+
ioc = IOC.from_dict(ioc_dict)
|
175
|
+
self.ioc_matcher.add_ioc(ioc)
|
176
|
+
except Exception as e:
|
177
|
+
logger.error(f"Erro ao carregar IOC {ioc_dict.get('value')}: {e}")
|
178
|
+
|
179
|
+
logger.info(f"Carregados {sum(len(iocs) for iocs in self.ioc_matcher.iocs.values())} IOCs")
|
180
|
+
|
181
|
+
def update_signatures(self, force: bool = False) -> bool:
|
182
|
+
"""
|
183
|
+
Atualiza as assinaturas a partir das fontes configuradas.
|
184
|
+
|
185
|
+
Args:
|
186
|
+
force: Se True, força a atualização mesmo que não seja necessário
|
187
|
+
|
188
|
+
Returns:
|
189
|
+
True se a atualização foi bem-sucedida, False caso contrário
|
190
|
+
"""
|
191
|
+
updated = False
|
192
|
+
|
193
|
+
for source in self.config.signature_sources:
|
194
|
+
if not source.get('enabled', True):
|
195
|
+
continue
|
196
|
+
|
197
|
+
source_name = source['name']
|
198
|
+
logger.info(f"Atualizando assinaturas de {source_name}...")
|
199
|
+
|
200
|
+
try:
|
201
|
+
# Verifica se é necessário atualizar
|
202
|
+
if not force and not self._needs_update(source_name):
|
203
|
+
logger.info(f"As assinaturas de {source_name} estão atualizadas")
|
204
|
+
continue
|
205
|
+
|
206
|
+
# Cria o carregador apropriado
|
207
|
+
loader = create_loader(
|
208
|
+
source.get('url', ''),
|
209
|
+
source.get('format', 'auto')
|
210
|
+
)
|
211
|
+
|
212
|
+
# Carrega as assinaturas
|
213
|
+
signatures = loader.load()
|
214
|
+
|
215
|
+
# Processa as assinaturas
|
216
|
+
self._process_signatures(signatures, source_name)
|
217
|
+
|
218
|
+
# Atualiza o status
|
219
|
+
self._update_source_status(source_name, success=True)
|
220
|
+
updated = True
|
221
|
+
|
222
|
+
logger.info(f"Assinaturas de {source_name} atualizadas com sucesso")
|
223
|
+
|
224
|
+
except Exception as e:
|
225
|
+
logger.error(f"Erro ao atualizar assinaturas de {source_name}: {e}")
|
226
|
+
self._update_source_status(source_name, success=False, error=str(e))
|
227
|
+
|
228
|
+
return updated
|
229
|
+
|
230
|
+
def _needs_update(self, source_name: str) -> bool:
|
231
|
+
"""Verifica se uma fonte precisa ser atualizada."""
|
232
|
+
with sqlite3.connect(str(self.config.db_path)) as conn:
|
233
|
+
cursor = conn.cursor()
|
234
|
+
cursor.execute(
|
235
|
+
"SELECT next_update FROM updates WHERE source = ?",
|
236
|
+
(source_name,)
|
237
|
+
)
|
238
|
+
row = cursor.fetchone()
|
239
|
+
|
240
|
+
if not row:
|
241
|
+
return True
|
242
|
+
|
243
|
+
next_update = datetime.fromisoformat(row[0])
|
244
|
+
return datetime.utcnow() >= next_update
|
245
|
+
|
246
|
+
def _update_source_status(self, source_name: str, success: bool, error: str = '') -> None:
|
247
|
+
"""Atualiza o status de uma fonte no banco de dados."""
|
248
|
+
now = datetime.utcnow()
|
249
|
+
next_update = now + timedelta(seconds=self.config.update_interval)
|
250
|
+
|
251
|
+
with sqlite3.connect(str(self.config.db_path)) as conn:
|
252
|
+
conn.execute(
|
253
|
+
"""
|
254
|
+
INSERT OR REPLACE INTO updates
|
255
|
+
(source, last_updated, next_update, status, error)
|
256
|
+
VALUES (?, ?, ?, ?, ?)
|
257
|
+
""",
|
258
|
+
(
|
259
|
+
source_name,
|
260
|
+
now.isoformat(),
|
261
|
+
next_update.isoformat(),
|
262
|
+
'success' if success else 'error',
|
263
|
+
error or ''
|
264
|
+
)
|
265
|
+
)
|
266
|
+
conn.commit()
|
267
|
+
|
268
|
+
def _process_signatures(self, signatures: List[Dict[str, Any]], source: str) -> None:
|
269
|
+
"""Processa e armazena as assinaturas carregadas."""
|
270
|
+
with sqlite3.connect(str(self.config.db_path)) as conn:
|
271
|
+
cursor = conn.cursor()
|
272
|
+
|
273
|
+
for sig in signatures:
|
274
|
+
try:
|
275
|
+
# Normaliza a assinatura
|
276
|
+
if 'name' not in sig or 'pattern' not in sig:
|
277
|
+
continue
|
278
|
+
|
279
|
+
# Insere ou atualiza a assinatura
|
280
|
+
cursor.execute(
|
281
|
+
"""
|
282
|
+
INSERT OR REPLACE INTO signatures
|
283
|
+
(name, category, pattern_type, pattern,
|
284
|
+
version_detection, confidence, source, updated_at)
|
285
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP)
|
286
|
+
""",
|
287
|
+
(
|
288
|
+
sig['name'],
|
289
|
+
sig.get('category', 'unknown'),
|
290
|
+
sig.get('pattern_type', 'unknown'),
|
291
|
+
sig['pattern'],
|
292
|
+
sig.get('version_detection'),
|
293
|
+
int(sig.get('confidence', 80)),
|
294
|
+
source
|
295
|
+
)
|
296
|
+
)
|
297
|
+
|
298
|
+
except Exception as e:
|
299
|
+
logger.error(f"Erro ao processar assinatura {sig.get('name')}: {e}")
|
300
|
+
|
301
|
+
conn.commit()
|
302
|
+
|
303
|
+
def add_ioc(self, ioc: Union[IOC, Dict[str, Any]]) -> bool:
|
304
|
+
"""
|
305
|
+
Adiciona um IOC ao banco de dados e ao matcher.
|
306
|
+
|
307
|
+
Args:
|
308
|
+
ioc: O IOC a ser adicionado (pode ser um dicionário ou objeto IOC)
|
309
|
+
|
310
|
+
Returns:
|
311
|
+
True se o IOC foi adicionado com sucesso, False caso contrário
|
312
|
+
"""
|
313
|
+
if isinstance(ioc, dict):
|
314
|
+
try:
|
315
|
+
ioc = IOC.from_dict(ioc)
|
316
|
+
except Exception as e:
|
317
|
+
logger.error(f"Erro ao criar IOC a partir de dicionário: {e}")
|
318
|
+
return False
|
319
|
+
|
320
|
+
if not isinstance(ioc, IOC):
|
321
|
+
logger.error("O parâmetro 'ioc' deve ser um dicionário ou instância de IOC")
|
322
|
+
return False
|
323
|
+
|
324
|
+
try:
|
325
|
+
with sqlite3.connect(str(self.config.db_path)) as conn:
|
326
|
+
# Converte listas/dicionários para JSON
|
327
|
+
tags_json = json.dumps(ioc.tags) if ioc.tags else '[]'
|
328
|
+
metadata_json = json.dumps(ioc.metadata) if ioc.metadata else '{}'
|
329
|
+
|
330
|
+
# Insere ou atualiza o IOC
|
331
|
+
cursor = conn.cursor()
|
332
|
+
cursor.execute(
|
333
|
+
"""
|
334
|
+
INSERT OR REPLACE INTO iocs
|
335
|
+
(type, value, threat_type, source, first_seen, last_seen,
|
336
|
+
confidence, tags, metadata, updated_at)
|
337
|
+
VALUES (?, ?, ?, ?, COALESCE(?, ?), ?, ?, ?, ?, CURRENT_TIMESTAMP)
|
338
|
+
""",
|
339
|
+
(
|
340
|
+
ioc.ioc_type.value,
|
341
|
+
ioc.value,
|
342
|
+
ioc.threat_type.value,
|
343
|
+
ioc.source,
|
344
|
+
ioc.first_seen.isoformat(),
|
345
|
+
ioc.last_seen.isoformat(),
|
346
|
+
ioc.confidence,
|
347
|
+
tags_json,
|
348
|
+
metadata_json,
|
349
|
+
ioc.first_seen.isoformat(),
|
350
|
+
datetime.utcnow().isoformat()
|
351
|
+
)
|
352
|
+
)
|
353
|
+
|
354
|
+
# Atualiza o matcher
|
355
|
+
self.ioc_matcher.add_ioc(ioc)
|
356
|
+
|
357
|
+
return True
|
358
|
+
|
359
|
+
except Exception as e:
|
360
|
+
logger.error(f"Erro ao adicionar IOC {ioc.value}: {e}")
|
361
|
+
return False
|
362
|
+
|
363
|
+
def search_iocs(self, query: str, limit: int = 100) -> List[IOC]:
|
364
|
+
"""
|
365
|
+
Busca IOCs que correspondem à consulta.
|
366
|
+
|
367
|
+
Args:
|
368
|
+
query: Termo de busca
|
369
|
+
limit: Número máximo de resultados a retornar
|
370
|
+
|
371
|
+
Returns:
|
372
|
+
Lista de IOCs correspondentes
|
373
|
+
"""
|
374
|
+
return self.ioc_matcher.search(query, limit)
|
375
|
+
|
376
|
+
def get_ioc(self, ioc_type: Union[str, IOCType], value: str) -> Optional[IOC]:
|
377
|
+
"""
|
378
|
+
Obtém um IOC específico.
|
379
|
+
|
380
|
+
Args:
|
381
|
+
ioc_type: Tipo do IOC
|
382
|
+
value: Valor do IOC
|
383
|
+
|
384
|
+
Returns:
|
385
|
+
O IOC correspondente ou None se não encontrado
|
386
|
+
"""
|
387
|
+
if isinstance(ioc_type, str):
|
388
|
+
ioc_type = IOCType(ioc_type.lower())
|
389
|
+
|
390
|
+
matches = self.ioc_matcher.match(value, ioc_type)
|
391
|
+
return matches[0] if matches else None
|
392
|
+
|
393
|
+
def get_related_iocs(self, ioc: Union[IOC, str, Tuple[str, str]],
|
394
|
+
max_relations: int = 10) -> Dict[str, List[IOC]]:
|
395
|
+
"""
|
396
|
+
Obtém IOCs relacionados ao IOC especificado.
|
397
|
+
|
398
|
+
Args:
|
399
|
+
ioc: O IOC de referência (pode ser um objeto IOC, um valor, ou uma tupla (tipo, valor))
|
400
|
+
max_relations: Número máximo de IOCs relacionados a retornar por tipo
|
401
|
+
|
402
|
+
Returns:
|
403
|
+
Dicionário mapeando tipos de relacionamento para listas de IOCs relacionados
|
404
|
+
"""
|
405
|
+
if not isinstance(ioc, IOC):
|
406
|
+
if isinstance(ioc, str):
|
407
|
+
# Tenta encontrar o IOC pelo valor
|
408
|
+
matches = self.ioc_matcher.match(ioc)
|
409
|
+
if not matches:
|
410
|
+
return {}
|
411
|
+
ioc = matches[0]
|
412
|
+
elif isinstance(ioc, tuple) and len(ioc) == 2:
|
413
|
+
# Tupla (tipo, valor)
|
414
|
+
ioc_type, value = ioc
|
415
|
+
matches = self.ioc_matcher.match(value, ioc_type)
|
416
|
+
if not matches:
|
417
|
+
return {}
|
418
|
+
ioc = matches[0]
|
419
|
+
else:
|
420
|
+
raise ValueError("O parâmetro 'ioc' deve ser um objeto IOC, um valor, ou uma tupla (tipo, valor)")
|
421
|
+
|
422
|
+
return self.ioc_matcher.get_related(ioc, max_relations)
|
423
|
+
|
424
|
+
def export_iocs(self, file_path: Union[str, Path],
|
425
|
+
format_name: str = 'json') -> bool:
|
426
|
+
"""
|
427
|
+
Exporta todos os IOCs para um arquivo.
|
428
|
+
|
429
|
+
Args:
|
430
|
+
file_path: Caminho para o arquivo de saída
|
431
|
+
format_name: Formato de saída ('json', 'yaml', 'csv')
|
432
|
+
|
433
|
+
Returns:
|
434
|
+
True se a exportação foi bem-sucedida, False caso contrário
|
435
|
+
"""
|
436
|
+
try:
|
437
|
+
# Obtém todos os IOCs do banco de dados
|
438
|
+
with sqlite3.connect(str(self.config.db_path)) as conn:
|
439
|
+
conn.row_factory = sqlite3.Row
|
440
|
+
cursor = conn.cursor()
|
441
|
+
cursor.execute("SELECT * FROM iocs")
|
442
|
+
|
443
|
+
iocs = []
|
444
|
+
for row in cursor.fetchall():
|
445
|
+
ioc_dict = dict(row)
|
446
|
+
# Converte campos JSON
|
447
|
+
for field in ('tags', 'metadata'):
|
448
|
+
if ioc_dict[field]:
|
449
|
+
ioc_dict[field] = json.loads(ioc_dict[field])
|
450
|
+
iocs.append(ioc_dict)
|
451
|
+
|
452
|
+
# Salva no formato especificado
|
453
|
+
save_iocs_to_file(iocs, file_path, format_name)
|
454
|
+
return True
|
455
|
+
|
456
|
+
except Exception as e:
|
457
|
+
logger.error(f"Erro ao exportar IOCs: {e}")
|
458
|
+
return False
|
459
|
+
|
460
|
+
def import_iocs(self, file_path: Union[str, Path],
|
461
|
+
format_name: str = 'auto') -> int:
|
462
|
+
"""
|
463
|
+
Importa IOCs de um arquivo.
|
464
|
+
|
465
|
+
Args:
|
466
|
+
file_path: Caminho para o arquivo de entrada
|
467
|
+
format_name: Formato do arquivo ('json', 'yaml', 'csv', 'auto' para detectar)
|
468
|
+
|
469
|
+
Returns:
|
470
|
+
Número de IOCs importados com sucesso
|
471
|
+
"""
|
472
|
+
try:
|
473
|
+
iocs = load_iocs_from_file(file_path, format_name)
|
474
|
+
count = 0
|
475
|
+
|
476
|
+
for ioc in iocs:
|
477
|
+
if self.add_ioc(ioc):
|
478
|
+
count += 1
|
479
|
+
|
480
|
+
logger.info(f"Importados {count} IOCs de {file_path}")
|
481
|
+
return count
|
482
|
+
|
483
|
+
except Exception as e:
|
484
|
+
logger.error(f"Erro ao importar IOCs de {file_path}: {e}")
|
485
|
+
return 0
|
486
|
+
|
487
|
+
# Função de conveniência para criar uma instância
|
488
|
+
def get_local_intelligence(config: Optional[LocalIntelligenceConfig] = None) -> LocalIntelligence:
|
489
|
+
"""
|
490
|
+
Retorna uma instância de LocalIntelligence configurada.
|
491
|
+
|
492
|
+
Args:
|
493
|
+
config: Configuração opcional
|
494
|
+
|
495
|
+
Returns:
|
496
|
+
Instância de LocalIntelligence
|
497
|
+
"""
|
498
|
+
return LocalIntelligence(config)
|
499
|
+
|
500
|
+
__all__ = [
|
501
|
+
'LocalIntelligence',
|
502
|
+
'LocalIntelligenceConfig',
|
503
|
+
'get_local_intelligence',
|
504
|
+
'IOC',
|
505
|
+
'IOCType',
|
506
|
+
'ThreatType'
|
507
|
+
]
|
@@ -0,0 +1,103 @@
|
|
1
|
+
"""Módulo para carregamento de assinaturas de diferentes fontes."""
|
2
|
+
from pathlib import Path
|
3
|
+
from typing import Dict, Type, Any, Optional
|
4
|
+
|
5
|
+
from .base import BaseSignatureLoader, SignatureManager
|
6
|
+
from .wappalyzer import WappalyzerLoader
|
7
|
+
from .ioc_feed import IOCFeedLoader
|
8
|
+
|
9
|
+
# Mapeamento de formatos para classes de carregador
|
10
|
+
LOADER_CLASSES: Dict[str, Type[BaseSignatureLoader]] = {
|
11
|
+
'wappalyzer': WappalyzerLoader,
|
12
|
+
'ioc': IOCFeedLoader,
|
13
|
+
# Adicione mais formatos aqui
|
14
|
+
}
|
15
|
+
|
16
|
+
def get_loader_class(format_name: str) -> Type[BaseSignatureLoader]:
|
17
|
+
"""
|
18
|
+
Obtém a classe de carregador para o formato especificado.
|
19
|
+
|
20
|
+
Args:
|
21
|
+
format_name: Nome do formato (ex: 'wappalyzer', 'ioc')
|
22
|
+
|
23
|
+
Returns:
|
24
|
+
Classe de carregador correspondente
|
25
|
+
|
26
|
+
Raises:
|
27
|
+
ValueError: Se o formato não for suportado
|
28
|
+
"""
|
29
|
+
format_name = format_name.lower()
|
30
|
+
if format_name not in LOADER_CLASSES:
|
31
|
+
raise ValueError(f"Formato de assinatura não suportado: {format_name}")
|
32
|
+
return LOADER_CLASSES[format_name]
|
33
|
+
|
34
|
+
def create_loader(source: Any, format_name: Optional[str] = None) -> BaseSignatureLoader:
|
35
|
+
"""
|
36
|
+
Cria um carregador de assinaturas apropriado para a fonte fornecida.
|
37
|
+
|
38
|
+
Args:
|
39
|
+
source: Fonte das assinaturas (caminho do arquivo, URL, dicionário, etc.)
|
40
|
+
format_name: Nome do formato (opcional, tenta detectar automaticamente)
|
41
|
+
|
42
|
+
Returns:
|
43
|
+
Instância de BaseSignatureLoader apropriada
|
44
|
+
|
45
|
+
Raises:
|
46
|
+
ValueError: Se não for possível determinar o formato
|
47
|
+
"""
|
48
|
+
# Se o formato for especificado, usa-o diretamente
|
49
|
+
if format_name:
|
50
|
+
loader_class = get_loader_class(format_name)
|
51
|
+
return loader_class(source)
|
52
|
+
|
53
|
+
# Tenta detectar o formato com base na fonte
|
54
|
+
if isinstance(source, (str, Path)):
|
55
|
+
source_str = str(source).lower()
|
56
|
+
|
57
|
+
# Verifica se é uma URL
|
58
|
+
if source_str.startswith(('http://', 'https://')):
|
59
|
+
# Tenta determinar o formato pela URL ou cabeçalhos
|
60
|
+
return IOCFeedLoader(source) # Padrão para URLs
|
61
|
+
|
62
|
+
# Verifica a extensão do arquivo
|
63
|
+
if source_str.endswith('.json'):
|
64
|
+
# Tenta determinar o formato pelo conteúdo
|
65
|
+
with open(source, 'r', encoding='utf-8') as f:
|
66
|
+
content = f.read(1024)
|
67
|
+
|
68
|
+
# Verifica se parece ser um arquivo Wappalyzer
|
69
|
+
if '"technologies"' in content:
|
70
|
+
return WappalyzerLoader(source)
|
71
|
+
# Verifica se parece ser um feed de IOCs
|
72
|
+
elif '"iocs"' in content or '"indicators"' in content:
|
73
|
+
return IOCFeedLoader(source)
|
74
|
+
|
75
|
+
elif source_str.endswith(('.yaml', '.yml')):
|
76
|
+
# Para YAML, tenta determinar o formato pelo conteúdo
|
77
|
+
import yaml
|
78
|
+
with open(source, 'r', encoding='utf-8') as f:
|
79
|
+
try:
|
80
|
+
data = yaml.safe_load(f)
|
81
|
+
if isinstance(data, dict):
|
82
|
+
if 'technologies' in data:
|
83
|
+
return WappalyzerLoader(source)
|
84
|
+
elif 'iocs' in data or 'indicators' in data:
|
85
|
+
return IOCFeedLoader(source)
|
86
|
+
except:
|
87
|
+
pass
|
88
|
+
|
89
|
+
# Se chegou aqui, não foi possível detectar o formato
|
90
|
+
raise ValueError(
|
91
|
+
"Não foi possível determinar o formato da fonte. "
|
92
|
+
"Especifique o parâmetro 'format_name'."
|
93
|
+
)
|
94
|
+
|
95
|
+
# Exporta as classes principais
|
96
|
+
__all__ = [
|
97
|
+
'BaseSignatureLoader',
|
98
|
+
'SignatureManager',
|
99
|
+
'WappalyzerLoader',
|
100
|
+
'IOCFeedLoader',
|
101
|
+
'get_loader_class',
|
102
|
+
'create_loader',
|
103
|
+
]
|
@@ -0,0 +1,54 @@
|
|
1
|
+
"""Módulo base para carregadores de assinaturas."""
|
2
|
+
from abc import ABC, abstractmethod
|
3
|
+
from pathlib import Path
|
4
|
+
from typing import Dict, List, Any, Optional, Union
|
5
|
+
|
6
|
+
class BaseSignatureLoader(ABC):
|
7
|
+
"""Classe base para carregadores de assinaturas."""
|
8
|
+
|
9
|
+
def __init__(self, source: Union[str, Path, Dict[str, Any]]):
|
10
|
+
self.source = source
|
11
|
+
self.signatures: List[Dict[str, Any]] = []
|
12
|
+
|
13
|
+
@abstractmethod
|
14
|
+
def load(self) -> List[Dict[str, Any]]:
|
15
|
+
"""Carrega as assinaturas da fonte."""
|
16
|
+
pass
|
17
|
+
|
18
|
+
def normalize(self, signature: Dict[str, Any]) -> Dict[str, Any]:
|
19
|
+
"""Normaliza uma assinatura para o formato interno."""
|
20
|
+
return {
|
21
|
+
"name": signature.get("name"),
|
22
|
+
"category": signature.get("categories", ["unknown"])[0],
|
23
|
+
"pattern_type": signature.get("pattern_type", "unknown"),
|
24
|
+
"pattern": signature.get("pattern"),
|
25
|
+
"version_detection": signature.get("version"),
|
26
|
+
"confidence": int(signature.get("confidence", 80)),
|
27
|
+
"metadata": {
|
28
|
+
k: v for k, v in signature.items()
|
29
|
+
if k not in {"name", "categories", "pattern_type",
|
30
|
+
"pattern", "version", "confidence"
|
31
|
+
}
|
32
|
+
}
|
33
|
+
}
|
34
|
+
|
35
|
+
|
36
|
+
class SignatureManager:
|
37
|
+
"""Gerencia múltiplos carregadores de assinaturas."""
|
38
|
+
|
39
|
+
def __init__(self):
|
40
|
+
self.loaders: Dict[str, BaseSignatureLoader] = {}
|
41
|
+
|
42
|
+
def register_loader(self, name: str, loader: BaseSignatureLoader):
|
43
|
+
"""Registra um novo carregador de assinaturas."""
|
44
|
+
self.loaders[name] = loader
|
45
|
+
|
46
|
+
def load_all(self) -> Dict[str, List[Dict[str, Any]]]:
|
47
|
+
"""Carrega assinaturas de todos os carregadores registrados."""
|
48
|
+
results = {}
|
49
|
+
for name, loader in self.loaders.items():
|
50
|
+
try:
|
51
|
+
results[name] = loader.load()
|
52
|
+
except Exception as e:
|
53
|
+
print(f"Erro ao carregar assinaturas de {name}: {e}")
|
54
|
+
return results
|