“A wise ninja does not seek out an enemy who he does not fully understand." - Splinter from Teenage Mutant Ninja Turtles
As a technical writer passionate about science fiction, one of the most exciting parts of my job at Sonatype is when I have the opportunity to collaborate with the security research team.
Ever since we found
It’s not a rare occurrence: they constantly assess hundreds of suspicious packages from open-source registries to determine if they’re truly malicious. During this procedure, they identify familiar patterns between the packages, and sometimes, upon recognizing strong similarities, they conduct further research to track down the actor/campaign behind them.
Between the last week of 2022 and the beginning of 2023, our AI system flagged suspicious packages uploaded to the PyPI registry including pyrologin
, easytimestamp
, discorder
, discord-dev
, style.py
, and pythonstyles
. Our security researchers looked at them and confirmed they were indeed malicious. And after further analysis, they noticed these packages added a series of features not often seen in Python malware.
In what has become a de facto strategy, bad actors hide a payload in the setup[.]py
file so developers only have to use a simple pip install to get infected. In this case, they’d be inadvertently launching a PowerShell script that downloads a ZIP file to install libraries that let the attacker control the victim’s mouse, the keyboard, take screenshots, and create hidden remote connections. And on top of that, these packages also exfiltrate sensitive information like passwords, cookies, and cryptocurrency wallet data, and even try to install a tool for remote access. Our findings were in line with
Nevertheless, security researcher Carlos Fernandez was having a haunting sense of déjà vu. During the week after we disclosed the packages, memories of having seen earlier versions of this malware flashed through his mind. A threat actor might have been evolving their malware through time, but we needed to make sure, so I put my OSINT hat on to help him see if there was any truth to his intuition.
Looking back on our database, on September 25, 2022, a package called pygradient
was uploaded to the PyPI repository. Our AI flagged it as suspicious and our security researchers confirmed that it contained malware and that it bundled the sources of another package called pystyle
. Both libraries were authored by
W4SP stealer boasts persistency (it gets reactivated every time users restart the PC), obfuscation (the author promises it’s fully undetectable), and steganography techniques to hide polymorphic and highly-obfuscated payloads within an image file. The malware sends all the victim’s Discord accounts, credit cards, passwords, and crypto-wallets back to the attacker through a hard-coded Discord webhook address. Bad actors interested in this malware have purchased it by paying about 20 USD in crypto.
Originally, pystyle
did not have a malicious nature—a harmless package to style and color console output to enhance readability and user experience. But according to Phylum research, once it became popular (the package is still active on PyPI and it accumulates more than 40,000 downloads every month), they decided to add W4SP malware in a couple of releases.
Open-source packages like pystyle
can act as sleeper agents for months only to be activated later by their own author for malicious purposes. A risky move, since their popular package can be discovered by security researchers like us who’ll report it as malicious and have it be taken down forever. That’s why they often create new packages instead where they include the source code of an innocuous library, add some type of malicious payload, and upload it under a new name: something generic, benign-sounding, innocent-looking. A name such as pygradient
.
After taking a closer look with Carlos, we found this proto-RAT mutant malware lacked some of the features of the December versions: even though it also launched a PowerShell script and exfiltrated sensitive data, it didn’t use base64 encoded payloads or an allowlist txt file to avoid self-infection. In a way, it was a milder, less sophisticated variant.
But then we looked at early-November uploaded packages, including paintpy
, devicespoof
, and devicespoofer
, and after diving deeper, we found confirmation of our suspicion: the malware was truly evolving.
Even though BillyTheGoat hasn’t been active on GitHub since November, we’re still finding malware that’s based on his creations or stealing directly from them, mostly by a user that’s apparently based in Portugal called
This user uploaded a recently removed package in PyPI called pystilez
, falsely credited to BillyTheGoat in what looked like
Checkmarx apicolor
(along with similarly-named variations) that included a Discord server link within their malicious code. The administrator profile linked to a verified Steam account and the name “zeeckt” appeared as one of the attacker’s Steam aliases.
A security researcher posted one of zeeckt’s payloads for educational purposes and he received an interesting reply from the co-author of W4SP stealer:
How ironic for your stealer to be stolen.
The same author, apparently a 17-year-old Python developer, reiterates his frustration in a README file on his GitHub profile:
We don’t know exactly what malicious code zeeckt has stolen from other bad actors, but one thing is certain: that name continues to pop up in malware campaigns across open-source registries.
Carlos recently found four more packages by forenitq
, forenith
, forenity
and forenitz
. After further investigation, he tagged them as malicious and reported them to PyPI to be taken down. The fastest case took about 20 minutes from publication to deletion.
Looking at setup[.]py
in forenitq
, Carlos found the following first-stage payload:
The attacker creates three temporary files that download and execute Windows binaries from specific URLs using the "start" command. Even though the slugs /rat
and /clip
are suggestive of malicious intent, we couldn’t confirm that assumption without looking under the hood.
At the time of this writing, the page hosted at hxxp://20[.]226[.]18[.]203
is still active and it only shows a link to a Discord invite that’s already expired or private.
Carlos noticed that the package was posing as the popular
After deobfuscating the RAT file, he found a line that loads a possible clipboard hijacker, but the specifics of it were base64 encoded:
Upon decoding, we get a Python code designed to hijack a victim's clipboard to replace the intended cryptocurrency wallet address with the attacker's address:
It looks for specified patterns like bitcoin (bc1), Ethereum (0x), Monero (4), and litecoin (L or M or 3), and when a pattern is found, it replaces the intended address with the attacker's cryptocurrency wallet address.
The code uses the
Additionally, we uncovered more techniques this RAT mutant uses to evade detection: a first-stage payload added to the file forenitq/ansi[.]py
instead of setup[.]py
and a second-stage polymorphic payload that changes every time you run the binary.
The attacker also added a new command and control with a very complete help menu—and this time se fala português:
As you can see, malicious actors are eager to steal your crypto funds and system credentials to further penetrate your infrastructure. Their RAT malware keeps mutating to be more evasive and damaging to developers. So, if you're not safeguarding your software supply chain today, consider taking action to do so as soon as possible.
hxxp://20[.]226[.]18[.]203/inject/tCxFLYLT6ViY9ZnP
hxxp://20[.]226[.]18[.]203/clip
hxxp://20[.]226[.]18[.]203/rat