Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/auxiliary/scanner/portscan/xmas.rb
21367 views
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
class MetasploitModule < Msf::Auxiliary
7
include Msf::Exploit::Capture
8
include Msf::Auxiliary::Scanner
9
include Msf::Auxiliary::Report
10
11
def initialize
12
super(
13
'Name' => 'TCP "XMas" Port Scanner',
14
'Description' => %q{
15
Enumerate open|filtered TCP services using a raw
16
"XMas" scan; this sends probes containing the FIN,
17
PSH and URG flags.
18
},
19
'Author' => 'kris katterjohn',
20
'License' => MSF_LICENSE
21
)
22
23
register_options([
24
OptString.new('PORTS', [true, "Ports to scan (e.g. 22-25,80,110-900)", "1-10000"]),
25
OptInt.new('TIMEOUT', [true, "The reply read timeout in milliseconds", 500]),
26
OptInt.new('BATCHSIZE', [true, "The number of hosts to scan per set", 256]),
27
OptInt.new('DELAY', [true, "The delay between connections, per thread, in milliseconds", 0]),
28
OptInt.new('JITTER', [true, "The delay jitter factor (maximum value by which to +/- DELAY) in milliseconds.", 0]),
29
OptString.new('INTERFACE', [false, 'The name of the interface'])
30
])
31
32
deregister_options('FILTER', 'PCAPFILE')
33
end
34
35
# No IPv6 support yet
36
def support_ipv6?
37
false
38
end
39
40
def run_batch_size
41
datastore['BATCHSIZE'] || 256
42
end
43
44
def run_batch(hosts)
45
open_pcap
46
47
pcap = self.capture
48
49
ports = Rex::Socket.portspec_crack(datastore['PORTS'])
50
if ports.empty?
51
raise Msf::OptionValidateError.new(['PORTS'])
52
end
53
54
jitter_value = datastore['JITTER'].to_i
55
if jitter_value < 0
56
raise Msf::OptionValidateError.new(['JITTER'])
57
end
58
59
delay_value = datastore['DELAY'].to_i
60
if delay_value < 0
61
raise Msf::OptionValidateError.new(['DELAY'])
62
end
63
64
to = (datastore['TIMEOUT'] || 500).to_f / 1000.0
65
66
# we copy the hosts because some may not be reachable and need to be ejected
67
host_queue = hosts.dup
68
# Spread the load across the hosts
69
ports.each do |dport|
70
host_queue.each do |dhost|
71
shost, sport = getsource(dhost)
72
73
pcap.setfilter(getfilter(shost, sport, dhost, dport))
74
75
begin
76
probe = buildprobe(shost, sport, dhost, dport)
77
78
# Add the delay based on JITTER and DELAY if needs be
79
add_delay_jitter(delay_value, jitter_value)
80
81
unless capture_sendto(probe, dhost)
82
host_queue.delete(dhost)
83
next
84
end
85
86
reply = probereply(pcap, to)
87
88
next if reply # Got a RST back
89
90
print_status(" TCP OPEN|FILTERED #{dhost}:#{dport}")
91
92
# Add Report
93
report_note(
94
:host => dhost,
95
:proto => 'tcp',
96
:port => dport,
97
:type => "TCP OPEN|FILTERED #{dhost}:#{dport}",
98
:data => {
99
:host => dhost,
100
:port => dport
101
}
102
)
103
rescue ::Exception
104
print_error("Error: #{$!.class} #{$!}")
105
end
106
end
107
end
108
109
close_pcap
110
end
111
112
def getfilter(shost, sport, dhost, dport)
113
# Look for associated RSTs
114
"tcp and (tcp[13] & 0x04) != 0 and " +
115
"src host #{dhost} and src port #{dport} and " +
116
"dst host #{shost} and dst port #{sport}"
117
end
118
119
def getsource(dhost)
120
# srcip, srcport
121
[ Rex::Socket.source_address(dhost), rand(0xffff - 1025) + 1025 ]
122
end
123
124
def buildprobe(shost, sport, dhost, dport)
125
p = PacketFu::TCPPacket.new
126
p.ip_saddr = shost
127
p.ip_daddr = dhost
128
p.tcp_sport = sport
129
p.tcp_flags.fin = 1
130
p.tcp_flags.urg = 1
131
p.tcp_flags.psh = 1
132
p.tcp_dport = dport
133
p.tcp_win = 3072
134
p.recalc
135
p
136
end
137
138
def probereply(pcap, to)
139
reply = nil
140
begin
141
Timeout.timeout(to) do
142
pcap.each do |r|
143
pkt = PacketFu::Packet.parse(r)
144
next unless pkt.is_tcp?
145
146
reply = pkt
147
break
148
end
149
end
150
rescue Timeout::Error
151
end
152
return reply
153
end
154
end
155
156