Mirror of metasploit
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

mdns.rb 3.0KB

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