Last active
June 21, 2022 14:50
-
-
Save usualsuspect/5dd6f77f0db59d229e7d8499a22d0928 to your computer and use it in GitHub Desktop.
Extract xor-encrypted archives from docx files as used by RemoteDllLoader in SVCReady execution chains
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
#!/usr/bin/env python3 | |
# | |
# Author: @jaydinbas | |
# | |
# Extract xor-encrypted archives from docx files as used by | |
# RemoteDllLoader in SVCReady execution chains | |
# | |
import sys | |
import zipfile | |
import struct | |
if len(sys.argv) != 3: | |
print("usage: %s <docx> <outfile>" % sys.argv[0]) | |
sys.exit(0) | |
def dword(data,off): | |
return struct.unpack_from("<I",data[off:])[0] | |
def decode_archive(data): | |
data = bytearray(data) | |
key_len = dword(data,4) | |
payload_len = dword(data,8) | |
#print("Key length: %d" % key_len) | |
#print("Payload length: %d" % payload_len) | |
key_off = 12 | |
payload_off = 12+key_len | |
for i in range(payload_len): | |
data[payload_off+i] ^= data[key_off+(i % key_len)] | |
return data[payload_off:payload_off+payload_len] | |
try: | |
zf = zipfile.ZipFile(sys.argv[1]) | |
except: | |
print("Not a .docx") | |
sys.exit(0) | |
for fn in zf.namelist(): | |
if fn.find("/") != -1: | |
continue | |
if fn == "[Content_Types].xml": | |
continue | |
# this should only be reached for archives | |
data = zf.read(fn) | |
if len(data) < 12: | |
print("Error: Data too short for %s" % fn) | |
continue | |
if dword(data,4) + dword(data,8) + 12 != len(data): | |
print("Error: Length mismatch for %s" % fn) | |
continue | |
print("Archive found: %s" % fn) | |
decoded = decode_archive(data) | |
open(sys.argv[2],"wb").write(decoded) | |
print("Archive decoded to %s" % sys.argv[2]) | |
break | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment