WasmForge — compile Go and C# programs to single-binary, WASM-sandboxed native executables with polymorphic output.
WasmForge compiles Go and C# programs to WebAssembly, then packages them as single native binaries. The resulting executables sandbox guest code inside a WASM runtime (a per-build fork of wazero). From inside that sandbox, guests get transparent access to networking, raw sockets, Win32 APIs, and macOS framework APIs.
You can write normal Go using net.Dial, net.Listen, or net/http. You can also migrate an existing .NET Framework C# project. Either way, the output is a single binary that runs on Windows or macOS, without requiring the user to make modifications to the guest source.

A quick glance at this project will make it fairly obvious that this was developed with some HEAVY usage of LLMs. A chunk of the documentation has been as well - but this section is not. I've done my best to de-slopify this README along with making the process for actually using WasmForge as straightforward as possible. Also while the LLMs will write documentation that heavily glazes its own accomplishments, the limitations aren't made QUITE as clear.
To set expectations properly, while this has been tested with lots of different features for Go, it is NOT a complete solution for all Go programs. There's still a healthy % of the win32 API that is not properly supported (like APIs that require callback thunks). Sliver, for example, works for a healthy number of commands but it is NOT a full 1:1 port with functionality. ls, for example, will still show paths with /s instead of the traditional C:\ pathing since the WASM blob isn't fully tricked into realizing its within Windows. There are other capabilities that will just trigger a crash. Make sure you test any functionality you want to use before trying to use it on a real target. If there's something that doesn't work, try to build out the most basic example of the API which is broken and open an issue / submit a PR.
The C# side of house is ultimately more proof-of-concept than implementation. The process that's used to compile C# to WASM is just too experimental and it means that WasmForge often needs to re-write a healthy amount of the program anyways to get it to run. Ultimately I probably rabbit holed too hard on this capability and should have just recommended people use an LLM to re-write C# code as Go code. It's probably less painful to deal with. That being said, the general pattern of C# -> Wasm -> WasmForge DOES work and it does break a healthy number of C#-specific detections.
On that note - WasmForge is primarily meant to deal with STATIC detections. The transpilation process breaks most detections, even for in-memory scanning, but ultimately if your binary has some very obvious strings like mimikatz or sliver in it there are some low-effort in-memory scans that will cause a detection. Automatic string obfuscation will likely be added in the future as it's a fairly easy feature to automate, but for the first pass I didn't want to add additional complexity to the build pipeline to keep debugging relatively straightforward.
While there has been some efforts to clean/consolidate the source code in this repository, it's still fairly disorganized. There's several different folders for different testing processes. Basic unit tests tend to live in examples/ and test/ while some of the more complex tests meant to be run in a full lab environment live in testdata/. There's also a number of development/testing only tools living in the scripts/ and internal/devtools folders. These will only be necessary if you're trying to setup your own test environment to do further development. In general any LLM development of something this complicated requires a number of very explicit test cases to guide generation otherwise you end up with something that doesn't work at all. The project includes these harnesses so anyone curious can further their own development of tooling or contribute to the project.
Hopefully the community finds this tooling relatively easy to use and over time we'll continue to improve this. Maybe one day C# compilation will actually work as well as Go compilation.
There are three ways to get wasmforge:
Prebuilt binary. Grab a release from the Releases page — Linux, macOS, and Windows builds of the CLI are attached to each tag.
Docker image. For C# / .NET projects, the bundled image ships every
prerequisite (.NET 10 SDK, NativeAOT-LLVM workload, WASI SDK 24.0,
wasm-ld, osslsigncode) preinstalled. Build it once with
make docker-build and drive it with make docker-run — see
docs/CSHARP.md for the full workflow. This is the
recommended path for C#.
Build from source.
make build
make build regenerates the embedded internal/build/build_assets.tar.gz
and then compiles the CLI. If you just run go build -o wasmforge ./cmd/wasmforge you'll get a working binary, but distribution-mode builds
(when the CLI runs outside this source tree) will use a stale embedded
archive. See CONTRIBUTING.md for the longer explanation.
The examples/ directory has runnable Go programs you can build right
away. See examples/README.md for the full menu.
GOOS=windows GOARCH=amd64 ./wasmforge build \
--ghost traefik \
-o myapp.exe \
/path/to/your/project
The Win32 API bridge is auto-enabled whenever GOOS=windows — you no
longer need to pass --win32-apis for the common case.
--ghost traefik swaps the embedded gopclntab symbol distribution to look like the Traefik reverse proxy. Of the bundled profiles, this one produces the lowest VirusTotal detection rate. Other profiles and instructions for generating your own live in docs/GHOST-PROFILES.md.
Windows targets are auto-signed with a self-signed certificate by default. Use --sign google.com to spoof a domain's TLS cert, or --no-sign to disable signing entirely.
# Intel
GOOS=darwin GOARCH=amd64 ./wasmforge build -o myapp /path/to/your/project
# Apple Silicon
GOOS=darwin GOARCH=arm64 ./wasmforge build -o myapp /path/to/your/project
No extra flags are required. The macOS framework bridge auto-enables whenever GOOS=darwin. See docs/MACOS.md for the framework bridge, purego/ObjC support, and other Apple-specific notes.
# Raw socket support (requires CAP_NET_RAW or root at build time)
./wasmforge build --raw-sockets -o myapp ./path/to/project
# Verbose output (useful for first builds)
GOOS=windows GOARCH=amd64 ./wasmforge build --ghost traefik --win32-apis -v -o tool.exe /path/to/project
# Custom PE VERSIONINFO (Windows only)
./wasmforge build --pe-company "Acme Corp" --pe-product "AcmeTool" --pe-file-version "10.0.19041.1" ...
C# projects (.csproj files) are auto-detected. WasmForge runs the full NativeAOT-WASI migration, patch, and build pipeline in one command:
GOOS=windows GOARCH=amd64 ./wasmforge build --win32-apis -o seatbelt.exe path/to/Seatbelt/Seatbelt/