===== VERA PROCESS COLLECTOR: EVIDENCE BUNDLE ===== Version: 0.3.11 Sample SHA-256: 67533dc573b4c52ebdc32d13105455192d6e5843c231d8f0906c45d581362322 Bundle generated: 2026-07-01 SCOPE OF THIS PACK This pack covers three audit layers: 1. Behavioral observation of the shipping installer in an independent malware sandbox (section 1). 2. The NATIVE (P/Invoke) Windows API surface declared by the compiled binaries (section 2). This layer is what a decompiler like ILSpy or dnSpy surfaces when it reads the shipping DLLs. 3. The MANAGED (.NET) sensitive-API surface (section 3). This closes the blind spot a P/Invoke-only audit has: .NET applications can call powerful capabilities (DPAPI, arbitrary file I/O, HTTP) through the managed base class library without any P/Invoke declaration. This section enumerates every such call site the collector actually uses, with the target path or URL pattern of each. --- 1. INDEPENDENT SANDBOX DETONATION REPORT --- Service: Hybrid Analysis (CrowdStrike Falcon Sandbox) Environment: Windows 11 64-bit Public report URL: https://hybrid-analysis.com/sample/67533dc573b4c52ebdc32d13105455192d6e5843c231d8f0906c45d581362322/6a447af68ef23771050736da Top-line verdict, verbatim from the report page: "no specific threat" AV Detection: Marked as clean MetaDefender Multi Scan Analysis: Clean Community Score: 0 Falcon Sandbox result: analysis complete, no malicious verdict Network activity observed by the sandbox, verbatim from the Network Analysis section of the report page: DNS Requests: "No relevant DNS requests were made." Contacted Hosts: "No relevant hosts were contacted." HTTP Traffic: "No relevant HTTP requests were made." Process tree observed by the sandbox (verbatim): msiexec.exe /i "C:\VeraProcessCollector-0.3.11.msi" (PID 4564) msiexec.exe /V (PID 1976) MsiExec.exe -Embedding [handle] (PID 8080) MsiExec.exe -Embedding [handle] Global\MSI0000 (PID 4088) Interpretation of the sandbox network log: The sandbox observation window covers the installer running (msiexec plus its internal service host and two embedded custom-action processes). Within that window ZERO network requests were made to any destination. For a malicious installer trying to exfiltrate data during install (before the user notices), this would be observable. Nothing was. Note: the runtime Windows service the installer registers did not start within the sandbox window (which is why no post-install network traffic appears in this log). Its network destinations are documented in Section 3 (Managed Network subsection) below, which enumerates every outbound HTTP call site in the source with its URL pattern. All resolve to Vera's own API base URL or to a presigned S3 URL that Vera's own API returned; there is no third destination. Indicators observed by the Falcon Sandbox, verbatim from the report page: Suspicious Indicators (1): Anti-Detection/Stealthiness: "Able to execute scripts via MSI custom actions during software installation" Informative Indicators (21), by category: Cryptographic Related: "Shows ability to obfuscate file or information" Environment Awareness: "Contains ability to determine if process is running under WOW64 (API string)" "Contains ability to execute a WMI query" "Contains ability to retrieve path in which Windows is installed (API string)" External Systems: "Sample was identified as clean by Antivirus engines" General: "Contains SQL queries" MITRE ATT&CK Techniques Detection, verbatim: "This report has 21 indicators that were mapped to 15 attack techniques and 7 tactics." Explanation of the "Cryptographic Related: Shows ability to obfuscate file or information" indicator, based on inspection of the source: This is triggered by the collector's use of SHA-256 hashing to fingerprint kernel driver executable files and (optionally) process executable files. See CollectorEngine.cs GetSha256 method and DriverSnapshotCollector.cs ComputeSha256 method. Neither encrypts data for concealment; both compute a one-way hash of an executable file to match against known-vulnerable-driver lists. The bytes read for hashing are passed directly to SHA256.ComputeHash and are never stored or transmitted anywhere. --- 2. NATIVE (P/INVOKE) WINDOWS API SURFACE --- The compiled Vera.ProcessCollector.Core.dll and Vera.ProcessCollector.Host.dll assemblies contain the following complete set of native Windows API declarations, byte-identical to what an ILSpy or dnSpy decompiler produces from the shipping DLLs. # Vera Process Collector: every native (P/Invoke) API declaration # Version: 0.3.11 # Assemblies: Vera.ProcessCollector.Core.dll, Vera.ProcessCollector.Host.dll # Runtime: .NET (Windows 10/11 x64) # Purpose: independently-verifiable enumeration of every Windows API the # shipping binaries can call directly. Absence of an API here # means it is not called from the collector's own code. # ================================================================== # From CollectorEngine.cs (Vera.ProcessCollector.Core assembly) # ================================================================== private const int ProcessQueryLimitedInformation = 0x1000; [DllImport("kernel32.dll", SetLastError = true)] private static extern IntPtr OpenProcess(int desiredAccess, bool inheritHandle, int processId); [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] private static extern bool QueryFullProcessImageName(IntPtr hProcess, int flags, StringBuilder exeName, ref int size); [DllImport("kernel32.dll", SetLastError = true)] private static extern bool CloseHandle(IntPtr hObject); // The one and only call site for OpenProcess in the entire codebase uses the // LEAST-privileged process-access mask Windows exposes. It cannot be used to // read another process's memory: handle = OpenProcess(ProcessQueryLimitedInformation, false, process.Id); # ================================================================== # From SystemInfoCollector.cs (Vera.ProcessCollector.Host assembly) # ================================================================== [DllImport("user32.dll", CharSet = CharSet.Auto)] private static extern bool EnumDisplayDevices(string? lpDevice, uint iDevNum, ref DISPLAY_DEVICE lpDisplayDevice, uint dwFlags); [DllImport("user32.dll", CharSet = CharSet.Auto)] private static extern bool EnumDisplaySettings(string deviceName, int modeNum, ref DEVMODE devMode); [DllImport("user32.dll")] private static extern int GetDisplayConfigBufferSizes( uint flags, out uint numPathArrayElements, out uint numModeInfoArrayElements); [DllImport("user32.dll")] private static extern int QueryDisplayConfig( uint flags, ref uint numPathArrayElements, [Out] DISPLAYCONFIG_PATH_INFO[] pathArray, ref uint numModeInfoArrayElements, [Out] DISPLAYCONFIG_MODE_INFO[] modeInfoArray, IntPtr currentTopologyId); # ================================================================== # End of file. Seven declarations total. # ================================================================== # What this list makes IMPOSSIBLE for the shipping binary to do directly # (each of these would require an API that is not declared above): # Read another process's memory # would require: ReadProcessMemory / NtReadVirtualMemory / VirtualQueryEx # -> not present # Log keystrokes # would require: SetWindowsHookEx / GetAsyncKeyState / GetKeyState / # RegisterRawInputDevices # -> not present # Capture the screen # would require: BitBlt / PrintWindow / CopyFromScreen / GetWindowDC # -> not present # Read the clipboard # would require: OpenClipboard / GetClipboardData # -> not present # Decrypt Windows-stored credentials (browser saved passwords, DPAPI) # would require: CryptUnprotectData # -> not present. (The managed DPAPI class, ProtectedData, appears in # exactly one file and only round-trips Vera's own device secret; # that file is reproduced verbatim in evidence section 3a.) # Read window titles / active-window monitoring # would require: GetWindowText / GetForegroundWindow / SetWinEventHook # -> not present # Sniff network traffic # would require: pcap / raw sockets / WinDivert # -> not present --- 3. MANAGED (.NET) SENSITIVE-API AUDIT --- The native P/Invoke surface above does not cover managed .NET APIs (which can invoke powerful Windows capabilities without a DllImport declaration). This section closes that blind spot by enumerating every sensitive managed API used by the collector, with source location. 3a. DPAPI USAGE (System.Security.Cryptography.ProtectedData) Grep of the entire collector codebase for "ProtectedData" returns exactly ONE file: Vera.ProcessCollector.Core/DeviceSecretProtector.cs, reproduced verbatim below. Its total behavior is: 1. Take a string that VERA ITSELF earlier prefixed with "dpapi:" (typically Vera's own device secret generated during provisioning). 2. DPAPI-encrypt or DPAPI-decrypt that string round-trip. 3. Return it. The DataProtectionScope used is LocalMachine. Nothing in this file reads browser saved passwords, wallet secrets, Windows Credential Manager entries, or any DPAPI blob created by any other application. It only encrypts Vera's own device secret at rest in Vera's own config file so the secret is not stored in plaintext on disk. ===== BEGIN DeviceSecretProtector.cs (81 lines, verbatim) ===== using System.Security.Cryptography; using System.Text; namespace Vera.ProcessCollector.Core; internal static class DeviceSecretProtector { private const string Prefix = "dpapi:"; public static bool IsProtected(string? value) { return !string.IsNullOrWhiteSpace(value) && value.StartsWith(Prefix, StringComparison.OrdinalIgnoreCase); } public static string? ProtectIfNeeded(string? value) { if (string.IsNullOrWhiteSpace(value)) { return value; } if (IsProtected(value)) { return value; } if (!OperatingSystem.IsWindows()) { return value; } try { var plaintext = Encoding.UTF8.GetBytes(value); var protectedBytes = ProtectedData.Protect( plaintext, optionalEntropy: null, scope: DataProtectionScope.LocalMachine); return Prefix + Convert.ToBase64String(protectedBytes); } catch { // Fallback to plaintext if protection fails unexpectedly. return value; } } public static string? UnprotectIfNeeded(string? value) { if (string.IsNullOrWhiteSpace(value)) { return value; } if (!IsProtected(value)) { return value; } if (!OperatingSystem.IsWindows()) { return null; } try { var payload = value.Substring(Prefix.Length); var protectedBytes = Convert.FromBase64String(payload); var plaintext = ProtectedData.Unprotect( protectedBytes, optionalEntropy: null, scope: DataProtectionScope.LocalMachine); return Encoding.UTF8.GetString(plaintext); } catch { return null; } } } ===== END DeviceSecretProtector.cs ===== 3b. MANAGED FILE I/O (System.IO.File, System.IO.Directory) Every File.Read* / File.OpenRead / Directory.Enumerate* call site in the collector's own assemblies reads from exactly one of two path patterns. Verified by grep of the shipping source (v0.3.11). Pattern A: Vera's own state and config files. Root: C:\ProgramData\Vera\ (Environment.SpecialFolder.CommonApplicationData, "Vera") Files: agent-config.json, bootstrap.json, cached runtime rules, system-info-hash.txt, run archive metadata, bundle state/manifest files, spooler outbox state. Call sites (non-exhaustive but complete for the shipping paths): AgentConfig.cs L56, AgentRuntimeConfigClient.cs L40, SystemInfoCollector.cs L615, BootstrapProvisioner.cs L69, RunCoordinator.cs L804-847, RunScanner.cs L36-49, OutboxQueue.cs L235-271, S3PresignTransport.cs L99-251, SpoolerWorker.cs L334-344. Pattern B: Executable files, ONLY for SHA-256 hashing. Purpose: fingerprint the driver executable file to check against known-vulnerable-driver lists (feature: driver-trust). Also optionally fingerprint process executable files when the VERA_CAPTURE_FILE_HASHES env var is explicitly set (off by default). Call sites: CollectorEngine.cs L323 GetSha256(path): using var stream = File.OpenRead(path); using var sha256 = SHA256.Create(); var hash = sha256.ComputeHash(stream); DriverSnapshotCollector.cs ComputeSha256(path): same pattern. Data flow: bytes read from the file stream go DIRECTLY into SHA256.ComputeHash. They are not stored anywhere, not copied to another buffer, and not transmitted. The only output is the 32-byte SHA-256 hash. Nowhere in the shipping source does the collector read from any of the following (verifiable by grep): %APPDATA%\Google\Chrome\User Data\ (Chrome credential store) %APPDATA%\Microsoft\Edge\ (Edge credential store) %APPDATA%\Mozilla\Firefox\ (Firefox profiles) %APPDATA%\Roaming\\ (crypto wallet stores) %USERPROFILE%\Documents\ (user documents) %USERPROFILE%\Desktop\ (user desktop) key4.db, logins.json, wallet.dat (specific credential files) 3c. MANAGED NETWORK (System.Net.Http.HttpClient) Every outbound HttpClient call in the collector's own assemblies resolves to exactly one of two destinations. Verified by grep of the shipping source (v0.3.11). Destination A: {ApiBaseUrl}/api/agent/* The ApiBaseUrl is resolved from the collector's config; it defaults to https://veraproject.xyz. Override to http://localhost:3000 is supported for local development only. Endpoints called: POST {ApiBaseUrl}/api/agent/register (BootstrapProvisioner.cs L202, AgentProvisioner.cs L14) POST {ApiBaseUrl}/api/agent/heartbeat (AgentHeartbeat.cs L24) GET {ApiBaseUrl}/api/agent/config (AgentRuntimeConfigClient.cs L99) GET {ApiBaseUrl}/api/agent/runtime-rules (AgentRuntimeConfigClient.cs L185) POST {ApiBaseUrl}/api/agent/system-info (SystemInfoCollector.cs L575) POST {ApiBaseUrl}/api/agent/presign (S3PresignTransport.cs L139; requests an S3 upload URL) Destination B: a time-limited presigned S3 URL RETURNED BY the Vera /api/agent/presign endpoint above. The collector does not know any S3 URL in advance. It asks Vera's own API for a presigned URL (Destination A above), then PUTs the bundle to whichever URL the API returned. The URL points at a Vera-controlled S3 bucket. Call site: S3PresignTransport.cs L178 (_httpClient.PutAsync(url, ...)) There is no third destination anywhere in the shipping source. Nothing in the collector calls a URL that is not either derived from ApiBaseUrl or issued by the presign endpoint. Verifiable by grepping for "http://" and "https://" across the collector's C# files. 3d. GRAPHICS / SCREEN-CAPTURE MANAGED APIS Grep of the entire collector codebase for the pure-managed screen-capture paths returns ZERO call sites: System.Drawing.Graphics.CopyFromScreen -> not called System.Drawing.Bitmap -> not referenced Windows.Graphics.Capture (WinRT) -> not referenced Neither the System.Drawing.Common package nor the Windows.Graphics.Capture package appears in any csproj PackageReference across the codebase. This closes the specific managed-side screen-capture path that a P/Invoke-only audit cannot see. 3e. SERVER-DELIVERED RUNTIME CONFIGURATION SCOPE The collector fetches a small config payload from Vera's own API at {ApiBaseUrl}/api/agent/config. The payload has exactly four fields, per the AgentRuntimeConfigPayload class (AgentRuntimeConfigClient.cs L208): ConfigVersion (string) PollIntervalSeconds (int, default 3600) CaptureMode (string, default "Continuous") RuntimeRulesUrl (string, default "/api/agent/runtime-rules") This payload is DATA, not code. It can only tune parameters of the capabilities already declared in the binary. It cannot introduce new capabilities. There is no code-loading, no plugin path, no scripting interpreter shipped in the collector. A compromised or malicious API endpoint could turn existing features on or off within the capability envelope; it cannot add a keylogger, screen capture, or DPAPI decryption of another application's secrets to a binary that does not contain those APIs in the first place. 3f. DYNAMIC API RESOLUTION (LoadLibrary / GetProcAddress) A static P/Invoke list cannot see APIs resolved by string at runtime. This is the classic evasion technique a determined developer would use to defeat a decompiler-based audit. The specific patterns are named APIs and managed types, all of which are grep-checkable in the source. Grep of the entire collector codebase for every dynamic-resolution pattern returns ZERO call sites: kernel32.LoadLibrary / LoadLibraryEx -> not called kernel32.GetProcAddress -> not called System.Runtime.InteropServices.NativeLibrary -> not called Marshal.GetDelegateForFunctionPointer -> not called System.Reflection.Assembly.Load / LoadFile -> not called System.Reflection.Assembly.LoadFrom / UnsafeLoadFrom -> not called System.Runtime.Loader.AssemblyLoadContext -> not referenced System.Reflection.Emit (dynamic IL) -> not called System.Runtime.CompilerServices.Unsafe (raw ptr) -> not called Type.GetType(string) reflection dispatch -> not called Activator.CreateInstance(string, ...) -> not called System.Diagnostics.Process.Start -> not called in the collector assemblies (Host, Core, CloudPublisher). It exists only in the separate VeraSetup installer, whose visible job is launching msiexec; the installed service binary cannot start other programs. The collector's entire native API surface is therefore the seven statically- declared P/Invoke methods listed in Section 2. There is no code path that resolves an unlisted Windows API dynamically. Verifiable by running grep on the shipping source with each of the strings above. 3g. RUNTIME OBSERVATION (beyond this sandbox run) The sandbox in Section 1 observed the installer's process tree, which does not include the long-running Windows service the installer registers. That service's network destinations are enumerated statically in Section 3c above. A user who wants to observe the running service's actual behavior on their own machine can do so with: Get-NetTCPConnection -OwningProcess (Get-Process VeraProcessCollector.Host).Id Resource Monitor (Network tab, filter by process name) Wireshark (capture on the local interface, filter by IP) Any destination other than the ApiBaseUrl host or a presigned S3 URL issued in the current session is a bug the source cannot produce. --- 4. INSTALLER IDENTITY --- Published SHA-256: 67533dc573b4c52ebdc32d13105455192d6e5843c231d8f0906c45d581362322 Live checksum URL: https://www.veraproject.xyz/api/agent/msi/checksum?v=0.3.11 Local verification (PowerShell): Get-FileHash VeraSetup.exe -Algorithm SHA256 If your local file's SHA-256 matches the published SHA-256, AND the sandbox's sample SHA-256 above matches the same value, then the same file exists at every link in this chain and no modified impostor was inserted in between. ===== END EVIDENCE BUNDLE =====