crouching_tiger/ctiger/__main__.py
anoduck 832e46bf1d feat(Features): 🚧 Work continues on development of Hidden Dragon
polishing signal reception, creation of ap class, added time class,further work on logging and features.

Hidden Dragon is unfinished, do not use.
2024-03-29 21:12:29 -04:00

235 lines
10 KiB
Python

# Copyright (c) 2024 Anoduck
#
# This software is released under the MIT License.
# https://opensource.org/licenses/MIT
import os
import sys
import argparse
from configobj import ConfigObj, validate
from proclog import ProcLog
from parse_config import ParseConfig
from mac_purge import Purge
from attack import Attack
from hdragon import Dragon
from semver import Version
from .__version__ import version as _version
config_file = os.path.abspath("/etc/ctiger/config.ini")
class ProcArgs:
def process_args(self, args: argparse.Namespace, ap) -> None:
"""
Processes the command line arguments.
Args:
args (argparse.Namespace): The parsed command line arguments.
Returns:
None
"""
alog = ProcLog()
log = alog.get_log(args.log_file, args.log_level)
log.info('Started crouching tiger')
log.info('Started logger...')
match args.module:
case "att":
log.info('Starting attack formation...')
att = Attack()
att.attack(mondev=args.interface,
scan_file=args.scan_file,
net_file=args.net_file,
log=log)
case "mac":
log.info('Beginning Mac Purge')
log.debug('args: {0}'.format(args))
global valid_file
valid_file = args.valid_file
purge = Purge()
purge.mac_revealer(interface=args.name,
mon_type=args.mon_type,
valid_file=args.valid_file,
channels=args.channels,
log=log)
case "dragon":
log.info('Beginning Hidden Dragon')
log.debug('args: {0}'.format(args))
dragon = Dragon()
dragon.hidden_dragon(ap_iface=args.ap_iface,
netdb_file=args.netdb_file,
results=args.results,
config=args.config, log=log)
case _:
ap.print_help()
def main(self):
"""
Main function that executes the script.
This function performs the following tasks:
- Prints a stylized message using the `tprint` function.
- Checks if the script is being run as root.
- Sets up the `config` object.
- Sets up the `ap` argument parser.
- Parses the command line arguments.
- Calls the appropriate function based on the chosen action.
Parameters:
- None
Returns:
- None
"""
print("""
░█▀▀█ █▀▀█ █▀▀█ █──█ █▀▀ █──█ ─▀─ █▀▀▄ █▀▀▀ ▀▀█▀▀ ─▀─ █▀▀▀ █▀▀ █▀▀█
░█─── █▄▄▀ █──█ █──█ █── █▀▀█ ▀█▀ █──█ █─▀█ ─░█── ▀█▀ █─▀█ █▀▀ █▄▄▀
░█▄▄█ ▀─▀▀ ▀▀▀▀ ─▀▀▀ ▀▀▀ ▀──▀ ▀▀▀ ▀──▀ ▀▀▀▀ ─░█── ▀▀▀ ▀▀▀▀ ▀▀▀ ▀─▀▀
""")
# This script must be run as root!
if not os.geteuid() == 0:
sys.exit('Must be root! Damn, Shawty!')
#############
# configObj #
############
config_path = os.path.realpath(config_file)
spec = cfg.split("\n")
if not os.path.isfile(config_file):
if not os.path.exists(os.path.dirname(config_file)):
os.mkdir(os.path.dirname(config_file))
config = ConfigObj(config_file, configspec=spec)
config.filename = config_file
validator = validate.Validator()
config.validate(validator, copy=True)
config.write()
print("configuration file written to ", config_path)
sys.exit()
config = ConfigObj(config_file, configspec=spec)
validator = validate.Validator()
test = config.validate(validator, preserve_errors=True)
if not test:
print("Configuration file is invalid")
sys.exit()
# Versioning
global version
if os.path.exists('../VERSION.md'):
with open('../VERSION.md', 'r') as f:
raw_vers = f.read()
versionMd = str(raw_vers)
pyver = Version.parse(_version, optional_minor_and_patch=True)
txtver = Version.parse(versionMd, optional_minor_and_patch=True)
sem_vers = max(pyver, txtver)
if sem_vers != pyver:
with open('__version__.py', 'w') as wrt:
wrt.write("__version__ = '{}'\n".format(str(sem_vers)))
wrt.close()
f.close()
version = str(sem_vers)
else:
sem_vers = Version.parse(_version, optional_minor_and_patch=True)
version = str(sem_vers)
print("Crouching Tiger version: ", version)
##################
# ArgParse Setup #
##################
ap = argparse.ArgumentParser(
formatter_class=argparse.RawTextHelpFormatter,
conflict_handler='resolve',
usage='%(prog)s -i $IFACE (-t $TARGET or -f $TARGET_FILE)\n',
description='Performs various actions on wifi targets.\n'
'\n'
'This program was created with the intent to allow users to attack\n'
'wifi targets that are only available some of the time, and extract\n'
'information from them.\n'
'\n'
'There are three types of actions that can be performed:\n'
'\n'
'1. ATTACK [att] = Will run a scan in the background looking for aps in target list.\n'
' If found will begin capturing a pcap file and deauth attack.\n'
'\n'
'2. Mac_Purge [mac] = Experimental: Scans for wireless devices and acquires their MAC\n' ' addresses. Then transmits a Clear to Send Frame. If the device responds with \n'
' data frame, then information on the device will be stored and written to file.\n'
'\n'
'3. Hidden_Dragon [dragon] = Experimental: Creates a "evil twin" access point\n'
'from which various attack vectors can be leverages.\n'
'\n')
# options parser
ap.add_argument('-v', '--version', action='version',
version=f'Crouching Tiger version: {version}')
ap.add_argument('-i', '--interface', dest='name',
default=config['interface'],
help='Interface(s) to scan on')
ap.add_argument('-f', '--file', dest='config_file', default='config_path',
help='configuration file')
ap.add_argument('-l', '--log_level', dest='log_level', default=config['logging_level'],
choices=['INFO', 'DEBUG'], help='Log level')
ap.add_argument('-z', '--log_file', dest='log_file', default=config['log_file'],
help='Log file')
# Subparser
subparse = ap.add_subparsers(title='actions',
description='Use "ctiger.py $(action) --help" for more info',
required=True, dest='module',
help='You must use one.')
# attack Subcommands
dest='config'
att_parse = subparse.add_parser('att', help='Attack target')
att_parse.add_argument('-s', '--scan_file', dest='scan_file',
default=config['ATTACK']['scan_file'],
required=False,)
att_parse.add_argument('-t', '--type', choices=['create', 'switch'],
dest='mon_type',
default=config['ATTACK']['mon_type'],
help='Create new monitor inf or switch mode.')
att_parse.add_argument('-n', '--netfile', dest='net_file',
default=config['ATTACK']['network_file'],
help='File containing names of local networks.')
# att_parse.add_argument('-d', '--use_daemon', action='store_true',
# dest='use_daemon', required=False,
# help='Run in daemon mode.')
att_parse.set_defaults(fun=Attack.attack)
# mac parse subcommands
mac_parse = subparse.add_parser('mac', help='Grab Valid addresses')
mac_parse.add_argument('-t', '--type', dest='mon_type',
choices=['create', 'switch'],
default=config['MAC_PURGE']['if_type'],
help='Create new monitor inf or switch mode.')
mac_parse.add_argument('-f', '--file', dest='valid_file',
default=config['MAC_PURGE']['valid_results'],
help='File to write results too.')
mac_parse.add_argument('-c', '--channels', dest='channels',
default=config['MAC_PURGE']['channel_list'],
help='A single or comma seperated list of channels.')
mac_parse.set_defaults(fun=Purge.mac_revealer)
# Dragon Subcommands
hd_parse = subparse.add_parser('dragon', help='Perform Dragon')
hd_parse.add_argument('-a', '--ap_iface', dest='ap_iface',
default=config['DRAGON']['ap_iface'],
help='Interface to use for AP')
hd_parse.add_argument('-d', '--netdb_file', dest='netdb_file',
default=config['DRAGON']['netdb_file'],
help='Database file of APs')
hd_parse.add_argument('-r', '--results', dest='results',
default=config['DRAGON']['dragon_results'],
help='File to write results too.')
hd_parse.add_argument('-c', '--config' , dest='config',
default=config_path, help='Config file')
##################
# parse the args #
##################
ap.set_defaults(fun=self.process_args)
args = ap.parse_args(args=None if sys.argv[1:] else ['--help'])
self.process_args(args, ap)
if __name__ == '__main__':
parse = ProcArgs()
parse.main()