Skip to content

Instantly share code, notes, and snippets.

@Steake
Created December 31, 2025 20:21
Show Gist options
  • Select an option

  • Save Steake/83c21f9b04fc48dcd5b716951969110e to your computer and use it in GitHub Desktop.

Select an option

Save Steake/83c21f9b04fc48dcd5b716951969110e to your computer and use it in GitHub Desktop.

AGAINST OBFUSCATION: A MEMOIR OF DIGITAL DISSECTION

BY OLIVER HIRST DATE: JANUARY 1, 2026


I. THE PRESTIGE OF THE CHARLATAN

There is a certain vulgar arrogance to modern malware authors. They present you not with code, but with a challenge to your sanity. The file in question, w_source.lua, arrived on my desk not as a script, but as a monument to obscuration. It was a hideous thing to behold—a sprawling wasteland of single-letter variables (W, r, e), stripped of all semantic meaning, designed to look less like logic and more like the static of a dying television channel.

My initial reaction was one of weary familiarity. "Another packer," I thought, "another tedious exercise in unzipping." I was wrong. This was not merely packed; it was a fortress built of glass and malice.

II. THE DESCENT INTO THE ABYSS (AND SEVERAL WRONG TURNS)

The first tribulation is always the underestimation of the adversary. I assumed, with the hubris of the seasoned analyst, that standard deobfuscation tools would strip away the outer shell. They did nothing but choke.

I began to poke at the edges. I noticed a suspicious offset—0x913—referenced in the loader. Extracting the data at this location yielded jit.txt. A text file? Hardly. It was a binary blob, a serialized state of a custom Virtual Machine. This was the first blind alley I walked down: treating it as static data. I wasted hours staring at hex dumps, looking for patterns that weren't there, convinced I could brute-force the decryption with a simple RC4 script (try_rc4_brute.py). The results were a litany of false positives and gibberish.

The code mocked me. I attempted to instrument the execution flow directly, modifying the source to print its secrets. LuaJIT spat back a Control structure too long error. The malware was so convoluted, so cyclically dense, that the compiler itself refused to process it. I was fighting a hydra; cut off one head, and the compiler crashes.

III. THE CLOCKWORK ORANGE

It became clear that static analysis was a fool's errand. I had to build a cage and let the beast run inside it. I constructed mock_runner.lua, a synthetic reality where I controlled the horizontal and the vertical.

The breakthrough came when I stopped trying to read the code and started tracing the data. I identified the heart of the machine, a flattened dispatch loop:

V = J(x, w)

Here, J was the instruction pointer mapping, and w was the memory state. But w was encrypted. The key wasn't in the code; it was in the air. The malware used a custom Pseudo-Random Number Generator (PRNG) properly seeded by the environment. If the seed was off by a single bit, the code decoded to garbage.

I spent a sleepless night wrestling with solve_lcg.py, trying to mathematically derive the parameters of the linear congruential generator. It failed. The math was sound, but the inputs were tainted. It was only when I looked at the entropy of the jit.txt header itself that I found the "divine" constant: 13578145.

When I fed this seed into the VM, the chaos ceased. The instructions aligned. The lock clicked open.

IV. THE GHOST IN THE MACHINE

With the PRNG synchronized, I placed a hook on loadstring—the function used to execute dynamic code. I ran the machine. It stuttered, crashed on a nil upvalue h, and then, finally, it produced the goods.

We captured payload_loadstring.bin—214 kilobytes of pure, decrypted Lua source.

And what did it do, this sophisticated piece of engineering? It didn't call a server. It didn't reach out to a domain that could be seized by the FBI or sinkholed by a brightly-colored tech giant. No, it turned to the one infrastructure that is truly indifferent to human law: the Polygon Blockchain.

V. THE UNSTOPPABLE CONFIGURATION

Deep within the decrypted payload, within a table simply labeled z[52], lay the true genius—and the true horror—of this operation:

{
    "jsonrpc": "2.0",
    "method": "eth_call",
    "params": [
        {
            "to": "0xd68910ED4D4A5A9bAdF9ec95604CAE0f3378479B",
            "data": "0xb68d1809"
        },
        "latest"
    ],
    "id": 1
}

The malware executes a "read-only" call (eth_call) to a smart contract on Polygon Mainnet. It uses an Alchemy API key (89pCO1NlLRkTZgb8DtZmKwC42AQcUeXF) to bridge the gap between the infected Windows machine and the blockchain.

VI. THE CONTRACT: A DEAD DROP IN CYBERSPACE

I obtained the bytecode of the contract at 0xd68910ED4D4A5A9bAdF9ec95604CAE0f3378479B and disassembled it. The architecture was elegant in its simplicity:

Function Selector Name Purpose
0xb68d1809 retrieve() Returns C2 payload from storage slot 1
0xb249cd2d setPayload(string) Admin-only: Updates C2 payload
0xf851a440 admin() Returns admin address from slot 0

The contract is nothing more than a key-value store. The admin writes the C2 address; the victim reads it. No transaction is created for the read. No gas is spent. The victim's query is invisible.

But the question remained: what was in storage slot 1?

VII. THE FINAL REVELATION

I queried the contract directly using eth_call via a public Polygon RPC:

curl -X POST https://polygon-rpc.com -d '{
  "jsonrpc":"2.0",
  "method":"eth_call",
  "params":[{
    "to":"0xd68910ED4D4A5A9bAdF9ec95604CAE0f3378479B",
    "data":"0xb68d1809"
  },"latest"],
  "id":1
}'

The response:

0x...687474703a2f2f39332e3132332e33392e323436...

Decoded from hex:

http://93.123.39.246

There it was. The Command & Control server. An IP address, hidden in plain sight on a public blockchain, immutable and unkillable unless the attacker chooses to update it.


VIII. INDICATORS OF COMPROMISE (IOCs)

Type Value
C2 Server http://93.123.39.246
C2 IP 93.123.39.246
Polygon Contract 0xd68910ED4D4A5A9bAdF9ec95604CAE0f3378479B
Function Selector 0xb68d1809
Alchemy API Key 89pCO1NlLRkTZgb8DtZmKwC42AQcUeXF
DGA/Subdomain gk7o1irwprznlvi3gzpqru4yq6dwnheq89hzeepkvvdrqoe1enf3hmps2lyyeljcgusxra6ekkkn02z3w7youq259yf86xqg3tthvcd76q9
PRNG Seed 13578145
Payload Offset 0x913

IX. FINAL REFLECTIONS

We have stripped this thing naked. We have seen its gears (VirtualAlloc, mocked and neutralized), we have stolen its keys, we have reverse-engineered its contract, and we have extracted its secrets from the blockchain.

It is a formidable piece of tradecraft, I will grant it that. It disguises itself as nothing, runs as a ghost in memory, and speaks only to the unkillable ledger of Polygon. But it is no longer magic. It is just code. And code, eventually, always yields to the determined mind.

The C2 is 93.123.39.246. Block it. Hunt it. The file is closed.

Oliver Hirst

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment