Inhalt
Wichtigste Erkenntnisse
- Im Rahmen eines Einsatzes zur Incident Response identifizierte das SECUINFRA Falcon Team eine interessante Malware-Probe mit dem Codenamen „CommieLoader“, die sich als Bewerbungsformular tarnt.
- CommieLoader installierte einen Cobalt Strike Beacon, der vom Angreifer für die Command-and-Control-Kommunikation genutzt wurde
Überblick
Unserem Kunden wurde per E-Mail ein ZIP-Archiv zugespielt, welche drei Dateien enthielt. Diese enthielt eine bisher unbekannte Malware, die wir aufgrund gewisser Artefakte “CommieLoader” nennen, welche schlussendlich zu einer Datenexfiltration führte. Im folgenden untersuchen wir die komplette Angriffskette dieser Malware.
Zeitrahmen
Die initiale Infektion erfolgte in dem Download-Verzeichnis des Nutzers. Durch die Ausführung des Sumatra Installers, welche in dem ZIP-Archiv enthalten war, wurde die maliziöse dbgcore.dll des selben Verzeichnisses mithilfe DLL-ForwardSideloadings geladen und Schadroutinen ausgeführt.
Im Folgenden sehen wir uns gemeinsam die schadhafte Datei dbgcore.dll an.
Analyse der Schadsoftware
Dbgcore.dll : a9121e70c39de2c10e6790da4aa3a22079242a201da2c1aeeb4ed65070e68e93
SumatraPDF installer (“Version_Bewerbung_2.0_202566_Bewerbungsnummer_0234521870_Datum_0000000200.exe“):
cb1d73323d3d80004ada185844b0d461abd9ded736d5dc690607f935b4f2b58a
Settings.txt :
b9fac5fd68f333b9459fa4b0111da8fba64a20022df8ea8595eae6a2fc4b9d9d
Im Rahmen unserer Untersuchungen fanden wir auf einer der Systeme unserer Kunden ein ZIP-Archiv das vermeintlich Bewerbungsunterlagen beinhalten sollte, stattdessen aber ein Installationsprogramm des SumatraPDF Viewers, eine Textdatei mit dem Namen “Settings.txt” und eine Dymanic-Linked-Library (DLL) namens “dbgcore.dll” enthielt. Bei dem Installationsprogramm handelt es sich um eine legitime PE, welche eine Signatur von Krzysztof Kowalczyk (dem Entwickler von SumatraPDF) enthält und deren Hash mit dem offiziellen Installer von SumatraPDF Version 3.3.3 übereinstimmt, weshalb unser Fokus vorerst auf die dbgcore.dll fiel.
dbgcore.dll wäre, insofern legitim, eine Windows-Systemdatei für Diagnosefunktionen und Speicherabbilder, welche direkt von Microsoft als Teil der Entwicklertools bereitgestellt wird. Sie hält sich in der Regel allerdings nicht in Dokumentenverzeichnissen auf. Unsere DLL war zudem mit zwei ungültigen Zertifikaten ausgestattet, welche im folgenden gezeigt werden:


Abbildung 1 & 2: Ungültige Zertifikate von „ESET, spol. s.r.o.“
Wenn man sich die Tabelle der importierten DLLs des Sumatra-Installers ansieht, fällt auf, dass dbgcore.dll gar nicht direkt importiert wird. Unsere Hauptaufgabe in diesem Schritt der Analyse ist also zu klären, wie ein Aufruf des Sumatra-Installationsprogramms (des „Bewerbungsschreibens“) zur Ausführung der potenziell schadhaften dbgcore.dll führt.

Abbildung 3: Importierte DLLs des Sumatra Installers
Wenn wir jedoch den Installer in einem Disassembler öffnen, sehen wir, wie der Installer versucht, eine DLL namens “dbghelp.dll” in den Prozess zu laden.

Abbildung 4: Importierung der legitimen dbghelp.dll
Auf dem ersten Blick scheint der Installer die DLL dbghelp.dll sauber zu laden: der absolute Pfad der DLL wird mithilfe von PathAppendW() aus dem Rückgabewert von GetSystemDirectoryW() und ”dbghelp.dll” zusammengebaut und erst dann wird die DLL mithilfe von LoadLibraryW() importiert.
Wenn wir uns jedoch anschauen, wozu der Handle der importierten DLL verwendet wird, sehen wir einen Aufruf zu GetProcAddress() mit MiniDumpWriteDump als zweiten Parameter:

