Created
July 12, 2023 13:17
-
-
Save lbpierre/ad699298e09110727a959a0b0ba54d63 to your computer and use it in GitHub Desktop.
CustomerLoader AES key and C2 URL extraction
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import sys, struct, clr | |
clr.AddReference("System.Memory") | |
from System.Reflection import Assembly, MethodInfo, BindingFlags | |
from System import Type | |
import string | |
import hashlib | |
from base64 import b64decode | |
from itertools import combinations | |
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes | |
from cryptography.hazmat.primitives import padding | |
DNLIB_PATH = '/home/jovyan/work/utils/dnlib.dll' | |
clr.AddReference(DNLIB_PATH) | |
import dnlib | |
from dnlib.DotNet import * | |
from dnlib.DotNet.Emit import OpCodes | |
def decrypt(key: str, data: str) -> bytes: | |
"""decrypt CustomerLoader encrypted data""" | |
cleartext = b"" | |
try: | |
cipher = Cipher(algorithms.AES(key), modes.ECB()) | |
decryptor = cipher.decryptor() | |
cleartext = decryptor.update(data) | |
unpadder = padding.PKCS7(128).unpadder() | |
block = unpadder.update(cleartext) | |
end = unpadder.finalize() | |
cleartext = block + end | |
except Exception: | |
pass | |
return cleartext | |
def extract_base64_strings(PE_PATH: str) -> list: | |
""" """ | |
base64_set = string.ascii_letters + string.digits + "+/=" | |
def is_base64(data: str) -> bool: | |
return True if all(map(lambda x: x in base64_set, data)) else False | |
datas = [] | |
module = dnlib.DotNet.ModuleDefMD.Load(PE_PATH) | |
for mtype in module.GetTypes(): | |
for method in mtype.Methods: | |
for ptr in range(100): | |
try: | |
if method.Body.Instructions[ptr].OpCode.Name == "ldstr": | |
data = method.Body.Instructions[ptr].Operand | |
if is_base64(data) and data and len(data) > 16: | |
datas.append(data) | |
except Exception: | |
pass | |
return datas | |
def search_key_and_c2(strings: list) -> tuple: | |
"""As CustomerLoader does not embedded too much base64 strings, | |
this function generate all combinaison of pair of strings to attempts | |
decrypting strings until one starts by http:// or https:// meaning | |
the decryption works successfuly. | |
Nb: clearly note the clever approach...""" | |
for x, y in combinations(strings, 2): | |
try: | |
b64decode(x) | |
b64decode(y) | |
except Exception: | |
continue | |
data = decrypt(b64decode(x), b64decode(y)) | |
if data.startswith(b"http://") or data.startswith(b"https://"): | |
print(f"found AES key: `{x}` {data}") | |
key = x | |
c2 = data | |
return key, c2 | |
data = decrypt(b64decode(y), b64decode(x)) | |
if data.startswith(b"http://") or data.startswith(b"https://"): | |
print(f"found AES key: `{y}` {data}") | |
key = y | |
c2 = data | |
return key, c2 | |
return None, None | |
if __name__ == "__main__": | |
import sys | |
strings = extract_base64_strings(sys.argv[1]) | |
key, c2 = search_key_and_c2(strings) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment