Party in Ibiza with PowerShell
Today, I would like to talk about PowerShell ISE or "Integration Scripting Environment"[1]. This tool is installed by default on all Windows computers (besides the classic PowerShell interpreter). From a malware analysis point of view, ISE offers a key feature: an interactive debugger! It provides all the classic features that you can expect from a debugger: breakpoints, step in, step over, step out, ... all of these features are available while you keep control of the environment to interact with the script through the help of other PowerShell commands. When you're facing a strongly obfuscated scripts, you could speed up the analysis with the help of carefully placed breakpoints. Let's have a look at a practical example.
The malicious script that I'd like to use contains a lot of references to "Ibiza" (hence the title of this diary). The script has a VT score ot 9/60 (SHA256:ead30df7867c2bcb99de71c1686e82d49c6fcc3ba00092a9fc8d878b78c62302).
/!\ Warning: Do NOT debug malicious scripts on sensitive or corporate computers, setup a lab to avoid mistakes and execute the script without breakpoint! /!\
Let's load the file into PowerShell ISE: (note: the file must have the extension .ps1 to be properly saved and debugged)
You can see that the script has some chunks of Base64 data (some of them based on format strings). This is confirmed via base64dump:
$ docker run -it --rm -v $(pwd):/malware rootshell/dssuite base64dump.py \ ead30df7867c2bcb99de71c1686e82d49c6fcc3ba00092a9fc8d878b78c62302.ps1 -n 100 ID Size Encoded Decoded MD5 decoded -- ---- ------- ------- ----------- 1: 172 bU3lzdGVtLk11bHR mM?????5????? a3373aca7480f0fd3063e6f3bd3d3bce 2: 172 Ww6R2V0LURlbGVnY [.??].Q.[.Y?].U. b9b01945b37903a46b09c46dd27b3d19 3: 204 kludm9rZSgkaFByb ?[????J....???\? 1ee694694f746acda3ebcd9cadf650cc 4: 136 dG8gdGhlIHJ1bm5p to the running P 1a41aab7dc9e6680fee5de37d0c31243 5: 156 0sIFtVaW50MzJdLC ??.?V??C3%??.?T? edc0526f5004950bfecf715f71f5217c 6: 70504 76492d1116743f04 ?=??u????8?~5? a2c38d7f5e380d0111f1b55d90986fa0
You see that the first Base64 payload is based on a concatenation of strings. Let's decode this from PowerShell ISE.
First, define a breakpoint via the menu "Debug / Toggle a breakpoint" or press F9. Where? By reading the script, you see that a good candidate is line 13 because, at line 12, we see a reference to Base64String. Once the breakpoint set, the line color is switched to red:
Now, launch the script via the menu 'Debug / Run / Continue" or press F5. Once the debugger reached the breakpoint, it displays a message on the console and the line becomes yellow. We can interact with the script and use more PowerCommand to, by example, display the content of variable or, better, dump it into a file for further analysis:
We now see the decoded Base64 data. It's a new set of PowerShell instructions! Let's dump them into a file:
With the help of WriteAllBytes(), we dump the contain of $PARtYINVITEpREtTY into a file 'payload.ps1'.
Let's have a look now at line 18. It refers to an object 'manaGEMeNT.AUtomatiON.pScreDENtial' which is used to store encrypted data (I wrote a diary about this technique[2]). Let's decode this! Stop the debugger, remove all breakpoints. At the end of line 18, you see that the extracted code is executed with an 'IEX' command ("Invoke-Expression"). Replace 'iex' with 'echo', put a breakpoint at line 20 (we can't set a breakpoint on a blank line), and launch the debugger again:
Once again, we see a new bunch of PowerShell instructions (that are normally executed). Copy this code and paste it into a new tab. To be able to debug it, save it as 'payload2.ps1'. Tthe code is executed by IEX (obfuscated and marked in the red rectangle):
The code is nicely obfuscated but we won't take too much time on this. Just execute the code without any breakpoint and have a look at the new variables. We have two interesting ones: '$Shellcode32' and '$Shellcode64'. We use the same technique to dump the shellcode into a file:
And we have a shellcode! The next step will be to have a look at this shellcode!
The first chunk of Base64 data that we decoded contains a framework used to perform injection of code into another process:
function Create-Party-Invite { <# .SYNOPSIS PARTY PARTY PARTY .DESCRIPTION Everybody can look it up, now lets just PAAAARTYYYY! .PARAMETER ProcessID Process ID of the process you want to party shellcode into. .PARAMETER Shellcode Specifies an optional Shellcode passed in as a byte array .PARAMETER Force Partys Shellcode without prompting for confirmation. .EXAMPLE C:\PS> Create-Party-Invite -Shellcode @(0x00,0x00,0x00) #> [CmdletBinding( DefaultParameterSetName = 'RunLocal', SupportsShouldProcess = $True , ConfirmImpact = 'High')] Param ( [ValidateNotNullOrEmpty()] [UInt16] $ProcessID, [Parameter( ParameterSetName = 'RunLocal' )] [ValidateNotNullOrEmpty()] [Byte[]] $Shellcode, [Switch] $Force = $False ) ...
This code is just a fork of some PowerSpoit code[3]. Note also that the injected process is a 'colorcpl.exe' launched by the script.
Conclusion: PowerShell ISE is a great tool to investigate malicious scripts! It could save you a lot of time.
[1] https://docs.microsoft.com/en-us/powershell/scripting/windows-powershell/ise/introducing-the-windows-powershell-ise?view=powershell-7
[2] https://isc.sans.edu/forums/diary/Powershell+Payload+Stored+in+a+PSCredential+Object/26058
[3] https://github.com/PowerShellMafia/PowerSploit/blob/master/CodeExecution/Invoke-Shellcode.ps1
Xavier Mertens (@xme)
Senior ISC Handler - Freelance Cyber Security Consultant
PGP Key
Reverse-Engineering Malware: Malware Analysis Tools and Techniques | Amsterdam | Jan 20th - Jan 25th 2025 |
Comments