# Vasl process capture

This crate captures ordinary public IPv4 TCP/UDP emitted by one executable
basename, such as `cs2.exe`, using the unmodified WinDivert 2.2.2 x64 API.
It does not use a default route, game injection, `PROCESS_VM_READ`,
`SeDebugPrivilege`, or a permanent network-interface change.

`ProcessCapture::open(name)` starts the session; `try_read(buffer)` is
nonblocking, `write(packet)` injects a reply only into an already observed
reverse five-tuple, `stats()` exposes counters, and `close()`/`Drop` ends
interception and joins the capture worker. Other applications' packets are
reinserted with their bytes and original checksum/offload metadata unchanged,
including fragments. Checksum repair runs only on selected, edited or newly
constructed packets, because incomplete fragments have no calculable full
transport checksum.

Connect Vasl before starting a fresh game connection. Only an initial TCP SYN
can be adopted. If that SYN was sent directly, its retransmissions and later
segments remain direct for that connection generation. Connections established
before capture stay direct. Restarting the game after connecting is the clearest
acceptance procedure.

Ownership uses fresh IP Helper owner-PID tables from both address families when
classification is needed, and limited process queries for executable image and
process creation time. IPv4-mapped and wildcard IPv6 socket rows are considered
because a dual-stack socket can emit IPv4 packets; native IPv6 routing is unchanged.
UDP wildcard binds are supported; multiple distinct owners are ambiguous and
never guessed. An unspecified IPv6 UDP row can also create ambiguity because
the table does not expose its IPV6_V6ONLY setting. An unknown first packet gets
one additional query after 1 ms.
Unknown UDP is not cached. Known UDP decisions are cached for at most 25 ms;
very fast socket/port reuse within that window remains a limitation. This is
normal game routing, **not a strict network isolation boundary**. Unresolved
owners, IPv6 and unclassifiable fragments remain direct and cannot be claimed
to be fully tunneled. DNS owned by the Windows DNS service is another process.
Private, local, multicast and reserved IPv4 destinations remain direct.

The complete inner packet limit is 1380 bytes, including IPv4 and transport
headers; UDP payload can be at most 1352 bytes with ordinary 20-byte IPv4 and
8-byte UDP headers. TCP SYN MSS is capped at 1340. An oversized selected packet
is dropped and the sender receives a local ICMP fragmentation-needed response
advertising MTU 1380. This uses the same packet-injection handle, not a raw
socket or a server ICMP permission change.

The selected-packet queue holds at most 512 complete datagrams; overflow drops
only the selected packet and is counted. The driver queue and flow maps are
also bounded. Reverse-path interface metadata is keyed by both addresses,
both ports and protocol. A missing or expired reply mapping returns `NotFound`
instead of guessing an interface. Capture errors release the driver handle;
shutdown first stops new interception, drains intercepted traffic, then closes
the handle. The native worker logs counters during activity every 30 seconds
and once on exit: selected, returned, direct, unknown owner, dropped, oversized,
read errors and reinjection errors.

## Driver provenance and loading

The default loader expects `WinDivert.dll` and `WinDivert64.sys` beside the
running x64 executable. The installer uses its protected installation directory;
the portable distribution deliberately remains supported. Both files are opened
with read sharing only, denying writes and deletion, hashed before loading and
held open while in use. Loading uses an absolute path and
`LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR | LOAD_LIBRARY_SEARCH_SYSTEM32`, never a bare
DLL name, current-directory search, or PATH search.

The following hashes were calculated from the official HTTPS release archive;
they are release pins, not a claim that the upstream separately published hashes.

| File | SHA-256 |
| --- | --- |
| WinDivert-2.2.2-A.zip | `63cb41763bb4b20f600b6de04e991a9c2be73279e317d4d82f237b150c5f3f15` |
| x64/WinDivert.dll | `c1e060ee19444a259b2162f8af0f3fe8c4428a1c6f694dce20de194ac8d7d9a2` |
| x64/WinDivert64.sys | `8da085332782708d8767bcace5327a6ec7283c17cfb85e40b03cd2323a90ddc2` |

The WinDivert source and LGPLv3/GPLv2 license accompany the distribution. Static
signature inspection found a Microsoft Windows Hardware Compatibility Publisher
signature and matching PE digest on the stock SYS. That does not replace Windows
kernel signature validation or an actual driver-load acceptance test. Windows
may reject a blocked or incompatible driver; such failure is reported, never
worked around by disabling signature enforcement.

## Administrator-controlled library replacement

To permit a compatible modified WinDivert library, the loader also supports an
explicit machine administrator override. It reads only the 64-bit registry view
of `HKEY_LOCAL_MACHINE\SOFTWARE\Vasl\WinDivert`, using these **REG_SZ** values:

| Value | Meaning |
| --- | --- |
| `Directory` | Absolute local drive directory containing `WinDivert.dll` and `WinDivert64.sys` |
| `DllSha256` | Exactly 64 hexadecimal characters for that DLL |
| `SysSha256` | Exactly 64 hexadecimal characters for that SYS |

All three values are required if the key exists. The key must retain an owner
and write permissions restricted to SYSTEM and the built-in Administrators group;
an unprotected key, malformed setting or hash mismatch is an error, not fallback.
No environment variable, HKCU entry or user configuration file can choose code
for this elevated process. Replacement files receive the same hash verification,
file locks and restricted loading rules; the administrator supplies the hashes
of their chosen compatible version. The WinDivert 2.2 ABI and Windows driver
signing requirements still apply. Deleting only this override key restores the
stock loader on the next session. Vasl does not change the override itself.

Administrator registry settings must be created in a protected machine location,
not populated from untrusted instructions or an automatic download. This is the
documented mechanism for library modification/replacement, not an option shown
to ordinary game users.

## Validation status

Pure Rust tests cover malformed packets, complete tuples, wildcard/ambiguous
ownership, PID creation time, TCP initial-SYN policy, UDP revalidation, packet
queue limits and the local MTU response. Windows cross-compilation checks the
native ABI wrapper and API calls. Running the signed driver, simultaneous game
and non-game traffic, shutdown, and actual CS2 traffic still require Windows
acceptance; a successful Linux test or cross-build is not that acceptance.

Official references: [WinDivert documentation](https://reqrypt.org/windivert-doc.html),
[upstream 2.2.2 release](https://github.com/basil00/WinDivert/releases/tag/v2.2.2),
[TCP owner rows](https://learn.microsoft.com/en-us/windows/win32/api/tcpmib/ns-tcpmib-mib_tcprow_owner_pid),
[UDP owner rows](https://learn.microsoft.com/en-us/windows/win32/api/udpmib/ns-udpmib-mib_udprow_owner_pid),
[limited image queries](https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-queryfullprocessimagenamew).
