CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/lib/msf/core/auxiliary/mdns.rb
Views: 1904
1
# -*- coding: binary -*-
2
require 'net/dns'
3
4
module Msf
5
# This module provides methods for working with mDNS
6
module Auxiliary::MDNS
7
# Initializes an instance of an auxiliary module that uses mDNS
8
def initialize(info = {})
9
super
10
register_options(
11
[
12
OptAddressRange.new('RHOSTS', [true, 'The multicast address or CIDR range of targets to query', '224.0.0.251']),
13
Opt::RPORT(5353),
14
OptString.new('NAME', [true, 'The name to query', '_services._dns-sd._udp.local']),
15
OptString.new('TYPE', [true, 'The query type (name, # or TYPE#)', 'PTR']),
16
OptString.new('CLASS', [true, 'The query class (name, # or CLASS#)', 'IN'])
17
],
18
self.class
19
)
20
end
21
22
def setup
23
query_class_name
24
query_type_name
25
end
26
27
def build_probe
28
@probe ||= ::Net::DNS::Packet.new(query_name, query_type_num, query_class_num).data
29
# TODO: support QU vs QM probes
30
#+ @probe[@probe.size-2] = [0x80].pack('C')
31
#+ @probe
32
end
33
34
def query_class
35
if datastore['CLASS'] =~ /^\d+$/
36
datastore['CLASS'].to_i
37
else
38
datastore['CLASS'].upcase
39
end
40
end
41
42
def query_class_name
43
Net::DNS::RR::Classes.new(query_class).to_s
44
end
45
46
def query_class_num
47
Net::DNS::RR::Classes.new(query_class).to_i
48
end
49
50
def query_type
51
if datastore['TYPE'] =~ /^\d+$/
52
datastore['TYPE'].to_i
53
else
54
datastore['TYPE'].upcase
55
end
56
end
57
58
def query_name
59
datastore['NAME']
60
end
61
62
def query_type_name
63
Net::DNS::RR::Types.new(query_type).to_s
64
end
65
66
def query_type_num
67
Net::DNS::RR::Types.new(query_type).to_i
68
end
69
70
def describe_response(response)
71
decoded = Resolv::DNS::Message.decode(response)
72
answers = decoded.answer
73
74
if answers.empty? # not sure this will ever happen...
75
"no answers"
76
else
77
# there are often many answers for the same RR, so group them
78
grouped_answers = answers.group_by { |name, _, _| name }
79
# now summarize each group by noting the resource type and the notable
80
# part(s) of that RR
81
summarized_answers = grouped_answers.map do |name, these_answers|
82
summarized_group = these_answers.map do |_, _, data|
83
case data
84
when Resolv::DNS::Resource::IN::A
85
"A #{data.address}"
86
when Resolv::DNS::Resource::IN::AAAA
87
"AAAA #{data.address}"
88
when Resolv::DNS::Resource::IN::PTR
89
"PTR #{data.name}"
90
when Resolv::DNS::Resource::IN::SRV
91
"SRV #{data.target}"
92
when Resolv::DNS::Resource::IN::TXT
93
"TXT #{data.strings.join(',')}"
94
else
95
data.inspect
96
end
97
end
98
"#{name}: (#{summarized_group.join(", ")})"
99
end
100
summarized_answers.join(', ')
101
end
102
end
103
104
def request_info
105
"#{query_name} #{query_class}/#{query_type}"
106
end
107
end
108
end
109
110