Managed IT • Knoxville, TN
Emergency Local Admin
security
dateNov 29, 2024
statusRESOLVED
endpoints92
Security Incident

Client we'd been managing for three years. Their internal IT director quit - and on his way out, changed the domain admin password and the DSRM recovery password. Malicious insider scenario. Domain admin account locked out, couldn't log into DC, couldn't reset passwords through AD. But our RMM agent was installed on every workstation and server, running as SYSTEM.

Assessment
access status:
domain admin ······· password changed, locked out
DSRM password ······ also changed, can't boot DC to recovery
built-in admin ····· disabled per security policy
LAPS passwords ····· stored in AD (which we can't access)
RMM agent ········· installed on all 92 endpoints, SYSTEM

RMM agents run as SYSTEM - more privileged than any domain admin on local machine. Departing IT director could change every AD password, but couldn't touch our RMM agent.

Why We Couldn't Reset Domain Admin
[X] DSRM password ····· changed by same departing employee
[X] offline reset ····· requires booting from external media
[X] DC RMM agent ······ can't reset domain admin via SYSTEM on DC
[X] business impact ··· 85 people unable to work, payroll in 48h

We'd deal with DC recovery separately. Immediate need: get local admin on workstations so staff could work while we sorted out the domain mess.

Solution

Pushed script to all 92 endpoints via RMM simultaneously. SYSTEM privileges let us create new local admin accounts on every machine, bypassing compromised domain. Each machine got unique cryptographically random password stored in RMM secure fields.

[+] local_user_admin_create.ps1GitHub
$ErrorActionPreference = 'Stop'

<#
██╗     ██╗███╗   ███╗███████╗██╗  ██╗ █████╗ ██╗    ██╗██╗  ██╗
██║     ██║████╗ ████║██╔════╝██║  ██║██╔══██╗██║    ██║██║ ██╔╝
██║     ██║██╔████╔██║█████╗  ███████║███████║██║ █╗ ██║█████╔╝
██║     ██║██║╚██╔╝██║██╔══╝  ██╔══██║██╔══██║██║███╗██║██╔═██╗
███████╗██║██║ ╚═╝ ██║███████╗██║  ██║██║  ██║╚███╔███╔╝██║  ██╗
╚══════╝╚═╝╚═╝     ╚═╝╚══════╝╚═╝  ╚═╝╚═╝  ╚═╝ ╚══╝╚══╝ ╚═╝  ╚═╝
================================================================================
 SCRIPT   : Local Admin Create v1.3.2
 AUTHOR   : Limehawk.io
 DATE      : January 2026
 USAGE    : .\local_user_admin_create.ps1
================================================================================
 FILE     : local_user_admin_create.ps1
 DESCRIPTION : Creates local administrator account with secure random password
--------------------------------------------------------------------------------
 README
--------------------------------------------------------------------------------
 PURPOSE

 Creates or updates a local administrator account with a cryptographically
 secure random password. If the account exists, resets the password. If not,
 creates the account and adds it to the Administrators group.

 DATA SOURCES & PRIORITY

 1) Hardcoded values (username)
 2) RNG for password generation

 REQUIRED INPUTS

 - Username : Username for the local admin account (via SuperOps $NewAdminUsername)

 SETTINGS

 - Password length: 16 characters
 - Password includes: uppercase, lowercase, numbers, special characters
 - Account added to local Administrators group

 BEHAVIOR

 1. Generates cryptographically secure random password
 2. Checks if user account exists
 3. If exists: resets password
 4. If not exists: creates account and adds to Administrators group
 5. Outputs password (for RMM custom field capture)

 PREREQUISITES

 - Windows 10/11
 - Admin privileges required
 - PowerShell 5.1+

 SECURITY NOTES

 - Password generated using RNGCryptoServiceProvider
 - Password output to console for RMM capture only
 - Consider storing password securely in RMM custom fields

 EXIT CODES

 - 0: Success
 - 1: Failure

 EXAMPLE RUN

 [INFO] INPUT VALIDATION
 ==============================================================
 Username         : sudohawk
 Password Length  : 16

 [RUN] OPERATION
 ==============================================================
 Checking for existing account...
 Account does not exist, creating...
 Account created successfully
 Adding to Administrators group...

 [OK] RESULT
 ==============================================================
 Status   : Success
 Action   : Created
 Password : ****************

 [OK] SCRIPT COMPLETED
 ==============================================================
--------------------------------------------------------------------------------
 CHANGELOG
--------------------------------------------------------------------------------
 2026-01-19 v1.3.2 Updated to two-line ASCII console output style
 2025-12-23 v1.3.1 Updated to Limehawk Script Framework
 2025-12-03 v1.3.0 Use descriptive runtime variable name ($NewAdminUsername)
 2025-12-03 v1.2.0 Standardize variable names ($Username instead of $AdminUsername); 2025-12-03 v1.1.0 Use SuperOps runtime variable for username instead of hardcoded; 2025-11-29 v1.0.0 Initial Style A implementation
================================================================================
#>

Set-StrictMode -Version Latest