Abbildung 5: Auflösung der Adresse zu MiniDumpWriteDump
Wenn man nun einen Blick in die Export-Tabelle der dbghelp.dll wirft, sieht man, dass die Funktion MiniDumpWriteDump zu „dbgcore.dll“ geforwarded wird:

Abbildung 6: MiniDumpWriteDump als forwarded function, welche in der dbgcore.dll implementiert ist
Um herauszufinden, wie der Einstiegspunkt der dbgcore.dll aufgerufen wird, haben den Sumatra Installer mit einer legitimen dbgcore.dll im selben Verzeichnis, in einem Debugger geöffnet. Dabei haben wir einen Breakpoint auf GetProcAddress()gesetzt und nach einer Weile single stepping stellten wir fest, dass LdrpCallInitRoutine() mit dem Einstiegspunkt der aufzurufenden DLL aufgerufen wird.

Abbildung 7: Callstack von GetProcAddress zu LdrpCallInitRoutine
Wie man hier im Screenshot erkennen kann, wird hier LdrpCallInitRoutine() mit der Addresse des Einstiegspunktes im RCX Register (1. Parameter) aufgerufen.

Abbildung 8: Aufruf zu LdrpCallInitRoutine mit dem Einstiegspunkt der dbgcore.dll im RCX register (Erster Parameter bei __fastcall)
Dies bekräftigt unsere Vermutung, dass sich der Schadcode im Einstiegspunkt der maliziösen dbgcore.dll befindet. Im Vergleich zu normalem DLL-Search-Order-Hijacking, wird in diesem das Laden, der maliziösen DLL von einer weiteren DLL übernommen, welche in diesem Fall die dbghelp.dll ist.
Exports
Wenn wir einen Blick in die Export-Tabelle unserer DLL werfen, erkennen wir, dass die vorliegende Datei dbgcore.dll insgesamt 38 Funktionen exportiert. Die echte dbgcore.dll Datei, welche von Microsoft herausgegeben wird, exportiert hingegen nur zwei Funktionen (MiniDumpReadDumpStream und MiniDumpWriteDump). Zudem sind aktuelle, von Microsoft bereitgestellte Versionen der DLL üblicherweise signiert, was hier nicht der Fall ist. Die folgenden exportierten Funktionsnamen in unserem dbgcore.dll Sample stechen besonders hervor:
ladeComm
antifa
kommEncoding
helloFriendssscommIsCom
stalin
SW3_HashSyscall
SC_Address
GetStalinNumber
GetStalin
AAAWriteaaaaaVirtualComm
ResumeComm
ProtectComm
Wir erkennen, dass die zwei originalen dbgcore.dll-Funktionen MiniDumpWriteDump und MiniDumpReadDumpStream nicht in dieser Liste vorzufinden sind. Stattdessen gibt es Verweise auf “stalin”, “getStalinNumber”, “SW3_HashSyscall”, welche eher unübliche Verweise für eine DLL sind. Somit kommen wir zu dem Schluss, dass es sich um eine schadhafte DLL ohne Bezug zur der legitimen dbgcore.dll von Microsoft handelt.
Deep Dive
Wenn wir die dbgcore.dll in einem Disassembler öffnen, und zur Hauptfunktion (DllMain) springen, sehen wir folgendes:

Abbildung 9: DllMain
Der Schadcode in der mw_Entrypoint() Funktion wird also nur ausgeführt, wenn die DLL mithilfe von LoadLibrary() oder einer ähnlichen API geladen wird und somit fdwReason auf DLL_PROCESS_ATTACH gesetzt wird.
In der mw_Entrypoint() Funktion, können wir einen groben Überblick über die Schadsoftware bekommen.

