Info Stealing Packages Hidden in PyPI

Affected platforms: All platforms where PyPI packages can be installed
Impacted parties: Any individuals or institutions that have these malicious packages installed
Impact: Leak of credentials, sensitive information, etc.
Severity level: High

The Python Package Index (PyPI) is an open repository of software packages developed by the Python community to help people quickly develop or update applications. While most of the packages uploaded to PyPI are posted by dedicated individuals looking to support the Python community, threat actors also regularly post packages infected with malware. The FortiGuard Labs team uses a proprietary, AI-driven OSS malware detection system to hunt for and monitor these threats. Recently, we identified a PyPI malware author (who goes by the ID “WS”) discreetly uploading malicious packages to PyPI. We now estimate that there may be well over 2000 victims of “WS” just from the packages described below alone.

The identified packages—nigpal, figflix, telerer, seGMM, fbdebug, sGMM, myGens, NewGends, and TestLibs111—exhibit attack methodologies similar to those outlined in a Checkmarx blog post published four months ago. The similarity suggests a possible connection to a malicious campaign from early 2023. Notably, these packages incorporate base64-encoded source code of PE or other Python scripts within their setup.py files. Depending on the victim devices’ operating system, the final malicious payload is dropped and executed when these Python packages are installed.

A brief timeline of our findings about this info-stealing author is detailed below.

Figure 1: A brief timeline of malicious PyPI packages published by the author “WS”

Figure 1: A brief timeline of malicious PyPI packages published by the author “WS”

The packages released before December 2023 are very similar to those discussed in earlier blog posts. Specifically, they deploy Whitesnake PE malware if the victim’s device runs on Windows, or they can deliver a Python script designed to steal information from Linux devices. A subtle distinction lies in the new method now being used by the Python script to transmit stolen data. Instead of relying on a single fixed URL, these new malware variants use a range of IP addresses as the destination, likely to ensure successful data transmission even if one server fails. Given the strong resemblance of these new packages to the previous ones, we will focus on analyzing the payloads from these more recent variants.

Unlike earlier attacks that targeted both Windows and Linux users, this recent set of packages predominantly targets Windows users. While the executable payload for each package varies slightly from one another, they consistently aim to exfiltrate sensitive information from victims.

Let’s take a brief look at a few of these payloads.

PE Payload of sGMM Package

Unlike the previous Whitesnake PE payloads developed using .NET, this sample manifests as a Python-compiled executable crafted using the PyInstaller tool.

Upon careful examination of its contents post-extraction, the primary script file is revealed as ‘main.pyc’ accompanied by an ‘addresses.py’ counterpart. The mere presence of this counterpart raises suspicions.

Figure 2: Extracted files

Figure 2: Extracted files

Upon decompiling ‘main.pyc,’ we can see that the code is somewhat incomplete, accentuating its clandestine nature. Red flags include copying itself to the Windows startup folder for autorun on startup. The script also probes logical drives, endeavoring to copy itself into non-removable drives. Notably, it adopts a discreet strategy by monitoring the count of its running instances, ensuring an inconspicuous profile complete with an exit strategy if the count surpasses two.

Figure 3: Decompiled main.pyc

Figure 3: Decompiled main.pyc

Finally, the script retrieves the clipboard contents and compares them against predefined cryptocurrency address patterns. The discovery of matching patterns prompts the script to overwrite the clipboard with corresponding addresses sourced from ‘addresses.py.’ This could deceive unsuspecting victims into directing things like cryptocurrency transactions to an unexpected destination.

Figure 4: addresses.py

Figure 4: addresses.py

PE Payload of myGens & NewGends Packages

This payload is an encrypted .NET executable. Upon being installed on the user’s device, the payload launches an invisible window of “cmd.exe.” It then uses “powershell.exe” through this window to add itself to the Windows Defender’s exclusion list to bypass the built-in security response:

Figure 5: Adding itself to the Windows Defender exclusion list

Figure 5: Adding itself to the Windows Defender exclusion list

It then copies itself to the Windows Application folder and creates a scheduled task to run itself every hour once the device is infected:

  • %LOCALAPPDATA%\Packages\Microsoft.Windows.Accounts.ControlRCP_ruzxpnew4af
  • HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tasks\{070B9798-7C59-4A69-BB25-F353628999B0}\Path|\MicrosoftWindowsControlRCP
Figure 6: Confirmation of copying itself and scheduling a task

