Files
Kevin Robertson 4934f19aae Added credential parameter to machine account tools
Added the ability to accept creds for all of the machine account
scripts. Also syncing Invoke-DNSUpdate with version that is currently in
the Inveigh dev branch.
2018-05-02 22:53:15 -04:00

189 lines
7.2 KiB
PowerShell

function New-MachineAccount
{
<#
.SYNOPSIS
This function adds a machine account with a specified password to Active Directory through an encrypted LDAP
add request. By default standard domain users can add up to 10 systems to AD (see ms-DS-MachineAccountQuota).
Author: Kevin Robertson (@kevin_robertson)
License: BSD 3-Clause
.DESCRIPTION
The main purpose of this function is to leverage the default ms-DS-MachineAccountQuota attribute setting which
allows all domain users to add up to 10 computers to a domain. The machine account and HOST SPNs are added
directly through an LDAP connection to a domain controller and not by attaching the host system to Active
Directory. This function does not modify the domain attachment and machine account associated with the host
system.
Note that you will not be able to remove the account without elevating privilege. You can however disable the
account as long as you maintain access to the account used to create the machine account.
.PARAMETER Credential
Credentials for adding the machine account. Note that machine accounts can also add machine accounts.
.PARAMETER Domain
The targeted domain. This parameter is mandatory on a non-domain attached system. Note this parameter
requires a DNS domain name and not a NetBIOS version.
.PARAMETER DomainController
Domain controller to target. This parameter is mandatory on a non-domain attached system.
.PARAMETER DistinguishedName
Distinguished name for the computers OU.
.PARAMETER MachineAccount
The username of the machine account that will be added.
.PARAMETER Password
The securestring of the password for the machine account.
.EXAMPLE
New-MachineAccount -MachineAccount iamapc
Add a machine account with the current user's session.
.EXAMPLE
$user_account_creds = Get-Credential
New-MachineAccount -MachineName iamapc -Credential $user_account_creds
Add a machine account with creds from another user.
.EXAMPLE
$machine_account_password = ConvertTo-SecureString 'Summer2018!' -AsPlainText -Force
$user_account_password = ConvertTo-SecureString 'Spring2018!' -AsPlainText -Force
$user_account_creds = New-Object System.Management.Automation.PSCredential('domain\user',$user_account_password)
New-MachineAccount -MachineAccount iamapc -Password $machine_account_password -Credential $user_account_creds
Add a machine account with creds from another user and also avoid the machine account password prompt.
.LINK
https://github.com/Kevin-Robertson/Powermad
#>
[CmdletBinding()]
param
(
[parameter(Mandatory=$false)][String]$DistinguishedName,
[parameter(Mandatory=$false)][String]$Domain,
[parameter(Mandatory=$false)][String]$DomainController,
[parameter(Mandatory=$true)][String]$MachineAccount,
[parameter(Mandatory=$false)][System.Security.SecureString]$Password,
[parameter(Mandatory=$false)][System.Management.Automation.PSCredential]$Credential
)
$null = [System.Reflection.Assembly]::LoadWithPartialName("System.DirectoryServices.Protocols")
if(!$Password)
{
$password = Read-Host -Prompt "Enter a password for the new machine account" -AsSecureString
}
$password_BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($password)
$password_cleartext = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($password_BSTR)
if(!$DomainController)
{
try
{
$DomainController = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain().DomainControllers[0].Name
}
catch
{
Write-Output "[-] domain controller not located"
throw
}
}
if(!$Domain)
{
try
{
$Domain = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain().Name
}
catch
{
$error_message = $_.Exception.Message
$error_message = $error_message -replace "`n",""
Write-Output "[-] $error_message"
throw
}
}
$Domain = $Domain.ToLower()
$machine_account = $MachineAccount
if($MachineAccount.EndsWith('$'))
{
$sam_account = $MachineAccount
$machine_account = $machine_account.SubString(0,$machine_account.Length - 1)
}
else
{
$sam_account = $machine_account + "$"
}
Write-Verbose "[+] SAMAccountName=$sam_account"
if(!$DistinguishedName)
{
$distinguished_name = "CN=$machine_account,CN=Computers"
$DC_array = $Domain.Split(".")
ForEach($DC in $DC_array)
{
$distinguished_name += ",DC=$DC"
}
}
else
{
$distinguished_name = "$DistinguishedName"
}
Write-Verbose "[+] Distinguished Name=$distinguished_name"
$password_cleartext = [System.Text.Encoding]::Unicode.GetBytes('"' + $password_cleartext + '"')
$identifier = New-Object System.DirectoryServices.Protocols.LdapDirectoryIdentifier($DomainController,389)
if($Credential)
{
$connection = New-Object System.DirectoryServices.Protocols.LdapConnection($identifier,$Credential.GetNetworkCredential())
}
else
{
$connection = New-Object System.DirectoryServices.Protocols.LdapConnection($identifier)
}
$connection.SessionOptions.Sealing = $true
$connection.SessionOptions.Signing = $true
$connection.Bind()
$request = New-Object -TypeName System.DirectoryServices.Protocols.AddRequest
$request.DistinguishedName = $distinguished_name
$request.Attributes.Add((New-Object "System.DirectoryServices.Protocols.DirectoryAttribute" -ArgumentList "objectClass","Computer")) > $null
$request.Attributes.Add((New-Object "System.DirectoryServices.Protocols.DirectoryAttribute" -ArgumentList "SamAccountName",$sam_account)) > $null
$request.Attributes.Add((New-Object "System.DirectoryServices.Protocols.DirectoryAttribute" -ArgumentList "userAccountControl","4096")) > $null
$request.Attributes.Add((New-Object "System.DirectoryServices.Protocols.DirectoryAttribute" -ArgumentList "DnsHostName","$machine_account.$Domain")) > $null
$request.Attributes.Add((New-Object "System.DirectoryServices.Protocols.DirectoryAttribute" -ArgumentList "ServicePrincipalName","HOST/$machine_account.$Domain",
"RestrictedKrbHost/$machine_account.$Domain","HOST/$machine_account","RestrictedKrbHost/$machine_account")) > $null
$request.Attributes.Add((New-Object "System.DirectoryServices.Protocols.DirectoryAttribute" -ArgumentList "unicodePwd",$password_cleartext)) > $null
Remove-Variable password_cleartext
try
{
$connection.SendRequest($request) > $null
Write-Output "[+] machine account $machine_account added"
}
catch
{
$error_message = $_.Exception.Message
$error_message = $error_message -replace "`n",""
Write-Output "[-] $error_message"
if($error_message -eq 'Exception calling "SendRequest" with "1" argument(s): "The server cannot handle directory requests."')
{
Write-Output "[!] User may have reached ms-DS-MachineAccountQuota limit"
}
}
}