Abbildung 10: Einstiegspunkt der Dll (Schadcode)
Hier erkennt man drei Funktionsaufrufe welche überprüfen, ob das Programm innerhalb einer Sandbox oder Analyseumgebung ausgeführt wird, gefolgt von zwei weiteren Funktionsaufrufen, welche darüber entscheiden, ob der Schadcode ausgeführt wird oder nicht.
Anti-Sandbox Mechanismen
Die erste Funktion, mw_ramCheck(), fragt die Größe des Arbeitsspeichers ab. Nur wenn mehr als ~4.19 GB auf dem System installiert ist wird die Ausführung an den Aufrufer zurückgegeben. Falls dies nicht der Fall ist wird tooLittleRam() aufgerufen, welches das Programm stoppt. Ein mögliches Szenario, welches zum Abbruch führen würde, wäre zum Bespiel die Ausführung in einer Sandbox oder virtuellen Maschine, welche weniger als 4GB RAM hat.

Abbildung 11: Sandbox-Check via Abfrage des physischen Arbeitsspeichers
Die nächste Funktion mw_detectResolution() überprüft, ob die Position des rechten, unteren Pixels des Desktopfensters größer als 1023 ist. Falls dies nicht der Fall sein sollte, nimmt das Programm an, dass es unter einer kontrollierten Umgebung, welche oftmals Auflösungen unter 1280×1024 Pixeln verwenden, ausgeführt wird und stoppt die weitere Ausführung. Andernfalls wird die Ausführung an den Aufrufer zurückgegeben.

Abbildung 12: Sandbox-Check via Abfrage der Bildschirmauflösung des Desktops
Der dritte Sandbox-Check mw_cpuCount() bricht das Programm ab, falls die Anzahl der Prozessorkerne des Systems weniger als 2 ist.

Abbildung 13: Sandbox Check via Abfrage der Prozessorkerne
Der vierte Sandbox-Check mw_timeDetect() überprüft, ob die Sleep API gehooked wird. Sandboxen, Analyse-Tools oder Endpoint Detection and Response Lösungen bedienen zum Teil diesem Trick, um längere Wartezeiten eines schadhaften Programms zu verkürzen. Es wird zuerst GetTickCount aufgerufen, gefolgt von einem Aufruf von Sleep() mit einer Sekunde. Danach wird GetTickCount() ein weiteres mal aufgerufen und die Differenz zwischen dem zweiten Tickcount mit dem initialen Tickcount gegen 0.9 Sekunden verglichen. Falls das Ergebnis niedriger ist als 0.9 Sekunden, wird die Sleep-Funktion gehooked und der Wert 1 zurückgegeben, wodurch das Programm dann abbricht.

Abbildung 14: Timing check ob Sleep gehooked wird
Der letzte Sandbox-Check, mw_hostnameCheck(), ist trivialer und vergleicht den Namen des Hosts gegen die Namen von populären Sandboxen. Nur wenn dabei kein Treffer erzielt wird, wird 0 zurückgegeben und die Ausführung des tatsächlichen Schadcodes beginnt, vorausgesetzt, nicht einer der vorherigen Checks hat angeschlagen.

Abbildung 15: Sandbox Check via Abfrage des Hostnames
Nur wenn alle fünf Sandbox Checks überstanden wurden, wird der restliche Code ausgeführt. Zuerst wird die globale Variable CmdLine mit der Zeichenkette “WmiPrvSE.exe”, d.h. der Executable des Windows Management Instrumentation (WMI) Provider Services, gefüllt. Danach wird die Funktion mw_read_settings() aufgerufen.

Abbildung 16: CommieLoaders’ Kernfunktionalitäten
mw_read_settings() setzt das aktuelle Verzeichnis auf das Verzeichnis, in dem sich der Installer befindet und liest den Inhalt der „Settings.txt“ Datei in die globale Variable my_payload.

Abbildung 17: Funktion, welche den Inhalt der Settings.txt in den my_payload buffer liest
Wenn wir die Datei „Settings.txt“ öffnen, erkennen wir unter anderem verschiedene Namen von Kommunisten, vielfältige MAC-Adressen und Ausschnitte aus dem komministischem Manifest (viele davon enthalten Schreibfehler). Demnach der Name “CommieLoader”. Bei genauerer Betrachtung scheint sich ein Muster zu ergeben, nach dem die Häufung der „trotzki“ Strings jeweils für ein Null-Byte (0x00) stehen könnte. Daher stellen wir die These auf, dass Settings.txt einen enkodierten Payload, ggf. die nächste Ausführungsstufe der Schadsoftware enthält. Das Enkodierungsverfahren wäre demnach eine Wörterbuch-Ersetzung, bei welcher für jeden Hexadezimalwert 0x00 bis 0xFF ein entsprechendes Wort als Übersetzung verwendet wird.

