Obfuscation Without Effort: Breaking a UAC-0226 GIFTEDCROOK Stealer

by Robin Dost


EDIT: I have YARA rules available for this one, if you need them, contact me at contact@robin-dost.de
Also, checkout my project KRAKEN if you’re interested in continuous threat actor tracking.

Lately I’ve been spending more time looking at malware targeting Ukraine and Europe. And yeah, a lot of it is neither new nor particularly creative. But it works. And that’s exactly why it’s worth digging into.

The sample we’re looking at here is fresh (from today, 09.04.2026), part of a UAC-0226 campaign and turns out to be a variant of the well-known GIFTEDCROOK stealer.

Initial access? Surprise: CVE-2025-6218 & CVE-2025-8088.
Maybe you already know this one from one of my previous articles.
A prepared archive, some basic social engineering, an LNK and the user still clicks it. End of story.

From there it’s the usual flow:

LNK launches payload
Payload decodes another binary
Binary initially looks like absolute garbage

Constants everywhere, useless function calls, pseudo-random noise. The classic “maybe the analyst just gives up” approach.

If you ignore all that noise, what’s actually happening becomes pretty obvious:

  • RC4-based encryption
  • Chunked data exfiltration
  • A simple but working exfil client
  • Runtime reconstructed C2

Nothing high-end. No fancy exploit chain fireworks.
Just cleanly glued together building blocks doing exactly what they’re supposed to do: grab data and ship it home.

And that’s exactly what makes this sample interesting.

So let’s take a look.


The sample has the hash
7200a9f1e1ea51b66ab9c9274e9d8f805633179634e8ff4dcb8ef82bc02518df

It’s a RAR archive and once extracted it’s immediately obvious the actor is abusing the WinRAR CVE to deliver the payload.

We’ve seen this before, for example with Gamaredon, but the execution here is slightly different.

We get a decoy PDF named:
“Відомості з реєстру військовозобов’язаних про працівників №20260409-7496423-1.pdf”

Roughly translated:
“Information from the Military Service Registry regarding employees No. 20260409-7496423-1.pdf”

So yeah, clearly targeting Ukraine.

Opening the PDF confirms the theme.

(Personal information has been redacted)

Alongside the PDF there are additional files:

  • ojMP31J28ohEDxT.lnk
  • Arj
  • 05fE

Naturally, we start with the LNK using lnkparse since that’s usually the entry point

We can see a PowerShell command that compiles the file “05fE”.

Easy to verify by just looking at the file:

The code is obfuscated, but nothing crazy.

Quick summary:

  • Random function names
  • Useless variables
  • Thousands of Write-Host calls -> pure noise
  • Sleep calls -> sandbox evasion

The key function is:

function table_pincenez_bruise()

This acts as a simple XOR/byte decoder.

We also see a lot of [Type]::(...).(...) usage, which is used for:

  • .NET reflection
  • Dynamically resolving WinAPI

Execution flow looks like this:

  1. Prepare shellcode
  2. Decrypt using (($value – $key) % 256)
  3. Allocate memory (VirtualAlloc)
  4. Write shellcode
  5. Start thread

At this point we have everything we need to reconstruct the decoded binary.

I threw together a quick script for that:

from pathlib import Path
import re
import hashlib
import subprocess

input_path = Path(r"Arj")
output_path = Path("decoded_arj.bin")

raw = input_path.read_bytes()

decoded = bytes(((b - 117) % 256) for b in raw)
output_path.write_bytes(decoded)
2a8ea9f1ad8936fb302243faa64b91c5767df411923715cbdb1a869e3bfd7e6d  decoded_arj.bin

Nice. Now we have the decoded payload.
Let’s throw it into Ghidra.

FUN_18008e2a0 -> Seed / Cookie Generation
FUN_18008e06c -> Dispatcher

This looks like a main dispatcher. Function FUN_1800189c0 stands out immediately.

The function is full of junk and noise with only a few real control paths hidden inside.
After going through it, a couple of functions are actually relevant. FUN_180001180

FUN_180001180

First it builds a 256-byte table:

local_128[0..255] = 0..255

Then

bVar24 = bVar24 + cVar4 + key[i % keylen]
swap(...)

That’s classic RC4 Key Scheduling (KSA)

It sets up a 256-byte state array (S-box) using the provided key. The algorithm starts with a simple identity permutation (0–255) and then shuffles it based on the key through a series of swaps. The process mixes the key material into the internal state, effectively “seeding” the cipher.

