Module: Msf::Exploit::Brute

Defined in:
lib/msf/core/exploit/brute.rb

Overview

This modules provides a target-aware brute-forcing wrapper. It implements the exploit method and calls exploit_brute with target supplied information. If the selected target is not a bruteforce target, then single_exploit is called.

Instance Method Summary collapse

Instance Method Details

#brute_exploit(addrs) ⇒ Object

This routine is called once per brute force iteration. The addresses parameter is a hash of addresses that are incremented each iteration and are derived from the target’s bruteforce information or the module’s datastore in case they are being overridden.



152
153
# File 'lib/msf/core/exploit/brute.rb', line 152

def brute_exploit(addrs)
end

#brute_wait(delay) ⇒ Object

Waits for the provide delay.



164
165
166
# File 'lib/msf/core/exploit/brute.rb', line 164

def brute_wait(delay)
  sleep(delay)
end

#exploitObject

Entry point for initiating an exploit. This module wrappers the exploit method and determines whether or not the selected target supports brute force. If it does, it does some special things and wraps the brute forcing logic.



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/msf/core/exploit/brute.rb', line 38

def exploit
  # Is the selected target a brute force target?
  if (target.bruteforce?)
    # The step direction is automatically calculated
    direction = {}

    bf = target.bruteforce

    # Get the start and stop address hashes
    start = bf.start_addresses ? bf.start_addresses.dup : {}
    stop  = bf.stop_addresses ? bf.stop_addresses.dup : {}
    step  = bf.step_size
    delay = bf.delay

    # Enumerate each start address and try to figure out the direction
    start.each_pair { |name, addr|
      # If there's a stop address, figure out if it's above or below
      # the start address
      if (stop[name])
        if (stop[name] < addr)
          direction[name] = -1
        else
          direction[name] = 1
        end
      # If there's no stop address, infer the direction based on
      # the default
      else
        direction[name] = bf.default_direction
      end
    }

    # Import start/stop address overrides from the datastore
    import_from_datastore(start, 'Start')
    import_from_datastore(stop,  'Stop')

    # User-defined brute wait?
    if self.datastore['BruteWait'] and self.datastore['BruteWait'] > 0
      delay = self.datastore['BruteWait'].to_i
    end

    # User-defined brute step?
    if self.datastore['BruteStep'] and self.datastore['BruteStep'] > 0
      step = self.datastore['BruteStep'].to_i
    end

    # Sane defaults
    delay = 1 if delay.nil? or delay == 0

    # Okay, we've got all this crap out of the way, let's actually brute
    # force
    stopped = []
    curr    = start.dup

    # Automatically determine the step size based off the nop sled length
    if step == 0
      step = payload.nop_sled_size

      if step == 0
        raise Msf::OptionValidateError.new(
          {
            'BruteStep' => 'The step size for this exploit is invalid'
          }
        )
      end
    end

    # Keep going until we run out of options
    while (curr.length != stopped.length)

      # Stop brute forcing once a session is found
      break if session_created?

      # Fire off an exploit attempt with the supplied addresses
      brute_exploit(curr)

      # Give it time before we try again
      brute_wait(delay)

      # Scan each current key, increasing it or decreasing it by the
      # step size according to its direction
      curr.each_key { |k|

        # Has movement been stopped on this address?  If so, skip it.
        next if (stopped.include?(k))

        # Calculate the next address before we move it to see if
        # we're going to go over
        next_addr = step * direction[k]

        # If this item has hit a stop address, add it to the stopped
        # hash and move it no further
        if (stop[k])
          if ((direction[k] == 1 and curr[k] + next_addr >= stop[k]) or
              (direction[k] == -1 and curr[k] + next_addr < stop[k]))
            stopped << k
            next
          end
        end

        # If it's not time to stop, move it
        curr[k] += next_addr
      }
    end
  else
    single_exploit
  end
end

#import_from_datastore(hash, prefix = '') ⇒ Object (protected)

Imports information into the supplied hash from the datastore. This is a way of allowing the user to override values for a specific brute force target by name without them actually being conveyed in the options list. This is a bit of a change from 2.x, but 2.x didn’t have per-target brute force addresses, which I think is more valuable.



178
179
180
181
182
183
184
# File 'lib/msf/core/exploit/brute.rb', line 178

def import_from_datastore(hash, prefix = '')
  hash.each_key { |k|
    if (self.datastore[prefix + k])
      hash[k] = self.datastore[prefix + k]
    end
  }
end

#initialize(info = {}) ⇒ Object

Initializes an instance of an exploit module that supports brute force targets.



18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/msf/core/exploit/brute.rb', line 18

def initialize(info = {})
  super

  #
  # Register BruteWait and BruteStep as two advanced options for this
  # exploit even though not all targets may be brute force targets.
  #
  register_advanced_options(
    [
      OptInt.new('BruteWait', [ false, "Delay between brute force attempts"     ]),
      OptInt.new('BruteStep', [ false, "Step size between brute force attempts" ])
    ], Msf::Exploit::Brute)
end

#single_exploitObject

Call if the target is not a brute force target.



158
159
# File 'lib/msf/core/exploit/brute.rb', line 158

def single_exploit
end