Gần đây, ESET đã công bố một báo cáo về một chiến dịch tấn công chuỗi cung ứng (supply chain attack) nhắm vào hãng phần mềm BigNox, lợi dụng cơ chế update của phần mềm NoxPlayer, một phần mềm giả lập (emulator) hệ điều hành Android chạy trên PC và Mac. Phần mềm này được nhiều game thủ của Việt Nam cũng như trên thế giới sử dụng. ESET đã đặt tên chiến dịch này là Operation NightScout. Với nhận định Việt Nam chúng ta cũng có thể có nhiều người đã bị lây nhiễm do tập người dùng lớn, nên chúng tôi đã bắt tay điều tra, phân tích thêm.
Dựa theo các hash của các mẫu mà ESET cung cấp, chúng tôi đã không chỉ phân tích lại hết mà còn phân tích sâu hơn vào các mẫu đó. Chúng tôi đã phát hiện ra nhiều điểm mà báo cáo của ESET không nêu ra. Đồng thời, chúng tôi đã tìm ra một số mối liên hệ, tương đồng giữa các mẫu này và các mẫu đã được dùng trong chiến dịch tấn công Ban Cơ yếu Chính phủ vừa qua cũng như một tập đoàn lớn của Việt Nam mà chúng tôi đã có đề cập. Không chỉ vậy, chúng tôi đã phát hiện ra một dòng RAT mới, đó là ElephantRat.
![]() |
“昆明版本”có nghĩa là “Phiên bản Côn Minh” |
Trong các mẫu đó, chúng tôi tập trung vào mẫu E45A5D9B03CFBE7EB2E90181756FDF0DD690C00C và phân tích xuyên suốt tới các PE được nhúng và thực thi fileless trên memory tới tận cùng. Tìm các điểm tương đồng trong binary pattern, chúng tôi phát hiện ra thêm một dòng mẫu khác đang được tin tặc sử dụng mới gần đây giống với tập mẫu đã dùng trong chiến dịch tấn công tập đoàn lớn của Việt Nam chúng ta.
Do bộ tập mẫu này hacker không dùng nhiều C++ theo style OOP. Công cụ chính chúng tôi dùng vẫn là IDA và các plugin chính sau: FindCrypt3, SusanRTTI, LazyIDA.
Mẫu E45A5D9B03CFBE7EB2E90181756FDF0DD690C00C (SHA-1), trong report của ESET là UpdatePackageSilence.exe, có:
- MD5 = 06AF27C0F47837FB54490A8FE8332E04
- SHA-256 = E76567A61F905A2825262D5F653416EF88728371A0A2FE75DDC53AAD100E6F46
- Compiler time: Wednesday, 26.08.2020 08:39:20 UTC
Là first stage trong chuỗi lây nhiễm. Cách code, thực thi và hành vi giống như VVSup.exe đã đề cập ở trong bài blog trước. Mẫu được biên dịch bằng Visual Studio 2008 (Linker version 9.00). Đặc biệt, file này có overlay data rất lớn ở cuối của PE, offset 0x45800.
File Exe này cũng là một MFC Dialog application, chỉ khác là dùng MFC ver 9.0 đi kèm Visual Studio 2008 (VVSup dùng MFC ver 4.2, đi kèm Visual Studio 6), ANSI mode. Và bản Visual Studio này của hacker là bản tiếng Trung Quốc, nên toàn bộ các resource items default mà MFC Wizard tự động tạo ra đều có language là Chinese.
Dialog 30721 là Dialog “New Item” default của MFC, StringTable ID từ 60000 cũng là resource string ID default của MFC. Hacker đã điền ngẫu nhiên vào About Wizard tên Exe và version number. Dialog mà hacker thêm vào thì hacker đã set lại language là English. Main Dialog có ID = 102, About Dialog có ID = 100
Control ID 1 và 2 là mặc định MFC Wizard tạo ra, là IDOK và IDCANCEL. Các button 3 (ID_ABORT), 4 (ID_RETRY), 5 (ID_IGNORE) là hacker thêm vào. Chúng ta lưu ý Button ID_ABORT 3. Main Icon của app (ID 1) được hacker sử dụng các icon mà các trình cài đặt thường dùng.
SusanRTTI cho chúng tôi lưu đồ class của app. Hình dưới là một phần của lưu đồ.
Dùng các tính năng Search của LazyIDA, với CSkinMfcApp và CSkinMfcDlg, chúng tôi chỉ tìm được một link này của China, nói về kỹ thuật tạo skin dialog cho MFC dialog.
Với sự xuất hiện thêm nữa của class CRgn, chúng ta có thể tin rằng hacker đã dùng toàn bộ project này và bổ sung thêm vài thay đổi. Cơ chế thực thi của một MFC app dạng dialog, chúng tôi đã post ở bài blog trước, các bạn có thể xem lại còn ở bài blog này, chúng tôi chỉ tập trung vào điểm chính.
Tại method OnInitDialog của CSkinMfcDlg, hacker có thay đổi cách gọi vào tác vụ lây nhiễm chính và code thêm:
- Resize Dialog về 0
- Hide Dialog
- Thay đổi style của Dialog để không hiện lên thanh Taskbar của Windows
- Post WM_COMMAND to Button ID 3
- Hacker cũng cẩn thận giả lập thêm user left mouse click vào Button ID 3
Tại AFX_MSGMAP của CSkinMfcDlg, chúng tôi mới tìm thấy hàm thực thi lây nhiễm chính.
Khi ExtractAndLoadOverlayDll được gọi, đầu tiên hacker sẽ kiểm tra app có quyền read vào thư mục Windows\System32 không và kiểm tra file clb.dll có tồn tại không. Clb.dll là file của Windows - Column ListBox. Sau đó hacker mở Exe chính nó, đọc vùng Overlay data tại offset 0x45800 và giải mã xor với 0xA0 để ra một PE là Dll. Sau đó sẽ manual load Dll này lên memory, bắt đầu một chuỗi dài các manual load fileless PE.
Tại hàm ManualLoadDll này, chúng tôi phát hiện một lỗi lập trình của hacker. Cụ thể, Malloc không có free và code nhầm: malloc(sizeof(PE_LOADER_INFO)) (16 bytes) thành malloc(sizeof(pLdrInfo)) (4 bytes). Struct PE_LOADER_INFO do chúng tôi đặt tên lại, gồm 4 data member, size là 16 bytes.
Sau khi alloc 4 byte:
Sau khi overwrite:
Về các giá trị 0xBAADFOOD và 0xABABABAB… của VC RTL và Windows Heap Manager, các bạn có thể đọc thêm ở đây. Các hàm làm nhiệm vụ manual (reflective) load overlay Dll được biên dịch thành dạng shellcode array of bytes, nhúng vào .data section, có size tổng cộng là 0xA9E. Bắt đầu từ địa chỉ của hàm LoaderProc: .data:00440830. 0xA95 là RVA của constant 0x12345678, sẽ được overwrite bằng nội dung vùng nhớ mà biến pLdrInfo sau khi được malloc lưu, sizeof(pointer) = 4 (x86). Byte đầu tiên của hàm LoaderProc sẽ được modify lại thành 0x55 = push ebp
Hàm GetLoaderApiAddrs làm nhiệm vụ get các API address từ kernel32.dll và ntdll.dll vào một struct chứa các pointer to các hàm API đó. Thuật toán tính toán giá trị hash từ các export API name được sử dụng là ROR13, được dùng phổ biến trong Metasploit. Bạn đọc có thể dùng plugin shellcode_hashes_search_plugin.py trong bộ tool Flare_ida của FireEye để tự động xác định name các hàm API, chọn hash function là ror13AddHash32AddDll. Struct này được chúng tôi định nghĩa lại như sau:
Hàm GetLoaderApiAddrs:
Giá trị của biến thuộc struct này trong hàm LoaderProc sau khi hàm GetLoaderApiAddrs được call và return.
Điểm đáng chú ý ở chỗ, hacker code tính năng manual/reflective load này sử dụng trực tiếp với các hàm native của Ntdll.dll, không thông qua các hàm của kernel32. Điều này có thể để tránh detect bởi các AV/EDR hook kernel32.dll. Và nó cũng dùng xuyên suốt với các mẫu khác và các PE fileless sau này.
Tới hàm ReflectiveLoadDll thì code tương tự như các manual load/reflective open source khác. Chúng tôi xin phép không trình bày lại. Tìm kiếm trên Github, Google và VirusTotal hàm GetLoaderApiAddrs, chúng tôi không tìm được hàm nào như vậy. Nên chúng tôi cho là đây là 1 thư viện manual/reflective load của nhóm này tự viết, không dùng open source nào.
Tới đây thì Overlay Dll đã được load và luồng thực thi chuyển thẳng vào OEP của Dll này. Exe mẹ không thoát ngay như VVSup.exe mà sẽ do các dll con thực thi fileless sẽ call ExitProcess hay TerminateProcess sau này.
Chúng ta tạm chuyển hướng sang một mẫu khác mà report của ESET có đề cập có SHA1 = 5732126743640525680C1F9460E52D361ACF6BB0. Mẫu này được compile bằng Visual Studio 2012, build vào ngày 16.11.2020 08:35:32 UTC, cũng là MFC app, nhưng không còn là Dialog app mà là một app Doc – View, dùng các class MFC Ribbon mới sau này. Do đó, số lượng code và class phình ra rất lớn, và có thể là first stage dùng MFC mới nhất của nhóm này. Hacker không còn dựa vào extrac32.exe để giải nén các Cab file được nhúng bên trong nữa mà tự viết một class CCabinet dùng các hàm API Cabinet có sẵn của Windows để giải nén.
PDB path = “C:\Users\enWin7x64\Desktop\XActor\CreateServer_src\XActorCreateServer\DATA_RES\CommandoLoader\mfeesp\Release\mfeesp.pdb”. Đoạn code thực thi extract hai cab file từ resource được viết thẳng vào hàm InitInstance của class CmfeespApp. Và file malware LBTServ.dll được extract ra từ cab file là một Dll, viết trên ngôn ngữ Delphi và build bằng RAD Studio 10.4 Sydney mới nhất của hãng Embarcadero. Đây có thể là sự chuyển hướng sang dùng ngôn ngữ, compiler/IDE khác cho các malware sau này của nhóm này. Vì phạm vi và mục đích bài viết, chúng tôi không trình bày về các mẫu này.
Quay lại overlay Dll ở trên, sau khi extract ra, chúng ta có một Dll với các thông tin sau:
- Size = 557,056 bytes
- MD5 = 054E07CB00E9B21786E2815E9B43CDA9
- SHA256 = 8BF3DF654459B1B8F553AD9A0770058FD2C31262F38F2E8BA12943F813200A4D
- Compile time: Monday, 17.08.2020 09:56:11 UTC
- Dùng Visual Studio 6
- Không có PDB path và export nên không xác định được tên Dll ban đầu
Size của .data section lớn, sau khi chạy FindCrypt3, chúng tôi thấy có nhiều vùng data lớn. Toàn bộ tác vụ chính của Dll này nằm hoàn toàn trong hàm DllMain. Khi DllMain được call với fdwReason khác DLL_PROCESS_ATTACK, hacker kiểm tra Dll có thể OpenProcess với System Process (PID = 4) với các quyền cao nhất 0x1F0FFF hay không. Nếu OpenProcess thành công sẽ return TRUE, không làm gì tiếp. Sau đó hacker đọc ngược lại Exe mẹ, dùng hàm MemSearch như ở VVSup.exe để tìm và extract thông tin C&C và lưu vào thành một file C:\ProgramData\resmon.resmoncfg. Điểm khác nhỏ là VVSup dùng MemSearch để lấy C&C info từ mẹ ghi vào Dll con. Còn ở đây là Dll con search ngược lại từ Exe mẹ.
Ghi thông tin C&C vào file resmon.resmoncfg
Byte array là mask để search là “3F 3E 2F 1E 7F 7E 6F 2E 1F 1E 00 03 3F 3E 2F 4E”. File size của file resmon.resmoncfg là 1550 bytes, copy nội dung từ offset của mask + 47.
Hacker cũng dùng hàm export MakeSureDirectoryPathExists từ dbghelp.dll để tạo thư mục, như ở VVSup, đồng thời dùng rất nhiều các biến, chuỗi, array toàn cục (global). Có nhiều đoạn code dư như lấy lấy các CreationTime, LastAccessTime, LastWriteTime của file hệ thống csrss.exe mà không dùng tới, khởi tạo các chuỗi không dùng. Tạo thư mục Sandboxie:
Dll tiếp tục giải nén các vùng data nhúng trong Dll thành các file: SbieIni.dat, SbieDll.dll, SandboxieBITS.exe vào trong thư mục C:\ProgramData\Sanboxie.
Thuật toán nén, giải nén mà hacker dùng ở đây là thuật toán LZMA của 7z. SDK của LZMA các bạn có thể download và tham khảo tại đây. Điểm nhận dạng thuật toán LZMA được dùng là LZMA_PROPS_SIZE = 5 và 8 byte đầu thuộc struct CLzmaProps tại đầu vùng data compressed.
Hàm giải nén, size của vùng data compressed truyền vào trừ đi bớt 4, giá trị size của vùng data đã uncompress là DWORD đứng ngay trước vùng data compressed đó.
Nhưng đặc biệt là hacker đã thay đổi trong code của thuật toán LZMA này, nên các vùng data compressed này nếu chúng tôi static extract ra theo thông tin trên thì khi giải nén bằng 7z hay tool, lib thông thường sẽ bị báo lỗi, nhưng vẫn có thể giải nén ra được vùng đầu của data đúng so với kết quả khi debug và dump ra.
Cách dùng thuật toán nén LZMA đã thay đổi này, chúng tôi cũng tìm thấy trong một mẫu plugin mới của SManager RAT, được upload lên VirusTotal đầu tiên ngày 23/01/2021, có:
- MD5= 0603145EFAD6A63F52B6D5161CC5E5AE
- SHA256= 321045519CC3A50CE7948C33C6BBC837B063CD878F8C2CE67DC8DE0825515E10
- Tên file: SuperShellC_x86.dll
Trong file Dll này, class CSuperShellC có thực hiện tác vụ giải nén ra một Exe nhúng bên trong, tên gốc là ssh_server.exe.
Thuật toán LZMA này tiếp tục được hacker cải tiến thêm, nên static dump và mở sẽ không được mà cần dùng debug để dump.
Quay trở lại Overlay Dll, sau khi extract ra 3 file x86 vào thư mục C:\ProgramData\Sandboxie, Dll tiếp tục kiểm tra xem chính nó có quyền ghi vào thư mục System32 và hệ điều hành Windows mục tiêu có phải là x64 không. Nếu thỏa mãn hết, Dll sẽ extract thêm hai file SbieMsg.dll và SbieMsg.dat vào thư mục đó.
Tại hàm HavePermission, hacker sẽ tạo một file ngẫu nhiên trong System32, có tên đầu là wmkawe_ và nội dung chỉ 1 dòng chữ: “Stupid Japanese”.
Ngoài ra hacker còn kiểm tra xem có hai file cũng tên ngẫu nhiên wmkawe_xxx.data trên trong hai thư mục:“%LOCALAPPDATA%\VirtualStore\Windows\System32\” và “%LOCALAPPDATA%\VirtualStore\Windows\SysWOW64\” không, nếu có sẽ xóa đi. Hàm kiểm tra Windows của mục tiêu là x64 hay không, hacker không dùng hàm API IsWow64Process thông thường, mà dùng hàm API GetNativeSystemInfo.
Sau khi extract ra thêm hai file SbieMsg.dat và SbieMsg.dll, Dll sẽ load SbieMsg.dll lên bằng rundll32.exe của Windows, gọi hàm export “installsvc”, truyền param là “ByPassUAC”.
Nếu không phải là Windows x64, SandboxieBITS.exe sẽ được gọi với param cũng là “ByPassUAC”. Và nếu không có quyền ghi vào System32, Dll chỉ gọi SandboxieBITS.exe với param là “InsertS”. Sau cùng, Dll sẽ tạo file bat tự xóa Exe mẹ và chính file bat rồi thoát Exe mẹ.
Hàm SelfDelete execute cmd.exe ở cửa sổ hide, idle priority và disable Ctrl-C/Ctrl-Break
Tới đây, stage một trong quá trình lây nhiễm đã hoàn tất. Stage 2 bắt đầu từ thực thi SandboxieBITS.exe hay SbieMsg.dll (x64) run as một service Dll.
Chúng tôi xin tạm dừng tại đây do còn rất dài. Các phần sau chúng tôi sẽ public khi thích hợp. Chúc bạn đọc năm mới Tân Sửu 2021 mạnh khỏe, bình an trước diễn biến phức tạp của đại dịch và vạn sự như ý.
Trương
Quốc Ngân (aka HTC)
Chuyên gia Phân tích mã độc - VinCSS (a member of Vingroup)
bài phân tích quá chi tiết và chuyên sâu. Xin cảm ơn tác giả. Mong chờ bài tiếp theo.
ReplyDelete