Last active
January 8, 2021 16:38
-
-
Save irshadqemu/ac67f55d7d4dc96d374ca0f800410f64 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
#!/usr/bin/env python3 | |
# Name: | |
# unpack_emotet.py | |
# Description: | |
# This script accompanies my blog at | |
# https://mirshadx.wordpress.com/2020/11/22/analyzing-an-emotet-dropper-and-writing-a-python-script-to-statically-unpack-payload/ | |
# and can be used to statically unpack given sample in the blog | |
# Author: | |
# https://twitter.com/mirshadx | |
# https://www.linkedin.com/in/irshad-muhammad-3020b0a5/ | |
# | |
# PE carving code is adopted from https://github.com/MalwareLu/tools/blob/master/pe-carv.py | |
# | |
import pefile | |
from Crypto.Cipher import ARC4 | |
import re | |
# if you like, you can use commandline args for these arguments | |
EXE_PATH = "C:\\Users\\user\\Downloads\\tmp\\284.bin" | |
RC4_KEY = b"?UPLkTcdjlHrhAW\x00" | |
RESOURCE_NAME = "KITTKOF" | |
def get_resource_data(path_to_exe, resource_name): | |
"""Given a resource name extracts binary data for it""" | |
pe = pefile.PE(path_to_exe) | |
for rsrc in pe.DIRECTORY_ENTRY_RESOURCE.entries: | |
if str(rsrc.name) == resource_name: | |
print("Found the resource with name KITTOFF") | |
# Get IMAGE_RESOURCE_DATA_ENTRY for resource and extract data | |
data_struc = rsrc.directory.entries[0].directory.entries[0].data.struct | |
data_size = data_struc.Size | |
data_offset = data_struc.OffsetToData | |
print(f"Rosource Size: {hex(data_size)}, Resource Offset:{hex(data_offset)}") | |
rsrc_data = pe.get_memory_mapped_image()[data_offset: data_offset + data_size] | |
return rsrc_data | |
raise ValueError(f"Unable to find resource with name: {resource_name}") | |
def rc4_decrypt_data(enc_data, key): | |
"""RC4 decrypts the encrypted data""" | |
cipher = ARC4.new(RC4_KEY) | |
dec_data = cipher.decrypt(enc_data) | |
return dec_data | |
def get_extension(pe): | |
"""returns ext of the file type using pefile""" | |
if pe.is_dll(): | |
return ".dll_" | |
if pe.is_driver(): | |
return ".sys_" | |
if pe.is_exe(): | |
return ".exe_" | |
else: | |
return ".bin_" | |
def write_pe_file_disk(pe, c): | |
"""Writes a PE file to disk""" | |
trimmed_pe = pe.trim() | |
pe_name = str(c)+get_extension(pe) | |
out = open(pe_name, "wb") | |
out.write(trimmed_pe) | |
out.close() | |
print(f"PE file: {pe_name} written to disk") | |
def carve_pe_file(data_stream): | |
"""carve out pe file from binary data stream""" | |
c = 1 | |
for y in [tmp.start() for tmp in re.finditer(b"\x4d\x5a", data_stream)]: | |
location = y | |
try: | |
pe = pefile.PE(data=data_stream[y:]) | |
except: | |
print(f"MZ header found at {hex(y)} but failed to parse it as PE") | |
continue | |
print(f"Found PE at offset: {hex(y)}") | |
write_pe_file_disk(pe, c) | |
if __name__ == '__main__': | |
rsrc_data = get_resource_data(EXE_PATH, RESOURCE_NAME) | |
dec_data = rc4_decrypt_data(rsrc_data, RC4_KEY) | |
carve_pe_file(dec_data) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment