diff --git a/pwncat/commands/connect.py b/pwncat/commands/connect.py index ab7cd84..9fd803c 100644 --- a/pwncat/commands/connect.py +++ b/pwncat/commands/connect.py @@ -58,7 +58,7 @@ class Command(CommandDefinition): action="store_true", help="List installed implants with remote connection capability", ), - "--connection,--conn": Parameter( + "--certificate,--cert": Parameter( Complete.NONE, help="Certificate for SSL-encrypted listeners", ), @@ -82,11 +82,17 @@ class Command(CommandDefinition): def run(self, manager: "pwncat.manager.Manager", args): - protocol = None - user = None - password = None - host = None - port = None + query_args = {} + query_args["protocol"] = None + query_args["user"] = None + query_args["password"] = None + query_args["host"] = None + query_args["port"] = None + query_args["platform"] = args.platform + query_args["identity"] = args.identity + query_args["certfile"] = args.certificate + query_args["keyfile"] = args.certificate + querystring = None used_implant = None if args.list: @@ -132,19 +138,33 @@ class Command(CommandDefinition): if args.connection_string: m = self.CONNECTION_PATTERN.match(args.connection_string) - protocol = m.group("protocol") - user = m.group("user") - password = m.group("password") - host = m.group("host") - port = m.group("port") + query_args["protocol"] = m.group("protocol") + query_args["user"] = m.group("user") + query_args["password"] = m.group("password") + query_args["host"] = m.group("host") + query_args["port"] = m.group("port") + querystring = m.group("querystring") - if protocol is not None: - protocol = protocol.removesuffix("://") + if query_args["protocol"] is not None: + query_args["protocol"] = query_args["protocol"].removesuffix("://") - if host is not None and host == "": - host = None + if querystring is not None: + for arg in querystring.split("&"): + if arg.find("=") == -1: + continue - if protocol is not None and args.listen: + key, *value = arg.split("=") + + if key in query_args and query_args[key] is not None: + console.log(f"[red]error[/red]: multiple values for {key}") + return + + query_args[key] = "=".join(value) + + if query_args["host"] is not None and query_args["host"] == "": + query_args["host"] = None + + if query_args["protocol"] is not None and args.listen: console.log( "[red]error[/red]: --listen is not compatible with an explicit connection string" ) @@ -153,7 +173,7 @@ class Command(CommandDefinition): if ( sum( [ - port is not None, + query_args["port"] is not None, args.port is not None, args.pos_port is not None, ] @@ -164,22 +184,24 @@ class Command(CommandDefinition): return if args.port is not None: - port = args.port + query_args["port"] = args.port if args.pos_port is not None: - port = args.pos_port + query_args["port"] = args.pos_port - if port is not None: + if query_args["port"] is not None: try: - port = int(port.lstrip(":")) + query_args["port"] = int(query_args["port"].lstrip(":")) except ValueError: - console.log(f"[red]error[/red]: {port}: invalid port number") + console.log( + f"[red]error[/red]: {query_args['port'].lstrip(':')}: invalid port number" + ) return # Attempt to reconnect via installed implants if ( - protocol is None - and password is None - and port is None + query_args["protocol"] is None + and query_args["password"] is None + and query_args["port"] is None and args.identity is None ): db = manager.db.open() @@ -188,11 +210,14 @@ class Command(CommandDefinition): # Locate all installed implants for target in db.root.targets: - if target.guid != host and target.public_address[0] != host: + if ( + target.guid != query_args["host"] + and target.public_address[0] != query_args["host"] + ): continue # Collect users - users = {} + userss = {} for fact in target.facts: if "user" in fact.types: users[fact.id] = fact @@ -211,11 +236,14 @@ class Command(CommandDefinition): ) as progress: task = progress.add_task("", status="...") for target, implant_user, implant in implants: - # Check correct user - if user is not None and implant_user.name != user: + # Check correct query_args["user"] + if query_args["user"] is not None and implant_user.name != user: continue # Check correct platform - if args.platform is not None and target.platform != args.platform: + if ( + query_args["platform"] is not None + and target.platform != query_args["platform"] + ): continue progress.update( @@ -229,17 +257,10 @@ class Command(CommandDefinition): used_implant = implant break except ModuleFailed: + db.transaction_manager.commit() continue if used_implant is not None: manager.target.log(f"connected via {used_implant.title(manager.target)}") else: - manager.create_session( - platform=args.platform, - protocol=protocol, - user=user, - password=password, - host=host, - port=port, - identity=args.identity, - ) + manager.create_session(**query_args)