Matanbuchus T research.openanalysis.net triage.html OALABS Research riage Notes /matanbuchus/loader/yara/triage/dumpulator/emulation/2022/06/19/matanbuchus- June 19, 2022 Overview Matanbuchus is a malware downloader that has been observed as the final loading stage in multiple phishing campaigns. There are two components, a Matanbuchus loader intented to load the Matanbuchus downloader. Once the downloader is executed it makes an HTTP request to the C2 with some victim info, and downloads the final payload. According to DCSO CyTec... Matanbuchus is the name given to a Malware-as-a-Service sold on Russian-speaking cybercriminal forums. Starting at a rental price of $2,500, the malware consists of an obfuscated two-stage loader which has been deployed in conjunction with Qakbot and Cobalt Strike payloads. 1/32 References Analysis The DLL has an export called start dll HackCheck The sample uses API hashing with FNV1a hash algo to resolve API calls Yara Rule This yara rule is very brittle and needs lots of testing/refining HackCheck that uses OutputDebugStringA to print 2/32 rule matanbuchus { meta: description = "Identifies matanbuchus" strings: // recursive fnv1 hash // 69 C2 93 01 00 01 imul eax, edx, 1000193h // 50 push eax // B9 01 00 00 00 mov ecx, 1 // C1 E1 00 shl ecx, 0 $x1 = { 69 c2 93 01 00 01 50 b9 01 00 00 00 c1 e1 00 } // string decryption // 0F BE 1C 01 movsx ebx, byte ptr [ecx+eax] // 33 DE xor ebx, esi // 6A 00 push 0 // 6A 01 push 1 $x2 = { 0f be 1c 01 33 de 6a 00 6a 01 } condition: all of ($x*) } Yara Rule Revised 3/32 rule matanbuchus { meta: description = "Identifies matanbuchus" strings: // fnv1 hash // 69 C2 93 01 00 01 imul eax, edx, 1000193h // // 69 C0 93 01 00 01 imul eax, 1000193h $x1 = { 69 ?? 93 01 00 01 } //pe loader $x2 = { B8 4D 5A 00 00 } $x3 = { 81 38 50 45 00 00 } //InternetCloseHandle $x5 = { 66 E9 DD 4D } //InternetOpenUrlA $x6 = { BC 8B CF F4 } //InternetCheckConnectionA $x7 = { 3F 82 58 52 } //InternetReadFile $x8 = { 66 E9 DD 4D } condition: all of ($x*) } String Decryption Simple Decryption Some strings are built as stack strings then copied into a buffer and returned from a function. The returned buffer is then decrypted directly using a simple XOR decryption routine where the first byte is the key. import struct data = b'jl8|tt8Py{s[p}{s' key = struct.pack('(?:\xC6\x85.{5} for m in re.finditer(string_egg, match_data = m.group(0) #stack_strings.append({"data":match_data.replace(b'\xC6\x45',b'')[1::2], "match":match_data}) stack_strings.append({"data": keys = [] key_byte_len_egg for m key_dw_len_egg = in re.finditer( keys.append( = rb rb'\x68(....)\x68(....)\x6a\x00\x6a(.)' key_byte_len_egg, {'key':m.group( '\x68(....)\x68(....)\x6a\x00\x68(....)' read() %len(key)]) *$", data) is data) is not ){0,})(?P(?:\xC6\x45..){1,})' file_data): m['a'][6::7] + file_data): 2) + m.group( not None None m['b'][3::4], "match": 1), 'length':ord(m.group( match_data}) 3))}) 10/32 for m in re.finditer(key_dw_len_egg, keys.append( {'key':m.group(2) 'length':struct.unpack('(?:\xC6\x85.{5} for m in re.finditer(string_egg, file_data): match_data = m.group(0) #stack_strings.append({"data":match_data.replace(b'\xC6\x45',b'')[1::2], "match":match_data}) stack_strings.append({"data":m['a'][ "match":match_data}) keys = [] key_byte_len_egg = rb'\x68(....)\x68(....)\x6a\x00\x6a(.)' for m in re.finditer(key_byte_len_egg, keys.append( {'key':m.group(2) + key_dw_len_egg = rb'\x68(....)\x68(....)\x6a\x00\x68(....)' for m in re.finditer(key_dw_len_egg, keys.append( {'key':m.group(2) + 'length':struct.unpack('(?:\xC6\x45..){3,})' 6::7] + file_data): m.group( file_data): m.group( m['b'][3 1), 'length': 1), ::4], ord(m.group(3))}) 14/32 for if out if if out if for if return Test All Samples get_strings( import for filename if tmp_out k in len elif len out_strings. else: = [] keys: k.get('length') == str_len: = xor_decrypt(s, k.get is_ascii(out): tmp_out.append(out) (tmp_out) == 0: = xor_decrypt(s[1:-1], is_ascii(out): out_strings.append(out) (tmp_out) == 1: append(tmp_out[ # This is a hack # We have strings that will give valid ascii for multiple keys # So far these have only been dll names out in tmp_out: out[:-3].lower() == b out_strings.append( break list(set(out_strings)) FILE_PATH) os in os.listdir('/tmp/samples'): filename.endswith(".bin"): file_path = os.path.join('/tmp/samples', print(f"\n{file_path}") print(get_strings(file_path)) ('key')) bytes([s[0]])) 0]) 'dll': out) filename) 15/32 /tmp/samples/55d329a13da236bec15c4c67686b809a2fbf5f6c9625b62d900ac22a7b729ba9.bin [b'VirtualAlloc', b'Windows-Update-Agent/11.0.10011.16384 Client-Protocol/2.0\x00', b'rundll32.exe\x00', b'9npSEGB3kg9suo3Yit\x00', b'kernel32.dll', b'https://azure- dbupdate.at/vuUwUx/FyNRoM/index.php\x00', b'Shlwapi.dll\x00', b'WS2_32.dll\x00', b'DllRegisterServer\x00', b'loaddll32.exe\x00', b'Shell32.dll\x00', b'Wininet.dll\x00', b'USER32.dll\x00', b'GetProcAddress', b'LoadLibraryA', b'IPHLPAPI.DLL\x00', b'https://azure-dbupdate.at/vuUwUx/FyNRoM/auth.php\x00', b'https://azure-updatedb.at/vuUwUx/FyNRoM/index.php\x00', b'VirtualFree', b'regsvr32.exe\x00', b'%PROCESSOR_LEVEL%'] /tmp/samples/4b87f95c4477fc66c58b8e16a74f9c47217913cb4a78dc69f27a364a099acd90.bin [b'VirtualAlloc', b'Windows-Update-Agent/11.0.10011.16384 Client-Protocol/2.0\x00', b'rundll32.exe\x00', b'9npSEGB3kg9suo3Yit\x00', b'kernel32.dll', b'https://azure- dbupdate.at/vuUwUx/FyNRoM/index.php\x00', b'Shlwapi.dll\x00', b'WS2_32.dll\x00', b'DllRegisterServer\x00', b'loaddll32.exe\x00', b'Shell32.dll\x00', b'Wininet.dll\x00', b'USER32.dll\x00', b'GetProcAddress', b'LoadLibraryA', b'IPHLPAPI.DLL\x00', b'https://azure-dbupdate.at/vuUwUx/FyNRoM/auth.php\x00', b'https://azure-updatedb.at/vuUwUx/FyNRoM/index.php\x00', b'VirtualFree', b'regsvr32.exe\x00', b'%PROCESSOR_LEVEL%'] /tmp/samples/0bdf1060b85ad55e73393eb0b59c1d226e091da4f4dcce65dacba5e9a1fd76a7.bin [b'VirtualAlloc', b'start dll HackCheck', b'http://collectiontelemetrysystem.com/m8YYdu/mCQ2U9/home.aspx\x00', b'https://telemetrysystemcollection.com/m8YYdu/mCQ2U9/auth.aspx\x00', b'rundll32.exe\x00', b'kernel32.dll', b'Shlwapi.dll\x00', b'WS2_32.dll\x00', b'DllRegisterServer\x00', b'loaddll32.exe\x00', b'Shell32.dll\x00', b'Wininet.dll\x00', b'USER32.dll\x00', b'GetProcAddress', b'Netapi32.dll\x00', b'LoadLibraryA', b'http://telemetrysystemcollection.com/m8YYdu/mCQ2U9/home.aspx\x00', b'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 10.0; Win64; x64; Trident/8.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729; Microsoft Outlook 16.0.5197; ms-office; MSOffice 16)\x00', b'IPHLPAPI.DLL\x00', b'Wkscli.dll\x00', b'https://telemetrysystemcollection.com/m8YYdu/mCQ2U9/home.aspx\x00', b'VirtualFree', b'https://collectiontelemetrysystem.com/m8YYdu/mCQ2U9/auth.aspx\x00', b'%PROCESSOR_LEVEL%'] /tmp/samples/3cae2ce9b2d7040292f1661af63dc28e778027c46f78d8be3b1d43f4b6c2b046.bin [b'VirtualAlloc', b'Windows-Update-Agent/11.0.10011.16384 Client-Protocol/2.0\x00', b'rundll32.exe\x00', b'9npSEGB3kg9suo3Yit\x00', b'kernel32.dll', b'https://azure- dbupdate.at/vuUwUx/FyNRoM/index.php\x00', b'Shlwapi.dll\x00', b'WS2_32.dll\x00', b'DllRegisterServer\x00', b'loaddll32.exe\x00', b'Shell32.dll\x00', b'Wininet.dll\x00', b'USER32.dll\x00', b'GetProcAddress', b'LoadLibraryA', b'IPHLPAPI.DLL\x00', b'https://azure-dbupdate.at/vuUwUx/FyNRoM/auth.php\x00', b'https://azure-updatedb.at/vuUwUx/FyNRoM/index.php\x00', b'VirtualFree', b'regsvr32.exe\x00', b'%PROCESSOR_LEVEL%'] /tmp/samples/b4e7710488c2b7aaa71688b8bd546410af07a215c2e835e8dfbe24887186bd4f.bin [b'VirtualAlloc', b'Windows-Update-Agent/11.0.10011.16384 Client-Protocol/2.0\x00', b'rundll32.exe\x00', b'9npSEGB3kg9suo3Yit\x00', b'kernel32.dll', b'https://azure- dbupdate.at/vuUwUx/FyNRoM/index.php\x00', b'Shlwapi.dll\x00', b'WS2_32.dll\x00', b'DllRegisterServer\x00', b'loaddll32.exe\x00', b'Shell32.dll\x00', b'Wininet.dll\x00', b'USER32.dll\x00', b'GetProcAddress', b'LoadLibraryA', 16/32 b'IPHLPAPI.DLL\x00', b'https://azure-dbupdate.at/vuUwUx/FyNRoM/auth.php\x00', b'https://azure-updatedb.at/vuUwUx/FyNRoM/index.php\x00', b'VirtualFree', b'regsvr32.exe\x00', b'%PROCESSOR_LEVEL%'] /tmp/samples/orig.bin [b'VirtualAlloc', b'start dll HackCheck', b'http://collectiontelemetrysystem.com/m8YYdu/mCQ2U9/home.aspx\x00', b'https://telemetrysystemcollection.com/m8YYdu/mCQ2U9/auth.aspx\x00', b'rundll32.exe\x00', b'kernel32.dll', b'Shlwapi.dll\x00', b'WS2_32.dll\x00', b'DllRegisterServer\x00', b'loaddll32.exe\x00', b'Shell32.dll\x00', b'Wininet.dll\x00', b'USER32.dll\x00', b'GetProcAddress', b'Netapi32.dll\x00', b'LoadLibraryA', b'http://telemetrysystemcollection.com/m8YYdu/mCQ2U9/home.aspx\x00', b'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 10.0; Win64; x64; Trident/8.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729; Microsoft Outlook 16.0.5197; ms-office; MSOffice 16)\x00', b'IPHLPAPI.DLL\x00', b'Wkscli.dll\x00', b'https://telemetrysystemcollection.com/m8YYdu/mCQ2U9/home.aspx\x00', b'VirtualFree', b'https://collectiontelemetrysystem.com/m8YYdu/mCQ2U9/auth.aspx\x00', b'%PROCESSOR_LEVEL%'] /tmp/samples/2f36c571f20b2b2c2058d4db574a6d53b148450356bf529d72aefc19505c912e.bin [b'VirtualAlloc', b'Windows-Update-Agent/11.0.10011.16384 Client-Protocol/2.0\x00', b'rundll32.exe\x00', b'9npSEGB3kg9suo3Yit\x00', b'kernel32.dll', b'https://azure- dbupdate.at/vuUwUx/FyNRoM/index.php\x00', b'Shlwapi.dll\x00', b'WS2_32.dll\x00', b'DllRegisterServer\x00', b'loaddll32.exe\x00', b'Shell32.dll\x00', b'Wininet.dll\x00', b'USER32.dll\x00', b'GetProcAddress', b'LoadLibraryA', b'IPHLPAPI.DLL\x00', b'https://azure-dbupdate.at/vuUwUx/FyNRoM/auth.php\x00', b'https://azure-updatedb.at/vuUwUx/FyNRoM/index.php\x00', b'VirtualFree', b'regsvr32.exe\x00', b'%PROCESSOR_LEVEL%'] /tmp/samples/4eb85a5532b98cbc4a6db1697cf46b9e2b7e28e89d6bbfc137b36c0736cd80e2.bin [b'rundll32.exe\x00', b'ztCYGAuJ\x00', b'Shlwapi.dll\x00', b'WS2_32.dll\x00', b'https://windowsdriverupdate.at/V.asp\x00', b'DllRegisterServer\x00', b'Microsoft Office/16.0 (Windows NT 10.0; Microsoft Outlook 16.0.13127; Pro)\x00', b'Shell32.dll\x00', b'Wininet.dll\x00', b'USER32.dll\x00', b'https://windowsdriverupdate.at/ZBEr.asp\x00', b'Dll Uinstall\x00', b'%PROCESSOR_LEVEL%\x00', b'https://driverwindowsupdate.at/V.asp\x00', b'UnregisterServer\x00', b'IPHLPAPI.DLL\x00', b'%PROCESSOR_REVISION%\\\x00', b'regsvr32.exe\x00', b'"C:\\Windows\\system32\\schtasks.exe" /Create /SC MINUTE /MO 1 /TN \x00'] /tmp/samples/10d5483faf9a4e0fbc17556164f47f7014650797b7d501289b269515a0853b64.bin [b'VirtualAlloc', b'Windows-Update-Agent/11.0.10011.16384 Client-Protocol/2.0\x00', b'rundll32.exe\x00', b'9npSEGB3kg9suo3Yit\x00', b'kernel32.dll', b'https://azure- dbupdate.at/vuUwUx/FyNRoM/index.php\x00', b'Shlwapi.dll\x00', b'WS2_32.dll\x00', b'DllRegisterServer\x00', b'loaddll32.exe\x00', b'Shell32.dll\x00', b'Wininet.dll\x00', b'USER32.dll\x00', b'GetProcAddress', b'LoadLibraryA', b'IPHLPAPI.DLL\x00', b'https://azure-dbupdate.at/vuUwUx/FyNRoM/auth.php\x00', b'https://azure-updatedb.at/vuUwUx/FyNRoM/index.php\x00', b'VirtualFree', b'regsvr32.exe\x00', b'%PROCESSOR_LEVEL%'] /tmp/samples/58a673023bbc7f2726e3b7ac917a43d9306692dc87b638ee21b98705a3262ccd.bin 17/32 [b'VirtualAlloc', b'Windows-Update-Agent/11.0.10011.16384 Client-Protocol/2.0\x00', b'rundll32.exe\x00', b'9npSEGB3kg9suo3Yit\x00', b'kernel32.dll', b'https://azure- dbupdate.at/vuUwUx/FyNRoM/index.php\x00', b'Shlwapi.dll\x00', b'WS2_32.dll\x00', b'DllRegisterServer\x00', b'loaddll32.exe\x00', b'Shell32.dll\x00', b'Wininet.dll\x00', b'USER32.dll\x00', b'GetProcAddress', b'LoadLibraryA', b'IPHLPAPI.DLL\x00', b'https://azure-dbupdate.at/vuUwUx/FyNRoM/auth.php\x00', b'https://azure-updatedb.at/vuUwUx/FyNRoM/index.php\x00', b'VirtualFree', b'regsvr32.exe\x00', b'%PROCESSOR_LEVEL%'] /tmp/samples/b9b399dbb5d901c16d97b7c30cc182736cd83a7c53313194a1798d61f9c7501e.bin [] /tmp/samples/fa6500946210334d397d612d5ee9b11456316e25672bc60c1267bbdb002af9c7.bin [b'VirtualAlloc', b'Windows-Update-Agent/11.0.10011.16384 Client-Protocol/2.0\x00', b'rundll32.exe\x00', b'9npSEGB3kg9suo3Yit\x00', b'kernel32.dll', b'https://azure- dbupdate.at/vuUwUx/FyNRoM/index.php\x00', b'Shlwapi.dll\x00', b'WS2_32.dll\x00', b'DllRegisterServer\x00', b'loaddll32.exe\x00', b'Shell32.dll\x00', b'Wininet.dll\x00', b'USER32.dll\x00', b'GetProcAddress', b'LoadLibraryA', b'IPHLPAPI.DLL\x00', b'https://azure-dbupdate.at/vuUwUx/FyNRoM/auth.php\x00', b'https://azure-updatedb.at/vuUwUx/FyNRoM/index.php\x00', b'VirtualFree', b'regsvr32.exe\x00', b'%PROCESSOR_LEVEL%'] /tmp/samples/60f030597c75f9df0f7a494cb5432b600d41775cfe5cf13006c1448fa3a68d8d.bin [b'VirtualAlloc', b'start dll HackCheck', b'http://collectiontelemetrysystem.com/m8YYdu/mCQ2U9/home.aspx\x00', b'https://telemetrysystemcollection.com/m8YYdu/mCQ2U9/auth.aspx\x00', b'rundll32.exe\x00', b'kernel32.dll', b'Shlwapi.dll\x00', b'WS2_32.dll\x00', b'DllRegisterServer\x00', b'loaddll32.exe\x00', b'Shell32.dll\x00', b'Wininet.dll\x00', b'USER32.dll\x00', b'GetProcAddress', b'Netapi32.dll\x00', b'LoadLibraryA', b'http://telemetrysystemcollection.com/m8YYdu/mCQ2U9/home.aspx\x00', b'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 10.0; Win64; x64; Trident/8.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729; Microsoft Outlook 16.0.5197; ms-office; MSOffice 16)\x00', b'IPHLPAPI.DLL\x00', b'Wkscli.dll\x00', b'https://telemetrysystemcollection.com/m8YYdu/mCQ2U9/home.aspx\x00', b'VirtualFree', b'https://collectiontelemetrysystem.com/m8YYdu/mCQ2U9/auth.aspx\x00', b'%PROCESSOR_LEVEL%'] /tmp/samples/e58b9bbb7bcdf3e901453b7b9c9e514fed1e53565e3280353dccc77cde26a98e.bin [b'C:\\Windows\\System32\\schtasks.exe\x00', b'rundll32.exe\x00', b' /TR "%windir%\\system32\\regsvr32.exe -e \x00', b'%ProgramData%\\\x00', b'Shlwapi.dll\x00', b'WS2_32.dll\x00', b'DllRegisterServer\x00', b'%PROGRAMFILES%\\Opera\\Opera.exe\x00', b'Shell32.dll\x00', b'Wininet.dll\x00', b'USER32.dll\x00', b'Dll Uinstall\x00', b'%COMPUTERNAME%\x00', b'https://manageintel.com/RKyiihqXQiyE/xukYadevoVow/BhJM.xml\x00', b'UnregisterServer\x00', b'IPHLPAPI.DLL\x00', b'https://manageintel.com/RKyiihqXQiyE/xukYadevoVow/QXms.xml\x00', b'.ocx\x00', b'regsvr32.exe\x00', b'%PROCESSOR_LEVEL%\\\x00', b'%PROCESSOR_REVISION%\x00'] /tmp/samples/a3c896e23c86e47bcb77096e743010546cd7699e0189344d11b9c642b89deef1.bin [b'VirtualAlloc', b'Windows-Update-Agent/11.0.10011.16384 Client-Protocol/2.0\x00', b'rundll32.exe\x00', b'9npSEGB3kg9suo3Yit\x00', b'kernel32.dll', b'https://azure- 18/32 dbupdate.at/vuUwUx/FyNRoM/index.php\x00', b'Shlwapi.dll\x00', b'WS2_32.dll\x00', b'DllRegisterServer\x00', b'loaddll32.exe\x00', b'Shell32.dll\x00', b'Wininet.dll\x00', b'USER32.dll\x00', b'GetProcAddress', b'LoadLibraryA', b'IPHLPAPI.DLL\x00', b'https://azure-dbupdate.at/vuUwUx/FyNRoM/auth.php\x00', b'https://azure-updatedb.at/vuUwUx/FyNRoM/index.php\x00', b'VirtualFree', b'regsvr32.exe\x00', b'%PROCESSOR_LEVEL%'] /tmp/samples/f27821dddb17b6c8d59fb2ada1e90eac8d561476e5af3a6be064177683b0eee9.bin [b'VirtualAlloc', b'Windows-Update-Agent/11.0.10011.16384 Client-Protocol/2.0\x00', b'rundll32.exe\x00', b'9npSEGB3kg9suo3Yit\x00', b'kernel32.dll', b'https://azure- dbupdate.at/vuUwUx/FyNRoM/index.php\x00', b'Shlwapi.dll\x00', b'WS2_32.dll\x00', b'DllRegisterServer\x00', b'loaddll32.exe\x00', b'Shell32.dll\x00', b'Wininet.dll\x00', b'USER32.dll\x00', b'GetProcAddress', b'LoadLibraryA', b'IPHLPAPI.DLL\x00', b'https://azure-dbupdate.at/vuUwUx/FyNRoM/auth.php\x00', b'https://azure-updatedb.at/vuUwUx/FyNRoM/index.php\x00', b'VirtualFree', b'regsvr32.exe\x00', b'%PROCESSOR_LEVEL%'] Sample Using ADV String Obfuscation A newer sample uses some type of ADV string obfuscation b9b399dbb5d901c16d97b7c30cc182736cd83a7c53313194a1798d61f9c7501e probably use our old dumpulator tricks for The start of the .text section contains a vtable with all of the string decryption functions. . We can this. 19/32 from dumpulator import Dumpulator, from dumpulator.native import * @syscall def ZwQueryVolumeInformationFile( ): return STATUS_SUCCESS dp = Dumpulator("/tmp/b9b.dmp", dp.start(dp.regs.eip, end=dp.read_ptr( functs = [0x74040976,0x740409A4,0x740409BA, for fn in functs: dp.call(fn,[]) str_tbl_start str_tbl_end = = 0x7407FDB4 0x7407FE7C str_tbl_start str_tbl_end = = 0x7407E000 0x74080224 for ptr in try: ss if except: continue range( = dp.read_str( len(ss print( str_tbl_start, ) > 4: ss) dp.read_ptr( syscall dp: Dumpulator, FileHandle: HANDLE, IoStatusBlock: P FsInformation: Length: ULONG, FsInformationClass: quiet=True) dp.regs.esp)) 0x74040998,0x7404098C, str_tbl_end,4): ptr)) (IO_STATUS_BLOCK), PVOID, FSINFOCLASS 0x7403F910,0x7403F91C,0x7403F9 20/32 Failed to read module data C:\Users\IEUser\Desktop\DLLLoader32_82D6.exe "C:\Users\IEUser\Desktop\DLLLoader32_82D6.exe" e03ed Uninstall 3fe11 Running exe Starting the exe with parameters Run CMD in memory Run PS in memory Running dll in memory #3 (DllInstall(Unstall)) Running dll in memory #3 (DllInstall(Install)) Regsvr32 & Execute MemLoadDllMain || MemLoadExe zNETjp 5deb9c Run EXE with admin rights TAMfm RunDll32 & Execute Crypt update & Bots upgrade Running dll in memory #2 (DllRegisterServer) tbesqn Different Sample From Same Family This is clearly a different sample based on the decrypted strings, but it seems to be part of the matanbuchus family... maybe this is a payload instead of a loader? The sample matches analysis from this blog: Introduction of a PE file extractor for various situations> We need to figure out why these samples are so different... Taking a Closer Look At Obfuscated Samples Obfuscated sample b9b399dbb5d901c16d97b7c30cc182736cd83a7c53313194a1798d61f9c7501e match yara (2021-11-12 11:47:44 UTC) Rony bd68ecd681b844232f050c21c1ea914590351ef64e889d8ef37ea63bd9e2a2ec doesn't match yara (2022-06-14 10:30:32 UTC) These samples appear to be the same (they are likely the "payload" portion of Matanbuchus) but the earlier sample uses obfuscated string encryption, while the newer sample uses the simpler stack based string encryption. Fixing our Yara Rule to Match the Stack Based String Encryption Payload (as well as loaders) - does - 21/32 This was a simple fix! The payload does not contain the murmur hash code, once we removed that the yara rule matched all samples. Let's Take a Look At the Obfusacated Strings We know that the one sample we have that is a "payload" will likely have some of the same strings as the obfuscated sample so let's pull these our first as a reference. 22/32 b'Content-Length: \x00' b'C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe \x00' b'collectiontelemetrysystem.com\x00' b'DllRegisterServer\x00' b'097f5m\x00' b'Running dll in memory #3 (DllInstall(Unstall))\x00' b'runas\x00' b'.exe\x00' b'timeout /t 3 && move /Y \x00' b'Running dll in memory #3 (DllInstall(Install))\x00' b'.exe\x00' b'.exe\x00' b'TiC7\x00' b'.nls\x00' b'Run PS in memory\x00' b'Admin\x00' b'%LOCALAPPDATA%\\\x00' b'DllInstall\x00' b'cmd.exe /c \x00' b'collectiontelemetrysystem.com\x00' b'Not in domain\x00' b'regsvr32.exe \x00' b'%PROCESSOR_REVISION%\\\x00' b'%APPDATA%\\\x00' b'41.4.0\x00' b'8QN04\x00' b'64 Bit\x00' b'8S2x\x00' b'Starting the exe with parameters\x00' b'C:\\Windows\\System32\\cmd.exe /c \x00' b'cmd.exe /c \x00' b'High start exe\x00' b'Running exe\x00' b'User-Agent: \x00' b'%PROCESSOR_REVISION%\\\x00' b'Content-Type: application/x-www-form-urlencoded\x00' b'%APPDATA%\\\x00' b'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\x00' b'\\explorer.exe\x00' b'MemLoadDllMain || MemLoadExe\x00' b'Run CMD in memory\x00' b'3CEk\x00' b'3m7x\x00' b'.nls\x00' b'%APPDATA%\\\x00' b'NCST \x00' b'BCha\x00' b"/c ECHO 'You must restart the program to resolve a critical error!' && start \x00" b'7eriel\x00' b'%APPDATA%\\\x00' b'.nls\x00' b'%PROCESSOR_REVISION%\\\x00' 23/32 b"\\'z{VIS\rA6\rb\x00" b'%LOCALAPPDATA%\\\x00' b'IsWow64Process\x00' b'rundll32.exe \x00' b'%PROCESSOR_REVISION%\\\x00' b'kernel32\x00' b'%PROCESSOR_REVISION%\\\x00' b'.nls\x00' b'User\x00' b'%PROCESSOR_REVISION%\\\x00' b'.nls\x00' b'\r\n\r\n\x00' b'\rXOGONSEzBER%\x00' b'%PROCESSOR_REVISION%\\\x00' b'\nost: \x00' b'MemLoadShellCode\x00' b'Q6X6\x00' b'timeout /t 3 && del \x00' b'cmd.exe\x00' b'%02X-%02X-%02X-%02X-%02X-%02X\x00' b'Running dll in memory #2 (DllRegisterServer)\x00' b'Crypt update & Bots upgrade\x00' b'timeout /t 3 && del \x00' b'3fe11\x00' b'%PROCESSOR_ARCHITECTURE%\x00' b'%PROCESSOR_ARCHITECTURE%\x00' b'NSeyDX\x00' b'%APPDATA%\\\x00' b'4nes\x00' b'jpofxs\x00' b'Not in domain\x00' b'DllInstall\x00' b' && rd /s /q \x00' b' && regsvr32.exe -e "\x00' b'32 Bit\x00' b'%USERDOMAIN%\x00' 24/32 from dumpulator import Dumpulator, from dumpulator.native import * import pefile @syscall def ZwQueryVolumeInformationFile( ): return STATUS_SUCCESS dp = Dumpulator("/tmp/b9b.dmp", dp.start(dp.regs.eip, end=dp.read_ptr( functs = [0x74040976,0x740409A4,0x740409BA, functs = [0x7403FC98] for fn in functs: dp.call(fn,[]) data_start data_end = for ptr in try: ss if except: continue = 0x7407E000 0x74080228 range(data_start,data_end, = dp.read_str(dp.read_ptr( len(ss) >= 4: print(ss) print("\n\n\n ===\n") print(dp.read_str( dp.read_ptr( syscall dp: Dumpulator, FileHandle: HANDLE, IoStatusBlock: P FsInformation: Length: ULONG, FsInformationClass: quiet=True) dp.regs.esp)) 0x74040998,0x7404098C, 4): ptr)) 0x7407FDFC ))) (IO_STATUS_BLOCK), PVOID, FSINFOCLASS 0x7403F910,0x7403F91C,0x7403F9 25/32 Failed to read module data C:\Users\IEUser\Desktop\DLLLoader32_82D6.exe "C:\Users\IEUser\Desktop\DLLLoader32_82D6.exe" Q6X6 zkC7 rJqU e03ed 3CEk Uninstall 3fe11 Running exe au5o Starting the exe with parameters 3m7x Run CMD in memory Run PS in memory Running dll in memory #3 (DllInstall(Unstall)) Running dll in memory #3 (DllInstall(Install)) Regsvr32 & Execute MemLoadDllMain || MemLoadExe b2tb hszA zNETjp 5deb9c DS2x Run EXE with admin rights TAMfm RunDll32 & Execute wgjv Crypt update & Bots upgrade f1da nX8y Running dll in memory #2 (DllRegisterServer) tbesqn === Running exe 26/32 FILE_PATH = '/tmp/samples/b9b399dbb5d901c16d97b7c30cc182736cd83a7c53313194a1798d61f9c7501e.bin' file_data = open(FILE_PATH,'rb') def xor_decrypt(data, key): out = [] for i in range(len(data)): out.append(data[i] ^ key return bytes(out) def is_ascii( return re data): .match(B"^[\s!-~]+\0 # .text:74049A7D C6 45 B8 0D mov byte ptr [ebp-48h], 13 # .text:74049A81 C7 45 E0 6E 60 69 23 mov dword ptr [ebp-20h], 2369606Eh # .text:74049A88 C7 45 E4 68 75 68 2D mov dword ptr [ebp-1Ch], 2D687568h # .text:74049A8F C7 45 E8 22 6E 2D 00 mov dword ptr [ebp-18h], 2D6E22h # .text:74049A96 C7 45 EC DA 4E 1E 00 mov dword ptr [ebp-14h], 1E4EDAh test_data = unhex('895db4c645b80dc745e06e606923c745e46875682dc745e8226e2d00c745ecda4e1e0052') stack_strings = [] string_egg = rb'(?P(?:\xC6\x45..){1} for m in re.finditer(string_egg, match_data = m.group(0) #print(tohex(match_data)) key = m['a'][3] raw_data = m['b'] str_data = b'' for i in range(0,len(raw_data), str_data += raw_data[i:i+ print(xor_decrypt(str_data, .read() [i%len(key)]) *$", data) is not None )(?P(?:\xC7\x45.....){2,})' file_data): 7): 7][-4:] bytes([key]))) 27/32 b'Shell32.dllR' b'Matanbuc' b' HTTP/1.' b'User-Agent: ' b'DllInsta' b'DllInsta' b'cmd.exe /c \x05\xdfK\x1b\x05' b' && rd /s /q' b'cmd.exe /c \r\xd7C\x13\r' # .text:7404406B C7 45 AC 71 5D 48 5D mov dword ptr [ebp-54h], 5D485D71h # .text:74044072 C7 45 B0 52 5E 49 5F mov dword ptr [ebp-50h], 5F495E52h # .text:74044079 C7 45 B4 54 49 4F 0A mov dword ptr [ebp-4Ch], 0A4F4954h # .text:74044080 66 C7 45 B8 0A 0A mov word ptr [ebp-48h], 0A0Ah # .text:74048CF5 C6 45 B8 31 mov byte ptr [ebp-48h], 31h ; '1' # .text:74048CF9 C7 45 E0 75 5D 5D 78 mov dword ptr [ebp-20h], 785D5D75h # .text:74048D00 C7 45 E4 5F 42 45 50 mov dword ptr [ebp-1Ch], 5045425Fh # .text:74048D07 66 C7 45 E8 5D 5D mov word ptr [ebp-18h], 5D5Dh # .text:74048D0D 88 5D EA mov [ebp-16h], bl # .text:74048D10 C7 45 EC DA 4E 1E 00 mov dword ptr [ebp-14h], 1E4EDAh # .text:740454A9 30 14 08 xor [eax+ecx], dl # .text:740454AC 41 inc ecx # .text:740454AD 83 F9 1D cmp ecx, 1Dh File "" 80 b0 d8 ff 07 74 a8 40 83 f8 06 ^ SyntaxError: invalid syntax , line 18 28/32 from dumpulator import Dumpulator, from dumpulator.native import * import pefile @syscall def ZwQueryVolumeInformationFile( ): return STATUS_SUCCESS dp = Dumpulator("/tmp/b9b.dmp", dp.start(dp.regs.eip, end=dp.read_ptr( start_addr end_addr = dp.start( dp.read(dp. Failed to read module data bytearray(b'193.56.146.60\\') = 0x74044390 0x740443C1 start_addr, regs.ebx, end=end_addr) 14) String Decryption Recap With these older samples, there are 3 different string decryption methods used Stack strings build with DWORDs that are decrypted using a single byte XOR, the byte is the first byte pushed onto the stack string (this is the same method used for small strings in the new samples) Global strings that are generated using constructors which have some light obfuscation. To deal with these we simply emulate all of the constructors and scrape the global strings from the The third and most complex method relies on two calls to functions used to build the encrypted string and then a simple single-byte XOR to decrypt the string. Complex Third String Decryption Method syscall dp: Dumpulator, FileHandle: HANDLE, IoStatusBlock: P(IO_STATUS_BLOCK), FsInformation: PVOID, Length: ULONG, FsInformationClass: FSINFOCLASS quiet=True) dp.regs.esp)) .data section of the PE. 29/32 c6 45 c4 53 57 6a 08 740458C7 .text:740436A5 BE DA 4E 1E 00 mov esi, 1E4EDAh .text:740436AA 89 9D 28 FF FF FF mov [ebp+var_D8], ebx .text:740436B0 89 9D 2C FF FF FF mov [ebp+var_D4], ebx BE DA ?? ?? ?? 89 ?? ?? ?? ?? ?? 89 .text:740480FF 89 5D B0 mov [ebp-50h], ebx .text:74048102 8B D3 mov edx, ebx .text:74048104 89 5D B4 mov [ebp-4Ch], ebx .text:74048107 89 5D B8 mov [ebp-48h], ebx .text:7404810A C6 45 BC 1A mov byte ptr [ebp-44h], 1Ah 89 ?? ?? 8b ?? 89 ?? ?? 89 ?? ?? c6 45 .text:740431A2 72 F7 jb short loc_7404319B .text:740431A4 88 59 0C mov [ecx+12], bl .text:740438E2 72 F7 jb short loc_740438DB .text:740438E4 88 59 0B mov [ecx+0Bh], bl 30/32 from dumpulator import Dumpulator, syscall from dumpulator.native import * import pefile @syscall def ZwQueryVolumeInformationFile(dp: Dumpulator, FileHandle: HANDLE, IoStatusBlock: P(IO_STATUS_BLOCK), FsInformation: PVOID, Length: ULONG, FsInformationClass: FSINFOCLASS ): return STATUS_SUCCESS def emulate(start_addr, end_addr, ret_reg, str_len): dp = Dumpulator("/tmp/b9b.dmp", quiet=True) dp.start(dp.regs.eip, end=dp.read_ptr(dp.regs.esp)) dp.start(start_addr, end=end_addr) return dp.read(dp.regs.__getitem__(ret_reg), str_len) pe = pefile.PE(data=file_data) em_egg = rb'\xBE\xDA...\x89.....\x89.+?(?=\x72\xf7\x88)' for m in re.finditer(em_egg, file_data): start_offset = m.start() end_offset = m.end() + 2 start_addr = pe.get_rva_from_offset(start_offset) + 0x74030000 end_addr = pe.get_rva_from_offset(end_offset) + 0x74030000 str_len = file_data[end_offset + 2] if file_data[end_offset + 1] == 0x5f: reg_name = 'edi' elif file_data[end_offset + 1] == 0x59: reg_name = 'ecx' print(f"Testing: {hex(start_addr)}") try: print(emulate(start_addr, end_addr, reg_name, str_len )) except: print("fail") continue 31/32 Testing: 0x74042f48 Failed to read module data bytearray(b'IPHLPAPI.DLL') Testing: 0x740430ce Failed to read module data bytearray(b'IPHLPAPI.DLL') Testing: 0x740436a5 Failed to read module data bytearray(b'\xfb\xcc\xf5\xfc\xd5i\xd2\t\xf7nz') Testing: 0x74043814 Failed to read module data bytearray(b'\x98\xe7\xe1\x13-\x0fo\xc0hUY') Testing: 0x74043991 Failed to read module data fail 32/32