Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@irshadqemu
Last active January 8, 2021 16:38
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save irshadqemu/ac67f55d7d4dc96d374ca0f800410f64 to your computer and use it in GitHub Desktop.
Save irshadqemu/ac67f55d7d4dc96d374ca0f800410f64 to your computer and use it in GitHub Desktop.
#!/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