Unveiling the intricacies of DiceLoader

This analysis dissects DiceLoader (aka Icebot), a small FIN7-associated downloader that is injected via Reflective DLL injection, uses a multi-threaded IoCompletionPort + linked-list architecture, and executes deobfuscated shellcode delivered over a bespoke raw-TCP protocol. Key technical elements include two XOR-based obfuscation layers for configuration and network traffic, an FNV-1 host fingerprint sent at connection startup, and a command packet format with action IDs controlling linked-list insertion and execution. #DiceLoader #FIN7 #Carbanak

Keypoints

  • DiceLoader is delivered by a PowerShell stage and implemented as a DLL using Reflective DLL injection to load itself into a host process.
  • On startup it initializes four critical sections, an IoCompletionPort for inter-thread queuing, and four linked lists (L0–L3) used to store messages, fingerprints, payload wrappers and related data.
  • Two XOR-based obfuscation schemes are used: a fixed-key XOR (key length 31) for stored C2 config and a chained XOR (byte XOR key + previous plaintext byte) for network payloads; the latter can use both embedded and runtime keys.
  • DiceLoader builds a host fingerprint (MAC + username + computer name), hashes it with FNV-1 (concatenated with PID), and sends the obfuscated fingerprint early in the TCP handshake.
  • The custom raw-TCP protocol begins with random bytes and a runtime XOR key, followed by obfuscated fingerprint, local IP, and an FNV-1 of the IP; subsequent server packets follow a fixed sequence (key length, packet length, payload, FNV-1).
  • Execution of payloads is performed like shellcode execution: VirtualAlloc(MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE), copy, deobfuscate, then call via an inline function pointer; consumer threads are awakened via PostQueuedCompletionStatus on the IoCompletionPort.
  • Sekoia tracked a persistent DiceLoader C2 infrastructure (dozens of servers); the loader remains actively used and is observed alongside other FIN7 tools such as Carbanak.

MITRE Techniques

  • [T1620] Reflective Code Loading – Loader uses Reflective DLL injection to load from memory: ‘Reflective DLL injection is a library injection technique in which the concept of reflective programming is employed to perform the loading of a library from memory into a host process.’
  • [T1105] Ingress Tool Transfer – DiceLoader is delivered by a PowerShell dropper alongside other tooling: ‘DiceLoader is dropped by a PowerShell script along with other malware of the intrusion set’s arsenal such as Carbanak RAT.’
  • [T1027] Obfuscated Files or Information – Configuration and network traffic are obfuscated with XOR-based schemes: ‘DiceLoader has two obfuscation methods’.
  • [T1027.007] Obfuscated Files or Information: Dynamic API Resolution – Use of inline function pointers and indirect calls to execute payloads implies runtime resolution/execution: ‘Inline function pointer declaration and execution.’
  • [T1140] Deobfuscate/Decode Files or Information – The sample performs explicit deobfuscation routines (un-XOR config and payloads): ‘The function used to un-XOR the configuration is straightforward…’
  • [T1132.002] Non-Standard Encoding – Network payloads use a custom chained-XOR encoding (key + previous byte): ‘each byte (Cx) is XORed with a byte of the key (Kx) … and is XORed with the previous byte result of the deobfuscation (Px-1).’
  • [T1571] Non-Standard Port – DiceLoader communicates over raw TCP with configurable ports per C2: ‘the loader uses a raw TCP connection to communicate with its Command and Control, where the port is configurable for each C2 of each sample.’
  • [T1082] System Information Discovery – The loader collects local system identifiers (MAC, username, computer name, local IP) to build a fingerprint: ‘it hashes the concatenation of the MAC address, the username and the computer name.’
  • [T1057] Process Discovery – The fingerprint includes the current process identifier and other process-related metadata used in reporting: ‘This hash is concatenated with the current process identifier and it is then re-hashed.’

Indicators of Compromise

  • [File name] Dropped artifacts – stage-0 PowerShell script (drops DiceLoader DLL and Carbanak RAT), DiceLoader DLL (exported ordinal #1 entry used for Reflective DLL injection).
  • [Repository/Tool] Reflective loader reference – https://github.com/stephenfewer/ReflectiveDLLInjection (used conceptually by the sample).
  • [URL/Source] Analysis/report URL – https://blog.sekoia.io/unveiling-the-intricacies-of-diceloader/ (original analysis and C2 tracking report).
  • [Infrastructure] C2 servers – Sekoia tracked ~20–50 active DiceLoader C2 servers over time (no specific hostnames disclosed in the report).

DiceLoader operates as a small downloader DLL loaded via reflective injection; its exported entry is invoked to initialize threading primitives (four critical sections), create an IoCompletionPort for inter-thread queuing, and allocate four linked lists (L0–L3) used to hold formatted C2 messages, fingerprints, shellcode wrappers, and payload data. The main thread receives raw TCP packets, unpacks them following a fixed sequence (runtime XOR key length, 4-byte payload length, obfuscated payload, 4-byte FNV-1 checksum), deobfuscates payloads first with the embedded XOR key and second with a runtime key supplied by the C2, then either inserts payload structures into L0/L3 or posts them to the IoCompletionPort for consumer threads.

Two XOR obfuscation routines are used: a simple XOR with a fixed 31-byte key stored in .data for C2 configuration, and a chained XOR used for network traffic where each plaintext byte is derived from the previous result, the ciphertext byte, and the key byte (IV = 0). The loader fingerprints hosts by hashing MAC+username+computer name with FNV-1, concatenating the PID and re-hashing; this obfuscated fingerprint and local IP (plus an FNV-1 of the IP) are included in the initial TCP handshake to the C2.

Payload execution is effectively shellcode execution: the consumer thread path uses PostQueuedCompletionStatus to wake a consumer, which then allocates executable memory (VirtualAlloc with MEM_RESERVE|MEM_COMMIT and PAGE_EXECUTE_READWRITE), copies and deobfuscates the shellcode, and invokes it via an inline function pointer. Execution depends on specific memory structures and action IDs (e.g., insert into L0, set stop flag, push to IoCompletionPort, increment queue pointer), which makes remote triggering non-trivial without correctly formatted structures and sequence of C2 commands.

Read more: https://blog.sekoia.io/unveiling-the-intricacies-of-diceloader/