Overview

Sample: c7574aac7583a5bdc446f813b8e347a768a9f4af858404371eae82ad2d136a01

Unpacked: eeb13cd51faa7c23d9a40241d03beb239626fbf3efe1dbbfa3994fc10dea0827

References:

Helper Functions

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)

Load The Sample

import struct
import pefile

EMOTET_FILE = r'/tmp/emotet3.bin'
data = open(EMOTET_FILE, 'rb').read()
pe = pefile.PE(data = data)
txt_data = None
for s in pe.sections:
    if b'.text' in s.Name:
        txt_data = s.get_data()
print(txt_data[:100])
b'\x03\xf2y\x1a\x0e\xf2y\x1aF\xb1:JV\xb05S@\xb05UA\x90\x13\xa3\x91\x9f&\\\xccr\xbf\xa6\x021\x91H\xa5=\x96\x07\x00\x00\x00\x00\x00\x00\x00\x00<n\xbf\x19 n\xbf\x19q\x07\xdckS\x1d\xd0\x7fHN\xefkU\x03\xd6mU\x18\xda9l\x1c\xd0oU\n\xdak,Gd>\xc0I\xbd\x9a\x9d>(\xc2g\xd3\x03\xdb'

Decrypt Strings Table

def xor_decrypt(data, key):
    out = []
    for i in range(len(data)):
        out.append(data[i] ^ key[i%len(key)])
    return bytes(out)


def is_ascii(s):
    return all(c < 128 for c in s)

strings_table = []
ECS1_string = None
ECK1_string = None
for i in range(0,0x1000,4):
    candidate_1 = struct.unpack('<I',txt_data[i:i+4])[0] 
    candidate_2 = struct.unpack('<I',txt_data[i+4:i+8])[0] 
    if (candidate_1  & 0xffffff00) ^ (candidate_2 & 0xffffff00) == 0:
        # We have a match!
        key = txt_data[i:i+4]
        data_len = candidate_1 ^ candidate_2
        enc_data = txt_data[i+8:i+8+data_len]
        ptxt_data = xor_decrypt(enc_data, key)
        if is_ascii(ptxt_data):
            if ptxt_data != b'':
                strings_table.append(ptxt_data.decode('latin1'))
        if b'ECS1' == ptxt_data[:4]:
            ECS1_string = ptxt_data
        if b'ECK1' == ptxt_data[:4]:
            ECK1_string = ptxt_data

# Print our strings
print(ECS1_string)
print(ECK1_string)
for s in strings_table:
    print(s)
b"ECS1 \x00\x00\x00\xf4/\x1a\x836\x1a'Q\x8c$\xf2\xca\xa8\xec\x85\xaeRYQuH\x94\x06p\x02s\xaa\xe8\x9a\xc4({V\t\x0f\xbc\x08{\x80!z\xa6(~\x96E\xb9\xc3\xc3\\&t\xcf\xd8\xbe\xa2\x85\x1f~\xa7\xa8-\x954"
b'ECK1 \x00\x00\x00\xd85\x93\xd7c\x8bP\xc5\xdf\xcd\xe1i\xf9\xb16\x00\x9b\x9bT;\x166\xa2]D.\xb280\xd8G6.\xb8\xd2\xf4\x8bj\xc8\xd8LzED\x1a\x06\xfa\x8f8\xbe\xda\xfb\x00\x96\x9c\x84,\xce\x1e6\x80$P\x96'
ECCPUBLICBLOB
Microsoft Primitive Provider
SHA256
ObjectLength
ECDSA_P256
HASH
AES
ECDH_P256
KeyDataBlob
%s\%s
%s\*
%s:Zone.Identifier
%s\%s.exe
Cookie: %s=%s


--%S--
%u.%u.%u.%u
Content-Type: multipart/form-data; boundary=%s


--%S
Content-Disposition: form-data; name="%S"; filename="%S"
Content-Type: application/octet-stream


%s\%s
%s\rundll32.exe "%s\%s",%s
SOFTWARE\Microsoft\Windows\CurrentVersion\Run
Control_RunDLL
%s\%s%x
%s\rundll32.exe "%s\%s",%s %s
%s\rundll32.exe "%s",Control_RunDLL
POST
userenv.dll
shell32.dll
bcrypt.dll
crypt32.dll
wtsapi32.dll
urlmon.dll
shlwapi.dll
wininet.dll
advapi32.dll
%s_%08X
%s%s.dll
%s%s.exe
DllRegisterServer
%s\regsvr32.exe -s "%s"
%s\rundll32.exe "%s",Control_RunDLL %s
%s\rundll32.exe "%s",Control_RunDLL
WinSta0\Default
RNG
print(ECS1_string)
print(ECK1_string)

