DEV Community

Cover image for I tried REA, the #1 trending repo on GitHub — can AI really reverse-engineer a .NET app?
Naze Code
Naze Code

Posted on

I tried REA, the #1 trending repo on GitHub — can AI really reverse-engineer a .NET app?

A repo called REA — "Reverse Engineer Anything" picked up about 183,000 stars in a single week and went to #1 on GitHub's weekly trending page. The pitch: plug it into your AI coding agent and it takes apart apps it has never seen the source for — even turning raw machine code back into readable code.

That's a big claim, especially for us .NET developers who like to think an obfuscator or Native AOT keeps our code (and our secrets) safe. So I tested it properly: one small, realistic C# app, compiled three different ways, with REA pointed at each build. And then the question the hype skips — can a plain AI agent already do this without REA at all?

What REA actually is

First, a correction the README buries: REA doesn't decompile anything by itself. It's a coordinator. Your agent asks a question; REA runs real analysis tools on the program and hands back findings with evidence.

  • For .NET, it has its own reader for the assembly metadata and CIL (bytecode) — static, no need to run the target.
  • For native machine code, it drives a classic decompiler: Ghidra (the free one from the NSA), Hopper, or IDA.

And here's the part the hype glosses over: a decompiler turns machine code into C-like pseudocode full of names like FUN_140001f00 and param_1. It's the AI that reads that soup, guesses what each piece does, and rewrites it as clean code. So REA is real — but it's "a decompiler plus a smart guess," not an undo button for the compiler.

The test app: Naze Pixel

Not a toy. Naze Pixel is ~105 lines of C# that converts a 24-bit BMP into dithered ASCII art: load the bitmap, grayscale it, shrink it, apply Floyd–Steinberg dithering, map pixels to characters. Like a lot of real apps, it also ships with an upload key baked in.

var image = Bmp.Load(path);
var gray  = Pixels.Grayscale(image);
var small = Pixels.Resize(gray, image.Width, image.Height, width);
var dots  = Pixels.Dither(small);
var art   = Pixels.ToAscii(dots);

Console.WriteLine(art);
if (args.Contains("--share")) Uploader.Share(art);
Enter fullscreen mode Exit fullscreen mode

The secret (the key below is fake, created only for this test):

const string ApiKey   = "nzp_live_7c41e9a0d3b8f2a6";          // FAKE upload key
const string Endpoint = "https://api.nazepixel.example/v1/art";
Enter fullscreen mode Exit fullscreen mode

A real run, at width 72, on a high-contrast "C#" test image:

                        ##########        ####  ###
                      ##############      ###   ###
                     ######     ###    #############
                     #####               ###   ###
                     #####               ###  ###
                     #####      #####  #############
                      ##############    ###  ####
                        ##########      ###  ###

     ################## ## ## # # # # # # #  #
     ########## ## # # ## ## ## ## # # # # #  # # # # #  #
     ####### ########### ## # ## # # # #   # #   #          #

Would POST 1480 chars to https://api.nazepixel.example/v1/art with key ...f2a6
Enter fullscreen mode Exit fullscreen mode

I compiled it three ways and, to keep the binaries from leaking my machine, built with <DebugType>none</DebugType> and <Deterministic>true</Deterministic> (otherwise the PDB path with your Windows username ends up inside the binary).

Test 1 — the normal .NET build

REA's .NET reader on NazePixel.dll returns 114 KB of JSON in about a second and a half: every method, its signature, a bytecode summary, and every string literal — including our usage text, the endpoint, and the key.

I handed that JSON, and only that JSON, to a fresh AI with no source code. 85 seconds later it had rebuilt the app: the grayscale weights to four decimal places, the 7/3/5/1 dithering pattern, the lot.

To prove the rebuild was faithful, I recompiled the AI's version, ran it on the same image, and fingerprinted both outputs with SHA-256:

ours    317eb0c60108775b9e6a88a7f371e21eb34fc11cc607fc3a66f6938ba6d92261
ai      317eb0c60108775b9e6a88a7f371e21eb34fc11cc607fc3a66f6938ba6d92261
Enter fullscreen mode Exit fullscreen mode

