Die Analyse der PartyTicket-Ransomware durch das CrowdStrike Intelligence Team Research & Threat Intel zeigt, dass sie Dateien oberflächlich verschlüsselt und den Verschlüsselungsschlüssel nicht ordnungsgemäß initialisiert, wodurch die verschlüsselte Datei mit der zugehörigen Erweiterung .encryptedJB wiederhergestellt werden kann. Die Ransomware enthält Implementierungsfehler, die ihre Verschlüsselung knackbar und langsam machen. Dieser Fehler deutet darauf hin, dass der Autor der Malware entweder keine Erfahrung im Schreiben in Go hatte oder nur begrenzte Anstrengungen in das Testen der Malware investiert hat, möglicherweise weil die verfügbare Entwicklungszeit begrenzt war.
Technische Analyse
Ein PartyTicket-Ransomware-Beispiel hat einen SHA256-Hash von 4dc13bb83a16d4ff9865a51b3e4d24112327c526c1392e14d56f20d6f4eaf382. Er wurde in Verbindung mit den Dateinamen cdir.exe, cname.exe, connh.exe und intpub.exe beobachtet.
Das Ransomware-Beispiel – geschrieben mit Go Version 1.10.1 – enthält viele Symbole, die auf das politische System der USA verweisen, darunter voteFor403, C:/projects/403forBiden/wHiteHousE und primaryElectionProcess.
Die Ransomware iteriert über alle Laufwerksbuchstaben und zählt rekursiv die Dateien in jedem Laufwerk und seinen Unterordnern auf, wobei Dateipfade ausgeschlossen werden, die die Zeichenfolgen Windows und Programme sowie den Ordnerpfad C:\Dokumente und Einstellungen enthalten (der letztgenannte Ordner wurde in Windows-Versionen nach Windows XP durch C:\Users ersetzt). Dateien mit den folgenden Erweiterungen werden für die Verschlüsselung ausgewählt:
acl, avi, bat, bmp, cab, cfg, chm, cmd, com, contact, crt, css, dat, dip, dll, doc, docx, dot, encryptedjb , epub, exe, gif, htm, html, ico, in, iso, jpeg, jpg, mp3, msi, odt, one, ova, pdf, pgsql, png, ppt, pptx, pub, rar, rtf, sfx, sql, txt, url, vdi, vsd, wma, wmv, wtv, xls, xlsx, xml, xps, zip
Für jeden Dateipfad, der die zuvor beschriebenen Pfad- und Erweiterungsprüfungen besteht, kopiert die Ransomware eine Instanz von sich selbst in dasselbe Verzeichnis, aus dem sie ausgeführt wurde, und führt sie über die Befehlszeile aus, wobei sie den Dateipfad als Argument angibt. Der übergeordnete Ransomware-Prozess benennt seine Klone mit einer zufälligen UUID, die von einer öffentlichen Bibliothek2 generiert wird, die den aktuellen Zeitstempel und die MAC-Adressen der Netzwerkadapter des infizierten Hosts verwendet.
Der Malware-Entwickler hat versucht, die WaitGroup-Typen von Go zu verwenden, um Gleichzeitigkeit zu implementieren. Aufgrund eines wahrscheinlichen Codierungsfehlers erstellt die Ransomware jedoch eine sehr große Anzahl von Threads (einen pro aufgezähltem Dateipfad) und kopiert ihre eigene Binärdatei so oft in das aktuelle Verzeichnis, wie es ausgewählte Dateien gibt. Nachdem alle Verschlüsselungs-Threads beendet sind, löscht sich die ursprüngliche Binärdatei über die Befehlszeile.
Wenn das Beispiel einen Dateipfad als Argument erhält, verschlüsselt es die Datei mit AES im Galois/Counter-Modus (GCM). Der AES-Schlüssel wird mit der Intn-Funktion des Go rand-Pakets erzeugt, um Offsets im Zeichenarray 1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ auszuwählen und einen 32-Byte-Schlüssel zu erzeugen. Aufgrund eines weiteren wahrscheinlichen Kodierungsfehlers wird der Seed für die Funktion Intn nach der Schlüsselgenerierung aktualisiert, was bedeutet, dass bei jeder Ausführung der Binärdatei und ihrer Klone derselbe AES-Schlüssel erzeugt wird. Alle auf einem Host verschlüsselten Dateien werden mit demselben Schlüssel verschlüsselt, und die Kenntnis des Schlüssels des entsprechenden PartyTicket-Beispiels ermöglicht ihre Entschlüsselung. Ein Skript, das diese Schwachstelle nutzt, um die verschlüsselten Dateien wiederherzustellen, ist im CrowdStrike Git Repository verfügbar.
Für jede Datei wird der AES-Verschlüsselungsschlüssel selbst mit RSA-OAEP verschlüsselt, wobei ein öffentlicher RSA-Schlüssel mit den folgenden Parametern verwendet wird:
Modulus (N): 0xcbb94cb189a638b51e7cfe161cd92edb7145ecbd93989e78c94f8c15c61829286fd834d80c931daed4ac4aba14835fd3a6721602bcaa7193245fc6cf8e1d3261460ff3f1cbae3d44690beb989adee69ac486a932ee44dbdf0a44e772ab9822a16753cd08bdbb169f866f722114ee69c0cf1588fdaf8f7efd1c3ed243786078593f9b0cd867bab2b170c1843660d16e2181ae679137e2650551a41631398e027206e22a55858c741079ceafd50d5bd69546d4d52f5a33b0a576e1750d3f83afa1ce4403d768cbd670b443f61794b44705a8b1132c0c0ce77dbd04053ba20aec9baf23944270f10d16ad0727ed490c91c7f469278827c20a3e560f7c84015f7e1b
Exponent (E): 0x10001
Vor der Verschlüsselung benennt die Ransomware die Datei im Format <Original-Dateiname>.[vote2024forjb@protonmail[.]com].encryptedJB um („JB“ steht angesichts der anderen politischen Inhalte in der Binärdatei sehr wahrscheinlich für die Initialen des US-Präsidenten Joseph Biden). Die Ransomware überschreibt dann den Inhalt mit den verschlüsselten Daten. PartyTicket verschlüsselt nur die ersten 9437184 Bytes (9,44 MB) einer Datei. Ist die als Argument übergebene Datei größer als diese Grenze, werden alle darüber liegenden Daten unverschlüsselt gelassen. Nachdem der Dateiinhalt verschlüsselt wurde, fügt PartyTicket den RSA-verschlüsselten AES-Schlüssel am Ende der Datei an.
Die Ransomware schreibt außerdem eine HTML-Lösegeldforderung mit dem Namen read_me.html auf das Desktop-Verzeichnis des Benutzers, bevor die Verschlüsselung der Datei beginnt. Sofern es sich nicht um absichtliche Fehler handelt, deuten die grammatikalischen Konstruktionen in der Notiz darauf hin, dass sie wahrscheinlich nicht von einem fließend Englisch sprechenden Benutzer geschrieben oder korrekturgelesen wurde.
CrowdStrike Intelligence ordnet die PartyTicket-Aktivität zum Zeitpunkt der Erstellung dieses Berichts keinem namentlich genannten Angreifer zu. Insbesondere ist PartyTicket nicht so fortschrittlich wie DriveSlayer, das eine Low-Level-NTFS-Parsing-Logik implementiert. Die relative Unreife und die politische Botschaft der Ransomware, der Zeitpunkt der Verbreitung und die Ausrichtung auf ukrainische Einrichtungen deuten darauf hin, dass die Ransomware als zusätzliche Nutzlast neben DriveSlayer-Aktivitäten und nicht als legitimer Ransomware-Erpressungsversuch eingesetzt wurde.
YARA-Signaturen
Die folgende YARA-Regel kann verwendet werden, um PartyTicket zu erkennen:
Regel CrowdStrike_PartyTicket_01 : ransomware golang
{
meta:
copyright = „(c) 2022 CrowdStrike Inc.“
description = „Erkennt Golang-basierte Krypter“
version = „202202250130“
letzte_Änderung = „2022-02-25“
strings:
$ = „.encryptedJB“ ascii
$start = { ff 20 47 6f 20 62 75 69 6c 64 20 49 44 3a 20 22 }
$end = { 0a 20 ff }
Bedingung:
uint16(0) == 0x5A4D und uint32(uint32(0x3C)) == 0x00004550 und
für 1 von ($end) : ( @start < @ und @start + 1024 > @) und
alle von ihnen
}
Regel CrowdStrike_PartyTicket_02 : PartyTicket golang
{
meta:
copyright = „(c) 2022 CrowdStrike Inc.“
description = „Erkennt Golang-basierte PartyTicket-Ransomware“
version = „202202250130“
letzte_Änderung = „2022-02-25“
strings:
$s1 = „voteFor403“
$s2 = „highWay60“
$s3 = „randomiseDuration“
$s4 = „subscribeNewPartyMember“
$s5 = „primäreWahlProzesse“
$s6 = „baggageGatherings“
$s7 = „getBoo“
$s8 = „selbstWahl“
$s9 = „wHiteHousE“
$s10 = „encryptedJB“
$goid = { ff 20 47 6f 20 62 75 69 6c 64 20 49 44 3a 20 22 71 62 30 48 37 41 64 57 41 59 44 7a 66 4d 41 31 4a 38 30 42 2f 6e 4a 39 46 46 38 66 75 70 4a 6c 34 71 6e 45 34 57 76 41 35 2f 50 57 6b 77 45 4a 66 4b 55 72 52 62 59 4e 35 39 5f 4a 62 61 2f 32 6f 30 56 49 79 76 71 49 4e 46 62 4c 73 44 73 46 79 4c 32 22 0a 20 ff }
$pdb = „C://projects//403forBiden//wHiteHousE“
Bedingung:
(uint32(0) == 0x464c457f oder (uint16(0) == 0x5a4d und uint16(uint32(0x3c)) == 0x4550)) und 4 von ($s*) oder $pdb oder $goid
}
Skript zur Entschlüsselung von PartyTicket-verschlüsselten Dateien
Aufgrund der zuvor diskutierten Implementierungsfehler bei der AES-Schlüsselgenerierung ist es möglich, den von PartyTicket zur Verschlüsselung verwendeten AES-Schlüssel wiederherzustellen. Das folgende Go-Skript entschlüsselt Dateien, die mit dem PartyTicket-Beispiel 4dc13bb83a16d4ff9865a51b3e4d24112327c526c1392e14d56f20d6f4eaf382 verschlüsselt wurden. Das Skript nimmt die zu entschlüsselnde Datei als Argument über das „-p“-Flag und speichert die entschlüsselte Ausgabe in „decrypted.bin“ im gleichen Verzeichnis. Das Skript kann als ausführbare Datei erstellt oder über das Go-Run-Paket ausgeführt werden; es wurde mit der Go-Version go1.16.6 getestet.
package main
import (
„crypto/aes“
„crypto/cipher“
„encoding/hex“
„fmt“
„os“
„flag“
)
func main() {
encrypted_filepath := flag.String(„p“, „encrypted.bin“, „Path to encrypted file“)
flag.Parse()
fmt.Printf(„Decrypting file : %s\n“, *encrypted_filepath)
key_bytes := []byte(„6FBBD7P95OE8UT5QRTTEBIWAR88S74DO“)
key := hex.EncodeToString(key_bytes)
fmt.Printf(„Decryption key : %s\n“, key_bytes)
dat, err := os.ReadFile(*encrypted_filepath)
if err != nil {
fmt.Println(„Unable to open file, please supply path of encrypted file with flag -p, default file path is ./encrypted.bin“)
os.Exit(3)
}
decrypted_filepath := „decrypted.bin“
filecontents := dat
encrypted_contents := filecontents[:len(filecontents) – 288]
enc_size := len(encrypted_contents)
bsize := 1048604
cycles := enc_size / bsize
if cycles == 0{
encrypted := hex.EncodeToString(encrypted_contents)
decrypted := decrypt(encrypted, key)
write_output(decrypted_filepath, decrypted)
} else {
for i:=0; i<cycles; i++ { if i >= 9 {
start := 9 * bsize
end := enc_size
data := string(encrypted_contents[start:end])
write_output(decrypted_filepath, data)
break
}
block_start := i * bsize
block_end := (i+1) * bsize
if block_end > enc_size{
block_end := enc_size
encrypted:=hex.EncodeToString(encrypted_contents[block_start:block_end])
decrypted := decrypt(encrypted, key)
write_output(decrypted_filepath, decrypted)
}
encrypted:=hex.EncodeToString(encrypted_contents[block_start:block_end])
decrypted := decrypt(encrypted, key)
write_output(decrypted_filepath, decrypted)
}
}
fmt.Printf(„Decrypted file written to : %s\n“, decrypted_filepath)
}
func write_output(filepath string, data string) {
f, err := os.OpenFile(filepath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
panic(err)
}
byte_data := []byte(data)
f.Write(byte_data)
f.Close()
}
func decrypt(encryptedString string, keyString string) (decryptedString string) {
key, _ := hex.DecodeString(keyString)
enc, _ := hex.DecodeString(encryptedString)
block, err := aes.NewCipher(key)
if err != nil {
panic(err.Error())
}
aesGCM, err := cipher.NewGCM(block)
if err != nil {
panic(err.Error())
}
nonceSize := aesGCM.NonceSize()
nonce, ciphertext := enc[:nonceSize], enc[nonceSize:]
plaintext, err := aesGCM.Open(nil, nonce, ciphertext, nil)
if err != nil {
panic(err.Error())
}
return fmt.Sprintf(„%s“, plaintext
Der Cybersecurity Report von Hornetsecurity stuft 2,3 Prozent der Inhalte gar als bösartig ein. Die…
Die Hintermänner haben es auf Zugangsdaten zu Microsoft Azure abgesehen. Die Kampagne ist bis mindestens…
Cloud-Plattform für elektronische Beschaffungsprozesse mit automatisierter Abwicklung elektronischer Rechnungen.
Mindestens eine Schwachstelle erlaubt eine Remotecodeausführung. Dem Entdecker zahlt Google eine besonders hohe Belohnung von…
Nur rund die Hälfte schaltet während der Feiertage komplett vom Job ab. Die anderen sind…
Security-Experten von Check Point sind einer neuen Angriffsart auf die Spur gekommen, die E-Mail-Schutzmaßnahmen umgehen…