LummaC2 Stealer Leverages Customized Control Flow Indirection For Execution


The LummaC2 obfuscator employs a novel control flow protection scheme designed specifically for its stealer component, which is part of a broader set of transformations, making it difficult for analysts to reverse engineer the binary. 

It introduces obfuscated code that is mixed with the original compiler-generated code, requiring a specialized deobfuscator for analysis.

The obfuscator’s authors appear to have a deep understanding of the LummaC2 stealer, as certain protections are tailored to specific components of the malware.

– Advertisement –
EHA
Dispatcher blocks overview

Dispatcher blocks a type of obfuscation technique used by malware, which breaks a function’s original control flow by inserting instructions that calculate jump destinations dynamically.

Free Webinar on How to Protect Small Businesses Against Advanced Cyberthreats -> Free Registration

The analysis identifies three main dispatcher block layouts: register-based (most common), memory-based, and mixed-order, where register-based layouts use registers for calculations and end with a jump to a register value. 

Memory-based layouts utilize both registers and stack values, and mixed-order layouts combine elements of both and can intersperse dispatcher instructions with original instructions, making deobfuscation harder. 

Register-based instruction dispatcher

The obfuscator uses conditional dispatchers to protect sensitive code logic, which are categorized into standard, loop, and syscall types, where standard dispatchers handle general conditional jumps, while loop dispatchers control loop execution. 

Syscall dispatchers evaluate NTSTATUS codes to determine Syscall success, and the obfuscator creates a table of branch targets indexed by the condition’s result. 

By evaluating the condition code and indexing the table, the obfuscator executes the appropriate branch, which effectively hides sensitive logic from analysis.

 A update-block loop

A method for deobfuscating a function’s control flow, as symbolic execution with Triton is used to distinguish between the original instructions and those injected by the obfuscator (dispatcher instructions). 

Backward slicing is performed on the destination register of an indirect jump to identify instructions influencing the final jump target. 

By analyzing the symbolic expressions generated during processing, dispatcher instructions responsible for the manipulation are isolated and the original function flow is pinpointed, which is effective regardless of dispatcher instruction placement.

ASTs of the destination register after the indirect jump instruction is processed

The deobfuscation process begins by recovering the original instructions and control flow using a depth-first search algorithm.

Conditional jumps are handled by assuming the condition is met and exploring the corresponding path, while alternative paths are stored for later exploration. 

The deobfuscated function is then rebuilt by overwriting the original instructions and replacing indirect jumps with direct ones or conditional jump pairs.

Finally, the offsets of memory-referencing instructions are adjusted to reflect their new locations, which effectively removes obfuscation and restores the original function’s semantics.

 Decompiler view of the subroutine at address 0x41EE50 after deobfuscation

Mandiant researchers developed a deobfuscation tool for LummaC2 by employing backward slicing and symbolic execution, which identify the original instructions obscured by the obfuscator’s indirect jumps, successfully remove dispatcher blocks, and reveal the program’s true control flow. 

Deobfuscated functions can then be recovered and decompiled using IDA Pro, enabling analysts to understand LummaC2’s functionalities, which highlights the effectiveness of backward slicing for binary analysis beyond the LummaC2 case study.

Analyse Any Suspicious Links Using ANY.RUN’s New Safe Browsing Tool: Try It for Free



Source link