WasmForge — compile des programmes Go et C# en exécutables natifs monobinaires, sandboxés par WASM, avec une sortie polymorphe.
WasmForge compile des programmes Go et C# en WebAssembly, puis les empaquette sous forme de binaires natifs uniques. Les exécutables résultants font tourner le code invité en sandbox dans un runtime WASM (un fork par build de wazero). Depuis l'intérieur de ce sandbox, les invités bénéficient d'un accès transparent à la mise en réseau, aux sockets brutes, aux API Win32 et aux API des frameworks macOS.
Vous pouvez écrire du Go normal en utilisant net.Dial, net.Listen ou net/http. Vous pouvez également migrer un projet C# .NET Framework existant. Dans les deux cas, le résultat est un binaire unique qui s'exécute sur Windows ou macOS, sans que l'utilisateur ait à modifier le code source de l'invité.

Un coup d'œil rapide à ce projet suffit pour comprendre qu'il a été développé avec une utilisation MASSIVE de LLM. Une partie de la documentation aussi — mais pas cette section. J'ai fait de mon mieux pour déslopifier ce README tout en rendant le processus d'utilisation de WasmForge aussi simple que possible. Et bien que les LLM écrivent une documentation qui encense lourdement leurs propres réalisations, les limites ne sont pas rendues TOUT À FAIT aussi claires.
Pour bien fixer les attentes : même si cela a été testé avec de nombreuses fonctionnalités différentes pour Go, ce n'est PAS une solution complète pour tous les programmes Go. Il reste encore un bon pourcentage de l'API Win32 qui n'est pas correctement pris en charge (comme les API qui nécessitent des thunks de rappel). Sliver, par exemple, fonctionne pour un bon nombre de commandes, mais ce n'est PAS un port 1:1 complet en termes de fonctionnalités. , par exemple, affichera toujours des chemins avec des au lieu du cheminement traditionnel , car le blob WASM n'est pas complètement dupe et ne réalise pas qu'il est sous Windows. D'autres capacités déclencheront tout simplement un crash. Si quelque chose ne fonctionne pas, essayez de construire l'exemple le plus basique de l'API qui est cassée et ouvrez une issue / soumettez une PR.
ls/C:\Le versant C# est au final plus une preuve de concept qu'une implémentation. Le processus utilisé pour compiler le C# vers WASM est trop expérimental, ce qui signifie que WasmForge doit souvent réécrire une bonne partie du programme de toute façon pour le faire fonctionner. Au final, je me suis probablement trop enfoncé dans ce terrier de lapin sur cette capacité et j'aurais simplement dû recommander aux gens d'utiliser un LLM pour réécrire le code C# en code Go. C'est probablement moins pénible à gérer. Cela dit, le schéma général C# -> Wasm -> WasmForge fonctionne VRAIMENT et il casse effectivement un bon nombre de détections spécifiques au C#.
À ce propos — WasmForge est avant tout conçu pour faire face aux détections STATIQUES. Le processus de transpilation casse la plupart des détections, même pour l'analyse en mémoire, mais au final, si votre binaire contient des chaînes très évidentes comme mimikatz ou sliver, certains scans en mémoire à faible effort déclencheront une détection. L'obfuscation automatique des chaînes sera probablement ajoutée à l'avenir, car c'est une fonctionnalité assez facile à automatiser, mais pour une première passe, je ne voulais pas ajouter de complexité supplémentaire au pipeline de build afin de garder le débogage relativement simple.
Bien que des efforts aient été faits pour nettoyer/consolider le code source de ce dépôt, il reste encore assez désorganisé. Il y a plusieurs dossiers différents pour différents processus de test. Les tests unitaires de base se trouvent généralement dans examples/ et test/, tandis que certains des tests les plus complexes, destinés à être exécutés dans un environnement de lab complet, se trouvent dans testdata/. Il y a aussi un certain nombre d'outils réservés au développement et aux tests dans les dossiers scripts/ et internal/devtools. Ils ne seront nécessaires que si vous cherchez à mettre en place votre propre environnement de test pour poursuivre le développement. En général, tout développement par LLM d'un projet aussi complexe nécessite un grand nombre de cas de test très explicites pour guider la génération, sinon on aboutit à quelque chose qui ne fonctionne pas du tout. Le projet inclut ces bancs de test afin que toute personne curieuse puisse approfondir son propre développement d'outillage ou contribuer au projet.
Espérons que la communauté trouvera cet outillage relativement facile à utiliser et que nous continuerons à l'améliorer au fil du temps. Peut-être qu'un jour la compilation C# fonctionnera aussi bien que la compilation Go.
Il y a trois façons d'obtenir wasmforge :
Binaire précompilé. Téléchargez une release depuis la page Releases — les builds Linux, macOS et Windows de la CLI sont attachés à chaque tag.
Image Docker. Pour les projets C# / .NET, l'image fournie embarque tous les
prérequis (.NET 10 SDK, workload NativeAOT-LLVM, WASI SDK 24.0,
wasm-ld, osslsigncode) préinstallés. Construisez-la une fois avec
make docker-build et pilotez-la avec make docker-run — voir
docs/CSHARP.md pour le workflow complet. C'est la
voie recommandée pour le C#.
Compilation depuis les sources.
make build
make build régénère l'archive embarquée internal/build/build_assets.tar.gz
puis compile la CLI. Si vous exécutez simplement go build -o wasmforge ./cmd/wasmforge, vous obtiendrez un binaire fonctionnel, mais les builds
en mode distribution (lorsque la CLI s'exécute en dehors de cet arbre
source) utiliseront une archive embarquée obsolète. Voir
CONTRIBUTING.md pour l'explication complète.
Le répertoire examples/ contient des programmes Go exécutables que vous pouvez compiler immédiatement. Voir examples/README.md pour la liste complète.
GOOS=windows GOARCH=amd64 ./wasmforge build \
--ghost traefik \
-o myapp.exe \
/path/to/your/project
Le pont d'API Win32 est activé automatiquement dès que GOOS=windows — vous n'avez plus besoin de passer --win32-apis dans le cas courant.
--ghost traefik remplace la distribution de symboles gopclntab embarquée pour ressembler au reverse proxy Traefik. Parmi les profils fournis, c'est celui qui produit le taux de détection VirusTotal le plus bas. Les autres profils et les instructions pour générer les vôtres se trouvent dans docs/GHOST-PROFILES.md.
Les cibles Windows sont signées automatiquement avec un certificat auto-signé par défaut. Utilisez --sign google.com pour usurper le certificat TLS d'un domaine, ou --no-sign pour désactiver entièrement la signature.
# 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
Aucun drapeau supplémentaire n'est requis. Le pont de frameworks macOS s'active automatiquement dès que GOOS=darwin. Voir docs/MACOS.md pour le pont de frameworks, le support purego/ObjC et les autres notes spécifiques à Apple.
# 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" ...
Les projets C# (fichiers .csproj) sont détectés automatiquement. WasmForge exécute l'intégralité du pipeline de migration, de patch et de compilation NativeAOT-WASI en une seule commande :
GOOS=windows GOARCH=amd64 ./wasmforge build --win32-apis -o seatbelt.exe path/to/Seatbelt/Seatbelt/
Pour le travail en C#, nous recommandons vivement l'environnement de build Docker. Il regroupe tous les prérequis (.NET 10 SDK, workload NativeAOT-LLVM, WASI SDK 24.0, wasm-ld) afin que vous n'ayez à en installer aucun sur l'hôte. Les instructions complètes se trouvent dans docs/CSHARP.md.
wasmforge build [package] Compile Go (or C#) package to a WASM-sandboxed native binary
-o, --output <path> Output binary path
--ghost <name> Ghost profile: traefik, caddy, terraform (see docs/GHOST-PROFILES.md)
--raw-sockets Enable raw socket support
--win32-apis Enable Win32 API bridge (Windows targets)
--sign <mode> Sign binary: 'self' or domain name (default: self for Windows)
--no-sign Disable default auto-signing for Windows targets
--tags <tags> Go build tags (comma-separated)
--pe-company / --pe-product / --pe-description / --pe-copyright / --pe-file-version
PE VERSIONINFO overrides
-v, --verbose Verbose build output
wasmforge run [package] Build and immediately execute
wasmforge clean Remove cached patched GOROOTs (~/.wasmforge/cache/)
wasmforge version Print version
wasmforge dotnet-migrate <dir> Migrate .NET Framework project to .NET 10 NativeAOT-WASI
wasmforge dotnet-patch <dir> Apply NativeAOT-WASI C# source patches
WasmForge comble le fossé entre WASM et l'hôte sous-jacent afin que les programmes invités n'aient pas à le faire.
API de plateforme. TCP, UDP, DNS, HTTP, TLS et sockets brutes fonctionnent sans modification du code invité, sur Windows comme sur macOS. Sur Windows, WasmForge agit comme proxy pour toute la surface Win32 : registre, entrées/sorties fichier, processus, chargement de DLL et SyscallN avec jusqu'à 15 arguments. La traduction de pointeurs est automatique. Les chaînes de vtable COM sont répliquées afin que le CLR et les autres API fortement basées sur COM fonctionnent de bout en bout. Sur macOS, dlopen et dlsym atteignent n'importe quel framework (Security, CoreGraphics, IOKit, etc.), et ebitengine/purego ainsi que le runtime Objective-C fonctionnent directement.
.NET : hébergement et migration. Le CLR se charge via la chaîne standard (CoInitializeEx, CLRCreateInstance, Load_3, Invoke_3). AMSI est patché au démarrage afin que Assembly.Load(byte[]) ne bloque pas les outils connus. Un pipeline séparé NativeAOT-WASI prend les projets .NET Framework existants et produit des binaires Windows PE uniques, sans runtime .NET requis sur la cible.
Mémoire hôte et shellcode. Un proxy mémoire hôte adossé à VirtualAlloc est accessible depuis l'intérieur de l'invité. Cela rend possibles les chargeurs COFF/BOF et l'exécution de shellcode sans sortir du sandbox WASM.
Cession coopérative (yield). Les API Win32 bloquantes (Sleep, WaitForSingleObject, ReadFile, etc.) ne gèlent pas les goroutines WASM. L'hôte délègue l'appel à une goroutine d'arrière-plan et signale à l'invité de céder la main jusqu'à ce que le résultat soit prêt.
Sortie polymorphe. Chaque build produit un binaire structurellement unique. Les opcodes WASM sont permutés, les identifiants de section et les octets magiques sont randomisés, et chaque identifiant, import PE, chaîne VERSIONINFO, bloc de licence et nom de fichier source est nettoyé. Le fork wazero embarqué est réécrit pour correspondre au bytecode permuté. Le profilage fantôme réécrit les symboles gopclntab pour correspondre à de vrais binaires Go d'entreprise (Traefik, Caddy, Terraform). Les sorties Windows sont signées Authenticode par défaut, soit auto-signées, soit en usurpant le certificat TLS d'un domaine réel via osslsigncode.
+-------------------- WASM Guest (wasip1) --------------------+
| |
| Your Go Program (net, net/http, os; works transparently) |
| |
+----------- go:wasmimport ABI (custom opcodes) --------------+
|
+----------- Host Runtime (per-build wazero fork) ------------+
| |
| 90+ host functions (networking, OS proxies, platform APIs) |
| Windows: pointer translation, shadow memory, COM mirroring |
| macOS: dlopen/dlsym framework bridge, ABI trampolines |
| |
+----------- wazero (custom VM: permuted opcodes/magic) ------+
|
OS Kernel / Windows APIs / macOS Frameworks
Le pipeline de build se déroule en six étapes.
syscall/ et net/ pour la mise en réseau WASM. Mis en cache dans ~/.wasmforge/cache/.GOOS=wasip1 GOARCH=wasm contre la stdlib patchée. Des auto-stubs couvrent les lacunes spécifiques aux plateformes. Des sysshims pour golang.org/x/sys et ebitengine/purego sont injectés lorsque ces imports sont présents.main.go polymorphe avec des identifiants randomisés, un fork wazero correspondant par build, des ressources PE intégrées et -trimpath.osslsigncode.WasmForge compile et exécute des projets Go tiers non modifiés, y compris ceux qui contiennent du code complexe spécifique à une plateforme.
| Programme | Plateforme | Description | Validé |
|---|---|---|---|
| Sliver | Windows | Framework C2, usage intensif de Win32 | Beacon HTTPS, whoami, ps, netstat, execute-assembly (Rubeus, Seatbelt) |
| Sliver | macOS | Framework C2 (beacon + session) | pwd, ls, download, execute, proxy SOCKS5 |
| go-clr | Windows | Hébergement CLR .NET + exécution d'assemblys | Chaîne de chargement CLR, triage Rubeus, scan système Seatbelt |
| Chisel | Windows | Tunnel TCP/UDP sur HTTP avec SOCKS5 | Connectivité du tunnel, forwarding du proxy |
| Ligolo-ng | Windows | Tunneling et pivot avancés | Interface TUN, connectivité de l'agent |
| goffloader | Windows | Chargeur COFF/BOF utilisant unsafe.Pointer | VirtualAlloc, exécution de shellcode, parsing PE, résolution IAT |
Programmes .NET NativeAOT-WASI :
| Programme | Plateforme | Description | Validé |
|---|---|---|---|
| Seatbelt | Windows | Énumération de sécurité | La plupart des commandes passent ; quelques-unes, qui nécessitent la distribution de callbacks WMI / Defender, sont honnêtement stubées en attendant le support du pont. |
| Rubeus | Windows | Outillage Kerberos | Les opérations de hash et de token fonctionnent directement ; les verbes réseau (asktgt, kerberoast, asreproast) passent par le pont TCP ; les requêtes LSA (klist, logonsession) correspondent aux références natives. |
Voir docs/BUILDING-SLIVER.md pour un guide pas à pas de Sliver, et docs/CSHARP.md pour le pipeline C#.
WasmForge s'exécute sur des hôtes de build Linux, macOS ou Windows. Go 1.25 ou plus est requis.
Quelques fonctionnalités nécessitent une configuration supplémentaire. Les sockets brutes nécessitent CAP_NET_RAW ou root. Le pont Win32 nécessite une cible Windows avec --win32-apis (les autres cibles renvoient ENOSYS). Le pont de frameworks macOS nécessite une cible macOS et est détecté automatiquement via GOOS=darwin. La signature de code nécessite osslsigncode dans le PATH. Les projets C# nécessitent le SDK .NET 10, le workload NativeAOT-LLVM et le WASI SDK 24.0. Alternativement, l'image Docker fournie (décrite dans docs/CSHARP.md) est livrée avec tout cela préinstallé.
Le banc de test de parité (test/parity/) et les scripts de montage du lab sous scripts/lab-setup/ supposent en outre un domaine Active Directory mis en place avec Ludus exécutant GOAD (Game of Active Directory) — chaque valeur par défaut codée en dur sevenkingdoms.local / kingslanding / SEVENKINGDOMS-CA est une valeur par défaut de GOAD, remplaçable via les variables d'environnement WASMFORGE_PARITY_* (voir test/parity/internal/lab/lab.go). Voir docs/internals/PARITY-HARNESS.md et docs/internals/LAB-STABILITY.md pour la configuration complète du lab.
Commencer ici
| Sujet | Document |
|---|---|
| Exemples exécutables (scanner TCP, serveur HTTP, ping ICMP) | examples/README.md |
| Build de Sliver de bout en bout (Windows + macOS) | docs/BUILDING-SLIVER.md |
| Compilation de projets C# / .NET (workflow Docker) | docs/CSHARP.md |
| Cibles macOS et pont de frameworks | docs/MACOS.md |
| Utilisation des profils fantômes et création de profils personnalisés | docs/GHOST-PROFILES.md |
Variables d'environnement au moment du build (recette R80, chaque réglage WASMFORGE_*) | docs/ENVIRONMENT.md |
Aller plus loin
| Sujet | Document |
|---|---|
| Architecture — module hôte, pipeline de build, décisions de conception | docs/ARCHITECTURE.md |
| Contribution — organisation du dépôt, prérequis, ajout de fonctions hôtes | CONTRIBUTING.md |
| Politique de sécurité + divulgation | SECURITY.md |
| Code de conduite | CODE_OF_CONDUCT.md |
Références pour les mainteneurs
| Sujet | Document |
|---|---|
| Contrat d'API hôte — exports enregistrés, stabilité des signatures | docs/internals/HOST-API-CONTRACT.md |
| Internes du patcher AST — règles de remplacement de chaînes et dispatch | docs/internals/AST-PATCHER.md |
| Banc de test de parité — exécution des différences C# natif vs WASM | docs/internals/PARITY-HARNESS.md |
| Stabilité du lab — configuration du domaine Ludus + GOAD, scripts de surveillance (watchdog) | docs/internals/LAB-STABILITY.md |
Copyright (c) 2025-2026 Praetorian Security, Inc.