Writeup: FlareOn 2020: 004 - report
1. TLDR
2. Dane wejściowe
Plik z zadaniem znajduje się tutaj. Hasło: flare.
Przedmiot zadania stanowi arkusz kalkulacyjny report.xls
. Z treści zadania wiadomo, że znajduje się w nim makro, w którym ukryto flagę.
3. Inspekcja pliku report.xls
Zweryfikowałem plik narzędziem file
:
$ file report.xls
report.xls: Composite Document File V2 Document, Little Endian, Os: Windows, Version 10.0, Code page: 1252, 0x17: 1048576CDFV2 Microsoft Excel
Poniżej przedstawiłem arkusz po otwarciu w LibreOffice Calc:
Potwierdziłem istnienie makra, wykorzystując do tego celu narzędzie oleid
:
$ oleid report.xls
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: report.xls
Indicator Value
OLE format True
Has SummaryInformation stream False
Application name unknown
Encrypted False
Word Document False
VBA Macros True
Excel Workbook True
PowerPoint Presentation False
Visio Drawing False
ObjectPool False
Flash objects 0
3. Inspekcja makra
W arkuszu faktycznie było wykorzystywane makro. W celu wykonania wstępnej analizy, uruchomiłem narzędzie olevba
:
$ olevba --analysis report.xls
olevba 0.55.1 on Python 2.7.17 - http://decalage.info/python/oletools
===============================================================================
FILE: report.xls
Type: OLE
-------------------------------------------------------------------------------
VBA MACRO ThisWorkbook.cls
in file: report.xls - OLE stream: u'_VBA_PROJECT_CUR/VBA/ThisWorkbook'
-------------------------------------------------------------------------------
VBA MACRO Sheet1.cls
in file: report.xls - OLE stream: u'_VBA_PROJECT_CUR/VBA/Sheet1'
-------------------------------------------------------------------------------
VBA MACRO F.frm
in file: report.xls - OLE stream: u'_VBA_PROJECT_CUR/VBA/F'
-------------------------------------------------------------------------------
VBA MACRO VBA_P-code.txt
in file: VBA P-code - OLE stream: 'VBA P-code'
-------------------------------------------------------------------------------
VBA FORM STRING IN 'report.xls' - OLE stream: u'_VBA_PROJECT_CUR/F/o'
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
�9655B040B64667238524D15D6201.B95D4E01C55CC562C7557405A532D768C55FA12DD074DC697
...
C14B7C4E8F1F8F21CB64
-------------------------------------------------------------------------------
VBA FORM STRING IN 'report.xls' - OLE stream: u'_VBA_PROJECT_CUR/F/o'
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
H�,�p
-------------------------------------------------------------------------------
VBA FORM STRING IN 'report.xls' - OLE stream: u'_VBA_PROJECT_CUR/F/o'
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
58c7661f00634702555f664b7756884c864edc4fef2d9c48881bac0911082214334e424f552f661
...
4c0046004e00060068000b001600ef000e002600cc
+----------+--------------------+---------------------------------------------+
|Type |Keyword |Description |
+----------+--------------------+---------------------------------------------+
|AutoExec |Auto_Open |Runs when the Excel Workbook is opened |
|AutoExec |Workbook_Open |Runs when the Excel Workbook is opened |
|Suspicious|CreateObject |May create an OLE object |
|Suspicious|Environ |May read system environment variables |
|Suspicious|Write |May write to a file (if combined with Open) |
|Suspicious|Put |May write to a file (if combined with Open) |
|Suspicious|Open |May open a file |
|Suspicious|Lib |May run code from a DLL |
|Suspicious|Chr |May attempt to obfuscate specific strings |
| | |(use option --deobf to deobfuscate) |
|Suspicious|Xor |May attempt to obfuscate specific strings |
| | |(use option --deobf to deobfuscate) |
|Suspicious|Binary |May read or write a binary file (if combined |
| | |with Open) |
|Suspicious|Hex Strings |Hex-encoded strings were detected, may be |
| | |used to obfuscate strings (option --decode to|
| | |see all) |
|IOC |wininet.dll |Executable file name |
|IOC |winmm.dll |Executable file name |
|Suspicious|VBA Stomping |VBA Stomping was detected: the VBA source |
| | |code and P-code are different, this may have |
| | |been used to hide malicious code |
+----------+--------------------+---------------------------------------------+
Narzędzie wylistowało używane funkcje, biblioteki oraz metody, których użycie zostało zaklasyfikowane jako podejrzane.
Na szczególną uwagę zasługuje informacja o wykorzystaniu metody VBA Stomping.
3.1 Pozyskanie makra
Wyodrębniłem makro w VBA:
$ olevba --code report.xls | tee report.vbs
Kod VBA zamieściłem poniżej:
olevba 0.55.1 on Python 2.7.17 - http://decalage.info/python/oletools
===============================================================================
FILE: report.xls
Type: OLE
-------------------------------------------------------------------------------
VBA MACRO ThisWorkbook.cls
in file: report.xls - OLE stream: u'_VBA_PROJECT_CUR/VBA/ThisWorkbook'
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Sub Workbook_Open()
Sheet1.folderol
End Sub
Sub Auto_Open()
Sheet1.folderol
End Sub
-------------------------------------------------------------------------------
VBA MACRO Sheet1.cls
in file: report.xls - OLE stream: u'_VBA_PROJECT_CUR/VBA/Sheet1'
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Private Declare Function InternetGetConnectedState Lib "wininet.dll" _
(ByRef dwflags As Long, ByVal dwReserved As Long) As Long
Private Declare PtrSafe Function mciSendString Lib "winmm.dll" Alias _
"mciSendStringA" (ByVal lpstrCommand As String, ByVal _
lpstrReturnString As Any, ByVal uReturnLength As Long, ByVal _
hwndCallback As Long) As Long
Private Declare Function GetShortPathName Lib "kernel32" Alias "GetShortPathNameA" _
(ByVal lpszLongPath As String, ByVal lpszShortPath As String, ByVal lBuffer As Long) As Long
Public Function GetInternetConnectedState() As Boolean
GetInternetConnectedState = InternetGetConnectedState(0&, 0&)
End Function
Function rigmarole(es As String) As String
Dim furphy As String
Dim c As Integer
Dim s As String
Dim cc As Integer
furphy = ""
For i = 1 To Len(es) Step 4
c = CDec("&H" & Mid(es, i, 2))
s = CDec("&H" & Mid(es, i + 2, 2))
cc = c - s
furphy = furphy + Chr(cc)
Next i
rigmarole = furphy
End Function
Function folderol()
Dim wabbit() As Byte
Dim fn As Integer: fn = FreeFile
Dim onzo() As String
Dim mf As String
Dim xertz As Variant
onzo = Split(F.L, ".")
If GetInternetConnectedState = False Then
MsgBox "Cannot establish Internet connection.", vbCritical, "Error"
End
End If
Set fudgel = GetObject(rigmarole(onzo(7)))
Set twattling = fudgel.ExecQuery(rigmarole(onzo(8)), , 48)
For Each p In twattling
Dim pos As Integer
pos = InStr(LCase(p.Name), "vmw") + InStr(LCase(p.Name), "vmt") + InStr(LCase(p.Name), rigmarole(onzo(9)))
If pos > 0 Then
MsgBox rigmarole(onzo(4)), vbCritical, rigmarole(onzo(6))
End
End If
Next
xertz = Array(&H11, &H22, &H33, &H44, &H55, &H66, &H77, &H88, &H99, &HAA, &HBB, &HCC, &HDD, &HEE)
wabbit = canoodle(F.T.Text, 0, 168667, xertz)
mf = Environ(rigmarole(onzo(0))) & rigmarole(onzo(1))
Open mf For Binary Lock Read Write As #fn
Put #fn, , wabbit
Close #fn
mucolerd = mciSendString(rigmarole(onzo(2)) & mf, 0&, 0, 0)
End Function
Function canoodle(panjandrum As String, ardylo As Integer, s As Long, bibble As Variant) As Byte()
Dim quean As Long
Dim cattywampus As Long
Dim kerfuffle() As Byte
ReDim kerfuffle(s)
quean = 0
For cattywampus = 1 To Len(panjandrum) Step 4
kerfuffle(quean) = CByte("&H" & Mid(panjandrum, cattywampus + ardylo, 2)) Xor bibble(quean Mod (UBound(bibble) + 1))
quean = quean + 1
If quean = UBound(kerfuffle) Then
Exit For
End If
Next cattywampus
canoodle = kerfuffle
End Function
3.2 Analiza makra: VBA
3.2.1 Funkcja rigmarole
Funkcja rigmarole odpowiadała za odkodowanie ciągów bajtów:
9655B040B64667238524D15D6201
B95D4E01C55CC562C7557405A532D768C55FA12DD074DC697A06E172992CAF3F8A5C7306B7476B38
C555AC40A7469C234424
853FA85C470699477D3851249A4B9C4E
A855AF40B84695239D24895D2101D05CCA62BE5578055232D568C05F902DDC74D2697406D7724C2CA83FCF5C2606B547A73898246B4BC14E941F9121D464D263B947EB77D36E7F1B8254
853FA85C470699477D3851249A4B9C4E
9A55B240B84692239624
CC55A940B44690238B24CA5D7501CF5C9C62B15561056032C468D15F9C2DE374DD696206B572752C8C3FB25C3806
A8558540924668236724B15D2101AA5CC362C2556A055232AE68B15F7C2DC17489695D06DB729A2C723F8E5C65069747AA389324AE4BB34E921F9421
CB55A240B5469B23
AC559340A94695238D24CD5D75018A5CB062BA557905A932D768D15F982D
D074B6696F06D5729E2CAE3FCF5C7506AD47AC388024C14B7C4E8F1F8F21CB64
do postaci:
AppData
\Microsoft\stomp.mp3
play
FLARE-ON
Sorry, this machine is not supported.
FLARE-ON
Error
winmgmts:\\.\root\CIMV2
SELECT Name FROM Win32_Process
vbox
WScript.Network
\Microsoft\v.png
3.2.2 Funkcja canoodle
Funkcja canoodle odpowiadała za odszyfrowanie ciągu danych szyfrem Vernama.
3.2.3 Funkcja folderol
Funkcja folderol była główną funkcją makra, która była automatycznie uruchamiana po załadowaniu arkusza. Oprócz realizowania faktycznego zamiaru programisty, odpowiadała za weryfikację obecności połączenia sieciowego oraz detekcję wirtualnego środowiska uruchomieniowego. Mechanizm detekcji polegał na przeszukaniu listy procesów w celu ujawnienia obecności procesu zawierającego ciąg znaków “vmw”, “vmt” lub “vbox”.
Właściwą funkcjonalnością realizowaną przez funkcję folderol było:
- poprawne odszyfrowanie szyfrogramu zawartego w polu tekstowym formatki zdefiniowanej w makrze:
- zapisanie tekstu jawnego do pliku
%AppData%\Microsoft\stomp.mp3
3.2.4 Analiza pliku stomp.mp3
Odtworzyłem plik stomp.mp3
, gdzie było słyszalne kilka tupnięć.
Następnie odczytałem metadane z wykorzystaniem narzędzia exiftool
:
$ exiftool stomp.mp3
ExifTool Version Number : 12.00
File Name : stomp.mp3
Directory : .
File Size : 165 kB
File Modification Date/Time : 2020:09:21 20:59:31+02:00
File Access Date/Time : 2020:09:21 20:59:31+02:00
File Inode Change Date/Time : 2020:09:21 20:59:31+02:00
File Permissions : rw-r--r--
File Type : MP3
File Type Extension : mp3
MIME Type : audio/mpeg
MPEG Audio Version : 1
Audio Layer : 3
Audio Bitrate : 160 kbps
Sample Rate : 44100
Channel Mode : Joint Stereo
MS Stereo : Off
Intensity Stereo : Off
Copyright Flag : False
Original Media : False
Emphasis : None
ID3 Size : 4096
Publisher : FLARE
Year : 2020
Title : This is not what you should be looking at...
Band : P. Code
Date/Time Original : 2020
Duration : 8.23 s (approx)
Jeżeli do tej pory ktoś nie zauważył wykorzystania metody VBA Stomping, to w tym momencie można było odczytać dwie wskazówki:
This is not what you should be looking at…
3.3 Analiza makra: P-code - wariant 1
Wiedząc, że wykorzystano metodę VBA Stomping, odczytałem zdeasemblowany P-code:
$ pcodedmp report.xls | tee report.pcode
3.3.1 Ukryty kod makra
Manualnie przeprowadzona analiza różnicowa P-code’u oraz kodu VBA ujawniła fragment P-code’u:
Line #53:
SetStmt
LitDI2 0x000A
ArgsLd onzo 0x0001
ArgsLd rigmarole 0x0001
ArgsLd CreateObject 0x0001
Set groke
Line #54:
Ld groke
MemLd UserDomain
St firkin
Line #55:
Ld firkin
LitDI2 0x0003
ArgsLd onzo 0x0001
ArgsLd rigmarole 0x0001
Ne
IfBlock
Line #56:
LitDI2 0x0004
ArgsLd onzo 0x0001
ArgsLd rigmarole 0x0001
Ld vbCritical
LitDI2 0x0006
ArgsLd onzo 0x0001
ArgsLd rigmarole 0x0001
ArgsCall MsgBox 0x0003
Line #57:
End
Line #58:
EndIfBlock
Line #59:
Line #60:
Ld firkin
FnLen
St n
Line #61:
StartForVariable
Ld i
EndForVariable
LitDI2 0x0001
Ld n
For
Line #62:
Ld firkin
Ld i
LitDI2 0x0001
ArgsLd Mid$ 0x0003
ArgsLd Asc 0x0001
Ld n
Ld i
Sub
ArgsSt buff 0x0001
Line #63:
StartForVariable
Next
Line #64:
Line #65:
Ld F
MemLd T
MemLd Text
LitDI2 0x0002
LitDI4 0x5C21 0x0004
Ld buff
ArgsLd canoodle 0x0004
St wabbit
Line #66:
LitDI2 0x0000
ArgsLd onzo 0x0001
ArgsLd rigmarole 0x0001
ArgsLd Environ 0x0001
LitDI2 0x000B
ArgsLd onzo 0x0001
ArgsLd rigmarole 0x000"FLARE-ON"1
Concat
St mf
3.3.2 Analiza ukrytego kodu
Analiza P-code pozwoliła odtworzyć możliwy kod VBA:
Set groke = CreateObject("WScript.Network")
Dim firkin As String
firkin = groke.UserDomain
If firkin <> "FLARE-ON" Then
MsgBox rigmarole(onzo(4)), vbCritical, rigmarole(onzo(6))
End
End If
Dim n As Integer
n = Len(firkin)
For i = 1 To n
buff(n - i) = Asc(Mid(firkin, i, 1))
Next
wabbit = canoodle(F.T.Text, 2, 285729, buff)
mf = Environ("AppData") & "\Microsoft\v.png"
3.4 Analiza makra: P-code - wariant 2
Wykorzystując narzędzie pcode2code.py
, pozyskałem zdekompilowany do VBA kod P-code:
$ python /home/remnux/.local/lib/python2.7/site-packages/pcode2code/pcode2code.py report.xls | tee report.pcode2vba
Analiza kodu VBA pozwoliła ustalić istotny fragment odpowiedzialny za poprawne odszyfrowanie szyfrogramu:
Set groke = CreateObject(rigmarole(onzo(10)))
firkin = groke.UserDomain
If firkin <> rigmarole(onzo(3)) Then
MsgBox rigmarole(onzo(4)), vbCritical, rigmarole(onzo(6))
End
End If
n = Len(firkin)
For i = 1 To n
buff(n - i) = Asc(Mid$(firkin, i, 1))
Next
wabbit = canoodle(F.T.Text, 2, 285729, buff)
mf = Environ(rigmarole(onzo(0))) & rigmarole(onzo(11))
4. Odczytanie flagi
Moją uwagę zwrócił fakt, że klucz do odszyfrowania był wyznaczany z nazwy maszyny. Ponadto skrypt wymagał, żeby była to nazwa “FLARE-ON”.
Wykonałem zatem skrypt:
Function folderol()
Dim wabbit() As Byte
Dim fn As Integer: fn = FreeFile
Dim mf As String
Dim buff(0 To 7) As Byte
Dim firkin As String
firkin = "FLARE-ON"
Dim n As Integer
n = Len(firkin)
For i = 1 To n
buff(n - i) = Asc(Mid(firkin, i, 1))
Next
wabbit = canoodle(F.T.Text, 2, 285729, buff)
mf = Environ("AppData") & "\Microsoft\v.png"
Open mf For Binary Lock Read Write As #fn
Put #fn, , wabbit
Close #fn
End Function
Jako skutek wykonania makra, został zapisany plik %AppData%\Microsoft\v.png
, który zawierał flagę: