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
[](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. 😉

## 🔑 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
================================================
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']
)