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/exploit/brute.rb
Views: 1904
1
# -*- coding: binary -*-
2
module Msf
3
4
###
5
#
6
# This modules provides a target-aware brute-forcing wrapper. It implements
7
# the exploit method and calls exploit_brute with target supplied information.
8
# If the selected target is not a bruteforce target, then single_exploit is
9
# called.
10
#
11
###
12
module Exploit::Brute
13
14
#
15
# Initializes an instance of an exploit module that supports brute force
16
# targets.
17
#
18
def initialize(info = {})
19
super
20
21
#
22
# Register BruteWait and BruteStep as two advanced options for this
23
# exploit even though not all targets may be brute force targets.
24
#
25
register_advanced_options(
26
[
27
OptInt.new('BruteWait', [ false, "Delay between brute force attempts" ]),
28
OptInt.new('BruteStep', [ false, "Step size between brute force attempts" ])
29
], Msf::Exploit::Brute)
30
end
31
32
#
33
# Entry point for initiating an exploit. This module wrappers the exploit
34
# method and determines whether or not the selected target supports brute
35
# force. If it does, it does some special things and wraps the brute
36
# forcing logic.
37
#
38
def exploit
39
# Is the selected target a brute force target?
40
if (target.bruteforce?)
41
# The step direction is automatically calculated
42
direction = {}
43
44
bf = target.bruteforce
45
46
# Get the start and stop address hashes
47
start = bf.start_addresses ? bf.start_addresses.dup : {}
48
stop = bf.stop_addresses ? bf.stop_addresses.dup : {}
49
step = bf.step_size
50
delay = bf.delay
51
52
# Enumerate each start address and try to figure out the direction
53
start.each_pair { |name, addr|
54
# If there's a stop address, figure out if it's above or below
55
# the start address
56
if (stop[name])
57
if (stop[name] < addr)
58
direction[name] = -1
59
else
60
direction[name] = 1
61
end
62
# If there's no stop address, infer the direction based on
63
# the default
64
else
65
direction[name] = bf.default_direction
66
end
67
}
68
69
# Import start/stop address overrides from the datastore
70
import_from_datastore(start, 'Start')
71
import_from_datastore(stop, 'Stop')
72
73
# User-defined brute wait?
74
if self.datastore['BruteWait'] and self.datastore['BruteWait'] > 0
75
delay = self.datastore['BruteWait'].to_i
76
end
77
78
# User-defined brute step?
79
if self.datastore['BruteStep'] and self.datastore['BruteStep'] > 0
80
step = self.datastore['BruteStep'].to_i
81
end
82
83
# Sane defaults
84
delay = 1 if delay.nil? or delay == 0
85
86
# Okay, we've got all this crap out of the way, let's actually brute
87
# force
88
stopped = []
89
curr = start.dup
90
91
# Automatically determine the step size based off the nop sled length
92
if step == 0
93
step = payload.nop_sled_size
94
95
if step == 0
96
raise Msf::OptionValidateError.new(
97
{
98
'BruteStep' => 'The step size for this exploit is invalid'
99
}
100
)
101
end
102
end
103
104
# Keep going until we run out of options
105
while (curr.length != stopped.length)
106
107
# Stop brute forcing once a session is found
108
break if session_created?
109
110
# Fire off an exploit attempt with the supplied addresses
111
brute_exploit(curr)
112
113
# Give it time before we try again
114
brute_wait(delay)
115
116
# Scan each current key, increasing it or decreasing it by the
117
# step size according to its direction
118
curr.each_key { |k|
119
120
# Has movement been stopped on this address? If so, skip it.
121
next if (stopped.include?(k))
122
123
# Calculate the next address before we move it to see if
124
# we're going to go over
125
next_addr = step * direction[k]
126
127
# If this item has hit a stop address, add it to the stopped
128
# hash and move it no further
129
if (stop[k])
130
if ((direction[k] == 1 and curr[k] + next_addr >= stop[k]) or
131
(direction[k] == -1 and curr[k] + next_addr < stop[k]))
132
stopped << k
133
next
134
end
135
end
136
137
# If it's not time to stop, move it
138
curr[k] += next_addr
139
}
140
end
141
else
142
single_exploit
143
end
144
end
145
146
#
147
# This routine is called once per brute force iteration. The addresses
148
# parameter is a hash of addresses that are incremented each iteration and
149
# are derived from the target's bruteforce information or the module's
150
# datastore in case they are being overridden.
151
#
152
def brute_exploit(addrs)
153
end
154
155
#
156
# Call if the target is not a brute force target.
157
#
158
def single_exploit
159
end
160
161
#
162
# Waits for the provide delay.
163
#
164
def brute_wait(delay)
165
sleep(delay)
166
end
167
168
protected
169
170
#
171
# Imports information into the supplied hash from the datastore.
172
# This is a way of allowing the user to override values for a
173
# specific brute force target by name without them actually
174
# being conveyed in the options list. This is a bit of a change
175
# from 2.x, but 2.x didn't have per-target brute force
176
# addresses, which I think is more valuable.
177
#
178
def import_from_datastore(hash, prefix = '')
179
hash.each_key { |k|
180
if (self.datastore[prefix + k])
181
hash[k] = self.datastore[prefix + k]
182
end
183
}
184
end
185
186
end
187
188
end
189
190