# ysoserial.net: generating .NET deserialization payloads from the command line

> ysoserial.net wraps a command in a chosen .NET gadget chain and serializes it to stdout, so you can check whether an application that deserializes untrusted data is exploitable. It is a proof-of-concept tool for authorized testing, not a scanner.

**pwntester/ysoserial.net** — Deserialization payload generator for a variety of .NET formatters

- Repository: https://github.com/pwntester/ysoserial.net
- Stars: 3,795 · Forks: 527
- Language: C#
- License: MIT
- Published: 2026-09-23 · Updated: 2026-09-23 · Language: en
- Canonical page: https://hysenlabs.com/projects/pwntester-ysoserial-net

## What ysoserial.net generates, and for whom

The README describes the project as "a proof-of-concept tool for generating payloads that exploit unsafe .NET object deserialization." It is a collection of utilities and property-oriented programming gadget chains found in common .NET libraries. The driver takes a command you supply, wraps it in a gadget chain you select, and serializes the resulting object graph to stdout.

The audience is narrow. This is for security engineers and penetration testers who already know that a target deserializes untrusted input and want to demonstrate what that means in practice. The README is explicit that the vulnerability sits in the application performing unsafe deserialization, not in the presence of gadgets on the classpath. A library containing a usable gadget is not itself a bug; the bug is the application that feeds attacker-controlled bytes to a formatter that instantiates types.

The project states it was inspired by Chris Frohoff's ysoserial, which does the equivalent job for Java. The design follows the same idea: a catalog of chains, each tied to specific formatters and, often, specific framework versions.

## How a gadget chain becomes a serialized payload

The mechanism is property-oriented programming. A chain is a set of .NET types whose properties or deserialization callbacks, when reconstructed in the right order by a formatter, end up invoking code. ysoserial.net does not exploit the target directly. It builds an object graph and hands you the bytes.

The output format depends on the formatter you pick, and the help output lists the formatters each gadget supports. BinaryFormatter, LosFormatter, NetDataContractSerializer, SoapFormatter and Json.NET all appear in the gadget list. Some entries carry labels such as "Bridge and derived" or "OnDeserialized" or "SecondOrderDeserialization", and some note a supported formatter for the bridge, for example BinaryFormatter. That distinction matters: a bridge gadget is used to reach a derived gadget, and the bridge must be serializable by the formatter the target actually uses.

Several gadgets accept extra options. ActivitySurrogateSelector and ActivitySurrogateSelectorFromFile take a --var or --variant flag with choices 1 and 2, where variant 2 is described as shorter but possibly not working between versions. ActivitySurrogateSelectorFromFile treats the command parameter as a path to a .cs file to compile as the exploit class, with a semicolon separating the file from additional assemblies, as in '-c ExploitClass.cs;System.Windows.Forms.dll'. DataSetOldBehaviour exposes a --spoofedAssembly option for changing the assembly name recorded in the serialized object.

Some gadgets ignore the command entirely. ActivitySurrogateDisableTypeCheck is documented as disabling 4.8+ type protections for ActivitySurrogateSelector, with the command ignored. ActivitySurrogateSelector executes the constructor of the ExploitClass class and also ignores the command. BaseActivationFactory is listed for .NET 5/6/7 with WPF enabled or PresentationFramework.dll available, and leads to remote DLL loading of a native C/C++ DLL. These are not interchangeable, and the help text is the only reliable map.

## Installing ysoserial.net and running a first payload

There is no installer and no package feed. The README recommends downloading the latest build from the GitHub Actions page, and says previous releases are available from the releases page. The most recent tagged release listed is v1.36 from 2023-10-17, so the release page is behind the Actions artifacts.

If you build from source on Windows, the README gives a Chocolatey-based setup that installs Visual Studio 2022 Community, the native desktop workload, msbuild.communitytasks, nuget.commandline and git, then restores and builds the solution:

```powershell
choco install visualstudio2022community --yes
choco install visualstudio2022-workload-nativedesktop --yes
choco install choco install msbuild.communitytasks --yes
choco install nuget.commandline --yes
choco install git --yes

git clone https://github.com/pwntester/ysoserial.net
cd ysoserial.net
nuget restore ysoserial.sln
msbuild ysoserial.sln -p:Configuration=Release
```

After that build, the README shows the binary being invoked with the help flag to confirm it runs:

```bash
.\ysoserial\bin\Release\ysoserial.exe -h
```

On Linux the README uses a Nix flake and Mono. Note that this path restores the solution, builds it with the dotnet CLI, and then runs the binary from the Debug output directory, which is a discrepancy in the documented steps rather than a separate build configuration:

```bash
nix develop --impure
nuget restore ysoserial.sln
dotnet build ysoserial.sln --configuration=Release

mono ysoserial/bin/Debug/ysoserial.exe -h
```

For a first real use, the README shows the full help output being requested, which is where you read the gadget list, the formatters each gadget supports and the extra options:

```bash
./ysoserial.exe --fullhelp
```

Expect a long listing. Each entry names the gadget, the formatters it works with, labels such as "Bridge and derived", and any extra options with their default values. Pick the gadget whose formatter matches the target application, then generate the payload and redirect stdout to a file. The README does not document a flag for writing to a file, so the shell redirect is the mechanism.