Abbildung 18: Ausschnitt des Inhalts der Settings.txt
Bei genauerer Betrachtung der Datei dbgcore.dll fällt auf, dass die Datei eine passende Datenstruktur mit 256 Einträgen enthält, welche sich als Wörterbuch eignet und wie vermutet auch mit „trotzki“ als Wert für 0x00 beginnt.

Abbildung 18: Ausschnitt des Wörterbuchs aus dbgcore.dll
Um das Wörtbuch aus dbgcore.dll zu exportieren, haben wir ein Python Skript entwickelt, welches die Datei Settings.txt dekodieren kann.
„`
#!/usr/bin/env python3
„““
Decoder for commieLoader Settings.txt payload.
dbgcore.dll contains a 256-entry wordlist stored as fixed-width (5000-byte) slots
starting at offset 0x8B40. Each word in Settings.txt maps to one byte of the
original binary payload.
„““
import sys
import argparse
DLL_PATH = „dbgcore.dll“
SETTINGS_PATH = „Settings.txt“
OUTPUT_PATH = „decoded_payload.bin“
WORDLIST_OFFSET = 0x8B40 # offset of first entry („trotzki“ = 0x00) in dbgcore.dll
WORDLIST_STRIDE = 5000 # each entry occupies a fixed 5000-byte slot
def load_wordlist(dll_path: str) -> dict[str, int]:
with open(dll_path, „rb“) as f:
data = f.read()
word_to_byte: dict[str, int] = {}
for i in range(256):
offset = WORDLIST_OFFSET + i * WORDLIST_STRIDE
chunk = data[offset:offset + WORDLIST_STRIDE]
end = chunk.find(b“\x00″)
word_bytes = chunk[:end] if end != -1 else chunk
word = word_bytes.decode(„utf-8“)
word_to_byte[word] = i
return word_to_byte
def decode(settings_path: str, word_to_byte: dict[str, int]) -> bytearray:
with open(settings_path, „r“, encoding=“utf-8″) as f:
content = f.read()
# Tokens are separated by „, “ strip only leading space to preserve
# trailing spaces that are part of some token names (e.g. „Ricardo „).
tokens = [t.lstrip(“ „) for t in content.split(„,“)]
unknown = {t for t in tokens if t and t not in word_to_byte}
if unknown:
print(f“[!] Warning: {len(unknown)} unknown token(s): {unknown}“, file=sys.stderr)
out = bytearray()
for t in tokens:
if t:
out.append(word_to_byte.get(t, 0))
return out
def main() -> None:
parser = argparse.ArgumentParser(description=“Decode commieLoader Settings.txt payload“)
parser.add_argument(„–dll“, default=DLL_PATH, help=f“Path to dbgcore.dll (default: {DLL_PATH})“)
parser.add_argument(„–input“, default=SETTINGS_PATH, help=f“Path to Settings.txt (default: {SETTINGS_PATH})“)
parser.add_argument(„–output“, default=OUTPUT_PATH, help=f“Output path for decoded binary (default: {OUTPUT_PATH})“)
args = parser.parse_args()
print(f“[*] Loading wordlist from {args.dll} …“)
word_to_byte = load_wordlist(args.dll)
print(f“[+] Loaded {len(word_to_byte)} wordlist entries“)
print(f“[*] Decoding {args.input} …“)
payload = decode(args.input, word_to_byte)
print(f“[+] Decoded {len(payload)} bytes“)
with open(args.output, „wb“) as f:
f.write(payload)
print(f“[+] Written to {args.output}“)
if __name__ == „__main__“:
main()
„`
Die dekodierte Datei konnten wir durch YARA Regel-Treffer und manuelle Analyse als CobaltStrike Beacon Shellcode identifizieren. CobaltStrike ist ein für Red-Teaming konzipiertes Adversary Emulation Framework, welches sowohl für legitime Sicherheitstests, als auch für Command&Control Zwecke von Angreifern mit maliziösen Motiven eingesetzt wird. Um eine Einordnung zu treffen und näheres über die Funktionalität des CobaltStrike Beacons herauszufinden, haben wir die Konfiguration dessen extrahiert.
Der Cobalt Strike Payload enthält die folgende Konfiguration, welche die Funktionalität und das Verhalten bzw. die Tarnung der Schadsoftware festlegt. Kommuniziert wird über das HTTPS Protokoll auf Port 443/tcp. Der Teamserver (die Command&Control Infrastruktur des Angreifers) wird unter der Domain refugee-help[.]com erreicht und ist als Kontaktformular getarnt, damit der Web-Traffic in einer Analyse nicht allzu sehr heraussticht. Der Beacon tarnt sich als das Windows Systemprogramm wmiprvse.exe, um im Prozessbaum nicht aufzufallen. Die letzte, für uns besonders relevante Information, ist der Watermark-Wert „987654321“, welcher normalerweise pseudonym den Lizenznehmer der Software identifiziert. Die absteigende Zahlenfolge ist jedoch an Anzeichen dafür, dass es sich um eine unlizensierte Kopie von CobaltStrike handeln muss, welche gerne unter Cyberkriminellen in Online-Foren zum Tausch oder Verkauf angeboten werden.
BeaconType – HTTPS
Port – 443
SleepTime – 30000
MaxGetSize – 16798776
Jitter – 50
MaxDNS – Not Found
PublicKey_MD5 – 1089d58afc804cfab88e6e2aca60e3f3
C2Server – refugee-help.com,/dpixel
UserAgent – Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.3600 (KHTML, like Gecko) Chrome/135.50.90.0 Safari/537.3600
HttpPostUri – /contact.php
Malleable_C2_Instructions – Base64 decode
HttpGet_Metadata – Metadata
base64
header „Cookie“
HttpPost_Metadata – ConstHeaders
Content-Type: application/x-www-form-urlencoded
ConstParams
name=OSF
subject=Resource support
SessionId
header „Cookie“
Output
base64url
prepend „message=“
PipeName – Not Found
DNS_Idle – Not Found
DNS_Sleep – Not Found
SSH_Host – Not Found
SSH_Port – Not Found
SSH_Username – Not Found
SSH_Password_Plaintext – Not Found
SSH_Password_Pubkey – Not Found
SSH_Banner –
HttpGet_Verb – GET
HttpPost_Verb – POST
HttpPostChunk – 0
Spawnto_x86 – %windir%\syswow64\wbem\wmiprvse.exe -Embedding
Spawnto_x64 – %windir%\sysnative\wbem\wmiprvse.exe -Embedding
CryptoScheme – 0
Proxy_Config – Not Found
Proxy_User – Not Found
Proxy_Password – Not Found
Proxy_Behavior – Use IE settings
Watermark_Hash – NtZOV6JzDr9QkEnX6bobPg==
Watermark – 987654321
bStageCleanup – True
bCFGCaution – True
KillDate – 0
bProcInject_StartRWX – False
bProcInject_UseRWX – False
bProcInject_MinAllocSize – 24576
ProcInject_PrependAppend_x86 – b’D@KCLH\x90f\x90\x0f\x1f\x00f\x0f\x1f\x04\x00\x0f\x1f\x04\x00\x0f\x1f\x00\x0f\x1f\x00′
Empty
ProcInject_PrependAppend_x64 – b’D@KCLH\x90f\x90\x0f\x1f\x00f\x0f\x1f\x04\x00\x0f\x1f\x04\x00\x0f\x1f\x00\x0f\x1f\x00′
Empty
ProcInject_Execute – kernel32.dll:BaseThreadInitThunk
NtQueueApcThread-s
kernel32.dll:LoadLibraryA
CreateRemoteThread
RtlCreateUserThread
SetThreadContext
ProcInject_AllocationMethod – NtMapViewOfSection
bUsesCookies – True
HostHeader –
headersToRemove – Not Found
DNS_Beaconing – Not Found
DNS_get_TypeA – Not Found
DNS_get_TypeAAAA – Not Found
DNS_get_TypeTXT – Not Found
DNS_put_metadata – Not Found
DNS_put_output – Not Found
DNS_resolver – Not Found
DNS_strategy – round-robin
DNS_strategy_rotate_seconds – -1
DNS_strategy_fail_x – -1
DNS_strategy_fail_seconds – -1
Retry_Max_Attempts – 0
Retry_Increase_Attempts – 0
Retry_Duration – 0
Sobald der Shellcode dekodiert ist, wird ein neuer Prozess erstellt. Wie oben erwähnt, wurde zuvor die Zeichenkette “WmiPrvSE.exe” in die globale Variable CmdLine kopiert. Und mit dem Aufruf zu CreateProcessA() wird ein Prozess davon im suspendierten Zustand erstellt.

