CrashStealer: C++-os macOS adathalász, amely összeomlásjelentőnek álcázza magát

enlightened Ez az oldal a közösségért készül. heart Kövess minket máshol is:  Linux Mint Magyar Közösség a Mastodon-on  Telegram csatorna – csak hírek  Beszélgessünk a Telegram – Linux csevegő csoport  Hírek olvasása RSS segítségével  Linux Mint Hivatalos Magyar Közösség a Facebook-on      Linux Mint Baráti Kör a Facebook-on
wink Ha hasznosnak találod, és szeretnéd, hogy folytatódjon, támogasd a munkát Ko-fi vagy Paypal segítségével. laugh

kami911 képe

A Jamf Threat Labs felfedezte és elemezte a CrashStealer nevű, C++-ban írt macOS adathalászt, amely az Apple összeomlásjelentő frameworkjének adja ki magát. Böngészőkben tárolt hitelesítő adatokat, kriptotárcákat és kulcskarika-adatokat gyűjt, a megszerzett fájlokat AES-GCM-mel titkosítja, majd egy távoli parancs- és vezérlőszerverre küldi.

Bevezetés

Május elején a ViRustotalra feltöltött gyanús macOS-mintára lettek figyelmesek a mintafeldolgozó pipeline-ukon keresztül, és a Jamf Threat Labs elkezdte követni. Az Apple összeomlásjelentő frameworkjét utánozta, és akkor még olyan adathalásznak tűnt, amely fejlesztés alatt áll. Július elejére már olyan, éles környezetben észlelt payloadokat láttak, amelyek megfeleltek az egyik saját szabályuknak. Ez arra utalt, hogy a projekt túllépett a fejlesztési szakaszon, és aktív támadásokban használják. Ezt a kártevőt CrashStealer néven követik.

A legtöbb, macOS-t célzó, tömegesen terjesztett adathalásszal ellentétben – amelyek többnyire AppleScript dropperre vagy vékony Objective-C shellre épülnek – a CrashStealer natív C++-ban készült, egy MacOSData nevű belső osztály köré szervezve. A támadó kód a helyi gépen ellenőrzi az áldozat bejelentkezési jelszavát, mielőtt adatgyűjtésbe kezd. Széles körben gyűjt adatokat böngészőkből, kriptotárcákból, jelszókezelőkből és a kulcskarikából, a begyűjtött információkat AES-GCM-mel titkosítja, majd libcurl segítségével küldi ki. A tartósságot úgy biztosítja, hogy lemásolja és újra aláírja önmagát. Bár céljai átfednek olyan családokéval, mint az Atomic (AMOS), a MacSync vagy a Phexia, natív C++-os megvalósítása és a kliensoldali titkosítás megkülönbözteti ezektől, ezért önálló családként, nem pedig variánsként kezeljük.

Azóta azonosították a payloadot megelőző lépcsőt is: egy aláírt és Apple által hitelesített droppert, amelyet "Werkbit Setup" nevű lemezképként terjesztenek. Ez tölti le a CrashStealer payloadot a támadó infrastruktúrájáról, majd elindítja. Mivel a dropper érvényes Developer ID-t és hozzácsatolt notarization ticketet tartalmaz, első indításkor gond nélkül átmegy a Gatekeeper ellenőrzésén, ellentétben az általa telepített, ad-hoc aláírással rendelkező payloaddal.

A cikkben végig a CrashStealert a saját megfigyeléseik alapján mutatják be, és kiemeljék azokat a viselkedésmintákat, amelyek a védekezés szempontjából a legfontosabbak.

Aláírt, hitelesített dropper, amely telepítőnek álcázza magát

A kezdeti fertőzés egy "Werkbit Setup" nevű lemezképen keresztül történik, amely a /Volumes/Werkbit Setup útvonalon csatolódik, és egyetlen alkalmazáscsomagot tartalmaz, a Werkbit.app-ot. A benne lévő futtatható állomány neve veltod, a bundle azonosítója pedig dev.golove.velto. A végül telepített payloaddal ellentétben a droppert szabályosan aláírták és hitelesítették: univerzális (arm64 és x86_64) bináris, amelyet az Emil Grigorov (WWB7JA7AQV) Developer ID-vel írtak alá, hardened runtime engedélyezve van rajta, és hozzácsatolt notarization ticketet is tartalmaz. Figyelemre méltó, hogy nemcsak az alkalmazást, hanem magát a lemezképfájlt is aláírták. Ez ritka a rosszindulatú DMG-k terjesztésénél, ahol a konténer általában aláíratlan marad.

