Cyble – New KEKW Malware Variant Identified In PyPI Package Distribution

Stealer with Clipper Making Rounds in a Mass Campaign

PyPI (Python Package Index) is a widely used repository for software packages for the Python programming language, utilized by developers worldwide for sharing and downloading Python code. Due to the widespread usage of PyPI, it has become a desirable target for Threat Actors (TAs) who aim to attack developers or their projects.

Malicious packages are usually uploaded by disguising them as useful software or by imitating well-known projects by altering their names. In the past, we have encountered multiple instances where attackers have utilized PyPI packages to distribute malware payloads. It has been noted that the frequency of InfoStealers being disseminated through malicious PyPI packages is increasing.

Recently, Cyble Research and Intelligence Labs (CRIL) uncovered multiple malicious Python .whl (Wheel) files that were found to be distributing a new malware named ‘KEKW’. KEKW malware can steal sensitive information from infected systems, as well as perform clipper activities which can lead to the hijacking of cryptocurrency transactions.

Following our investigation, we found that the Python packages under scrutiny were not present in the PyPI repository, indicating that the Python security team had removed the malicious packages. Additionally, CRIL verified with the Python security team on 02-05-2023 and confirmed that they took down the malicious packages within 48 hours of them being uploaded.

Since the malicious packages were taken down quickly, it is impossible to determine the number of people who downloaded them. Nevertheless, we believe that the impact of the incident may have been minimal.

The following packages were observed spreading KEKW malware:

  • pythonsqlitetool-1.0.0
  • pipsqlpackageV2-1.0.0
  • pipfontingaddonsV2-1.0.0
  • pythoncryptoaddition-1.0.0
  • pipcoloringsextV1-1.0.0
  • syssqlitemods-1.0.0
  • syscryptographymodsV2-1.0.0
  • syscoloringspkg-1.0.0
  • syssqlite2toolsV2-1.0.0
  • pythoncolorlibV1-1.0.0
  • pythoncryptolibV2-1.0.0
  • pythonsqlite2toolsV1-1.0.0
  • pycolourkits-1.0.0
  • pythoncolouringslibV2-3.0.0
  • pythoncolouringslibV2-3.0.2
  • pythoncolouringslibV2-3.0.1
  • pythoncolouringslibV2-1.0.0
  • pysqlite3pkgV2-1.0.0
  • pyapicolorv2-0.0.1
  • pythoncryptlibery-1.0
  • pipcryptaddsV2-1.0.0
  • sysdatalib-0.0.2
  • pysqlilibraryV1-1.0.0
  • syscryptlibV2-1.0.0
  • syssqlite2package-1.0.0
  • pipcolourpackagesV2-1.0.0
  • pylibfont-0.1.0
  • pythonsqlite2mod-1.0.0

In this campaign, we have identified TAs engaging in financial theft by incorporating clipper functionality and stealer. We have also observed several stealer payloads containing different crypto addresses associated with the TA’s clipper activities. We selected one of the Bitcoin addresses that appeared in over 20 packages and found that there had been a significant increase in transactions for that specific crypto address in the past month.

The figure below provides details of the TAs’ Bitcoin wallet transactions.

Figure 1 Transactions per Month
Figure 1 – Transactions per Month

Additionally, we discovered that the majority of Python files within the packages contained the domain name “kekwltd[.]ru”. In contrast, only a few contained “blackcap[.]ru”, suggesting that these domains may be linked to the TA.

The figure below shows the TA’s active domain.

Figure 2 TAs Domain
Figure 2 – TA’s Domain

Code Analysis

For our analysis, we have taken the Python package “pythonsqlitetool-1.0.0”, which is a .whl file. The .whl file in Python is a wheel distribution format used for packaging and distributing Python software. The .whl file is essentially a ZIP archive containing all the necessary files to install a Python package, including the code, data files, and metadata.

Package name pythonsqlitetool-1.0.0-py3-none-any.whl

The .whl file includes an ‘__init__.py’ Python file capable of carrying out malicious actions within the user’s system.

At the beginning of the ‘__init__.py’ Python file, the necessary packages are installed on the victim’s system using the ‘pip install’ command, as shown below.

