Repository: chiasmod0n/chiasmodon Branch: main Commit: 256f2045cf34 Files: 7 Total size: 65.4 KB Directory structure: gitextract_3q7hvgfq/ ├── Dockerfile ├── LICENSE.txt ├── README.md ├── cli/ │ └── chiasmodon_cli.py ├── pychiasmodon.py ├── requirements.txt └── setup.py ================================================ FILE CONTENTS ================================================ ================================================ FILE: Dockerfile ================================================ FROM python:3.11-alpine COPY . . RUN python setup.py install ENTRYPOINT [ "python3","/cli/chiasmodon_cli.py" ] ================================================ FILE: LICENSE.txt ================================================ MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ # Chiasmodon [![asciicast](https://asciinema.org/a/QrEtBLFMQrjU1sjRjcgTdo41m.svg)](https://asciinema.org/a/QrEtBLFMQrjU1sjRjcgTdo41m)

Chiasmodon is an OSINT tool that allows users to gather information from various sources and conduct targeted searches based on domains, Google Play applications, email addresses, IP addresses, organizations, URLs, and more. It provides comprehensive scanning capabilities, customizable output formats, and additional options for enhanced data analysis and customization. ## ✨Features - [x] **🌐Domain**: Conduct targeted searches by specifying a domain name to gather relevant information related to the domain. - [x] **🎮Google Play Application**: Search for information related to a specific application on the Google Play Store by providing the application ID. - [x] **✉️Email, 👤Username, 🔒Password**: Conduct searches based on email, username, or password to identify potential security risks or compromised credentials. - [x] **🔍 IP Address**: Perform searches using an IP address to gather information such as geolocation, associated domain names, and historical data. - [x] **🌍 CIDR**: Search for information related to a specified CIDR (Classless Inter-Domain Routing) block, including IP range details and associated networks. - [x] **🔢 ASN**: Retrieve information about an Autonomous System Number (ASN), including its owner, associated IP ranges, and network details. - [x] **🔌 Port**: Search for information about a specific port number, including its common usage, associated services, and potential vulnerabilities. - [x] **🌐 ISP**: Conduct searches based on an Internet Service Provider (ISP) name to gather information about the ISP, its services, and associated IP ranges. - [x] **🏢 Organization (ORG)**: Search for information related to a specific organization or company, including its contact details, associated domains, and network infrastructure. - [x] **🔗 URL Path**: Perform searches based on a specific URL path to gather information about the path, its content, and potential security risks. - [x] **📞 Phone**: Conduct searches using a phone number to gather information such as the associated owner, location, and any available public records. - [x] **🔍Scan**: Perform a comprehensive scan on a given company domain name in one click, including finding - Related companies. - App applications. - Ips (`Port, Org, Isp, Asn`). - Subdomains. - Client credentials (`Email, Username, Password`). - Employee credentials (`Email, Username, Password`) - URLs (`Domain/IP, Port, Endpoint`) - [X] **🌍Country**: Sort and filter search results by country to gain insights into the geographic distribution of the identified information. - [x] **📋Output Customization**: Choose the desired output format (text, JSON, or CSV) and specify the filename to save the search results. - [x] **⚙️Additional Options**: The tool offers various additional options, such as viewing different result types (credentials, URLs, subdomains, emails, passwords, usernames, or applications), setting API tokens, specifying timeouts, limiting results, and more. ## 🚀Comming soon - **🏢Company Name**: We understand the importance of comprehensive company research. In our upcoming release, you'll be able to search by company name and access a wide range of documents associated with that company. This feature will provide you with a convenient and efficient way to gather crucial information, such as legal documents, financial reports, and other relevant records. - **👤Face (Photo)**: Visual data is a powerful tool, and we are excited to introduce our advanced facial recognition feature. With "Search by Face (Photo)," you can upload an image containing a face and leverage cutting-edge technology to identify and match individuals across various data sources. This will allow you to gather valuable information, such as social media profiles, online presence, and potential connections, all through the power of facial recognition. ## Why Chiasmodon name ? Chiasmodon niger is a species of deep sea fish in the family Chiasmodontidae. It is known for its ability to **swallow fish larger than itself**. and so do we. 😉 ![Chiasmodon background](https://journal.voca.network/wp-content/uploads/2017/10/DTR083_1200.png) ## 🔑 Subscription Join us today and unlock the potential of our cutting-edge OSINT tool. Contact https://t.me/Chiasmod0n on Telegram to subscribe and start harnessing the power of Chiasmodon for your domain investigations. ## ⬇️Install ```bash $ pip install chiasmodon ``` Only for linux 👇 ```bash $ activate-global-python-argcomplete ``` ## 💻Usage Chiasmodon provides a flexible and user-friendly command-line interface and python library. Here are some examples to demonstrate its usage: ``` usage: chiasmodon_cli.py [-h] [-m {cred.username,cred.password,cred.email,cred.phone,cred.email.domain,cred.country,domain,domain.all,ip,ip.asn,ip.isp,ip.org,ip.port,ip.country,app.id,app.name,app.domain,url.path,url.port}] [-vt {full,cred,url,email,phone,password,username,app,domain,ip,related,subdomain}] [-s] [-sr SCAN_RELATED] [-ss SCAN_SUBDOMAINS] [-sa SCAN_APPS] [-si SCAN_IPS] [-sc SCAN_CLIENTS] [-se SCAN_EMPLOYEES] [-o OUTPUT] [-ot {text,json,csv}] [-t TIMEOUT] [-l LIMIT] [-nc] [-lv] [-lm] [--init INIT] [-v] query Chiasmodon CLI positional arguments: query query argument options: -h, --help show this help message and exit -m {cred.username,cred.password,cred.email,cred.phone,cred.email.domain,cred.country,domain,domain.all,ip,ip.asn,ip.isp,ip.org,ip.port,ip.country,app.id,app.name,app.domain,url.path,url.port}, --method {cred.username,cred.password,cred.email,cred.phone,cred.email.domain,cred.country,domain,domain.all,ip,ip.asn,ip.isp,ip.org,ip.port,ip.country,app.id,app.name,app.domain,url.path,url.port} method to search by it,default is "domain". -vt {full,cred,url,email,phone,password,username,app,domain,ip,related,subdomain}, --view-type {full,cred,url,email,phone,password,username,app,domain,ip,related,subdomain} type view the result default is "full". -s, --scan scan the company domain (Related company, Clients, Employees, Company ASNs, Company Apps). -sr SCAN_RELATED, --scan-related SCAN_RELATED Run related scan, default is yes, Ex: -sr no -ss SCAN_SUBDOMAINS, --scan-subdomains SCAN_SUBDOMAINS Run subdomains scan, default is yes, Ex: -ss no -sa SCAN_APPS, --scan-apps SCAN_APPS Run App scan, default is yes, Ex: -sa no -si SCAN_IPS, --scan-ips SCAN_IPS Run IPs scan, default is yes, Ex: -si no -sc SCAN_CLIENTS, --scan-clients SCAN_CLIENTS Run clients scan, default is yes, Ex: -sc no -se SCAN_EMPLOYEES, --scan-employees SCAN_EMPLOYEES Run employees scan, default is yes, Ex: -se no -o OUTPUT, --output OUTPUT filename to save the result -ot {text,json,csv}, --output-type {text,json,csv} output format default is "text". -t TIMEOUT, --timeout TIMEOUT request timeout default is 360 sec. -l LIMIT, --limit LIMIT limit results default is 10000. -nc, --no-color show result without color. -lv, --list-view-type list view type. -lm, --list-methods list methods. --init INIT set the api token. -v, --version version. ``` Examples: ``` # Scan company by domain chiasmodon_cli.py example.com --scan # Search for target domain, you will see the result for only this "example.com" chiasmodon_cli.py example.com # Search in target and target subdomains chiasmodon_cli.py example.com --method domain.all # Search for target subdomains chiasmodon_cli.py example.com --view-type subdomain # Search for all creds in United States chiasmodon_cli.py US --method cred.country # Search for related companies by domain chiasmodon_cli.py example.com --view-type related # search for target app id chiasmodon_cli.py com.discord --method app.id # search for target app domain chiasmodon_cli.py discord.com --method app.domain # search for target app name chiasmodon_cli.py Discord --method app.name # Search for ip asn chiasmodon_cli.py AS123 --method ip.asn # Search for cred username chiasmodon_cli.py someone --method cred.username # Search for cred password chiasmodon_cli.py example@123 --method cred.password # Search for url endpoint chiasmodon_cli.py /wp-login.php --method url.path # Search for ip chiasmodon_cli.py 1.1.1.1 --method ip # Search for cidr chiasmodon_cli.py xx.xx.xx.0/24 --method ip # Search for target creds by domain emsils chiasmodon_cli.py example.com --method cred.email.domain # Search for target email chiasmodon_cli.py someone@example.com --method cred.email # search for multiple targets: chiasmodon_cli.py targets.txt --method domain --output example-creds.txt ``` Please note that these examples represent only a fraction of the available options and use cases. Refer to the documentation for more detailed instructions and explore the full range of features provided by Chiasmodon. ## 💬 Contributions and Feedback Contributions and feedback are welcome! If you encounter any issues or have suggestions for improvements, please submit them to the Chiasmodon GitHub repository. Your input will help us enhance the tool and make it more effective for the OSINT community. ## 📜License Chiasmodon is released under the [MIT License](https://opensource.org/licenses/MIT). See the [LICENSE](https://github.com/chiasmodon/LICENSE.txt) file for more details. ## ⚠️Disclaimer Chiasmodon is intended for legal and authorized use only. Users are responsible for ensuring compliance with applicable laws and regulations when using the tool. The developers of Chiasmodon disclaim any responsibility for the misuse or illegal use of the tool. ## 📢Acknowledgments Chiasmodon is the result of collaborative efforts from a dedicated team of contributors who believe in the power of OSINT. We would like to express our gratitude to the open-source community for their valuable contributions and support. ## 🔗Chiasmodon Links - [🐍 Python Library](https://pypi.org/project/chiasmodon) - [📱 Mobile (APK)](https://github.com/chiasmod0n/chiasmodon-mobile) - [🌐 Website](http://chiasmodon.online) - [💬 Telegram](https://t.me/chiasmod0n) - [🐦 X/Twitter](https://x.com/chiasmod0n) ## ⭐️Star History Star History Chart ================================================ FILE: cli/chiasmodon_cli.py ================================================ #!/usr/bin/python3 # PYTHON_ARGCOMPLETE_OK import os import sys import argcomplete import json import argparse import tldextract from yaspin import yaspin from pathlib import Path from pychiasmodon import Chiasmodon,Result,VERSION,VIEW_TYPE_LIST,T,_METHODS ROOT_DIR = os.path.dirname(os.path.abspath(__file__)) class ULIT: @staticmethod def rFile(file:Path) -> str: if not file.is_file(): print(f'{T.RED}Not found {file} file.{T.RESET}') return with open(file, 'r') as f: return f.read() @staticmethod def wFile(file:Path, data:str) -> str: with open(file, 'w') as f: f.write(data) @staticmethod def rFileToJson(file:Path) -> dict: return json.loads(ULIT.rFile(file=file)) @staticmethod def wJsonToFile(file:Path, data:dict) -> dict: ULIT.wFile( file=file, data=json.dumps(data) ) @staticmethod def get_root_domain(d:str) -> str: domain = d.split()[0] x = tldextract.extract(domain) if not x.suffix: return None return '{}.{}'.format(x.domain, x.suffix) class Scan(Chiasmodon): def __init__(self, options:argparse.Namespace) -> None: self.options :argparse.Namespace=options self.result :list = [] conf_file :Path = Path(ROOT_DIR, 'conf.json') token:str = '' if not conf_file.is_file():ULIT.wJsonToFile(conf_file, {}) if self.options.init: token = self.options.init ULIT.wJsonToFile(conf_file, {'token':self.options.init}) elif not conf_file.is_file(): ULIT.wJsonToFile(conf_file, {}) token = '' else: token = ULIT.rFileToJson(conf_file).get('token') or '' super().__init__( token=token, conf_file=conf_file, color=True if not self.options.no_color else False, debug=True, check_token=self.options.init, ) if self.options.init: sys.exit() self.scan_mode = True def scan_callback(self,beta,ys): self.print(beta.print(), ys) def proc(self): if not self.options.query: self.print(f"{T.RED}You can't run scan without company domain\nPlease use (-d or --domain) to scan the domain{T.RESET}") sys.exit(0) domain = ULIT.get_root_domain(self.options.query) if not domain: self.print(f"{T.RED}Wrong domain{T.RESET}",) sys.exit(0) self.output_folder = Path(domain) self.output_folder.mkdir(exist_ok=True, parents=True) self.__scan( domain=domain, ) def __scan(self, domain): status = False print_output = f'{T.MAGENTA}>{T.RESET}{T.YELLOW} Saved output{T.RESET}: \n' output = { 'related':[], 'apps':[], 'client-creds':[], 'client-usernames':[], 'client-passwords':[], 'client-emails':[], 'employe-creds':[], 'employe-usernames':[], 'employe-passwords':[], 'employe-emails':[], 'subdomains':[], 'urls':[], 'endpoints':[], 'ports':[], } if self.options.scan_related.lower() == 'yes': related = self.search( method='domain', query=domain, view_type='related', sort=True , timeout=self.options.timeout, limit=1000000, callback_view_result=self.scan_callback, yaspin=yaspin, search_text=f'Find {T.GREEN+domain+T.RESET} related companies...', err_text=f'Not found related !' ) if related: status = True output['related'] = [i.save_format() for i in related] ULIT.wFile((self.output_folder / 'related.txt'), '\n'.join(output['related'])) print_output += f"\t{T.MAGENTA}-{T.RESET} {T.BLUE}{(self.output_folder / 'related.txt')}{T.RESET}\n" else: self.print(f'{T.RED}💥 Not found related !{T.RESET}') self.print(f'{T.MAGENTA}{"-"*30}{T.RESET}') if self.options.scan_subdomains.lower() == 'yes': subdomains = self.search( method='domain', query=domain, view_type='subdomain', sort=True , timeout=self.options.timeout, limit=1000000, callback_view_result=self.scan_callback, yaspin=yaspin, search_text=f'Find {T.GREEN+domain+T.RESET} subdomains...', err_text=f'Not found subdomains !' ) if subdomains: status = True output['subdomains'] = [i.save_format() for i in subdomains] ULIT.wFile((self.output_folder / 'subdomains.txt'), '\n'.join(output['subdomains'])) print_output += f"\t{T.MAGENTA}-{T.RESET} {T.BLUE}{(self.output_folder / 'subdomains.txt')}{T.RESET}\n" self.print(f'{T.MAGENTA}{"-"*30}{T.RESET}') if self.options.scan_apps.lower() == 'yes': apps = self.search( method='app.domain', query=domain, view_type='app', sort=True , timeout=self.options.timeout, limit=1000000, callback_view_result=self.scan_callback, yaspin=yaspin, search_text=f'Find {T.GREEN+domain+T.RESET} Apps...', err_text=f'Not found apps !' ) if apps: status = True output['apps'] = [i.save_format() for i in apps] ULIT.wFile((self.output_folder / 'apps.txt'), '\n'.join(output['apps'])) print_output += f"\t{T.MAGENTA}-{T.RESET} {T.BLUE}{(self.output_folder / 'apps.txt')}{T.RESET}\n" self.print(f'{T.MAGENTA}{"-"*30}{T.RESET}') if self.options.scan_ips.lower() == 'yes': ips = self.search( method='domain.all', query=domain, view_type='ip', sort=True , timeout=self.options.timeout, limit=1000000, callback_view_result=self.scan_callback, yaspin=yaspin, search_text=f'Find {T.GREEN+domain+T.RESET} IPs...', err_text=f'Not found ips !' ) if ips: status = True output['ips'] = [i.save_format() for i in ips] ULIT.wFile((self.output_folder / 'ips.txt'), '\n'.join(output['ips'])) print_output += f"\t{T.MAGENTA}-{T.RESET} {T.BLUE}{(self.output_folder / 'ips.txt')}{T.RESET}\n" self.print(f'{T.MAGENTA}{"-"*30}{T.RESET}') if self.options.scan_clients.lower() == 'yes': client_creds:list[Result] = self.search( query=domain, method='domain.all', view_type='full', sort=True , timeout=self.options.timeout, limit=1000000, callback_view_result=self.scan_callback, yaspin=yaspin, search_text=f'Find {T.GREEN+domain+T.RESET} client creds...', err_text=f'Not found clients !' ) if client_creds: status = True output['client-creds'] =[i.save_format() for i in client_creds] ULIT.wFile((self.output_folder / 'client-creds.txt'), '\n'.join([':'.join(i) for i in output['client-creds']])) print_output += f"\t{T.MAGENTA}-{T.RESET} {T.BLUE}{(self.output_folder / 'client-creds.txt')}{T.RESET}\n" for i in client_creds: output['client-usernames'].append(i.credUsername) if i.credUsername and not i.credEmail and '/' not in i.credUsername and i.credUsername not in output['client-usernames'] else None output['client-passwords'].append(i.credPassword) if i.credPassword and i.credPassword not in output['client-passwords'] else None output['client-emails'].append(i.credEmail) if i.credEmail and i.credEmail not in output['client-emails'] else None output['subdomains'].append(i.domain) if i.domain and i.domain not in output['subdomains'] and i.domain != domain else None output['urls'].append(i.url) if i.url and i.url not in output['urls'] else None output['endpoints'].append(i.urlPath) if i.urlPath and i.urlPath not in output['endpoints'] else None output['ports'].append(i.urlPort) if i.urlPort and i.urlPort not in output['ports'] else None ULIT.wFile((self.output_folder / 'client-usernames.txt'), '\n'.join(output['client-usernames'])) print_output += f"\t{T.MAGENTA}-{T.RESET} {T.BLUE}{(self.output_folder / 'client-usernames.txt')}{T.RESET}\n" ULIT.wFile((self.output_folder / 'client-emails.txt'), '\n'.join(output['client-emails'])) print_output += f"\t{T.MAGENTA}-{T.RESET} {T.BLUE}{(self.output_folder / 'client-emails.txt')}{T.RESET}\n" ULIT.wFile((self.output_folder / 'client-passwords.txt'), '\n'.join(output['client-passwords'])) print_output += f"\t{T.MAGENTA}-{T.RESET} {T.BLUE}{(self.output_folder / 'client-passwords.txt')}{T.RESET}\n" ULIT.wFile((self.output_folder / 'endpoints.txt'), '\n'.join(output['endpoints'])) print_output += f"\t{T.MAGENTA}-{T.RESET} {T.BLUE}{(self.output_folder / 'endpoints.txt')}{T.RESET}\n" ULIT.wFile((self.output_folder / 'ports.txt'), '\n'.join([f"{i}" for i in output['ports']])) print_output += f"\t{T.MAGENTA}-{T.RESET} {T.BLUE}{(self.output_folder / 'ports.txt')}{T.RESET}\n" ULIT.wFile((self.output_folder / 'subdomains.txt'), '\n'.join(output['subdomains'])) print_output += f"\t{T.MAGENTA}-{T.RESET} {T.BLUE}{(self.output_folder / 'subdomains.txt')}{T.RESET}\n" ULIT.wFile((self.output_folder / 'urls.txt'), '\n'.join([f"{i}" for i in output['urls']])) print_output += f"\t{T.MAGENTA}-{T.RESET} {T.BLUE}{(self.output_folder / 'urls.txt')}{T.RESET}\n" self.print(f'{T.MAGENTA}{"-"*30}{T.RESET}') if self.options.scan_employees.lower() == 'yes': employe_creds = self.search( query=domain, method='cred.email.domain', view_type='full', sort=True, timeout=self.options.timeout, callback_view_result=self.scan_callback, limit=1000000, yaspin=yaspin, search_text=f'Find {T.GREEN+domain+T.RESET} employees creds...', err_text=f'Not found Employees!' ) if employe_creds: status = True output['employe-creds'] =[i.save_format() for i in employe_creds] ULIT.wFile((self.output_folder / 'employe-creds.txt'), '\n'.join([':'.join(i) for i in output['employe-creds']])) print_output += f"\t{T.MAGENTA}-{T.RESET} {T.BLUE}{(self.output_folder / 'employe-creds.txt')}{T.RESET}\n" for i in employe_creds: output['employe-usernames'].append(i.credUsername) if i.credUsername and not i.credEmail and '/' not in i.credUsername and i.credUsername not in output['employe-usernames'] else None output['employe-passwords'].append(i.credPassword) if i.credPassword and i.credPassword not in output['employe-passwords'] else None output['employe-emails'].append(i.credEmail) if i.credEmail and i.credEmail not in output['employe-emails'] else None ULIT.wFile((self.output_folder / 'employe-usernames.txt'), '\n'.join(output['employe-usernames'])) print_output += f"\t{T.MAGENTA}-{T.RESET} {T.BLUE}{(self.output_folder / 'employe-usernames.txt')}{T.RESET}\n" ULIT.wFile((self.output_folder / 'employe-emails.txt'), '\n'.join(output['employe-emails'])) print_output += f"\t{T.MAGENTA}-{T.RESET} {T.BLUE}{(self.output_folder / 'employe-emails.txt')}{T.RESET}\n" ULIT.wFile((self.output_folder / 'employe-passwords.txt'), '\n'.join(output['employe-passwords'])) print_output += f"\t{T.MAGENTA}-{T.RESET} {T.BLUE}{(self.output_folder / 'employe-passwords.txt')}{T.RESET}\n" if status: ULIT.wJsonToFile((self.output_folder / 'scan.json'), output) print_output += f"\t{T.MAGENTA}-{T.RESET} {T.BLUE}{(self.output_folder / 'scan.json')}{T.RESET}" self.print(print_output) class CLI(Chiasmodon): def __init__(self, options:argparse.Namespace) -> None: self.options :argparse.Namespace=options self.result :list = [] conf_file :Path = Path(ROOT_DIR, 'conf.json') token:str = '' if not conf_file.is_file():ULIT.wJsonToFile(conf_file, {}) if self.options.init: token = self.options.init ULIT.wJsonToFile(conf_file, {'token':self.options.init}) elif not conf_file.is_file(): ULIT.wJsonToFile(conf_file, {}) token = '' else: token = ULIT.rFileToJson(conf_file).get('token') or '' super().__init__( token=token, conf_file=conf_file, color=True if not self.options.no_color else False, #debug=self.options.debug, debug=True, check_token=self.options.init, ) if self.options.init: sys.exit() def review_results(self, beta:Result, ys=True, ) -> None: if beta.save_format() not in self.result: self.print(beta.print(), ys=ys) self.result.append(beta.save_format()) def save_result(self, view_type) -> None: if self.options.output: if self.options.output_type == "text": if self.result and view_type != 'cred': self.result.remove(None) if None in self.result else None ULIT.wFile( self.options.output, '\n'.join([':'.join(i) if type(i) == list else i for i in self.result]) ) if self.options.output_type == "csv": if self.result and view_type != 'cred': self.result.remove(None) if None in self.result else None ULIT.wFile( self.options.output, '\n'.join([','.join(['url/app_id','user/email', 'password', 'country', 'date'])]+[','.join(i) if type(i) == list else i for i in self.result]) if view_type == 'cred' else '\n'.join([view_type]+[','.join(i) if type(i) == list else i for i in self.result]) ) if self.options.output_type == "json": ULIT.wJsonToFile( self.options.output, self.result ) def proc(self): query = ULIT.rFile(f).splitlines() if (f:=Path(self.options.query)).is_file() else [self.options.query.strip()] for i in query: self.search( query=i, method=self.options.method, view_type=self.options.view_type, limit=self.options.limit, timeout=self.options.timeout, sort=True, yaspin=yaspin, callback_view_result=self.review_results, ) if self.options.output and self.result: self.save_result(self.options.view_type) self.print(f'{T.MAGENTA}>{T.RESET}{T.YELLOW} Saved output to {T.RESET}: {T.GREEN}{self.options.output}{T.RESET}') if __name__ == "__main__": if len(sys.argv) == 1 or '--help' in sys.argv or '-h' in sys.argv: print(f""" 🙂 🙂 /|\\ /|\\ /\\ /\\ \\___/ \\___/ 🔑 {T.BLUE}~^~^~^~^~^~^~^~^~^~^~^~^~{T.BLUE}~^~^~^~{T.GREEN} {T.RESET}/|\\{T.GREEN} |\\ {T.YELLOW}\\\\\\\\{T.GREEN}__ {T.MAGENTA}Chiasmodon{T.RESET} {T.RED}{VERSION}{T.GREEN} {T.RESET}/\\{T.GREEN} | \\_/ {T.RED}o{T.GREEN} \\ {T.CYAN}o{T.GREEN} {T.RESET}\\___/{T.GREEN} > _ {T.YELLOW}(({T.GREEN} <_ {T.CYAN}oo{T.GREEN} | / \\__+___/ |/ |/ {T.MAGENTA}>{T.RESET} {T.YELLOW}Admin{T.RESET}: {T.GREEN}https://t.me/Chiasmod0n {T.RESET}""") parser = argparse.ArgumentParser(description='Chiasmodon CLI', formatter_class=argparse.RawTextHelpFormatter,) if '-lm' not in sys.argv and '--list-methods' not in sys.argv and '-lv' not in sys.argv and '--list-view-type' not in sys.argv and '-v' not in sys.argv and '--version' not in sys.argv and '--init' not in sys.argv: parser.add_argument('query', type=str, help='query argument') parser.add_argument('-m','--method', help='method to search by it,default is "domain".', choices=_METHODS, type=str, default='domain') parser.add_argument('-vt','--view-type', help='type view the result default is "full".', choices=VIEW_TYPE_LIST, type=str, default='full') parser.add_argument('-s','--scan', help='scan the company domain (Related company, Clients, Employees, Company ASNs, Company Apps).',action='store_true') parser.add_argument('-sr','--scan-related', help='Run related scan, default is yes, Ex: -sr no',type=str, default='yes') parser.add_argument('-ss','--scan-subdomains', help='Run subdomains scan, default is yes, Ex: -ss no',type=str, default='yes') parser.add_argument('-sa','--scan-apps', help='Run App scan, default is yes, Ex: -sa no',type=str, default='yes') parser.add_argument('-si','--scan-ips', help='Run IPs scan, default is yes, Ex: -si no',type=str, default='yes') parser.add_argument('-sc','--scan-clients', help='Run clients scan, default is yes, Ex: -sc no',type=str, default='yes') parser.add_argument('-se','--scan-employees',help='Run employees scan, default is yes, Ex: -se no',type=str, default='yes') parser.add_argument('-o','--output', help='filename to save the result', type=str,) parser.add_argument('-ot','--output-type', help='output format default is "text".', choices=['text', 'json', 'csv'], type=str, default='text') parser.add_argument('-t','--timeout', help='request timeout default is 360 sec.',type=int, default=360) parser.add_argument('-l','--limit', help='limit results default is 10000.',type=int, default=10000) parser.add_argument('-nc','--no-color', help='show result without color.',action='store_true') parser.add_argument('-lv','--list-view-type',help='list view type.',action='store_true') parser.add_argument('-lm','--list-methods', help='list methods.', action='store_true') parser.add_argument('--init', help='set the api token.',type=str) parser.add_argument('-v','--version', help='version.',action='store_true') parser.epilog = f''' Examples: # Scan company by domain {Path(sys.argv[0]).name} example.com --scan # Search for target domain, you will see the result for only this "example.com" {Path(sys.argv[0]).name} example.com # Search in target and target subdomains {Path(sys.argv[0]).name} example.com --method domain.all # Search for target subdomains {Path(sys.argv[0]).name} example.com --view-type subdomain # Search for all creds in United States {Path(sys.argv[0]).name} US --method cred.country # Search for related companies by domain {Path(sys.argv[0]).name} example.com --view-type related # search for target app id {Path(sys.argv[0]).name} com.discord --method app.id # search for target app domain {Path(sys.argv[0]).name} discord.com --method app.domain # search for target app name {Path(sys.argv[0]).name} Discord --method app.name # Search for ip asn {Path(sys.argv[0]).name} AS123 --method ip.asn # Search for cred username {Path(sys.argv[0]).name} someone --method cred.username # Search for cred password {Path(sys.argv[0]).name} example@123 --method cred.password # Search for url endpoint {Path(sys.argv[0]).name} /wp-login.php --method url.path # Search for ip {Path(sys.argv[0]).name} 1.1.1.1 --method ip # Search for cidr {Path(sys.argv[0]).name} xx.xx.xx.0/24 --method ip # Search for target creds by domain emsils {Path(sys.argv[0]).name} example.com --method cred.email.domain # Search for target email {Path(sys.argv[0]).name} someone@example.com --method cred.email # search for multiple targets: {Path(sys.argv[0]).name} targets.txt --method domain --output example-creds.txt ''' argcomplete.autocomplete(parser) args = parser.parse_args() if args.list_view_type: for i in VIEW_TYPE_LIST: print(i) sys.exit(0) if args.list_methods: for i in _METHODS: print(i) sys.exit(0) if args.version: print(VERSION) sys.exit(0) if args.scan: root=Scan(options=args) root.proc() else: root=CLI(options=args) root.proc() ================================================ FILE: pychiasmodon.py ================================================ import re import os import sys import time import requests from yaspin import Spinner VERSION = "3.0.2" _API_URL = 'http://chiasmodon.online/v2/api/beta' _API_HEADERS = {'user-agent':'cli/python'} _VIEW_TYPE = { 'full':[ 'cred.username', 'cred.phone', 'cred.password', 'cred.email', 'cred.email.domain', 'cred.country', 'domain', 'domain.all', 'ip', 'ip.asn', 'ip.isp', 'ip.org', 'ip.port', 'ip.country', 'app.id', 'app.name', 'app.domain', 'url.path', 'url.port', ], 'cred':[ 'cred.phone', 'cred.username', 'cred.password', 'cred.email', 'cred.email.domain', 'cred.country', 'domain', 'domain.all', 'ip', 'ip.asn', 'ip.isp', 'ip.org', 'ip.port', 'ip.country', 'app.id', 'app.name', 'app.domain', 'url.path', 'url.port', ], 'url':[ 'cred.username', 'cred.password', 'cred.phone', 'cred.email', 'cred.email.domain', 'cred.country', 'domain', 'domain.all', 'ip', 'ip.asn', 'ip.isp', 'ip.org', 'ip.port', 'ip.country', 'url.path', 'url.port', ], 'email':[ 'cred.username', 'cred.phone', 'cred.password', 'cred.country', 'cred.email.domain', 'domain', 'domain.all', 'ip', 'ip.asn', 'ip.isp', 'ip.org', 'ip.port', 'ip.country', 'app.id', 'app.name', 'app.domain', 'url.path', 'url.port', ], 'phone':[ 'cred.username', 'cred.email', 'cred.email.domain', 'domain', 'domain.all', 'ip', 'ip.asn', 'ip.isp', 'ip.org', 'ip.port', 'ip.country', 'app.id', 'app.name', 'app.domain', 'url.path', 'url.port', 'cred.country', ], 'password':[ 'cred.username', 'cred.phone', 'cred.email', 'cred.email.domain', 'domain', 'domain.all', 'ip', 'ip.asn', 'ip.isp', 'ip.org', 'ip.port', 'ip.country', 'app.id', 'app.name', 'app.domain', 'url.path', 'url.port', 'cred.country', ], 'username': [ 'cred.phone', 'cred.password', 'domain', 'domain.all', 'ip', 'ip.asn', 'ip.isp', 'ip.org', 'ip.port', 'ip.country', 'app.id', 'app.name', 'app.domain', 'url.path', 'url.port', 'cred.country', ], 'app':[ 'cred.phone', 'cred.username', 'cred.password', 'cred.email', 'cred.email.domain', 'cred.country', 'app.domain' ], 'domain':[ 'cred.username', 'cred.phone', 'cred.password', 'cred.email', 'cred.email.domain', 'cred.country', 'domain', 'domain.all', 'ip', 'ip.asn', 'ip.isp', 'ip.org', 'ip.port', 'ip.country', 'app.id', 'app.name', 'app.domain', 'url.path', 'url.port', ], 'ip':[ 'cred.username', 'cred.phone', 'cred.password', 'cred.email', 'cred.email.domain', 'domain', 'domain.all', 'ip.asn', 'ip.isp', 'ip.org', 'ip.port', 'ip.country', 'app.id', 'app.name', 'app.domain', 'url.path', 'url.port', 'cred.country', ], 'related':[ 'domain', ], 'subdomain':[ 'domain' ] } _METHODS = [ # cred 'cred.username', # Query like -> somone 'cred.password', # Query like -> lol@123 'cred.email', # Query like -> somone@example.com 'cred.phone', # Query line -> xxxxxxxx # without : + or - or space or ) or ( 'cred.email.domain', # Query like -> example.com 'cred.country', # Query like -> US # domain 'domain', # Query like -> example.com 'domain.all', # Query like -> example.com # ip 'ip', # Query like -> 1.1.1.1 'ip.asn', # Query like -> as123 'ip.isp', # Query like -> "isp company" 'ip.org', # Query like -> "org name" 'ip.port', # Query like -> 22 'ip.country', # Query like -> US # app 'app.id', # Query like -> com.example 'app.name', # Query like -> Example 'app.domain', # Query like -> example.com # url 'url.path', # Query like -> "isp company" 'url.port', # Query like -> 8080 ] VIEW_TYPE_LIST = list(_VIEW_TYPE.keys()) class T: RED = '\033[91m' GREEN = '\033[92m' YELLOW = '\033[93m' BLUE = '\033[94m' MAGENTA = '\033[95m' CYAN = '\033[96m' RESET = '\033[0m' class Chiasmodon: def __init__(self, token=None, color=True, debug=True,conf_file=None,check_token=True) -> None: self.token = token self.conf_file = conf_file self.debug = debug self.err :bool = False self.msg :str = '' self.__result:list[Result] = [] self.scan_mode = False if not color: T.RED = '' T.GREEN = '' T.YELLOW = '' T.BLUE = '' T.MAGENTA = '' T.CYAN = '' T.RESET = '' if self.token and check_token: if self.__check_token(): self.print(f'{T.GREEN}Set token successfully{T.RESET}') else: try:os.remove(conf_file) except:pass self.print(f'{T.RED}{self.msg}{T.RESET}') return def proc_all_domains(self, query, view_type, sort, timeout, limit, callback_view_result, yaspin, search_text, err_text) -> list: domains :list = self.__proc_query( query=query, method='domain', view_type='subdomain', sort=sort, timeout=timeout, limit=limit, callback_view_result=None, yaspin=None, search_text=search_text, err_text=err_text, ) self.__result :list = [] result :list = [] domains = [i.domain for i in domains] if query not in domains:domains.append(query) for domain in domains: result.extend(self.__proc_query( query=domain, method='domain', view_type=view_type, sort=sort, timeout=timeout, limit=limit, callback_view_result=callback_view_result, yaspin=yaspin, search_text=search_text.replace(query, domain), err_text=err_text, )) self.__result :list = [] return result def filter(self,query:str,method:str): if 'domain' in method: if not re.match(r"^(?!.*\d+\.\d+\.\d+\.\d+$)[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$", query): self.print(f'{T.RED}Your format query is wrong!\nThis is not domain.{T.RESET}') return False elif method == 'ip': if not re.match(r"\b(?:\d{1,3}\.){3}\d{1,3}\b", query): self.print(f'{T.RED}Your format query is wrong!\nAccept only ipv4.{T.RESET}') return False elif method == 'ip.asn': if not query.lower().startswith('as'): self.print(f'{T.RED}Your format query is wrong!\nThe ASN starts with AS\nLike this: AS1234.{T.RESET}') return False elif method in ['ip.port', 'url.port']: if not re.match(r":(\d+)", query): self.print(f'{T.RED}Your format query is wrong!\nThis is not port.{T.RESET}') return False elif method == 'cred.email': if not re.match(r'^[\w\.-]+@[\w\.-]+\.\w+$', query): self.print(f'{T.RED}Your format query is wrong!\nThis is not email.{T.RESET}') return False elif method == 'cred.country' or method == 'ip.country': if not len(query) == 2: self.print(f'{T.RED}Your format query is wrong!\nAccept only country code.{T.RESET}') return False elif method == 'url.path': if not query[0] == '/': self.print(f'{T.RED}Your format query is wrong!\nThe url path moset be like: /somthing{T.RESET}') return False return query def print(self,text, ys=None, ys_err=False) -> None: if text == None:return if self.debug: if ys: if not ys_err: ys.write(text) else: ys.text = text else: print(text) def __check_token(self): if self.__request({ 'token' : self.token, 'version' : VERSION, 'method' : 'token' }).get('is_active'): return True return False def __request(self, data:dict,timeout=60): try: resp = requests.post(_API_URL, data=data, headers=_API_HEADERS, timeout=timeout) resp.close() resp = resp.json() try: if resp.get('err'): self.err = True self.msg = resp['msg'] except:pass return resp except requests.exceptions.ReadTimeout: self.print(f"{T.RED}\nError: timeout !\nPlease try agine later.{T.RESET}") sys.exit() except requests.exceptions.InvalidJSONError: self.print(f"{T.RED}\nError: Server send wrong data.\nPlease try agine later.{T.RESET}") sys.exit() except Exception as e: self.print(f"{T.RED}\nRequest error: {e}\nPlease try agine later.{T.RESET}") sys.exit() def __proc_query(self, method:str, query:str, view_type:str, timeout:int, sort:bool, limit:int, yaspin:bool, callback_view_result, search_text='', err_text='' ) -> dict: Result.VIEW_TYPE = view_type result : list[Result] = [] data = { 'token' : self.token, 'type-view' : view_type, 'method' : method, 'version' : VERSION, 'query' : query, 'get-info' : 'yes' } if yaspin: with yaspin(Spinner(["🐟","🐠","🐡","🐬","🐋","🐳","🦈","🐙","🐚","🪼","🪸"], 200),text=f"Processing {query} ..." if not search_text else search_text) as sp: process_info = self.__request( data=data, timeout=timeout, ) if process_info and process_info.get('count') == 0: if not err_text: self.print(f"{T.RED}Not found result{T.RESET}", sp,ys_err=True) else: self.print(f"{T.RED}{err_text}{T.RESET}", sp,ys_err=True) sp.fail("💥 ") sp.stop() return result else: sp.ok("⚓ ") else: process_info = self.__request( data=data, timeout=timeout, ) if process_info and process_info.get('count') == 0: self.print(f"{T.RED}Not found result{T.RESET}") return result del data['get-info'] if self.err: self.err= False self.print(f'{T.RED}Error: {self.msg}{T.RESET}',ys_err=True) return if yaspin: self.print(f"{T.YELLOW}Pages count{T.YELLOW}: {T.GREEN}{process_info['pages'] if process_info['count'] != -1 else 'unknown'}{T.RESET}") data['sid'] = process_info['sid'] if yaspin: YS = yaspin(f'Get pages 0/{process_info["pages"]}').green.bold.shark #.on_black YS.start() else: YS = None for p in range(1, process_info['pages']+0x1): if yaspin:YS.text = f'Get pages {p}/{process_info["pages"]}' data['page'] = p beta_result = self.__request( data=data, timeout=timeout, ) if self.err: self.err=False if yaspin:self.print(f"{T.RED}{self.msg}{T.RESET}", YS, ys_err=True);YS.fail("💥 ");YS.stop() return result for r in beta_result['data']: column :Result = Result(**r) if sort and column in self.__result: continue if callback_view_result != None: callback_view_result(beta=column, ys=YS) result.append(column) self.__result.append(column) if len(result) == limit: if yaspin:YS.text='';YS.stop() return result if beta_result['done']: if yaspin:YS.text='';YS.stop() return result time.sleep(0x1) if not result: if yaspin:self.print(f"{T.RED}Not found result{T.RESET}", YS,ys_err=True);YS.fail("💥 ");YS.stop() else:self.print(f"{T.RED}Not found result{T.RESET}") else: if yaspin:YS.text='';YS.stop() return result def search(self, query, method='domain', view_type='full', limit=10000, timeout=60, sort=True, yaspin=False, search_text='', err_text='', callback_view_result=None) -> dict: if method not in _METHODS: raise Exception(f"{T.RED}not found this method: {method}.{T.RESET}") if method not in _VIEW_TYPE[view_type]: raise Exception(f"{T.RED}{view_type} doesn't support ({method}).{T.RESET}") self.err = False self.msg = '' result = None query = self.filter(query, method) if query == False: return if method == "domain.all": result = self.proc_all_domains( query=query, view_type=view_type, sort=sort, timeout=timeout, limit=limit, callback_view_result=callback_view_result, yaspin=yaspin, search_text=search_text, err_text=err_text, ) else: result = self.__proc_query( query=query, method=method, view_type=view_type, sort=sort, timeout=timeout, limit=limit, callback_view_result=callback_view_result, yaspin=yaspin, search_text=search_text, err_text=err_text, ) self.__result:list = [] return result class Result(dict): VIEW_TYPE = None HID_PASS = True if os.environ.get('HID_PASS') else False def __init__(self,type,**kwargs) -> None: self.kwargs = kwargs Type = type self.url = None self.urlPort = None self.urlPath = None self.credEmail = None self.credUsername = None self.credPassword = None self.credCountry = None self.credDate = None self.credPhone = None self.domain = None self.ip = None self.ipAsn = None self.ipIsp = None self.ipOrg = None self.ipPorts = None self.ipCountry = None self.appID = None self.appName = None self.appIcon = None self.appDomain = None if Type == "login": if kwargs.get('url'): self.urlPath = kwargs['url']['path'] self.urlPort = kwargs['url']['port'] self.url = self.__convert_url(kwargs['url']) if kwargs['url']['ip']: self.__convert_and_set_ip(kwargs['url']['ip']) elif kwargs['url']['domain']: self.domain = self.__convert_domain(kwargs['url']['domain']) if kwargs.get('app'): self.appID = kwargs['app']['id'] self.appName = kwargs['app']['name'] self.appIcon = kwargs['app']['icon'] if kwargs['app']['domain']: self.appDomain = self.__convert_domain(kwargs['app']['domain']) if kwargs.get('cred'): if kwargs['cred']['email']: self.credEmail = self.__convert_email(kwargs['cred']['email']) self.credUsername = kwargs['cred']['username'] self.credPassword = kwargs['cred']['password'] if not self.HID_PASS else '*'*len(kwargs['cred']['password']) if kwargs['cred']['phone']: self.credPhone = self.__convert_phone(kwargs['cred']['phone']) if kwargs.get('country'): self.credCountry = kwargs['country']['f'] self.credDate = kwargs['date'] elif Type == 'url': self.urlPath = kwargs['path'] self.urlPort = kwargs['port'] self.url = self.__convert_url(kwargs) if kwargs['ip']: self.url = self.__convert_url(kwargs) self.__convert_and_set_ip(kwargs['ip']) elif kwargs['domain']: self.domain = self.__convert_domain(kwargs['domain']) elif Type == "email": self.credEmail = self.__convert_email(kwargs) elif Type == "domain": self.domain = self.__convert_domain(kwargs) elif Type == 'app': self.appID = kwargs['id'] self.appName = kwargs['name'] self.appIcon = kwargs['icon'] if kwargs['domain']: self.domain = self.__convert_domain(kwargs['domain']) elif Type == 'ip': self.__convert_and_set_ip(kwargs) def __convert_phone(self,phone): return f"+{phone['country']['p']} {phone['number']}" def __convert_email(self,email): return f"{email['name']}@{self.__convert_domain(email['domain'])}" def __convert_and_set_ip(self,ip): self.ip = ip['ip'] self.ipAsn = ip['asn'] self.ipOrg = ip['org'] self.ipIsp = ip['isp'] self.ipPorts = ip['ports'] self.ipCountry = ip['country']['f'] if ip['country'] else None def __convert_url(self,url:dict): if url['domain']: return f"{url['proto']}://{self.__convert_domain(url['domain'])}:{url['port']}{url['path']}" elif url['ip']: return f"{url['proto']}://{url['ip']['ip']}:{url['port']}{url['path']}" return None def __convert_domain(self,domain:dict): return f"{(domain['sub']+'.') if domain['sub'] else ''}{domain['name']}{('.'+domain['suffix']) if domain['suffix'] else ''}" def __str__(self) -> str: return self.save_format() def __radd__(self, other): if isinstance(other, str): return other + self.save_format() else: return NotImplemented def __add__(self, other): if isinstance(other, str): return self.save_format() + other else: return NotImplemented def __getattr__(self, key): if key in self: return self[key] else: raise AttributeError(f"'Result' object has no attribute '{key}'") def __setattr__(self, key, value): self[key] = value def print(self,): c="" if self.VIEW_TYPE == "email" and self.credEmail: c+=f"{T.MAGENTA}[ {T.YELLOW}Email{T.MAGENTA} ]{T.MAGENTA}> {T.CYAN}{self.credEmail}{T.RESET}" if self.VIEW_TYPE == "password" and self.credPassword: c+=f"{T.MAGENTA}[ {T.YELLOW}Email{T.MAGENTA} ]{T.MAGENTA}> {T.CYAN}{self.credPassword}{T.RESET}" if self.VIEW_TYPE == "username" and self.credUsername: c+=f"{T.MAGENTA}[ {T.YELLOW}Email{T.MAGENTA} ]{T.MAGENTA}> {T.CYAN}{self.credUsername}{T.RESET}" if self.VIEW_TYPE == "app" and self.appID: if self.appID:c+=f"{T.MAGENTA}[ {T.YELLOW}APP{T.MAGENTA} ]{T.RED}{T.MAGENTA}> {T.CYAN}{self.appID}{T.RESET}\n" if self.appName:c+=f"{T.MAGENTA}[ {T.YELLOW}APP{T.MAGENTA} ]{T.RED}{T.MAGENTA}> {T.RED} Name{T.RESET}{' ':10}: {T.CYAN}{self.appName}{T.RESET}\n" if self.appIcon:c+=f"{T.MAGENTA}[ {T.YELLOW}APP{T.MAGENTA} ]{T.RED}{T.MAGENTA}> {T.RED} Icon{T.RESET}{' ':10}: {T.CYAN}{self.appIcon}{T.RESET}\n" if self.appDomain:c+=f"{T.MAGENTA}[ {T.YELLOW}APP{T.MAGENTA} ]{T.MAGENTA}> {T.RED} Domain{T.RESET}{' ':8}: {T.CYAN}{self.appDomain}{T.RESET}\n" if self.VIEW_TYPE == "url" and self.url: if self.url:c+=f"{T.MAGENTA}[ {T.YELLOW}URL{T.MAGENTA} ]{T.MAGENTA}> {T.CYAN}{self.url}{T.RESET}\n" if self.urlPath:c+=f"{T.MAGENTA}[ {T.YELLOW}URL{T.MAGENTA} ]{T.MAGENTA}> {T.RED} Path{T.RESET}{' ':10}: {T.CYAN}{self.urlPath}{T.RESET}\n" if self.urlPort:c+=f"{T.MAGENTA}[ {T.YELLOW}URL{T.MAGENTA} ]{T.MAGENTA}> {T.RED} Port{T.RESET}{' ':10}: {T.CYAN}{self.urlPort}{T.RESET}\n" if self.VIEW_TYPE == "ip" and self.ip: if self.ip:c+=f"{T.MAGENTA}[ {T.YELLOW}IP{T.MAGENTA} ]{T.MAGENTA}> {T.BLUE}{self.ip}{T.RESET}\n" if self.ipPorts:c+=f"{T.MAGENTA}[ {T.YELLOW}IP{T.MAGENTA} ]{T.RED}{T.MAGENTA}> {T.RED} Ports{T.RESET}{' ':9}: {T.CYAN}{self.ipPorts}{T.RESET}\n" if self.ipAsn:c+=f"{T.MAGENTA}[ {T.YELLOW}IP{T.MAGENTA} ]{T.RED}{T.MAGENTA}> {T.RED} Asn{T.RESET}{' ':11}: {T.CYAN}{self.ipAsn}{T.RESET}\n" if self.ipIsp:c+=f"{T.MAGENTA}[ {T.YELLOW}IP{T.MAGENTA} ]{T.RED}{T.MAGENTA}> {T.RED} Isp{T.RESET}{' ':11}: {T.CYAN}{self.ipIsp}{T.RESET}\n" if self.ipOrg:c+=f"{T.MAGENTA}[ {T.YELLOW}IP{T.MAGENTA} ]{T.RED}{T.MAGENTA}> {T.RED} Org{T.RESET}{' ':11}: {T.CYAN}{self.ipOrg}{T.RESET}\n" if self.ipCountry:c+=f"{T.MAGENTA}[ {T.YELLOW}IP{T.MAGENTA} ]{T.MAGENTA}>{T.RED} Country{T.RESET}{' ':7}: {T.CYAN}{self.ipCountry}{T.RESET}\n" if self.VIEW_TYPE in ["domain", 'subdomain', 'related'] and self.domain: c+=f"{T.MAGENTA}[ {T.YELLOW}Domain{T.MAGENTA} ]{T.MAGENTA}> {T.CYAN}{self.domain}{T.RESET}" if self.VIEW_TYPE == "phone" and self.credPhone: return f"{T.MAGENTA}> {T.CYAN}{self.credPhone}{T.RESET}" if self.VIEW_TYPE == "cred": if self.url:c+=f"{T.MAGENTA}[ {T.YELLOW}URL{T.MAGENTA} ]{T.MAGENTA}> {T.BLUE}{self.url}{T.RESET}\n" if self.appID:c+=f"{T.MAGENTA}[ {T.YELLOW}APP{T.MAGENTA} ]{T.RED}{T.MAGENTA}> {T.CYAN}{self.appID}{T.RESET}\n" if self.credEmail:c+=f"{T.MAGENTA}[ {T.YELLOW}CRED{T.MAGENTA} ]{T.MAGENTA}> {T.RED} Email{T.RESET}{' ':9}: {T.GREEN}{self.credEmail}{T.RESET}\n" if self.credUsername and not self.credEmail:c+=f"{T.MAGENTA}[ {T.YELLOW}CRED{T.MAGENTA} ]{T.MAGENTA}> {T.RED} Username{T.RESET}{' ':6}: {T.GREEN}{self.credUsername}{T.RESET}\n" if self.credPassword:c+=f"{T.MAGENTA}[ {T.YELLOW}CRED{T.MAGENTA} ]{T.MAGENTA}> {T.RED} Password{T.RESET}{' ':6}: {T.GREEN}{self.credPassword}{T.RESET}\n" if self.credPhone:c+=f"{T.MAGENTA}[ {T.YELLOW}CRED{T.MAGENTA} ]{T.MAGENTA}> {T.RED} Phone{T.RESET}{' ':9}: {T.GREEN}{self.credPhone}{T.RESET}\n" if self.credCountry:c+=f"{T.MAGENTA}[ {T.YELLOW}CRED{T.MAGENTA} ]{T.MAGENTA}>{T.RED} Country{T.RESET}{' ':7}: {T.CYAN}{self.credCountry}{T.RESET}\n" if self.VIEW_TYPE == "full": if self.url:c+=f"{T.MAGENTA}[ {T.YELLOW}URL{T.MAGENTA} ]{T.MAGENTA}> {T.BLUE}{self.url}{T.RESET}\n" if self.urlPath and self.urlPath != '/':c+=f"{T.MAGENTA}[ {T.YELLOW}URL{T.MAGENTA} ]{T.MAGENTA}> {T.RED} Path{T.RESET}{' ':10}: {T.CYAN}{self.urlPath}{T.RESET}\n" if self.urlPort and self.urlPort not in [80, 443]:c+=f"{T.MAGENTA}[ {T.YELLOW}URL{T.MAGENTA} ]{T.MAGENTA}> {T.RED} Port{T.RESET}{' ':10}: {T.CYAN}{self.urlPort}{T.RESET}\n" if self.ip:c+=f"{T.MAGENTA}[ {T.YELLOW}IP{T.MAGENTA} ]{T.MAGENTA}> {T.BLUE}{self.ip}{T.RESET}\n" if self.ipPorts:c+=f"{T.MAGENTA}[ {T.YELLOW}IP{T.MAGENTA} ]{T.RED}{T.MAGENTA}> {T.RED} Ports{T.RESET}{' ':9}: {T.CYAN}{self.ipPorts}{T.RESET}\n" if self.ipAsn:c+=f"{T.MAGENTA}[ {T.YELLOW}IP{T.MAGENTA} ]{T.RED}{T.MAGENTA}> {T.RED} Asn{T.RESET}{' ':11}: {T.CYAN}{self.ipAsn}{T.RESET}\n" if self.ipIsp:c+=f"{T.MAGENTA}[ {T.YELLOW}IP{T.MAGENTA} ]{T.RED}{T.MAGENTA}> {T.RED} Isp{T.RESET}{' ':11}: {T.CYAN}{self.ipIsp}{T.RESET}\n" if self.ipOrg:c+=f"{T.MAGENTA}[ {T.YELLOW}IP{T.MAGENTA} ]{T.RED}{T.MAGENTA}> {T.RED} Org{T.RESET}{' ':11}: {T.CYAN}{self.ipOrg}{T.RESET}\n" if self.ipCountry:c+=f"{T.MAGENTA}[ {T.YELLOW}IP{T.MAGENTA} ]{T.MAGENTA}>{T.RED} Country{T.RESET}{' ':7}: {T.CYAN}{self.ipCountry}{T.RESET}\n" if self.appID:c+=f"{T.MAGENTA}[ {T.YELLOW}APP{T.MAGENTA} ]{T.RED}{T.MAGENTA}> {T.CYAN}{self.appID}{T.RESET}\n" if self.appName:c+=f"{T.MAGENTA}[ {T.YELLOW}APP{T.MAGENTA} ]{T.RED}{T.MAGENTA}> {T.RED} Name{T.RESET}{' ':10}: {T.CYAN}{self.appName}{T.RESET}\n" if self.appIcon:c+=f"{T.MAGENTA}[ {T.YELLOW}APP{T.MAGENTA} ]{T.RED}{T.MAGENTA}> {T.RED} Icon{T.RESET}{' ':10}: {T.CYAN}{self.appIcon}{T.RESET}\n" if self.appDomain:c+=f"{T.MAGENTA}[ {T.YELLOW}APP{T.MAGENTA} ]{T.MAGENTA}> {T.RED} Domain{T.RESET}{' ':8}: {T.CYAN}{self.appDomain}{T.RESET}\n" if self.credEmail:c+=f"{T.MAGENTA}[ {T.YELLOW}CRED{T.MAGENTA} ]{T.MAGENTA}> {T.RED} Email{T.RESET}{' ':9}: {T.GREEN}{self.credEmail}{T.RESET}\n" if self.credUsername and not self.credEmail:c+=f"{T.MAGENTA}[ {T.YELLOW}CRED{T.MAGENTA} ]{T.MAGENTA}> {T.RED} Username{T.RESET}{' ':6}: {T.GREEN}{self.credUsername}{T.RESET}\n" if self.credPassword:c+=f"{T.MAGENTA}[ {T.YELLOW}CRED{T.MAGENTA} ]{T.MAGENTA}> {T.RED} Password{T.RESET}{' ':6}: {T.GREEN}{self.credPassword}{T.RESET}\n" if self.credPhone:c+=f"{T.MAGENTA}[ {T.YELLOW}CRED{T.MAGENTA} ]{T.MAGENTA}> {T.RED} Phone{T.RESET}{' ':9}: {T.GREEN}{self.credPhone}{T.RESET}\n" if self.credCountry:c+=f"{T.MAGENTA}[ {T.YELLOW}CRED{T.MAGENTA} ]{T.MAGENTA}>{T.RED} Country{T.RESET}{' ':7}: {T.CYAN}{self.credCountry}{T.RESET}\n" return c def save_format(self): result = [] if self.VIEW_TYPE in ['cred', 'full']: # 1 if self.url: result.append(self.url) elif self.appID: result.append(self.appID) else: result.append('') # 2 if self.credUsername: result.append(self.credUsername) elif self.credEmail: result.append(self.credEmail) else: result.append('') # 3 if self.credPassword: result.append(self.credPassword) else: result.append('') # 4 if self.credCountry: result.append(self.credCountry) else: result.append('') # 5 #if self.credDate: # result.append(self.credDate) #else: # result.append('') return result elif self.VIEW_TYPE in ['subdomain', 'related', 'domain']: return self.domain elif self.VIEW_TYPE == 'email': return self.credEmail elif self.VIEW_TYPE == 'phone': return self.credPhone elif self.VIEW_TYPE == 'username': return self.credUsername elif self.VIEW_TYPE == 'password': return self.credPassword elif self.VIEW_TYPE == 'ip': return self.ip elif self.VIEW_TYPE == 'app': return self.appID elif self.VIEW_TYPE == 'url': return self.url else: return 'null' ================================================ FILE: requirements.txt ================================================ tldextract==5.1.2 yaspin==3.0.1 argcomplete==3.3.0 requests==2.31.0 ================================================ FILE: setup.py ================================================ #!/usr/bin/python3 from distutils.core import setup from os import path here = path.abspath(path.dirname(__file__)) with open(path.join(here, 'README.md'), encoding='utf-8') as f: long_description = f.read() setup(name='chiasmodon', version='3.0.2', description='Chiasmodon is an OSINT tool that allows users to gather information from various sources and conduct targeted searches based on domains, Google Play applications, email addresses, IP addresses, organizations, URLs, and more. It provides comprehensive scanning capabilities, customizable output formats, and additional options for enhanced data analysis and customization.', long_description=long_description, long_description_content_type='text/markdown', author='chiasmod0n', keywords='intelligence osint credentials emails asn cidr bugbounty subdomains information-gathering intelligence-analysis reconnaissance attack-surface subdomain-enumeration reconnaissance-framework bugbounty-tool email-enumeration chiasmodon', url='https://github.com/chiasmod0n/chiasmodon', packages=['.'], scripts=['cli/chiasmodon_cli.py'], install_requires=['requests', 'yaspin', 'tldextract','argcomplete'] )