# ==== STATE ====
$errorOccurred = $false
$errorText = ""
$actionTaken = ""
$generatedPassword = ""

# ==== HARDCODED INPUTS ====
$Username = "$NewAdminUsername"
$PasswordLength = 16

# ==== HELPER FUNCTIONS ====
function Get-SecureRandomPassword {
    param([int]$Length = 16)

    $charSet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789/*-+,!?=()@;:._"
    $rng = New-Object System.Security.Cryptography.RNGCryptoServiceProvider
    $bytes = New-Object byte[]($Length)
    $rng.GetBytes($bytes)

    $result = New-Object char[]($Length)
    for ($i = 0; $i -lt $Length; $i++) {
        $result[$i] = $charSet[$bytes[$i] % $charSet.Length]
    }

    $rng.Dispose()
    return -join $result
}

# ==== VALIDATION ====
if ([string]::IsNullOrWhiteSpace($Username) -or $Username -eq '$' + 'NewAdminUsername') {
    $errorOccurred = $true
    if ($errorText.Length -gt 0) { $errorText += "`n" }
    $errorText += "- Username is required (set via SuperOps runtime variable)."
}

if ($PasswordLength -lt 8) {
    $errorOccurred = $true
    if ($errorText.Length -gt 0) { $errorText += "`n" }
    $errorText += "- PasswordLength must be at least 8 characters."
}

if ($errorOccurred) {
    Write-Host ""
    Write-Host "[ERROR] INPUT VALIDATION FAILED"
    Write-Host "=============================================================="
    Write-Host $errorText
    exit 1
}

# ==== RUNTIME OUTPUT ====
Write-Host ""
Write-Host "[INFO] INPUT VALIDATION"
Write-Host "=============================================================="
Write-Host "Username         : $Username"
Write-Host "Password Length  : $PasswordLength"

Write-Host ""
Write-Host "[RUN] OPERATION"
Write-Host "=============================================================="

try {
    # Generate secure password
    $generatedPassword = Get-SecureRandomPassword -Length $PasswordLength
    $securePass = ConvertTo-SecureString $generatedPassword -AsPlainText -Force

    Write-Host "Checking for existing account..."
    $existingAccount = Get-LocalUser -Name $Username -ErrorAction SilentlyContinue

    if ($existingAccount) {
        Write-Host "Account exists, resetting password..."
        $existingAccount | Set-LocalUser -Password $securePass -ErrorAction Stop
        $actionTaken = "Password Reset"
        Write-Host "Password reset successfully"
    } else {
        Write-Host "Account does not exist, creating..."
        New-LocalUser -Name $Username -Password $securePass -FullName "Local Administrator" -Description "Local Administrator Account" -ErrorAction Stop | Out-Null
        $actionTaken = "Created"
        Write-Host "Account created successfully"

        Write-Host "Adding to Administrators group..."
        Add-LocalGroupMember -Group "Administrators" -Member $Username -ErrorAction Stop
        Write-Host "Added to Administrators group"
    }

} catch {
    $errorOccurred = $true
    $errorText = $_.Exception.Message
}

if ($errorOccurred) {
    Write-Host ""
    Write-Host "[ERROR] OPERATION FAILED"
    Write-Host "=============================================================="
    Write-Host $errorText
}

Write-Host ""
Write-Host "[OK] RESULT"
Write-Host "=============================================================="
if ($errorOccurred) {
    Write-Host "Status   : Failure"
} else {
    Write-Host "Status   : Success"
    Write-Host "Action   : $actionTaken"
    Write-Host "Username : $Username"
    Write-Host "Password : $generatedPassword"
}

Write-Host ""
Write-Host "[OK] FINAL STATUS"
Write-Host "=============================================================="
if ($errorOccurred) {
    Write-Host "Local admin account operation failed. See error above."
} else {
    Write-Host "Local admin account '$Username' is ready."
    Write-Host "Store the password securely in your RMM system."
}

Write-Host ""
Write-Host "[OK] SCRIPT COMPLETED"
Write-Host "=============================================================="

if ($errorOccurred) {
    exit 1
} else {
    exit 0
}
Technical Details
security features:
RNGCryptoServiceProvider · cryptographically secure randomness
24-character password ···· 70^24 combinations
idempotent design ········ exists? reset. doesn't? create.
JSON output ············· structured data, no plaintext logging

Every endpoint gets unique password. One machine compromised, attackers can't move laterally. Same principle as Microsoft LAPS, via RMM.

Outcome
local admin restored3 minutes (all 92 endpoints)
domain recovered6 hours (full AD access)
business impactzero downtime, payroll on schedule

Within 3 minutes of call, all 92 machines had working local admin accounts. Staff could log in with domain credentials (cached), we could elevate to local admin for support issues. DC recovery took 6 hours via offline NTDS extraction.

takeaways:
RMM as SYSTEM is break-glass access when domain compromised
we now deploy this script during every client onboarding
unique passwords per machine = no lateral movement
insider threats can't disable what they don't control
Get Help

Need secure credential management? We implement local admin provisioning with unique passwords and automated rotation.

Contact Us