def configure(cmdline=None) -> MITMConfig: parser = buildArgParser() if cmdline: args = parser.parse_args(cmdline) else: args = parser.parse_args() # Load configuration file. cfg = settings.load(settings.CONFIG_DIR + '/mitm.ini', DEFAULTS) # Override some of the switches based on command line arguments. if args.output: cfg.set('vars', 'output_dir', args.output) if args.log_filter: cfg.set('logs', 'filter', args.log_filter) if args.log_level: cfg.set('vars', 'level', args.log_level) if args.sensor_id: cfg.set('vars', 'sensor_id', args.sensor_id) outDir = Path(cfg.get('vars', 'output_dir')) outDir.mkdir(exist_ok=True) configureLoggers(cfg) logger = logging.getLogger(LOGGER_NAMES.PYRDP) if args.target is None and not args.transparent: parser.print_usage() sys.stderr.write( 'error: A relay target is required unless running in transparent proxy mode.\n' ) sys.exit(1) if (args.nla_redirection_host is None) != (args.nla_redirection_port is None): sys.stderr.write( 'Error: please provide both --nla-redirection-host and --nla-redirection-port' ) sys.exit(1) if args.target: targetHost, targetPort = parseTarget(args.target) else: targetHost = None targetPort = 3389 # FIXME: Allow to set transparent port as well. key, certificate = validateKeyAndCertificate(args.private_key, args.certificate) config = MITMConfig() config.targetHost = targetHost config.targetPort = targetPort config.privateKeyFileName = key config.listenPort = int(args.listen) config.certificateFileName = certificate config.attackerHost = args.destination_ip config.attackerPort = int(args.destination_port) config.replacementUsername = args.username config.replacementPassword = args.password config.outDir = outDir config.enableCrawler = args.crawl config.crawlerMatchFileName = args.crawler_match_file config.crawlerIgnoreFileName = args.crawler_ignore_file config.recordReplays = not args.no_replay config.downgrade = not args.no_downgrade config.transparent = args.transparent config.extractFiles = not args.no_files config.disableActiveClipboardStealing = args.disable_active_clipboard config.useGdi = not args.no_gdi config.redirectionHost = args.nla_redirection_host config.redirectionPort = args.nla_redirection_port payload = None powershell = None npayloads = int(args.payload is not None) + \ int(args.payload_powershell is not None) + \ int(args.payload_powershell_file is not None) if npayloads > 1: logger.error( "Only one of --payload, --payload-powershell and --payload-powershell-file may be supplied." ) sys.exit(1) if args.payload is not None: payload = args.payload logger.info("Using payload: %(payload)s", {"payload": args.payload}) elif args.payload_powershell is not None: powershell = args.payload_powershell logger.info("Using powershell payload: %(payload)s", {"payload": args.payload_powershell}) elif args.payload_powershell_file is not None: if not os.path.exists(args.payload_powershell_file): logger.error("Powershell file %(path)s does not exist.", {"path": args.payload_powershell_file}) sys.exit(1) try: with open(args.payload_powershell_file, "r") as f: powershell = f.read() except IOError as e: logger.error( "Error when trying to read powershell file: %(error)s", {"error": e}) sys.exit(1) logger.info("Using payload from powershell file: %(path)s", {"path": args.payload_powershell_file}) if powershell is not None: payload = "powershell -EncodedCommand " + b64encode( powershell.encode("utf-16le")).decode() if payload is not None: if args.payload_delay is None: logger.error( "--payload-delay must be provided if a payload is provided.") sys.exit(1) if args.payload_duration is None: logger.error( "--payload-duration must be provided if a payload is provided." ) sys.exit(1) try: config.payloadDelay = int(args.payload_delay) except ValueError: logger.error( "Invalid payload delay. Payload delay must be an integral number of milliseconds." ) sys.exit(1) if config.payloadDelay < 0: logger.error("Payload delay must not be negative.") sys.exit(1) if config.payloadDelay < 1000: logger.warning( "You have provided a payload delay of less than 1 second." " We recommend you use a slightly longer delay to make sure it runs properly." ) try: config.payloadDuration = int(args.payload_duration) except ValueError: logger.error( "Invalid payload duration. Payload duration must be an integral number of milliseconds." ) sys.exit(1) if config.payloadDuration < 0: logger.error("Payload duration must not be negative.") sys.exit(1) config.payload = payload elif args.payload_delay is not None: logger.error("--payload-delay was provided but no payload was set.") sys.exit(1) # Configure allowed authentication protocols. for auth in args.auth.split(','): auth = auth.strip() if auth == "tls": config.authMethods |= NegotiationProtocols.SSL elif auth == "ssp": # CredSSP implies TLS. config.authMethods |= (NegotiationProtocols.SSL | NegotiationProtocols.CRED_SSP) showConfiguration(config) return config
def configure(cmdline=None) -> MITMConfig: parser = buildArgParser() if cmdline: args = parser.parse_args(cmdline) else: args = parser.parse_args() # Load configuration file. cfg = settings.load(settings.CONFIG_DIR + '/mitm.ini', DEFAULTS) # Override some of the switches based on command line arguments. if args.output: cfg.set('vars', 'output_dir', args.output) if args.log_filter: cfg.set('logs', 'filter', args.log_filter) if args.log_level: cfg.set('vars', 'level', args.log_level) configureLoggers(cfg) logger = logging.getLogger(LOGGER_NAMES.PYRDP) outDir = Path(cfg.get('vars', 'output_dir')) outDir.mkdir(exist_ok=True) targetHost, targetPort = parseTarget(args.target) key, certificate = validateKeyAndCertificate(args.private_key, args.certificate) config = MITMConfig() config.targetHost = targetHost config.targetPort = targetPort config.privateKeyFileName = key config.listenPort = int(args.listen) config.certificateFileName = certificate config.attackerHost = args.destination_ip config.attackerPort = int(args.destination_port) config.replacementUsername = args.username config.replacementPassword = args.password config.outDir = outDir config.enableCrawler = args.crawl config.crawlerMatchFileName = args.crawler_match_file config.crawlerIgnoreFileName = args.crawler_ignore_file config.recordReplays = not args.no_replay config.downgrade = not args.no_downgrade config.transparent = args.transparent config.extractFiles = not args.no_files config.disableActiveClipboardStealing = args.disable_active_clipboard payload = None powershell = None if int(args.payload is not None) + int( args.payload_powershell is not None) + int( args.payload_powershell_file is not None) > 1: logger.error( "Only one of --payload, --payload-powershell and --payload-powershell-file may be supplied." ) sys.exit(1) if args.payload is not None: payload = args.payload logger.info("Using payload: %(payload)s", {"payload": args.payload}) elif args.payload_powershell is not None: powershell = args.payload_powershell logger.info("Using powershell payload: %(payload)s", {"payload": args.payload_powershell}) elif args.payload_powershell_file is not None: if not os.path.exists(args.payload_powershell_file): logger.error("Powershell file %(path)s does not exist.", {"path": args.payload_powershell_file}) sys.exit(1) try: with open(args.payload_powershell_file, "r") as f: powershell = f.read() except IOError as e: logger.error( "Error when trying to read powershell file: %(error)s", {"error": e}) sys.exit(1) logger.info("Using payload from powershell file: %(path)s", {"path": args.payload_powershell_file}) if powershell is not None: payload = "powershell -EncodedCommand " + b64encode( powershell.encode("utf-16le")).decode() if payload is not None: if args.payload_delay is None: logger.error( "--payload-delay must be provided if a payload is provided.") sys.exit(1) if args.payload_duration is None: logger.error( "--payload-duration must be provided if a payload is provided." ) sys.exit(1) try: config.payloadDelay = int(args.payload_delay) except ValueError: logger.error( "Invalid payload delay. Payload delay must be an integral number of milliseconds." ) sys.exit(1) if config.payloadDelay < 0: logger.error("Payload delay must not be negative.") sys.exit(1) if config.payloadDelay < 1000: logger.warning( "You have provided a payload delay of less than 1 second. We recommend you use a slightly longer delay to make sure it runs properly." ) try: config.payloadDuration = int(args.payload_duration) except ValueError: logger.error( "Invalid payload duration. Payload duration must be an integral number of milliseconds." ) sys.exit(1) if config.payloadDuration < 0: logger.error("Payload duration must not be negative.") sys.exit(1) config.payload = payload elif args.payload_delay is not None: logger.error("--payload-delay was provided but no payload was set.") sys.exit(1) showConfiguration(config) return config