def remove_builds(): print_output("Removing agent build files..") config = get_config() build_path = os.path.join(config["FACTION_PATH"], "agents/build") command = "sudo su -c 'rm -rf {0}*'".format(build_path) log.debug("Running: '{0}' from {1}".format(command, os.path.join(config["FACTION_PATH"]))) call(command, cwd=os.path.join(config["FACTION_PATH"]), shell=True)
def remove_modules(): print_output("Removing modules..") config = get_config() modules_path = os.path.join(config["FACTION_PATH"], "modules/") command = "sudo su -c 'rm -rf {0}*'".format(modules_path) log.debug("Running: '{0}' from {1}".format(command, os.path.join(config["FACTION_PATH"]))) call(command, cwd=os.path.join(config["FACTION_PATH"]), shell=True)
def stop_faction(): print_output("Stopping Faction..") config = get_config() install_path = os.path.join(config["FACTION_PATH"], "install/") log.debug("Running: 'docker-compose -p faction stop' from {0}".format( install_path)) call("docker-compose -p faction stop", cwd=install_path, shell=True)
def remove_database_files(): print_output("Removing database files..") config = get_config() install_path = os.path.join(config["FACTION_PATH"], "install/") data_path = os.path.join(config["FACTION_PATH"], "data/") command = "sudo su -c 'rm -rf {0}*'".format(data_path) log.debug("Running: '{0}' from {1}".format(command, install_path)) call(command, cwd=install_path, shell=True)
def create_api_key(user_id, owner_id, api_key_type): print_output("Creating API Key with type: {0}".format(api_key_type)) key = new_api_key(api_key_type=api_key_type, user_id=user_id, owner_id=owner_id) return dict({"Id": key.Id, "Name": key.Name, "Token": key.Token})
def take_action(self, parsed_args): if (parsed_args.transport_key): system_id = get_user_id('system') api_key = create_api_key(user_id=system_id, owner_id=system_id, type="Transport") print_output( "Transport API Key Created.\n\nKey Name: {0}\nSecret: {1}". format(api_key["Name"], api_key["Token"]))
def drop_database(container_name='faction_core_1'): print_output("Dropping database..") core = get_container(container_name) result = execute_container_command(core, 'dotnet ef database drop --force') if result.exit_code != 0: error_out("Could not drop database. Output from command: \n{0}".format( result.output)) else: print_output("Database dropped.")
def clean_faction(): print_output("Removing Faction Docker Containers and Images..") config = get_config() install_path = os.path.join(config["FACTION_PATH"], "install/") log.debug( "Running: 'docker-compose -p faction down --remove-orphans --rmi all' from {0}" .format(install_path)) call("docker-compose -p faction down --remove-orphans --rmi all", cwd=install_path, shell=True)
def create_database_migration(name, container_name='faction_core_1'): print_output("Creating database migration..") core = get_container(container_name) name = name + "_" + secrets.token_hex(8) result = execute_container_command( core, 'dotnet ef migrations add {0}'.format(name)) if result.exit_code != 0: error_out("Could create migration. Output from command: \n{0}".format( result.output)) else: print_output("Database dropped.")
def write_config(config): print_output("Writing Faction config file..") config_dir = os.path.dirname(config_file_path) path = Path(config_dir) path.mkdir(parents=True, exist_ok=True) with open(config_file_path, 'wb+') as f: json.dump(config, codecs.getwriter('utf-8')(f), ensure_ascii=False, indent=2, sort_keys=True)
def remove_uploads(): print_output("Removing uploaded files..") config = get_config() paths = [] uploads_path = os.path.join(config["FACTION_PATH"], "uploads/") paths.append(os.path.join(uploads_path, "files/")) paths.append(os.path.join(uploads_path, "payloads/")) for path in paths: command = "sudo su -c 'rm -rf {0}*'".format(path) log.debug("Running: '{0}' from {1}".format(command, uploads_path)) call(command, cwd=uploads_path, shell=True)
def create_direct_transport(name="DIRECT Transport", transport_type="DIRECT", guid="0000-0000-0000-0000-0000", api_key=None): print_output("Creating {0}".format(name)) config = get_config() if not api_key: error_out("No API Key included in request") configuration = '{"TransportId": 1, "ApiUrl":"' + config[ 'EXTERNAL_ADDRESS'] + '","ApiKeyName":"' + api_key[ 'Name'] + '","ApiSecret":"' + api_key['Token'] + '"}' create_transport(name, transport_type, guid, api_key["Id"], configuration)
def _cleanup_build_artifacts(container_name='faction_core_1'): print_output("Cleaning build artifacts from Core..") core = get_container(container_name) bin_result = execute_container_command(core, 'rm -rf /app/bin') obj_result = execute_container_command(core, 'rm -rf /app/obj') if bin_result.exit_code != 0: error_out( "Could not clean up build artifacts. Output from rm -rf /app/bin: \n{0}" .format(bin_result.output)) if obj_result.exit_code != 0: error_out( "Could not clean up build artifacts. Output from rm -rf /app/obj: \n{0}" .format(obj_result.output))
def create_user(username, password, role_id): faction_db = FactionDB() print_output("Creating User: {0}".format(username)) log.debug("Password: {0}".format(password)) log.debug("User Role ID: {0}".format(role_id)) faction_db.session.add( faction_db.User(Username=username, Password=bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt()), Created=datetime.utcnow(), RoleId=role_id, Enabled=True, Visible=True)) faction_db.session.commit()
def create_transport(name, transport_type, guid, api_key_id, configuration): faction_db = FactionDB() print_output("Creating Transport: {0}".format(name)) log.debug("Transport Type: {0}".format(transport_type)) log.debug("Guid: {0}".format(guid)) log.debug("API Key ID: {0}".format(api_key_id)) log.debug("Configuration: {0}".format(configuration)) faction_db.session.add( faction_db.Transport(Name=name, TransportType=transport_type, Guid=guid, ApiKeyId=api_key_id, Configuration=configuration, Enabled=True, Visible=True)) faction_db.session.commit()
def build_faction(): print_output("Building Faction containers..") try: config = get_config() install_path = os.path.join(config["FACTION_PATH"], "install/") log.debug( "Running: 'docker-compose -p faction up -d --force-recreate --build' from {0}" .format(install_path)) ret = call("docker-compose -p faction up -d --force-recreate --build", cwd=install_path, shell=True) if ret == 0: print_output("Faction has been built") else: error_out("Failed to build Faction.") except Exception as e: error_out("Building Faction failed. Error: {0}".format(str(e)))
def create_api_key(user_id, owner_id, type): faction_db = FactionDB() print_output("Creating API Key with type: {0}".format(type)) name = secrets.token_urlsafe(12) token = secrets.token_urlsafe(48) api_key = faction_db.ApiKey(Name=name, Key=bcrypt.hashpw(token.encode('utf-8'), bcrypt.gensalt()), Created=datetime.utcnow(), UserId=user_id, OwnerId=owner_id, Enabled=True, Visible=True ) faction_db.session.add(api_key) faction_db.session.commit() return dict({ "Id": api_key.Id, "Name": name, "Token": token })
def download_github_repo(repo_name, output_dir, access_token=None): print_output("Downloading module: {0}".format(repo_name)) log.debug("Access Token: {0}".format(access_token)) url = "https://api.github.com/repos/{0}/zipball".format(repo_name) temporary_zip = tempfile.NamedTemporaryFile(suffix=".zip") log.debug("Temporary File: {0}".format(temporary_zip.name)) if access_token: log.debug("Adding Github PAT Header") headers = {'Authorization': 'token {0}'.format(access_token)} log.debug("Downloading Zip") r = requests.get(url, headers=headers, allow_redirects=True) else: print_output("Downloading Zip") r = requests.get(url, allow_redirects=True) log.debug("Writing Zip") temporary_zip.write(r.content) log.debug("Opening Zip") zip_ref = zipfile.ZipFile(temporary_zip.name, 'r') log.debug("Extracting Zip") temporary_dir = tempfile.mkdtemp() log.debug("Creating Temporary Dir: {0}".format(temporary_dir)) zip_ref.extractall(temporary_dir) log.debug("Buildling source folder") repo_path = repo_name.replace('/', '-') source_path = os.path.join( temporary_dir, "{0}-{1}".format(repo_path, zip_ref.comment.decode())) log.debug("Checking for source path: {0}".format(source_path)) if not os.path.exists(source_path): source_path = temporary_dir log.debug("Source Path: {0}".format(source_path)) log.debug("Creating output directory: {0}".format(output_dir)) path = Path(output_dir) if path.exists(): log.debug("Cleaning out {0}".format(output_dir)) shutil.rmtree(output_dir, ignore_errors=True) path.mkdir(parents=True, exist_ok=True) module_files = os.listdir(source_path) print_output("Moving files to {0}".format(output_dir)) for module_file in module_files: module_file_path = os.path.join(source_path, module_file) log.debug("Moving {0}".format(module_file_path)) shutil.move(module_file_path, output_dir) zip_ref.close() temporary_zip.close() shutil.rmtree(temporary_dir, ignore_errors=True)
def clone_github_repo(branch, repo_name, output_dir): print_output("Cloning {0} to {1}".format(repo_name, output_dir)) command = "git clone --single-branch --branch {0} https://github.com/{1} {2}".format( branch, repo_name, output_dir) subprocess.call(command, shell=True)
def create_role(name): faction_db = FactionDB() print_output("Creating UserRole: {0}".format(name)) faction_db.session.add(faction_db.UserRole(Name=name.lower())) faction_db.session.commit()
def clone_github_repo(repo_name, output_dir): print_output("Cloning {0} to {1}".format(repo_name, output_dir)) command = "git clone https://github.com/{0} {1}".format( repo_name, output_dir) subprocess.call(command, shell=True)
def create_faction_roles(roles=("system", "admin", "operator", "readonly")): print_output("Creating Faction Roles..") for role in roles: create_role(role)
def take_action(self, parsed_args): print_output("Setup started..") generate_config_file( admin_username=parsed_args.admin_username, admin_password=parsed_args.admin_password, api_upload_dir=parsed_args.api_upload_dir, build=parsed_args.build, console_port=parsed_args.console_port, containers=parsed_args.container_names, docker_network_name=parsed_args.docker_network_name, external_address=parsed_args.external_address, faction_path=parsed_args.faction_path, flask_secret=parsed_args.flask_secret, postgres_host=parsed_args.postgres_host, postgres_database=parsed_args.postgres_database, postgres_username=parsed_args.postgres_username, postgres_password=parsed_args.postgres_password, rabbit_host=parsed_args.rabbit_host, rabbit_username=parsed_args.rabbit_username, rabbit_password=parsed_args.rabbit_password, system_username=parsed_args.system_username, system_password=parsed_args.system_password) if parsed_args.external_address: if not parsed_args.external_address.startswtih( 'http://') or not parsed_args.external_address.startswtih( 'https://'): error_out( 'Setup failed. --external-address argument must begin with http:// or https://' ) if parsed_args.build: for component in parsed_args.components: download_github_repo( "FactionC2/{0}".format(component), "{0}/source/{1}".format(parsed_args.faction_path, component), parsed_args.github_pat) write_build_compose_file() elif parsed_args.dev: write_dev_compose_file() else: write_hub_compose_file() clone_github_repo( "FactionC2/Modules-Dotnet", "{0}/modules/dotnet".format(parsed_args.faction_path)) clone_github_repo( "maraudershell/Marauder", "{0}/agents/Marauder".format(parsed_args.faction_path)) build_faction() if parsed_args.dev: print_output("Pausing setup, you need to do stuff.") print("Add the following to your hosts file: ") print("127.0.0.1 api") print("127.0.0.1 db") print("127.0.0.1 mq\n") print( "Run the following commands from the Faction Core directory: ") print( "1. dotnet ef migration add 'Initial' (You only have to do this once, unless you change the db schema)" ) print("2. dotnet ef database update\n") input("Press enter to continue setup..") else: print_output("Waiting 30 seconds for Core to come up..") core_down = True sleep(30) while core_down: status = get_container_status('faction_core_1') self.log.debug("Got status: {0}".format(status)) if status: if status.status.lower() == 'running': print_output("Core is up, continuing..") core_down = False else: print_output( "Core is not up yet. Waiting 15 more seconds..") sleep(15) create_database_migration("Initial") update_database() create_faction_roles() create_system_user() create_admin_user() system_id = get_user_id('system') api_key = create_api_key(user_id=system_id, owner_id=system_id, type="Transport") create_direct_transport(api_key=api_key) if parsed_args.dev == None or parsed_args.dev == False: print_output("Restarting Core for database changes..") core = get_container("faction_core_1") restart_container(core) config = get_config() print_output( "Setup complete! Get to hacking!!\n\nURL: {0}\nUsername: {1}\nPassword: {2}" .format(config["EXTERNAL_ADDRESS"], config["ADMIN_USERNAME"], config["ADMIN_PASSWORD"]))
def take_action(self, parsed_args): print_output("Setup started..") if parsed_args.external_address: if not (parsed_args.external_address.startswith("http://") or parsed_args.external_address.startswith("https://")): error_out( "Setup failed. --external-address argument must begin with http:// or https://" ) else: ip_options = get_ip_addresses() while True: print_output("Available NICs : IP Addresses") for key, value in ip_options.items(): print(key, " : ", value) selection = input( "Please select a NIC that corresponds to the ip address you wish to use: " ) if selection in ip_options: break parsed_args.external_address = "https://" + ip_options[selection] generate_config_file( admin_username=parsed_args.admin_username, admin_password=parsed_args.admin_password, api_upload_dir=parsed_args.api_upload_dir, build=parsed_args.build_from_source, console_port=parsed_args.console_port, containers=parsed_args.container_names, docker_network_name=parsed_args.docker_network_name, external_address=parsed_args.external_address, faction_path=parsed_args.faction_path, flask_secret=parsed_args.flask_secret, postgres_host=parsed_args.postgres_host, postgres_database=parsed_args.postgres_database, postgres_username=parsed_args.postgres_username, postgres_password=parsed_args.postgres_password, rabbit_host=parsed_args.rabbit_host, rabbit_username=parsed_args.rabbit_username, rabbit_password=parsed_args.rabbit_password, system_username=parsed_args.system_username, system_password=parsed_args.system_password, log_file_size=parsed_args.log_file_size, log_file_number=parsed_args.log_file_number) docker_tag = "latest" github_repo = "master" if parsed_args.release == "development": docker_tag = "dev" github_repo = "development" if parsed_args.build_from_source: for component in parsed_args.components: download_github_repo( "FactionC2/{0}".format(component), "{0}/source/{1}".format(parsed_args.faction_path, component), component, parsed_args.github_pat) write_build_compose_file() elif parsed_args.build_for_dev_environment: write_dev_compose_file() else: write_hub_compose_file(docker_tag) clone_github_repo( github_repo, "FactionC2/Modules-Dotnet", "{0}/modules/dotnet".format(parsed_args.faction_path)) clone_github_repo( github_repo, "maraudershell/Marauder", "{0}/agents/Marauder".format(parsed_args.faction_path)) build_faction() if parsed_args.build_for_dev_environment: print_output("Pausing setup, you need to do stuff.") print("Add the following to your hosts file: ") print("127.0.0.1 api") print("127.0.0.1 db") print("127.0.0.1 mq\n") print( "Run the following commands from the Faction Core directory: ") print( "1. dotnet ef migration add 'Initial' (You only have to do this once, unless you change the db schema)" ) print("2. dotnet ef database update\n") input("Press enter to continue setup..") else: print_output("Waiting 30 seconds for Core to come up..") core_down = True sleep(30) while core_down: status = get_container_status('faction_core_1') self.log.debug("Got status: {0}".format(status)) if status: if status.status.lower() == 'running': print_output("Core is up, continuing..") core_down = False else: print_output( "Core is not up yet. Waiting 15 more seconds..") sleep(15) create_database_migration("Initial") update_database() # Now that the environment is up, we can import common lib from factionpy.processing.user import get_user_id from factionpy.processing.api_key import new_api_key from factioncli.processing.setup.transport import create_direct_transport from factioncli.processing.setup.user_role import create_faction_roles from factioncli.processing.setup.user import create_admin_user, create_system_user create_faction_roles() create_system_user() create_admin_user() print_output("Creating API Key for Direct Transport") system_id = get_user_id('system') api_key = new_api_key(api_key_type="Transport", user_id=system_id, owner_id=system_id) create_direct_transport(api_key=api_key) if parsed_args.build_for_dev_environment is None or parsed_args.build_for_dev_environment is False: print_output("Restarting Core for database changes..") core = get_container("faction_core_1") restart_container(core) config = get_config() print_output( "Setup complete! Happy hacking!!\n\nURL: {0}\nUsername: {1}\nPassword: {2}" .format(config["EXTERNAL_ADDRESS"], config["ADMIN_USERNAME"], config["ADMIN_PASSWORD"]))