Figure 6: Confirmation of copying itself and scheduling a task

Each time the task runs, it establishes a connection to the malicious IP: 194[.]36[.]177[.]30. It uses “socket.io” to connect the server to the client. This way, if the connection is lost, it will automatically try to reconnect. 

Figure 7: Decryption of “socket.io” and IP

Figure 7: Decryption of “socket.io” and IP

The core of this payload tries to collect user information, such as the user’s IP address, the host credentials, etc.:

Figure 8: User info grabber

Figure 8: User info grabber

The following strings offer more compelling evidence of the information-stealing capabilities of this payload. They reveal that the payload not only captures mouse and keyboard interactions but also acquires and transmits wallet and browser data to the remote server.

Figure 9: List of Properties for the stealer

Figure 9: List of Properties for the stealer

Figure 10: Snippet of code showing wallet grabbing

Figure 10: Snippet of code showing wallet grabbing

Figure 11: Function showing browser stealing

Figure 11: Function showing browser stealing

PE payload of TestLibs111 Package

Once this sample runs, we can observe data being sent to a suspicious IP address (194[.]36[.]177[.]30), as shown in Figure 12. At first glance, we might dismiss these as inconspicuous strings. However, further investigation shows this to be a .zip file shrouded in multiple layers of encryption. This raises serious concerns about its behavior.

Figure 12: Traffic sent to IP address 194[.]36[.]177[.]30

Figure 12: Traffic sent to IP address 194[.]36[.]177[.]30

Upon decryption, we see ‘PK’ as the initial bytes, indicating a .zip file format.

Figure 13: Hex dump of .zip file

Figure 13: Hex dump of .zip file

After debugging this sample, there are several indicators as to what sensitive content it may be interested in. Below are a few of the many interesting strings that were found during our analysis.

Figure 14: Strings found in assembly code

Figure 14: Strings found in assembly code

Some of these strings may indicate info-stealing from different services, such as browsers, applications, and cryptocurrency services. Some examples we found included Chrome, Discord, Filezilla, and Coinbase.

When we extract the .zip file, we can see some of the collected content.

Figure 15: zip file contents

Figure 15: zip file contents

The author then exfiltrates this sensitive information to the server.

Conclusion

This blog demonstrates the ability of a single malware author to disseminate numerous info-stealing malware packages into the PyPI library over time, each featuring distinct payload intricacies. Users are urged to exercise utmost caution when using open-source packages, checking for malicious content or payloads that may render targeted devices susceptible to information theft. The narrative of this particular malware author has unfolded over several months and showcases the considerable amount of havoc that has been wrought. Information-stealing malware is an increasingly pertinent and pressing subject. Safeguarding against such persistent adversaries demands a strategic and forward-thinking approach to fortify your defenses.

Fortinet Protections

FortiGuard AntiVirus detects the malicious files identified in this report as

nigpal-0.1 setup.py: PYTHON/Agent.c51b!tr
nigpal payload: (PE) MSIL/WhiteSnake.C!tr
nigpal payload: (Python) PYTHON/Agent.7f73!tr
figflix-0.1 setup.py: PYTHON/Agent.c51b!tr
figflix-0.2 setup.py: PYTHON/Agent.c51b!tr
figflix payload: (PE) MSIL/WhiteSnake.C!tr
figflix payload: (Python) PYTHON/Agent.7f73!tr
telerer-2.0 setup.py: PYTHON/Agent.c51b!tr
telerer-2.1 setup.py: PYTHON/Agent.c51b!tr
telerer-2.2 setup.py: PYTHON/Agent.c51b!tr
telerer-2.3 setup.py: PYTHON/Agent.c51b!tr
telerer payload: W32/Kryptik.HTVT!tr
seGMM-1.3.1 setup.py: PYTHON/Agent.c51b!tr
seGMM-3.1.1 setup.py: PYTHON/Agent.c51b!tr
seGMM payload: W32/Kryptik.HTVT!tr
fbdebug-0.1 setup.py: PYTHON/Agent.c51b!tr
fbdebug payload (PE): MSIL/WhiteSnake.C!tr
fbdebug payload (Python): PYTHON/Agent.7f73!tr
sGMM-1.3.2 setup.py: PYTHON/Agent.c51b!tr
sGMM payload: W32/ClipBanker.DE!tr
myGens-1.3 setup.py: PYTHON/Agent.c51b!tr
myGens-1.3 payload: MSIL/Agent.ERW!tr.spy
NewGends-1.3 setup.py: PYTHON/Agent.c51b!tr
NewGends-1.3 payload: MSIL/Agent.ERW!tr.spy
TestLibs111-1.4 setup.py: PYTHON/Agent.c51b!tr
TestLibs111-1.5 setup.py: PYTHON/Agent.c51b!tr
TestLibs111-1.7 setup.py: PYTHON/Agent.c51b!tr
TestLibs111 payload: W32/Agent.ORR!tr.pws

