Files
2026-05-06 09:32:58 +10:00

376 lines
12 KiB
C++

#include "core/controller_private.h"
#pragma comment(lib, "advapi32.lib")
#pragma comment(lib, "tdh.lib")
SERVICE_STATUS_HANDLE g_ServiceStatusHandle = NULL;
SERVICE_STATUS g_ServiceStatus;
HANDLE g_StopEvent = NULL;
class ControllerLogger
{
public:
ControllerLogger() noexcept = default;
~ControllerLogger() noexcept
{
Close();
}
ControllerLogger(const ControllerLogger &) = delete;
ControllerLogger &operator=(const ControllerLogger &) = delete;
void Init() noexcept
{
CHAR logDir[MAX_PATH];
CHAR logPath[MAX_PATH];
CHAR rotatePath[MAX_PATH];
CHAR intermediate[MAX_PATH];
DWORD expanded;
ScopedCriticalSection guard(m_lock);
if (m_file != INVALID_HANDLE_VALUE)
{
return;
}
expanded = ExpandEnvironmentStringsA("%ProgramData%\\Blackbird", intermediate, RTL_NUMBER_OF(intermediate));
if (expanded > 0 && expanded <= RTL_NUMBER_OF(intermediate))
{
CreateDirectoryA(intermediate, NULL);
}
expanded =
ExpandEnvironmentStringsA("%ProgramData%\\Blackbird\\Node", intermediate, RTL_NUMBER_OF(intermediate));
if (expanded > 0 && expanded <= RTL_NUMBER_OF(intermediate))
{
CreateDirectoryA(intermediate, NULL);
}
expanded = ExpandEnvironmentStringsA("%ProgramData%\\Blackbird\\Node\\logs", logDir, RTL_NUMBER_OF(logDir));
if (expanded == 0 || expanded > RTL_NUMBER_OF(logDir))
{
return;
}
CreateDirectoryA(logDir, NULL);
ApplyLogDirectoryAcl(logDir);
(void)StringCchPrintfA(logPath, RTL_NUMBER_OF(logPath), "%s\\controller.log", logDir);
(void)StringCchPrintfA(rotatePath, RTL_NUMBER_OF(rotatePath), "%s\\controller.log.1", logDir);
HANDLE probe = CreateFileA(logPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
OPEN_EXISTING, 0, NULL);
if (probe != INVALID_HANDLE_VALUE)
{
CloseHandle(probe);
(void)MoveFileExA(logPath, rotatePath, MOVEFILE_REPLACE_EXISTING);
}
m_file = CreateFileA(logPath, FILE_APPEND_DATA, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (m_file != INVALID_HANDLE_VALUE)
{
LARGE_INTEGER end = {};
(void)SetFilePointerEx(m_file, end, NULL, FILE_END);
}
}
void Close() noexcept
{
ScopedCriticalSection guard(m_lock);
if (m_file != INVALID_HANDLE_VALUE)
{
FlushFileBuffers(m_file);
CloseHandle(m_file);
m_file = INVALID_HANDLE_VALUE;
}
}
static bool TagEquals(_In_reads_(tagLen) PCSTR tag, _In_ SIZE_T tagLen, _In_z_ PCSTR expected) noexcept
{
SIZE_T expectedLen = strlen(expected);
return tagLen == expectedLen && _strnicmp(tag, expected, expectedLen) == 0;
}
static bool IsSeverityTag(_In_reads_(tagLen) PCSTR tag, _In_ SIZE_T tagLen) noexcept
{
return TagEquals(tag, tagLen, "WARN") || TagEquals(tag, tagLen, "ERR") || TagEquals(tag, tagLen, "ERROR") ||
TagEquals(tag, tagLen, "INFO") || TagEquals(tag, tagLen, "DIAG") || TagEquals(tag, tagLen, "PANIC");
}
static PCSTR ComponentForTag(_In_reads_(tagLen) PCSTR tag, _In_ SIZE_T tagLen) noexcept
{
if (TagEquals(tag, tagLen, "DRIVER"))
{
return "blackbird.sys";
}
if (TagEquals(tag, tagLen, "NETSVC") || TagEquals(tag, tagLen, "NODE"))
{
return "BlackbirdNetSvc.exe";
}
if (TagEquals(tag, tagLen, "INJ") || TagEquals(tag, tagLen, "HOOK"))
{
return "SR71.dll";
}
if (TagEquals(tag, tagLen, "IPC") || TagEquals(tag, tagLen, "ETW") || TagEquals(tag, tagLen, "MON") ||
TagEquals(tag, tagLen, "MITIGATION") || TagEquals(tag, tagLen, "WARN") || TagEquals(tag, tagLen, "ERR") ||
TagEquals(tag, tagLen, "ERROR") || TagEquals(tag, tagLen, "INFO") || TagEquals(tag, tagLen, "*") ||
TagEquals(tag, tagLen, "-"))
{
return "BlackbirdController.exe";
}
return NULL;
}
static void ApplyLogDirectoryAcl(_In_z_ PCSTR logDir) noexcept
{
PSECURITY_DESCRIPTOR securityDescriptor = NULL;
if (logDir == NULL || logDir[0] == '\0')
{
return;
}
if (ConvertStringSecurityDescriptorToSecurityDescriptorA(
"D:P(A;OICI;GA;;;SY)(A;OICI;GA;;;BA)(A;OICI;GRGW;;;BU)", SDDL_REVISION_1, &securityDescriptor, NULL) &&
securityDescriptor != NULL)
{
(void)SetFileSecurityA(logDir, DACL_SECURITY_INFORMATION, securityDescriptor);
LocalFree(securityDescriptor);
}
}
static void NormalizeComponentPrefix(_In_z_ PCSTR message, _Out_writes_z_(normalizedChars) PSTR normalized,
_In_ SIZE_T normalizedChars) noexcept
{
PCSTR close;
PCSTR component;
PCSTR tail;
SIZE_T tagLen;
if (normalized == NULL || normalizedChars == 0)
{
return;
}
normalized[0] = '\0';
if (message == NULL || message[0] != '[')
{
(void)StringCchCopyA(normalized, normalizedChars, message != NULL ? message : "");
return;
}
close = strchr(message + 1, ']');
if (close == NULL || close == message + 1)
{
(void)StringCchCopyA(normalized, normalizedChars, message);
return;
}
tagLen = (SIZE_T)(close - (message + 1));
component = ComponentForTag(message + 1, tagLen);
if (component == NULL)
{
(void)StringCchCopyA(normalized, normalizedChars, message);
return;
}
tail = close + 1;
if (_stricmp(component, "BlackbirdController.exe") == 0 && _strnicmp(tail, " BlackbirdController:", 21) == 0)
{
tail += 21;
}
if (IsSeverityTag(message + 1, tagLen))
{
(void)StringCchPrintfA(normalized, normalizedChars, "[%s][%.*s]%s", component, (int)tagLen, message + 1,
tail);
}
else
{
(void)StringCchPrintfA(normalized, normalizedChars, "[%s]%s", component, tail);
}
}
void Log(_In_z_ _Printf_format_string_ PCSTR fmt, va_list args) noexcept
{
char message[2048];
char normalized[2048];
char stamped[2200];
SYSTEMTIME st;
DWORD written;
(void)StringCchVPrintfA(message, RTL_NUMBER_OF(message), fmt, args);
NormalizeComponentPrefix(message, normalized, RTL_NUMBER_OF(normalized));
(void)OutputDebugStringA(normalized);
(void)printf("%s", normalized);
if (m_file == INVALID_HANDLE_VALUE)
{
return;
}
GetLocalTime(&st);
SIZE_T msgLen = strlen(normalized);
while (msgLen > 0 && (normalized[msgLen - 1] == '\n' || normalized[msgLen - 1] == '\r'))
{
normalized[--msgLen] = '\0';
}
(void)StringCchPrintfA(stamped, RTL_NUMBER_OF(stamped),
"[%04u-%02u-%02u %02u:%02u:%02u pid=%lu tid=%lu] %s\r\n", st.wYear, st.wMonth, st.wDay,
st.wHour, st.wMinute, st.wSecond, GetCurrentProcessId(), GetCurrentThreadId(),
normalized);
ScopedCriticalSection guard(m_lock);
if (m_file != INVALID_HANDLE_VALUE)
{
(void)WriteFile(m_file, stamped, (DWORD)strlen(stamped), &written, NULL);
(void)FlushFileBuffers(m_file);
}
}
private:
OwnedCriticalSection m_lock;
HANDLE m_file = INVALID_HANDLE_VALUE;
};
static ControllerLogger g_Log;
HANDLE g_ServerThread = NULL;
HANDLE g_DriverPumpThread = NULL;
HANDLE g_EtwThread = NULL;
HANDLE g_DriverHandle = INVALID_HANDLE_VALUE;
BKSC_ETW_SESSION *g_EtwSession = NULL;
BOOL g_ThreatIntelEnabled = FALSE;
DWORD g_ThreatIntelEnableError = ERROR_SUCCESS;
volatile LONG g_EtwDetectionEvents = 0;
volatile LONG g_EtwTiEvents = 0;
OwnedCriticalSection g_ClientListLock;
OwnedCriticalSection g_DriverLock;
OwnedCriticalSection g_DriverConfigLock;
volatile LONG g_DriverSubscriptionsDirty = 0;
PBK_CONTROLLER_CLIENT g_ClientList = NULL;
PBK_CONTROLLER_CLIENT g_ClientSlots[BK_CONTROLLER_MAX_CLIENTS];
DWORD g_ClientCount = 0;
DWORD g_ProgrammedPids[BK_MAX_PID_LIST];
DWORD g_ProgrammedPidCount = 0;
BK_CONTROLLER_PID_INDEX_ENTRY g_PidIndex[BK_MAX_PID_LIST];
DWORD g_PidIndexCount = 0;
SRWLOCK g_HollowLock = SRWLOCK_INIT;
BK_CONTROLLER_HOLLOW_ENTRY g_HollowEntries[BK_CONTROLLER_HOLLOW_MAX_ENTRIES];
VOID ControllerLogInit(VOID)
{
g_Log.Init();
}
VOID ControllerLogClose(VOID)
{
g_Log.Close();
}
VOID ControllerLog(_In_z_ _Printf_format_string_ PCSTR Format, ...)
{
va_list args;
va_start(args, Format);
g_Log.Log(Format, args);
va_end(args);
}
VOID ControllerApplyProcessMitigations(VOID)
{
PROCESS_MITIGATION_DYNAMIC_CODE_POLICY dynamicCode = {};
PROCESS_MITIGATION_EXTENSION_POINT_DISABLE_POLICY extensionPoints = {};
PROCESS_MITIGATION_STRICT_HANDLE_CHECK_POLICY strictHandles = {};
PROCESS_MITIGATION_IMAGE_LOAD_POLICY imageLoad = {};
SetDefaultDllDirectories(LOAD_LIBRARY_SEARCH_SYSTEM32);
dynamicCode.ProhibitDynamicCode = 1;
dynamicCode.AllowThreadOptOut = 0;
dynamicCode.AllowRemoteDowngrade = 0;
if (!SetProcessMitigationPolicy(ProcessDynamicCodePolicy, &dynamicCode, sizeof(dynamicCode)))
{
ControllerLog("[MITIGATION][WARN] dynamic-code mitigation failed err=%lu\n", GetLastError());
}
extensionPoints.DisableExtensionPoints = 1;
if (!SetProcessMitigationPolicy(ProcessExtensionPointDisablePolicy, &extensionPoints, sizeof(extensionPoints)))
{
ControllerLog("[MITIGATION][WARN] extension-point mitigation failed err=%lu\n", GetLastError());
}
strictHandles.RaiseExceptionOnInvalidHandleReference = 1;
strictHandles.HandleExceptionsPermanentlyEnabled = 1;
if (!SetProcessMitigationPolicy(ProcessStrictHandleCheckPolicy, &strictHandles, sizeof(strictHandles)))
{
ControllerLog("[MITIGATION][WARN] strict-handle mitigation failed err=%lu\n", GetLastError());
}
imageLoad.NoRemoteImages = 1;
imageLoad.NoLowMandatoryLabelImages = 1;
imageLoad.PreferSystem32Images = 1;
if (!SetProcessMitigationPolicy(ProcessImageLoadPolicy, &imageLoad, sizeof(imageLoad)))
{
ControllerLog("[MITIGATION][WARN] image-load mitigation failed err=%lu\n", GetLastError());
}
}
VOID ControllerUpdateServiceStatus(_In_ DWORD CurrentState, _In_ DWORD Win32ExitCode, _In_ DWORD WaitHint)
{
static DWORD checkpoint = 1;
if (g_ServiceStatusHandle == NULL)
{
return;
}
g_ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
g_ServiceStatus.dwCurrentState = CurrentState;
g_ServiceStatus.dwWin32ExitCode = Win32ExitCode;
g_ServiceStatus.dwWaitHint = WaitHint;
g_ServiceStatus.dwControlsAccepted = 0;
g_ServiceStatus.dwCheckPoint = 0;
if (CurrentState == SERVICE_START_PENDING || CurrentState == SERVICE_STOP_PENDING)
{
g_ServiceStatus.dwCheckPoint = checkpoint++;
}
if (CurrentState == SERVICE_RUNNING)
{
g_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
}
(void)SetServiceStatus(g_ServiceStatusHandle, &g_ServiceStatus);
}
BOOL ControllerShouldStop(VOID)
{
return (g_StopEvent != NULL && WaitForSingleObject(g_StopEvent, 0) == WAIT_OBJECT_0);
}
VOID ControllerStopEtwSessionByNameBestEffort(_In_z_ PCWSTR SessionName, _In_z_ PCSTR Reason)
{
ULONG status;
if (SessionName == NULL || SessionName[0] == L'\0')
{
return;
}
status = BkscStopSessionByName(SessionName);
if (status == ERROR_SUCCESS)
{
ControllerLog("[ETW] stopped session reason=%s name=%ws\n", Reason, SessionName);
}
else
{
ControllerLog("[ETW][WARN] stop-by-name failed reason=%s name=%ws status=%lu\n", Reason, SessionName, status);
}
}
VOID ControllerCleanupStaleEtwSessions(VOID)
{
ControllerStopEtwSessionByNameBestEffort(BK_CONTROLLER_ETW_SESSION_NAMEW, "pre-start");
}