Figure 3 Installing new python packages
Figure 3 – Installing new Python packages

Functionalities

The primary function of the Python package file includes various capabilities such as anti-debugging, persistence, collecting system information, stealing and grabbing sensitive data from various applications, carrying out clipper activities, and more.

Figure 4 Primary functions of the malware python file
Figure 4 – Primary functions of the malware Python file

Anti-VM

The Python malware file verifies whether it is running within a controlled environment by examining pre-defined blacklisted hard-coded strings such as username, computer name, system IP address, or hardware ID.

The malware terminates its execution if it identifies a match with any of the strings mentioned below.

Figure 5 Hardcoded strings to identify virtual environment
Figure 5 – Hardcoded strings to identify a virtual environment

Process Termination

The malware checks to determine if any security-related processes are running on the target’s system. If it identifies such processes, it terminates them. The list of security-related process names hardcoded into the script can be seen in the figure below.

Figure 6 Hardcoded security related process name
Figure 6 – Hardcoded security-related process name

Persistence

The KEKW malware sets up a startup entry to achieve persistence, allowing it to execute automatically whenever the victim logs in to their computer using the function startupkekw().

The code snippet below depicts how the malware achieves persistence on the victim’s system.

Figure 7 Establishing Persistence on victim systems
Figure 7 – Establishing Persistence on victim systems

Collecting System information

The KEKW malware uses the system_information() function to acquire system-related data such as login username, computer name, Windows product key and version, RAM capacity, HWID, IP address, geographic location, Google Maps information, and more.

This is illustrated in the figure below.

Figure 8 Collecting system details
Figure 8 – Collecting system details

Stealer

The primary objective of the malicious Python script is to retrieve sensitive information from the target’s web browser, which includes:

  • Passwords
  • Cookies
  • Histories
  • Credit card details
  • Tokens
  • Profiles

The Python script utilizes multiple separate functions to extract browser data, including files from a range of web browsers such as Google Chrome, Microsoft Edge, Yandex, Brave, Amigo, and others, as shown in the figure below.

Figure 9 Targeted browsers to steal sensitive information
Figure 9 – Targeted browsers to steal sensitive information

The figure below displays the code snippet of the Python function responsible for stealing passwords from the targeted browsers.

Figure 10 Steal passwords function
Figure 10 – Steal passwords function

The figure below shows the code snippet of the function used to steal the cookies from the browsers.

Figure 11 Steal cookies function
Figure 11  – Steal cookies function

The code snippet function was used to steal the history from the browsers files in the image below.

Figure 12 Steal browser history function
Figure 12 – Steal browser histories function

The Python function that steals the credit card details from the browsers is illustrated in the figure below.

Figure 13 Steal Credit card function
Figure 13 – Steal Credit card function

The image below shows the various browsers targeted by this malware to steal tokens.

Figure 14 Targeted application to steal tokens
Figure 14 – Targeted application to steal tokens

Grabber

Additionally, the Python script has functions grabb_mc() and grabb_roblox() to retrieve crucial data, including profiles, account credentials, cookies, cache, and more, from well-known video game platforms like Minecraft and Roblox as shown in the below code snippet.

Figure 15 Grabber function
Figure 15 – Grabber function

Clipper

The malware uses the address_swap() function to carry out the clipper activity by replacing the intended cryptocurrency wallet address (as specified in the ‘__config__’  section of the Python file) with the attacker’s cryptocurrency address. This action redirects the victim’s cryptocurrency funds to the attacker’s account.

The below figure shows the code snippet of the clipper function used in the malware Python file.

Figure 16 Clipper function
Figure 16 – Clipper function

Capture Screenshot

Moreover, the malware can capture screenshots of the target system by utilizing the steal_screen() function. This action allows the attacker to gain access to sensitive information on the victim’s device, which can be used for malicious purposes by the threat actor.

Figure 17 Capture screenshot
Figure 17 – Capture screenshot

grabb_GatherAll()

The malware has a function called grabb_GatherAll() that steals passwords and cookies from various popular applications, including Gmail, YouTube, eBay, Netflix, Uber, Outlook, Hotmail, PayPal, TikTok, and others.