Abbildung 19: Erstellung des suspendierten WmiPrvSE Prozesses
Sobald der Prozess erstellt ist, erkennen wir mehrere Syscall-Aufrufe, die auf klassische Process-Injection hindeuten. Der Aufruf ZwAllocateVirtualMemory() allokiert einen Buffer im neuerstellten Prozess, welche als Speicher für den Shellcode dient. Dieser wird mittels ZwWriteVirtualMemory() in den Addressspeicher des Prozesses geschrieben, welcher mit ZwProtectVirtualMemory() ausführbar gemacht wird.
Danach wird mithilfe von ZwQueueApcThread() der Shellcode an die APC Queue des Prozesses angehangen und mittels ZwResumeThread() wird der Shellcode schließlich auf dem Hauptthread ausgeführt.

Abbildung 20: Übertragung des Shellcodes in den Speicherbereich des WmiPrvSE Prozesses, gefolgt von der der Ausführung des Shellcodes
Nachdem der Shellcode in den Prozess geschrieben und ausgeführt wurde, beginnt das Programm Persistenz-Mechanismen durchzuführen. Diese finden sich in der Funktion copyfiles().
Es wird zuerst der Nutzername des aktuellen Nutzers abgefragt, um dessen Dokumenten-Verzeichnis zu finden. Nachdem die Zeichenkette des Pfads zum Dokumenten-Verzeichnis zusammengebaut wurde, werden alle drei Dateien „Settings.txt“, dbgcore.dll und der Sumatra Installer in das Verzeichnis kopiert.

