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
moriarty/cli/email.py
ADDED
@@ -0,0 +1,383 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
from typing import Any, Dict, Optional
|
4
|
+
|
5
|
+
import typer
|
6
|
+
from rich import box
|
7
|
+
from rich.panel import Panel
|
8
|
+
from rich.table import Table
|
9
|
+
|
10
|
+
from .async_utils import run_async
|
11
|
+
from .output import console, emit_json, emit_yaml, ensure_state
|
12
|
+
from .state import GlobalOptions
|
13
|
+
from ..modules.email_check import EmailCheckOptions, EmailCheckResult, EmailCheckService
|
14
|
+
from ..modules.email_investigate import EmailInvestigator, EmailInvestigationResult
|
15
|
+
|
16
|
+
app = typer.Typer(add_completion=False, help="Email reconnaissance primitives.")
|
17
|
+
|
18
|
+
|
19
|
+
@app.command("check")
|
20
|
+
def check( # noqa: PLR0913 - CLI interface requires multiple parameters
|
21
|
+
ctx: typer.Context,
|
22
|
+
email: str = typer.Option(..., "--email", "-e", help="Target email address."),
|
23
|
+
dns: bool = typer.Option(True, "--dns/--no-dns", help="Run DNS lookups (MX/SPF/DMARC)."),
|
24
|
+
smtp: bool = typer.Option(False, "--smtp/--no-smtp", help="Attempt SMTP RCPT TO verification."),
|
25
|
+
from_address: str = typer.Option("postmaster@localhost", "--from", help="Envelope MAIL FROM address."),
|
26
|
+
retries: int = typer.Option(1, min=0, help="SMTP retry attempts after the first try."),
|
27
|
+
wait: float = typer.Option(1.0, min=0.0, help="Seconds to wait between SMTP retries."),
|
28
|
+
json_output: Optional[str] = typer.Option(None, "--json", help="Write JSON output to path or '-' for stdout."),
|
29
|
+
) -> None:
|
30
|
+
"""Validate an email address using DNS and SMTP heuristics."""
|
31
|
+
state = ensure_state(ctx)
|
32
|
+
|
33
|
+
options = EmailCheckOptions(
|
34
|
+
check_dns=dns,
|
35
|
+
check_smtp=smtp,
|
36
|
+
from_address=from_address,
|
37
|
+
retries=retries,
|
38
|
+
wait=wait,
|
39
|
+
)
|
40
|
+
|
41
|
+
service = EmailCheckService(email=email, options=options, timeout=state.options.timeout)
|
42
|
+
|
43
|
+
try:
|
44
|
+
result = run_async(service.run())
|
45
|
+
except ValueError as exc:
|
46
|
+
raise typer.BadParameter(str(exc)) from exc
|
47
|
+
|
48
|
+
if state.options.professional_mode:
|
49
|
+
_render_professional_banner(state.options)
|
50
|
+
|
51
|
+
output_format = ("json" if json_output else state.options.format).lower()
|
52
|
+
|
53
|
+
if output_format == "json":
|
54
|
+
payload = _result_to_dict(result)
|
55
|
+
emit_json(payload, json_output, state.options.output)
|
56
|
+
elif output_format == "yaml":
|
57
|
+
payload = _result_to_dict(result)
|
58
|
+
emit_yaml(payload, json_output, state.options.output)
|
59
|
+
else:
|
60
|
+
_render_table(result, state.options)
|
61
|
+
|
62
|
+
for warning in result.warnings:
|
63
|
+
console.print(f"[warning]⚠️ {warning}")
|
64
|
+
|
65
|
+
|
66
|
+
def _render_professional_banner(options: GlobalOptions) -> None:
|
67
|
+
notice = (
|
68
|
+
"⚠️ Professional Mode\n"
|
69
|
+
"Consent required. Ensure investigative actions comply with policy."
|
70
|
+
)
|
71
|
+
console.print(
|
72
|
+
Panel(
|
73
|
+
notice,
|
74
|
+
title="MORIARTY",
|
75
|
+
border_style="yellow",
|
76
|
+
)
|
77
|
+
)
|
78
|
+
|
79
|
+
|
80
|
+
def _render_table(result: EmailCheckResult, options: GlobalOptions) -> None:
|
81
|
+
table = Table(title=f"Email Check · {result.normalized_email}", box=box.SIMPLE_HEAVY)
|
82
|
+
table.add_column("Attribute", style="cyan", no_wrap=True)
|
83
|
+
table.add_column("Value", style="white")
|
84
|
+
|
85
|
+
table.add_row("Input", result.input_email)
|
86
|
+
table.add_row("Normalized", result.normalized_email)
|
87
|
+
table.add_row("Local Part", result.local_part)
|
88
|
+
table.add_row("Domain", result.domain)
|
89
|
+
|
90
|
+
if result.dns:
|
91
|
+
mx_summary = ", ".join(f"{mx.exchange} (prio {mx.priority})" for mx in result.dns.mx) or "—"
|
92
|
+
spf_summary = "; ".join(result.dns.spf) or "—"
|
93
|
+
dmarc_summary = "; ".join(result.dns.dmarc) or "—"
|
94
|
+
table.add_row("A", ", ".join(result.dns.a) or "—")
|
95
|
+
table.add_row("AAAA", ", ".join(result.dns.aaaa) or "—")
|
96
|
+
table.add_row("MX", mx_summary)
|
97
|
+
table.add_row("SPF", spf_summary)
|
98
|
+
table.add_row("DMARC", dmarc_summary)
|
99
|
+
|
100
|
+
if result.smtp:
|
101
|
+
status = "deliverable" if result.smtp.deliverable else "undeliverable"
|
102
|
+
attempt_lines = []
|
103
|
+
for attempt in result.smtp.attempts:
|
104
|
+
if attempt.result_code is not None:
|
105
|
+
message = attempt.result_message or ""
|
106
|
+
attempt_lines.append(f"{attempt.host}: {attempt.result_code} {message}".strip())
|
107
|
+
elif attempt.error:
|
108
|
+
attempt_lines.append(f"{attempt.host}: error {attempt.error}")
|
109
|
+
table.add_row("SMTP", f"{status}\n" + "\n".join(attempt_lines) if attempt_lines else status)
|
110
|
+
|
111
|
+
console.print(table)
|
112
|
+
|
113
|
+
|
114
|
+
def _result_to_dict(result: EmailCheckResult) -> Dict[str, Any]:
|
115
|
+
return {
|
116
|
+
"input_email": result.input_email,
|
117
|
+
"normalized_email": result.normalized_email,
|
118
|
+
"local_part": result.local_part,
|
119
|
+
"domain": result.domain,
|
120
|
+
"dns": _dns_to_dict(result.dns) if result.dns else None,
|
121
|
+
"smtp": _smtp_to_dict(result.smtp) if result.smtp else None,
|
122
|
+
"warnings": result.warnings,
|
123
|
+
}
|
124
|
+
|
125
|
+
|
126
|
+
def _dns_to_dict(dns_result: Optional[Any]) -> Optional[Dict[str, Any]]:
|
127
|
+
if dns_result is None:
|
128
|
+
return None
|
129
|
+
return {
|
130
|
+
"a": dns_result.a,
|
131
|
+
"aaaa": dns_result.aaaa,
|
132
|
+
"mx": [
|
133
|
+
{
|
134
|
+
"priority": record.priority,
|
135
|
+
"exchange": record.exchange,
|
136
|
+
}
|
137
|
+
for record in dns_result.mx
|
138
|
+
],
|
139
|
+
"spf": dns_result.spf,
|
140
|
+
"dmarc": dns_result.dmarc,
|
141
|
+
"txt": [record.text for record in dns_result.txt],
|
142
|
+
}
|
143
|
+
|
144
|
+
|
145
|
+
def _smtp_to_dict(smtp_result: Optional[Any]) -> Optional[Dict[str, Any]]:
|
146
|
+
if smtp_result is None:
|
147
|
+
return None
|
148
|
+
return {
|
149
|
+
"deliverable": smtp_result.deliverable,
|
150
|
+
"attempts": [
|
151
|
+
{
|
152
|
+
"host": attempt.host,
|
153
|
+
"port": attempt.port,
|
154
|
+
"code": attempt.result_code,
|
155
|
+
"message": attempt.result_message,
|
156
|
+
"success": attempt.success,
|
157
|
+
"error": attempt.error,
|
158
|
+
}
|
159
|
+
for attempt in smtp_result.attempts
|
160
|
+
],
|
161
|
+
}
|
162
|
+
|
163
|
+
|
164
|
+
@app.command("investigate")
|
165
|
+
def investigate(
|
166
|
+
ctx: typer.Context,
|
167
|
+
email: str = typer.Option(..., "--email", "-e", help="Email a investigar."),
|
168
|
+
json_output: Optional[str] = typer.Option(None, "--json", help="Escreve saída JSON no caminho ou '-'"),
|
169
|
+
include_breaches: bool = typer.Option(True, "--breaches/--no-breaches", help="Verificar data breaches."),
|
170
|
+
) -> None:
|
171
|
+
"""Investiga email em múltiplas fontes (Gravatar, social, breaches)."""
|
172
|
+
import logging
|
173
|
+
from rich.tree import Tree
|
174
|
+
|
175
|
+
state = ensure_state(ctx)
|
176
|
+
|
177
|
+
# Suprime logs INFO/WARNING de bibliotecas externas - apenas durante investigate
|
178
|
+
if not state.options.verbose:
|
179
|
+
logging.getLogger("httpx").setLevel(logging.ERROR)
|
180
|
+
logging.getLogger("httpcore").setLevel(logging.ERROR)
|
181
|
+
logging.getLogger("moriarty.modules.email_investigate").setLevel(logging.ERROR)
|
182
|
+
logging.getLogger("moriarty.modules.template_executor").setLevel(logging.ERROR)
|
183
|
+
|
184
|
+
if state.options.professional_mode:
|
185
|
+
notice = (
|
186
|
+
"⚠️ Investigação Profunda\n\n"
|
187
|
+
"Esta ferramenta consulta fontes públicas. Respeite a privacidade e "
|
188
|
+
"use apenas para fins legítimos de segurança e investigação autorizada."
|
189
|
+
)
|
190
|
+
console.print(
|
191
|
+
Panel(
|
192
|
+
notice,
|
193
|
+
title="MORIARTY · Professional Mode",
|
194
|
+
border_style="yellow",
|
195
|
+
padding=(1, 2),
|
196
|
+
)
|
197
|
+
)
|
198
|
+
console.print()
|
199
|
+
|
200
|
+
console.print(f"[info]🔎 Investigando: {email}")
|
201
|
+
console.print()
|
202
|
+
|
203
|
+
with console.status("[cyan]Buscando em múltiplas fontes...", spinner="dots"):
|
204
|
+
investigator = EmailInvestigator(timeout=state.options.timeout)
|
205
|
+
result = run_async(investigator.investigate(email))
|
206
|
+
|
207
|
+
# Saída
|
208
|
+
output_format = ("json" if json_output else state.options.format).lower()
|
209
|
+
|
210
|
+
if output_format == "json":
|
211
|
+
payload = _investigation_to_dict(result)
|
212
|
+
emit_json(payload, json_output, state.options.output)
|
213
|
+
elif output_format == "yaml":
|
214
|
+
payload = _investigation_to_dict(result)
|
215
|
+
emit_yaml(payload, json_output, state.options.output)
|
216
|
+
else:
|
217
|
+
_render_investigation(result, state.options.redact)
|
218
|
+
|
219
|
+
if not include_breaches:
|
220
|
+
console.print("\n[dim]Verificação de breaches desabilitada (use --breaches para habilitar)")
|
221
|
+
|
222
|
+
|
223
|
+
def _render_investigation(result: EmailInvestigationResult, redact: bool) -> None:
|
224
|
+
"""Renderiza resultado da investigação."""
|
225
|
+
from rich.tree import Tree
|
226
|
+
|
227
|
+
# Painel principal
|
228
|
+
email_display = _redact_email(result.email) if redact else result.email
|
229
|
+
|
230
|
+
tree = Tree(f"[bold cyan]📧 {email_display}[/bold cyan]")
|
231
|
+
|
232
|
+
# Informações básicas
|
233
|
+
basic_node = tree.add("[bold]Informações Básicas[/bold]")
|
234
|
+
basic_node.add(f"Local Part: {result.local_part}")
|
235
|
+
basic_node.add(f"Domínio: {result.domain}")
|
236
|
+
basic_node.add(f"Normalizado: {result.normalized_email}")
|
237
|
+
|
238
|
+
# Gravatar
|
239
|
+
gravatar_node = tree.add("[bold]Gravatar[/bold]")
|
240
|
+
if result.gravatar_profile:
|
241
|
+
gravatar_node.add("✓ Perfil encontrado")
|
242
|
+
gravatar_node.add(f"Hash: {result.gravatar_hash[:16]}...")
|
243
|
+
if result.gravatar_avatar:
|
244
|
+
gravatar_node.add(f"Avatar: {result.gravatar_avatar}")
|
245
|
+
|
246
|
+
# Dados do perfil
|
247
|
+
profile = result.gravatar_profile
|
248
|
+
if profile.get("displayName"):
|
249
|
+
gravatar_node.add(f"Nome: {profile['displayName']}")
|
250
|
+
if profile.get("profileUrl"):
|
251
|
+
gravatar_node.add(f"URL: {profile['profileUrl']}")
|
252
|
+
else:
|
253
|
+
gravatar_node.add("[dim]✗ Nenhum perfil Gravatar encontrado[/dim]")
|
254
|
+
|
255
|
+
# Perfis sociais
|
256
|
+
social_node = tree.add(f"[bold]Perfis Sociais ({len(result.social_profiles)})[/bold]")
|
257
|
+
if result.social_profiles:
|
258
|
+
for profile in result.social_profiles:
|
259
|
+
platform_node = social_node.add(f"[green]✓[/green] [cyan]{profile.platform.title()}[/cyan]")
|
260
|
+
platform_node.add(f"🔗 {profile.url}")
|
261
|
+
if profile.display_name:
|
262
|
+
platform_node.add(f"👤 {profile.display_name}")
|
263
|
+
if profile.bio:
|
264
|
+
bio_preview = profile.bio[:80] + "..." if len(profile.bio) > 80 else profile.bio
|
265
|
+
platform_node.add(f"📝 {bio_preview}")
|
266
|
+
if profile.metadata.get("location"):
|
267
|
+
platform_node.add(f"📍 {profile.metadata['location']}")
|
268
|
+
if profile.metadata.get("website"):
|
269
|
+
platform_node.add(f"🌐 {profile.metadata['website']}")
|
270
|
+
platform_node.add(f"💯 Confidence: {profile.confidence:.0%}")
|
271
|
+
else:
|
272
|
+
social_node.add("[dim]✗ Nenhum perfil encontrado com o username '{local_part}'[/dim]".format(local_part=result.local_part))
|
273
|
+
|
274
|
+
# Usernames extraídos
|
275
|
+
if result.usernames:
|
276
|
+
usernames_node = tree.add(f"[bold]Usernames Encontrados ({len(result.usernames)})[/bold]")
|
277
|
+
for username in result.usernames:
|
278
|
+
usernames_node.add(f"• {username}")
|
279
|
+
|
280
|
+
# Websites
|
281
|
+
if result.websites:
|
282
|
+
websites_node = tree.add(f"[bold]Websites Vinculados ({len(result.websites)})[/bold]")
|
283
|
+
for website in result.websites:
|
284
|
+
websites_node.add(f"🔗 {website}")
|
285
|
+
|
286
|
+
# Data Breaches
|
287
|
+
breach_node = tree.add("[bold]Data Breaches[/bold]")
|
288
|
+
if result.breached:
|
289
|
+
breach_node.add(f"[red]⚠️ Email encontrado em {result.breach_count} breach(es)[/red]")
|
290
|
+
for breach in result.breaches:
|
291
|
+
breach_node.add(f"• {breach.get('source', 'Unknown')}: {breach.get('occurrences', 0)} ocorrências")
|
292
|
+
else:
|
293
|
+
breach_node.add("[green]✓ Nenhum breach conhecido[/green]")
|
294
|
+
|
295
|
+
console.print(tree)
|
296
|
+
console.print()
|
297
|
+
|
298
|
+
# Estatísticas
|
299
|
+
stats_table = Table(title="Resumo da Investigação", box=box.SIMPLE)
|
300
|
+
stats_table.add_column("Métrica", style="cyan")
|
301
|
+
stats_table.add_column("Valor", style="white")
|
302
|
+
|
303
|
+
stats_table.add_row("Email", email_display)
|
304
|
+
stats_table.add_row("Plataformas encontradas", str(result.total_platforms_found))
|
305
|
+
stats_table.add_row("Usernames únicos", str(len(result.usernames)))
|
306
|
+
stats_table.add_row("Websites vinculados", str(len(result.websites)))
|
307
|
+
stats_table.add_row("Gravatar", "✓ Sim" if result.gravatar_profile else "✗ Não")
|
308
|
+
stats_table.add_row("Breaches", f"{'✗ Sim (' + str(result.breach_count) + ')' if result.breached else '✓ Não'}")
|
309
|
+
stats_table.add_row("Timestamp", result.search_timestamp)
|
310
|
+
|
311
|
+
console.print(stats_table)
|
312
|
+
|
313
|
+
# Recomendações
|
314
|
+
if result.breached:
|
315
|
+
console.print()
|
316
|
+
console.print(
|
317
|
+
Panel(
|
318
|
+
"[red]⚠️ Este email foi encontrado em data breaches.\n"
|
319
|
+
"Recomendações:\n"
|
320
|
+
"• Alterar senhas imediatamente\n"
|
321
|
+
"• Habilitar autenticação de dois fatores\n"
|
322
|
+
"• Verificar atividades suspeitas nas contas[/red]",
|
323
|
+
title="Alerta de Segurança",
|
324
|
+
border_style="red",
|
325
|
+
)
|
326
|
+
)
|
327
|
+
|
328
|
+
|
329
|
+
def _redact_email(email: str) -> str:
|
330
|
+
"""Redige email para exibição."""
|
331
|
+
local, domain = email.split("@", 1)
|
332
|
+
if len(local) <= 2:
|
333
|
+
redacted_local = local[0] + "*"
|
334
|
+
else:
|
335
|
+
redacted_local = local[0] + "*" * (len(local) - 2) + local[-1]
|
336
|
+
return f"{redacted_local}@{domain}"
|
337
|
+
|
338
|
+
|
339
|
+
def _investigation_to_dict(result: EmailInvestigationResult) -> Dict[str, Any]:
|
340
|
+
"""Converte resultado para dict."""
|
341
|
+
return {
|
342
|
+
"email": result.email,
|
343
|
+
"normalized_email": result.normalized_email,
|
344
|
+
"domain": result.domain,
|
345
|
+
"local_part": result.local_part,
|
346
|
+
"gravatar": {
|
347
|
+
"hash": result.gravatar_hash,
|
348
|
+
"profile": result.gravatar_profile,
|
349
|
+
"avatar_url": result.gravatar_avatar,
|
350
|
+
},
|
351
|
+
"social_profiles": [
|
352
|
+
{
|
353
|
+
"platform": p.platform,
|
354
|
+
"url": p.url,
|
355
|
+
"username": p.username,
|
356
|
+
"user_id": p.user_id,
|
357
|
+
"display_name": p.display_name,
|
358
|
+
"avatar_url": p.avatar_url,
|
359
|
+
"bio": p.bio,
|
360
|
+
"verified": p.verified,
|
361
|
+
"confidence": p.confidence,
|
362
|
+
"metadata": p.metadata,
|
363
|
+
}
|
364
|
+
for p in result.social_profiles
|
365
|
+
],
|
366
|
+
"breaches": {
|
367
|
+
"breached": result.breached,
|
368
|
+
"count": result.breach_count,
|
369
|
+
"details": result.breaches,
|
370
|
+
},
|
371
|
+
"extracted_data": {
|
372
|
+
"usernames": result.usernames,
|
373
|
+
"websites": result.websites,
|
374
|
+
"phone_numbers": result.phone_numbers,
|
375
|
+
},
|
376
|
+
"metadata": {
|
377
|
+
"total_platforms_found": result.total_platforms_found,
|
378
|
+
"search_timestamp": result.search_timestamp,
|
379
|
+
},
|
380
|
+
}
|
381
|
+
|
382
|
+
|
383
|
+
__all__ = ["app"]
|
@@ -0,0 +1,224 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
from typing import Any, Dict, List, Optional
|
4
|
+
|
5
|
+
import typer
|
6
|
+
from rich import box
|
7
|
+
from rich.panel import Panel
|
8
|
+
from rich.table import Table
|
9
|
+
from rich.tree import Tree
|
10
|
+
|
11
|
+
from .async_utils import run_async
|
12
|
+
from .output import console, emit_json, emit_yaml, ensure_state
|
13
|
+
from ..modules.email_investigate import EmailInvestigator, SocialProfile
|
14
|
+
|
15
|
+
app = typer.Typer(add_completion=False, help="Investigação profunda de emails.")
|
16
|
+
|
17
|
+
|
18
|
+
@app.command("investigate")
|
19
|
+
def investigate(
|
20
|
+
ctx: typer.Context,
|
21
|
+
email: str = typer.Option(..., "--email", "-e", help="Email a investigar."),
|
22
|
+
json_output: Optional[str] = typer.Option(None, "--json", help="Escreve saída JSON no caminho ou '-'"),
|
23
|
+
include_breaches: bool = typer.Option(True, "--breaches/--no-breaches", help="Verificar data breaches."),
|
24
|
+
) -> None:
|
25
|
+
"""Investiga email em múltiplas fontes (Gravatar, social, breaches)."""
|
26
|
+
state = ensure_state(ctx)
|
27
|
+
|
28
|
+
if state.options.professional_mode:
|
29
|
+
_render_professional_banner()
|
30
|
+
|
31
|
+
console.print(f"[info]🔎 Investigando: {email}")
|
32
|
+
console.print()
|
33
|
+
|
34
|
+
investigator = EmailInvestigator(timeout=state.options.timeout)
|
35
|
+
result = run_async(investigator.investigate(email))
|
36
|
+
|
37
|
+
# Saída
|
38
|
+
output_format = ("json" if json_output else state.options.format).lower()
|
39
|
+
|
40
|
+
if output_format == "json":
|
41
|
+
payload = _result_to_dict(result)
|
42
|
+
emit_json(payload, json_output, state.options.output)
|
43
|
+
elif output_format == "yaml":
|
44
|
+
payload = _result_to_dict(result)
|
45
|
+
emit_yaml(payload, json_output, state.options.output)
|
46
|
+
else:
|
47
|
+
_render_investigation(result, state.options.redact)
|
48
|
+
|
49
|
+
if not include_breaches:
|
50
|
+
console.print("\n[dim]Verificação de breaches desabilitada (use --breaches para habilitar)")
|
51
|
+
|
52
|
+
|
53
|
+
def _render_professional_banner() -> None:
|
54
|
+
notice = (
|
55
|
+
"⚠️ Investigação Profunda\n\n"
|
56
|
+
"Esta ferramenta consulta fontes públicas. Respeite a privacidade e "
|
57
|
+
"use apenas para fins legítimos de segurança e investigação autorizada."
|
58
|
+
)
|
59
|
+
console.print(
|
60
|
+
Panel(
|
61
|
+
notice,
|
62
|
+
title="MORIARTY · Professional Mode",
|
63
|
+
border_style="yellow",
|
64
|
+
padding=(1, 2),
|
65
|
+
)
|
66
|
+
)
|
67
|
+
console.print()
|
68
|
+
|
69
|
+
|
70
|
+
def _render_investigation(result: Any, redact: bool) -> None:
|
71
|
+
"""Renderiza resultado da investigação."""
|
72
|
+
|
73
|
+
# Painel principal
|
74
|
+
email_display = _redact_email(result.email) if redact else result.email
|
75
|
+
|
76
|
+
tree = Tree(f"[bold cyan]📧 {email_display}[/bold cyan]")
|
77
|
+
|
78
|
+
# Informações básicas
|
79
|
+
basic_node = tree.add("[bold]Informações Básicas[/bold]")
|
80
|
+
basic_node.add(f"Local Part: {result.local_part}")
|
81
|
+
basic_node.add(f"Domínio: {result.domain}")
|
82
|
+
basic_node.add(f"Normalizado: {result.normalized_email}")
|
83
|
+
|
84
|
+
# Gravatar
|
85
|
+
gravatar_node = tree.add("[bold]Gravatar[/bold]")
|
86
|
+
if result.gravatar_profile:
|
87
|
+
gravatar_node.add(f"✓ Perfil encontrado")
|
88
|
+
gravatar_node.add(f"Hash: {result.gravatar_hash[:16]}...")
|
89
|
+
if result.gravatar_avatar:
|
90
|
+
gravatar_node.add(f"Avatar: {result.gravatar_avatar}")
|
91
|
+
|
92
|
+
# Dados do perfil
|
93
|
+
profile = result.gravatar_profile
|
94
|
+
if profile.get("displayName"):
|
95
|
+
gravatar_node.add(f"Nome: {profile['displayName']}")
|
96
|
+
if profile.get("profileUrl"):
|
97
|
+
gravatar_node.add(f"URL: {profile['profileUrl']}")
|
98
|
+
else:
|
99
|
+
gravatar_node.add("[dim]✗ Nenhum perfil Gravatar encontrado[/dim]")
|
100
|
+
|
101
|
+
# Perfis sociais
|
102
|
+
social_node = tree.add(f"[bold]Perfis Sociais ({len(result.social_profiles)})[/bold]")
|
103
|
+
if result.social_profiles:
|
104
|
+
for profile in result.social_profiles:
|
105
|
+
platform_node = social_node.add(f"[cyan]{profile.platform}[/cyan]")
|
106
|
+
platform_node.add(f"URL: {profile.url}")
|
107
|
+
if profile.username:
|
108
|
+
platform_node.add(f"Username: {profile.username}")
|
109
|
+
if profile.display_name:
|
110
|
+
platform_node.add(f"Nome: {profile.display_name}")
|
111
|
+
platform_node.add(f"Confidence: {profile.confidence:.2f}")
|
112
|
+
else:
|
113
|
+
social_node.add("[dim]Nenhum perfil encontrado (use local_part como username)[/dim]")
|
114
|
+
|
115
|
+
# Usernames extraídos
|
116
|
+
if result.usernames:
|
117
|
+
usernames_node = tree.add(f"[bold]Usernames Encontrados ({len(result.usernames)})[/bold]")
|
118
|
+
for username in result.usernames:
|
119
|
+
usernames_node.add(f"• {username}")
|
120
|
+
|
121
|
+
# Websites
|
122
|
+
if result.websites:
|
123
|
+
websites_node = tree.add(f"[bold]Websites Vinculados ({len(result.websites)})[/bold]")
|
124
|
+
for website in result.websites:
|
125
|
+
websites_node.add(f"🔗 {website}")
|
126
|
+
|
127
|
+
# Data Breaches
|
128
|
+
breach_node = tree.add("[bold]Data Breaches[/bold]")
|
129
|
+
if result.breached:
|
130
|
+
breach_node.add(f"[red]⚠️ Email encontrado em {result.breach_count} breach(es)[/red]")
|
131
|
+
for breach in result.breaches:
|
132
|
+
breach_node.add(f"• {breach.get('source', 'Unknown')}: {breach.get('occurrences', 0)} ocorrências")
|
133
|
+
else:
|
134
|
+
breach_node.add("[green]✓ Nenhum breach conhecido[/green]")
|
135
|
+
|
136
|
+
console.print(tree)
|
137
|
+
console.print()
|
138
|
+
|
139
|
+
# Estatísticas
|
140
|
+
stats_table = Table(title="Resumo da Investigação", box=box.SIMPLE)
|
141
|
+
stats_table.add_column("Métrica", style="cyan")
|
142
|
+
stats_table.add_column("Valor", style="white")
|
143
|
+
|
144
|
+
stats_table.add_row("Email", email_display)
|
145
|
+
stats_table.add_row("Plataformas encontradas", str(result.total_platforms_found))
|
146
|
+
stats_table.add_row("Usernames únicos", str(len(result.usernames)))
|
147
|
+
stats_table.add_row("Websites vinculados", str(len(result.websites)))
|
148
|
+
stats_table.add_row("Gravatar", "✓ Sim" if result.gravatar_profile else "✗ Não")
|
149
|
+
stats_table.add_row("Breaches", f"{'✗ Sim (' + str(result.breach_count) + ')' if result.breached else '✓ Não'}")
|
150
|
+
stats_table.add_row("Timestamp", result.search_timestamp)
|
151
|
+
|
152
|
+
console.print(stats_table)
|
153
|
+
|
154
|
+
# Recomendações
|
155
|
+
if result.breached:
|
156
|
+
console.print()
|
157
|
+
console.print(
|
158
|
+
Panel(
|
159
|
+
"[red]⚠️ Este email foi encontrado em data breaches.\n"
|
160
|
+
"Recomendações:\n"
|
161
|
+
"• Alterar senhas imediatamente\n"
|
162
|
+
"• Habilitar autenticação de dois fatores\n"
|
163
|
+
"• Verificar atividades suspeitas nas contas[/red]",
|
164
|
+
title="Alerta de Segurança",
|
165
|
+
border_style="red",
|
166
|
+
)
|
167
|
+
)
|
168
|
+
|
169
|
+
|
170
|
+
def _redact_email(email: str) -> str:
|
171
|
+
"""Redige email para exibição."""
|
172
|
+
local, domain = email.split("@", 1)
|
173
|
+
if len(local) <= 2:
|
174
|
+
redacted_local = local[0] + "*"
|
175
|
+
else:
|
176
|
+
redacted_local = local[0] + "*" * (len(local) - 2) + local[-1]
|
177
|
+
return f"{redacted_local}@{domain}"
|
178
|
+
|
179
|
+
|
180
|
+
def _result_to_dict(result: Any) -> Dict[str, Any]:
|
181
|
+
"""Converte resultado para dict."""
|
182
|
+
return {
|
183
|
+
"email": result.email,
|
184
|
+
"normalized_email": result.normalized_email,
|
185
|
+
"domain": result.domain,
|
186
|
+
"local_part": result.local_part,
|
187
|
+
"gravatar": {
|
188
|
+
"hash": result.gravatar_hash,
|
189
|
+
"profile": result.gravatar_profile,
|
190
|
+
"avatar_url": result.gravatar_avatar,
|
191
|
+
},
|
192
|
+
"social_profiles": [
|
193
|
+
{
|
194
|
+
"platform": p.platform,
|
195
|
+
"url": p.url,
|
196
|
+
"username": p.username,
|
197
|
+
"user_id": p.user_id,
|
198
|
+
"display_name": p.display_name,
|
199
|
+
"avatar_url": p.avatar_url,
|
200
|
+
"bio": p.bio,
|
201
|
+
"verified": p.verified,
|
202
|
+
"confidence": p.confidence,
|
203
|
+
"metadata": p.metadata,
|
204
|
+
}
|
205
|
+
for p in result.social_profiles
|
206
|
+
],
|
207
|
+
"breaches": {
|
208
|
+
"breached": result.breached,
|
209
|
+
"count": result.breach_count,
|
210
|
+
"details": result.breaches,
|
211
|
+
},
|
212
|
+
"extracted_data": {
|
213
|
+
"usernames": result.usernames,
|
214
|
+
"websites": result.websites,
|
215
|
+
"phone_numbers": result.phone_numbers,
|
216
|
+
},
|
217
|
+
"metadata": {
|
218
|
+
"total_platforms_found": result.total_platforms_found,
|
219
|
+
"search_timestamp": result.search_timestamp,
|
220
|
+
},
|
221
|
+
}
|
222
|
+
|
223
|
+
|
224
|
+
__all__ = ["app"]
|