The figure below shows the code snippet that steals sensitive information from various popular applications.

Figure 18 Code snippet used to steal information from popular applications
Figure 18 – Code snippet used to steal information from popular applications

Moreover, the malware scans the “Desktop”, “Downloads”, and “Documents” directories for text files with specific names related to sensitive information, such as passwords, login credentials, online transactions, online accounts, wallets, and others. Upon locating these files, it extracts the pertinent data.

Figure 19 File grabber function with keyword list
Figure 19 – File grabber function with keyword list

The malware is also designed to collect sensitive information from specific applications such as Atomic Wallet, Exodus Wallet, Steam, and NationsGlory.

After obtaining the stolen data, the malware formats it into JSON, compresses it into a ZIP file, and then proceeds to upload the compressed archive to the command and control (C&C) server, as shown below.

  • hxxps[:]//kekwltd[.]ru
Figure 20 Exfiltrating stolen information
Figure 20 – Exfiltrating stolen information

Conclusion

The group responsible for the KEKW stealer malware has launched a widespread campaign to distribute it. The group targets developers using malicious Python packages, which may also put corporate networks at risk.

The timely action of the Python security team in removing the malicious packages has helped to mitigate the severity of this incident. However, this incident highlights the ongoing threat of supply chain attacks and the importance of remaining vigilant and practicing good cybersecurity hygiene.

Our Recommendations

  • Avoid downloading pirated software from warez/torrent websites. The “Hack Tool” on sites such as YouTube, Torrent sites, etc., contains such malware.
  • Use strong passwords and enforce multi-factor authentication wherever possible.
  • Turn on the automatic software update feature on your computer, mobile, and other connected devices.
  • Use a reputed anti-virus and internet security software package on your connected devices, including PC, laptop, and mobile.
  • Refrain from opening untrusted links and Email attachments without first verifying their authenticity.
  • Educate employees on protecting themselves from threats like phishing/untrusted URLs.
  • Block URLs that could be used to spread the malware, e.g., Torrent/Warez.
  • Monitor the beacon on the network level to block data exfiltration by malware or TAs.
  • Enable Data Loss Prevention (DLP) Solutions on the employees’ systems.

MITRE ATT&CK® Techniques

Tactic  Technique ID  Technique Name 
Execution  T1204 
T1047
User Execution
Windows Management Instrumentation
Persistence T1547 Registry Run Keys / Startup Folder
Defense Evasion T1497
T1562
Virtualization/Sandbox Evasion
Disable or Modify Tools
Credential Access T1056 Credential API Hooking
Discovery    T1057
T1012
T1082
T1083
Process Discovery
Query Registry
System Information Discovery
File and Directory Discovery
Collection T1005 Data from Local System
Command and
Control   
T1071 Application Layer Protocol  

Indicators of Compromise (IOCs)

Indicators Indicator Type Description
1cc87ac9d9066a9829e4245fd86d4cfc
b449b53a50d80ccfaba259ce98424d3f8e4b2c85
7167f3c8f24eebc374ecf4d132fc5e2ff681d208a3b02ab5547f488698d2fffc
MD5
SHA1 SHA256
pipcoloringsextV1-1.0.0-py3-none-any.whl
76e08229aae953002dce4fe06454e158
ac9ac60bd7bdb43bdd8c728c3aa00434f05d52cc
7485ce031144f1800328b1d538c3eaddd589af85e0323d895e0763f88cb74652
MD5
SHA1 SHA256
pipcolourpackagesV2-1.0.0-py3-none-any.whl
d211815d0507aa070b99d5a6c9e3c300
11485ddb88da5dae6e4f9b81f51b32a56565141c
6b951cc544151c6d21ebc2b92dcbeccb03e5c130060fcc671335caead0a19a9e
MD5
SHA1 SHA256
pipcryptaddsV2-1.0.0-py3-none-any.whl
1e5a4f71632ed0eac001551c6453e2e0
4e2b1fe66e3961f1bbf9805289a9d3d2b3dc0b61
1553712ce5551698f2eeacba0aedaac9d14a6a236d5da1d17e0456a554cf457d
MD5
SHA1 SHA256
pipfontingaddonsV2-1.0.0-py3-none-any.whl
001beecd74578178013fec56d10724df
228f0d5bb26d7dab58a80bdcb07a7e686e373448
510bc06cfbecf2e1f135bb28b3361558eb529c86d7c65e614d0baea1843db997
MD5
SHA1 SHA256
pipsqlpackageV2-1.0.0-py3-none-any.whl
a09e78a04a89e5756c5e5f327758a95e
9ac5ea70a7d8bab4150f670eab33cc41e5375223
744e76feed753102fbb364bdc9cb93faaa63388affa2d30b13c3aa6fe55b0ed9
MD5
SHA1
SHA256
pyapicolorv2-0.0.1-py3-none-any.whl
7fa034ccc098809acabfff2fcd4e96ef
2d9d01ea2b76de6d442cd06f1d480593a40962f9
729844cd91c501cd0a5e5bdac6011713f5615b1a2ea408b18551e7f0214f7c47
MD5
SHA1
SHA256
pycolourkits-1.0.0-py3-none-any.whl
1629406cbb606fdc4b6a83849f05d12c
6ab46b181445b6dcb52241b02c28b871f913bff9
37fcab1f0926a59c0eead0fbbd597c485e46749ebc5ea177b7ccddfff638cd6a
MD5
SHA1
SHA256
pylibfont-0.1.0-py3-none-any.whl
d2b0d9bfd1b01f5dfc4cb7f89ffab1ad
d0d1a5c2dff40f7a5025e38548bcddfca6dd3863
2d4e38b5fbcdbbdd23a12974c2ee0f0443b27d57b1bebf68a489c1d45dd544f5
MD5
SHA1
SHA256
pysqlilibraryV1-1.0.0-py3-none-any.whl
0e2861958488e067d3da724d9baaa42a
d3391263ce5b0f516ec1f664692583562215c094
0b4350d79fa4d48942357eac02d1d77d78aa5a2f3b46e0baf802b9bcfc9866dd
MD5
SHA1
SHA256
pysqlite3pkgV2-1.0.0-py3-none-any.whl
16c67a78cb0f52a8f8fc3091db86b32d
b50134c238f77610581524d5280fdc54e9c9aa4b
9f615cc4af941382e81d8327ccfee8aa5f9df06911e04c0687f93643fea176c0
MD5
SHA1
SHA256
pythoncolorlibV1-1.0.0-py3-none-any.whl
aec4cc668cb66f5647090efe65e1a878
a1f056b8fb4ba621801c562bcffd5881e3c9879b
74cf526d7f1a9cc9695ebd467e98c494ed2a411cf78140219ceeeb411a2a1aa0
MD5 SHA1 SHA256 pythoncolouringslibV2-1.0.0-py3-none-any.whl
e84408efb2d1bf3602163c2670de695d
96127e2e7a7e8dd3663dd16e936dd99a86d3b4ed
3d2631c811648f1d127c1a4463b31261ef966353da8c4b5e8fa25ebd78e2644c
MD5
SHA1
SHA256
pythoncolouringslibV2-3.0.0-py3-none-any.whl
c49f69cc7ee19e5587b383ab46606862
69b3e7acb9ac9c33ca2fb6319995572d23261f41
beb591e7824c255603e240eb944525b8894ff50da8cafd6b13d024b710730f0b
MD5
SHA1
SHA256
pythoncolouringslibV2-3.0.1-py3-none-any.whl
535e0ec23456420e9e584e56becdde4c
839041e7ee124b2081fa8bbe4f4cc7cc6378865a
63b71c19226c3b6d0cfaa1e5a77593baba711c011d7926ac3fd47848230c02de
MD5
SHA1
SHA256
pythoncolouringslibV2-3.0.2-py3-none-any.whl
7cba37fe4a82bd727d16140cb00192cb
bbfd43cb3d7f7cb0807ff10474ce26d1b85bea61
25b2892e4cff541fcf93ba6b04b047d8e6ef4ad991ebebf2354ad1cb8572e714
MD5
SHA1
SHA256
pythoncryptlibery-1.0-py3-none-any.whl
1ba4b9a81a9df9a457e8565e63785b85
f28bb0f3cdb2d1d3181e02df6c908c5a952eb6e1
9ff56e7adf7b56956a0c6e1b9500f0818dafa540da18c23a3eaf1740f6ba00f7
MD5
SHA1
SHA256
pythoncryptoaddition-1.0.0-py3-none-any.whl
f13c2c898f2ed318897bca865a9c8069
928a521c6a63da6cdb6a8e3b5dbe204c1e2dfe15
a435a615856ac27b7a004874ed85082a576abe48fb1af2853bd7f6edbf2a938c
MD5
SHA1
SHA256
pythoncryptolibV2-1.0.0-py3-none-any.whl
7eb67f0591d6ade5ad399dca770a0a6b
9774d70072f8c37a1e610351fd59a47444d1cd06
11e24f6bcf023b570395053d55b5a80126aee80e5ec95b5a85edb435fc503dce
MD5
SHA1
SHA256
pythonsqlite2mod-1.0.0-py3-none-any.whl
a325f3786acb7806a132684fdfe2112b
67c033b047d858ba06658d9576815e6b9d759d0e
350e2e499cb216273474d872668ce49f495c732166ab20babef02c9dc8962055
MD5
SHA1
SHA256
pythonsqlite2toolsV1-1.0.0-py3-none-any.whl
258df1f7a44e343f41a1167e919a3821
2e9ad7aae14b8dae6db1fdcc58c7f449c779ad73
10591a1e39f0d4d39fc9368d5624c0d63c44dbb2d8edb3620d8e02e611c40c49
MD5
SHA1
SHA256
pythonsqlitetool-1.0.0-py3-none-any.whl
fd4bd57d2e4e819ce372d5c5d7bba38a
9c44ff1cd30fb5a7690ac38ed38bbcf3247707e0
844d6bb5871f867e9d284c543c38934a4b50c4f5830af097244bbc612e8c3b7f
MD5
SHA1
SHA256
syscoloringspkg-1.0.0-py3-none-any.whl
e1c8f589963cb0eff93027a7fcfb4b73
1013143dfdb13b44b7f4dfa63e97cf8915339fa7
5cdeae60841c390df95f8c8ad67819746116873ed1e1ae6cc7900c1b74927524
MD5
SHA1
SHA256
syscryptlibV2-1.0.0-py3-none-any.whl
38af78324644015f6f607722c128b5d8
ad3e9fa977236ceac8189176ae4d957eead1374f
cb6622ad17023ea904a1523d7d1e3f6608a94cdec00f891bccf8735d6e2821cb
MD5
SHA1
SHA256
syscryptographymodsV2-1.0.0-py3-none-any.whl
cd674b4f5df5c2714205f25097621fae
7cf35adab2ce09ae0fdf629314b86fb2e6d41b53
21e175a3ea87dc5911b2d4cf30d17846cdd28c8bab7f402b20530699108400f4
MD5
SHA1
SHA256
sysdatalib-0.0.2-py3-none-any.whl
55145b977e2aade4dd6a1e7f9966266f
bec7cd783f07edd2d9c688bdb3678607e3b9516c
75980669d22cf5461ba563fd8a484486e1786d26c653036729b5af8a3e00b061
MD5
SHA1
SHA256
syssqlite2package-1.0.0-py3-none-any.whl
cb7c4e1944f852862ec30c2a593582a2
7239e24630b89dd9694c19bab4f4e461b8074d2e
3087728bc04ecc0df07100a297d393d8b94f21245a8a4aa0c4414e5eb84eb8c7
MD5
SHA1
SHA256
syssqlite2toolsV2-1.0.0-py3-none-any.whl
e9e052a0448f8da19f75bb1360978505
69f9f8ea73c4cabb80440e091455af3a9a69d478
ba860998a5f7b935461d127b103604e65fd353673a1e571cfca987ac7d5121ef
MD5
SHA1
SHA256
syssqlitemods-1.0.0-py3-none-any.whl

Source: https://blog.cyble.com/2023/05/03/new-kekw-malware-variant-identified-in-pypi-package-distribution/