brute force mixin for exploits, untested
git-svn-id: file:///home/svn/incoming/trunk@2739 4d416f70-5f16-0410-b530-b9f4589650daunstable
parent
41b656d45e
commit
ea047805a7
|
@ -0,0 +1,167 @@
|
|||
module Msf
|
||||
|
||||
###
|
||||
#
|
||||
# Brute
|
||||
# -----
|
||||
#
|
||||
# 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 exploit_single is
|
||||
# called.
|
||||
#
|
||||
###
|
||||
module Exploit::Brute
|
||||
|
||||
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(
|
||||
[
|
||||
OptData.new('BruteWait', [ false, "Delay between brute force attempts" ]),
|
||||
OptData.new('BruteStep', [ false, "Step size between brute force attempts" ])
|
||||
], Msf::Exploit::Brute)
|
||||
end
|
||||
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
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_address.dup) || {}
|
||||
stop = (bf.stop_addresses && bf.stop_address.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 = 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'])
|
||||
delay = self.datastore['BruteWait'].to_i
|
||||
end
|
||||
|
||||
# User-defined brute step?
|
||||
if (self.datastore['BruteStep'])
|
||||
step = self.datastore['BruteStep'].to_i
|
||||
end
|
||||
|
||||
# Okay, we've got all this crap out of the way, let's actually brute
|
||||
# force
|
||||
stopped = []
|
||||
curr = start.dup
|
||||
|
||||
# Keep going until we run out of options
|
||||
while (curr.length != stopped.length)
|
||||
|
||||
# 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_size * 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 next_addr >= stop[k]) or
|
||||
(direction[k] == -1 and 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
|
||||
|
||||
#
|
||||
# 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 overriden.
|
||||
#
|
||||
def brute_exploit(addrs)
|
||||
end
|
||||
|
||||
#
|
||||
# Call if the target is not a brute force target.
|
||||
#
|
||||
def single_exploit
|
||||
end
|
||||
|
||||
#
|
||||
# Waits for the provide delay
|
||||
#
|
||||
def brute_wait(delay)
|
||||
sleep(delay)
|
||||
end
|
||||
|
||||
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.
|
||||
#
|
||||
def import_from_datastore(hash, prefix = '')
|
||||
hash.each_key { |k|
|
||||
if (self.datastore[prefix + k])
|
||||
hash[k] = self.datastore[prefix + k]
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
Loading…
Reference in New Issue