Amikor a lemezképet csatolják, egy igényes, Werkbit Setup logóval ellátott „telepítő” ablak jelenik meg. Lépésről lépésre végigvezeti az áldozatot az alkalmazás megnyitásán, és arra utasítja, hogy a programot jobb gombbal kattintva, az Open menüponttal indítsa el. A jobb gombos megnyitás jól ismert módszer a Gatekeeper megkerülésére. Itt viszont a dropper már notarizált, normálisan is elindulna, ezért ez az utasítás elsősorban social engineering: ráveszi az áldozatot, hogy futtassa az alkalmazást.

Amikor az áldozat megnyitja, a veltod először a GitHub felé fordul: lekérdezi a GitHub API-t, majd nyers tartalmat tölt le, hogy megszerezze a sys.cache nevű fájlt a mgothiclove/pkeys tárolóból (hxxps://GitHub.com/mgothiclove/pkeys/blob/main/sys.cache). Ez a fájl tartalmazza azt a curl parancsot, amelyet a dropper a következő lépésben futtat. Az első ugrást egy tRustelt fejlesztői domainre helyezik, így a kezdeti hálózati forgalom kevésbé feltűnő. A letöltött parancs curl segítségével egy shell scriptet húz le a hxxps://endpoint-api-v1[.]com/d/f1b24e kézbesítési végpontról. A script nem olvasható formában kerül a lemezre; a működéséhez szükséges sztringek Base64 blokkok sorozataként érkeznek, amelyeket futásidőben dekódolnak (három egymást követő base64 -d hívást figyeltünk meg, amelyek egy végső tr -cd 'a-zA-Z0-9' tisztítást tápláltak), mielőtt az összeállított scriptet a bash-nak továbbítják.

Dekódolás után a script egy önálló downloader-telepítő, amely letölti és előkészíti a payloadot:

A viselkedés egyértelmű, és megmagyarázza azokat az artefaktumokat, amelyeket korábban csak az endpointon láttunk. A script a payload lemezképet titkosítatlan HTTP-n tölti le a hxxp://endpoint-api-v1[.]com/d/f1b24e/download címről, legfeljebb háromszor próbálkozik, és CrashReporter.dmg néven menti a /tmp könyvtárba. A lemezképet böngészés és ellenőrzés nélkül csatolja (hdiutil attach -nobrowse -noverify -noautoopen -quiet), bemásolja az első .app bundle-t, amit talál, egy rejtett könyvtárba, a /tmp/.CrashReporter alá, majd leválasztja a lemezképet és törli a letöltött .dmg fájlt. Az előkészített bundle kiterjesztett attribútumait az xattr -cr paranccsal törli, futtathatóvá teszi a belső binárist, eltávolítja a payload meglévő aláírását, majd ad-hoc módon újra aláírja (codesign --remove-signature, majd codesign -s - --force --deep --no-strict), regisztrálja a Launch Services felé az lsregister -f paranccsal, végül háttérben elindítja az open -g -n segítségével.

Két dolgot érdemes kiemelni a védekezők számára. Először is, a payload ad-hoc aláírását és azt, hogy a rejtett /private/tmp/.CrashReporter/ útvonalról fut; az alábbiakban jelzett mindkét jellemzőt ez a dropper script hozza létre, nem maga a payload. Másodszor, a kezdeti hozzáférési fázist aláírták és hitelesítették az Emil Grigorov (WWB7JA7AQV) Developer ID alatt, a dev.golove.velto bundle azonosítóval, és először a GitHub tároló mgothiclove/pkeys projektjét éri el, majd az endpoint-api-v1[.]com címet. Ezek mindegyike tartós jelző a detektáláshoz és a célzott kereséshez. Maga a Werkbit Setup lemezkép a hxxps://werkbit[.]io címről származik, amelynek domainjét 2026 júniusának végén regisztrálták, szinte napra pontosan egybeesve az általunk elemzett dropper build dátumával. A letöltés ott egy meeting PIN mögé van rejtve, így a telepítőt csak azok kapják meg, akik a megfelelő kóddal érkeznek, nem pedig bármelyik véletlen látogató. Azóta további domaineket és közös backend infrastruktúrát azonosítottunk, amelyek ugyanahhoz a művelethez köthetők, ami arra utal, hogy a CrashStealer egy nagyobb, többplatformos kampány egyik eleme.

Miután megerősítette, hogy ezt a Developer Team ID-t rosszindulatú payloadok terjesztésére használták, a Jamf Threat Labs jelentette az ügyet az Apple-nek.

A payload: lemezkép, amely rendszerkomponenst utánoz

A dropper által letöltött CrashReporter.dmg lemezkép egyetlen alkalmazás bundle-t tartalmaz, a CrashReporter.app-ot, amelyet úgy alakítottak ki, hogy az Apple beépített összeomlásjelentő komponensének tűnjön: a com.apple.crashreporter bundle azonosítót használja, a megjelenített neve CrashReporter, és saját alkalmazásikonja van, így az áldozat a lemezkép csatolásakor egy látszólag legitim Apple segédprogramot lát. Ahogy fentebb már szó volt róla, a futáskor látható ad-hoc aláírást a dropper adja a bundle-nek: eltávolítja az eredeti aláírást, majd helyben, indulás előtt újra aláírja.

Mostanra vissza tudtuk követni, hogyan jut el a payload a gépre: a fent leírt, aláírt dropper tölti le és készíti elő. Jól látszik, hogy a csomagolás ugyanarra az Apple-komponens-utánzásra épít, amely a kártevő többi részén is végigvonul, a bundle azonosítótól kezdve egészen a később telepített LaunchAgent címkéjéig.

A terepen észlelt fertőzésekből kiderült, hogy a bundle egy rejtett könyvtárból futott a /private/tmp alatt, pontosan innen: /private/tmp/.CrashReporter/CrashReporter.app/Contents/MacOS/CrashReporter. Ez megegyezik azzal az előkészítési útvonallal, amelyet a dropper hoz létre és ahonnan elindítja a programot. Eltér attól a helytől, ahová a minta később a tartós jelenlét érdekében másolatot telepít magáról (a ~/Library/Caches/ alá, erről később lesz szó), és a .CrashReporter könyvtár nevében lévő kezdőpont elrejti az előkészítési helyet az alapértelmezett Finder nézet elől. Egy alkalmazásbundle, amely egy rejtett /private/tmp útvonalról indul, önmagában is szokatlan, erős jelzésértékű indikátor.

Szándék az Info.plistben

Mielőtt rátérnénk a futás közbeni viselkedésre, érdemes alaposan megnézni a bundle Info.plist állományát, mert a készítők feltűnően sok működési részletet rejtettek el benne. Ahelyett, hogy a teljes konfigurációt a titkosított karaktersor-blokkba zsúfolták volna, a kártevő a property listben nyíltan elárulja a szándékai egy részét.

Két bejegyzéscsoport különösen szembeötlő. Az első egy sor TCC-használati leírás, amelyek egyértelműen megmutatják, milyen adatokhoz akar hozzáférni a kártevő:

Ezek a szövegek előre kitöltik azt az üzenetet, amelyet a macOS a jogosultságkérő ablakokban megjelenít. A „rendszeradminisztrációhoz” szükséges jogosultságként beállított szöveg tipikus social engineering: arra próbálja rávenni az áldozatot, hogy engedélyezze a teljes lemezhozzáférést. A Desktop, Documents, Downloads és a cserélhető meghajtók leírásai pontosan megfelelnek azoknak a helyeknek, amelyeket a fájlkereső komponens később végigjár. A bundle az LSUIElement értékét true-ra állítja, így háttéragentként fut Dock ikon és ablak nélkül, a CFBundleVersion pedig mindössze 1.0.1, ami jól illik egy korai fejlesztési fázisban lévő projekthez. Figyelemre méltó, hogy a később megfigyelt minták már teljesen elhagyják az LSUIElement kulcsot; ez csak egy a több kisebb, buildenként változó eltérés közül, amelyet a családon belül láttunk.

A második, jóval szokatlanabb bejegyzés egy App Transport Security (ATS) kivétel, amely közvetlenül a property listben kódolja a command-and-control címet:

Az App Transport Security határozza meg macOS-en, hogy egy alkalmazás milyen hálózati kapcsolatokat létesíthet; alapértelmezés szerint HTTPS-t ír elő TLS 1.2-vel vagy újabbal, továbbá forward secrecyvel. Ez a kivétel fellazítja ezeket a követelményeket a 179.43.166.242 címre: engedélyezi a titkosítatlan HTTP-t, a minimális TLS-verziót 1.0-ra csökkenti, és elengedi a forward secrecy követelményét, az NSAllowsArbitraryLoads pedig végső menekülőútként gyakorlatilag teljesen kiiktatja az ATS-t.

Valószínűleg a fejlesztők tesztkörnyezetének melléktermékéről van szó: így az operátor akkor is eléri a C2-t, ha a szerver konfigurációja nem megfelelő. A védelmi oldal számára a lényeg: a C2-cím a property listben, tiszta szövegként szerepel.

Ez az ATS-kivétel a korábbi mintákban még megjelenik, az újabbakból viszont már hiányzik. Valószínű, hogy időközben érvényes TLS-t állítottak be a command-and-control szerveren, így már nem kellett az App Transport Securityt fellazítani egy nem biztonságos végpont kedvéért. Ez jól illeszkedik ahhoz a képhez, hogy a kártevőcsalád a fejlesztési fázisból fokozatosan a „termelési” használat felé mozdul, és azt is jelenti, hogy az Info.plistben keménykódolt C2-cím jó indikátor a korábbi mintákra, de nem feltétlenül igaz a legfrissebb buildekre.

Végrehajtási folyamat

A mintát sandboxolt környezetben futtattuk, és dinamikus elemzéssel rögzítettük a tevékenységét. A megfigyelt végrehajtási lánc megfelel a statikus elemzésnek, és kitölti a lemezen zajló műveletek részleteit.

Magas szinten a végrehajtás az alábbi lépéseken halad végig, ezeket vesszük sorra a folytatásban:

  • A bináris törli a metaadatokat, beleértve a saját karantén attribútumát is.
  • Jelszókérő ablakot jelenít meg, és helyben ellenőrzi a megadott hitelesítő adatot.
  • A hitelesített jelszóval feloldja a login kulcskarikat.
  • Felderíti a telepített biztonsági és elemző eszközöket.
  • Összegyűjti a böngészők adatait, a kriptotárca-bővítményeket, a jelszókezelők adatait és a kulcskarika tartalmát.
  • A begyűjtött adatokat titkosítja, miközben rejtett könyvtárakba helyezi őket, majd archívumokba csomagolja.
  • Második példányt ír magáról, azt újra aláírja, majd LaunchAgentként állandó jelenlétet alakít ki.
  • Törli az ideiglenes tárolásra használt könyvtárakat.

Karantén eltávolítása

Indulás után azonnal egy shell-paranccsal törli a saját útvonalán lévő kiterjesztett attribútumokat:

Az xattr -cr egyetlen lépésben szedi le az összes kiterjesztett attribútumot, így egyszerre tűnik el a com.apple.quarantine jelző és a com.apple.lastuseddate#PS időbélyeg is. Ez csökkenti annak esélyét, hogy a következő futtatásoknál megjelenjen a Gatekeeper figyelmeztetése. A com.apple.lastuseddate#PS időbélyeg, amely ezzel együtt törlődik, gyakran hasznos az incidenskezeléssel foglalkozó szakembereknek.

Jelszóbeaptés és helyi ellenőrzés dscl-lel

Futása során a stealer egy natív jelszókérő ablakot jelenít meg, amely megtévesztésig hasonlít egy valódi macOS jogosultságkérő párbeszédablakra. Ahogy sok macOS adathalász, a megadott hitelesítő adatot helyben ellenőrzi: a dscl nevű, leGititim macOS directory-service segédprogramot hívja meg -authonly opcióval, mielőtt továbbhaladna:

A dinamikus elemzés során ez a parancs sikeresen lefutott, ami megerősítette, hogy a megadott jelszó érvényes volt. A rutin ciklusban működik: ha a jelszó hibás, a végrehajtási lánc megakad, és a stealer újra és újra kéri a jelszót, amíg helyes hitelesítő adatot nem kap. Az, hogy a jelszót először dscl -authonly segítségével ellenőrzi, majd csak ezután kezd a gyűjtésbe, lehetővé teszi a támadónak, hogy csak valóban működő hitelesítő adatokat tartson meg, a zajt pedig ne küldje ki. A létrehozott dscl folyamat hasznos viselkedésbeli jel a védelmi oldalon.

A hitelesített jelszót egy helyi cache-fájlba írja (a megfigyelt elérési út: ~/.cache/.sys_auth, a jogosultság 600), hogy a további lépésekben újra felhasználhassa. A tartalom nem egyszerű szöveg, de az alacsony entrópia arra utal, hogy csak egyszerű elrejtésről van szó, nem valódi titkosításról.

Kulcskarika feloldása

A hitelesített jelszó birtokában a stealer feloldja a login kulcskarikat, ismét egy leGititim Apple bináris meghívásával:

Az így feloldott login.keychain-db ezután a staging területre kerül másolásra, így az áldozat eltárolt titkai a gyűjtő rutin számára könnyen elérhetővé válnak.

Biztonsági eszközök felderítése

A gyűjtés előtt és közben a stealer jellegzetes felderítő pásztázást végez. A célzott listában szereplő minden egyes alkalmazásnál két parancsot futtat: először kiolvassa az alkalmazás verzióját, majd leméri a lemezen elfoglalt méretét:

A felelős belső rutin neve a bináris saját debug sztringjei szerint collectSoftwareTargets, és számlálókat vezet a feldolgozott és kihagyott elemekhez. Nem az összes telepített alkalmazást veszi sorra, hanem egy beágyazott, előre meghatározott listából dolgozik. Elemzésünkben az általa lekérdezett alkalmazások – egy kivétellel – macOS kártevőelemző, endpoint security és EDR eszközök voltak, nem pedig olyan szoftverek, amelyek nyilvánvalóan értékesek lennének adatlopás szempontjából. Az egyetlen kivétel a Safari volt, amelyet a stealer máshol, külön gyűjtési célpontként kezel.

A defaults read és du -sh párosítása könnyű módszer arra, hogy ellenőrizze, telepítve van-e egy adott eszköz, és melyik build található a rendszeren. Az, hogy főleg elemző, endpoint security és EDR eszközöket vizsgál, arra utal, hogy a rutin legalább részben a védelmi környezet feltérképezésére szolgál. Ugyanakkor az, hogy egy adott futás során mit kérdez le, attól függ, mi van telepítve, és a célpontlista titkosítva van a binárisban, ezért a teljes halmaz valószínűleg jóval szélesebb annál, mint amit mi láttunk.

Gyűjtési kör

A stealer gyűjtési köre kiterjedt. Saját debug sztringjei nevezik meg a felelős rutinokat: collectBrowserData (amely egy skipSafari kapcsolót kap), collectExtensions, collectFirefoxExtensions, collectSoftwareTargets és runFileSearcher. A dinamikus elemzés során megfigyelt fájlrendszer-aktivitás alapján a megfelelő könyvtárstruktúrát egy rejtett staging gyökér alá hozza létre: ~/.cache/com.apple.crashreporter/.

A böngészőadatoknál a stealer a Chromium-családba tartozó böngészőket célozza. A sztringjei között szerepel többek között a Chrome, Brave, Edge, Opera és Opera GX, Vivaldi, Chromium és NAVER Whale, és kezeli a Default, Profile nevű profilkönyvtárakat is. A bináris linkeli az SQLite-ot, beleértve az sqlite3_backup API-t (ez a szabványos módja annak, hogy egy futó böngésző által zárolt adatbázist lemásoljanak), és olyan artefaktumokat hoz létre, amelyek a Firefox logins.json hitelesítéstárolójáról kapták a nevüket, illetve _IDB utótagú könyvtárakat, amelyek a böngészők és kiegészítőik által használt IndexedDB tárolóknak felelnek meg.

A célzott kriptotárcák és jelszókezelők köre is kiterjedt. Dinamikus elemzés közben a stealer minden egyes célponthoz külön staging könyvtárat hozott létre, így közvetlenül látszott a lista: nagyjából 80 kriptotárca-bővítmény, köztük a MetaMask, Phantom, Coinbase, TRust Wallet, Rabby, OKX Wallet, Exodus, Keplr, Solflare és Backpack; emellett hosszú a kisebb szereplők sora a Solana, Cosmos, TON, Sui, aptos és NEO ökoszisztémákból. Emellett 14 jelszókezelőt is gyűjt, például az 1Password, Bitwarden, LastPass, Dashlane, Keeper, KeePassXC, NordPass, Enpass és RoboForm alkalmazásokat. A begyűjtött adatokat rejtett, futásonként külön könyvtárakba írja a staging gyökér alatt (például ~/.cache/com.apple.crashreporter/.brw_/), ahol az egyes elemeket külön-külön titkosított .cache fájlokban tárolja, nem pedig olvasható formában. A böngészős és hitelesítési staging könyvtárban a feloldott login kulcskarika másolata is megjelenik Keychain/login.keychain-db néven, a captured fiókhoz tartozó jelszót pedig a könyvtár gyökerében lévő password.txt fájlba írja.

A bináris szimbólumaiban és debug sztringjeiben runFileSearcher / FileSearcher::search néven szereplő külön fájlkereső komponens rekurzívan bejárja a felhasználói könyvtárakat – például a ~/Documents és ~/Downloads útvonalakat – és megpróbálja kiszűrni azokat a fájlokat, amelyeket érdemes ellopni. A szűrési logika külön figyelmet érdemel, mert tudatos válogatásra utal, nem pedig vaktában történő gyűjtésre. A kereső a fájlrendszer bejárása közben kihagy egy beégetett könyvtárlistát, amit a visszafejtett összehasonlító logika is megerősít: Caches, Logs, Trash és .Trash, CrashReporter, DiagnosticReports, WebKit, Saved Application State, nsurlsessiond, bird, node_modules, __pycache__ és .Git. Kiterjesztés alapján is szűr, minden fájlnevet összevet egy táblázattal (amely .dylib-bel kezdődik), és ami egyezik, azt eldobja: futtatható állományok és libraryk (.dylib, .so, .o, .a, .framework, .app, .exe, .dll, .sys), lemezképek és telepítők (.dmg, .iso, .pkg, .deb, .msi), valamint nagy archívum- és médiaformátumok (.zip, .tar, .gz, .rar, .7z, .mp4, .mov, .png és hasonlók). Az ilyen nagy, lényegtelen binárisok és telepítők kihagyása bevett gyakorlat az infostealerek körében, mert így a begyűjtött adathalmaz kisebb és célzottabb marad. Az eljárás eredményét a FileSearch_Results.txt fájlba és egy GrabbedFiles könyvtárba írja.

Titkosítás és exfiltráció

A CrashStealer a begyűjtött adatokat titkosítja, mielőtt elhagyják a gépet, és ezt már a staging során megteszi: a gyűjtő rutinok eleve titkosított .cache fájlokként írják ki az adatokat a staging könyvtárakba, így a zsákmány a lemezen sincs olvasható formában, mielőtt archiválnák.

A titkosítás hitelesített és mai szemmel is korszerű. Minden elemet AES-256-GCM-mel titkosít a CommonCrypto frameworkön keresztül, a szokásos lépéssorral: cryptor létrehozása (CCCryptorCreateWithMode), inicializáló vektor beállítása (CCCryptorGCMSetIV), titkosítás (CCCryptorGCMEncrypt), majd a hitelesítési tag véglegesítése (CCCryptorGCMFinal). A 32 bájtos kulcsot PBKDF2-HMAC-SHA256-tal származtatja 10 000 iteráción keresztül (CCKeyDerivationPBKDF), egy jelszó és egy só felhasználásával. A só nem véletlenszerű: futásidőben dekódolja egy beégetett konstansból, amelyet a készítők panel_salt_v1 néven jelöltek, illetve egy közeli, olvasható sztringből: using fallback salt — set CONFIG_CRYPTO_SALT for production. Ez arra utal, hogy a fejlesztők eredetileg konfigurálható sóval számoltak, de bennhagyták a fejlesztői alapértelmezést. Ugyanez a rutin hívja meg a GCM visszafejtő függvényeket is, így az üzemeltető oldalon a megfelelő kulccsal vissza tudják fejteni az adatokat. A .cache kiterjesztésű staging fájlok vizsgálata ezt támasztja alá: nincs bennük olvasható fejléc vagy fájltípusra utaló magic, és a mért entrópiájuk közel van az elméleti maximumhoz (nagyjából 8,0 bit bájtonként), ami erős titkosításra, nem pedig kódolásra vagy tömörítésre utal.

Feltöltés előtt a stealer minden staging könyvtárat saját, rejtett ZIP archívumba csomagol, a zip segédprogram meghívásával. Az elemzés során gyűjtési kategóriánként egy archívumot hozott létre, mindet a staging gyökérbe írta, .zx_ előtaggal és nyolc hexadecimális karakterrel, például: .zx_c67e4203.zip:

A nyolcjegyű hex érték futásonként véletlenszerű, ezért a fenti konkrét nevek fertőzésenként eltérnek, de a .zx_ előtag, a nyolc hexadecimális karakter mintázata, a .zip kiterjesztés és az elhelyezkedés állandó. A staging könyvtárak és az azokban lévő titkosított .cache fájlok más, nem hexadecimális elnevezési sémát használnak, ezért a ZIP archívumok adják a legtisztább kapaszkodót a felismeréshez.

A .brw_ archívum tartalmazza a böngészőkből és hitelesítő tárolókból származó adatokat, köztük a lemásolt login.keychain-db fájlt és a password.txt-t. A .ext_ archívumba kerülnek a kriptotárca- és jelszókezelő-bővítmények adatai, míg a .sw_ archívum a szoftveres felderítés eredményeit gyűjti. Ezek a .zx_.zip fájlok jelentik a becsomagolt zsákmányt, és nagy valószínűséggel ezeket találják meg a védelmi oldalon a lemezen. Figyelemre méltó, hogy amikor a stealer takarít maga után, csak a staging könyvtárakat (.brw_, .ext_ és .sw_) törli rm -rf paranccsal; az általunk megfigyelt tevékenység során a .zx_.zip archívumokat nem törölte, így azok futás után is a ~/.cache/com.apple.crashreporter/ alatt maradnak. Emiatt a rejtett, .zx_-el kezdődő ZIP fájlok keresése ebben a könyvtárban, ~/.cache/com.apple.crashreporter/, kiemelten hasznos lépés a detektálás és a triage során. Mivel a staging fájlok már titkosítottak, ezek az archívumok csak titkosított adatot tartalmaznak, így a jelenlétük a gyűjtés tényét igazolja, akkor is, ha a benne lévő adatok nyugalmi állapotban nem olvashatók.

Az adatexfiltrációt a libcurl végzi, annak multipart űrlap interfészével (a curl_mime függvénycsaláddal). A command-and-control végpont a 179.43.166.242-es IP-cím, amelyet a minta Info.plist fájljában keménykódolt ATS-kivételként adtak meg. Dinamikus elemzés közben azt láttuk, hogy a minta közvetlenül indulás után hálózati forgalmat generál erre az IP-re, ami megerősíti, hogy ez egy aktív C2, nem pedig egy tétlen konfigurációs bejegyzés. Az elemzés idején a címre 11 rosszindulatú találatot jeleztek a nyilvános threat intelligence források. A teljes command-and-control URL futásidőben áll össze titkosított sztringekből.

Másolás, újra-aláírás és perzisztencia

Ahelyett, hogy egy külön második fázist töltene le, a CrashStealer úgy marad tartósan jelen a rendszeren, hogy lemásolja és újra-aláírja önmagát. A futó bináris létrehozza a ~/Library/Caches/com.apple.crashreporter/CrashReporter.app csomagot, a saját futtatható állományát a Contents/MacOS/ alá írja (először .tmp kiterjesztéssel, majd átnevezi a végleges helyére és futtathatóvá teszi), és mellé ír egy Info.plist fájlt. Ezután eltávolítja a karantént az új bundle-ről, és ad-hoc módon újra-aláírja:

Az ad-hoc újra-aláírás felülírja a kódaláírási adatokat a másolt binárisban, így megváltozik a fájl hash értéke és a CodeDirectory hash (cdhash) is, noha a kód maga változatlan marad.

A perzisztenciát ezután egy felhasználói LaunchAgent biztosítja. A stealer létrehozza a ~/Library/LaunchAgents/com.apple.crashreporter.helper.plist fájlt, majd betölti:

A bootstrap hívás regisztrálja a com.apple.crashreporter.helper labelt, ismét egy Apple-összetevőt utánozva, így az újra-aláírt másolat minden bejelentkezéskor elindul. Az archiválás után a stealer rm -rf paranccsal eltávolítja az ideiglenes staging könyvtárait.

Az alábbiakban látható a telepített property list:

Néhány kulcs jól mutatja, mire helyezi a hangsúlyt ez a kártevőcsalád. A RunAtLoad és a KeepAlive, amelyben a SuccessfulExit false, együtt azt eredményezi, hogy az agent bejelentkezéskor elindul, és a launchd minden sikertelen kilépés után újraindítja, így a kártevő folyamatosan jelen marad. A ProcessType értéke Background, az AssociatedBundleIdentifiers mezőben pedig ismét a com.apple.crashreporter szerepel, vagyis az Apple-összetevőnek álcázás a perzisztencia rétegében is folytatódik. A StandardOutPath és a StandardErrorPath egyaránt a /dev/null-ra mutat, így minden kimenetet eldob, amit a folyamat egyébként hátrahagyhatna, ami jól illeszkedik a máshol is megfigyelt csendes működéshez.

Obfuszkáció és elemzés elleni védekezés

A CrashStealer látványos energiát fordít arra, hogy megnehezítse az elemzést, három fő területen.

Control-flow flattening. A függvényeket úgy lapítja el, hogy az áttekinthető vezérlési gráf helyett a végrehajtás diszpécser blokkokon fut keresztül, amelyek fordítási idejű konstansok alapján, jump table-ök segítségével ágaznak el. Széles körben alkalmazza, és jelentősen lelassítja a kézi visszafejtést.

Titkosított sztringek. Az érzékeny sztringeket – köztük a command-and-control URL-t, fájlrendszer-útvonalakat, böngésző- és tárcaazonosítókat, valamint a szoftverfelderítési célpontok listáját – egy titkosított blobként tárolja a __const szekcióban, és futásidőben dekódolja egy bájt-helyettesítéses rutin segítségével. Csak a fejlesztési és debug sztringek maradnak olvashatók, ennek köszönhetően a működési sztringek visszafejtése előtt is név szerint fel tudtuk sorolni a család képességeit.

Többrétegű anti-debugging. A minta több ponton is ellenőrzi, fut-e debugger. Egy, a main előtt lefutó konstruktor – a dinamikus linker inicializálása során – a szokásos macOS debugger-ellenőrzést használja: sysctl hívást végez KERN_PROC / P_TRACED lekérdezéssel, és ha debugger csatlakozik, 45-ös kilépési kóddal leáll, még mielőtt bármilyen kártékony viselkedés elindulna. Önmagában nem elég ezt az első ellenőrzést kiiktatni: az alkalmazás inicializálása későbbi szakaszában egy második ellenőrzés ugyanígy kilép. Ha nincs debugger csatlakoztatva, a minta normálisan fut, ami alátámasztja, hogy a vizsgálatok kifejezetten a debugger jelenlétét célozzák, és a naiv, egyetlen pontra irányuló patch-elést akarják meghiúsítani.

Élő operátori felület a terjesztési domainen

A terjesztési domain egy webes operátori felületet is kiszolgál. Ha a böngészővel a hxxps://endpoint-api-v1[.]com/login címre lépünk, egy sötét témájú, „Command Panel” feliratú bejelentkezési oldal jelenik meg, felhasználónév- és jelszómezővel, valamint „Remember me” opcióval. Nem tudni, pontosan mi található mögötte, de az a tény, hogy ugyanazon a gépen fut, amely a dropper scriptet és a payloadot is kiszolgálja, arra utal, hogy az endpoint-api-v1[.]com élő operátori infrastruktúra, nem pedig egyszer használatos terjesztési domain. A panelt a MalwareHunterTeam is azonosította, és megosztotta X-en. Mivel ugyanahhoz a terjesztési domainhez tartozik, a CrashStealerhez tudjuk kötni.

Nem ez az egyetlen ilyen panel. Azóta további, ugyanahhoz a kampányhoz köthető operátori felületeket is azonosítottak, például a cohezo[.]io, cohezo[.]com, cordinex[.]io címeken; ezeket alább, a Kompromittálódás jelei szakaszban soroljuk fel.

Következtetés

A CrashStealer terjesztési lánca átgondolt felépítést mutat: a támadók nem egy egyszerű, aláíratlan csalit használnak, hanem egy aláírt és notarizált dropperrel indítanak, amely átengedi a Gatekeepert, majd csendben letölti, újra aláírja és elindítja a payloadot. Maga a payload egy natív C++ macOS infostealer, amely a megszokott célokat tudatosabb megvalósítással párosítja. Nem az különbözteti meg igazán a tömegterméknek számító stealerektől, hogy mit gyűjt, hanem az, hogyan építették fel: a begyűjtött fájlok kliensoldali AES-GCM titkosítása, valamint az elemzéssel szembeni ellenállás hangsúlyozása control-flow flatteninggel, titkosított sztringekkel és többrétegű anti-debugging technikákkal.

A Jamf Threat Labs továbbra is figyeli ezt az aktivitást, és követi a kapcsolódó infrastruktúrát és variánsokat. A Jamf for Mac termékben az ügyfelek úgy állíthatják be a threat prevention, advanced threat controls és web protection funkciókat, hogy Block and Report módon segítsenek megelőzni a hasonló fenyegetések futtatását.