Dbatloader is a simple loader that is used to download and execute a payload. It is very small and written in delphi. The sample we are looking at is the second? stage, likely the first stages are some sort of document chain. From OSINT we expect that this stage is simply used to download a third stage which will contain the payload as a resource.


  • Packed Parent 5be5708b720b520f2292ec10196f47ff3a687843a529540d75c0d7621fad247e malshare
  • Unpacked payload dc5ec82e7cb2590ae612a2dd7203ae3a81662707377f2be44c94378ef0b0d3b0 malshare



C2 Extraction

The packed payload actually contains the C2s which are accessed by the unpacked payload. This is done via a hard-coded delimiter in the unpacked child. In our sample there are two identical C2 URLs using the delimters ^^Nc, and Ymo_^. The child will open the parent and search for a string that is sandwiched between the delimiter. Once the string has been extracted it is decrypted using a simple add/mod algorithm with a hard coded number. In our sample the number is 217.

def unhex(hex_string):
    import binascii
    if type(hex_string) == str:
        return binascii.unhexlify(hex_string.encode('utf-8'))
        return binascii.unhexlify(hex_string)
c2_data = unhex('2F 3B 3B 37 3A 01 F6 F6 36 35 2C 2B 39 30 3D 2C F5 33 30 3D 2C F5 2A 36 34 F6 2B 36 3E 35 33 36 28 2B 06 2A 30 2B 04 0C 08 0C 00 F7 F7 00 F8 FB FA 0D FE 0A FB F9 F7 ED 39 2C 3A 30 2B 04 0C 08 0C 00 F7 F7 00 F8 FB FA 0D FE 0A FB F9 F7 EC F9 F8 F8 F9 FE ED 28 3C 3B 2F 32 2C 40 04 08 09 18 09 13 15 21 2D F7 FC 16 11 2F 41 2A E7 E7'.replace(' ',''))
delim = b'^^Nc'

def addit(data, key):
    out = []
    for c in data:
        out.append((c + (0x112 % key))&0xff)
    return bytes(out)

b'https://onedrive.live.com/download?cid=EAE9009143F7C420&resid=EAE9009143F7C420%21127&authkey=ABQBLNZf05OJhzc  '

Parsing Downloaded Data

The downloaded data is a complex encrypted structure that must be parsed before the Stage3 binary can be extracted. An ecrypted version of the data can be downloaded from Malshare here: 7fac3d9c98127d11ce69c3130dbbd6a876e1ae37c80304516cc8dd675423b9f2.

The downloaded data is first decrypted ysing a simple add/sub algorithm using the same hard coded key as the C2 decryption routine. In our sample this key was 217. Once decrypted the data is inverted and split using a hard coded delimiter. In our sample the delimiter is is a string starting with *()%@5YT....

data = open('/tmp/stage3.bin', 'rb').read()
key = 217

out = []
for c in data:
    if c & 1 != 0:
        out.append((c + key) & 0xff)
        out.append((c - key) & 0xff)

out = bytes(out)
out = out[::-1]

delim = b'*()%@5YT!@#G__T@#$%^&*()__#@$#57$#!@'

out_sections = out.split(delim)

for s in out_sections:










Stage3 Extraction

Once the data has been split into sections the second section is used as a key to decrypt the forth section, which contains the Stage3 payload. In our sample there were 10 sections in total and the first section was skipped entirly and contained no data. The decryption routine is a simple xor with the key, and the key, and data lengths (unusual).

Once the Stage3 payload has been decrypted it is inverted, then decrypted a second time using the same add/mod algorithm that was used to decrypt the C2 URLs. The decryption key is located in the tenth section. In our sample this key matched the hard coded C2 key in Stage2 217.

The decrypted Stage3 payload is then inverted again and passed through a final decryption algorythm that was refered to as decrypt_yak in this blog post and reproduced in Python (our graditute <3).

A decrypted Stage3 payload can be downloaded from Malshare here: 05962419fba7b3b2b2fee77365db12e71d33d2919db5e1c162f2211398b7c8d2

key = out_sections[1]
key_len = len(key)

payload_data = out_sections[3]
payload_data_len = len(payload_data)

out = []
key_count = 0
for i in range(payload_data_len):
    tmp_byte = (payload_data[i] ^ payload_data_len ) & 0xff
    out.append((key[key_count]  ^ key_len ^ tmp_byte ) & 0xff)
    key_count = (key_count + 1) % key_len

payload_out = bytes(out)

payload_out_dec = addit(payload_out, 217)

payload_out_dec = payload_out_dec[::-1]

def decrypt_yak(data):
    implements the first decryption layer of function 0x416408
    res = bytearray(data)
    for i, c in enumerate(data):
        if 0x21 <= c <= 0x7e:
            res[i] = ((((c + 0xe) % 0x5e) + 0x21) & 0xff)
    return bytes(res)

final_payload = decrypt_yak(payload_out_dec)

b'MZP\x00\x02\x00\x00\x00\x04\x00\x0f\x00\xff\xff\x00\x00\xb8\x00\x00\x00\x00\x00\x00\x00@\x00\x1a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\xba\x10\x00\x0e\x1f\xb4\t\xcd!\xb8\x01L\xcd!\x90\x90This program must be run under Win32\r\n$7\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00PE\x00\x00L\x01\x02\x00\xc0\x1b\xc4+\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x8f\x81\x0b\x01\x04 \x00$\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x17\x15\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00S\x00\x00\x10\x00\x00\x00\x02\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00P\x02\x00\x00\x04\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x10\x00\x00\x00\x01\x00\x00\x00\x10\x00\x00\x00\x01\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00@\x02\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'