ProvenPort modernizes source-less .NET Framework binaries to modern .NET — and proves the modernized build behaves identically to the original. The binary itself is the golden master.
What goes in, what comes out
Input
One .NET 4.x binary — we've validated net 4.0 through net 4.8. No source code, no project files, no build scripts, no original author. The binary is all we need.
Output
Readable C# source that compiles on .NET 10, for your team to keep and maintain — delivered with the evidence that it behaves identically to the binary it came from.
The problem
Two decades of .NET Framework left organizations running DLLs whose source is lost, whose authors are gone, and whose behavior nobody dares touch. .NET Framework is now legacy, but migrating a binary you can't read is a leap of faith.
The asset is a compiled binary. Reverse-engineering it produces code that rarely behaves — or even rebuilds — like the original.
The modern runtime quietly changed subtle behaviors — numbers, text, dates, formatting — with no warning at build time. A "clean" port can still be wrong.
Rewriting code is easy to do and impossible to trust. What's missing is evidence that the new build does exactly what the old one did.
The approach
Instead of trusting the modernized code, ProvenPort measures it. It establishes the original binary's exact behavior, reproduces the same conditions on modern .NET, and compares the two. Differences are reconciled with verified, behavior-preserving changes until the old and new builds agree.
Conversion alone isn't enough for software you can't afford to break. ProvenPort delivers a modern build and the evidence that its behavior matches the original — the thing you actually need to sign off a migration.
How it works
A repeatable process where every change is behavior-preserving and equivalence is verified — not assumed.
Run safely, by default
Capturing a binary's true behavior means executing it — including code whose source nobody has read in years. ProvenPort runs every source-less assembly inside a hardened, disposable, network-isolated sandbox, so a binary that deletes files, spawns processes, or phones home can do no harm to anything that matters.
Every run executes in a throwaway, hypervisor-isolated container with no network and a read-only view of the assembly — destroyed the moment it finishes.
Whatever the code does stays inside the sandbox. The host, your network, and your data are never in reach.
We don't just block side effects — we record them. What the binary writes or changes is captured and compared, so even effects are held to the equivalence standard.
Where the AI fits
Most differences between framework generations are well understood: a deterministic engine resolves the patterns we've seen before with changes known to preserve behavior. AI is held in reserve for the cases that engine can't cover — a genuinely novel divergence with no known fix.
A tightly scoped problem: the exact input that produced a difference, the two differing results, and the specific piece of code responsible — never "rewrite this library."
Every AI-proposed fix is recompiled and re-checked against the original binary. It is kept only if it makes the behavior match, and discarded otherwise. The AI proposes; the equivalence proof decides.
Why it's hard
The difficulty isn't producing modern-looking code — it's making it actually behave like the binary it replaces, and being able to demonstrate it.
Reconstructed code can look correct while being subtly wrong. We hold the result to the binary's exact behavior.
The modern runtime changed behaviors the compiler will never flag. We know where to look — and how to restore the original.
Equivalence is established by measurement, producing an auditable result you can stand behind.
A calculation that used to throw an error on overflow now silently returns infinity instead.
A duration that rounded to whole milliseconds now keeps finer precision — quietly shifting results.
The same text capitalizes and sorts differently depending on the language and the runtime underneath.
Helper code the original compiler invented — which has no written form — must be reconstructed before the source will even rebuild.
A library's translations, shipped as dozens of separate per-language files, have to be rebuilt so every locale still loads.
A platform feature the binary relied on was moved or removed, and each call has to be rerouted to its modern replacement.
A money library's own tests seemed to fail by the dozen — until we proved the new runtime itself changed how currency symbols resolve, not the port, by running the original binary on the modern runtime and watching it diverge identically.
Two values rebuilt in the wrong order left one of them empty — a wrong answer that compiles cleanly and raises no warning at all.
A serialization format the binary depended on was deleted outright from the modern runtime — no port can bring it back, so the honest answer is to say so, precisely and in writing.
A date library's tests failed because the world's timezone rules changed since the binary shipped — the machine had moved on, not the code. Telling those apart is the difference between a real defect and a false alarm.
Bridging that gap takes deep expertise in .NET internals paired with a system built to prove, not assume.
Proof
For each library, ProvenPort modernizes the legacy binary, then runs the library's own test suite against the result. Independent, third-party evidence of equivalence.
| Library | Framework | Domain | Tests passing | Status |
|---|---|---|---|---|
| Iced | net 4.5 | x86 / x64 encoder-decoder | 481,397 / 481,397 | validated |
| MathNet.Numerics | net 4.8 | Numerical computing | 20,908 / 20,908 | validated |
| NodaTime | net 4.5 | Date & time | 18,702 / 18,702 | validated |
| Humanizer | net 4.8 | Text & localization | 15,023 / 15,023 | validated |
| NUnit | net 4.6.2 | Test framework | 6,264 / 6,264 | validated |
| FakeItEasy | net 4.6.2 | Mocking / test fakes | 5,119 / 5,119 | validated |
| AutoFixture | net 4.5.2 | Test-data generation | 4,382 / 4,382 | validated |
| Markdig | net 4.6.2 | Markdown parser | 3,795 / 3,795 | validated |
| System.Reactive | net 4.7.2 | Reactive extensions (Rx) | 3,692 / 3,692 | validated |
| AngleSharp | net 4.6.2 | HTML / CSS DOM engine | 3,643 / 3,643 | validated |
| Newtonsoft.Json | net 4.5 | JSON serializer | 3,464 / 3,464 | validated |
| MimeKit | net 4.6.2 | MIME / email parsing | 2,429 / 2,429 | validated |
| Sentry | net 4.6.2 | Error reporting | 2,386 / 2,386 | validated |
| SSH.NET | net 4.6.2 | SSH / SFTP client | 2,310 / 2,310 | validated |
| DocumentFormat.OpenXml | net 4.6 | Office Open XML | 2,304 / 2,304 | validated |
| Polly | net 4.6.1 | Resilience (retry / breaker) | 1,895 / 1,895 | validated |
| Cronos | net 4.5 | Cron scheduling | 1,868 / 1,868 | validated |
| BouncyCastle.Cryptography | net 4.6.1 | Cryptography suite | 1,529 / 1,529 | validated |
| DotLiquid | net 4.5 | Liquid templating | 1,427 / 1,427 | validated |
| Nito.Comparers | net 4.6.1 | Comparer composition | 1,351 / 1,351 | validated |
| ExCSS | net 4.8 | CSS parser | 1,263 / 1,263 | validated |
| McMaster.Extensions.CommandLineUtils | net 4.7.2 | Command-line apps | 1,120 / 1,120 | validated |
| SauceControl.Blake2Fast | net 4.6 | BLAKE2 hashing | 1,102 / 1,102 | validated |
| Verify | net 4.6.2 | Snapshot testing | 1,071 / 1,071 | validated |
| CsvHelper | net 4.8 | CSV parsing | 1,058 / 1,058 | validated |
| MailKit | net 4.6.2 | IMAP / SMTP / POP3 | 1,052 / 1,052 | validated |
| Bogus | net 4.0 | Fake-data generation | 1,051 / 1,051 | validated |
| SmartFormat | net 4.6.2 | String templating | 1,021 / 1,021 | validated |
| TimeZoneNames | net 4.6.2 | Localized TZ names | 1,001 / 1,001 | validated |
| MessagePack | net 4.7.2 | MessagePack serializer | 997 / 997 | validated |
| YamlDotNet | net 4.7 | YAML serializer | 884 / 884 | validated |
| FluentValidation | net 4.6.1 | Validation | 813 / 813 | validated |
| Refit | net 4.6.2 | Typed REST client | 810 / 810 | validated |
| CommonMark | net 4.5 | Markdown (CommonMark) | 736 / 736 | validated |
| NCalc | net 4.6.2 | Expression evaluation | 718 / 718 | validated |
| CommandLineParser | net 4.6.1 | Command-line parsing | 684 / 684 | validated |
| Semver | net 4.5.2 | Semantic versioning | 665 / 665 | validated |
| QRCoder | net 4.0 | QR-code generation | 644 / 644 | validated |
| MoonSharp.Interpreter | net 4.5 | Lua scripting | 638 / 638 | validated |
| Colourful | net 4.5 | Color science | 579 / 579 | validated |
| Serilog | net 4.7 | Structured logging | 578 / 578 | validated |
| FileHelpers | net 4.5 | Delimited / fixed-width files | 558 / 558 | validated |
| Flurl | net 4.7.2 | HTTP / URL building | 542 / 542 | validated |
| ExcelDataReader | net 4.6.2 | Excel reading | 501 / 501 | validated |
| Stateless | net 4.6.2 | Workflow / state machines | 424 / 424 | validated |
| Jil | net 4.5 | Fast JSON serializer | 410 / 410 | validated |
| DiscUtils.Core | net 4.5 | Disk images / filesystems | 404 / 404 | validated |
| NodaMoney | net 4.5 | Money / currency | 391 / 391 | validated |
| Mono.Cecil | net 4.0 | IL metadata read / write | 353 / 353 | validated |
| ICSharpCode.SharpZipLib | net 4.5 | Compression / archives | 339 / 339 | validated |
| KellermanSoftware.Compare-NET-Objects | net 4.6 | Object-graph comparison | 322 / 322 | validated |
| Rationals | net 4.7 | Rational arithmetic | 317 / 317 | validated |
| Pipelines.Sockets.Unofficial | net 4.6.2 | Socket pipelines | 287 / 287 | validated |
| K4os.Compression.LZ4 | net 4.6.2 | LZ4 compression | 282 / 282 | validated |
| Lib.Harmony | net 4.5.2 | Runtime method patching | 276 / 276 | validated |
| EmailValidation | net 4.6.2 | Email validation | 269 / 269 | validated |
| DiffPlex | net 4.5 | Text diffing | 248 / 248 | validated |
| Ensure.That | net 4.6.2 | Guard clauses | 226 / 226 | validated |
| Utf8Json | net 4.5 | UTF-8 JSON serializer | 209 / 209 | validated |
| HtmlSanitizer | net 4.6.2 | HTML sanitization | 198 / 198 | validated |
| ObjectDumper | net 4.8 | Object-graph dump | 192 / 192 | validated |
| LiteDB | net 4.5 | Embedded database | 186 / 186 | validated |
| zxcvbn-core | net 4.6.1 | Password-strength | 169 / 169 | validated |
| MiniProfiler.Shared | net 4.7.2 | Application profiling | 125 / 125 | validated |
| FluentFTP | net 4.6.2 | FTP client | 121 / 121 | validated |
| JsonSubTypes | net 4.6 | JSON polymorphism | 120 / 120 | validated |
| Sprache | net 4.5 | Parser combinators | 117 / 117 | validated |
| Namotion.Reflection | net 4.6.2 | Reflection / XML docs | 116 / 116 | validated |
| Mono.TextTemplating | net 4.7.2 | T4 templating | 112 / 112 | validated |
| Enums.NET | net 4.6.1 | Enum utilities | 111 / 111 | validated |
| DotNet.Glob | net 4.5 | Glob matching | 110 / 110 | validated |
| GraphQL.Client | net 4.6.1 | GraphQL client | 110 / 110 | validated |
| prometheus-net | net 4.6.2 | Metrics / Prometheus | 108 / 108 | validated |
| TimeZoneConverter | net 4.6.2 | Timezone conversion | 101 / 101 | validated |
| JsonDiffPatch.Net | net 4.5 | JSON diff / patch | 93 / 93 | validated |
| LitJson | net 4.5 | JSON serializer | 93 / 93 | validated |
| OptimizedPriorityQueue | net 4.5 | Priority queues | 89 / 89 | validated |
| HtmlAgilityPack | net 4.5 | HTML parsing | 85 / 85 | validated |
| TinyMapper | net 4.0 | Object-to-object mapping | 81 / 81 | validated |
| Scrutor | net 4.6.2 | DI assembly scanning | 80 / 80 | validated |
| Scientist | net 4.5.1 | Refactoring experiments | 76 / 76 | validated |
| DiffEngine | net 4.6.2 | Diff-tool launching | 74 / 74 | validated |
| Optional | net 4.5 | Functional option type | 69 / 69 | validated |
| MarkdownSharp | net 4.0 | Markdown parser | 58 / 58 | validated |
| BCrypt.Net-Next | net 4.6.2 | Password hashing (bcrypt) | 53 / 53 | validated |
| K4os.Hash.xxHash | net 4.6.2 | xxHash hashing | 42 / 42 | validated |
| Cyotek.Drawing.BitmapFont | net 4.8 | Bitmap-font parsing | 39 / 39 | validated |
| FastMember | net 4.6.1 | Fast reflection | 38 / 38 | validated |
| Otp.NET | net 4.6.1 | OTP / 2FA (TOTP/HOTP) | 37 / 37 | validated |
| FuzzySharp | net 4.6.1 | Fuzzy string matching | 37 / 37 | validated |
| Hashids.net | net 4.5 | ID obfuscation | 33 / 33 | validated |
| NGettext | net 4.6 | gettext localization | 30 / 30 | validated |
| Fastenshtein | net 4.6.2 | String distance | 28 / 28 | validated |
| NeoSmart.Unicode | net 4.6.1 | Emoji / Unicode | 25 / 25 | validated |
| Pluralize.NET | net 4.6 | Pluralization | 19 / 19 | validated |
| System.IO.Abstractions | net 4.7.2 | Filesystem abstraction | 18 / 18 | validated |
| OneOf | net 4.5 | Discriminated unions | 11 / 11 | validated |
| ValueOf | net 4.8 | Value objects | 8 / 8 | validated |
| RandomDataGenerator.Net | net 4.5 | Random data | 6 / 6 | validated |
| Figgle | net 4.5.2 | FIGlet ASCII-art text | 4 / 4 | validated |
Counts are of the tests applicable to the original binary. The remainder exercise behavior that only exists in newer frameworks — features the legacy binary never had, and faithfully doesn't have after porting.
In a date-and-time library, the modernized build answered a basic question — which zone is UTC? — with nothing at all. Two values had been rebuilt in the wrong order, so one was still empty when the other was derived from it. Nothing failed to compile. No warning fired. ProvenPort surfaced it, pinpointed the cause, and restored the original behavior. Catching that class of silent change is the whole point: not just porting, but knowing the behavior is identical.
A test suite only checks the inputs its authors thought to write down. ProvenPort verifies the behavior — probing each library across edge cases its own tests never reach, and comparing the original binary to the modernized build value for value. On a library with 15,000+ passing tests, that independently surfaced behavioral changes the modern runtime introduced — how an exceptional numeric value becomes a whole number, how a hash code is derived — which those tests never exercised. The distance between "the tests pass" and "we measured that it behaves identically" is exactly the risk in a migration you can't afford to get wrong.
Author–market fit
Sébastien Lebreton — Principal Engineer working on Microsoft IDEs and developer tools, creator of Reflexil (the IL assembly editor), and co-founder of DataGalaxy. ProvenPort sits squarely at the intersection of his expertise: IL, decompilation, debuggers, and .NET runtime internals.