metasploit-framework/lib/msf/core/auxiliary/mdns.rb

109 lines
3.0 KiB
Ruby

# -*- coding: binary -*-
require 'net/dns'
module Msf
# This module provides methods for working with mDNS
module Auxiliary::MDNS
# Initializes an instance of an auxiliary module that uses mDNS
def initialize(info = {})
super
register_options(
[
OptAddressRange.new('RHOSTS', [true, 'The multicast address or CIDR range of targets to query', '224.0.0.251']),
Opt::RPORT(5353),
OptString.new('NAME', [true, 'The name to query', '_services._dns-sd._udp.local']),
OptString.new('TYPE', [true, 'The query type (name, # or TYPE#)', 'PTR']),
OptString.new('CLASS', [true, 'The query class (name, # or CLASS#)', 'IN'])
],
self.class
)
end
def setup
query_class_name
query_type_name
end
def build_probe
@probe ||= ::Net::DNS::Packet.new(query_name, query_type_num, query_class_num).data
# TODO: support QU vs QM probes
# @probe[@probe.size-2] = [0x80].pack('C')
# @probe
end
def query_class
if datastore['CLASS'] =~ /^\d+$/
datastore['CLASS'].to_i
else
datastore['CLASS'].upcase
end
end
def query_class_name
Net::DNS::RR::Classes.new(query_class).to_s
end
def query_class_num
Net::DNS::RR::Classes.new(query_class).to_i
end
def query_type
if datastore['TYPE'] =~ /^\d+$/
datastore['TYPE'].to_i
else
datastore['TYPE'].upcase
end
end
def query_name
datastore['NAME']
end
def query_type_name
Net::DNS::RR::Types.new(query_type).to_s
end
def query_type_num
Net::DNS::RR::Types.new(query_type).to_i
end
def describe_response(response)
decoded = Resolv::DNS::Message.decode(response)
answers = decoded.answer
if answers.empty? # not sure this will ever happen...
"no answers"
else
# there are often many answers for the same RR, so group them
grouped_answers = answers.group_by { |name, _, _| name }
# now summarize each group by noting the resource type and the notable
# part(s) of that RR
summarized_answers = grouped_answers.map do |name, these_answers|
summarized_group = these_answers.map do |_, _, data|
case data
when Resolv::DNS::Resource::IN::A
"A #{data.address}"
when Resolv::DNS::Resource::IN::AAAA
"AAAA #{data.address}"
when Resolv::DNS::Resource::IN::PTR
"PTR #{data.name}"
when Resolv::DNS::Resource::IN::SRV
"SRV #{data.target}"
when Resolv::DNS::Resource::IN::TXT
"TXT #{data.strings.join(',')}"
else
data.inspect
end
end
"#{name}: (#{summarized_group.join(", ")})"
end
summarized_answers.join(', ')
end
end
def request_info
"#{query_name} #{query_class}/#{query_type}"
end
end
end