# Extract ECS1 key
ECS1_key_len = struct.unpack('<I',ECS1_string[4:8])[0]
ECS1_x = int.from_bytes(ECS1_string[8:8+ECS1_key_len], "big")
ECS1_y = int.from_bytes(ECS1_string[8+ECS1_key_len:], "big")

from Crypto.PublicKey import ECC
ECS1_key = ECC.construct(curve="p256", point_x=ECS1_x, point_y=ECS1_y)
print("\nECS1 Key")
print(ECS1_key.export_key(format="PEM"))

# Extract ECK1 key
ECK1_key_len = struct.unpack('<I',ECK1_string[4:8])[0]
ECK1_x = int.from_bytes(ECK1_string[8:8+ECK1_key_len], "big")
ECK1_y = int.from_bytes(ECK1_string[8+ECK1_key_len:], "big")

from Crypto.PublicKey import ECC
ECK1_key = ECC.construct(curve="p256", point_x=ECK1_x, point_y=ECK1_y)
print("\nECK1 Key")
print(ECK1_key.export_key(format="PEM"))
b"ECS1 \x00\x00\x00\xf4/\x1a\x836\x1a'Q\x8c$\xf2\xca\xa8\xec\x85\xaeRYQuH\x94\x06p\x02s\xaa\xe8\x9a\xc4({V\t\x0f\xbc\x08{\x80!z\xa6(~\x96E\xb9\xc3\xc3\\&t\xcf\xd8\xbe\xa2\x85\x1f~\xa7\xa8-\x954"
b'ECK1 \x00\x00\x00\xd85\x93\xd7c\x8bP\xc5\xdf\xcd\xe1i\xf9\xb16\x00\x9b\x9bT;\x166\xa2]D.\xb280\xd8G6.\xb8\xd2\xf4\x8bj\xc8\xd8LzED\x1a\x06\xfa\x8f8\xbe\xda\xfb\x00\x96\x9c\x84,\xce\x1e6\x80$P\x96'

ECS1 Key
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE9C8agzYaJ1GMJPLKqOyFrlJZUXVI
lAZwAnOq6JrEKHtWCQ+8CHuAIXqmKH6WRbnDw1wmdM/YvqKFH36nqC2VNA==
-----END PUBLIC KEY-----

ECK1 Key
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE2DWT12OLUMXfzeFp+bE2AJubVDsW
NqJdRC6yODDYRzYuuNL0i2rI2Ex6RUQaBvqPOL7a+wCWnIQszh42gCRQlg==
-----END PUBLIC KEY-----

C2 Ground Truth

81.0.236.93:443

data_data = None
for s in pe.sections:
    if b'.data' in s.Name:
        data_data = s.get_data()
print(data_data[:100])

key = data_data[:4]
data_len = struct.unpack('<I',data_data[:4])[0] ^ struct.unpack('<I',data_data[4:8])[0]
enc_data = data_data[8:8+data_len]
ptxt_data = xor_decrypt(enc_data, key)

print(tohex(ptxt_data))

print("\n== C2 List== ")
for i in range(0,len(ptxt_data),8):
    print("%d.%d.%d.%d:%d" % (ptxt_data[i+0],ptxt_data[i+1],ptxt_data[i+2],ptxt_data[i+3],struct.unpack('>H',ptxt_data[i+4:i+6])[0]))
b'5\x84\xe9?\x95\x84\xe9?\x066\xd4\x034?\xe9>\x9dA\x1315\xd4\xe9>\x18\xcb\xc8\x0f*\x14\xe9>\xf1\xa8\x8b\x81*\x14\xe9>\x84\xcc\xb91.,\xe9>\x06V\x1b\xd5*\x14\xe9>\x8c\x10@5*\x14\xe9>\xbb\x802\x92*\x14\xe9>{\xab%o4?\xe9>{\xaa\xa0B4?\xe9>\x10\xa8\x1d\x8e*\x14\xe9>\x10\xbf8\xb2'
b'33b23d3c01bb0001a8c5fa0e005000012d4f21301f900001c42c62be1f900001b148500e1ba8000133d2f2ea1f900001b994a90a1f9000018e04dbad1f9000014e2fcc5001bb00014e2e497d01bb0001252cf4b11f900001253bd18d1f900001bffc6710005000013626f2b901bb000155d643cb1f9000013625e47a01bb0001cf9451771f900001c34def271f900001422a399501bb0001c39a922301bb0001'

== C2 List== 
51.178.61.60:443
168.197.250.14:80
45.79.33.48:8080
196.44.98.190:8080
177.72.80.14:7080
51.210.242.234:8080
185.148.169.10:8080
142.4.219.173:8080
78.47.204.80:443
78.46.73.125:443
37.44.244.177:8080
37.59.209.141:8080
191.252.103.16:80
54.38.242.185:443
85.214.67.203:8080
54.37.228.122:443
207.148.81.119:8080
195.77.239.39:8080
66.42.57.149:443
195.154.146.35:443