WasmForge — Go および C# プログラムを、ポリモーフィックな出力を備えたシングルバイナリの WASM サンドボックス化ネイティブ実行ファイルにコンパイルします。
WasmForge は Go および C# プログラムを WebAssembly にコンパイルし、単一のネイティブバイナリとしてパッケージ化します。生成された実行ファイルは、WASM ランタイム(ビルドごとにフォークされた wazero)内でゲストコードをサンドボックス化します。そのサンドボックス内から、ゲストはネットワーキング、raw ソケット、Win32 API、macOS フレームワーク API への透過的なアクセスを得られます。
net.Dial、net.Listen、net/http を使用して通常の Go コードを記述できます。また、既存の .NET Framework C# プロジェクトを移行することもできます。いずれの場合も、出力は Windows または macOS で動作する単一のバイナリであり、ユーザーがゲストソースを変更する必要はありません。

このプロジェクトをひと目見れば、LLM を多用して開発されたことがかなり明白でしょう。ドキュメントの一部も同様ですが、このセクションは違います。この README のスロップを取り除き、WasmForge を実際に使うプロセスを可能な限りわかりやすくすることに努めました。また、LLM は自分の成果を大きく持ち上げるドキュメントを書きますが、制限事項はそれほど明確にはされません。
期待値を適切に設定するために言っておくと、これは Go のさまざまな機能でテストされていますが、すべての Go プログラムに対応する完全なソリューションではありません。win32 API のかなりの割合がまだ適切にサポートされていません(コールバックサンクを必要とする API など)。たとえば Sliver はかなりの数のコマンドで動作しますが、機能面で完全な 1:1 移植ではありません。たとえば ls は、WASM ブロブが Windows 内にいることを完全に認識させられていないため、従来の C:\ パスではなく / を含むパスを表示します。クラッシュするだけの機能もあります。実際のターゲットで使用する前に、使用したい機能を必ずテストしてください。 動作しないものがある場合は、壊れている API の最も基本的な例を作成し、issue を開くか PR を送信してください。
C# 側は、最終的には実装というよりも概念実証です。C# を WASM にコンパイルするプロセスはあまりにも実験的であり、そのため、WasmForge はプログラムを実行可能にするために、そのかなりの部分を書き換える必要がしばしば発生します。結局のところ、この機能に深入りしすぎたかもしれません。人々に LLM を使って C# コードを Go コードとして書き直すことを勧めるべきだったでしょう。おそらくそのほうが苦痛が少ないです。とはいえ、C# -> Wasm -> WasmForge という一般的なパターンは機能し、C# 固有の検出のかなりの数を回避できます。
その点について言えば、WasmForge は主に静的検出への対処を目的としています。トランスパイルプロセスは、インメモリスキャンであってもほとんどの検出を回避します。ただし、バイナリ内に mimikatz や sliver のような非常に明白な文字列が含まれている場合、労力の少ないインメモリスキャンで検出される可能性があります。文字列の自動難読化は、自動化が比較的容易な機能であるため、将来追加される可能性があります。ただし、最初のパスでは、デバッグを比較的簡単に保つためにビルドパイプラインに追加の複雑さを加えたくありませんでした。
このリポジトリのソースコードを整理・統合する努力は行われてきましたが、まだかなり整理されていません。テストプロセスごとに異なるフォルダがいくつかあります。基本的な単体テストは examples/ と test/ に置かれる傾向があり、本格的なラボ環境で実行することを意図したより複雑なテストは testdata/ に置かれています。また、scripts/ と internal/devtools フォルダには、開発/テスト専用のツールが多数あります。これらは、独自のテスト環境をセットアップしてさらなる開発を行おうとする場合にのみ必要です。一般に、このような複雑なものを LLM で開発するには、生成を導くための非常に明示的なテストケースが多数必要であり、そうでなければまったく動作しないものができあがります。このプロジェクトにはこれらのハーネスが含まれているため、興味のある人は誰でもツールの開発を進めたり、プロジェクトに貢献したりできます。
コミュニティがこのツールを比較的使いやすいと感じてくれれば幸いです。そして、時間をかけて改善を続けていきます。いつか C# のコンパイルが Go のコンパイルと同じくらい実際に機能するようになるかもしれません。
wasmforge を入手する方法は 3 つあります。
プリビルドバイナリ。 Releases ページ から リリースを取得してください。Linux、macOS、Windows ビルドの CLI が各タグに添付されています。
Docker イメージ。 C# / .NET プロジェクト向けに、バンドルされたイメージには
すべての前提条件(.NET 10 SDK、NativeAOT-LLVM ワークロード、WASI SDK 24.0、wasm-ld、
osslsigncode)がプリインストールされています。make docker-build で一度ビルドし、
make docker-run で実行してください。完全なワークフローについては
docs/CSHARP.md を参照してください。これは C# に推奨される方法です。
ソースからビルド。
make build
make build は埋め込まれた internal/build/build_assets.tar.gz を再生成してから CLI をコンパイルします。単に go build -o wasmforge ./cmd/wasmforge を実行しただけでも動作するバイナリは得られますが、ディストリビューションモードのビルド
(CLI がこのソースツリーの外で実行される場合)では古い埋め込みアーカイブが使用されます。
詳細な説明については CONTRIBUTING.md を参照してください。
examples/ ディレクトリには、すぐにビルドできる実行可能な Go プログラムがあります。完全な一覧は examples/README.md を参照してください。
GOOS=windows GOARCH=amd64 ./wasmforge build \
--ghost traefik \
-o myapp.exe \
/path/to/your/project
Win32 API ブリッジは GOOS=windows のときに自動的に有効になります。通常のケースでは --win32-apis を渡す必要はなくなりました。
--ghost traefik は、埋め込まれた gopclntab シンボル分布を Traefik リバースプロキシのように見えるように置き換えます。バンドルされているプロファイルの中で、これが最も低い VirusTotal 検出率を実現します。他のプロファイルと独自のプロファイルを生成する手順は docs/GHOST-PROFILES.md にあります。
Windows ターゲットはデフォルトで自己署名証明書によって自動署名されます。--sign google.com を使用してドメインの TLS 証明書を偽装するか、--no-sign を使用して署名を完全に無効にします。
# 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
追加のフラグは必要ありません。macOS フレームワークブリッジは GOOS=darwin のときに自動的に有効になります。フレームワークブリッジ、purego/ObjC サポート、その他の Apple 固有の注意事項については docs/MACOS.md を参照してください。
# 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# プロジェクト(.csproj ファイル)は自動検出されます。WasmForge は、NativeAOT-WASI の移行、パッチ、ビルドのパイプライン全体を 1 つのコマンドで実行します:
GOOS=windows GOARCH=amd64 ./wasmforge build --win32-apis -o seatbelt.exe path/to/Seatbelt/Seatbelt/
C# の作業には Docker ビルド環境を強くお勧めします。すべての前提条件(.NET 10 SDK、NativeAOT-LLVM ワークロード、WASI SDK 24.0、wasm-ld)がバンドルされているため、ホストにそれらをインストールする必要はありません。完全な手順は 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 は WASM と基盤となるホストの間のギャップを埋めるため、ゲストプログラム側で対応する必要はありません。
プラットフォーム API。 TCP、UDP、DNS、HTTP、TLS、raw ソケットは、Windows と macOS の両方でゲストコードの変更なしに動作します。Windows では、WasmForge はレジストリ、ファイル I/O、プロセス、DLL ロード、最大 15 引数の SyscallN など、Win32 の全機能をプロキシします。ポインタ変換は自動です。COM vtable チェーンはミラーリングされるため、CLR やその他の COM を多用する API がエンドツーエンドで動作します。macOS では、dlopen と dlsym が任意のフレームワーク(Security、CoreGraphics、IOKit など)に到達でき、ebitengine/purego と Objective-C ランタイムがそのまま動作します。
.NET ホスティングと移行。 CLR は標準のチェーン(CoInitializeEx、CLRCreateInstance、Load_3、Invoke_3)を通じてロードされます。AMSI は起動時にパッチされるため、Assembly.Load(byte[]) が既知のツールをブロックしません。別の NativeAOT-WASI パイプラインは、既存の .NET Framework プロジェクトを取得し、ターゲットに .NET ランタイムを必要としない単一の Windows PE バイナリを生成します。
ホストメモリとシェルコード。 VirtualAlloc をバックエンドとするホストメモリプロキシは、ゲスト内部から到達可能です。これにより、WASM サンドボックスから脱出することなく、COFF/BOF ローダーとシェルコード実行が可能になります。
協調的ヨールド。 ブロッキング Win32 API(Sleep、WaitForSingleObject、ReadFile など)は WASM ゴルーチンをフリーズさせません。ホストはバックグラウンドのゴルーチンで呼び出しをディスパッチし、結果が準備できるまでゲストにヨールドを指示します。
ポリモーフィックな出力。 すべてのビルドは構造的に一意なバイナリを生成します。WASM オペコードは並べ替えられ、セクション ID とマジックバイトはランダム化され、すべての識別子、PE インポート、VERSIONINFO 文字列、ライセンスブロック、ソースファイル名がスクラブされます。バンドルされた wazero フォークは、並べ替えられたバイトコードに一致するように書き換えられます。ゴーストプロファイリングは、実際のエンタープライズ Go バイナリ(Traefik、Caddy、Terraform)に一致するように gopclntab シンボルを書き換えます。Windows の出力はデフォルトで Authenticode 署名され、自己署名または osslsigncode による実際のドメインの TLS 証明書の偽装のいずれかです。