Once KSA is complete, the resulting permutation is used by the PRGA (Pseudo-Random Generation Algorithm) to produce the keystream that will later be XORed with the data

After that:

cVar4 = S[i]
j += cVar4
swap(...)
output = S[(cVar4 + S[i])]

-> That’s RC4 PRGA.
So part of the payload is RC4 encrypted, no surprises here

FUN_1800128a0

The key comes from here:

JtyIQxPND8G


his function also handles setting up and executing the HTTP communication

FUN_180014580

This is the file exfiltration function.
It loads data into memory and sends it to the C2

Chunk-size:

0x21400 = 136192 Bytes (~133 KB)

So data is sent in chunks.
Simple, works.

Sending to C2:


The network layer is most likely HTTP using WinHTTP or something similar.

Options are set, payload prepared, callback configured, request sent

Behavior


Behavior is straightforward:
Initial beacon Environment check If OK -> data exfiltration

To extract the C2 URL, we need to rebuild the RC4 decoding process.

Overall Architecture

Extracting the C2 URL

In the end we obviously want to extract the C2 URL.

For that we basically just need to rebuild the RC4 logic.

For this I jump to the memory region of DAT_1800b2ff2 and use those values to reconstruct the RC4 decoding.


I’ll just drop my script here in case anyone cares, I basically just reconstructed the logic in Python.

Source Code (Click to view)
def rc4_crypt(data: bytes, key: bytes) -> bytes:
    # KSA
    s = list(range(256))
    j = 0
    for i in range(256):
        j = (j + s[i] + key[i % len(key)]) & 0xFF
        s[i], s[j] = s[j], s[i]

    # PRGA
    i = 0
    j = 0
    out = bytearray()
    for b in data:
        i = (i + 1) & 0xFF
        j = (j + s[i]) & 0xFF
        s[i], s[j] = s[j], s[i]
        k = s[(s[i] + s[j]) & 0xFF]
        out.append(b ^ k)

    return bytes(out)

def run():
    encrypted = bytes([
        0x8A, 0xE5, 0xBA, 0x1E, 0x2C, 0x19, 0x48, 0xF0,
        0x8E, 0x3B, 0xED, 0x22, 0xED, 0xBE, 0xBE, 0x0D,
        0xCE, 0x6F, 0x72, 0x81, 0xD2, 0xD7, 0x52, 0xE9,
        0xD6, 0x8B, 0x14, 0x0A, 0x9A, 0x33, 0xF9
    ])

    key = b"JtyIQxPND8G"

    decrypted = rc4_crypt(encrypted, key)

    print("Raw bytes:", decrypted)
    print("ASCII:", decrypted.decode("utf-8", errors="replace"))


if __name__ == "__main__":
    run()
https://136.0.141[.]138:8406/rcv/

And if I open the URL in the browser:


There’s our candidate.

Certificate looks funny too:



The malware is a GIFTEDCROOK stealer variant used by UAC-0226.

Who is UAC-0226?

UAC-0226 is basically a designation used by Ukrainian CERT for a Russian-aligned threat actor group primarily targeting Ukraine.
Some of the artifacts and the tradecraft found currently and in the past make me also believe that this is a russian (speaking) threat actor, but that’s just me.
Their tradecraft is pretty straightforward “it works, so we use it” operations: a lot of phishing, archives, LNKs, then multi-stage payload chains.

Classic flow is: user clicks something > loader > next stage > eventually you end up with a stealer like GIFTEDCROOK.

What makes this interesting:

They don’t build ultra complex frameworks.
They build simple chains that are just obfuscated enough (RC4, some string garbage, staged decoding) to make analysis annoying, even if this one wasn’t exactly a masterpiece.

It’s not elegant, but effective enough and that’s exactly what makes them relevant for us 🙂

References:


https://cert.gov.ua/article/6282946
https://arcticwolf.com/resources/blog/giftedcrook-strategic-pivot-from-browser-stealer-to-data-exfiltration-platform/
https://malpedia.caad.fkie.fraunhofer.de/actor/uac-0226
https://socprime.com/de/blog/detect-uac-0226-attacks-against-ukraine/
https://netzpalaver.de/2025/06/27/cyberspionage-gruppe-uac-0226-hat-giftedcrook-zu-einem-umfassenden-exfiltrations-tool-ausgebaut/