From cd6619603aa1e36081650636c651eecde3229bd5 Mon Sep 17 00:00:00 2001 From: Vincent Rose Date: Tue, 16 May 2023 18:35:22 -0700 Subject: [PATCH 01/20] File type for modules (#606) * initial work on file types * fix tests * add tests * convert the rest of the modules that use file types * fix tests * fix naming --- CHANGELOG.md | 2 + empire/server/api/v2/download/download_api.py | 1 - empire/server/api/v2/download/download_dto.py | 10 +++- empire/server/api/v2/module/module_dto.py | 3 +- empire/server/api/v2/shared_dto.py | 14 ++++-- empire/server/api/v2/starkiller | 2 +- empire/server/common/empire.py | 2 +- empire/server/core/module_service.py | 48 +++++++++++++----- .../modules/csharp/Assembly.Covenant.py | 5 +- .../modules/csharp/Assembly.Covenant.yaml | 2 +- .../csharp/AssemblyReflect.Covenant.py | 5 +- .../csharp/AssemblyReflect.Covenant.yaml | 2 +- .../modules/csharp/Inject_BOF.Covenant.py | 5 +- .../modules/csharp/Inject_BOF.Covenant.yaml | 2 +- .../modules/csharp/Shellcode.Covenant.py | 5 +- .../modules/csharp/Shellcode.Covenant.yaml | 2 +- .../code_execution/invoke_assembly.py | 5 +- .../code_execution/invoke_assembly.yaml | 2 +- .../powershell/code_execution/invoke_bof.py | 5 +- .../powershell/code_execution/invoke_bof.yaml | 2 +- empire/server/utils/option_util.py | 5 ++ empire/test/test_agent_task_api.py | 50 +++++++++++++++++-- 22 files changed, 122 insertions(+), 57 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 42d17dbdd..bba5f992a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +- Add the ability to specify a module option as a file (@Vinnybod) + ## [5.2.2] - 2023-04-30 - Dependency upgrades (@Vinnybod) diff --git a/empire/server/api/v2/download/download_api.py b/empire/server/api/v2/download/download_api.py index ca2a23399..bc690ce83 100644 --- a/empire/server/api/v2/download/download_api.py +++ b/empire/server/api/v2/download/download_api.py @@ -70,7 +70,6 @@ async def read_download( return domain_to_dto_download(db_download) -# todo basically everything should go to downloads which means the path should start after downloads. @router.get("/", response_model=Downloads) async def read_downloads( db: Session = Depends(get_db), diff --git a/empire/server/api/v2/download/download_dto.py b/empire/server/api/v2/download/download_dto.py index 3703ff266..e729ef0b7 100644 --- a/empire/server/api/v2/download/download_dto.py +++ b/empire/server/api/v2/download/download_dto.py @@ -5,10 +5,18 @@ from pydantic import BaseModel +def removeprefix(value: str, prefix: str) -> str: + if value.startswith(prefix): + return value[len(prefix) :] + else: + return value[:] + + def domain_to_dto_download(download): + location = removeprefix(download.location, "empire/server/downloads/") return Download( id=download.id, - location=download.location, + location=location, filename=download.filename, size=download.size, created_at=download.created_at, diff --git a/empire/server/api/v2/module/module_dto.py b/empire/server/api/v2/module/module_dto.py index 67449b5de..50126f95b 100644 --- a/empire/server/api/v2/module/module_dto.py +++ b/empire/server/api/v2/module/module_dto.py @@ -18,7 +18,8 @@ def domain_to_dto_module(module: EmpireModule, uid: str): "value": x[1].value, "strict": x[1].strict, "suggested_values": x[1].suggested_values, - "value_type": to_value_type(x[1].value), + # todo expand to listener, stager, etc + "value_type": to_value_type(x[1].value, x[1].type), }, ), options.items(), diff --git a/empire/server/api/v2/shared_dto.py b/empire/server/api/v2/shared_dto.py index e3eb0fbe4..9d527f508 100644 --- a/empire/server/api/v2/shared_dto.py +++ b/empire/server/api/v2/shared_dto.py @@ -19,6 +19,7 @@ class ValueType(str, Enum): float = "FLOAT" integer = "INTEGER" boolean = "BOOLEAN" + file = "FILE" class CustomOptionSchema(BaseModel): @@ -63,14 +64,17 @@ def domain_to_dto_download_description(download: models.Download): ) -def to_value_type(value: Any) -> ValueType: - if isinstance(value, str): +def to_value_type(value: Any, type: str = "") -> ValueType: + type = type or "" + if type.lower() == "file": + return ValueType.file + elif type.lower() in ["string", "str"] or isinstance(value, str): return ValueType.string - elif isinstance(value, bool): + elif type.lower() in ["boolean", "bool"] or isinstance(value, bool): return ValueType.boolean - elif isinstance(value, float): + elif type.lower() == "float" or isinstance(value, float): return ValueType.float - elif isinstance(value, int): + elif type.lower() in ["integer", "int"] or isinstance(value, int): return ValueType.integer else: return ValueType.string diff --git a/empire/server/api/v2/starkiller b/empire/server/api/v2/starkiller index 5a8273ab8..d7ecadf58 160000 --- a/empire/server/api/v2/starkiller +++ b/empire/server/api/v2/starkiller @@ -1 +1 @@ -Subproject commit 5a8273ab8d19aed189a21b6938219fa72fa268c3 +Subproject commit d7ecadf587b76ce4995cfbf73e5ecd283ca7b8c9 diff --git a/empire/server/common/empire.py b/empire/server/common/empire.py index 2a81cae19..8c5b953b0 100755 --- a/empire/server/common/empire.py +++ b/empire/server/common/empire.py @@ -83,8 +83,8 @@ def __init__(self, args=None): self.credentialsv2 = CredentialService(self) self.hostsv2 = HostService(self) self.processesv2 = HostProcessService(self) - self.modulesv2 = ModuleService(self) self.downloadsv2 = DownloadService(self) + self.modulesv2 = ModuleService(self) self.agenttasksv2 = AgentTaskService(self) self.agentfilesv2 = AgentFileService(self) self.agentsv2 = AgentService(self) diff --git a/empire/server/core/module_service.py b/empire/server/core/module_service.py index eaba77f66..714d801a9 100644 --- a/empire/server/core/module_service.py +++ b/empire/server/core/module_service.py @@ -6,6 +6,7 @@ from typing import Dict, List, Optional, Tuple import yaml +from packaging.version import parse from sqlalchemy.orm import Session from empire.server.api.v2.module.module_dto import ( @@ -17,6 +18,7 @@ from empire.server.core.config import empire_config from empire.server.core.db import models from empire.server.core.db.base import SessionLocal +from empire.server.core.download_service import DownloadService from empire.server.core.module_models import EmpireModule, LanguageEnum from empire.server.core.obfuscation_service import ObfuscationService from empire.server.utils.option_util import convert_module_options, validate_options @@ -28,6 +30,7 @@ class ModuleService(object): def __init__(self, main_menu): self.main_menu = main_menu self.obfuscation_service: ObfuscationService = main_menu.obfuscationv2 + self.download_service: DownloadService = main_menu.downloadsv2 self.modules = {} @@ -92,7 +95,7 @@ def execute_module( module = self._create_modified_module(module, modified_input) cleaned_options, err = self._validate_module_params( - module, agent, params, ignore_language_version_check, ignore_admin_check + db, module, agent, params, ignore_language_version_check, ignore_admin_check ) if err: @@ -193,6 +196,7 @@ def execute_module( def _validate_module_params( self, + db: Session, module: EmpireModule, agent: models.Agent, params: Dict[str, str], @@ -202,7 +206,7 @@ def _validate_module_params( """ Given a module and execution params, validate the input and return back a clean Dict for execution. :param module: EmpireModule - :param params: the execution parameters + :param params: the execution parameters set by the user :return: tuple with options and the error message (if applicable) """ converted_options = convert_module_options(module.options) @@ -211,19 +215,17 @@ def _validate_module_params( if err: return None, err + files, err = self._get_file_options(db, converted_options, params) + if err: + return None, err + + options.update(files) + if not ignore_language_version_check: - module_version = (module.min_language_version or "0").split(".") - agent_version = (agent.language_version or "0").split(".") - # makes sure the version is the right format: "x.x" - if len(agent_version) == 1: - agent_version.append(0) - if len(module_version) == 1: - module_version.append(0) + module_version = parse(module.min_language_version or "0") + agent_version = parse(agent.language_version or "0") # check if the agent/module PowerShell versions are compatible - if (int(module_version[0]) > int(agent_version[0])) or ( - (int(module_version[0])) == int(agent_version[0]) - and int(module_version[1]) > int(agent_version[1]) - ): + if module_version > agent_version: return ( None, f"module requires language version {module.min_language_version} but agent running language version {agent.language_version}", @@ -236,6 +238,26 @@ def _validate_module_params( return options, None + def _get_file_options(self, db, options, params): + def lower_default(x): + return "" if x is None else x.lower() + + files = {} + + for option_name, option_meta in filter( + lambda x: lower_default(x[1].get("Type")) == "file", options.items() + ): + db_download = self.download_service.get_by_id(db, params[option_name]) + if not db_download: + return ( + None, + f"File not found for '{option_name}' id {params[option_name]}", + ) + + files[option_name] = db_download + + return files, None + def _generate_script( self, db: Session, diff --git a/empire/server/modules/csharp/Assembly.Covenant.py b/empire/server/modules/csharp/Assembly.Covenant.py index fbe0e381d..24e07ebef 100755 --- a/empire/server/modules/csharp/Assembly.Covenant.py +++ b/empire/server/modules/csharp/Assembly.Covenant.py @@ -5,7 +5,6 @@ import yaml -from empire.server.core.db.base import SessionLocal from empire.server.core.module_models import EmpireModule @@ -18,9 +17,7 @@ def generate( obfuscate: bool = False, obfuscation_command: str = "", ): - base64_assembly = main_menu.downloadsv2.get_all( - SessionLocal(), None, params["File"] - )[0][0].get_base64_file() + base64_assembly = params["File"].get_base64_file() compiler = main_menu.pluginsv2.get_by_id("csharpserver") if not compiler.status == "ON": diff --git a/empire/server/modules/csharp/Assembly.Covenant.yaml b/empire/server/modules/csharp/Assembly.Covenant.yaml index 00e9d21f1..b53744927 100755 --- a/empire/server/modules/csharp/Assembly.Covenant.yaml +++ b/empire/server/modules/csharp/Assembly.Covenant.yaml @@ -167,7 +167,7 @@ - name: File description: Assembly file to execute. required: true - value: '' + type: file - name: Parameters description: The command-line parameters to pass to the assembly's EntryPoint. required: false diff --git a/empire/server/modules/csharp/AssemblyReflect.Covenant.py b/empire/server/modules/csharp/AssemblyReflect.Covenant.py index 301922753..0a86688ef 100755 --- a/empire/server/modules/csharp/AssemblyReflect.Covenant.py +++ b/empire/server/modules/csharp/AssemblyReflect.Covenant.py @@ -5,7 +5,6 @@ import yaml -from empire.server.core.db.base import SessionLocal from empire.server.core.module_models import EmpireModule @@ -18,9 +17,7 @@ def generate( obfuscate: bool = False, obfuscation_command: str = "", ): - base64_assembly = main_menu.downloadsv2.get_all( - SessionLocal(), None, params["File"] - )[0][0].get_base64_file() + base64_assembly = params["File"].get_base64_file() compiler = main_menu.pluginsv2.get_by_id("csharpserver") if not compiler.status == "ON": diff --git a/empire/server/modules/csharp/AssemblyReflect.Covenant.yaml b/empire/server/modules/csharp/AssemblyReflect.Covenant.yaml index e3d07a61d..2df28a071 100755 --- a/empire/server/modules/csharp/AssemblyReflect.Covenant.yaml +++ b/empire/server/modules/csharp/AssemblyReflect.Covenant.yaml @@ -128,7 +128,7 @@ - name: File description: Assembly file to execute. required: true - value: '' + type: file - name: Parameters description: The command-line parameters to pass to the assembly's EntryPoint. required: false diff --git a/empire/server/modules/csharp/Inject_BOF.Covenant.py b/empire/server/modules/csharp/Inject_BOF.Covenant.py index 609573a62..65b58be0a 100644 --- a/empire/server/modules/csharp/Inject_BOF.Covenant.py +++ b/empire/server/modules/csharp/Inject_BOF.Covenant.py @@ -5,7 +5,6 @@ import yaml -from empire.server.core.db.base import SessionLocal from empire.server.core.module_models import EmpireModule @@ -18,9 +17,7 @@ def generate( obfuscate: bool = False, obfuscation_command: str = "", ): - b64_bof_data = main_menu.downloadsv2.get_all( - SessionLocal(), None, params["File"] - )[0][0].get_base64_file() + b64_bof_data = params["File"].get_base64_file() compiler = main_menu.pluginsv2.get_by_id("csharpserver") if not compiler.status == "ON": diff --git a/empire/server/modules/csharp/Inject_BOF.Covenant.yaml b/empire/server/modules/csharp/Inject_BOF.Covenant.yaml index 84255d18b..c62207c1e 100644 --- a/empire/server/modules/csharp/Inject_BOF.Covenant.yaml +++ b/empire/server/modules/csharp/Inject_BOF.Covenant.yaml @@ -86,7 +86,7 @@ - name: File description: Beacon object file to load and execute. required: false - value: '' + type: file - name: EntryPoint description: Name of the function exported to execute in the beacon object file. required: false diff --git a/empire/server/modules/csharp/Shellcode.Covenant.py b/empire/server/modules/csharp/Shellcode.Covenant.py index dad1e9e58..e879d4df1 100755 --- a/empire/server/modules/csharp/Shellcode.Covenant.py +++ b/empire/server/modules/csharp/Shellcode.Covenant.py @@ -5,7 +5,6 @@ import yaml -from empire.server.core.db.base import SessionLocal from empire.server.core.module_models import EmpireModule @@ -19,9 +18,7 @@ def generate( obfuscation_command: str = "", ): try: - base64_shellcode = main_menu.downloadsv2.get_all( - SessionLocal(), None, params["File"] - )[0][0].get_base64_file() + base64_shellcode = params["File"].get_base64_file() except Exception as e: return None, f"Failed to get base64 encoded shellcode: {e}" diff --git a/empire/server/modules/csharp/Shellcode.Covenant.yaml b/empire/server/modules/csharp/Shellcode.Covenant.yaml index d450ba401..b39ba2a93 100755 --- a/empire/server/modules/csharp/Shellcode.Covenant.yaml +++ b/empire/server/modules/csharp/Shellcode.Covenant.yaml @@ -106,6 +106,6 @@ - name: File description: Shellcode file to execute. required: true - value: '' + type: file advanced: custom_generate: true \ No newline at end of file diff --git a/empire/server/modules/powershell/code_execution/invoke_assembly.py b/empire/server/modules/powershell/code_execution/invoke_assembly.py index efacce257..68de3ec9c 100644 --- a/empire/server/modules/powershell/code_execution/invoke_assembly.py +++ b/empire/server/modules/powershell/code_execution/invoke_assembly.py @@ -3,7 +3,6 @@ from builtins import object, str from typing import Dict -from empire.server.core.db.base import SessionLocal from empire.server.core.module_models import EmpireModule from empire.server.utils.module_util import handle_error_message @@ -56,9 +55,7 @@ def parse_assembly_args(args): return handle_error_message(err) try: - encode_assembly = main_menu.downloadsv2.get_all( - SessionLocal(), None, params["File"] - )[0][0].get_base64_file() + encode_assembly = params["File"].get_base64_file() except Exception: return handle_error_message( "[!] Could not read .NET assembly path at: " + str(params["Arguments"]) diff --git a/empire/server/modules/powershell/code_execution/invoke_assembly.yaml b/empire/server/modules/powershell/code_execution/invoke_assembly.yaml index 7ef664ffe..4f0fb513f 100644 --- a/empire/server/modules/powershell/code_execution/invoke_assembly.yaml +++ b/empire/server/modules/powershell/code_execution/invoke_assembly.yaml @@ -27,7 +27,7 @@ options: - name: File description: Filename in '/empire/server/downloads' to load and execute. supported. required: true - value: '' + type: file - name: Arguments description: Any arguments to be passed to the assembly required: false diff --git a/empire/server/modules/powershell/code_execution/invoke_bof.py b/empire/server/modules/powershell/code_execution/invoke_bof.py index 785e37db0..5625c5ac3 100644 --- a/empire/server/modules/powershell/code_execution/invoke_bof.py +++ b/empire/server/modules/powershell/code_execution/invoke_bof.py @@ -3,7 +3,6 @@ from builtins import object, str from typing import Dict -from empire.server.core.db.base import SessionLocal from empire.server.core.module_models import EmpireModule from empire.server.utils.module_util import handle_error_message @@ -27,9 +26,7 @@ def generate( if err: return handle_error_message(err) - bof_data = main_menu.downloadsv2.get_all(SessionLocal(), None, params["File"])[ - 0 - ][0].get_base64_file() + bof_data = params["File"].get_base64_file() script_end = f"$bofbytes = [System.Convert]::FromBase64String('{ bof_data }');" script_end += ( diff --git a/empire/server/modules/powershell/code_execution/invoke_bof.yaml b/empire/server/modules/powershell/code_execution/invoke_bof.yaml index 2239a5721..0291fb0cd 100644 --- a/empire/server/modules/powershell/code_execution/invoke_bof.yaml +++ b/empire/server/modules/powershell/code_execution/invoke_bof.yaml @@ -28,7 +28,7 @@ options: - name: File description: Beacon object file to load and execute. required: true - value: '' + type: file - name: EntryPoint description: Name of the function exported to execute in the beacon object file. required: true diff --git a/empire/server/utils/option_util.py b/empire/server/utils/option_util.py index 6c7b6cc5c..3ab7370de 100644 --- a/empire/server/utils/option_util.py +++ b/empire/server/utils/option_util.py @@ -43,12 +43,17 @@ class (instance). If any options are invalid, returns a Tuple of (options, None). Will also attempt to cast the options to the correct type using safe_cast. + + Options of type "file" are not validated. """ options = {} # make a copy so that the original options are not modified params = params.copy() for instance_key, option_meta in instance_options.items(): + if option_meta.get("Type") == "file": + continue + # Attempt to default a unset required option to the default value if ( instance_key not in params diff --git a/empire/test/test_agent_task_api.py b/empire/test/test_agent_task_api.py index 0416af635..a562eca3d 100644 --- a/empire/test/test_agent_task_api.py +++ b/empire/test/test_agent_task_api.py @@ -338,13 +338,13 @@ def test_create_task_module_modified_input(client, admin_auth_header, agent): def test_create_task_bof_module_disabled_csharpserver( client, admin_auth_header, agent, bof_download ): - response_module = client.post( + response = client.post( f"/api/v2/agents/{agent.session_id}/tasks/module", headers=admin_auth_header, json={ "module_id": "csharp_inject_bof_inject_bof", "options": { - "File": "whoami.x64.o", + "File": bof_download["id"], "EntryPoint": "", "ArgumentList": "", "Architecture": "x64", @@ -352,8 +352,50 @@ def test_create_task_bof_module_disabled_csharpserver( }, ) - assert response_module.status_code == 400 - assert response_module.json()["detail"] == "csharpserver plugin not running" + assert response.status_code == 400 + assert response.json()["detail"] == "csharpserver plugin not running" + + +def test_create_task_module_with_file_option_not_found( + client, admin_auth_header, agent, bof_download +): + response = client.post( + f"/api/v2/agents/{agent.session_id}/tasks/module", + headers=admin_auth_header, + json={ + "module_id": "powershell_code_execution_invoke_bof", + "options": { + "File": "999", + "EntryPoint": "go", + "ArgumentList": "", + "UnicodeStringParameter": "False", + }, + }, + ) + + assert response.status_code == 400 + assert response.json()["detail"] == "File not found for 'File' id 999" + + +def test_create_task_module_with_file_option( + client, admin_auth_header, agent, bof_download +): + response = client.post( + f"/api/v2/agents/{agent.session_id}/tasks/module", + headers=admin_auth_header, + json={ + "module_id": "powershell_code_execution_invoke_bof", + "options": { + "File": bof_download["id"], + "EntryPoint": "go", + "ArgumentList": "", + "UnicodeStringParameter": "False", + }, + }, + ) + + assert response.status_code == 201 + assert response.json()["id"] > 0 def test_create_task_module_validates_required_options( From 461380585b1ab00f8f9341e026a809292169d834 Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Wed, 17 May 2023 02:27:11 +0000 Subject: [PATCH 02/20] Prepare release 5.3.0 private --- CHANGELOG.md | 6 +++++- empire/server/common/empire.py | 2 +- pyproject.toml | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bba5f992a..8fea4ff63 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [5.3.0] - 2023-05-17 + - Add the ability to specify a module option as a file (@Vinnybod) ## [5.2.2] - 2023-04-30 @@ -466,7 +468,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Updated shellcoderdi to newest version (@Cx01N) - Added a Nim launcher (@Hubbl3) -[Unreleased]: https://github.com/BC-SECURITY/Empire-Sponsors/compare/v5.2.2...HEAD +[Unreleased]: https://github.com/BC-SECURITY/Empire-Sponsors/compare/v5.3.0...HEAD + +[5.3.0]: https://github.com/BC-SECURITY/Empire-Sponsors/compare/v5.2.2...v5.3.0 [5.2.2]: https://github.com/BC-SECURITY/Empire-Sponsors/compare/v5.2.1...v5.2.2 diff --git a/empire/server/common/empire.py b/empire/server/common/empire.py index 8c5b953b0..0eefbee32 100755 --- a/empire/server/common/empire.py +++ b/empire/server/common/empire.py @@ -39,7 +39,7 @@ from . import agents, credentials, listeners, stagers -VERSION = "5.2.2 BC Security Fork" +VERSION = "5.3.0 BC Security Fork" log = logging.getLogger(__name__) diff --git a/pyproject.toml b/pyproject.toml index a42391d4a..7ad6129f5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "empire-bc-security-fork" -version = "5.2.2" +version = "5.3.0" description = "" authors = ["BC Security "] readme = "README.md" From 79a9a5ceb3d40e05d64ad40fbbec1dcbf8ed6dba Mon Sep 17 00:00:00 2001 From: Anthony Rose <20302208+Cx01N@users.noreply.github.com> Date: Wed, 17 May 2023 19:20:58 -0400 Subject: [PATCH 03/20] fixed error when launching ironpython stagers (#609) --- empire/server/listeners/http.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/empire/server/listeners/http.py b/empire/server/listeners/http.py index ac295cffe..109cfc0c9 100755 --- a/empire/server/listeners/http.py +++ b/empire/server/listeners/http.py @@ -856,9 +856,14 @@ def start_server(self, listenerOptions): @app.route("/download//") def send_stager(stager): with SessionLocal.begin() as db: - obfuscation_config = self.mainMenu.obfuscationv2.get_obfuscation_config( - db, stager - ) + if stager == "ironpython": + obfuscation_config = ( + self.mainMenu.obfuscationv2.get_obfuscation_config(db, "csharp") + ) + else: + obfuscation_config = ( + self.mainMenu.obfuscationv2.get_obfuscation_config(db, stager) + ) obfuscation = obfuscation_config.enabled obfuscation_command = obfuscation_config.command From c3526199dce345d01ce2f7ef9d09f2dc4a20498f Mon Sep 17 00:00:00 2001 From: Anthony Rose <20302208+Cx01N@users.noreply.github.com> Date: Wed, 17 May 2023 19:21:30 -0400 Subject: [PATCH 04/20] Updated client to use new file endpoint (#610) --- empire/client/src/menus/InteractMenu.py | 2 +- empire/client/src/menus/UseModuleMenu.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/empire/client/src/menus/InteractMenu.py b/empire/client/src/menus/InteractMenu.py index f220f3464..efcb16df8 100644 --- a/empire/client/src/menus/InteractMenu.py +++ b/empire/client/src/menus/InteractMenu.py @@ -503,7 +503,6 @@ def execute_shortcut(self, command_name: str, params: List[str]): try: file_directory = post_body.get("options")["File"] filename = file_directory.split("/")[-1] - post_body.get("options")["File"] = filename data = get_data_from_file(file_directory) except Exception: log.error("Invalid filename or file does not exist") @@ -511,6 +510,7 @@ def execute_shortcut(self, command_name: str, params: List[str]): response = state.upload_file(filename, data) if "id" in response.keys(): log.info("File uploaded to server successfully") + post_body.get("options")["File"] = response["id"] elif "detail" in response.keys(): if response["detail"].startswith("[!]"): msg = response["detail"] diff --git a/empire/client/src/menus/UseModuleMenu.py b/empire/client/src/menus/UseModuleMenu.py index dc584c6eb..120246e2e 100644 --- a/empire/client/src/menus/UseModuleMenu.py +++ b/empire/client/src/menus/UseModuleMenu.py @@ -83,7 +83,6 @@ def execute(self): try: file_directory = self.record_options["File"]["value"] filename = file_directory.split("/")[-1] - self.record_options["File"]["value"] = filename data = get_data_from_file(file_directory) except Exception: log.error("Invalid filename or file does not exist") @@ -91,6 +90,7 @@ def execute(self): response = state.upload_file(filename, data) if "id" in response.keys(): log.info("File uploaded to server successfully") + self.record_options["File"]["value"] = response["id"] elif "detail" in response.keys(): if response["detail"].startswith("[!]"): From 4f7cde0041a59da9d3042892ebad67d9054ec186 Mon Sep 17 00:00:00 2001 From: Anthony Rose <20302208+Cx01N@users.noreply.github.com> Date: Thu, 18 May 2023 17:20:04 -0400 Subject: [PATCH 05/20] generate_comms fix for dbx (#611) --- empire/server/listeners/dbx.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/empire/server/listeners/dbx.py b/empire/server/listeners/dbx.py index d5448d710..e348072b3 100755 --- a/empire/server/listeners/dbx.py +++ b/empire/server/listeners/dbx.py @@ -581,7 +581,7 @@ def generate_comms(self, listenerOptions, language=None): This is so agents can easily be dynamically updated for the new listener. """ baseFolder = listenerOptions["BaseFolder"]["Value"].strip("/") - api_token = listenerOptions["API_TOKEN"]["Value"] + api_token = listenerOptions["APIToken"]["Value"] taskingsFolder = "/%s/%s" % ( baseFolder, From eb9fa6f660ec65598e11590f9748dc2b2edf8011 Mon Sep 17 00:00:00 2001 From: Vincent Rose Date: Sun, 21 May 2023 22:56:13 -0700 Subject: [PATCH 06/20] Remove starkiller submodule (#595) * remove starkiller submodule * ignore starkiller dir * Remove starkiller as a submodule * fix auto update * update sync script --- .gitignore | 1 + .gitmodules | 3 -- CHANGELOG.md | 3 ++ empire/scripts/sync_starkiller.py | 63 +++++++++++----------------- empire/server/api/app.py | 18 ++------ empire/server/api/v2/starkiller | 1 - empire/server/config.yaml | 5 +-- empire/server/core/config.py | 2 +- empire/server/core/plugin_service.py | 2 +- 9 files changed, 34 insertions(+), 64 deletions(-) delete mode 160000 empire/server/api/v2/starkiller diff --git a/.gitignore b/.gitignore index c60473c3d..a5adf9bae 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ empire/server/data/generated-stagers/* empire/server/downloads/* empire/server/api/static/* empire/server/api/v2/starkiller-temp +empire/server/api/v2/starkiller # client empire/client/generated-stagers/* diff --git a/.gitmodules b/.gitmodules index 660094935..e4aeea038 100644 --- a/.gitmodules +++ b/.gitmodules @@ -46,9 +46,6 @@ [submodule "empire/server/csharp/Covenant/Data/ReferenceSourceLibraries/DotNetStratumMiner"] path = empire/server/csharp/Covenant/Data/ReferenceSourceLibraries/DotNetStratumMiner url = https://github.com/BC-SECURITY/DotNetStratumMiner.git -[submodule "empire/server/api/v2/starkiller"] - path = empire/server/api/v2/starkiller - url = git@github.com:BC-SECURITY/Starkiller-Sponsors.git [submodule "empire/server/csharp/Covenant/Data/ReferenceSourceLibraries/RunOF"] path = empire/server/csharp/Covenant/Data/ReferenceSourceLibraries/RunOF url = https://github.com/BC-SECURITY/RunOF.git diff --git a/CHANGELOG.md b/CHANGELOG.md index 8fea4ff63..b2fa97723 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +- Remove Starkiller as a submodule, treat it as a normal directory (@Vinnybod) + - Everything should 'just work', but if you have issues after pulling these latest changes, try deleting the Starkiller directory before running the server `rm -r empire/server/api/v2/starkiller`. + ## [5.3.0] - 2023-05-17 - Add the ability to specify a module option as a file (@Vinnybod) diff --git a/empire/scripts/sync_starkiller.py b/empire/scripts/sync_starkiller.py index 1dfa0e1c1..faa9f4e07 100644 --- a/empire/scripts/sync_starkiller.py +++ b/empire/scripts/sync_starkiller.py @@ -1,60 +1,45 @@ import logging -import os import subprocess +from pathlib import Path +from typing import Dict log = logging.getLogger(__name__) def sync_starkiller(empire_config): """ - Syncs the starkiller submodule with what is in the config. - Using dict acccess because this script should be able to run with minimal packages, not just within empire. + Syncs the starkiller directory with what is in the config. + Using dict access because this script should be able to run with minimal packages, + not just within empire server. """ starkiller_config = empire_config["starkiller"] - starkiller_submodule_dir = "empire/server/api/v2/starkiller" - starkiller_temp_dir = "empire/server/api/v2/starkiller-temp" + starkiller_dir = starkiller_config["directory"] - subprocess.run(["git", "submodule", "update", "--init", "--recursive"], check=True) + if not Path(starkiller_dir).exists(): + log.info("Starkiller: directory not found. Cloning Starkiller") + _clone_starkiller(starkiller_config, starkiller_dir) - if not starkiller_config["use_temp_dir"]: - log.info("Syncing starkiller submodule to match config.yaml") - subprocess.run( - [ - "git", - "submodule", - "set-url", - "--", - starkiller_submodule_dir, - starkiller_config["repo"], - ], - check=True, + if starkiller_config.get("auto_update"): + log.info("Starkiller: Autoupdate on. Pulling latest ref.") + _fetch_checkout_pull( + starkiller_config["repo"], starkiller_config["ref"], starkiller_dir ) - subprocess.run( - ["git", "submodule", "sync", "--", starkiller_submodule_dir], check=True - ) - - _fetch_checkout_pull(starkiller_config["ref"], starkiller_submodule_dir) - else: - if not os.path.exists(starkiller_temp_dir): - log.info("Cloning starkiller to temp dir") - subprocess.run( - ["git", "clone", starkiller_config["repo"], starkiller_temp_dir], - check=True, - ) - else: - log.info("Updating starkiller temp dir") - subprocess.run( - ["git", "remote", "set-url", "origin", starkiller_config["repo"]], - cwd=starkiller_temp_dir, - check=True, - ) +def _clone_starkiller(starkiller_config: Dict, starkiller_dir: str): + subprocess.run( + ["git", "clone", starkiller_config["repo"], starkiller_dir], + check=True, + ) - _fetch_checkout_pull(starkiller_config["ref"], starkiller_temp_dir) +def _fetch_checkout_pull(remote_repo, ref, cwd): + subprocess.run( + ["git", "remote", "set-url", "origin", remote_repo], + cwd=cwd, + check=True, + ) -def _fetch_checkout_pull(ref, cwd): subprocess.run(["git", "fetch"], cwd=cwd, check=True) subprocess.run( ["git", "checkout", ref], diff --git a/empire/server/api/app.py b/empire/server/api/app.py index d1d5e3693..e578e14d2 100644 --- a/empire/server/api/app.py +++ b/empire/server/api/app.py @@ -3,7 +3,6 @@ import os from datetime import datetime from json import JSONEncoder -from pathlib import Path import socketio import uvicorn @@ -44,22 +43,11 @@ def default(self, o): def load_starkiller(v2App): - use_temp = empire_config.starkiller.use_temp_dir - starkiller_submodule_dir = "empire/server/api/v2/starkiller" - starkiller_temp_dir = "empire/server/api/v2/starkiller-temp" - - if ( - Path(starkiller_submodule_dir) / ".git" - ).exists() and empire_config.starkiller.auto_update: - sync_starkiller(empire_config.dict()) + sync_starkiller(empire_config.dict()) v2App.mount( "/", - StaticFiles( - directory=f"{starkiller_temp_dir}/dist" - if use_temp - else f"{starkiller_submodule_dir}/dist" - ), + StaticFiles(directory=f"{empire_config.starkiller.directory}/dist"), name="static", ) @@ -147,7 +135,7 @@ def shutdown_event(): load_starkiller(v2App) log.info(f"Starkiller served at http://localhost:{port}/index.html") except Exception as e: - log.warning("Failed to load Starkiller: %s", e) + log.warning("Failed to load Starkiller: %s", e, exc_info=True) pass cert_path = os.path.abspath("./empire/server/data/") diff --git a/empire/server/api/v2/starkiller b/empire/server/api/v2/starkiller deleted file mode 160000 index d7ecadf58..000000000 --- a/empire/server/api/v2/starkiller +++ /dev/null @@ -1 +0,0 @@ -Subproject commit d7ecadf587b76ce4995cfbf73e5ecd283ca7b8c9 diff --git a/empire/server/config.yaml b/empire/server/config.yaml index f0d1d7616..a6ddcf2b8 100644 --- a/empire/server/config.yaml +++ b/empire/server/config.yaml @@ -36,12 +36,9 @@ database: ip-blacklist: "" starkiller: repo: git@github.com:BC-SECURITY/Starkiller-Sponsors.git + directory: empire/server/api/v2/starkiller # Can be a branch, tag, or commit hash ref: sponsors-main - # for private-main, instead of updating the submodule, just work out of a local copy. - # So devs can work off the latest changes and not worry about accidentally updating the submodule - # for the downstream main branches. - use_temp_dir: false auto_update: true plugins: # Auto-load plugin with defined settings diff --git a/empire/server/core/config.py b/empire/server/core/config.py index 8271eb1a2..8d0986449 100644 --- a/empire/server/core/config.py +++ b/empire/server/core/config.py @@ -10,8 +10,8 @@ class StarkillerConfig(BaseModel): repo: str = "bc-security/starkiller" + directory: str = "empire/server/api/v2/starkiller" ref: str = "main" - use_temp_dir: bool = False auto_update: bool = True diff --git a/empire/server/core/plugin_service.py b/empire/server/core/plugin_service.py index 5080d57ff..4f4f60bf0 100644 --- a/empire/server/core/plugin_service.py +++ b/empire/server/core/plugin_service.py @@ -122,7 +122,7 @@ def execute_plugin( return plugin.execute(cleaned_options, db=db, user=user), None except TypeError: log.warning( - "Plugin does not support db session or user_id, falling back to old method" + f"Plugin {plugin.info.get('Name')} does not support db session or user_id, falling back to old method" ) try: From 6f3b89cb961acec6e2bd8d09f3b537457fc1b36c Mon Sep 17 00:00:00 2001 From: Vincent Rose Date: Sun, 21 May 2023 23:00:06 -0700 Subject: [PATCH 07/20] Release flow improvements (#597) * Some improvements to the release flow after starkiller submodule removal * use changelog-path * remove todos * combine sponsors changelog for release notes * update docs * update readme * add commit to sponsors changelog --- .github/actions/update-starkiller/action.yml | 31 ++------- .github/ci-and-release.md | 15 +++-- .../workflows/release-sponsor-kali-start.yml | 65 ++++--------------- .../workflows/release-sponsor-kali-tag.yml | 12 +++- CHANGELOG.md | 3 +- 5 files changed, 40 insertions(+), 86 deletions(-) diff --git a/.github/actions/update-starkiller/action.yml b/.github/actions/update-starkiller/action.yml index 700b72406..60470a1ec 100644 --- a/.github/actions/update-starkiller/action.yml +++ b/.github/actions/update-starkiller/action.yml @@ -1,8 +1,8 @@ name: 'Update Starkiller' -description: 'Updates the config.yaml and starkiller submodule to the specified version and commits the change.' +description: 'Updates the config.yaml to the specified version and commits the change.' inputs: starkiller-version: - description: 'The branch to merge from' + description: 'The starkiller ref to use' required: true app-version: description: 'The changelog section to update' @@ -10,16 +10,12 @@ inputs: repo: description: "The starkiller repo to use. If not set, doesn't update the field." required: false + changelog-path: + description: "The changelog path" + default: CHANGELOG.md runs: using: "composite" steps: - - name: Install Python - uses: actions/setup-python@v2 - with: - python-version: '3.9' - - name: Install minimal python packages - shell: bash - run: python -m pip install pyyaml # This is technically only needed for the first time we update the public repo, as a bootstrap. # After that, the submodule is already initialized to the right repo. - name: Update config.yaml repo @@ -29,28 +25,15 @@ runs: sed -i "s|repo:.*|repo: ${{ inputs.repo }}|" empire/server/config.yaml - name: Update config.yaml ref shell: bash - # this depends on there not being any other keys in teh config named ref + # this depends on there not being any other keys in the config named ref # if there are, this will break. We could be safer to load/dump the yaml, # but would lose the comments. run: | sed -i "s/ref: .*/ref: ${{ inputs.starkiller-version }}/" empire/server/config.yaml - # If use_temp_dir is true, Starkiller is cloned into a temp directory, the CI will fail, - # and the submodule will not be updated. So set it to false, make the changes, then set it back. - - name: Update config.yaml use_temp_dir - shell: bash - run: | - sed -i'.bak' "s/use_temp_dir: .*/use_temp_dir: false/" empire/server/config.yaml - - name: Run starkiller update script - shell: bash - run: python empire.py sync-starkiller - - name: Reset use_tmp_dir - shell: bash - run: | - mv empire/server/config.yaml.bak empire/server/config.yaml - name: Update changelog shell: bash run: | - sed -i '/## \[${{ inputs.app-version }}\]/a - Updated Starkiller to ${{ inputs.starkiller-version }}' CHANGELOG.md + sed -i '/## \[${{ inputs.app-version }}\]/a - Updated Starkiller to ${{ inputs.starkiller-version }}' ${{ inputs.changelog-path }} - name: Commit changes shell: bash run: | diff --git a/.github/ci-and-release.md b/.github/ci-and-release.md index e09ca2440..3858b3f93 100644 --- a/.github/ci-and-release.md +++ b/.github/ci-and-release.md @@ -121,23 +121,24 @@ the `private-main` branch. Once the `release/` pull request is merged, the `Private - Tag Release` workflow will automatically run. The workflow will create a tag and release on the `HEAD` of `private-main` using the release notes from `CHANGELOG.md` for the body of the release. -### 6. Start Sponsor/Kali Release +### 6. Repeat Step 2 - Prerelease Merge +Repeat step 2 to merge `private-main` into `sponsors-main` and `kali-main`. + +### 7. Start Sponsor/Kali Release Start the release by running the `Sponsors & Kali - Create Release` manual workflow. If starkiller needs to be updated, provide a `starkillerVersion` input. The value provided should be a git tag minus the `-kali` or `-sponsors` suffix. -This will first attempt to merge the `private-main` branch into `sponsors-main` and `kali-main` with the new release changes. Most likely, if there is a merge conflict here it is caused by `CHANGELOG.md` and should be minor. If that occurs, the merge conflict can be resolved in the pull request via the GitHub editor, or locally. - -If a Starkiller tag was provided, it will update the Starkiller submodule and the changelog accordingly. It does this on the `sponsors-main` and `kali-main` release branches separately. +If a Starkiller tag was provided, it will update the Starkiller config and the changelog accordingly. A release PR will then be opened for each branch and the test suite will run. -#### 7. Manual Step - Merge sponsor/kali release PRs +#### 8. Manual Step - Merge sponsor/kali release PRs Once the workflow runs, it will open two pull requests from the `release/v{version}-sponsors` and `release/v{version}-kali` branches to `sponsors-main` and `kali-main` respectively. Check the changelog on these branches, this will be the changelog that is used for the release notes. -If there are sponsor/kali specific changelog entries that need to be added, add them to the `CHANGELOG.md` file on the release branch. +If there are sponsor specific changelog entries that need to be added, add them to the `CHANGELOG-SPONSORS.md` file on the release branch. You can get a list of the new commits that are in this release by using the following command. Replace `v4.9.0-sponsors` with whatever the previous release was. ``` @@ -151,7 +152,7 @@ the `sponsors-main` branch or `kali-main` branch. **Potential Enhancement** We could add automation that copies the `unreleased` section from the target branch to the version section in the `head` branch. -### 7. Tag and Release +### 9. Tag and Release Once the pull requests are merged, the `Sponsors - Tag Release` and `Kali - Tag Release` workflows will automatically run. The workflows will create a tag and release on the `HEAD` of `sponsors-main` and `kali-main`, using the release notes from `CHANGELOG.md` for the body of the release. diff --git a/.github/workflows/release-sponsor-kali-start.yml b/.github/workflows/release-sponsor-kali-start.yml index c3ede73c7..d24afa9cc 100644 --- a/.github/workflows/release-sponsor-kali-start.yml +++ b/.github/workflows/release-sponsor-kali-start.yml @@ -19,7 +19,7 @@ jobs: - name: Check out code uses: actions/checkout@v3 with: - ref: private-main + ref: sponsors-main submodules: 'recursive' fetch-depth: 0 token: ${{ secrets.RELEASE_TOKEN }} @@ -37,61 +37,22 @@ jobs: with: starkiller-version: ${{ env.STARKILLER_TAG }} app-version: ${{ env.APP_VERSION }} - - name: Get release branch name - run: | - echo "RELEASE_BRANCH=release/$APP_VERSION-sponsors" >> $GITHUB_ENV - - name: Create release branch - run: git checkout -b ${{ env.RELEASE_BRANCH }} - - name: Push new branch - run: git push origin ${{ env.RELEASE_BRANCH }} - - name: Create pull request into ${{ env.TARGET_BRANCH }} - uses: thomaseizinger/create-pull-request@1.0.0 + changelog-path: CHANGELOG-SPONSORS.md + - name: Update Sponsors Changelog + uses: vinnybod/keep-a-changelog-new-release@1.4.0 with: - GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }} - head: ${{ env.RELEASE_BRANCH }} - base: ${{ env.TARGET_BRANCH }} - title: v${{ env.APP_VERSION }} into ${{ env.TARGET_BRANCH }} - reviewers: ${{ github.event.issue.user.login }} - body: | - This PR was automatically generated by the `release-sponsor-kali-start` workflow. - I've updated the version name and code commit: ${{ steps.make-commit.outputs.commit }}. - This PR should be merged with a merge commit, **not a squash commit.** - Merging this PR will trigger a tag and release automatically. - # this is basically copy/paste from the above. - create_kali: - # disable for now. - if: false -# if: ${{ github.repository == 'BC-Security/Empire-Sponsors' }} - runs-on: ubuntu-latest - steps: - - name: Set env vars + tag: v${{ env.APP_VERSION }} + changelogPath: CHANGELOG-SPONSORS.md + skipDiff: false + - name: Commit changelog and manifest files + id: make-commit run: | - echo "TARGET_BRANCH=kali-main" >> $GITHUB_ENV - echo "STARKILLER_TAG=${{ github.event.inputs.starkillerVersion }}-kali" >> $GITHUB_ENV - - name: Check out code - uses: actions/checkout@v3 - with: - ref: private-main - submodules: 'recursive' - fetch-depth: 0 - token: ${{ secrets.RELEASE_TOKEN }} - - name: Initialize mandatory git config - run: | - git config user.name "GitHub Actions" - git config user.email noreply@github.com - - name: Get app version - run: | - # Get the version from pyproject.toml using sed - echo "APP_VERSION=$(sed -n 's/^version = "\(.*\)"/\1/p' pyproject.toml)" >> $GITHUB_ENV - - name: Update Starkiller Version - if: ${{ github.event.inputs.starkillerVersion }} - uses: ./.github/actions/update-starkiller - with: - starkiller-version: ${{ env.STARKILLER_TAG }} - app-version: ${{ env.APP_VERSION }} + git add -A + git commit --message "Prepare release ${{ env.APP_VERSION }} sponsors" + echo "commit=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT - name: Get release branch name run: | - echo "RELEASE_BRANCH=release/$APP_VERSION-kali" >> $GITHUB_ENV + echo "RELEASE_BRANCH=release/$APP_VERSION-sponsors" >> $GITHUB_ENV - name: Create release branch run: git checkout -b ${{ env.RELEASE_BRANCH }} - name: Push new branch diff --git a/.github/workflows/release-sponsor-kali-tag.yml b/.github/workflows/release-sponsor-kali-tag.yml index c95225d88..d7f7255ea 100644 --- a/.github/workflows/release-sponsor-kali-tag.yml +++ b/.github/workflows/release-sponsor-kali-tag.yml @@ -5,7 +5,6 @@ on: - closed branches: - sponsors-main -# - kali-main jobs: tag_release: @@ -27,6 +26,11 @@ jobs: - name: Extract release notes id: extract_release_notes uses: vinnybod/extract-release-notes@v2 + - name: Extract release notes - sponsors + id: extract_release_notes_sponsors + uses: vinnybod/extract-release-notes@v2 + with: + changelog_file: CHANGELOG-SPONSORS.md - name: Create Release id: create_release uses: actions/create-release@v1 @@ -35,6 +39,10 @@ jobs: with: tag_name: v${{ env.TAG_NAME }} release_name: v${{ env.TAG_NAME }} - body: ${{ steps.extract_release_notes.outputs.release_notes }} + body: | + ${{ steps.extract_release_notes.outputs.release_notes }} + + ### Sponsors Only + ${{ steps.extract_release_notes_sponsors.outputs.release_notes }} draft: false prerelease: false diff --git a/CHANGELOG.md b/CHANGELOG.md index b2fa97723..c1cbc55ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Remove Starkiller as a submodule, treat it as a normal directory (@Vinnybod) - Everything should 'just work', but if you have issues after pulling these latest changes, try deleting the Starkiller directory before running the server `rm -r empire/server/api/v2/starkiller`. - +- Some improvements to the release flow after starkiller submodule removal (@Vinnybod) +- ## [5.3.0] - 2023-05-17 - Add the ability to specify a module option as a file (@Vinnybod) From 2f8fb4be90dcf0856de1c5d2056601e05e9c71aa Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Mon, 22 May 2023 06:03:28 +0000 Subject: [PATCH 08/20] Prepare release 5.4.0 private --- CHANGELOG.md | 11 ++++++++--- empire/server/common/empire.py | 2 +- pyproject.toml | 2 +- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c1cbc55ba..f037ba3a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,10 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [5.4.0] - 2023-05-22 + - Remove Starkiller as a submodule, treat it as a normal directory (@Vinnybod) - - Everything should 'just work', but if you have issues after pulling these latest changes, try deleting the Starkiller directory before running the server `rm -r empire/server/api/v2/starkiller`. + - Everything should 'just work', but if you have issues after pulling these latest changes, try deleting the Starkiller directory before running the server `rm -r empire/server/api/v2/starkiller`. - Some improvements to the release flow after starkiller submodule removal (@Vinnybod) -- +- + ## [5.3.0] - 2023-05-17 - Add the ability to specify a module option as a file (@Vinnybod) @@ -472,7 +475,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Updated shellcoderdi to newest version (@Cx01N) - Added a Nim launcher (@Hubbl3) -[Unreleased]: https://github.com/BC-SECURITY/Empire-Sponsors/compare/v5.3.0...HEAD +[Unreleased]: https://github.com/BC-SECURITY/Empire-Sponsors/compare/v5.4.0...HEAD + +[5.4.0]: https://github.com/BC-SECURITY/Empire-Sponsors/compare/v5.3.0...v5.4.0 [5.3.0]: https://github.com/BC-SECURITY/Empire-Sponsors/compare/v5.2.2...v5.3.0 diff --git a/empire/server/common/empire.py b/empire/server/common/empire.py index 0eefbee32..b5bbeb312 100755 --- a/empire/server/common/empire.py +++ b/empire/server/common/empire.py @@ -39,7 +39,7 @@ from . import agents, credentials, listeners, stagers -VERSION = "5.3.0 BC Security Fork" +VERSION = "5.4.0 BC Security Fork" log = logging.getLogger(__name__) diff --git a/pyproject.toml b/pyproject.toml index 7ad6129f5..3503623cb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "empire-bc-security-fork" -version = "5.3.0" +version = "5.4.0" description = "" authors = ["BC Security "] readme = "README.md" From c224b4f9e20201a328042313e7f1f044a2720ec5 Mon Sep 17 00:00:00 2001 From: Vincent Rose Date: Sun, 21 May 2023 23:04:25 -0700 Subject: [PATCH 09/20] Update CHANGELOG.md --- CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f037ba3a0..787d4206c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Remove Starkiller as a submodule, treat it as a normal directory (@Vinnybod) - Everything should 'just work', but if you have issues after pulling these latest changes, try deleting the Starkiller directory before running the server `rm -r empire/server/api/v2/starkiller`. - Some improvements to the release flow after starkiller submodule removal (@Vinnybod) -- ## [5.3.0] - 2023-05-17 From 29d0bef1895624109edad4ddce7b66801e62a0e6 Mon Sep 17 00:00:00 2001 From: Vincent Rose Date: Wed, 24 May 2023 21:03:46 -0700 Subject: [PATCH 10/20] fix db reset issue for mysql (#614) --- CHANGELOG.md | 2 ++ empire/server/core/db/base.py | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 787d4206c..7b8ae6627 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +- Fix database reset issue with MySQL (@Vinnybod) + ## [5.4.0] - 2023-05-22 - Remove Starkiller as a submodule, treat it as a normal directory (@Vinnybod) diff --git a/empire/server/core/db/base.py b/empire/server/core/db/base.py index c4f0f7fe8..f112084ad 100644 --- a/empire/server/core/db/base.py +++ b/empire/server/core/db/base.py @@ -45,8 +45,15 @@ def try_create_engine(engine_url: str, *args, **kwargs) -> Engine: def reset_db(): + if use == "mysql": + cmd = f"DROP DATABASE IF EXISTS {database_config.database_name}" + reset_engine = try_create_engine(mysql_url, echo=False) + with reset_engine.connect() as connection: + connection.execute(text(cmd)) + SessionLocal.close_all() Base.metadata.drop_all(engine) + if use == "sqlite": os.unlink(database_config.location) From d836e9068f386b89bf357e6b8dfa8ec294b7fea3 Mon Sep 17 00:00:00 2001 From: Vincent Rose Date: Tue, 30 May 2023 22:10:58 -0700 Subject: [PATCH 11/20] Recommend starkiller in the client (#616) --- CHANGELOG.md | 1 + empire/client/src/EmpireCliState.py | 7 +++++-- empire/client/src/utils/print_util.py | 6 ++++-- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b8ae6627..4ab9feaf5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] - Fix database reset issue with MySQL (@Vinnybod) +- Add a message to the client recommending the use of the Starkiller (@Vinnybod) ## [5.4.0] - 2023-05-22 diff --git a/empire/client/src/EmpireCliState.py b/empire/client/src/EmpireCliState.py index 3c0e9959b..2d1baac56 100644 --- a/empire/client/src/EmpireCliState.py +++ b/empire/client/src/EmpireCliState.py @@ -78,9 +78,11 @@ def notify_disconnected(self): def connect(self, host, port, socketport, username, password): self.host = host self.port = port + server = f"{host}:{port}" + try: response = requests.post( - url=f"{host}:{port}/token", + url=f"{server}/token", data={"username": username, "password": password}, verify=False, ) @@ -92,7 +94,7 @@ def connect(self, host, port, socketport, username, password): self.connected = True self.sio = socketio.Client(ssl_verify=False, reconnection_attempts=3) - self.sio.connect(f"{host}:{port}/socket.io/", auth={"token": self.token}) + self.sio.connect(f"{server}/socket.io/", auth={"token": self.token}) # Wait for version to be returned self.empire_version = self.get_version()["version"] @@ -102,6 +104,7 @@ def connect(self, host, port, socketport, username, password): self.notify_connected() print_util.title( self.empire_version, + server, len(self.modules), len(self.listeners), len(self.active_agents), diff --git a/empire/client/src/utils/print_util.py b/empire/client/src/utils/print_util.py index 5b7cf53ea..deb802743 100644 --- a/empire/client/src/utils/print_util.py +++ b/empire/client/src/utils/print_util.py @@ -51,7 +51,7 @@ def color(string_name, color_name=None): return string_name -def title(version, modules, listeners, agents): +def title(version, server, modules, listeners, agents): """ Print the tool title, with version. """ @@ -71,7 +71,7 @@ def title(version, modules, listeners, agents): "========================================================================================" ) print( - " [\x1b[1;32mStarkiller\x1b[0m] Multi-User GUI | [Web] https://github.com/BC-SECURITY/Starkiller" + " [\x1b[1;32mStarkiller\x1b[0m] Web UI | [Web] https://github.com/BC-SECURITY/Starkiller" ) print( "========================================================================================" @@ -103,6 +103,8 @@ def title(version, modules, listeners, agents): print("") print(" " + color(str(agents), "green") + " agents currently active") print("") + print(color("Starkiller is now the recommended way to use Empire.", "green")) + print(color(f"Try it out at {server}/index.html", "green")) def loading(): From 7f7e78ca3f4b0489850e5ac8da680698abf23fd8 Mon Sep 17 00:00:00 2001 From: Vincent Rose Date: Wed, 31 May 2023 23:12:50 -0700 Subject: [PATCH 12/20] Use fewer ci minutes (#619) * run fewer python versions and skip sqlite for pr builds * unstashed * Update lint-and-test.yml * Update lint-and-test.yml * Update lint-and-test.yml * Update lint-and-test.yml * Update lint-and-test.yml * add missing property * Update lint-and-test.yml * test fix config * remove debug --- .github/workflows/lint-and-test.yml | 23 +++++++++++++++++++---- CHANGELOG.md | 1 + 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/.github/workflows/lint-and-test.yml b/.github/workflows/lint-and-test.yml index 7b2307fd1..42182dffc 100644 --- a/.github/workflows/lint-and-test.yml +++ b/.github/workflows/lint-and-test.yml @@ -20,14 +20,28 @@ jobs: run: | pip install ruff ruff . + matrix-prep-config: + runs-on: ubuntu-latest + steps: + - id: release + if: ${{ startsWith(github.head_ref, 'release/') || contains( github.event.pull_request.labels.*.name, 'run-all-versions') }} + run: | + echo "config={\"python-version\": [\"3.8\", \"3.9\", \"3.10\", \"3.11\"]}" >> $GITHUB_OUTPUT + - id: not-release + if: ${{ !startsWith(github.head_ref, 'release/') }} + run: | + echo "config={\"python-version\": [\"3.8\", \"3.11\"]}" >> $GITHUB_OUTPUT + outputs: + config: ${{ steps.release.outputs.config || steps.not-release.outputs.config }} test: - needs: lint + needs: + - matrix-prep-config + - lint timeout-minutes: 15 runs-on: ubuntu-latest name: Test Python ${{ matrix.python-version }} strategy: - matrix: - python-version: [ '3.8', '3.9', '3.10', '3.11' ] + matrix: ${{ fromJson(needs.matrix-prep-config.outputs.config) }} steps: - uses: actions/checkout@v3 if: ${{ github.repository == 'BC-SECURITY/Empire' }} @@ -64,6 +78,7 @@ jobs: run: | DATABASE_USE=mysql poetry run pytest . -v - name: Run test suite - sqlite + if: ${{ startsWith(github.head_ref, 'release/') || contains(github.event.pull_request.labels.*.name, 'test-sqlite') }} run: | DATABASE_USE=sqlite poetry run pytest . -v @@ -181,4 +196,4 @@ jobs: uses: plexsystems/container-structure-test-action@v0.1.0 with: image: docker.io/bcsecurity/empire-test-parrotrolling:latest - config: .github/install_tests/cst-config-parrotrolling.yaml \ No newline at end of file + config: .github/install_tests/cst-config-parrotrolling.yaml diff --git a/CHANGELOG.md b/CHANGELOG.md index 4ab9feaf5..eeec96f59 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fix database reset issue with MySQL (@Vinnybod) - Add a message to the client recommending the use of the Starkiller (@Vinnybod) +- Pair down the amount of minutes needed to run pull request builds (@Vinnybod) ## [5.4.0] - 2023-05-22 From 8f366b7678ba08ae99292fac44f51d7568b30477 Mon Sep 17 00:00:00 2001 From: Anthony Rose <20302208+Cx01N@users.noreply.github.com> Date: Thu, 1 Jun 2023 12:57:23 -0400 Subject: [PATCH 13/20] Fixed dynamic function issue with Powerview (#617) * Fixed dynamic function issue with powerview * fixed naming issue * updated changelog * added test for dynamic functions * moved test to helpers.py --------- Co-authored-by: Vincent Rose --- CHANGELOG.md | 1 + empire/server/common/helpers.py | 9 ++++++--- .../situational_awareness/network/powerview.ps1 | 2 +- empire/test/test_helpers.py | 13 +++++++++++++ 4 files changed, 21 insertions(+), 4 deletions(-) create mode 100644 empire/test/test_helpers.py diff --git a/CHANGELOG.md b/CHANGELOG.md index eeec96f59..e6a8d6228 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fix database reset issue with MySQL (@Vinnybod) - Add a message to the client recommending the use of the Starkiller (@Vinnybod) +- Fixed dynamic function issue with Powerview (@Cx01N) - Pair down the amount of minutes needed to run pull request builds (@Vinnybod) ## [5.4.0] - 2023-05-22 diff --git a/empire/server/common/helpers.py b/empire/server/common/helpers.py index 55b0853e0..f1d0ed7f0 100644 --- a/empire/server/common/helpers.py +++ b/empire/server/common/helpers.py @@ -349,9 +349,10 @@ def generate_dynamic_powershell_script(script, function_names): functions = {} pattern = re.compile(r"\n(?:function|filter).*?{.*?\n}\n", re.DOTALL) - for match in pattern.findall(script): - name = match[:40].split()[1] - functions[name] = strip_powershell_comments(match) + script = re.sub(re.compile("<#.*?#>", re.DOTALL), "", script) + for func_match in pattern.findall(script): + name = func_match[:40].split()[1] + functions[name] = func_match # recursively enumerate all possible function dependencies and # start building the new result script @@ -373,6 +374,8 @@ def generate_dynamic_powershell_script(script, function_names): if any(el in set(psreflect_functions) for el in function_dependencies): new_script += get_powerview_psreflect_overhead(script) + new_script = strip_powershell_comments(new_script) + return new_script + "\n" diff --git a/empire/server/data/module_source/situational_awareness/network/powerview.ps1 b/empire/server/data/module_source/situational_awareness/network/powerview.ps1 index 87ca61c0a..b7a11b7a5 100644 --- a/empire/server/data/module_source/situational_awareness/network/powerview.ps1 +++ b/empire/server/data/module_source/situational_awareness/network/powerview.ps1 @@ -731,7 +731,7 @@ New-Struct. :P # ######################################################## -Function New-DynamicParameter { +function New-DynamicParameter { <# .SYNOPSIS diff --git a/empire/test/test_helpers.py b/empire/test/test_helpers.py new file mode 100644 index 000000000..91fbf6f9c --- /dev/null +++ b/empire/test/test_helpers.py @@ -0,0 +1,13 @@ +from empire.server.common import helpers + + +def test_dynamic_powershell(): + with open( + "empire/server/data/module_source/situational_awareness/network/powerview.ps1", + "r", + ) as file: + script = file.read() + new_script = helpers.generate_dynamic_powershell_script( + script, "Find-LocalAdminAccess" + ) + assert len(new_script) == 96681 From 761c580103c6e8b8258346c93719f0ad9a385286 Mon Sep 17 00:00:00 2001 From: Anthony Rose <20302208+Cx01N@users.noreply.github.com> Date: Thu, 1 Jun 2023 15:58:26 -0400 Subject: [PATCH 14/20] fixed issue with invoke-wmi not returning success message (#620) Co-authored-by: Vincent Rose --- CHANGELOG.md | 1 + empire/server/modules/powershell/lateral_movement/invoke_wmi.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e6a8d6228..d18ca5734 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fix database reset issue with MySQL (@Vinnybod) - Add a message to the client recommending the use of the Starkiller (@Vinnybod) +- Fixed issue with Invoke-wmi not returning a success message (@Cx01N) - Fixed dynamic function issue with Powerview (@Cx01N) - Pair down the amount of minutes needed to run pull request builds (@Vinnybod) diff --git a/empire/server/modules/powershell/lateral_movement/invoke_wmi.py b/empire/server/modules/powershell/lateral_movement/invoke_wmi.py index 46c62f3e1..594d95a43 100644 --- a/empire/server/modules/powershell/lateral_movement/invoke_wmi.py +++ b/empire/server/modules/powershell/lateral_movement/invoke_wmi.py @@ -101,7 +101,7 @@ def generate( + " -Credential $Credential" ) - script += ";'Invoke-Wmi executed on " + computer_names + "'" + script += ";'Invoke-Wmi executed on " + computer_names + "'" script = main_menu.modulesv2.finalize_module( script=script, From 35af0e6c750a61bd91e76743cc479dc2136e30a5 Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Fri, 2 Jun 2023 03:55:02 +0000 Subject: [PATCH 15/20] Prepare release 5.4.1 private --- CHANGELOG.md | 6 +++++- empire/server/common/empire.py | 2 +- pyproject.toml | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d18ca5734..876b288ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [5.4.1] - 2023-06-02 + - Fix database reset issue with MySQL (@Vinnybod) - Add a message to the client recommending the use of the Starkiller (@Vinnybod) - Fixed issue with Invoke-wmi not returning a success message (@Cx01N) @@ -480,7 +482,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Updated shellcoderdi to newest version (@Cx01N) - Added a Nim launcher (@Hubbl3) -[Unreleased]: https://github.com/BC-SECURITY/Empire-Sponsors/compare/v5.4.0...HEAD +[Unreleased]: https://github.com/BC-SECURITY/Empire-Sponsors/compare/v5.4.1...HEAD + +[5.4.1]: https://github.com/BC-SECURITY/Empire-Sponsors/compare/v5.4.0...v5.4.1 [5.4.0]: https://github.com/BC-SECURITY/Empire-Sponsors/compare/v5.3.0...v5.4.0 diff --git a/empire/server/common/empire.py b/empire/server/common/empire.py index b5bbeb312..c9db8da3b 100755 --- a/empire/server/common/empire.py +++ b/empire/server/common/empire.py @@ -39,7 +39,7 @@ from . import agents, credentials, listeners, stagers -VERSION = "5.4.0 BC Security Fork" +VERSION = "5.4.1 BC Security Fork" log = logging.getLogger(__name__) diff --git a/pyproject.toml b/pyproject.toml index 3503623cb..d59a99c7a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "empire-bc-security-fork" -version = "5.4.0" +version = "5.4.1" description = "" authors = ["BC Security "] readme = "README.md" From e465100e20abfd94d8b60d62a6f8e419bc839e45 Mon Sep 17 00:00:00 2001 From: Anthony Rose <20302208+Cx01N@users.noreply.github.com> Date: Sun, 4 Jun 2023 10:45:41 -0400 Subject: [PATCH 16/20] Fixed tasking to python agent (#625) * fixed tasking to python agent * changelog --- CHANGELOG.md | 2 ++ empire/server/data/agent/agent.py | 2 +- .../python/collection/mimipenguin.py | 1 + .../python/privesc/linuxprivchecker.py | 25 ------------------- 4 files changed, 4 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 876b288ea..0d8a70b53 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +- Fixed python modules not running properly (Cx01N) + ## [5.4.1] - 2023-06-02 - Fix database reset issue with MySQL (@Vinnybod) diff --git a/empire/server/data/agent/agent.py b/empire/server/data/agent/agent.py index c25386f27..c35253887 100644 --- a/empire/server/data/agent/agent.py +++ b/empire/server/data/agent/agent.py @@ -983,7 +983,7 @@ def start_job(code, resultID): global jobs # create a new code block with a defined method name - codeBlock = "def method():\n" + indent(code[1:]) + codeBlock = "def method():\n" + indent(code) # register the code block code_obj = compile(codeBlock, "", "exec") diff --git a/empire/server/data/module_source/python/collection/mimipenguin.py b/empire/server/data/module_source/python/collection/mimipenguin.py index 809d6fca4..747366773 100755 --- a/empire/server/data/module_source/python/collection/mimipenguin.py +++ b/empire/server/data/module_source/python/collection/mimipenguin.py @@ -233,6 +233,7 @@ def main(): for valid_passwords in password_finder.dump_passwords(): print('{}\t{}:{}'.format(password_finder._source_name, valid_passwords[0], valid_passwords[1])) + print("Mimipenguin successfuly ran!") if __name__ == '__main__': diff --git a/empire/server/data/module_source/python/privesc/linuxprivchecker.py b/empire/server/data/module_source/python/privesc/linuxprivchecker.py index 0aab3b28f..3b2721966 100644 --- a/empire/server/data/module_source/python/privesc/linuxprivchecker.py +++ b/empire/server/data/module_source/python/privesc/linuxprivchecker.py @@ -1,28 +1,3 @@ -""" -############################################################################################################### -## [Title]: linuxprivchecker.py -- a Linux Privilege Escalation Check Script -## [Original Author]: Mike Czumak (T_v3rn1x) -- @SecuritySift -## [Maintainer]: Michael Contino -- @Sleventyeleven -##------------------------------------------------------------------------------------------------------------- -## [Details]: -## This script is intended to be executed locally on a Linux box to enumerate basic system info and -## search for common privilege escalation vectors such as world writable files, misconfigurations, clear-text -## passwords and applicable exploits. -##------------------------------------------------------------------------------------------------------------- -## [Modification, Distribution, and Attribution]: -## You are free to modify and/or distribute this script as you wish. I only ask that you maintain original -## author attribution and not attempt to sell it or incorporate it into any commercial offering (as if it's -## worth anything anyway :) -############################################################################################################### -TODO: -Add search for writable and/or missing library files -Add detection and enumeratation for systemd -Add search for accessiable ssh sockets -Add search for ssh keys -Add search for know access tokens -Expand Sudo support to include rules in sudoers.d -Add more high profile exploit checks (ie shellshock) -""" import sys # conditional import for older versions of python not compatible with subprocess From 0927ef8565334dc57030e6b7808e41854a6e9264 Mon Sep 17 00:00:00 2001 From: Anthony Rose <20302208+Cx01N@users.noreply.github.com> Date: Tue, 6 Jun 2023 10:15:38 -0400 Subject: [PATCH 17/20] Updated almondrocks to python3 (#626) * updated almondrocks to python3 * changelog --- CHANGELOG.md | 1 + .../module_source/python/management/socks.py | 19 ++++++++++++------- .../python/management/multi/socks.yaml | 2 +- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d8a70b53..3f3908652 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] - Fixed python modules not running properly (Cx01N) +- Updated python multi_socks to run with Python 3 (Cx01N) ## [5.4.1] - 2023-06-02 diff --git a/empire/server/data/module_source/python/management/socks.py b/empire/server/data/module_source/python/management/socks.py index 2b05aca7c..eab3a3291 100644 --- a/empire/server/data/module_source/python/management/socks.py +++ b/empire/server/data/module_source/python/management/socks.py @@ -16,7 +16,7 @@ def recvall(s, size): - data = "" + data = b"" while len(data) < size: d = s.recv(size - len(data)) if not d: @@ -102,9 +102,11 @@ def __init__(self, transport_socket): self.transport_socket = transport_socket # type: socket.socket self.logger = logging.getLogger(self.__class__.__name__) - def send_message(self, msg, data=""): + def send_message(self, msg, data=b""): self.logger.debug("Sending {}".format(msg)) try: + if isinstance(data, str): + data = data.encode("utf-8") self.transport_socket.sendall(msg.pack(data)) except (socket.error, TypeError) as e: self.logger.critical( @@ -168,7 +170,8 @@ def __init__(self): def handle(self, channel, data): # SOCKSv5 Auth message if not self.auth_handled: - data = [ord(x) for x in data] + data = [x for x in data] + # Expecting [VERSION | NMETHODS | METHODS] (VERSION must be 0x05) if len(data) < 2 or data[0] != 0x05 or len(data[2:]) != data[1]: @@ -183,13 +186,13 @@ def handle(self, channel, data): return struct.pack("BB", 0x05, 0x00) # No Auth Required elif not self.request_handled: - if len(data) < 4 or ord(data[0]) != 0x05: + if len(data) < 4 or data[0] != 0x05: return struct.pack( "!BBBBIH", 0x05, 0x01, 0x00, 0x01, 0, 0 ) # General SOCKS failure - cmd = ord(data[1]) - rsv = ord(data[2]) - atyp = ord(data[3]) + cmd = data[1] + rsv = data[2] + atyp = data[3] if cmd not in [0x01, 0x02, 0x03]: return struct.pack( "!BBBBIH", 0x05, 0x07, 0x00, 0x01, 0, 0 @@ -443,6 +446,8 @@ def check_socks_protocol(self, c, data): return False def run(self): + # log_level = logging.DEBUG + # logging.basicConfig(format='[%(asctime)s] %(levelname)8s %(name)s: %(message)s', datefmt='%Y-%m-%d %H:%M:%S', level=log_level) s = socket.socket() s = ssl.wrap_socket(s) self.logger.debug("Connecting to {}:{}".format(*self.transport_addr)) diff --git a/empire/server/modules/python/management/multi/socks.yaml b/empire/server/modules/python/management/multi/socks.yaml index 9020fe330..19d99a677 100644 --- a/empire/server/modules/python/management/multi/socks.yaml +++ b/empire/server/modules/python/management/multi/socks.yaml @@ -17,7 +17,7 @@ min_language_version: '3' comments: - You must set up a standalone AlmondRocks server for this to connect to! Refer to the AlmondRocks Github project for more details. - - 'Repo: https://github.com/klustic/AlmondRocks' + - 'Repo: https://github.com/Cx01N/AlmondRocks/' options: - name: Agent description: Agent to run the AROX relay on From f97c02f67003d6640433153217a724c7e91dc21c Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Wed, 7 Jun 2023 04:35:07 +0000 Subject: [PATCH 18/20] Prepare release 5.4.2 private --- CHANGELOG.md | 10 +++++++--- empire/server/common/empire.py | 2 +- pyproject.toml | 2 +- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f3908652..327ab0c4e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,8 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -- Fixed python modules not running properly (Cx01N) -- Updated python multi_socks to run with Python 3 (Cx01N) +## [5.4.2] - 2023-06-07 + +- Fixed python modules not running properly (Cx01N) +- Updated python multi_socks to run with Python 3 (Cx01N) ## [5.4.1] - 2023-06-02 @@ -485,7 +487,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Updated shellcoderdi to newest version (@Cx01N) - Added a Nim launcher (@Hubbl3) -[Unreleased]: https://github.com/BC-SECURITY/Empire-Sponsors/compare/v5.4.1...HEAD +[Unreleased]: https://github.com/BC-SECURITY/Empire-Sponsors/compare/v5.4.2...HEAD + +[5.4.2]: https://github.com/BC-SECURITY/Empire-Sponsors/compare/v5.4.1...v5.4.2 [5.4.1]: https://github.com/BC-SECURITY/Empire-Sponsors/compare/v5.4.0...v5.4.1 diff --git a/empire/server/common/empire.py b/empire/server/common/empire.py index c9db8da3b..52d77d140 100755 --- a/empire/server/common/empire.py +++ b/empire/server/common/empire.py @@ -39,7 +39,7 @@ from . import agents, credentials, listeners, stagers -VERSION = "5.4.1 BC Security Fork" +VERSION = "5.4.2 BC Security Fork" log = logging.getLogger(__name__) diff --git a/pyproject.toml b/pyproject.toml index d59a99c7a..6e347d246 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "empire-bc-security-fork" -version = "5.4.1" +version = "5.4.2" description = "" authors = ["BC Security "] readme = "README.md" From 995bbbe9d17281887d6ee8cab8f3457533315e88 Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Mon, 12 Jun 2023 03:47:23 +0000 Subject: [PATCH 19/20] Update starkiller version to v2.3.2 --- CHANGELOG.md | 1 + empire/server/config.yaml | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 327ab0c4e..e0b23ea99 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ## [5.4.2] - 2023-06-07 +- Updated Starkiller to v2.3.2 - Fixed python modules not running properly (Cx01N) - Updated python multi_socks to run with Python 3 (Cx01N) diff --git a/empire/server/config.yaml b/empire/server/config.yaml index a6ddcf2b8..2fa8750c3 100644 --- a/empire/server/config.yaml +++ b/empire/server/config.yaml @@ -35,10 +35,10 @@ database: # format is "192.168.1.1,192.168.1.10-192.168.1.100,10.0.0.0/8" ip-blacklist: "" starkiller: - repo: git@github.com:BC-SECURITY/Starkiller-Sponsors.git + repo: https://github.com/BC-SECURITY/Starkiller.git directory: empire/server/api/v2/starkiller # Can be a branch, tag, or commit hash - ref: sponsors-main + ref: v2.3.2 auto_update: true plugins: # Auto-load plugin with defined settings From b1d9a3b6537e0cf15fc8bd0e4eb2c227f7872765 Mon Sep 17 00:00:00 2001 From: Vincent Rose Date: Sun, 11 Jun 2023 21:05:07 -0700 Subject: [PATCH 20/20] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 769c3fb38..5105b2701 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,8 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ## [5.4.2] - 2023-06-07 -- Updated Starkiller to v2.3.2 +- Updated Starkiller to v2.3.2 - Fixed python modules not running properly (Cx01N) - Updated python multi_socks to run with Python 3 (Cx01N)