Abbildung 21: Kopierung des Sumatra-Installers, dbgcore.dll und der Settings.txt in den Documents Ordner des Nutzers
Zuletzt wird die write_auto-Funktion aufgerufen, welche einen Autorun Registry Key getarnt als „Firefox_Updater_Version_2.3.1000“ für den Installer erstellt. Dieser führt dazu, dass der Installer bei jedem Systemstart ausgeführt wird, sodass der Angreifer den Zugang auf das System nicht nach einem Neustart verliert.

Abbildung 22: Eintragung des Autorun-Keys im Registry

Abbildung 23: Registry Eintrag nach Ausführung der Schadsoftware
Kleiner Bonus: Wir konnten Artefakte eines Vectored-Exception-Handlers in der DLL finden, welche einen Hook auf die EtwEventWrite-Funktion setzen. Jedoch konnten wir keine Anzeichen dazu finden, dass dieser Handler registriert wird.

Abbildung 24: Ein Vectored-Exception-Handler, welches EtwEventWrite mit einer ret Instruktion überschreibt (Jedoch wird er nie registriert)
Noteworthy
Zu bemerken ist vielleicht noch, dass unser Sample nur bedingt Anti-AV Maßnahmen ergriffen hat. Auf dem System unseres Kunden lief Microsoft Defender, der, soweit wir sehen konnten, während des gesamten Infektionszeitraumes aktiv war und das Sample mehrfach scannte. Zu bemängel hatte er am Ende nichts, auch wenn er an der dbgcore.dll durchschnittlich am längsten scannte.
In zwei Fällen identifizierte er jedoch maliziöse Aktivitäten („VirTool:MSIL/Deimos.A!MTB“ und „Trojan:Win32/Sabsik.EN.B!ml“) im Zusammenhang mit WmiPrvSE.exe:

