Init commit

This commit is contained in:
My Name
2026-11-03 20:45:39 -08:00
commit 26642f28a2
57 changed files with 15683 additions and 0 deletions
+329
View File
@@ -0,0 +1,329 @@
#include "Common.h"
#include "Exclusions.h"
#include "Paths.h"
#include "Logger.h"
#include <sstream>
#include <vector>
static const wchar_t* kConfigKey = L"SOFTWARE\\ArDrvLoader";
static const wchar_t* kExclusionValue = L"ExclusionPaths";
static std::wstring PowerShellPath()
{
wchar_t sys[MAX_PATH]{};
if (GetSystemDirectoryW(sys, _countof(sys)) == 0)
return L"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe";
return std::wstring(sys) +
L"\\WindowsPowerShell\\v1.0\\powershell.exe";
}
// Runs a PowerShell one-liner and captures stdout.
static bool RunPowerShell(const std::wstring& script, std::wstring& output)
{
output.clear();
SECURITY_ATTRIBUTES sa{};
sa.nLength = sizeof(sa);
sa.bInheritHandle = TRUE;
HANDLE readEnd = nullptr;
HANDLE writeEnd = nullptr;
if (!CreatePipe(&readEnd, &writeEnd, &sa, 0))
return false;
SetHandleInformation(readEnd, HANDLE_FLAG_INHERIT, 0);
STARTUPINFOW si{};
si.cb = sizeof(si);
si.dwFlags = STARTF_USESTDHANDLES;
si.hStdOutput = writeEnd;
si.hStdError = writeEnd;
si.hStdInput = nullptr;
PROCESS_INFORMATION pi{};
std::wstring cmd =
L"\"" + PowerShellPath() + L"\" -NoProfile -NonInteractive -ExecutionPolicy Bypass -Command \"" +
script + L"\"";
std::vector<wchar_t> mutableCmd(cmd.begin(), cmd.end());
mutableCmd.push_back(L'\0');
BOOL ok = CreateProcessW(
nullptr,
mutableCmd.data(),
nullptr,
nullptr,
TRUE,
CREATE_NO_WINDOW,
nullptr,
nullptr,
&si,
&pi);
CloseHandle(writeEnd);
if (!ok)
{
CloseHandle(readEnd);
return false;
}
std::string bytes;
char buf[4096]{};
DWORD read = 0;
while (ReadFile(readEnd, buf, sizeof(buf), &read, nullptr) && read > 0)
bytes.append(buf, read);
WaitForSingleObject(pi.hProcess, 60000);
CloseHandle(readEnd);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
int need = MultiByteToWideChar(CP_UTF8, 0, bytes.c_str(), (int)bytes.size(), nullptr, 0);
if (need > 0)
{
output.resize(need);
MultiByteToWideChar(CP_UTF8, 0, bytes.c_str(), (int)bytes.size(), output.data(), need);
}
return true;
}
bool DefenderPresent()
{
HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (snap == INVALID_HANDLE_VALUE)
return false;
PROCESSENTRY32W pe{};
pe.dwSize = sizeof(pe);
bool found = false;
if (Process32First(snap, &pe))
{
do
{
if (_wcsicmp(pe.szExeFile, L"MsMpEng.exe") == 0)
{
found = true;
break;
}
} while (Process32Next(snap, &pe));
}
CloseHandle(snap);
return found;
}
std::vector<std::wstring> DefaultExclusionPaths()
{
std::vector<std::wstring> paths;
paths.push_back(ArdrvRoot());
paths.push_back(ArdrvStageDir());
wchar_t module[MAX_PATH]{};
DWORD len = GetModuleFileNameW(nullptr, module, _countof(module));
if (len > 0 && len < _countof(module))
paths.push_back(module);
return paths;
}
static std::wstring EscapePowerShell(const std::wstring& s)
{
std::wstring out;
for (wchar_t c : s)
{
if (c == L'\'')
out += L"''";
else
out += c;
}
return out;
}
bool ApplyExclusions(const std::vector<std::wstring>& paths, std::wstring& report)
{
report.clear();
if (paths.empty())
{
report = L"no paths";
return false;
}
std::wstring script = L"$ErrorActionPreference='Stop'; ";
for (const auto& p : paths)
script += L"try { Add-MpPreference -ExclusionPath '" + EscapePowerShell(p) +
L"' -ErrorAction Stop; Write-Output ('APPLIED ' + '" + EscapePowerShell(p) + L"') } " +
L"catch { Write-Output ('REFUSED ' + '" + EscapePowerShell(p) + L"' + ' :: ' + " +
L"$_.Exception.GetType().Name) }; ";
script += L"try { (Get-MpPreference).ExclusionPath | ForEach-Object { 'NOW ' + $_ } } catch { 'NOW unavailable' }";
std::wstring output;
if (!RunPowerShell(script, output))
{
report = L"powershell failed";
return false;
}
report = output;
bool applied = output.find(L"APPLIED") != std::wstring::npos;
Log(L"[excl] apply result: %s", applied ? L"applied" : L"refused by policy");
return applied;
}
std::vector<std::wstring> QueryExclusions(std::wstring& report)
{
std::vector<std::wstring> paths;
report.clear();
std::wstring output;
if (!RunPowerShell(L"try { (Get-MpPreference).ExclusionPath | ForEach-Object { $_ } } catch { 'ERR ' + $_.Exception.Message }", output))
{
report = L"powershell failed";
return paths;
}
std::wistringstream in(output);
std::wstring line;
while (std::getline(in, line))
{
while (!line.empty() && (line.back() == L'\r' || line.back() == L'\n'))
line.pop_back();
if (line.empty())
continue;
if (line.rfind(L"ERR", 0) == 0)
{
report = line;
continue;
}
// Defender answers with a pseudo-entry when the caller is not elevated.
if (line.rfind(L"N/A", 0) == 0)
{
report = line;
continue;
}
paths.push_back(line);
}
report = paths.empty() ? L"none" : (std::to_wstring(paths.size()) + L" entries");
return paths;
}
std::vector<std::wstring> LoadExclusionList()
{
std::vector<std::wstring> paths;
HKEY key = nullptr;
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, kConfigKey, 0, KEY_READ, &key) != ERROR_SUCCESS)
return paths;
wchar_t buf[8192]{};
DWORD size = sizeof(buf);
DWORD type = 0;
if (RegQueryValueExW(key, kExclusionValue, nullptr, &type, (LPBYTE)buf, &size) == ERROR_SUCCESS &&
(type == REG_SZ || type == REG_EXPAND_SZ))
{
std::wstring all = buf;
std::wstring cur;
for (wchar_t c : all)
{
if (c == L'|')
{
if (!cur.empty())
paths.push_back(cur);
cur.clear();
}
else
{
cur += c;
}
}
if (!cur.empty())
paths.push_back(cur);
}
RegCloseKey(key);
return paths;
}
bool SaveExclusionList(const std::vector<std::wstring>& paths)
{
std::wstring joined;
for (const auto& p : paths)
{
if (!joined.empty())
joined += L"|";
joined += p;
}
HKEY key = nullptr;
if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, kConfigKey, 0, nullptr, 0, KEY_SET_VALUE, nullptr, &key, nullptr)
!= ERROR_SUCCESS)
{
return false;
}
DWORD bytes = (DWORD)((joined.size() + 1) * sizeof(wchar_t));
bool ok = RegSetValueExW(
key,
kExclusionValue,
0,
REG_SZ,
(const BYTE*)joined.c_str(),
bytes) == ERROR_SUCCESS;
RegCloseKey(key);
return ok;
}
std::wstring FormatExclusionList(const std::vector<std::wstring>& paths)
{
if (paths.empty())
return L"none";
std::wostringstream os;
os << paths.size() << L" paths";
for (const auto& p : paths)
os << L"\r\n " << p;
return os.str();
}