ancsjs
ancsjs

Reputation: 37

How can I run powershell script that uses both local & elevated permissions?

I need to edit two registry keys. One needs to be run by the local user, the other by an account with elevated privileges.

How can I write a script that is run as a different user, but still has access to the local user's credentials?

Upvotes: 0

Views: 915

Answers (2)

Theo
Theo

Reputation: 61068

As administrator, you can set the registry value for the currently logged on user too, if you can get the SID for that user. When you have that, you can access the local users registry via the HKEY_USERS hive.

Import-Module ActiveDirectory

# set this to the registry path, property name and value you need to access
$regPath   = 'Software\SomePath\SomeKey'
$propName  = 'ThePropertyName'
$propValue = 'ThePropertyValue'
$propType  = 'String'           # use any of the `[Microsoft.Win32.RegistryValueKind]` enum values or names

# get the domain\username of the user currently logged in to the computer
$user = (Get-CimInstance -ClassName Win32_ComputerSystem).UserName
# get the SID for that user 
$sid = (Get-ADUser -Identity ($user -split '\\', 2)[0]).SID
if (!$sid) {
    throw "Could not determine the SID for user '$user'"
}

# Admin registry: HKEY_LOCAL_MACHINE
$path = Join-Path -Path 'HKLM:' -ChildPath $regPath
Set-Itemproperty -Path $path -Name $propName -Value $propValue -Type $propType

# Current user registry: HKEY_USERS
$path = Join-Path -Path "Registry::HKEY_USERS\$sid" -ChildPath $regPath
Set-Itemproperty -Path $path -Name $propName -Value $propValue -Type $propType

As mklement0 commented, the above code uses the ActiveDirectory module to get the SID for the currently logged on user via Get-ADUser.
If this is not possible for you, or you are not in an AD domain, the following helper function can also get the SID, without the need for ActiveDirectory:

function Get-UserSID {
    param (
        [Parameter(ValuefromPipeline = $true, Position = 0)]
        [Alias('Account', 'User')]
        [string]$UserName = $env:USERNAME,
        [string]$Domain   = $env:USERDOMAIN
    )
    if ($UserName.Contains("\")) { $Domain, $UserName = $UserName -split '\\', 2 }   #"# split on the backslash
    try {
        $objUser = New-Object System.Security.Principal.NTAccount($Domain, $UserName)
        $strSID = $objUser.Translate([System.Security.Principal.SecurityIdentifier])
        $strSID.Value
    }
    catch [System.Security.Principal.IdentityNotMappedException] {
        Write-Warning "User '$UserName' does not exist in '$Domain'"
    }
    catch {
        throw
    }
}

Put that on top of your script and then use as:

# get the domain\username of the user currently logged in to the computer
$user = (Get-CimInstance -ClassName Win32_ComputerSystem).UserName
# get the SID for that user 
$sid = Get-UserSID $user

A possible third way of getting the SID is by reading the registry:

# get the domain\username of the user currently logged in to the computer
$user = (Get-CimInstance -ClassName Win32_ComputerSystem).UserName
# get the SID for that user by probing the registry
$sid = ((Get-ItemProperty -Path 'Registry::HKEY_USERS\S-*\Volatile Environment' |
         Where-Object { ('{0}\{1}' -f $_.USERDOMAIN, $_.USERNAME) -eq $user }).PSParentPath -split '\\')[-1]

Upvotes: 1

Vad
Vad

Reputation: 743

You can use key "-credential" to set user that would be change registry like :

New-Item –Path "HKCU:\dummy" –Name newregistrykey -Credential myuser@domain

or to set property:

Set-Itemproperty -path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run' -Name 'someProcess' -value 'C:\Program Files\someapp\myprogramm.exe' -Credential myuser@domain

And you can save you both cred to variables like:

$localCred = Get-Credential
$domainCred = Get-Credential

Upvotes: 0

Related Questions