## Where ysoserial.net is the wrong tool

The most common misuse is treating it as a scanner. It does not discover whether a target deserializes untrusted data, it does not fingerprint which formatter is in use, and it does not tell you whether the gadget assembly is loaded. The README states the condition plainly: the chain is invoked "when an application with the required gadgets on the classpath unsafely deserializes this data." If either half of that condition is missing, the payload does nothing, and the tool will still have produced a file.

Version sensitivity is the second trap. The variant option on ActivitySurrogateSelector is documented as variant 2 being shorter but possibly not working between versions, which is a direct admission that a payload can fail for reasons unrelated to the target's configuration. The ActivitySurrogateDisableTypeCheck gadget exists specifically because .NET 4.8 and later changed type protections, so payloads written against older runtimes do not carry over unchanged.

Finally, the project is explicitly scoped. The disclaimer says the software was created for academic research and for developing defensive techniques, and is not intended to attack systems except where explicitly authorized. It is a payload generator, not a post-exploitation framework: it does not deliver the payload, maintain a session, or handle authentication. Delivery is your problem, and it is usually the harder half.

## How it differs from frohoff/ysoserial

The README names the Java project as the inspiration, and the two share a shape: a driver, a catalog of chains, formatter-specific output. The difference is the runtime and therefore the entire gadget surface.

In the Java tool the chains are built from classes in the JDK and common Java libraries, and the output is typically a serialized Java object stream. Here the chains come from .NET assemblies, the formatters are BinaryFormatter, LosFormatter, NetDataContractSerializer, SoapFormatter and Json.NET, and the payload is whatever bytes that formatter produces. A gadget that works against a Java service has no meaning for a .NET one, and vice versa.

There is also a structural difference in the catalog itself. ysoserial.net exposes bridge gadgets and derived gadgets as separate labelled entries, and some gadgets exist only to reach another one. That layering is visible in the help output in a way that the Java tool's flat list of chain names is not. If you are moving between the two, expect to relearn the catalog rather than translate it.

## Maintenance, releases and the MIT licence

The repository is not archived, and the last push was on 2026-09-07. That is recent enough that the source tree is moving, but the tagged releases tell a different story: v1.36 dates from 2023-10-17, v1.35 from 2022-08-16 and v1.34 from 2020-10-08. The README's own recommendation, to download from the Actions page rather than the releases page, is consistent with that gap. If you pin to a release, you are pinning to something years old; if you build from master, you own the build.

The build cost is real. The Windows path pulls in Visual Studio 2022 Community plus the native desktop workload through Chocolatey, which is a large install for a command-line tool. The Nix path exists for Linux and uses Mono to run the built executable, which means the runtime you test against and the runtime you generate for are not the same thing.

The project is licensed under MIT, per the LICENSE.txt file at the repository root. MIT is permissive: it allows use, modification and redistribution provided the copyright notice and permission notice are retained. That said, the disclaimer in the README limits the stated intent of the software to academic research and defensive development, and places responsibility for misuse on the user. Those are two separate documents and they do not say the same thing. If you plan to redistribute a build or embed the code in a product, read LICENSE.txt yourself and get your own legal review; nothing here is legal advice.

## Conclusion

Use ysoserial.net if you are doing authorized testing of a .NET application that deserializes untrusted data and you need to prove which gadget chains and formatters are reachable. Do not use it as a scanner or as a general exploit framework, and do not run it against systems you do not have written permission to test. Before relying on any payload, verify three things: that the target application really deserializes the data, that the required gadget assembly is present on its classpath, and that the formatter you selected matches the one the application uses. Check the licence file before redistributing anything built from the source tree.

## FAQ

### Does ysoserial.net work on Linux?

The README documents a Nix path: clone the repository, run nix develop --impure, restore the solution with nuget restore ysoserial.sln, build with dotnet build ysoserial.sln --configuration=Release, then run the executable under Mono with mono ysoserial/bin/Debug/ysoserial.exe -h.

### Which formatters does ysoserial.net support?

The full help output lists BinaryFormatter, LosFormatter, NetDataContractSerializer, SoapFormatter and Json.NET across the gadget catalog, and each gadget entry names the formatters it works with. Some gadgets also name a supported formatter for the bridge.

### Where do I download the latest version of ysoserial.net?

The README recommends downloading the latest version from the GitHub Actions page, and says previous releases are available from the releases page. The most recent tagged release listed is v1.36 from 2023-10-17.

### Why does my ysoserial.net payload not execute anything on the target?

The README states the chain is invoked when an application with the required gadgets on the classpath unsafely deserializes the data. If the target does not deserialize the input, or the gadget assembly is not present, the payload will not run. Variant selection can also matter: variant 2 of ActivitySurrogateSelector is documented as shorter but possibly not working between versions.

## Sources

- [Issues](https://github.com/pwntester/ysoserial.net/issues)
- [License: MIT](https://github.com/pwntester/ysoserial.net/blob/master/LICENSE)
- [pwntester/ysoserial.net on GitHub](https://github.com/pwntester/ysoserial.net)
- [README](https://github.com/pwntester/ysoserial.net/blob/master/README.md)
- [Releases](https://github.com/pwntester/ysoserial.net/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/pwntester-ysoserial-net
