115 Followers
22 Following
30 Posts

Over the past couple years, I have come to know the #dotnet platform pretty well, from a developer's and a #reversing standpoint.

I can’t always say the same the #infosec community.

Today, I decided to rant a little (or maybe a lot πŸ™ƒ)

πŸ‘‰ https://blog.washi.dev/posts/misconceptions-about-dotnet/

Better late than never, I finally managed to finalize my #flareon12 write-upsπŸ˜„

Overall, it was a fun set of challenges and the latter ones a reminder of how much I still have to learn in the field of RE :).

πŸ‘‰ https://blog.washi.dev/posts/flareon12/
πŸ‘‰ https://washi1337.github.io/ctf-writeups/writeups/flare-on/2025/
Image

After #flareon11 challenge 7, I got inspired to build tooling for #dotnet Native AOT reverse engineering.

As such, I built a #Ghidra Analyzer that can automatically recover most .NET types, methods and frozen objects (e.g., strings).

πŸ‘‰https://blog.washi.dev/posts/recovering-nativeaot-metadata/

Recovering Metadata from .NET Native AOT Binaries

Ever seen a binary that looks like a .NET binary based on its strings, but .NET decompilers are not able to open them?

Washi

Did you know you could write entire #csharp programs just by using the "await" keyword?

OK, well not really, but I spent some weekends developing AwaitFuscator: A (dumb) #obfuscator that turns your #dotnet program into nothing but "await" expressions!

πŸ‘‰https://blog.washi.dev/posts/awaitfuscator

Awaiting the Awaitables - Building the AwaitFuscator

Here is a scenario you probably have never encountered. Have you ever decompiled a .NET binary that only consists of a bunch of await keywords and nothing else?

Washi

"Noo! Ghidra has such a bad UI! IDA is much better!"

Explain to me: In what world does a hex view need column selection that crosses multiple columns (and beyond) and disappears upon scrolling?

The decompiler may be good but I genuinely don't see how people put up with IDA's UI.

Earlier this month I found a way to consistently pop calculators in #dnSpy by opening a file and clicking some nodes in its browser.

Today I release a write-up on how this can be done:

πŸ‘‰ https://blog.washi.dev/posts/popping-calcs-in-dnspy/

Update dnSpy if you haven't already!

#dotnet #reversing #bug

A problem with .NET Self-Contained Apps and how to pop calculators in dnSpy

Programming languages that operate on a virtual machine often promise safety guards against many unsafe operations. However, virtual machines can have pretty serious bugs. In this post, we explore one interesting limitation of self-contained applications in .NET, and see how we can exploit it to pop calculators from our trusty decompiler dnSpy:

Washi

I participated in DEFCON CTF Qualifiers of this year with Shellphish (thanks for inviting me!), and solved a web/rev/pwn challenge where we pwned a Javascript VM with... Python PicklesπŸ₯’?

Have a read how we ended up doing this on my blog πŸ‘‰ https://blog.washi.dev/posts/defcon-brinebid

Breaking Javascript with Python Pickles (Solving brinebid in DEFCON CTF Qualifiers 2023)

On May 27 until May 29, I had the pleasure to join Shellphish in the DEFCON CTF Qualifiers of 2023. I wanted to highlight one of the challenges called brinebid that I ended up working on as well as finding and submitting the flag for. It is a really interesting challenge, combining web security with some reverse engineering a virtual machine (VM), as well as exploiting a vulnerability in the VM to get arbitrary code execution.

Washi

What really is the entry point of a #dotnet application? Is it `public static void Main()`, or are there other places that we should look at when reverse engineering .NET samples?

πŸ‘‰Read about it in my new blog post: https://washi.dev/blog/posts/entry-points/

#reversing #malware

What really is the Entry Point of a .NET Module?

public static void Main(); This is what most people associate with the entry point of a .NET module. However, as it so turns out, this is not the place where it all begins. In this post, we will review different types of entry points that are available to us, and go on a quest to find the holy grail the actual place where user code really starts.

Washi

I thought it was time to show off some of #AsmResolver's new #native #PE #patching API. In this blog, we discuss how to programmatically inject code into an arbitrary PE, and learn how to construct new import directories as we go.

Full post: https://washi.dev/blog/posts/import-patching/

#reversing

Injecting Code using Imported Functions into Native PE Files

Patching PE files is easy. Injecting new code that uses functions from external modules, however, is more complicated. In this post, we are implementing a method for rebuilding import directories, such that we can inject any type of code in an arbitrary PE file.

Washi

Time for another blog post!

This time we are tackling .NET debuggers and make them display garbage data with the help of proxy objects and debugger display attributes.

Full post: https://washi.dev/blog/posts/debugger-proxy-objects/
PoC Implementation: https://github.com/Washi1337/ProxyObjects

#dotnet #obfuscation #reversing #asmresolver #cil #dnspy #decompiler #debugger #poc

Confusing .NET Debuggers: Proxy Objects

.NET decompilers and debuggers have become very good at helping reverse engineers figure out the inner workings of a program. However, they also make a lot of assumptions that can be used against them. In this post, we will explore a method that can be used to trick the debugger into hiding a lot of important information during a debugging session.

Washi