Source
- Malware Bazaar: https://bazaar.abuse.ch/sample/ac3afdcdd6989262b365e5850c82bdd3e42c63714419acf891d8c4f8435f964c/
- File type: Powershell
- Size: ~3.5 MB
Analysis
Functionality and Obfuscation
- The Powershell script embeds the main payload launcher Powershell script as a here-string. The payload remains the same irrespective of whether the given Powershell process was 64-bit or 32-bit.
- If the given Powershell process is 64-bit, a payload launcher script is written to the current user’s
AppData\Local\Tempdirectory with a random integer (Get-Randomcmdlet) as filename with.ps1extension. Then, the 32-bit Powershell executable path is built; one of$env:WINDIR\SysWOW64\WindowsPowerShell\v1.0\powershell.exeor$env:WINDIR\System32\WindowsPowerShell\v1.0\powershell.exeand used to execute the launcher script in a hidden window. After the launcher exited, its file was deleted from disk. - If the given Powershell process is 32-bit, the payload launcher Powershell is piped into
Invoke-Expressioncmdlet and executed.
The payload launcher script had primarily two forms of obfuscation:
- Dead/junk code:
[void]([System.Text.Encoding]::UTF8.GetBytes("XaaJYkDrACzA"))
...
$YHlxhIabnbiAggZZ = @(4623,9444,6378,6182,3132,5090,2265,9832,2541,9313,8790,8274,8374,3964,1472,9474,4825,5789,2665,3346,9380,3162,5690,9550,2954)
foreach ($fkegcfDWcAcyhwZs in $YHlxhIabnbiAggZZ) { $null = [Math]::Sqrt($fkegcfDWcAcyhwZs) }
function PxDAgSfVrK {
$vHGBTQcQhWihkOpP = @(1,2,3,4,5)
foreach ($XmInOoVJszWTbpKf in $vHGBTQcQhWihkOpP) {
$result = $XmInOoVJszWTbpKf * 2
}
}
PxDAgSfVrK
...
foreach ($gIYjeRkcYgUZhHJd in $qrdtCMfWpbqJidck) { $null = $gIYjeRkcYgUZhHJd.ToLower() }
- Opaque predicate that evaluates to
true.
if (205 -eq 205) { $jHypmcWMPaQtBXp = "FrsnYjHYk" }
if (263 -eq 263) { $dkQpjcPAYBTmbLJ = "oiPmLfdYw" }
Payload Launcher Deobfuscation
Utilities: https://github.com/nikhilh-20/re_tools/tree/main/powershell
> .\PsUnwrap-TrueIf.ps1 -InputFile C:\Users\Ashura\Desktop\payload.ps1 -OutputFile C:\Users\Ashura\Desktop\payload_pass1.ps1 {"changed":4,"output_path":"C:\\Users\\Ashura\\Desktop\\payload_pass1.ps1","output_bytes":1826435,"input_bytes":1826519}
> .\PsRemove-DeadCode.ps1 -InputFile C:\Users\Ashura\Desktop\payload_pass1.ps1 -OutputFile C:\Users\Ashura\Desktop\payload_pass2.ps1 -aggressive
{"input_bytes":1826435,"output_path":"C:\\Users\\Ashura\\Desktop\\payload_pass2.ps1","by_reason":"4x no-op function, 1x pure statement, 20x dead store, 5x non-functional loop","changed":30,"output_bytes":1825024,"aggressive":true}
After deobfuscation, the resultant payload launcher script was ~1.75 MB.
Although the payload launcher script is the same for the initial 32-bit or 64-bit Powershell process, it was embedded as-is twice in the Powershell script. Whether this was an intentional effort to artificially increase the Powershell script size is not known, but it can serve as an evasionary measure.
Payload
The resulting deobfuscated launcher script embeds the main payload in base64 + xor-encrypted form. After decryption, the main payload pointed to a .NET executable which was invoked through reflection by the launcher.
[System.Reflection.Assembly]::Load($payload)
$entry = $assembly.EntryPoint
$entry.Invoke($null, @($null))