mirror of
https://github.com/Kevin-Robertson/Powermad
synced 2026-06-08 11:28:52 +00:00
4934f19aae
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.
189 lines
7.2 KiB
PowerShell
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"
|
|
}
|
|
|
|
}
|
|
|
|
} |