Init commit
This commit is contained in:
@@ -0,0 +1,229 @@
|
||||
#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";
|
||||
}
|
||||
Reference in New Issue
Block a user