<jupyter_start><jupyter_text>Matanbuchus Triage Notes> Matanbuchus loader triage and yara rule- toc: true - badges: true- categories: [Matanbuchus,loader,yara,triage,dumpulator,emulation] ![](https://cdn.discordapp.com/attachments/885652495421030431/988186871660183612/a_horse.png) OverviewMatanbuchus 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](https://twitter.com/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.![](https://isc.sans.edu/diaryimages/images/2022-06-17-ISC-diary-image-00a.jpg) References - [Malspam pushes Matanbuchus malware, leads to Cobalt Strike](https://isc.sans.edu/forums/diary/Malspam+pushes+Matanbuchus+malware+leads+to+Cobalt+Strike/28752/)- [Not Packed (UnpacMe)](https://www.unpac.me/results/7166936d-dcd6-40ed-9d15-0151953e46ff/)- [f8cc2cf36e193774f13c9c5f23ab777496dcd7ca588f4f73b45a7a5ffa96145e](https://malshare.com/sample.php?action=detail&hash=f8cc2cf36e193774f13c9c5f23ab777496dcd7ca588f4f73b45a7a5ffa96145e)- [Matanbuchus: Malware-as-a-Service with Demonic Intentions](https://unit42.paloaltonetworks.com/matanbuchus-malware-as-a-service/)- [A deal with the devil: Analysis of a recent Matanbuchus sample](https://medium.com/@DCSO_CyTec/a-deal-with-the-devil-analysis-of-a-recent-matanbuchus-sample-3ce991951d6a)- [MATANBUCHUS: Another Loader As A Service Malware](https://www.0ffset.net/reverse-engineering/matanbuchus-loader-analysis/)- [List of known versions of Windows DLLs](https://winbindex.m417z.com/?file=ntdll.dll)  Analysis- The DLL has an export called `HackCheck` that uses OutputDebugStringA to print `start dll HackCheck` - The sample uses API hashing with FNV1a hash algo to resolve API calls  Yara RuleThis yara rule is very brittle and needs lots of testing/refining```rule diceloader {    meta:        description = "Identifies diceloader"           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*)}``` String Decryption Simple DecryptionSome 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.<jupyter_code>import struct

data = b'jl8|tt8Py{s[p}{s'
key = struct.pack('<I',<KEY>)
data = key[1:] + data
out = []


for i in data:
    out.append(i ^ key[0])

bytes(out)



def unhex(hex_string):
    import binascii
    if type(hex_string) == str:
        return binascii.unhexlify(hex_string.encode('utf-8'))
    else:
        return binascii.unhexlify(hex_string)

def tohex(data):
    import binascii
    if type(data) == str:
        return binascii.hexlify(data.encode('utf-8'))
    else:
        return binascii.hexlify(data)<jupyter_output><empty_output><jupyter_text>Complex DecryptionOther strings are also build from stack strings in a function and returned in a buffer, but these strings are decrypted with a second function call to a decryption function. To handle these more complex strings, we will use [dumpulator](https://github.com/mrexodia/dumpulator)<jupyter_code>from dumpulator import Dumpulator
import struct
import re
import pefile

file_data = open('/tmp/mat.bin','rb').read()
pe = pefile.PE(data=file_data)






dp = Dumpulator("/tmp/mat.dmp", quiet=True)
fn_get_string = 0x708641C0
ss_start = 0x708631B2
ss_end = 0x708632AA 

dp.start(ss_start, end=ss_end)

ss = dp.read(dp.regs.ebp-0x50, 0x48)




ss = bytes(ss)[:0x3e]

buff = dp.allocate(0x3e)
dp.write(buff, ss)
fn_dec_str = 0x7086F3D0 

dp.call(fn_dec_str, [buff, 0x3e, 0x0, 0x7ebbfa3, 0x1010101])
dp.read(buff,0x3e)<jupyter_output>Failed to read module data<jupyter_text>Dumpulator NotesThe DLL uses thread safe functions that require a call into `EnterCriticalSection` and `LeaveCriticalSection`. Because our dump was taken before the DLL was initialized the critical section object was not initialized and this causes Dumpulator to crash.First we tried just calling the initialization function in the DLL to setup this object (also tried calling the wrapper functions for `InitializeCriticalSectionEx`) but these all led to crashes (we could implement some syscalls and try again but we are lazy!Our solution is to just patch out the `EnterCriticalSection` and `LeaveCriticalSection` calls in the loaded `ntdll` using a simple return 0.```33 C0     xor eax,eaxC2 04 00  ret 4``` Dumpulator Patching Out Functions<jupyter_code>dp = Dumpulator("/tmp/mat.dmp", quiet=True)

ntdll_start = 0x77a10000


patch_bytes = b'\x33\xC0\xC2\x04\x00'

ptr_RtlLeaveCriticalSection = 0x77A5FFF0
ptr_RtlEnterCriticalSection = 0x77A5FDF0

get_str_fn = 0x70861000

#tohex(dp.read(ntdll_init_crit_sec,10))

dp.write(ptr_RtlLeaveCriticalSection, patch_bytes)
dp.write(ptr_RtlEnterCriticalSection, patch_bytes)



dp.call(get_str_fn)<jupyter_output>Failed to read module data
unmapped read from 8[4], cip = 77a6693a
error: Invalid memory read (UC_ERR_READ_UNMAPPED), cip = 77a6693a<jupyter_text>Dumpulator Implementing Syscalls to Load DLLOur patching method sort of worked but there is other initializations stuff that was causing more crashes. We are going to try and just implement the syscalls that we need to actually emulate the full DLL load routine and see if that works better.<jupyter_code>from dumpulator import Dumpulator, syscall
from dumpulator.native import *

@syscall
def ZwQueryVolumeInformationFile(dp: Dumpulator,
                                 FileHandle: HANDLE,
                                 IoStatusBlock: P(IO_STATUS_BLOCK),
                                 FsInformation: PVOID,
                                 Length: ULONG,
                                 FsInformationClass: FSINFOCLASS
                                 ):
    return STATUS_SUCCESS



dp = Dumpulator("/tmp/mat2.dmp", quiet=True)

dll_base_addr = 0x71950000

dp.start(dp.regs.eip, end=dp.read_ptr(dp.regs.esp))


get_str_fn = 0x71951000
dp.read_str(dp.call(get_str_fn))<jupyter_output>Failed to read module data<jupyter_text>Finding Encrypted Stack Strings<jupyter_code>egg = rb'(\xC6\x45..){4}'

egg = rb'\x55\x8b\xec\x83\xec\x08\x33\xc0\x88\x45\xff'

stack_string_offsets = []
for m in re.finditer(egg, file_data):
    fn_offset = m.start()
    fn_addr = pe.get_rva_from_offset(fn_offset) + dll_base_addr
    tmp_str = dp.read_str(dp.call(fn_addr))
    print(tmp_str)<jupyter_output>https://telemetrysystemcollection.com/m8YYdu/mCQ2U9/auth.aspx
https://collectiontelemetrysystem.com/m8YYdu/mCQ2U9/auth.aspx
DllRegisterServer
http://collectiontelemetrysystem.com/m8YYdu/mCQ2U9/home.aspx
http://telemetrysystemcollection.com/m8YYdu/mCQ2U9/home.aspx
https://telemetrysystemcollection.com/m8YYdu/mCQ2U9/home.aspx
{'fraction_non_alphanumeric': 0.087893864013267, 'fraction_numerical': 0.05549177190968236, 'mean_word_length': 3.467236467236467, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 20, 'https://': 14, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 18, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '5', 'dir': 'jupyter-structured-clean-dedup', 'id': '605701', 'license': 'Apache-2.0', 'n_tokens_mistral': 2934, 'n_tokens_neox': 2572, 'n_words': 705, 'path': '_notebooks/2022-06-19-matanbuchus-triage.ipynb', 'repo_name': 'OALabs/research', 'size': '7844'}