1
+ function Get-VolumeShadowCopy
2
+ {
3
+ <#
4
+ . SYNOPSIS
5
+
6
+ Lists the device paths of all local volume shadow copies.
7
+
8
+ PowerSploit Function: Get-VolumeShadowCopy
9
+ Author: Matthew Graeber (@mattifestation)
10
+ License: BSD 3-Clause
11
+ Required Dependencies: None
12
+ Optional Dependencies: None
13
+ Version: 2.0.0
14
+ #>
15
+
16
+ $UserIdentity = ([Security.Principal.WindowsPrincipal ][Security.Principal.WindowsIdentity ]::GetCurrent())
17
+
18
+ if (-not $UserIdentity.IsInRole ([Security.Principal.WindowsBuiltInRole ]' Administrator' ))
19
+ {
20
+ Throw ' You must run Get-VolumeShadowCopy from an elevated command prompt.'
21
+ }
22
+
23
+ Get-WmiObject - Namespace root\cimv2 - Class Win32_ShadowCopy | ForEach-Object { $_.DeviceObject }
24
+ }
25
+
26
+ function New-VolumeShadowCopy
27
+ {
28
+ <#
29
+ . SYNOPSIS
30
+
31
+ Creates a new volume shadow copy.
32
+
33
+ PowerSploit Function: New-VolumeShadowCopy
34
+ Author: Jared Atkinson (@jaredcatkinson)
35
+ License: BSD 3-Clause
36
+ Required Dependencies: None
37
+ Optional Dependencies: None
38
+ Version: 2.0.0
39
+
40
+ . DESCRIPTION
41
+
42
+ New-VolumeShadowCopy creates a volume shadow copy for the specified volume.
43
+
44
+ . PARAMETER Volume
45
+
46
+ Volume used for the shadow copy. This volume is sometimes referred to as the original volume.
47
+ The Volume parameter can be specified as a volume drive letter, mount point, or volume globally unique identifier (GUID) name.
48
+
49
+ . PARAMETER Context
50
+
51
+ Context that the provider uses when creating the shadow. The default is "ClientAccessible".
52
+
53
+ . EXAMPLE
54
+
55
+ New-VolumeShadowCopy -Volume C:\
56
+
57
+ Description
58
+ -----------
59
+ Creates a new VolumeShadowCopy of the C drive
60
+ #>
61
+ Param (
62
+ [Parameter (Mandatory = $True )]
63
+ [ValidatePattern (' ^\w:\\' )]
64
+ [String ]
65
+ $Volume ,
66
+
67
+ [Parameter (Mandatory = $False )]
68
+ [ValidateSet (" ClientAccessible" )]
69
+ [String ]
70
+ $Context = " ClientAccessible"
71
+ )
72
+
73
+ $UserIdentity = ([Security.Principal.WindowsPrincipal ][Security.Principal.WindowsIdentity ]::GetCurrent())
74
+
75
+ if (-not $UserIdentity.IsInRole ([Security.Principal.WindowsBuiltInRole ]' Administrator' ))
76
+ {
77
+ Throw ' You must run Get-VolumeShadowCopy from an elevated command prompt.'
78
+ }
79
+
80
+ # Save VSS Service initial state
81
+ $running = (Get-Service - Name VSS).Status
82
+
83
+ $class = [WMICLASS ]" root\cimv2:win32_shadowcopy"
84
+
85
+ $return = $class.create (" $Volume " , " $Context " )
86
+
87
+ switch ($return.returnvalue )
88
+ {
89
+ 1 {Write-Error " Access denied." ; break }
90
+ 2 {Write-Error " Invalid argument." ; break }
91
+ 3 {Write-Error " Specified volume not found." ; break }
92
+ 4 {Write-Error " Specified volume not supported." ; break }
93
+ 5 {Write-Error " Unsupported shadow copy context." ; break }
94
+ 6 {Write-Error " Insufficient storage." ; break }
95
+ 7 {Write-Error " Volume is in use." ; break }
96
+ 8 {Write-Error " Maximum number of shadow copies reached." ; break }
97
+ 9 {Write-Error " Another shadow copy operation is already in progress." ; break }
98
+ 10 {Write-Error " Shadow copy provider vetoed the operation." ; break }
99
+ 11 {Write-Error " Shadow copy provider not registered." ; break }
100
+ 12 {Write-Error " Shadow copy provider failure." ; break }
101
+ 13 {Write-Error " Unknown error." ; break }
102
+ default {break }
103
+ }
104
+
105
+ # If VSS Service was Stopped at the start, return VSS to "Stopped" state
106
+ if ($running -eq " Stopped" )
107
+ {
108
+ Stop-Service - Name VSS
109
+ }
110
+ }
111
+
112
+ function Remove-VolumeShadowCopy
113
+ {
114
+ <#
115
+ . SYNOPSIS
116
+
117
+ Deletes a volume shadow copy.
118
+
119
+ PowerSploit Function: Remove-VolumeShadowCopy
120
+ Author: Jared Atkinson (@jaredcatkinson)
121
+ License: BSD 3-Clause
122
+ Required Dependencies: None
123
+ Optional Dependencies: None
124
+ Version: 2.0.0
125
+
126
+ . DESCRIPTION
127
+
128
+ Remove-VolumeShadowCopy deletes a volume shadow copy from the system.
129
+
130
+ . PARAMETER InputObject
131
+
132
+ Specifies the Win32_ShadowCopy object to remove
133
+
134
+ . PARAMETER DevicePath
135
+
136
+ Specifies the volume shadow copy 'DeviceObject' path. This path can be retrieved with the Get-VolumeShadowCopy PowerSploit function or with the Win32_ShadowCopy object.
137
+
138
+ . EXAMPLE
139
+
140
+ Get-VolumeShadowCopy | Remove-VolumeShadowCopy
141
+
142
+ Description
143
+ -----------
144
+ Removes all volume shadow copy
145
+
146
+ . EXAMPLE
147
+
148
+ Remove-VolumeShadowCopy -DevicePath '\\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy4'
149
+
150
+ Description
151
+ -----------
152
+ Removes the volume shadow copy at the 'DeviceObject' path \\?\GLOBALROOT\DeviceHarddiskVolumeShadowCopy4
153
+ #>
154
+ [CmdletBinding (SupportsShouldProcess = $True )]
155
+ Param (
156
+ [Parameter (Mandatory = $True , ValueFromPipeline = $True )]
157
+ [ValidatePattern (' ^\\\\\?\\GLOBALROOT\\Device\\HarddiskVolumeShadowCopy[0-9]{1,3}$' )]
158
+ [String ]
159
+ $DevicePath
160
+ )
161
+
162
+ PROCESS
163
+ {
164
+ if ($PSCmdlet.ShouldProcess (" The VolumeShadowCopy at DevicePath $DevicePath will be removed" ))
165
+ {
166
+ (Get-WmiObject - Namespace root\cimv2 - Class Win32_ShadowCopy | Where-Object {$_.DeviceObject -eq $DevicePath }).Delete()
167
+ }
168
+ }
169
+ }
170
+
171
+ function Mount-VolumeShadowCopy
172
+ {
173
+ <#
174
+ . SYNOPSIS
175
+
176
+ Mounts a volume shadow copy.
177
+
178
+ PowerSploit Function: Mount-VolumeShadowCopy
179
+ Author: Matthew Graeber (@mattifestation)
180
+ License: BSD 3-Clause
181
+ Required Dependencies: None
182
+ Optional Dependencies: None
183
+ Version: 2.0.0
184
+
185
+ . DESCRIPTION
186
+
187
+ Mount-VolumeShadowCopy mounts a volume shadow copy volume by creating a symbolic link.
188
+
189
+ . PARAMETER Path
190
+
191
+ Specifies the path to which the symbolic link for the mounted volume shadow copy will be saved.
192
+
193
+ . PARAMETER DevicePath
194
+
195
+ Specifies the volume shadow copy 'DeviceObject' path. This path can be retrieved with the Get-VolumeShadowCopy PowerSploit function or with the Win32_ShadowCopy object.
196
+
197
+ . EXAMPLE
198
+
199
+ Get-VolumeShadowCopy | Mount-VolumeShadowCopy -Path C:\VSS
200
+
201
+ Description
202
+ -----------
203
+ Create a mount point in 'C:\VSS' for each volume shadow copy volume
204
+
205
+ . EXAMPLE
206
+
207
+ Mount-VolumeShadowCopy -Path C:\VSS -DevicePath '\\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy4'
208
+
209
+ . EXAMPLE
210
+
211
+ Get-WmiObject Win32_ShadowCopy | % { $_.DeviceObject -Path C:\VSS -DevicePath $_ }
212
+ #>
213
+
214
+ Param (
215
+ [Parameter (Mandatory = $True )]
216
+ [ValidateNotNullOrEmpty ()]
217
+ [String ]
218
+ $Path ,
219
+
220
+ [Parameter (Mandatory = $True , ValueFromPipeline = $True )]
221
+ [ValidatePattern (' ^\\\\\?\\GLOBALROOT\\Device\\HarddiskVolumeShadowCopy[0-9]{1,3}$' )]
222
+ [String []]
223
+ $DevicePath
224
+ )
225
+
226
+ BEGIN
227
+ {
228
+ $UserIdentity = ([Security.Principal.WindowsPrincipal ][Security.Principal.WindowsIdentity ]::GetCurrent())
229
+
230
+ if (-not $UserIdentity.IsInRole ([Security.Principal.WindowsBuiltInRole ]' Administrator' ))
231
+ {
232
+ Throw ' You must run Get-VolumeShadowCopy from an elevated command prompt.'
233
+ }
234
+
235
+ # Validate that the path exists before proceeding
236
+ Get-ChildItem $Path - ErrorAction Stop | Out-Null
237
+
238
+ $DynAssembly = New-Object System.Reflection.AssemblyName(' VSSUtil' )
239
+ $AssemblyBuilder = [AppDomain ]::CurrentDomain.DefineDynamicAssembly($DynAssembly , [Reflection.Emit.AssemblyBuilderAccess ]::Run)
240
+ $ModuleBuilder = $AssemblyBuilder.DefineDynamicModule (' VSSUtil' , $False )
241
+
242
+ # Define [VSS.Kernel32]::CreateSymbolicLink method using reflection
243
+ # (i.e. none of the forensic artifacts left with using Add-Type)
244
+ $TypeBuilder = $ModuleBuilder.DefineType (' VSS.Kernel32' , ' Public, Class' )
245
+ $PInvokeMethod = $TypeBuilder.DefinePInvokeMethod (' CreateSymbolicLink' ,
246
+ ' kernel32.dll' ,
247
+ ([Reflection.MethodAttributes ]::Public -bor [Reflection.MethodAttributes ]::Static ),
248
+ [Reflection.CallingConventions ]::Standard,
249
+ [Bool ],
250
+ [Type []]@ ([String ], [String ], [UInt32 ]),
251
+ [Runtime.InteropServices.CallingConvention ]::Winapi,
252
+ [Runtime.InteropServices.CharSet ]::Auto)
253
+ $DllImportConstructor = [Runtime.InteropServices.DllImportAttribute ].GetConstructor(@ ([String ]))
254
+ $SetLastError = [Runtime.InteropServices.DllImportAttribute ].GetField(' SetLastError' )
255
+ $SetLastErrorCustomAttribute = New-Object Reflection.Emit.CustomAttributeBuilder($DllImportConstructor ,
256
+ @ (' kernel32.dll' ),
257
+ [Reflection.FieldInfo []]@ ($SetLastError ),
258
+ @ ($true ))
259
+ $PInvokeMethod.SetCustomAttribute ($SetLastErrorCustomAttribute )
260
+
261
+ $Kernel32Type = $TypeBuilder.CreateType ()
262
+ }
263
+
264
+ PROCESS
265
+ {
266
+ foreach ($Volume in $DevicePath )
267
+ {
268
+ $Volume -match ' ^\\\\\?\\GLOBALROOT\\Device\\(?<LinkName>HarddiskVolumeShadowCopy[0-9]{1,3})$' | Out-Null
269
+
270
+ $LinkPath = Join-Path $Path $Matches.LinkName
271
+
272
+ if (Test-Path $LinkPath )
273
+ {
274
+ Write-Warning " '$LinkPath ' already exists."
275
+ continue
276
+ }
277
+
278
+ if (-not $Kernel32Type ::CreateSymbolicLink($LinkPath , " $ ( $Volume ) \" , 1 ))
279
+ {
280
+ Write-Error " Symbolic link creation failed for '$Volume '."
281
+ continue
282
+ }
283
+
284
+ Get-Item $LinkPath
285
+ }
286
+ }
287
+
288
+ END
289
+ {
290
+
291
+ }
292
+ }
0 commit comments