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,329 @@
|
|
1
|
+
"""Comandos para gerenciamento de inteligência local."""
|
2
|
+
from pathlib import Path
|
3
|
+
from typing import List, Optional, Dict, Any
|
4
|
+
|
5
|
+
import typer
|
6
|
+
from rich.console import Console
|
7
|
+
from rich.table import Table
|
8
|
+
from rich.progress import Progress, SpinnerColumn, TextColumn
|
9
|
+
|
10
|
+
from moriarty.data import (
|
11
|
+
get_local_intelligence,
|
12
|
+
IOC, IOCType, ThreatType,
|
13
|
+
load_iocs_from_file, save_iocs_to_file
|
14
|
+
)
|
15
|
+
|
16
|
+
app = typer.Typer(name="intel", help="🔍 Gerenciamento de inteligência local")
|
17
|
+
console = Console()
|
18
|
+
|
19
|
+
# Tipos de IOC suportados para autocompletar
|
20
|
+
IOC_TYPES = [t.value for t in IOCType]
|
21
|
+
THREAT_TYPES = [t.value for t in ThreatType]
|
22
|
+
|
23
|
+
# Configuração
|
24
|
+
DEFAULT_DATA_DIR = Path("~/.moriarty/data").expanduser()
|
25
|
+
|
26
|
+
def _get_intel():
|
27
|
+
"""Retorna uma instância de LocalIntelligence."""
|
28
|
+
return get_local_intelligence()
|
29
|
+
|
30
|
+
@app.command("add")
|
31
|
+
def add_ioc(
|
32
|
+
value: str = typer.Argument(..., help="Valor do IOC"),
|
33
|
+
ioc_type: str = typer.Argument(..., help=f"Tipo do IOC: {', '.join(IOC_TYPES)}",
|
34
|
+
autocompletion=lambda: IOC_TYPES),
|
35
|
+
threat_type: str = typer.Option("unknown", "--threat", "-t",
|
36
|
+
help=f"Tipo de ameaça: {', '.join(THREAT_TYPES)}",
|
37
|
+
autocompletion=lambda: THREAT_TYPES),
|
38
|
+
source: str = typer.Option("manual", "--source", "-s",
|
39
|
+
help="Fonte da informação"),
|
40
|
+
confidence: int = typer.Option(50, "--confidence", "-c",
|
41
|
+
min=0, max=100,
|
42
|
+
help="Nível de confiança (0-100)"),
|
43
|
+
tags: str = typer.Option("", "--tags", help="Tags separadas por vírgula"),
|
44
|
+
notes: str = typer.Option("", "--notes", "-n", help="Notas adicionais"),
|
45
|
+
):
|
46
|
+
"""Adiciona um novo IOC à base de inteligência local."""
|
47
|
+
try:
|
48
|
+
# Valida o tipo de IOC
|
49
|
+
ioc_type_enum = IOCType(ioc_type.lower())
|
50
|
+
threat_type_enum = ThreatType(threat_type.lower())
|
51
|
+
|
52
|
+
# Cria o IOC
|
53
|
+
ioc = IOC(
|
54
|
+
value=value,
|
55
|
+
ioc_type=ioc_type_enum,
|
56
|
+
threat_type=threat_type_enum,
|
57
|
+
source=source,
|
58
|
+
confidence=confidence,
|
59
|
+
tags=[t.strip() for t in tags.split(",") if t.strip()],
|
60
|
+
metadata={"notes": notes} if notes else {}
|
61
|
+
)
|
62
|
+
|
63
|
+
# Adiciona ao sistema
|
64
|
+
intel = _get_intel()
|
65
|
+
if intel.add_ioc(ioc):
|
66
|
+
console.print(f"✅ [green]IOC adicionado com sucesso![/green]")
|
67
|
+
_display_ioc(ioc)
|
68
|
+
else:
|
69
|
+
console.print("[red]❌ Falha ao adicionar IOC.[/red]")
|
70
|
+
|
71
|
+
except ValueError as e:
|
72
|
+
console.print(f"[red]❌ Erro: {str(e)}[/red]")
|
73
|
+
raise typer.Exit(1)
|
74
|
+
|
75
|
+
@app.command("search")
|
76
|
+
def search_iocs(
|
77
|
+
query: str = typer.Argument(..., help="Termo de busca"),
|
78
|
+
limit: int = typer.Option(20, "--limit", "-l", help="Número máximo de resultados"),
|
79
|
+
output: Optional[Path] = typer.Option(None, "--output", "-o", help="Arquivo de saída"),
|
80
|
+
format: str = typer.Option("table", "--format", "-f",
|
81
|
+
help="Formato de saída: table, json, yaml, csv")
|
82
|
+
):
|
83
|
+
"""Busca IOCs na base de inteligência local."""
|
84
|
+
intel = _get_intel()
|
85
|
+
|
86
|
+
with Progress(
|
87
|
+
SpinnerColumn(),
|
88
|
+
TextColumn("[progress.description]{task.description}"),
|
89
|
+
transient=True,
|
90
|
+
) as progress:
|
91
|
+
progress.add_task(description="Buscando IOCs...", total=None)
|
92
|
+
results = intel.search_iocs(query, limit=limit)
|
93
|
+
|
94
|
+
if not results:
|
95
|
+
console.print("[yellow]Nenhum IOC encontrado.[/yellow]")
|
96
|
+
return
|
97
|
+
|
98
|
+
# Formata a saída
|
99
|
+
if output:
|
100
|
+
_export_results(results, output, format)
|
101
|
+
console.print(f"✅ Resultados exportados para [cyan]{output}[/cyan]")
|
102
|
+
else:
|
103
|
+
if format == "table":
|
104
|
+
_display_iocs_table(results)
|
105
|
+
else:
|
106
|
+
_export_results(results, None, format)
|
107
|
+
|
108
|
+
@app.command("get")
|
109
|
+
def get_ioc(
|
110
|
+
ioc_type: str = typer.Argument(..., help=f"Tipo do IOC: {', '.join(IOC_TYPES)}",
|
111
|
+
autocompletion=lambda: IOC_TYPES),
|
112
|
+
value: str = typer.Argument(..., help="Valor do IOC"),
|
113
|
+
):
|
114
|
+
"""Obtém detalhes de um IOC específico."""
|
115
|
+
intel = _get_intel()
|
116
|
+
|
117
|
+
try:
|
118
|
+
ioc = intel.get_ioc(ioc_type, value)
|
119
|
+
if not ioc:
|
120
|
+
console.print("[yellow]IOC não encontrado.[/yellow]")
|
121
|
+
return
|
122
|
+
|
123
|
+
_display_ioc(ioc)
|
124
|
+
|
125
|
+
# Mostra IOCs relacionados
|
126
|
+
related = intel.get_related_iocs(ioc)
|
127
|
+
if any(related.values()):
|
128
|
+
console.print("\n[bold]Relacionados:[/bold]")
|
129
|
+
for rel_type, items in related.items():
|
130
|
+
if items:
|
131
|
+
console.print(f" [cyan]{rel_type.title()}:[/cyan]")
|
132
|
+
for item in items[:3]: # Mostra no máximo 3 itens por categoria
|
133
|
+
console.print(f" • {item.value} ([yellow]{item.threat_type.value}[/yellow])")
|
134
|
+
except ValueError as e:
|
135
|
+
console.print(f"[red]❌ Erro: {str(e)}[/red]")
|
136
|
+
raise typer.Exit(1)
|
137
|
+
|
138
|
+
@app.command("import")
|
139
|
+
def import_iocs(
|
140
|
+
file_path: Path = typer.Argument(..., help="Arquivo para importar"),
|
141
|
+
format: str = typer.Option("auto", "--format", "-f",
|
142
|
+
help="Formato do arquivo: auto, json, yaml, csv"),
|
143
|
+
):
|
144
|
+
"""Importa IOCs de um arquivo."""
|
145
|
+
if not file_path.exists():
|
146
|
+
console.print(f"[red]❌ Arquivo não encontrado: {file_path}[/red]")
|
147
|
+
raise typer.Exit(1)
|
148
|
+
|
149
|
+
try:
|
150
|
+
intel = _get_intel()
|
151
|
+
count = intel.import_iocs(file_path, format)
|
152
|
+
console.print(f"✅ [green]Importados {count} IOCs com sucesso![/green]")
|
153
|
+
except Exception as e:
|
154
|
+
console.print(f"[red]❌ Erro ao importar IOCs: {str(e)}[/red]")
|
155
|
+
raise typer.Exit(1)
|
156
|
+
|
157
|
+
@app.command("export")
|
158
|
+
def export_iocs(
|
159
|
+
output_file: Path = typer.Argument(..., help="Arquivo de saída"),
|
160
|
+
format: str = typer.Option("json", "--format", "-f",
|
161
|
+
help="Formato de saída: json, yaml, csv"),
|
162
|
+
query: Optional[str] = typer.Option(None, "--query", "-q",
|
163
|
+
help="Filtrar IOCs por termo"),
|
164
|
+
):
|
165
|
+
"""Exporta IOCs para um arquivo."""
|
166
|
+
try:
|
167
|
+
intel = _get_intel()
|
168
|
+
|
169
|
+
if query:
|
170
|
+
# Exporta apenas os IOCs que correspondem à consulta
|
171
|
+
iocs = intel.search_iocs(query, limit=1000) # Limite razoável
|
172
|
+
if not iocs:
|
173
|
+
console.print("[yellow]Nenhum IOC encontrado para exportar.[/yellow]")
|
174
|
+
return
|
175
|
+
|
176
|
+
# Converte para dicionários
|
177
|
+
ioc_dicts = [ioc.to_dict() for ioc in iocs]
|
178
|
+
|
179
|
+
# Salva no formato especificado
|
180
|
+
save_iocs_to_file(ioc_dicts, output_file, format)
|
181
|
+
else:
|
182
|
+
# Exporta todos os IOCs
|
183
|
+
intel.export_iocs(output_file, format)
|
184
|
+
|
185
|
+
console.print(f"✅ [green]IOCs exportados para [cyan]{output_file}[/cyan] no formato {format.upper()}[/green]")
|
186
|
+
|
187
|
+
except Exception as e:
|
188
|
+
console.print(f"[red]❌ Erro ao exportar IOCs: {str(e)}[/red]")
|
189
|
+
raise typer.Exit(1)
|
190
|
+
|
191
|
+
@app.command("update")
|
192
|
+
def update_signatures(
|
193
|
+
force: bool = typer.Option(False, "--force", "-f",
|
194
|
+
help="Forçar atualização mesmo se não for necessário")
|
195
|
+
):
|
196
|
+
"""Atualiza as assinaturas de ameaças a partir das fontes configuradas."""
|
197
|
+
with Progress(
|
198
|
+
SpinnerColumn(),
|
199
|
+
TextColumn("[progress.description]{task.description}"),
|
200
|
+
transient=True,
|
201
|
+
) as progress:
|
202
|
+
progress.add_task(description="Atualizando assinaturas...", total=None)
|
203
|
+
|
204
|
+
try:
|
205
|
+
intel = _get_intel()
|
206
|
+
updated = intel.update_signatures(force=force)
|
207
|
+
|
208
|
+
if updated:
|
209
|
+
console.print("✅ [green]Assinaturas atualizadas com sucesso![/green]")
|
210
|
+
else:
|
211
|
+
console.print("ℹ️ [yellow]As assinaturas já estão atualizadas.[/yellow]")
|
212
|
+
|
213
|
+
except Exception as e:
|
214
|
+
console.print(f"[red]❌ Erro ao atualizar assinaturas: {str(e)}[/red]")
|
215
|
+
raise typer.Exit(1)
|
216
|
+
|
217
|
+
def _display_ioc(ioc: IOC):
|
218
|
+
"""Exibe os detalhes de um IOC formatado."""
|
219
|
+
from rich.panel import Panel
|
220
|
+
from rich.text import Text
|
221
|
+
from rich.syntax import Syntax
|
222
|
+
|
223
|
+
# Cabeçalho com tipo e valor
|
224
|
+
header = Text()
|
225
|
+
header.append(f"{ioc.ioc_type.value.upper()}: ", style="bold")
|
226
|
+
header.append(ioc.value, style="bold green")
|
227
|
+
|
228
|
+
# Detalhes
|
229
|
+
details = []
|
230
|
+
details.append(f"[cyan]Ameaça:[/cyan] [yellow]{ioc.threat_type.value}[/yellow]")
|
231
|
+
details.append(f"[cyan]Fonte:[/cyan] {ioc.source}")
|
232
|
+
details.append(f"[cyan]Confiança:[/cyan] {ioc.confidence}/100")
|
233
|
+
|
234
|
+
if ioc.tags:
|
235
|
+
tags = ", ".join(f"[yellow]{t}[/yellow]" for t in ioc.tags)
|
236
|
+
details.append(f"[cyan]Tags:[/cyan] {tags}")
|
237
|
+
|
238
|
+
if ioc.first_seen:
|
239
|
+
details.append(f"[cyan]Primeira vez visto:[/cyan] {ioc.first_seen}")
|
240
|
+
|
241
|
+
if ioc.last_seen:
|
242
|
+
details.append(f"[cyan]Última vez visto:[/cyan] {ioc.last_seen}")
|
243
|
+
|
244
|
+
# Metadados adicionais
|
245
|
+
if ioc.metadata:
|
246
|
+
details.append("\n[bold]Metadados:[/bold]")
|
247
|
+
for k, v in ioc.metadata.items():
|
248
|
+
details.append(f" [cyan]{k}:[/cyan] {v}")
|
249
|
+
|
250
|
+
# Cria o painel
|
251
|
+
panel = Panel(
|
252
|
+
"\n".join(details),
|
253
|
+
title=header,
|
254
|
+
border_style="blue",
|
255
|
+
expand=False
|
256
|
+
)
|
257
|
+
|
258
|
+
console.print(panel)
|
259
|
+
|
260
|
+
def _display_iocs_table(iocs: List[IOC]):
|
261
|
+
"""Exibe uma tabela com múltiplos IOCs."""
|
262
|
+
from rich.table import Table
|
263
|
+
|
264
|
+
table = Table(show_header=True, header_style="bold magenta")
|
265
|
+
table.add_column("Tipo", style="cyan")
|
266
|
+
table.add_column("Valor", style="green")
|
267
|
+
table.add_column("Ameaça", style="yellow")
|
268
|
+
table.add_column("Fonte")
|
269
|
+
table.add_column("Confiança", justify="right")
|
270
|
+
table.add_column("Tags")
|
271
|
+
|
272
|
+
for ioc in iocs:
|
273
|
+
table.add_row(
|
274
|
+
ioc.ioc_type.value.upper(),
|
275
|
+
ioc.value,
|
276
|
+
ioc.threat_type.value,
|
277
|
+
ioc.source,
|
278
|
+
str(ioc.confidence),
|
279
|
+
", ".join(ioc.tags) if ioc.tags else ""
|
280
|
+
)
|
281
|
+
|
282
|
+
console.print(table)
|
283
|
+
|
284
|
+
def _export_results(iocs: List[IOC], output: Optional[Path] = None,
|
285
|
+
format: str = "table") -> str:
|
286
|
+
"""Exporta os resultados para o formato especificado."""
|
287
|
+
import json
|
288
|
+
import yaml
|
289
|
+
import csv
|
290
|
+
from io import StringIO
|
291
|
+
|
292
|
+
# Converte para dicionários
|
293
|
+
ioc_dicts = [ioc.to_dict() for ioc in iocs]
|
294
|
+
|
295
|
+
if format == "json":
|
296
|
+
result = json.dumps({"iocs": ioc_dicts}, indent=2, ensure_ascii=False)
|
297
|
+
elif format in ("yaml", "yml"):
|
298
|
+
result = yaml.safe_dump({"iocs": ioc_dicts}, allow_unicode=True)
|
299
|
+
elif format == "csv":
|
300
|
+
if not ioc_dicts:
|
301
|
+
return ""
|
302
|
+
|
303
|
+
# Extrai todos os campos possíveis
|
304
|
+
all_fields = set()
|
305
|
+
for ioc in ioc_dicts:
|
306
|
+
all_fields.update(ioc.keys())
|
307
|
+
|
308
|
+
fieldnames = sorted(all_fields)
|
309
|
+
|
310
|
+
# Escreve para uma string
|
311
|
+
output = StringIO()
|
312
|
+
writer = csv.DictWriter(output, fieldnames=fieldnames)
|
313
|
+
writer.writeheader()
|
314
|
+
writer.writerows(ioc_dicts)
|
315
|
+
result = output.getvalue()
|
316
|
+
else:
|
317
|
+
raise ValueError(f"Formato não suportado: {format}")
|
318
|
+
|
319
|
+
# Se um arquivo de saída for especificado, salva nele
|
320
|
+
if output:
|
321
|
+
with open(output, 'w', encoding='utf-8') as f:
|
322
|
+
f.write(result)
|
323
|
+
|
324
|
+
return result
|
325
|
+
|
326
|
+
# Adiciona o comando ao grupo principal
|
327
|
+
def register_app(main_app):
|
328
|
+
"""Registra os comandos de inteligência na aplicação principal."""
|
329
|
+
main_app.add_typer(app, name="intel", help="🔍 Comandos de inteligência local")
|
moriarty/cli/output.py
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
from pathlib import Path
|
4
|
+
from typing import Any, Dict, Optional
|
5
|
+
|
6
|
+
import typer
|
7
|
+
from rich.console import Console
|
8
|
+
|
9
|
+
from .state import CLIState, GlobalOptions
|
10
|
+
|
11
|
+
console = Console()
|
12
|
+
|
13
|
+
try:
|
14
|
+
import orjson # type: ignore
|
15
|
+
except ModuleNotFoundError: # pragma: no cover
|
16
|
+
import json
|
17
|
+
|
18
|
+
def _dumps(data: Any) -> bytes:
|
19
|
+
return json.dumps(data, ensure_ascii=False, separators=(",", ":")).encode("utf-8")
|
20
|
+
else:
|
21
|
+
def _dumps(data: Any) -> bytes:
|
22
|
+
return orjson.dumps(data, option=orjson.OPT_INDENT_2) # type: ignore[attr-defined]
|
23
|
+
|
24
|
+
|
25
|
+
try:
|
26
|
+
import yaml
|
27
|
+
except ModuleNotFoundError: # pragma: no cover
|
28
|
+
yaml = None # type: ignore
|
29
|
+
|
30
|
+
|
31
|
+
def ensure_state(ctx: typer.Context) -> CLIState:
|
32
|
+
obj = ctx.obj
|
33
|
+
if isinstance(obj, CLIState):
|
34
|
+
return obj
|
35
|
+
state = CLIState(options=GlobalOptions())
|
36
|
+
ctx.obj = state
|
37
|
+
return state
|
38
|
+
|
39
|
+
|
40
|
+
def emit_json(payload: Dict[str, Any], target: Optional[str], fallback: Optional[str]) -> None:
|
41
|
+
destination = target or fallback
|
42
|
+
data = _dumps(payload)
|
43
|
+
if destination in (None, "-"):
|
44
|
+
console.print_json(data=data.decode("utf-8"))
|
45
|
+
else:
|
46
|
+
Path(destination).write_bytes(data)
|
47
|
+
console.print(f"[success]JSON escrito em {destination}")
|
48
|
+
|
49
|
+
|
50
|
+
def emit_yaml(payload: Dict[str, Any], target: Optional[str], fallback: Optional[str]) -> None:
|
51
|
+
if yaml is None:
|
52
|
+
raise typer.BadParameter("PyYAML é necessário para saída YAML, instale a dependência.")
|
53
|
+
destination = target or fallback
|
54
|
+
data = yaml.safe_dump(payload, sort_keys=False)
|
55
|
+
if destination in (None, "-"):
|
56
|
+
console.print(data)
|
57
|
+
else:
|
58
|
+
Path(destination).write_text(data, encoding="utf-8")
|
59
|
+
console.print(f"[success]YAML escrito em {destination}")
|
60
|
+
|
61
|
+
|
62
|
+
__all__ = ["console", "ensure_state", "emit_json", "emit_yaml"]
|
moriarty/cli/rdap.py
ADDED
@@ -0,0 +1,94 @@
|
|
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.table import Table
|
8
|
+
|
9
|
+
from .async_utils import run_async
|
10
|
+
from .output import console, emit_json, emit_yaml, ensure_state
|
11
|
+
from ..modules.orchestrator import Orchestrator
|
12
|
+
from ..modules.rdap import RDAPResult, RDAPService
|
13
|
+
from ..net.rdap_client import RDAPClient
|
14
|
+
|
15
|
+
app = typer.Typer(add_completion=False, help="Consultas RDAP.")
|
16
|
+
|
17
|
+
|
18
|
+
@app.command("domain")
|
19
|
+
def domain(
|
20
|
+
ctx: typer.Context,
|
21
|
+
domain: str = typer.Option(..., "--domain", "-d", help="Domínio a consultar."),
|
22
|
+
json_output: Optional[str] = typer.Option(None, "--json", help="Escreve saída JSON no caminho ou '-'"),
|
23
|
+
) -> None:
|
24
|
+
_execute_rdap(ctx, query=domain, path="domain", json_output=json_output)
|
25
|
+
|
26
|
+
|
27
|
+
@app.command("ip")
|
28
|
+
def ip(
|
29
|
+
ctx: typer.Context,
|
30
|
+
ip_value: str = typer.Option(..., "--ip", "-i", help="Endereço IP ou prefixo."),
|
31
|
+
json_output: Optional[str] = typer.Option(None, "--json", help="Escreve saída JSON no caminho ou '-'"),
|
32
|
+
) -> None:
|
33
|
+
_execute_rdap(ctx, query=ip_value, path="ip", json_output=json_output)
|
34
|
+
|
35
|
+
|
36
|
+
def _execute_rdap(ctx: typer.Context, query: str, path: str, json_output: Optional[str]) -> None:
|
37
|
+
state = ensure_state(ctx)
|
38
|
+
orchestrator: Orchestrator = Orchestrator(
|
39
|
+
concurrency=state.options.concurrency,
|
40
|
+
timeout=state.options.timeout,
|
41
|
+
)
|
42
|
+
service = RDAPService(
|
43
|
+
client=RDAPClient(timeout=state.options.timeout, http2=True),
|
44
|
+
orchestrator=orchestrator,
|
45
|
+
)
|
46
|
+
|
47
|
+
if path == "domain":
|
48
|
+
result = run_async(service.domain(query))
|
49
|
+
else:
|
50
|
+
result = run_async(service.ip(query))
|
51
|
+
|
52
|
+
payload = _result_to_dict(result)
|
53
|
+
output_format = ("json" if json_output else state.options.format).lower()
|
54
|
+
|
55
|
+
if output_format == "json":
|
56
|
+
emit_json(payload, json_output, state.options.output)
|
57
|
+
elif output_format == "yaml":
|
58
|
+
emit_yaml(payload, json_output, state.options.output)
|
59
|
+
else:
|
60
|
+
_render_table(result)
|
61
|
+
|
62
|
+
|
63
|
+
def _render_table(result: RDAPResult) -> None:
|
64
|
+
table = Table(title=f"RDAP · {result.query}", box=box.SIMPLE_HEAVY)
|
65
|
+
table.add_column("Campo", style="cyan", no_wrap=True)
|
66
|
+
table.add_column("Valor", style="white")
|
67
|
+
|
68
|
+
table.add_row("URL", result.url)
|
69
|
+
table.add_row("Status", str(result.status))
|
70
|
+
table.add_row("Latência (ms)", f"{result.latency_ms:.2f}")
|
71
|
+
handle = result.response.get("handle")
|
72
|
+
if handle:
|
73
|
+
table.add_row("Handle", str(handle))
|
74
|
+
entity_type = result.response.get("objectClassName")
|
75
|
+
if entity_type:
|
76
|
+
table.add_row("Objeto", str(entity_type))
|
77
|
+
events = result.response.get("events", [])
|
78
|
+
if events:
|
79
|
+
table.add_row("Eventos", "\n".join(f"{e.get('eventAction')}: {e.get('eventDate')}" for e in events))
|
80
|
+
|
81
|
+
console.print(table)
|
82
|
+
|
83
|
+
|
84
|
+
def _result_to_dict(result: RDAPResult) -> Dict[str, Any]:
|
85
|
+
return {
|
86
|
+
"query": result.query,
|
87
|
+
"url": result.url,
|
88
|
+
"status": result.status,
|
89
|
+
"latency_ms": result.latency_ms,
|
90
|
+
"response": result.response,
|
91
|
+
}
|
92
|
+
|
93
|
+
|
94
|
+
__all__ = ["app"]
|
moriarty/cli/state.py
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
from dataclasses import dataclass
|
4
|
+
from typing import Optional
|
5
|
+
|
6
|
+
from ..logging.config import LogStyle
|
7
|
+
|
8
|
+
|
9
|
+
@dataclass
|
10
|
+
class GlobalOptions:
|
11
|
+
concurrency: int = 50
|
12
|
+
timeout: float = 8.0
|
13
|
+
proxy: Optional[str] = None
|
14
|
+
headless: str = "auto"
|
15
|
+
allowlist_domain: Optional[str] = None
|
16
|
+
output: Optional[str] = None
|
17
|
+
format: str = "table"
|
18
|
+
redact: bool = True
|
19
|
+
verbose: bool = False
|
20
|
+
quiet: bool = False
|
21
|
+
professional_mode: bool = False
|
22
|
+
seed: Optional[int] = None
|
23
|
+
dry_run: bool = False
|
24
|
+
plan_only: bool = False
|
25
|
+
sign: bool = False
|
26
|
+
resume_path: Optional[str] = None
|
27
|
+
http3: bool = False
|
28
|
+
doh: Optional[str] = None
|
29
|
+
dot: Optional[str] = None
|
30
|
+
logs: LogStyle = "structured"
|
31
|
+
|
32
|
+
|
33
|
+
@dataclass
|
34
|
+
class CLIState:
|
35
|
+
options: GlobalOptions
|
36
|
+
|
37
|
+
|
38
|
+
__all__ = ["CLIState", "GlobalOptions"]
|
moriarty/cli/tls.py
ADDED
@@ -0,0 +1,91 @@
|
|
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.table import Table
|
8
|
+
|
9
|
+
from .async_utils import run_async
|
10
|
+
from .output import console, emit_json, emit_yaml, ensure_state
|
11
|
+
from ..modules.orchestrator import Orchestrator
|
12
|
+
from ..modules.tls_scan import TLSScanService
|
13
|
+
from ..net.tls_client import TLSClient, TLSInspection
|
14
|
+
|
15
|
+
app = typer.Typer(add_completion=False, help="Inspeção de certificados TLS.")
|
16
|
+
|
17
|
+
|
18
|
+
@app.command("certs")
|
19
|
+
def certs(
|
20
|
+
ctx: typer.Context,
|
21
|
+
domain: str = typer.Option(..., "--domain", "-d", help="Host a ser inspecionado."),
|
22
|
+
port: int = typer.Option(443, help="Porta TLS."),
|
23
|
+
json_output: Optional[str] = typer.Option(None, "--json", help="Escreve saída JSON no caminho ou '-'"),
|
24
|
+
) -> None:
|
25
|
+
state = ensure_state(ctx)
|
26
|
+
orchestrator: Orchestrator[TLSInspection] = Orchestrator(
|
27
|
+
concurrency=state.options.concurrency,
|
28
|
+
timeout=state.options.timeout,
|
29
|
+
)
|
30
|
+
|
31
|
+
service = TLSScanService(
|
32
|
+
client=TLSClient(timeout=state.options.timeout),
|
33
|
+
orchestrator=orchestrator,
|
34
|
+
host=domain,
|
35
|
+
port=port,
|
36
|
+
)
|
37
|
+
|
38
|
+
result = run_async(service.run())
|
39
|
+
payload = _result_to_dict(result.inspection)
|
40
|
+
|
41
|
+
output_format = ("json" if json_output else state.options.format).lower()
|
42
|
+
if output_format == "json":
|
43
|
+
emit_json(payload, json_output, state.options.output)
|
44
|
+
elif output_format == "yaml":
|
45
|
+
emit_yaml(payload, json_output, state.options.output)
|
46
|
+
else:
|
47
|
+
_render_table(result.inspection)
|
48
|
+
|
49
|
+
|
50
|
+
def _render_table(inspection: TLSInspection) -> None:
|
51
|
+
table = Table(title=f"TLS Certs · {inspection.host}:{inspection.port}", box=box.SIMPLE_HEAVY)
|
52
|
+
table.add_column("Campo", style="cyan", no_wrap=True)
|
53
|
+
table.add_column("Valor", style="white")
|
54
|
+
|
55
|
+
table.add_row("Protocolo", inspection.protocol or "—")
|
56
|
+
table.add_row("Cipher", inspection.cipher or "—")
|
57
|
+
table.add_row("Latência (ms)", f"{inspection.latency_ms:.2f}")
|
58
|
+
|
59
|
+
for idx, cert in enumerate(inspection.certificates, start=1):
|
60
|
+
table.add_row(f"Certificado {idx} - Subject", cert.subject or "—")
|
61
|
+
table.add_row(f"Certificado {idx} - Issuer", cert.issuer or "—")
|
62
|
+
table.add_row(f"Certificado {idx} - Validade", f"{cert.not_before} → {cert.not_after}")
|
63
|
+
table.add_row(f"Certificado {idx} - SHA256", cert.fingerprint_sha256)
|
64
|
+
if cert.subject_alt_names:
|
65
|
+
table.add_row(f"Certificado {idx} - SANs", ", ".join(cert.subject_alt_names))
|
66
|
+
|
67
|
+
console.print(table)
|
68
|
+
|
69
|
+
|
70
|
+
def _result_to_dict(inspection: TLSInspection) -> Dict[str, Any]:
|
71
|
+
return {
|
72
|
+
"host": inspection.host,
|
73
|
+
"port": inspection.port,
|
74
|
+
"protocol": inspection.protocol,
|
75
|
+
"cipher": inspection.cipher,
|
76
|
+
"latency_ms": inspection.latency_ms,
|
77
|
+
"certificates": [
|
78
|
+
{
|
79
|
+
"subject": cert.subject,
|
80
|
+
"issuer": cert.issuer,
|
81
|
+
"not_before": cert.not_before.isoformat(),
|
82
|
+
"not_after": cert.not_after.isoformat(),
|
83
|
+
"fingerprint_sha256": cert.fingerprint_sha256,
|
84
|
+
"subject_alt_names": cert.subject_alt_names,
|
85
|
+
}
|
86
|
+
for cert in inspection.certificates
|
87
|
+
],
|
88
|
+
}
|
89
|
+
|
90
|
+
|
91
|
+
__all__ = ["app"]
|