The FortiGuard AntiVirus service is supported by FortiGate, FortiMail, FortiClient, and FortiEDR. Customers running current AntiVirus updates are protected.

The FortiGuard Web Filtering Service detects and blocks the download URLs cited in this report as Malicious.

The FortiDevSec SCA scanner detects malicious packages, including those cited in this report that may operate as dependencies in users’ projects in test phases, and prevents those dependencies from being introduced into users’ products.

If you believe these or any other cybersecurity threat has impacted your organization, please contact our Global FortiGuard Incident Response Team.

IOCs

FileHash (sha256)Detection
nigpal-0.1 setup.pyc53d1387864ea3034bc4e19af492b3e67147d3fdc1d8b9752e24600d6919e3afPYTHON/Agent.c51b!tr
nigpal payload (PE)ab75ea75d1fe5bc51ecef274a95f7b835b09a0c7c95c4227366a3d64b5dee7c0MSIL/WhiteSnake.C!tr
nigpal payload (Python)24e07dd8c4a6fb92d842ebc168a40505bbd0421a16c13a06571910ca7a40a5a5PYTHON/Agent.7f73!tr
figflix-0.1 setup.py41ff3fedb78c672c6d0e5e849f81c8be10c0767558fcfdf6f529215556354d9ePYTHON/Agent.c51b!tr
figflix-0.2 setup.py377e8ca04aed57a10b350d9eb4a6e64818bb69b790f33db4be0fd22589c435adPYTHON/Agent.c51b!tr
figflix payload (PE)34e5bd67fbd9a7040dca9cae90e36013aaeda1940bb39e7fcd5d5fa9c85cadc8MSIL/WhiteSnake.C!tr
figflix payload (Python)b2bf755c4e1336f5ab36bc679d4a86e4c0d4da7b33a26b9ec8c01e179027f66bPYTHON/Agent.7f73!tr
telerer-2.0 setup.py3dcff80475ebfb9a3aa93f3cebd8f008ea64d857a7c53719f1ca047dfd050e1cPYTHON/Agent.c51b!tr
telerer-2.1 setup.pydc5b74c1007bbe9acce3cddf30870766867b40e7d37264b7bdaf3b5f40747c10PYTHON/Agent.c51b!tr
telerer-2.2 setup.pyf1f6501a97b9145d8dd755d25a39c1803fe54995a39fd59b2914f591d56bdc68PYTHON/Agent.c51b!tr
telerer-2.3 setup.py8bdc674e3a41370a2d0a997b6ca673c6d646ed580400af242980a5ec374864a2PYTHON/Agent.c51b!tr
telerer payload4fac457f8170e26643d0a4d8a0199e93d72872e1799e95f5c522a50754982079W32/Kryptik.HTVT!tr
seGMM-1.3.1 setup.pyef0e1a8378d1dd9e3cfd0d59d1969b618e15ddb4bbfaf50057670842004346e8PYTHON/Agent.c51b!tr
seGMM-3.1.1 setup.py6fe87ab0590229d11f2d174bcf13cfbaca6f6c9dc55af84527c96de16c12c799PYTHON/Agent.c51b!tr
seGMM payload4fac457f8170e26643d0a4d8a0199e93d72872e1799e95f5c522a50754982079W32/Kryptik.HTVT!tr
fbdebug-0.1 setup.pyda0c21c66fd0dc42b1bcb06c9bd0d7e48b1b866720229712df64410eebd62199PYTHON/Agent.c51b!tr
fbdebug payload (PE)d9568da21005794d80eb6572ccce47cc766ba5fe24b2b82cd4ff2cf05d8531a2MSIL/WhiteSnake.C!tr
fbdebug payload (Python)ec9e1342b0bddbd0ef65cd37a751b3a8c3c8170cdd8cce0f0fb6815b6be26a45PYTHON/Agent.7f73!tr
sGMM-1.3.2 setup.py8fb72c3a6a5d96f91c3dc46541331ebf0a6cf326d2353ab6f2b1c119e9907670PYTHON/Agent.c51b!tr
sGMM payload94be6da31c5f896017af733a44b9ea00abbb35bce0a8dbcab776367234e4d818W32/ClipBanker.DE!tr
myGens-1.0 setup.pyf22110ea2376082651f5f0724875e6f9d083e2be0688dc06b59206c35fa50defPYTHON/Agent.c51b!tr
myGens payload03a1621af484ff8f5c1797b25426bab656b6731dba43e31fe58fc1f1963d8484MSIL/Agent.ERW!tr.spy
NewGends-1.3 setup.py857bc70fb5968b9f5e257e41f4be9cdd8c7135314bf6200e2cf5b60186401e7aPYTHON/Agent.c51b!tr
NewGends payload03a1621af484ff8f5c1797b25426bab656b6731dba43e31fe58fc1f1963d8484MSIL/Agent.ERW!tr.spy
TestLibs111-1.4 setup.pyc9e0b8c6c5140acae2b3bf003d9ae2a69abf04253b0bd932ec97c732a4b9bf97PYTHON/Agent.c51b!tr
TestLibs111-1.5 setup.py0e13bb49aba0878b919bc0980ce2e9e3cfa876387fcedf5af41235ab0f7a440aPYTHON/Agent.c51b!tr
TestLibs111-1.7 setup.py14cd40cce030bfca6a4c06fdadd353b5eaa092e7f73ba65308afedc04270c9b9PYTHON/Agent.c51b!tr
TestLibs111 payload2b617277fc551b7500867ee009a0f80cbe6d5ee729bdfbf9b4f9d52164811082W32/Agent.ORR!tr.pws
IP Address
194[.]36[.]177[.]30
95[.]140[.]147[.]126[:]8080
78[.]46[.]66[.]9[:]8080
116[.]203[.]194[.]247[:]8080
206[.]189[.]109[.]146[:]80
217[.]145[.]238[.]175[:]80
164[.]90[.]185[.]9[:]443
185[.]216[.]26[.]127[:]8080
94[.]156[.]6[.]209[:]80
185[.]217[.]98[.]121[:]443
185[.]217[.]98[.]121[:]80
192[.]99[.]44[.]107[:]8080
52[.]86[.]18[.]77[:]8080
18[.]218[.]18[.]183[:]80
192[.]99[.]196[.]191[:]443
216[.]250[.]190[.]139[:]80
24[.]199[.]110[.]250[:]8080
35[.]166[.]49[.]216[:]8080
5[.]78[.]68[.]6[:]8009
44[.]228[.]161[.]50[:]443
162[.]33[.]178[.]113[:]80
103[.]226[.]125[.]218[:]80
106[.]15[.]66[.]6[:]8080
121[.]63[.]250[.]132[:]88
18[.]228[.]80[.]130[:]80
65[.]20[.]76[.]112[:]80
47[.]96[.]78[.]224[:]8080
216[.]39[.]242[.]18[:]8080
129[.]151[.]109[.]160[:]8080
168[.]138[.]211[.]88[:]8099
139[.]99[.]123[.]53[:]9191
54[.]92[.]18[.]154[:]443
135[.]181[.]98[.]45[:]8888
65[.]108[.]226[.]108[:]8080
45[.]155[.]171[.]134[:]8080
141[.]94[.]175[.]31[:]8098
116[.]202[.]101[.]219[:]8080
129[.]159[.]134[.]19[:]8080
107[.]161[.]20[.]142[:]8080
3[.]142[.]76[.]113[:]80
104[.]184[.]140[.]41[:]9000
205[.]185[.]123[.]66[:]8080
154[.]31[.]165[.]232[:]80
139[.]84[.]231[.]199[:]8080
103[.]244[.]151[.]46[:]8080
52[.]196[.]241[.]27[:]443
13[.]112[.]250[.]213[:]443
189[.]115[.]63[.]77[:]8080

Don’t Stop Here

More To Explore

favicon__1_ removebg-png

BE THE FIRST TO KNOW

Stay informed with the latest insights in our Infostealers weekly report.

Receive immediate notification if your email is involved in an infostealer infection.

No Spam, We Promise

favicon__1_ removebg-png

BE THE FIRST TO KNOW

Stay informed with the latest insights in our Infostealers weekly report.

Receive immediate notification if your email is involved in an infostealer infection.

No Spam, We Promise