Same hash means byte-for-byte identical output. (A SHA-256 is a file's fingerprint: change one character and the hash is completely different.)

Control, no REA: given the bare .dll and told "use any tools you like," the same agent found ILSpy (a free .NET decompiler, already installed) and had real C# back in 41 seconds.

Test 2 — the obfuscated build

Next I ran the build through Obfuscar, a free open-source obfuscator. Every class and method was renamed to invisible Unicode space characters, and every string was encrypted. REA's string list came back empty.

So, can the AI still make sense of it? Given REA's output only, after about three minutes it had:

  • Rebuilt the whole algorithm from the bytecode.
  • Cracked the encryption on paper: every byte XOR'd with its position and a fixed value — b ^ i ^ 0xAA. I verified that myself, and it's right.
  • Not actually read the strings — it could only guess them by length (it guessed the share flag was --debug; it's really --share).

But it made one prediction: the key is a constant, and constants live in the metadata, so it's probably still plain text. So I looked:

> search the obfuscated .dll for a UTF-16 "nzp_live_..." string
nzp_live_7c41e9a0d3b8f2a6
Enter fullscreen mode Exit fullscreen mode

There it is — the full key, in plain text, inside the "obfuscated" file. The obfuscator renamed everything to invisible characters; the one thing I actually wanted hidden, it never touched.

Control, no REA: 56 seconds to decompile it, find the encryption, and decrypt every string (key included) with a couple of lines of Python.

Test 3 — Native AOT (machine code)

This is the case the hype is really about. dotnet publish -p:PublishAot=true produces a 1.1 MB .exe of pure x64 machine code — no CIL bytecode at all. Here's what our Dither function looks like now:

140001f00  48 89 5c 24 08 57 48 83 ec 20 8b f2 48 8b d9 ...
Enter fullscreen mode Exit fullscreen mode

REA loads the exe into Ghidra, which finds 3,627 functions — almost all of them the .NET runtime. Our code is a few needles in that haystack. Given REA (and only REA), the AI searched for our strings, followed the code that used them, and decompiled our functions one at a time. About 18 minutes later: the whole app, same weights, same dithering, same key — and it even labeled each function with its address in the exe.

I compiled that machine-code rebuild too, and its output has the same hash as the original:

ours     317eb0c6...6d92261
rebuild  317eb0c6...6d92261
Enter fullscreen mode Exit fullscreen mode

Byte-for-byte, reconstructed from machine code. That part of the hype holds.

Control, no Ghidra: under 4 minutes. The agent wrote its own disassembler scripts in Python and recovered the same constants, the same key, and even the real class names (.NET leaves those in the exe for stack traces). One catch worth flagging: it also ran the unknown exe to see what it did — fine for my own app, not something you want an agent doing to a stranger's binary.

So, real or hype?

Build With REA Without REA (plain AI)
Normal .NET 85 s, byte-identical rebuild 41 s (ILSpy)
Obfuscated ~3 min, key recovered 56 s, key recovered
Native AOT ~18 min, byte-identical rebuild ~4 min, key + class names

REA is real. It's careful, it's static for .NET, and on pure machine code it genuinely helped the AI rebuild my app exactly. But in every single test, the same AI without it got there too — and faster. For apps this size, the AI was doing the reverse engineering; REA or no REA.

Where REA earns its stars is the case I didn't test: big native applications where you want a real decompiler plus evidence you can check, instead of an agent improvising with Python. For a 105-line C# app, it's overkill. The capability is real; the "you need this tool" framing is the hype — only half true.

The actual lesson for .NET developers

This was never really about one trending repo. It's the same lesson three ways:

  • Obfuscation slows people down.
  • Native AOT slows them down more.
  • Neither keeps a secret.

Anything you ship to a user's machine can be read — strings, keys, endpoints, all of it. A secret baked into your app is just a password with a delivery address. Keep it on a server behind an API you control.


This is **Naze Lab* — we break things to find out why.*

Sources: morluto/rea · REA docs · Ghidra 12.1.4 · Obfuscar · ILSpy · .NET 10 Native AOT.

Top comments (0)