Files
Kevin Robertson 6a6da09db0 Added better support for legacy ADIDNS zone location
Added 'System' to the accepted values for the Partition parameter.
2018-07-17 22:22:17 -04:00

1566 lines
74 KiB
PowerShell

function Invoke-DNSUpdate
{
<#
.SYNOPSIS
This function performs secure and nonsecure DNS dynamic updates against an AD domain controller. Authentication
for secure updates is performed through Kerberos GSS-TSIG.
Author: Kevin Robertson (@kevin_robertson)
License: BSD 3-Clause
.DESCRIPTION
This function can be used to add/delete dynamic DNS records through secure or nonsecure dynamic updates against an
AD domain controller. A, AAAA, CNAME, MX, PTR, SRV, and TXT records are currently supported. Invoke-DNSUpdate is modeled
after BIND`s nsupdate tool when using the '-g' or 'gsstsig' options for secure updates or no authentication for
nonsecure updates.
By default, Active Directory-integrated zones have secure dynamic updates enabled with authenticated users having
'Create all child objects' permission. Records that do not exist in an AD zone can be added/deleted with a standard
user account. Existing records created by default or created by other users impose limitations. For example, creating
records that apply to the root of the zone or creating additional SRV records for kerberos/ldap will likely be blocked
due to existing records. Note however that older existing dynamic records can sometimes be hijacked. Subdomain folders
can also be created.
With secure dynamic updates, this function supports only GSS-TSIG through Kerberos AES256-CTS-HMAC-SHA1-96 using
two separate methods. By default, the function will have Windows perform all Kerberos steps up until the AP-REQ
is sent to DNS on the DC. This method will work with either the current session context or with specified credentials.
The second method performs Kerberos authentication using just PowerShell code over a TCPClient connection. This method
will accept a password or AES256 hash and will not place any tickets in the client side cache.
In the event that a zone is configured for nonsecure dynamic updates, you should have full control over the zone.
Note that wpad and isatap are on a block list by default starting with Server 2008. Although the records can be added
with both secure and nonsecure dynamic updates, AD DNS will not answer requests for wpad and isatap if they are listed
on the block list.
.PARAMETER Credential
PSCredential object that will be used to to perform dynamic update.
.PARAMETER DomainController
Domain controller to target in FQDN format.
.PARAMETER Realm
Kerberos realm.
.PARAMETER Username
Username of user with DNS secure dynamic update access. If using a machine account, the trailing '$' must be
included if one is shown in the SAMAccountName attribute. Note, this is an alternative to using Credential and
is mainly included as part of pass the hash functionality.
.PARAMETER Password
Password of user with DNS secure dynamic update access. The password must be in the form of a secure string.
Note, this is an alternative to using Credential and is mainly included as part of pass the hash
functionality.
.PARAMETER Hash
AES256 password hash for user with DNS secure dynamic update access. Note that this will use Kerberos
authentication built on top of TCPClient. Note, this is an alternative to using Credential and is mainly
included as part of pass the hash functionality.
.PARAMETER Security
Default = Secure: (Auto/Nonsecure/Secure) Dynamic update security type. Auto will attempt to use nonsecure. If
nonsecure fails, secure will be used. This is the standard dynamic update behavior. Secure is the default
because it generates less traffic with default setups.
.PARAMETER DNSName
DNS record name.
.PARAMETER DNSData
DNS records data. For most record types this will be the destination hostname or IP address. For TXT records
this can be used for data. If deleting a record, do not set this parameter.
.PARAMETER DNSPort
DNS SRV record port.
.PARAMETER DNSPreference
DNS MX record preference.
.PARAMETER DNSPriority
DNS SRV record priority.
.PARAMETER DNSTTL
Default = 600: DNS record TTL.
.PARAMETER DNSType
Default = A: DNS record type. This function supports A, AAAA, CNAME, MX, PTR, SRV, and TXT.
.PARAMETER DNSWeight
DNS SRV record weight.
.PARAMETER DNSZone
DNS zone.
.PARAMETER RecordCheck
Check for an existing matching record before attempting to add or delete.
.PARAMETER TCPClientAuth
Switch to force usage of the TCPClient based Kerberos authentication. Note, usernames are case sensitive with
this switch.
.EXAMPLE
Invoke-DNSUpdate -DNSName www -DNSData 192.168.100.125
Add A Record
.EXAMPLE
Invoke-DNSUpdate -DNSType AAAA -DNSName www.test.local -DNSData 2001:0db8:85a3:0000:0000:8a2e:0370:7334
Add AAAA Record
.EXAMPLE
Invoke-DNSUpdate -DNSType CNAME -DNSName www.test.local -DNSData system.test.local
Add CNAME Record
.EXAMPLE
Invoke-DNSUpdate -DNSType MX -DNSName test.local -DNSData 192.168.100.125 -DNSPreference 10
Add MX Record
.EXAMPLE
Invoke-DNSUpdate -DNSType PTR -DNSName 125.100.168.192.in-addr.arpa -DNSData www.test.local -DNSZone 100.168.192.in-addr.arpa
Add PTR Record - there is a good chance this will be denied if there is an existing record for an IP
.EXAMPLE
Invoke-DNSUpdate -DNSType SRV -DNSName _autodiscover._tcp.lab.local -DNSData system.test.local -DNSPriority 100 -DNSWeight 80 -DNSPort 443
Add SRV Record
.EXAMPLE
Invoke-DNSUpdate -DNSType TXT -DNSName host.test.local -DNSData "some text"
Add TXT Record
.EXAMPLE
Invoke-DNSUpdate -DNSType TXT -DNSName host.test.local
Delete TXT record - all deletes follow the same format, just specify DNSType and DNSName
.EXAMPLE
Invoke-DNSUpdate -DNSType A -DNSName www.test.local -Username testuser
Add A record using another account
.EXAMPLE
Invoke-DNSUpdate -DNSType A -DNSName www.test.local -Username testuser -Hash 0C27E0A5B0D69640B40DDED4A28EB3BB0D157659EBED2816A41A8228E98D111B
Add A record using another account and an AES256 hash
.LINK
https://github.com/Kevin-Robertson/Powermad
#>
[CmdletBinding()]
param
(
[parameter(Mandatory=$false)][String]$DomainController,
[parameter(Mandatory=$false)][String]$Realm,
[parameter(Mandatory=$false)][String]$Username,
[parameter(Mandatory=$false)][System.Security.SecureString]$Password,
[parameter(Mandatory=$false)][ValidateScript({$_.Length -eq 64})][String]$Hash,
[parameter(Mandatory=$false)][String]$Zone,
[parameter(Mandatory=$false)][Int]$DNSTTL = 600,
[parameter(Mandatory=$false)][Int]$DNSPreference,
[parameter(Mandatory=$false)][Int]$DNSPriority,
[parameter(Mandatory=$false)][Int]$DNSWeight,
[parameter(Mandatory=$false)][Int]$DNSPort,
[parameter(Mandatory=$false)][ValidateSet("Auto","Nonsecure","Secure")][String]$Security = "Secure",
[parameter(Mandatory=$false)][ValidateSet("A","AAAA","CNAME","MX","PTR","SRV","TXT")][String]$DNSType = "A",
[parameter(Mandatory=$true)][String]$DNSName,
[parameter(Mandatory=$false)][ValidateScript({$_.Length -le 255})][String]$DNSData,
[parameter(Mandatory=$false)][Switch]$RecordCheck,
[parameter(Mandatory=$false)][Switch]$TCPClientAuth,
[parameter(Mandatory=$false)][System.Management.Automation.PSCredential]$Credential,
[parameter(ValueFromRemainingArguments=$true)]$invalid_parameter
)
if($invalid_parameter)
{
Write-Output "[-] $($invalid_parameter) is not a valid parameter"
throw
}
if($TCPClientAuth -and (!$Credential -and !$Username))
{
Write-Output "[-] TCPClientAuth requires a username or PSCredential"
throw
}
switch ($DNSType)
{
'MX'
{
if(!$DNSPreference)
{
Write-Output "[-] MX records require a DNSPreference"
throw
}
}
'PTR'
{
if(!$Zone)
{
Write-Output "[-] PTR records require a DNSZone"
throw
}
}
'SRV'
{
if(!$DNSPriority -and !$DNSWeight -and !$DNSPort -and $DNSData)
{
Write-Output "[-] DNSType SRV requires DNSPriority, DNSWeight, and DNSPort"
throw
}
if($DNSName -notlike '*._tcp.*' -and $DNSName -notlike '*._udp.*')
{
Write-Output "[-] DNSName doesn't contain a protocol"
throw
}
}
}
if($Security -ne 'Nonsecure' -and $Username -and !$Hash)
{
$password = Read-Host -Prompt "Enter password" -AsSecureString
}
if(!$DistinguishedName -and (!$DomainController -or !$Domain -or !$Realm -or !$Zone))
{
try
{
$current_domain = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
}
catch
{
Write-Output "[-] $($_.Exception.Message)"
throw
}
}
if(!$DomainController)
{
$DomainController = $current_domain.PdcRoleOwner.Name
Write-Verbose "[+] Domain Controller = $DomainController"
}
if(!$Domain)
{
$Domain = $current_domain.Name
Write-Verbose "[+] Domain = $Domain"
}
if(!$Realm)
{
$Realm = $current_domain.Name
Write-Verbose "[+] Kerberos Realm = $Realm"
}
if(!$Zone)
{
$Zone = $current_domain.Name
Write-Verbose "[+] DNS Zone = $Zone"
}
$Zone = $Zone.ToLower()
if($TCPClientAuth -or $Hash -or ($TCPClientAuth -and $Credential))
{
$kerberos_tcpclient = $true
$Realm = $Realm.ToUpper()
if($Credential)
{
$Username = $Credential.Username
$Password = $Credential.Password
}
if($username -like "*\*")
{
$username = $username.SubString(($username.IndexOf("\") + 1),($username.Length - ($username.IndexOf("\") + 1)))
}
if($username -like "*@*")
{
$username = $username.SubString(0,($username.IndexOf("@")))
}
if($Username.EndsWith("$"))
{
$salt = $Realm + "host" + $Username.SubString(0,$Username.Length - 1) + "." + $Realm.ToLower()
}
else
{
$salt = $Realm + $Username
}
Write-Verbose "[+] Salt $salt"
}
function ConvertFrom-PacketOrderedDictionary($OrderedDictionary)
{
ForEach($field in $OrderedDictionary.Values)
{
$byte_array += $field
}
return [Byte[]]$byte_array
}
function Get-KerberosAES256UsageKey
{
param([String]$key_type,[Int]$usage_number,[Byte[]]$base_key)
$padding = 0x00 * 16
if($key_type -eq 'checksum')
{
switch($usage_number)
{
25 {[Byte[]]$usage_constant = 0x5d,0xfb,0x7d,0xbf,0x53,0x68,0xce,0x69,0x98,0x4b,0xa5,0xd2,0xe6,0x43,0x34,0xba + $padding}
}
}
elseif($key_type -eq 'encrypt')
{
switch($usage_number)
{
1 {[Byte[]]$usage_constant = 0xae,0x2c,0x16,0x0b,0x04,0xad,0x50,0x06,0xab,0x55,0xaa,0xd5,0x6a,0x80,0x35,0x5a + $padding}
3 {[Byte[]]$usage_constant = 0xbe,0x34,0x9a,0x4d,0x24,0xbe,0x50,0x0e,0xaf,0x57,0xab,0xd5,0xea,0x80,0x75,0x7a + $padding}
4 {[Byte[]]$usage_constant = 0xc5,0xb7,0xdc,0x6e,0x34,0xc7,0x51,0x12,0xb1,0x58,0xac,0x56,0x2a,0x80,0x95,0x8a + $padding}
7 {[Byte[]]$usage_constant = 0xde,0x44,0xa2,0xd1,0x64,0xe0,0x51,0x1e,0xb7,0x5b,0xad,0xd6,0xea,0x80,0xf5,0xba + $padding}
11 {[Byte[]]$usage_constant = 0xfe,0x54,0xaa,0x55,0xa5,0x02,0x52,0x2f,0xbf,0x5f,0xaf,0xd7,0xea,0x81,0x75,0xfa + $padding}
12 {[Byte[]]$usage_constant = 0x05,0xd7,0xec,0x76,0xb5,0x0b,0x53,0x33,0xc1,0x60,0xb0,0x58,0x2a,0x81,0x96,0x0b + $padding}
}
}
elseif($key_type -eq 'integrity')
{
switch($usage_number)
{
1 {[Byte[]]$usage_constant = 0x5b,0x58,0x2c,0x16,0x0a,0x5a,0xa8,0x05,0x56,0xab,0x55,0xaa,0xd5,0x40,0x2a,0xb5 + $padding}
4 {[Byte[]]$usage_constant = 0x72,0xe3,0xf2,0x79,0x3a,0x74,0xa9,0x11,0x5c,0xae,0x57,0x2b,0x95,0x40,0x8a,0xe5 + $padding}
7 {[Byte[]]$usage_constant = 0x8b,0x70,0xb8,0xdc,0x6a,0x8d,0xa9,0x1d,0x62,0xb1,0x58,0xac,0x55,0x40,0xeb,0x15 + $padding}
11 {[Byte[]]$usage_constant = 0xab,0x80,0xc0,0x60,0xaa,0xaf,0xaa,0x2e,0x6a,0xb5,0x5a,0xad,0x55,0x41,0x6b,0x55 + $padding}
}
}
$AES = New-Object "System.Security.Cryptography.AesManaged"
$AES.Mode = [System.Security.Cryptography.CipherMode]::CBC
$AES.Padding = [System.Security.Cryptography.PaddingMode]::Zeros
$AES.IV = 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
$AES.KeySize = 256
$AES.Key = $base_key
$AES_encryptor = $AES.CreateEncryptor()
$usage_key = $AES_encryptor.TransformFinalBlock($usage_constant,0,$usage_constant.Length)
return $usage_key
}
# TCPClient Kerberos start - this section can be removed if not using a hash or -TCPClientAuth
function Get-KerberosAES256BaseKey
{
param([String]$salt,[System.Security.SecureString]$password)
$password_BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($password)
$password_cleartext = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($password_BSTR)
[Byte[]]$salt = [System.Text.Encoding]::UTF8.GetBytes($salt)
[Byte[]]$password_cleartext = [System.Text.Encoding]::UTF8.GetBytes($password_cleartext)
$constant = 0x6B,0x65,0x72,0x62,0x65,0x72,0x6F,0x73,0x7B,0x9B,0x5B,0x2B,0x93,0x13,0x2B,0x93,0x5C,0x9B,0xDC,0xDA,0xD9,0x5C,0x98,0x99,0xC4,0xCA,0xE4,0xDE,0xE6,0xD6,0xCA,0xE4
$PBKDF2 = New-Object Security.Cryptography.Rfc2898DeriveBytes($password_cleartext,$salt,4096)
Remove-Variable password_cleartext
$PBKDF2_key = $PBKDF2.GetBytes(32)
$AES = New-Object "System.Security.Cryptography.AesManaged"
$AES.Mode = [System.Security.Cryptography.CipherMode]::CBC
$AES.Padding = [System.Security.Cryptography.PaddingMode]::None
$AES.IV = 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
$AES.KeySize = 256
$AES.Key = $PBKDF2_key
$AES_encryptor = $AES.CreateEncryptor()
$base_key_part_1 = $AES_encryptor.TransformFinalBlock($constant,0,$constant.Length)
$base_key_part_2 = $AES_encryptor.TransformFinalBlock($base_key_part_1,0,$base_key_part_1.Length)
$base_key = $base_key_part_1[0..15] + $base_key_part_2[0..15]
return $base_key
}
function New-PacketKerberosASREQ()
{
param([Byte[]]$Username,[Byte[]]$Realm,[Byte[]]$NameString,[Byte[]]$Nonce,[Byte[]]$PAC,[Byte[]]$PACSignature)
$timestamp = Get-Date
$till = $timestamp.AddYears(20)
$timestamp = ("{0:u}" -f $timestamp) -replace "-","" -replace " ","" -replace ":",""
$till = ("{0:u}" -f $till) -replace "-","" -replace " ","" -replace ":",""
[Byte[]]$timestamp = [System.Text.Encoding]::UTF8.GetBytes($timestamp)
[Byte[]]$till = [System.Text.Encoding]::UTF8.GetBytes($till)
if($PAC)
{
$pac_extra_length = 78
}
[Byte[]]$namestring1_length = Get-ASN1LengthArray $NameString.Count
[Byte[]]$namestring_length = Get-ASN1LengthArray ($NameString.Count + $namestring1_length.Count + 6)
[Byte[]]$namestring_length2 = Get-ASN1LengthArray ($NameString.Count + $namestring1_length.Count + $namestring_length.Count + 7)
[Byte[]]$sname_length = Get-ASN1LengthArray ($NameString.Count + $namestring1_length.Count + $namestring_length.Count + $namestring_length2.Count + 13)
[Byte[]]$sname_length2 = Get-ASN1LengthArray ($NameString.Count + $namestring1_length.Count + $namestring_length.Count + $namestring_length2.Count + $sname_length.Count + 14)
[Byte[]]$realm_length = Get-ASN1LengthArray $Realm.Count
[Byte[]]$realm_length2 = Get-ASN1LengthArray ($Realm.Count + $realm_length.Count + 1)
[Byte[]]$cname_length = Get-ASN1LengthArray $Username.Count
[Byte[]]$cname_length2 = Get-ASN1LengthArray ($Username.Count + $cname_length.Count + 1)
[Byte[]]$cname_length3 = Get-ASN1LengthArray ($Username.Count + $cname_length.Count + $cname_length2.Count + 2)
[Byte[]]$cname_length4 = Get-ASN1LengthArray ($Username.Count + $cname_length.Count + $cname_length2.Count + $cname_length3.Count + 8)
[Byte[]]$cname_length5 = Get-ASN1LengthArray ($Username.Count + $cname_length.Count + $cname_length2.Count + $cname_length3.Count + $cname_length4.Count + 9)
$grouped_length = $address_length.Count + $address_length2.Count + $address_length3.Count + $address_length4.Count + $address_length5.Count + $NameString.Count +
$namestring1_length.Count + $namestring_length.Count + $namestring_length2.Count + $sname_length.Count + $sname_length2.Count + $Realm.Count + $realm_length.Count +
$realm_length2.Count + $Username.Count + $cname_length.Count + $cname_length2.Count + $cname_length3.Count + $cname_length4.Count + $cname_length5.Count
[Byte[]]$reqbody_length = Get-ASN1LengthArrayLong ($grouped_length + 86)
[Byte[]]$reqbody_length2 = Get-ASN1LengthArrayLong ($grouped_length + $reqbody_length.Count + 87)
[Byte[]]$message_length = Get-ASN1LengthArrayLong ($grouped_length + $reqbody_length.Count + $reqbody_length2.Count + $pac_extra_length + 114)
[Byte[]]$message_length2 = Get-ASN1LengthArrayLong ($grouped_length + $reqbody_length.Count + $reqbody_length2.Count + $message_length.Count + $pac_extra_length + 115)
[Byte[]]$asreq_length = [System.BitConverter]::GetBytes($grouped_length + $reqbody_length.Count + $reqbody_length2.Count + $message_length.Count + $message_length2.Count +
$pac_extra_length + 116)[3..0]
$KerberosASREQ = New-Object System.Collections.Specialized.OrderedDictionary
$KerberosASREQ.Add("Length",$asreq_length)
$KerberosASREQ.Add("Message_Encoding",[Byte[]](0x6a) + $message_length2 + [Byte[]](0x30) + $message_length)
$KerberosASREQ.Add("Message_PVNO_Encoding",[Byte[]](0xa1,0x03,0x02,0x01))
$KerberosASREQ.Add("Message_PVNO",[Byte[]](0x05))
$KerberosASREQ.Add("Message_MSGType_Encoding",[Byte[]](0xa2,0x03,0x02,0x01))
$KerberosASREQ.Add("Message_MSGType",[Byte[]](0x0a))
if($PAC)
{
$KerberosASREQ.Add("Message_PAData_Encoding",[Byte[]](0xa3,0x5c,0x30,0x5a,0x30,0x4c,0xa1,0x03,0x02,0x01,0x02))
$KerberosASREQ.Add("Message_PAData0_Type_Encoding",[Byte[]](0xa2,0x45,0x04,0x43,0x30,0x41,0xa0,0x03,0x02,0x01))
$KerberosASREQ.Add("Message_PAData0_Type",[Byte[]](0x12))
$KerberosASREQ.Add("Message_PAData0_Value_Encoding",[Byte[]](0xa2,0x3a,0x04,0x38))
$KerberosASREQ.Add("Message_PAData0_Value",$PAC)
$KerberosASREQ.Add("Message_PAData0_Signature",$PACSignature)
$KerberosASREQ.Add("Message_PAData1_Type_Encoding",[Byte[]](0x30,0x0a,0xa1,0x04,0x02,0x02))
}
else
{
$KerberosASREQ.Add("Message_PAData_Encoding",[Byte[]](0xa3,0x0e,0x30,0x0c,0x30,0x0a))
$KerberosASREQ.Add("Message_PAData1_Type_Encoding",[Byte[]](0xa1,0x04,0x02,0x02))
}
$KerberosASREQ.Add("Message_PAData1_Type",[Byte[]](0x00,0x95))
$KerberosASREQ.Add("Message_PAData1_Value_Encoding",[Byte[]](0xa2,0x02,0x04))
$KerberosASREQ.Add("Message_PAData1_Value",[Byte[]](0x00))
$KerberosASREQ.Add("Message_REQBody_Encoding",[Byte[]](0xa4) + $reqbody_length2 + [Byte[]](0x30) + $reqbody_length)
$KerberosASREQ.Add("Message_REQBody_KDCOptions_Encoding",[Byte[]](0xa0,0x07,0x03,0x05))
$KerberosASREQ.Add("Message_REQBody_KDCOptions_Padding",[Byte[]](0x00))
$KerberosASREQ.Add("Message_REQBody_KDCOptions",[Byte[]](0x50,0x00,0x00,0x00))
$KerberosASREQ.Add("Message_REQBody_CName_Encoding",[Byte[]](0xa1) + $cname_length5 + [Byte[]](0x30) + $cname_length4)
$KerberosASREQ.Add("Message_REQBody_CName_NameType_Encoding",[Byte[]](0xa0,0x03,0x02,0x01))
$KerberosASREQ.Add("Message_REQBody_CName_NameType",[Byte[]](0x01))
$KerberosASREQ.Add("Message_REQBody_CName_NameString_Encoding",[Byte[]](0xa1) + $cname_length3 + [Byte[]](0x30) + $cname_length2 + [Byte[]](0x1b) + $cname_length)
$KerberosASREQ.Add("Message_REQBody_CName_NameString",$Username)
$KerberosASREQ.Add("Message_REQBody_Realm_Encoding",[Byte[]](0xa2) + $realm_length2 + [Byte[]](0x1b) + $realm_length)
$KerberosASREQ.Add("Message_REQBody_Realm",$Realm)
$KerberosASREQ.Add("Message_REQBody_SName_Encoding",[Byte[]](0xa3) + $sname_length2 + [Byte[]](0x30) + $sname_length)
$KerberosASREQ.Add("Message_REQBody_SName_NameType_Encoding",[Byte[]](0xa0,0x03,0x02,0x01))
$KerberosASREQ.Add("Message_REQBody_SName_NameType",[Byte[]](0x01))
$KerberosASREQ.Add("Message_REQBody_SName_NameString_Encoding",[Byte[]](0xa1) + $namestring_length2 + [Byte[]](0x30) + $namestring_length)
$KerberosASREQ.Add("Message_REQBody_SName_NameString0_Encoding",[Byte[]](0x1b,0x03))
$KerberosASREQ.Add("Message_REQBody_SName_NameString0",[Byte[]](0x44,0x4e,0x53))
$KerberosASREQ.Add("Message_REQBody_SName_NameString1_Encoding",[Byte[]](0x1b) + $namestring1_length) #50
$KerberosASREQ.Add("Message_REQBody_SName_NameString1",$NameString)
$KerberosASREQ.Add("Message_REQBody_Till_Encoding",[Byte[]](0xa5,0x11,0x18,0x0f))
$KerberosASREQ.Add("Message_REQBody_Till",$till)
$KerberosASREQ.Add("Message_REQBody_Nonce_Encoding",[Byte[]](0xa7,0x06,0x02,0x04))
$KerberosASREQ.Add("Message_REQBody_Nonce",$Nonce)
$KerberosASREQ.Add("Message_REQBody_EType_Encoding",[Byte[]](0xa8,0x15,0x30,0x13))
$KerberosASREQ.Add("Message_REQBody_EType",[Byte[]](0x02,0x01,0x12,0x02,0x01,0x11,0x02,0x01,0x17,0x02,0x01,0x18,0x02,0x02,0xff,0x79,0x02,0x01,0x03))
return $KerberosASREQ
}
function New-PacketKerberosAPREQ()
{
param([Byte[]]$Realm,[Byte[]]$SPN,[Byte[]]$KVNO,[Byte[]]$Ticket,[Byte[]]$Authenticator,[Byte[]]$AuthenticatorSignature)
$Authenticator += $AuthenticatorSignature
$parameter_length = $Realm.Count + $SPN.Count + $ticket.Count + $Authenticator.Count
[Byte[]]$authenticator_length = Get-ASN1LengthArrayLong $Authenticator.Count
[Byte[]]$authenticator_length2 = Get-ASN1LengthArrayLong ($Authenticator.Count + $authenticator_length.Count + 1)
[Byte[]]$Authenticator_length3 = Get-ASN1LengthArrayLong ($authenticator.Count + $authenticator_length.Count + $authenticator_length2.Count + 7)
[Byte[]]$authenticator_length4 = Get-ASN1LengthArrayLong ($Authenticator.Count + $authenticator_length.Count + $authenticator_length2.Count + $authenticator_length3.Count + 8)
[Byte[]]$ticket_length = Get-ASN1LengthArrayLong $ticket.Count
[Byte[]]$ticket_length2 = Get-ASN1LengthArrayLong ($ticket.Count + $ticket_length.Count + 1)
[Byte[]]$ticket_length3 = Get-ASN1LengthArrayLong ($ticket.Count + $ticket_length.Count + $ticket_length2.Count + 12)
[Byte[]]$ticket_length4 = Get-ASN1LengthArrayLong ($ticket.Count + $ticket_length.Count + $ticket_length2.Count + $ticket_length3.Count + 13)
[Byte[]]$namestring1_length = Get-ASN1LengthArray $SPN.Count
[Byte[]]$namestring_length = Get-ASN1LengthArray ($SPN.Count + $namestring_length.Count + 4)
[Byte[]]$namestring_length2 = Get-ASN1LengthArray ($SPN.Count + $namestring1_length.Count + $namestring_length.Count + 5)
[Byte[]]$sname_length = Get-ASN1LengthArray ($SPN.Count + $namestring1_length.Count + $namestring_length.Count + $namestring_length2.Count + 4)
[Byte[]]$sname_length2 = Get-ASN1LengthArray ($SPN.Count + $namestring1_length.Count + $namestring_length.Count + $namestring_length2.Count + $sname_length.Count + 5)
[Byte[]]$sname_length3 = Get-ASN1LengthArray ($SPN.Count + $namestring1_length.Count + $namestring_length.Count + $namestring_length2.Count + $sname_length.Count + $sname_length2.Count + 11)
[Byte[]]$sname_length4 = Get-ASN1LengthArray ($SPN.Count + $namestring1_length.Count + $namestring_length.Count + $namestring_length2.Count + $sname_length.Count + $sname_length2.Count +
$sname_length3.Count + 12)
[Byte[]]$realm_length = Get-ASN1LengthArray $Realm.Count
[Byte[]]$realm_length2 = Get-ASN1LengthArray ($Realm.Count + $realm_length.Count + 1)
[Byte[]]$ticket_length5 = Get-ASN1LengthArrayLong ($ticket.Count + $ticket_length.Count + $ticket_length2.Count + $ticket_length3.Count + $ticket_length4.Count +
$SPN.Count + $namestring1_length.Count + $namestring_length.Count + $namestring_length2.Count + $sname_length.Count + $sname_length2.Count +
$sname_length3.Count + $sname_length4.Count + $Realm.Count + $realm_length.Count + $realm_length2.Count + 34)
[Byte[]]$ticket_length6 = Get-ASN1LengthArrayLong ($ticket.Count + $ticket_length.Count + $ticket_length2.Count + $ticket_length3.Count + $ticket_length4.Count +
$SPN.Count + $namestring1_length.Count + $namestring_length.Count + $namestring_length2.Count + $sname_length.Count + $sname_length2.Count +
$sname_length3.Count + $sname_length4.Count + $Realm.Count + $realm_length.Count + $realm_length2.Count + $ticket_length5.Count + 35)
[Byte[]]$ticket_length7 = Get-ASN1LengthArrayLong ($ticket.Count + $ticket_length.Count + $ticket_length2.Count + $ticket_length3.Count + $ticket_length4.Count +
$SPN.Count + $namestring1_length.Count + $namestring_length.Count + $namestring_length2.Count + $sname_length.Count + $sname_length2.Count +
$sname_length3.Count + $sname_length4.Count + $Realm.Count + $realm_length.Count + $realm_length2.Count + $ticket_length5.Count + $ticket_length6.Count + 36)
[Byte[]]$apreq_length = Get-ASN1LengthArrayLong ($parameter_length + $ticket_length.Count + $ticket_length2.Count + $ticket_length3.Count +
$ticket_length4.Count + $namestring1_length.Count + $namestring_length.Count + $namestring_length2.Count + $sname_length.Count + $sname_length2.Count +
$sname_length3.Count + $sname_length4.Count + $realm_length.Count + $realm_length2.Count + $ticket_length5.Count + $ticket_length6.Count + $ticket_length7.Count + 73)
[Byte[]]$apreq_length2 = Get-ASN1LengthArrayLong ($parameter_length + $ticket_length.Count + $ticket_length2.Count + $ticket_length3.Count +
$ticket_length4.Count + $namestring1_length.Count + $namestring_length.Count + $namestring_length2.Count + $sname_length.Count + $sname_length2.Count +
$sname_length3.Count + $sname_length4.Count + $realm_length.Count + $realm_length2.Count + $ticket_length5.Count + $ticket_length6.Count + $ticket_length7.Count +
$apreq_length.Count + 74)
[Byte[]]$length = Get-ASN1LengthArrayLong ($parameter_length + $ticket_length.Count + $ticket_length2.Count + $ticket_length3.Count +
$ticket_length4.Count + $namestring1_length.Count + $namestring_length.Count + $namestring_length2.Count + $sname_length.Count + $sname_length2.Count +
$sname_length3.Count + $sname_length4.Count + $realm_length.Count + $realm_length2.Count + $ticket_length5.Count + $ticket_length6.Count + $ticket_length7.Count +
$apreq_length.Count + $apreq_length2.Count + 88)
$KerberosAPREQ = New-Object System.Collections.Specialized.OrderedDictionary
$KerberosAPREQ.Add("Length",([Byte[]](0x60) + $length))
$KerberosAPREQ.Add("MechToken_ThisMech",[Byte[]](0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x12,0x01,0x02,0x02))
$KerberosAPREQ.Add("MechToken_TokenID",[Byte[]](0x01,0x00))
$KerberosAPREQ.Add("APReq_Encoding",[Byte[]](0x6e) + $apreq_length2 + [Byte[]](0x30) + $apreq_length)
$KerberosAPREQ.Add("PVNO_Encoding",[Byte[]](0xa0,0x03,0x02,0x01))
$KerberosAPREQ.Add("PVNO",[Byte[]]0x05)
$KerberosAPREQ.Add("MSGType_Encoding",[Byte[]](0xa1,0x03,0x02,0x01))
$KerberosAPREQ.Add("MSGType",[Byte[]](0x0e))
$KerberosAPREQ.Add("Padding_Encoding",[Byte[]](0xa2,0x07,0x03,0x05))
$KerberosAPREQ.Add("Padding",[Byte[]](0x00))
$KerberosAPREQ.Add("APOptions",[Byte[]](0x20,0x00,0x00,0x00))
$KerberosAPREQ.Add("Ticket_Encoding",[Byte[]](0xa3) + $ticket_length7 + [Byte[]](0x61) + $ticket_length6 + [Byte[]](0x30) + $ticket_length5)
$KerberosAPREQ.Add("Ticket_TKTVNO_Encoding",[Byte[]](0xa0,0x03,0x02,0x01))
$KerberosAPREQ.Add("Ticket_TKTVNO",[Byte[]](0x05))
$KerberosAPREQ.Add("Ticket_Realm_Encoding",[Byte[]](0xa1) + $realm_length2 + [Byte[]](0x1b) + $realm_length)
$KerberosAPREQ.Add("Ticket_Realm",$Realm)
$KerberosAPREQ.Add("Ticket_SName_Encoding",[Byte[]](0xa2) + $sname_length4 + [Byte[]](0x30) + $sname_length3)
$KerberosAPREQ.Add("Ticket_SName_NameType_Encoding",[Byte[]](0xa0,0x03,0x02,0x01))
$KerberosAPREQ.Add("Ticket_SName_NameType",[Byte[]](0x01))
$KerberosAPREQ.Add("Ticket_SName_NameString_Encoding",[Byte[]](0xa1) + $sname_length2 + [Byte[]](0x30) + $sname_length)
$KerberosAPREQ.Add("Ticket_SName_NameString0_Encoding",[Byte[]](0x1b,0x03))
$KerberosAPREQ.Add("Ticket_SName_NameString0",[Byte[]](0x44,0x4e,0x53))
$KerberosAPREQ.Add("Ticket_SName_NameString1_Encoding",[Byte[]](0x1b) + $namestring1_length)
$KerberosAPREQ.Add("Ticket_SName_NameString1",$SPN)
$KerberosAPREQ.Add("Ticket_EncPart_Encoding",[Byte[]](0xa3) + $ticket_length4 + [Byte[]](0x30) + $ticket_length3)
$KerberosAPREQ.Add("Ticket_EncPart_EType_Encoding",[Byte[]](0xa0,0x03,0x02,0x01))
$KerberosAPREQ.Add("Ticket_EncPart_EType",[Byte[]](0x12))
$KerberosAPREQ.Add("Ticket_EncPart_KVNO_Encoding",[Byte[]](0xa1,0x03,0x02,0x01))
$KerberosAPREQ.Add("Ticket_EncPart_KVNO",$KVNO)
$KerberosAPREQ.Add("Ticket_EncPart_Cipher_Encoding",[Byte[]](0xa2) + $ticket_length2 + [Byte[]](0x04) + $ticket_length)
$KerberosAPREQ.Add("Ticket_EncPart_Cipher",$ticket)
$KerberosAPREQ.Add("Authenticator_Encoding",[Byte[]](0xa4) + $authenticator_length4 + [Byte[]](0x30) + $authenticator_length3)
$KerberosAPREQ.Add("Authenticator_EType_Encoding",[Byte[]](0xa0,0x03,0x02,0x01))
$KerberosAPREQ.Add("Authenticator_EType",[Byte[]](0x12))
$KerberosAPREQ.Add("Authenticator_Cipher_Encoding",[Byte[]](0xa2) + $authenticator_length2 + [Byte[]](0x04) + $authenticator_length)
$KerberosAPREQ.Add("Authenticator_Cipher",$Authenticator)
return $KerberosAPREQ
}
function Unprotect-KerberosASREP
{
param([Byte[]]$ke_key,[Byte[]]$encrypted_data)
$final_block_length = [Math]::Truncate($encrypted_data.Count % 16)
[Byte[]]$final_block = $encrypted_data[($encrypted_data.Count - $final_block_length)..$encrypted_data.Count]
[Byte[]]$penultimate_block = $encrypted_data[($encrypted_data.Count - $final_block_length - 16)..($encrypted_data.Count - $final_block_length - 1)]
$AES = New-Object "System.Security.Cryptography.AesManaged"
$AES.Mode = [System.Security.Cryptography.CipherMode]::CBC
$AES.Padding = [System.Security.Cryptography.PaddingMode]::Zeros
$AES.IV = 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
$AES.KeySize = 256
$AES.Key = $ke_key
$AES_decryptor = $AES.CreateDecryptor()
$penultimate_block_cleartext = $AES_decryptor.TransformFinalBlock($penultimate_block,0,$penultimate_block.Length)
[Byte[]]$final_block_padding = $penultimate_block_cleartext[$final_block_length..$penultimate_block_cleartext.Count]
$final_block += $final_block_padding
[Byte[]]$cts_encrypted_data = $encrypted_data[0..($encrypted_data.Count - $final_block_length - 17)] + $final_block + $penultimate_block
[Byte[]]$cleartext = $AES_decryptor.TransformFinalBlock($cts_encrypted_data,0,$cts_encrypted_data.Length)
return $cleartext
}
function New-KerberosPACTimestamp
{
param([Byte[]]$ke_key)
[Byte[]]$timestamp = Get-KerberosTimestampUTC
[String]$confounder = [String](1..16 | ForEach-Object {"{0:X2}" -f (Get-Random -Minimum 1 -Maximum 255)})
[Byte[]]$confounder = $confounder.Split(" ") | ForEach-Object{[Char][System.Convert]::ToInt16($_,16)}
[Byte[]]$PAC_timestamp = $confounder +
0x30,0x1a,0xa0,0x11,0x18,0x0f +
$timestamp +
0xa1,0x05,0x02,0x03,0x01,0x70,0x16
return $PAC_timestamp
}
function New-KerberosAuthenticator
{
param([Byte[]]$Realm,[Byte[]]$Username,[Byte[]]$SubKey,[Byte[]]$SequenceNumber)
$parameter_length = $Realm.Count + $Username.Count + $SubKey.Count
[Byte[]]$subkey_length = Get-ASN1LengthArray $SubKey.Count
[Byte[]]$subkey_length2 = Get-ASN1LengthArray ($SubKey.Count + $subkey_length.Count + 1)
[Byte[]]$subkey_length3 = Get-ASN1LengthArray ($SubKey.Count + $subkey_length.Count + $subkey_length2.Count + 7)
[Byte[]]$subkey_length4 = Get-ASN1LengthArray ($SubKey.Count + $subkey_length.Count + $subkey_length2.Count + $subkey_length3.Count + 8)
[Byte[]]$cname_length = Get-ASN1LengthArray $Username.Count
[Byte[]]$cname_length2 = Get-ASN1LengthArray ($Username.Count + $cname_length.Count + 1)
[Byte[]]$cname_length3 = Get-ASN1LengthArray ($Username.Count + $cname_length.Count + $cname_length2.Count + 2)
[Byte[]]$cname_length4 = Get-ASN1LengthArray ($Username.Count + $cname_length.Count + $cname_length2.Count + $cname_length3.Count + 8)
[Byte[]]$cname_length5 = Get-ASN1LengthArray ($Username.Count + $cname_length.Count + $cname_length2.Count + $cname_length3.Count + $cname_length4.Count + 9)
[Byte[]]$crealm_length = Get-ASN1LengthArray $Realm.Count
[Byte[]]$crealm_length2 = Get-ASN1LengthArray ($Realm.Count + $crealm_length.Count + 1)
[Byte[]]$authenticator_length = Get-ASN1LengthArrayLong ($parameter_length + 99 + $crealm_length.Count + $crealm_length2.Count +
$cname_length.Count + $cname_length2.Count + $cname_length3.Count + $cname_length4.Count + $cname_length5.Count + $subkey_length.Count +
$subkey_length2.Count + $subkey_length3.Count + $subkey_length4.Count)
[Byte[]]$authenticator_length2 = Get-ASN1LengthArrayLong ($parameter_length + 100 + $crealm_length.Count + $crealm_length2.Count +
$cname_length.Count + $cname_length2.Count + $cname_length3.Count + $cname_length4.Count + $cname_length5.Count + $subkey_length.Count +
$subkey_length2.Count + $subkey_length3.Count + $subkey_length4.Count + $authenticator_length.Count)
$KerberosAuthenticator = New-Object System.Collections.Specialized.OrderedDictionary
$KerberosAuthenticator.Add("Encoding",[Byte[]](0x62) + $authenticator_length2 + [Byte[]](0x30) + $authenticator_length)
$KerberosAuthenticator.Add("AuthenticatorVNO_Encoding",[Byte[]](0xa0,0x03,0x02,0x01))
$KerberosAuthenticator.Add("AuthenticatorVNO",[Byte[]](0x05))
$KerberosAuthenticator.Add("CRealm_Encoding",[Byte[]](0xa1) + $crealm_length2 + [Byte[]](0x1b) + $crealm_length)
$KerberosAuthenticator.Add("CRealm",$Realm)
$KerberosAuthenticator.Add("CName_Encoding",[Byte[]](0xa2) + $cname_length5 + [Byte[]](0x30) + $cname_length4)
$KerberosAuthenticator.Add("CName_NameType_Encoding",[Byte[]](0xa0,0x03,0x02,0x01))
$KerberosAuthenticator.Add("CName_NameType",[Byte[]](0x01))
$KerberosAuthenticator.Add("CName_CNameString_Encoding",[Byte[]](0xa1) + $cname_length3 + [Byte[]](0x30) +
$cname_length2 + [Byte[]](0x1b) + $cname_length)
$KerberosAuthenticator.Add("CName_CNameString",$Username)
$KerberosAuthenticator.Add("CKSum_Encoding",[Byte[]](0xa3,0x25,0x30,0x23,0xa0,0x05,0x02,0x03))
$KerberosAuthenticator.Add("CKSum_CKSumType",[Byte[]](0x00,0x80,0x03))
$KerberosAuthenticator.Add("CKSum_Length_Encoding",[Byte[]](0xa1,0x1a,0x04,0x18))
$KerberosAuthenticator.Add("CKSum_Length",[Byte[]](0x10,0x00,0x00,0x00))
$KerberosAuthenticator.Add("CKSum_Bnd",[Byte[]](0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00))
$KerberosAuthenticator.Add("CKSum_Flags",[Byte[]](0x36,0x01,0x00,0x00))
$KerberosAuthenticator.Add("CKSum_CUSec_Encoding",[Byte[]](0xa4,0x05,0x02,0x03))
$KerberosAuthenticator.Add("CKSum_CUSec",(Get-KerberosMicrosecond))
$KerberosAuthenticator.Add("CKSum_CTime_Encoding",[Byte[]](0xa5,0x11,0x18,0x0f))
$KerberosAuthenticator.Add("CKSum_CTime",(Get-KerberosTimestampUTC))
$KerberosAuthenticator.Add("CKSum_Subkey_Encoding",[Byte[]](0xa6) + $subkey_length4 + [Byte[]](0x30) + $subkey_length3)
$KerberosAuthenticator.Add("CKSum_Subkey_KeyType_Encoding",[Byte[]](0xa0,0x03,0x02,0x01))
$KerberosAuthenticator.Add("CKSum_Subkey_KeyType",[Byte[]](0x12))
$KerberosAuthenticator.Add("CKSum_Subkey_KeyValue_Encoding",[Byte[]](0xa1) + $subkey_length2 + [Byte[]](0x04) + $subkey_length)
$KerberosAuthenticator.Add("CKSum_Subkey_KeyValue",$SubKey)
$KerberosAuthenticator.Add("CKSum_SEQNumber_Encoding",[Byte[]](0xa7,0x06,0x02,0x04))
$KerberosAuthenticator.Add("CKSum_SEQNumber",$SequenceNumber)
return $KerberosAuthenticator
}
function Get-KerberosTimestampUTC
{
[DateTime]$timestamp = (Get-Date).ToUniversalTime()
[String]$timestamp = ("{0:u}" -f $timestamp) -replace "-","" -replace " ","" -replace ":",""
[Byte[]]$timestamp = [System.Text.Encoding]::UTF8.GetBytes($timestamp)
return $timestamp
}
function Get-KerberosMicrosecond
{
[Int]$microseconds = Get-Date -Format ffffff
[Byte[]]$microseconds = [System.Bitconverter]::GetBytes($microseconds)[0..2]
return $microseconds
}
function Protect-KerberosAES256CTS
{
param([Byte[]]$ke_key,[Byte[]]$data)
$AES = New-Object "System.Security.Cryptography.AesManaged"
$AES.Mode = [System.Security.Cryptography.CipherMode]::CBC
$AES.Padding = [System.Security.Cryptography.PaddingMode]::Zeros
$IV = 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
$AES.IV = $IV
$AES.KeySize = 256
$AES.Key = $ke_key
$AES_encryptor = $AES.CreateEncryptor()
$data_encrypted = $AES_encryptor.TransformFinalBlock($data,0,$data.Length)
$block_count = [Math]::Ceiling($data_encrypted.Count / 16)
if($block_count -gt 2)
{
$data_encrypted = $data_encrypted[0..($data_encrypted.Count - 33)] + $data_encrypted[($data_encrypted.Count - 16)..$data_encrypted.Count] +
$data_encrypted[($data_encrypted.Count - 32)..($data_encrypted.Count - 17)]
}
elseif($blocks -eq 2)
{
$data_encrypted = $data_encrypted[16..31] + $data_encrypted[0..15]
}
$final_block_length = [Math]::Truncate($data.Count % 16)
if($final_block_length -ne 0)
{
$remove_count = 16 - $final_block_length
$data_encrypted = $data_encrypted[0..($data_encrypted.Count - $remove_count - 1)]
}
return $data_encrypted
}
# TCPClient Kerberos end
function Get-KerberosHMACSHA1
{
param([Byte[]]$key,[Byte[]]$data)
$HMAC_SHA1 = New-Object System.Security.Cryptography.HMACSHA1
$HMAC_SHA1.key = $key
$hash = $HMAC_SHA1.ComputeHash($data)
$hash = $hash[0..11]
return $hash
}
function Get-ASN1LengthArray
{
param([Int]$Length)
[Byte[]]$asn1 = [System.BitConverter]::GetBytes($Length)
if($asn1[1] -eq 0)
{
$asn1 = $asn1[0]
}
else
{
$asn1 = $asn1[1,0]
}
return $asn1
}
function Get-ASN1LengthArrayLong
{
param([Int]$Length)
[Byte[]]$asn1 = [System.BitConverter]::GetBytes($Length)
if($asn1[1] -eq 0)
{
$asn1 = $asn1[0]
$asn1 = [Byte[]]0x81 + $asn1
}
else
{
$asn1 = $asn1[1,0]
$asn1 = [Byte[]]0x82 + $asn1
}
return $asn1
}
function New-RandomByteArray
{
param([Int]$Length,[Int]$Minimum=1,[Int]$Maximum=255)
[String]$random = [String](1..$Length | ForEach-Object {"{0:X2}" -f (Get-Random -Minimum $Minimum -Maximum $Maximum)})
[Byte[]]$random = $random.Split(" ") | ForEach-Object{[Char][System.Convert]::ToInt16($_,16)}
return $random
}
function New-DNSNameArray
{
param([String]$Name)
$character_array = $Name.ToCharArray()
[Array]$index_array = 0..($character_array.Count - 1) | Where-Object {$character_array[$_] -eq '.'}
if($index_array.Count -gt 0)
{
$name_start = 0
ForEach ($index in $index_array)
{
$name_end = $index - $name_start
[Byte[]]$name_array += $name_end
[Byte[]]$name_array += [System.Text.Encoding]::UTF8.GetBytes($Name.Substring($name_start,$name_end))
$name_start = $index + 1
}
[Byte[]]$name_array += ($Name.Length - $name_start)
[Byte[]]$name_array += [System.Text.Encoding]::UTF8.GetBytes($Name.Substring($name_start))
}
else
{
[Byte[]]$name_array = $Name.Length
[Byte[]]$name_array += [System.Text.Encoding]::UTF8.GetBytes($Name.Substring($name_start))
}
return $name_array
}
function New-PacketDNSQuery
{
param([String]$Name,[String]$Type)
switch ($Type)
{
'A'
{[Byte[]]$type = 0x00,0x01}
'AAAA'
{[Byte[]]$type = 0x00,0x1c}
'CNAME'
{[Byte[]]$type = 0x00,0x05}
'MX'
{[Byte[]]$type = 0x00,0x0f}
'PTR'
{[Byte[]]$type = 0x00,0x0c}
'SRV'
{[Byte[]]$type = 0x00,0x21}
'TXT'
{[Byte[]]$type = 0x00,0x10}
}
[Byte[]]$name = (New-DNSNameArray $Name) + 0x00
[Byte[]]$length = [System.BitConverter]::GetBytes($Name.Count + 16)[1,0]
[Byte[]]$transaction_ID = New-RandomByteArray 2
$DNSQuery = New-Object System.Collections.Specialized.OrderedDictionary
$DNSQuery.Add("Length",$length)
$DNSQuery.Add("TransactionID",$transaction_ID)
$DNSQuery.Add("Flags",[Byte[]](0x01,0x00))
$DNSQuery.Add("Questions",[Byte[]](0x00,0x01))
$DNSQuery.Add("AnswerRRs",[Byte[]](0x00,0x00))
$DNSQuery.Add("AuthorityRRs",[Byte[]](0x00,0x00))
$DNSQuery.Add("AdditionalRRs",[Byte[]](0x00,0x00))
$DNSQuery.Add("Queries_Name",$name)
$DNSQuery.Add("Queries_Type",$type)
$DNSQuery.Add("Queries_Class",[Byte[]](0x00,0x01))
return $DNSQuery
}
function New-PacketDNSQueryTKEY
{
param([Byte[]]$Name,[byte[]]$Type,[Byte[]]$APReq)
[Byte[]]$transaction_ID = New-RandomByteArray 2
if($APReq)
{
$mechtoken_length = Get-ASN1LengthArrayLong ($APReq.Count)
$mechtoken_length2 = Get-ASN1LengthArrayLong ($APReq.Count + $mechtoken_length.Count + 1)
$innercontexttoken_length = Get-ASN1LengthArrayLong ($APReq.Count + $mechtoken_length.Count + $mechtoken_length2.Count + 17) # 31
$innercontexttoken_length2 = Get-ASN1LengthArrayLong ($APReq.Count + $mechtoken_length.Count + $mechtoken_length2.Count +
$innercontexttoken_length.Count + 18)
$spnego_length = Get-ASN1LengthArrayLong ($APReq.Count + $mechtoken_length.Count + $mechtoken_length2.Count +
$innercontexttoken_length.Count + $innercontexttoken_length2.Count + 27)
$grouped_length = $APReq.Count + $mechtoken_length.Count + $mechtoken_length2.Count + $innercontexttoken_length.Count +
$innercontexttoken_length2.Count + $spnego_length.Count + 25
$key_size = [System.BitConverter]::GetBytes($grouped_length + 3)[1,0]
$RD_length = [System.BitConverter]::GetBytes($grouped_length + $key_size.Count + 27)[1,0]
$inception = [int64](([datetime]::UtcNow)-(Get-Date "1/1/1970")).TotalSeconds
$inception = [System.BitConverter]::GetBytes($inception)
$inception = $inception[3..0]
}
if($APReq)
{
[Byte[]]$length = [System.BitConverter]::GetBytes($grouped_length + $Name.Count + 57)[1,0]
}
else
{
[Byte[]]$length = [System.BitConverter]::GetBytes($Name.Count + 16)[1,0]
}
$DNSQueryTKEY = New-Object System.Collections.Specialized.OrderedDictionary
$DNSQueryTKEY.Add("Length",$length)
$DNSQueryTKEY.Add("TransactionID",$transaction_ID)
$DNSQueryTKEY.Add("Flags",[Byte[]](0x00,0x00))
$DNSQueryTKEY.Add("Questions",[Byte[]](0x00,0x01))
$DNSQueryTKEY.Add("AnswerRRs",[Byte[]](0x00,0x00))
$DNSQueryTKEY.Add("AuthorityRRs",[Byte[]](0x00,0x00))
if($apreq)
{
$DNSQueryTKEY.Add("AdditionalRRs",[Byte[]](0x00,0x01))
}
else
{
$DNSQueryTKEY.Add("AdditionalRRs",[Byte[]](0x00,0x00))
}
$DNSQueryTKEY.Add("Queries_Name",$Name)
$DNSQueryTKEY.Add("Queries_Type",$Type)
$DNSQueryTKEY.Add("Queries_Class",[Byte[]](0x00,0xff))
if($apreq)
{
$DNSQueryTKEY.Add("Queries_AdditionalRecords_Name",[Byte[]](0xc0,0x0c))
$DNSQueryTKEY.Add("Queries_AdditionalRecords_Type",[Byte[]](0x00,0xf9))
$DNSQueryTKEY.Add("Queries_AdditionalRecords_Class",[Byte[]](0x00,0xff))
$DNSQueryTKEY.Add("Queries_AdditionalRecords_TTL",[Byte[]](0x00,0x00,0x00,0x00))
$DNSQueryTKEY.Add("Queries_AdditionalRecords_RDLength",$RD_length)
$DNSQueryTKEY.Add("Queries_AdditionalRecords_RData_Algorithm",[Byte[]](0x08,0x67,0x73,0x73,0x2d,0x74,0x73,0x69,0x67,0x00))
$DNSQueryTKEY.Add("Queries_AdditionalRecords_RData_Inception",$inception)
$DNSQueryTKEY.Add("Queries_AdditionalRecords_RData_Expiration",$inception)
$DNSQueryTKEY.Add("Queries_AdditionalRecords_RData_Mode",[Byte[]](0x00,0x03))
$DNSQueryTKEY.Add("Queries_AdditionalRecords_RData_Error",[Byte[]](0x00,0x00))
$DNSQueryTKEY.Add("Queries_AdditionalRecords_RData_KeySize",$key_size)
$DNSQueryTKEY.Add("Queries_AdditionalRecords_RData_SPNego_Encoding",[Byte[]](0x60) + $spnego_length)
$DNSQueryTKEY.Add("Queries_AdditionalRecords_RData_SPNego_ThisMech",[Byte[]](0x06,0x06,0x2b,0x06,0x01,0x05,0x05,0x02))
$DNSQueryTKEY.Add("Queries_AdditionalRecords_RData_SPNego_InnerContextToken_Encoding",[Byte[]](0xa0) + $innercontexttoken_length2 + [Byte[]](0x30) +
$innercontexttoken_length)
$DNSQueryTKEY.Add("Queries_AdditionalRecords_RData_SPNego_InnerContextToken_MechTypes_Encoding",[Byte[]](0xa0,0x0d,0x30,0x0b))
$DNSQueryTKEY.Add("Queries_AdditionalRecords_RData_SPNego_InnerContextToken_MechType0",[Byte[]](0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x12,0x01,0x02,0x02))
$DNSQueryTKEY.Add("Queries_AdditionalRecords_RData_SPNego_InnerContextToken_MechToken_Encoding",[Byte[]](0xa2) + $mechtoken_length2 + [Byte[]](0x04) +
$mechtoken_length)
$DNSQueryTKEY.Add("Queries_AdditionalRecords_RData_SPNego_InnerContextToken_MechToken_Token",$APReq)
$DNSQueryTKEY.Add("Queries_AdditionalRecords_RData_OtherSize",[Byte[]](0x00,0x00))
}
return $DNSQueryTKEY
}
function New-PacketDNSUpdate
{
param([Byte[]]$TransactionID,[String]$Zone,[String]$Name,[String]$Type,[Int]$TTL,[Int]$Preference,[Int]$Priority,[Int]$Weight,[Int]$Port,[String]$Data,[Byte[]]$TimeSigned,[Byte[]]$TKeyname,[Byte[]]$MAC)
if($Data)
{
$add = $true
[Byte[]]$class = 0x00,0x01
}
else
{
[Byte[]]$class = 0x00,0xff
$TTL = 0
}
switch ($Type)
{
'A'
{
[Byte[]]$type = 0x00,0x01
if($Data -and [Bool]($Data -as [System.Net.IPAddress]))
{
[Byte[]]$data = ([System.Net.IPAddress][String]([System.Net.IPAddress]$Data)).GetAddressBytes()
}
elseif($Data)
{
[Byte[]]$data = [System.Text.Encoding]::UTF8.GetBytes($Data)
}
}
'AAAA'
{
[Byte[]]$type = 0x00,0x1c
if($Data -and [Bool]($Data -as [System.Net.IPAddress]))
{
[Byte[]]$data = ([System.Net.IPAddress][String]([System.Net.IPAddress]$Data)).GetAddressBytes()
}
elseif($Data)
{
[Byte[]]$data = [System.Text.Encoding]::UTF8.GetBytes($Data)
}
}
'CNAME'
{
[Byte[]]$type = 0x00,0x05
if($Data -and [Bool]($Data -as [System.Net.IPAddress]))
{
[Byte[]]$data = (New-DNSNameArray $Data) + 0x00
}
elseif($Data)
{
[Byte[]]$data = (New-DNSNameArray ($Data -replace ('.' + $Zone),'')) + 0xc0,0x0c
}
}
'MX'
{
$MX = $true
[Byte[]]$type = 0x00,0x0f
if($Data)
{
$extra_length = 2
[Byte[]]$preference = [System.Bitconverter]::GetBytes($Preference)[1,0]
}
if($Data -and [Bool]($Data -as [System.Net.IPAddress]))
{
[Byte[]]$data = (New-DNSNameArray $Data) + 0x00
}
elseif($Data)
{
[Byte[]]$data = (New-DNSNameArray ($Data -replace ('.' + $Zone),'')) + 0xc0,0x0c
}
}
'PTR'
{
[Byte[]]$type = 0x00,0x0c
if($Data)
{
[Byte[]]$data = (New-DNSNameArray $Data) + 0x00
}
}
'SRV'
{
$SRV = $true
[Byte[]]$type = 0x00,0x21
if($Data)
{
[Byte[]]$priority = [System.Bitconverter]::GetBytes($Priority)[1,0]
[Byte[]]$weight = [System.Bitconverter]::GetBytes($Weight)[1,0]
[Byte[]]$port = [System.Bitconverter]::GetBytes($Port)[1,0]
$extra_length = 6
[Byte[]]$data = (New-DNSNameArray $Data) + 0x00
}
}
'TXT'
{
$TXT = $true
[Byte[]]$type = 0x00,0x10
[Byte[]]$TXT_length = [System.BitConverter]::GetBytes($Data.Length)[0]
if($Data)
{
$extra_length = 1
[Byte[]]$data = [System.Text.Encoding]::UTF8.GetBytes($Data)
}
}
}
if($Name -eq $Zone)
{
[Byte[]]$name = 0xc0,0x0c
}
else
{
[Byte[]]$name = (New-DNSNameArray ($Name -replace ('.' + $Zone),'')) + 0xc0,0x0c
}
[Byte[]]$Zone = (New-DNSNameArray $Zone) + 0x00
[Byte[]]$TTL = [System.Bitconverter]::GetBytes($TTL)[3..0]
[Byte[]]$data_length = [System.BitConverter]::GetBytes($data.Length + $extra_length)[1,0]
if($MAC)
{
[Byte[]]$length = [System.BitConverter]::GetBytes($Zone.Count + $name.Count + $data.Length + $TKeyname.Count + $MAC.Count + 62 + $extra_length)[1,0]
}
elseif(!$TKeyname)
{
[Byte[]]$length = [System.BitConverter]::GetBytes($Zone.Count + $name.Count + $data.Length + 26 + $extra_length)[1,0]
}
$DNSUpdate = New-Object System.Collections.Specialized.OrderedDictionary
if(!$TKeyname -or $MAC)
{
$DNSUpdate.Add("Length",$length)
}
$DNSUpdate.Add("TransactionID",$TransactionID)
$DNSUpdate.Add("Flags",[Byte[]](0x28,0x00))
$DNSUpdate.Add("Zones",[Byte[]](0x00,0x01))
$DNSUpdate.Add("Prerequisites",[Byte[]](0x00,0x00))
$DNSUpdate.Add("Updates",[Byte[]](0x00,0x01))
if($MAC)
{
$DNSUpdate.Add("AdditionalRRs",[Byte[]](0x00,0x01))
}
else
{
$DNSUpdate.Add("AdditiionalRRs",[Byte[]](0x00,0x00))
}
$DNSUpdate.Add("Zone_Name",$Zone)
$DNSUpdate.Add("Zone_Type",[Byte[]](0x00,0x06))
$DNSUpdate.Add("Zone_Class",[Byte[]](0x00,0x01))
$DNSUpdate.Add("Updates_Name",$name)
$DNSUpdate.Add("Updates_Type",$type)
$DNSUpdate.Add("Updates_Class",$class)
$DNSUpdate.Add("Updates_TTL",$TTL)
$DNSUpdate.Add("Updates_DataLength",$data_length)
if($MX)
{
$DNSUpdate.Add("Updates_TXTLength",$preference)
}
if($TXT -and $add)
{
$DNSUpdate.Add("Updates_TXTLength",$TXT_length)
}
if($SRV -and $add)
{
$DNSUpdate.Add("Updates_Priority",$priority)
$DNSUpdate.Add("Updates_Weight",$weight)
$DNSUpdate.Add("Updates_Port",$port)
}
if($add)
{
$DNSUpdate.Add("Updates_Address",$data)
}
if($TKeyname)
{
$DNSUpdate.Add("AdditionalRecords_Name",$TKeyname)
if($MAC)
{
$DNSUpdate.Add("AdditionalRecords_Type",[Byte[]](0x00,0xfa))
}
$DNSUpdate.Add("AdditionalRecords_Class",[Byte[]](0x00,0xff))
$DNSUpdate.Add("AdditionalRecords_TTL",[Byte[]](0x00,0x00,0x00,0x00))
if($MAC)
{
$DNSUpdate.Add("AdditionalRecords_DataLength",[Byte[]](0x00,0x36))
}
$DNSUpdate.Add("AdditionalRecords_AlgorithmName",[Byte[]](0x08,0x67,0x73,0x73,0x2d,0x74,0x73,0x69,0x67,0x00))
$DNSUpdate.Add("AdditionalRecords_TimeSigned",$TimeSigned)
$DNSUpdate.Add("AdditionalRecords_Fudge",[Byte[]](0x01,0x2c))
if($MAC)
{
$DNSUpdate.Add("AdditionalRecords_MACSize",[Byte[]](0x00,0x1c))
$DNSUpdate.Add("AdditionalRecords_MAC",$MAC)
$DNSUpdate.Add("AdditionalRecords_OriginalID",$TransactionID)
}
$DNSUpdate.Add("AdditionalRecords_Error",[Byte[]](0x00,0x00))
$DNSUpdate.Add("AdditionalRecords_OtherLength",[Byte[]](0x00,0x00))
}
return $DNSUpdate
}
function New-PacketDNSUpdateMAC
{
param([Byte[]]$Flags,[Byte[]]$SequenceNumber,[Byte[]]$Checksum)
$DNSUpdateMAC = New-Object System.Collections.Specialized.OrderedDictionary
$DNSUpdateMAC.Add("DNSUpdateMAC_TokenID",[Byte[]](0x04,0x04))
$DNSUpdateMAC.Add("DNSUpdateMAC_Flags",$Flags)
$DNSUpdateMAC.Add("DNSUpdateMAC_Filler",[Byte[]](0xff,0xff,0xff,0xff,0xff))
$DNSUpdateMAC.Add("DNSUpdateMAC_SequenceNumber",[Byte[]](0x00,0x00,0x00,0x00) + $SequenceNumber)
if($Checksum)
{
$DNSUpdateMAC.Add("DNSUpdateMAC_Checksum",$Checksum)
}
return $DNSUpdateMAC
}
function Get-DNSUpdateResponseStatus
{
param([Byte[]]$DNSClientReceive)
$DNS_response_flags = [System.BitConverter]::ToString($DNSClientReceive[4..5])
$DNS_response_flags = $DNS_response_flags -replace "-",""
switch ($DNS_response_flags)
{
'A800' {$DNS_update_response_status = "[+] DNS update successful"}
'A801' {$DNS_update_response_status = ("[-] format error 0x" + $DNS_response_flags)}
'A802' {$DNS_update_response_status = ("[-] failed to complete 0x" + $DNS_response_flags)}
'A804' {$DNS_update_response_status = ("[-] not implemented 0x" + $DNS_response_flags)}
'A805' {$DNS_update_response_status = ("[-] update refused 0x" + $DNS_response_flags)}
Default {$DNS_update_response_status = ("[-] DNS update was not successful 0x" + $DNS_response_flags)}
}
return $DNS_update_response_status
}
if($RecordCheck)
{
if($DNSType -ne 'MX' -and $DNSName -notlike '*.*')
{
$query_name = $DNSName + "." + $Zone
}
else
{
$query_name = $DNSName
}
$DNS_client = New-Object System.Net.Sockets.TCPClient
$DNS_client.Client.ReceiveTimeout = 3000
try
{
$DNS_client.Connect($DomainController,"53")
$DNS_client_stream = $DNS_client.GetStream()
$DNS_client_receive = New-Object System.Byte[] 2048
$packet_DNSQuery = New-PacketDNSQuery $query_name $DNSType
[Byte[]]$DNS_client_send = ConvertFrom-PacketOrderedDictionary $packet_DNSQuery
$DNS_client_stream.Write($DNS_client_send,0,$DNS_client_send.Length) > $null
$DNS_client_stream.Flush()
$DNS_client_stream.Read($DNS_client_receive,0,$DNS_client_receive.Length) > $null
$DNS_client.Close()
$DNS_client_stream.Close()
if($DNS_client_receive[9] -ne 0)
{
$DNS_record_exists = $true
Write-Output "[-] $DNSName of record type $DNSType already exists"
}
}
catch
{
Write-Output "[-] $DomainController did not respond on TCP port 53"
}
}
if(!$RecordCheck -or ($RecordCheck -and !$DNS_record_exists))
{
$DNS_client = New-Object System.Net.Sockets.TCPClient
$DNS_client.Client.ReceiveTimeout = 3000
if($Security -ne 'Secure')
{
try
{
$DNS_client.Connect($DomainController,"53")
}
catch
{
Write-Output "$DomainController did not respond on TCP port 53"
}
if($DNS_client.Connected)
{
$DNS_client_stream = $DNS_client.GetStream()
$DNS_client_receive = New-Object System.Byte[] 2048
[Byte[]]$transaction_id = New-RandomByteArray 2
$packet_DNSUpdate = New-PacketDNSUpdate $transaction_ID $Zone $DNSName $DNSType $DNSTTL $DNSPreference $DNSPriority $DNSWeight $DNSPort $DNSData
[Byte[]]$DNSUpdate = ConvertFrom-PacketOrderedDictionary $packet_DNSUpdate
$DNS_client_send = $DNSUpdate
$DNS_client_stream.Write($DNS_client_send,0,$DNS_client_send.Length) > $null
$DNS_client_stream.Flush()
$DNS_client_stream.Read($DNS_client_receive,0,$DNS_client_receive.Length) > $null
$DNS_update_response_status = Get-DNSUpdateResponseStatus $DNS_client_receive
Write-Output $DNS_update_response_status
$DNS_client.Close()
$DNS_client_stream.Close()
}
}
if($Security -eq 'Secure' -or ($Security -eq 'Auto' -and $DNS_update_response_status -like '*0xA805'))
{
$tkey = "6" + ((0..9) | Get-Random -Count 2) + "-ms-7.1-" + ((0..9) | Get-Random -Count 4) + "." + ((0..9) | Get-Random -Count 8) +
"-" + ((0..9) | Get-Random -Count 4) + "-11e7-" + ((0..9) | Get-Random -Count 4) + "-000c296694e0"
$tkey = $tkey -replace " ",""
Write-Verbose "[+] TKEY name $tkey"
[Byte[]]$tkey_name = [System.Text.Encoding]::UTF8.GetBytes($tkey)
$tkey_name = [Byte[]]0x08 + $tkey_name + 0x00
$tkey_name[9] = 0x06
$tkey_name[16] = 0x24
if($kerberos_tcpclient)
{
$kerberos_client = New-Object System.Net.Sockets.TCPClient
$kerberos_client.Client.ReceiveTimeout = 3000
$domain_controller = [System.Text.Encoding]::UTF8.GetBytes($DomainController)
$kerberos_username = [System.Text.Encoding]::UTF8.GetBytes($Username)
$kerberos_realm = [System.Text.Encoding]::UTF8.GetBytes($Realm)
try
{
$kerberos_client.Connect($DomainController,"88")
}
catch
{
Write-Output "$DomainController did not respond on TCP port 88"
}
}
if(!$kerberos_tcpclient -or $kerberos_client.Connected)
{
if($kerberos_tcpclient)
{
if($Hash)
{
$base_key = (&{for ($i = 0;$i -lt $hash.Length;$i += 2){$hash.SubString($i,2)}}) -join "-"
$base_key = $base_key.Split("-") | ForEach-Object{[Char][System.Convert]::ToInt16($_,16)}
}
else
{
$base_key = Get-KerberosAES256BaseKey $salt $password
}
$ke_key = Get-KerberosAES256UsageKey encrypt 1 $base_key
$ki_key = Get-KerberosAES256UsageKey integrity 1 $base_key
$nonce = New-RandomByteArray 4
$kerberos_client_stream = $kerberos_client.GetStream()
$kerberos_client_receive = New-Object System.Byte[] 2048
$packet_AS_REQ = New-PacketKerberosASREQ $kerberos_username $kerberos_realm $domain_controller $nonce
$AS_REQ = ConvertFrom-PacketOrderedDictionary $packet_AS_REQ
$kerberos_client_send = $AS_REQ
$kerberos_client_stream.Write($kerberos_client_send,0,$kerberos_client_send.Length) > $null
$kerberos_client_stream.Flush()
$kerberos_client_stream.Read($kerberos_client_receive,0,$kerberos_client_receive.Length) > $null
[Byte[]]$PAC_Timestamp = New-KerberosPACTimestamp $ke_key
[Byte[]]$PAC_ENC_Timestamp = Protect-KerberosAES256CTS $ke_key $PAC_Timestamp
[Byte[]]$PAC_Timestamp_Signature = Get-KerberosHMACSHA1 $ki_key $PAC_Timestamp
$packet_AS_REQ = New-PacketKerberosASREQ $kerberos_username $kerberos_realm $domain_controller $nonce $PAC_ENC_Timestamp $PAC_Timestamp_Signature
$AS_REQ = ConvertFrom-PacketOrderedDictionary $packet_AS_REQ
$kerberos_client_send = $AS_REQ
$kerberos_client_stream.Write($kerberos_client_send,0,$kerberos_client_send.Length) > $null
$kerberos_client_stream.Flush()
$kerberos_client_stream.Read($kerberos_client_receive,0,$kerberos_client_receive.Length) > $null
$asrep_payload = [System.BitConverter]::ToString($kerberos_client_receive)
$asrep_payload = $asrep_payload -replace "-",""
$kerberos_client.Close()
$kerberos_client_stream.Close()
}
else
{
try
{
$Null = [System.Reflection.Assembly]::LoadWithPartialName("System.IdentityModel")
if($username -or $Credential)
{
if(!$Credential)
{
$Credential = New-Object System.Management.Automation.PSCredential ($username,$Password)
}
$network_creds = $Credential.GetNetworkCredential()
$network_creds.Domain = $domain
$token = New-Object System.IdentityModel.Selectors.KerberosSecurityTokenProvider ("DNS/$DomainController",[System.Security.Principal.TokenImpersonationLevel]::Impersonation,$network_creds)
$ticket = $token.GetToken([System.TimeSpan]::FromMinutes(1))
}
else
{
$ticket = New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken ("DNS/$DomainController")
}
$asrep_key = $ticket.SecurityKey.GetSymmetricKey()
$kerberos_client_receive = $Ticket.GetRequest()
$asrep_payload = [System.BitConverter]::ToString($kerberos_client_receive)
$asrep_payload = $asrep_payload -replace "-",""
}
catch
{
$auth_success = $false
}
}
if($asrep_key -or ($asrep_payload.Length -gt 0 -and $asrep_payload -like '*A003020105A10302010B*'))
{
Write-Verbose "[+] Kerberos preauthentication successful"
$auth_success = $true
}
elseif($asrep_payload.Length -gt 0 -and $asrep_payload -like '*A003020105A10302011E*')
{
Write-Output ("[-] Kerberos preauthentication error 0x" + $asrep_payload.Substring(96,2))
$auth_success = $false
}
else
{
Write-Output "[-] Kerberos authentication failure"
$auth_success = $false
}
if($auth_success)
{
$ticket_index = $asrep_payload.IndexOf("A003020112A1030201")
$ticket_kvno = $kerberos_client_receive[($ticket_index / 2 + 9)]
if($asrep_payload.Substring($ticket_index + 22,2) -eq '82')
{
$ticket_length = ([System.BitConverter]::ToUInt16($kerberos_client_receive[($ticket_index / 2 + 13)..($ticket_index / 2 + 12)],0)) - 4
}
else
{
$ticket_length = $kerberos_client_receive[($ticket_index / 2 + 12)] - 3
}
$ticket = $Kerberos_client_receive[($ticket_index / 2 + 18)..($ticket_index/2 + 17 + $ticket_length)]
if($kerberos_tcpclient)
{
$cipher_index = $asrep_payload.Substring($ticket_index + 1).IndexOf("A003020112A1030201") + $ticket_index + 1
if($asrep_payload.Substring($cipher_index + 22,2) -eq '82')
{
$cipher_length = ([System.BitConverter]::ToUInt16($kerberos_client_receive[($cipher_index / 2 + 13)..($cipher_index / 2 + 12)],0)) - 4
}
else
{
$cipher_length = $kerberos_client_receive[($cipher_length / 2 + 12)] - 3
}
$cipher = $kerberos_client_receive[($cipher_index / 2 + 18)..($cipher_index / 2 + 17 + $cipher_length)]
$ke_key = Get-KerberosAES256UsageKey encrypt 3 $base_key
$asrep_cleartext = Unprotect-KerberosASREP $ke_key $cipher[0..($cipher.Count - 13)]
$kerberos_session_key = $asrep_cleartext[37..68]
$ke_key = Get-KerberosAES256UsageKey encrypt 11 $kerberos_session_key
$ki_key = Get-KerberosAES256UsageKey integrity 11 $kerberos_session_key
[Byte[]]$subkey = New-RandomByteArray 32
[Byte[]]$sequence_number = New-RandomByteArray 4
$packet_authenticator = New-KerberosAuthenticator $kerberos_realm $kerberos_username $subkey $sequence_number
[Byte[]]$authenticator = ConvertFrom-PacketOrderedDictionary $packet_authenticator
$authenticator = (New-RandomByteArray 16) + $authenticator
$authenticator_encrypted = Protect-KerberosAES256CTS $ke_key $authenticator
$authenticator_signature = Get-KerberosHMACSHA1 $ki_key $authenticator
$packet_apreq = New-PacketKerberosAPREQ $kerberos_realm $domain_controller $ticket_kvno $ticket $authenticator_encrypted $authenticator_signature
[Byte[]]$apreq = ConvertFrom-PacketOrderedDictionary $packet_apreq
[Byte[]]$mac_flags = 0x04
}
else
{
[Byte[]]$apreq = $kerberos_client_receive
[Byte[]]$mac_flags = 0x00
}
$packet_DNSQuery = New-PacketDNSQueryTKEY $tkey_name 0x00,0xf9 $apreq
$DNSQueryTKEY = ConvertFrom-PacketOrderedDictionary $packet_DNSQuery
$DNS_client = New-Object System.Net.Sockets.TCPClient
$DNS_client.Client.ReceiveTimeout = 3000
try
{
$DNS_client.Connect($DomainController,"53")
}
catch
{
Write-Output "$DomainController did not respond on TCP port 53"
}
if($DNS_client.Connected)
{
$DNS_client_stream = $DNS_client.GetStream()
$DNS_client_receive = New-Object System.Byte[] 2048
$DNS_client_send = $DNSQueryTKEY
$DNS_client_stream.Write($DNS_client_send,0,$DNS_client_send.Length) > $null
$DNS_client_stream.Flush()
$DNS_client_stream.Read($DNS_client_receive,0,$DNS_client_receive.Length) > $null
$tkey_payload = [System.BitConverter]::ToString($DNS_client_receive)
$tkey_payload = $tkey_payload -replace "-",""
if($tkey_payload.Substring(8,4) -eq '8000')
{
Write-Verbose "[+] Kerberos TKEY query successful"
$TKEY_success = $true
}
else
{
Write-Output ("[-] Kerberos TKEY query error 0x" + $tkey_payload.Substring(8,4))
$TKEY_success = $false
}
if($TKEY_success)
{
if($kerberos_tcpclient)
{
$cipher_index = $tkey_payload.IndexOf("A003020112A2")
$cipher_length = $DNS_client_receive[($cipher_index / 2 + 8)]
$cipher = $DNS_client_receive[($cipher_index / 2 + 9)..($cipher_index / 2 + 8 + $cipher_length)]
$ke_key = Get-KerberosAES256UsageKey encrypt 12 $kerberos_session_key
$tkey_cleartext = Unprotect-KerberosASREP $ke_key $cipher[0..($cipher.Count - 13)]
$acceptor_subkey = $tkey_cleartext[59..90]
}
else
{
$sequence_index = $tkey_payload.IndexOf("FFFFFFFFFF00000000")
$sequence_number = $DNS_client_receive[($sequence_index / 2 + 9)..($sequence_index / 2 + 12)]
$acceptor_subkey = $asrep_key
}
$kc_key = Get-KerberosAES256UsageKey checksum 25 $acceptor_subkey
$time_signed = [Int](([DateTime]::UtcNow)-(Get-Date "1/1/1970")).TotalSeconds
$time_signed = [System.BitConverter]::GetBytes($time_signed)
$time_signed = 0x00,0x00 + $time_signed[3..0]
[Byte[]]$transaction_id = New-RandomByteArray 2
$packet_DNSUpdate = New-PacketDNSUpdate $transaction_ID $Zone $DNSName $DNSType $DNSTTL $DNSPreference $DNSPriority $DNSWeight $DNSPort $DNSData $time_signed $tkey_name
[Byte[]]$DNSUpdateTSIG = ConvertFrom-PacketOrderedDictionary $packet_DNSUpdate
$packet_DNSUpdateMAC = New-PacketDNSUpdateMAC $mac_flags $sequence_number
[Byte[]]$DNSUpdateMAC = ConvertFrom-PacketOrderedDictionary $packet_DNSUpdateMAC
$DNSUpdateTSIG += $DNSUpdateMAC
$checksum = Get-KerberosHMACSHA1 $kc_key $DNSUpdateTSIG
$packet_DNSUpdateMAC = New-PacketDNSUpdateMAC $mac_flags $sequence_number $checksum
[Byte[]]$DNSUpdateMAC = ConvertFrom-PacketOrderedDictionary $packet_DNSUpdateMAC
$packet_DNSUpdate = New-PacketDNSUpdate $transaction_ID $Zone $DNSName $DNSType $DNSTTL $DNSPreference $DNSPriority $DNSWeight $DNSPort $DNSData $time_signed $tkey_name $DNSUpdateMAC
[Byte[]]$DNSUpdateTSIG = ConvertFrom-PacketOrderedDictionary $packet_DNSUpdate
$DNS_client_send = $DNSUpdateTSIG
$DNS_client_stream.Write($DNS_client_send,0,$DNS_client_send.Length) > $null
$DNS_client_stream.Flush()
$DNS_client_stream.Read($DNS_client_receive,0,$DNS_client_receive.Length) > $null
$DNS_update_response_status = Get-DNSUpdateResponseStatus $DNS_client_receive
Write-Output $DNS_update_response_status
$DNS_client.Close()
$DNS_client_stream.Close()
}
}
}
}
}
}
}