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/modules/post/windows/manage/vss.rb
Views: 1904
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
class MetasploitModule < Msf::Post
7
include Msf::Post::Windows::FileSystem
8
include Msf::Post::Windows::Priv
9
include Msf::Post::Windows::ShadowCopy
10
11
def initialize(info = {})
12
super(
13
update_info(
14
info,
15
'Name' => 'Windows Manage Volume Shadow Copies',
16
'Description' => %q{
17
This module will perform management actions for Volume Shadow Copies on the system. This is based on the VSSOwn
18
Script originally posted by Tim Tomes and Mark Baggett.
19
20
Works on win2k3 and later.
21
},
22
'License' => MSF_LICENSE,
23
'Platform' => ['win'],
24
'SessionTypes' => ['meterpreter'],
25
'Author' => ['theLightCosine'],
26
'References' => [
27
[ 'URL', 'https://web.archive.org/web/20201111212952/https://securityweekly.com/2011/11/02/safely-dumping-hashes-from-liv/' ]
28
],
29
'Actions' => [
30
[ 'VSS_CREATE', { 'Description' => 'Create a new VSS copy' } ],
31
[ 'VSS_LIST_COPIES', { 'Description' => 'List VSS copies' } ],
32
[ 'VSS_MOUNT', { 'Description' => 'Mount a VSS copy' } ],
33
[ 'VSS_UNMOUNT', { 'Description' => 'Unmount a VSS copy' } ],
34
[ 'VSS_GET_INFO', { 'Description' => 'Get VSS information' } ],
35
[ 'VSS_SET_MAX_STORAGE_SIZE', { 'Description' => 'Set the VSS maximum storage size' } ]
36
],
37
'DefaultAction' => 'VSS_GET_INFO',
38
'Compat' => {
39
'Meterpreter' => {
40
'Commands' => %w[
41
stdapi_fs_delete_dir
42
]
43
}
44
},
45
'Notes' => {
46
'Stability' => [CRASH_SAFE],
47
'Reliability' => [],
48
'SideEffects' => [CONFIG_CHANGES, ARTIFACTS_ON_DISK]
49
}
50
)
51
)
52
53
register_options(
54
[
55
OptInt.new('SIZE', [ false, 'Size in bytes to set for max storage.' ], conditions: %w[ACTION == VSS_SET_MAX_STORAGE_SIZE]),
56
OptString.new('VOLUME', [ false, 'Volume to make a copy of.', 'C:\\' ], conditions: %w[ACTION == VSS_CREATE]),
57
OptString.new('DEVICE', [ false, 'DeviceObject of the shadow copy to mount.' ], conditions: %w[ACTION == VSS_MOUNT]),
58
OptString.new('PATH', [ false, 'Path to use for mounting the shadow copy.', 'ShadowCopy' ], conditions: ['ACTION', 'in', %w[VSS_MOUNT VSS_UNMOUNT] ])
59
]
60
)
61
end
62
63
def run
64
# all conditional options are required when active, make sure none of them are blank
65
options.each_pair do |name, option|
66
next if option.conditions.empty?
67
next unless Msf::OptCondition.show_option(self, option)
68
69
fail_with(Failure::BadConfig, "The #{name} option is required by the #{action.name} action.") if datastore[name].blank?
70
end
71
72
fail_with(Failure::NoAccess, 'This module requires administrative privileges to run') unless is_admin?
73
fail_with(Failure::NoAccess, 'This module requires UAC to be bypassed first') if is_uac_enabled?
74
fail_with(Failure::Unknown, 'Failed to start the necessary VSS services') unless start_vss
75
76
send("action_#{action.name.downcase}")
77
end
78
79
def action_vss_create
80
if (id = create_shadowcopy(datastore['VOLUME']))
81
print_good "Shadow Copy #{id} created!"
82
end
83
end
84
85
def action_vss_get_info
86
return unless (storage_data = vss_get_storage)
87
88
tbl = Rex::Text::Table.new(
89
'Header' => 'Shadow Copy Storage Data',
90
'Indent' => 2,
91
'Columns' => ['Field', 'Value']
92
)
93
storage_data.each_pair { |k, v| tbl << [k, v] }
94
print_good(tbl.to_s)
95
store_loot('host.shadowstorage', 'text/plain', session, tbl.to_s, 'shadowstorage.txt', 'Shadow Copy Storage Info')
96
end
97
98
def action_vss_mount
99
print_status('Creating the symlink...')
100
device = datastore['DEVICE']
101
unless device =~ %r{^([/\\])\1\?\1GLOBALROOT\1Device\1([\w\- ]+)\1?$}
102
fail_with(Failure::BadConfig, 'The DEVICE parameter is incorrect, it should begin with \\\\?\\GLOBALROOT\\Device\\')
103
end
104
device << Regexp.last_match(1) unless device.end_with?(Regexp.last_match(1)) # the DEVICE parameter needs to end with / or the link will be created successfully but will not work
105
106
if create_symlink(datastore['PATH'], device, directory: true)
107
print_good('Mounted successfully')
108
end
109
end
110
111
def action_vss_unmount
112
print_status('Deleting the symlink...')
113
session.fs.dir.rmdir(datastore['PATH'])
114
end
115
116
def action_vss_list_copies
117
shadow_copies = vss_list
118
return if shadow_copies.empty?
119
120
list = ''
121
shadow_copies.each do |copy|
122
tbl = Rex::Text::Table.new(
123
'Header' => 'Shadow Copy Data',
124
'Indent' => 2,
125
'Columns' => ['Field', 'Value']
126
)
127
copy.each_pair { |k, v| tbl << [k, v] }
128
list << " #{tbl} \n\n"
129
print_good tbl.to_s
130
end
131
store_loot('host.shadowcopies', 'text/plain', session, list, 'shadowcopies.txt', 'Shadow Copy Info')
132
end
133
134
def action_vss_set_max_storage_size
135
if vss_set_storage(datastore['SIZE'])
136
print_good('Size updated successfully')
137
else
138
print_error('There was a problem updating the storage size')
139
end
140
end
141
end
142
143