Abbildung 25: Detektionen des Windows Defenders
In beiden Fällen wurde die WmiPrvSE.exe vom Windows Defender in die Quarantäne gesteckt.
Wir konnten den „CommieLoader“ keiner bereits bekannten Malware-Familie zuordnen. Bei der Suche danach in Plattformen zur Analyse und zum Austausch von Malware-Samplen konnten wir durch eine YARA-Regel ein weiteres Sample (SHA256: 127c525b0107045c39d4c956d51a16aba6b28e8a08cb1687e3fe7fc1f16e0de5)finden, das sich ebenfalls in einem ZIP-Archiv („bewerbung_gesamt.zip“) mit einer Settings.txt und dem SumatraPDF Installers befand. Der Payload dieses Samples ist nahezu identisch mit unserem Sample bis darauf, dass statt ein WmiPrvSE.exe ein msedge.exe-Prozess für die APC-Injection genutzt wird. Dies deutet darauf hin, dass es sich bei diesem Sample um ein Testsample handeln könnte, um die Detektion durch AVs und EDRs zu testen. Nach Angaben des vermeintlichen Angreifers hätte wohl auch der Elastic EDR sein Sample detektiert. Ob es sich bei unseren Angriff um einen gezielten Angriff gegen unseren Kunden handelt, oder das Sample in Zukunft noch öfter auftauchen wird, wird die Zukunft sagen.
Anhang
Host-based Indicators
| Filename | SHA256 | Description |
| dbgcore.dll | a9121e70c39de2c10e6790da4aa3a22079242a201da2c1aeeb4ed65070e68e93 | Malicious dll loaded by the SumatraPDF installer via Dll ForwardSideloading |
| Version_Bewerbung_2.0_202566_Bewerbungsnummer_0234521870_Datum_0000000200 | cb1d73323d3d80004ada185844b0d461abd9ded736d5dc690607f935b4f2b58a | Legitimate SumatraPDF installer |
| Settings.txt | b9fac5fd68f333b9459fa4b0111da8fba64a20022df8ea8595eae6a2fc4b9d9d | Text file containing an encoded Cobalt Strike beacon |
Zusätzliche Host-Based IoC’s:
Software\Microsoft\Windows\CurrentVersion\Run\Firefox_Updater_Version_2.3.1000:
„C:\Users\[Username]\Documents\Version_Bewerbung_2.0_202566_Bewerbungsnummer_0234521870_Datum_0000000200.exe
Network-based Indicators
| Type | Indicator |
| C2 | refugee-help[.]com |
| URIs | /dpixel, /contact.php |
Detection Rule
rule SI_MAL_LDR_CommieLoader_Apr13 {
meta:
version = „1.0“
date = „2026-04-13“
modified = „2026-04-14“
status = „RELEASED“
sharing = „TLP:CLEAR“
source = „SECUINFRA Falcon Team“
description = „Detects the dbgcore.dll used in the CommieLoader campaign“
category = „malware“
mitre_att = „T1129, T1055, T1112“
// SHA-256 hashes of our observed samples
hash1 = „a9121e70c39de2c10e6790da4aa3a22079242a201da2c1aeeb4ed65070e68e93“
hash2 = „127c525b0107045c39d4c956d51a16aba6b28e8a08cb1687e3fe7fc1f16e0de5“
strings:
$mz = { 4d 5a }
// Below are code snippets used in CommieLoaders Sandbox/VM check.
$a1 =
{
// Stub for retrieving the computer name.
48 81 ec 30 01 00 00 // sub rsp, 0x130
48 8d ac 24 80 00 00 00 // lea rbp, [rsp+0x80]
c7 45 ac 00 01 00 00 // mov dword [rbp-0x54], 0x100
48 8d 55 ac // lea rdx, [rbp-0x54]
48 8d 45 b0 // lea rax, [rbp-0x50]
48 89 c1 // mov rcx, rax
48 ?? ?? ?? ?? ?? ?? // mov rax, ?
ff d0 85 c0 // call rax
}
$a2 =
{
// Stub for comparing the computer name against common sandbox hostnames.
48 8d 45 b0 // lea rax, [rbp-0x50]
48 ?? ?? ?? ?? ?? ?? // lea rdx, ?
48 89 c1 // mov rcx, rax
e8 ?? ?? ?? ?? // call ?
85 c0 // test eax, eax
}
// SysWhispers3 function names that are observed in the samples.
$b1 = „SW3_GetSyscallAddress“ ascii
$b2 = „SW3_HashSyscall“ ascii
$b3 = „SW3_PopulateSyscallList“ ascii
// Strings related to the Autorun key, CommieLoader sets for purpose of persistence.
$c1 = „Software\\Microsoft\\Windows\\CurrentVersion\\Run“ ascii
$c2 = „Firefox_Updater_Version_2.3.1000“ ascii
condition:
$mz at 0 and
filesize < 3MB and
all of ($a*) and
all of ($b*) and
all of ($c*)
}

