Skip to content

Instantly share code, notes, and snippets.

@usualsuspect
Last active June 21, 2022 14:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save usualsuspect/5dd6f77f0db59d229e7d8499a22d0928 to your computer and use it in GitHub Desktop.
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
#!/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