I'm trying to modify the permissions of the UAC with a powershell script that looks like:
Start-Process powershell -Verb runAs Administrator
Set-ItemProperty -Path registry::HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\policies\system -Name EnableLUA -Value 0
$UAC = Get-ItemProperty -Path registry::HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\policies\system -Name EnableLUA
$UAC.EnableLUA
Even though I am running the script as administrator, I still get the following error:
Set-ItemProperty : Requested registry access is not allowed. At
C:\Users\Bert\Desktop\autoLims.ps1:8 char:17
+ Set-ItemProperty <<<< -Path registry::HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\policies\system
-Name EnableLUA -Value 0
+ CategoryInfo : PermissionDenied: (HKEY_LOCAL_MACH...policies\system:String) [Set-ItemProperty],
SecurityException
+ FullyQualifiedErrorId : System.Security.SecurityException,Microsoft.PowerShell.Commands.SetItemPropertyCommand
Any ideas why it wont run the script even though I am running the script as administrator? Is there something else I need to change?
The -Verb parameter only takes one argument e.g. print. In the case of elevation it will be RunAs which will run the process with the current user's full privileges.
From the Start-Process documentation:
-Verb <String>
Specifies a verb to use when starting the process. The verbs that are available are determined by the file name extension of the file that runs in the process.
The following table shows the verbs for some common process file types.
File type Verbs
--------- -------
.cmd Edit, Open, Print, Runas
.exe Open, RunAs
.txt Open, Print, PrintTo
.wav Open, Play
To find the verbs that can be used with the file that runs in a process, use the New-Object cmdlet to create a System.Diagnostics.ProcessStartInfo object for the file. The available verbs are in the Verbs property of the ProcessStartInfo object.
Related
I want to remotely trigger some commands with power shell on a Windows Server Core 2019.
I am using the following to enter the remote Session:
$Username = "x.x.x.x\Administrator"
$PasswordSS = ConvertTo-SecureString 'The-Password' -AsPlainText -Force
$Cred = New-Object System.management.Automation.PSCredential $Username,$PasswordSS
Enter-PSSession -ComputerName 'x.x.x.x' -Credential $cred
The connection then fails with the following message:
Enter-PSSession : Connecting to remote server x.x.x.x failed with the
following error message : Access is denied. For more information, see
the about_Remote_Troubleshooting Help topic. At line:4 char:2
+ Enter-PSSession -ComputerName 'x.x.x.x' -Credential $cred
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (x.x.x.x:String) [Enter-PSSession], PSRemotingTransportException
+ FullyQualifiedErrorId : CreateRemoteRunspaceFailed
The remote computer is on the local network and I can ping it.
The Administrator account is a local account on the remote computer.
The remote ip is on the trusted host list on the client.
PSRemoting was enabled on the remote computer.
What am I missing? Help would be appreciated.
This ought to be in a comment. Not enough reps
a. Reset PSSession configurations:
https://stackoverflow.com/a/22385798/10994804
b. Add -ComputerName 'x.x.x.x to trusted hosts.
Get-Item WSMan:\localhost\Client\TrustedHosts
Set-Item WSMan:\localhost\Client\TrustedHosts -Value x.x.x.x -Force
CONTEXT ANALYSIS:
You chose another Input Language than the Time And Currency Format language during the installation. However, your choice is ignored for the Welcome Screen.
At the end of the installation, at the first boot, when you are asked to enter a password for the Administrator account, you type a password with the Time And Currency Format language but you are not aware of this.
At every login, you will use the Time And Currency Format language, until you change this behavior, but you are still not aware of it.
That's why you cannot:
PSRemote
RDP
change the local Administrator's password with ALT + CTRL + SUPPR
SOLUTION:
To be able to RDP or PSRemote, you must set the password again but with PowerShell
Set-LocalUser -Name Administrator -Password (Read-Host -AsSecureString)
However, now you won't be able to login with the console anymore.
To fix this you must change the Welcome screen language.
Easy graphical solution for a few computers:
In the command prompt type intl.cpl to open the Region control panel.
Go to the Administrative tab.
Click on the Copy settings button.
Check the Welcome screen and system accounts check box.
Click OK
PowerShell solution for many computers:
1.Check your current substitutes
Get-ItemProperty -Path 'HKCU:\Keyboard Laytout\Substitutes'
The complete list of Keyboard Identifiers can be found on Microsoft Docs:
Keyboard Identifiers and Input Method Editors for Windows
2.Check current substitutes of the Default user account
Get-ItemProperty -Path 'Registry::HKEY_USERS\.DEFAULT\Keyboard Layout\Substitutes'
3. Add one or all missing substitutes to the Default user account
New-ItemProperty -Path 'Registry::HKEY_USERS\.DEFAULT\Keyboard Layout\Substitutes' -Name '00000809' -Value '00000040c' -PropertyType 'String'
4. Just for information have a look at the current values of the Preload key of the Default user account
Get-ItemProperty -Path 'Registry::HKEY_USERS\.DEFAULT\Keyboard Layout\Preload'
5. Configure value 1 of the Preload key with the substitute name which will be used first on the Welcome screen. (If you want, you can also remove other values from the Preload key or even reorder them...)
Set-ItemProperty -Path 'Registry::HKEY_USERS\.DEFAULT\Keyboard Layout\Preload' -Name 1 -Value '00000809'
I've been looking into Group Managed Service Accounts (gmsa) accounts and I've been using them to run scheduled tasks on Server 2012R2 and PowerShell 5.0.10586.117.
After I've been using them a while I've encountered some very weird behavior.
The problem seem to be some kind of timing issue/race condition somewhere when a task is run as a gmsa account. Some core commands might not exists/be loaded while running the script.
Example:
Script called in the task C:\temp\broken-task\test.cmd
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy "ByPass" -File "C:\temp\broken-task\test.ps1" > "C:\temp\broken-task\test.cmd.txt"
The actual script with weird behavior C:\temp\broken-task\test.ps1
<#
.SYNOPSIS
Broken task.
.DESCRIPTION
Broken task.
#>
[CmdletBinding()] Param ()
Process {
$ErrorActionPreference
Set-Variable -Name "ErrorActionPreference" -Scope "Script" -Value "Stop"
Set-Variable -Name "ErrorActionPreference" -Scope "Script" -Value "Stop"
$ErrorActionPreference
}
I then create and run a task in C:\temp\broken-task\task.ps1
$Action = New-ScheduledTaskAction -Execute "C:\Windows\System32\cmd.exe" -Argument "/C C:\temp\broken-task\test.cmd"
$Principal = New-ScheduledTaskPrincipal -UserID "my-gmsa-user$" -LogonType "Password"
New-ScheduledTask -Action $Action -Principal $Principal | Register-ScheduledTask -TaskPath "\test\" -TaskName "test123" | Out-Null
Start-ScheduledTask -TaskPath "\test\" -TaskName "test123"
After task completion the content of C:\temp\broken-task\test.cmd.txt is the following:
Continue
Set-Variable : The term 'Set-Variable' is not recognized as the name of a cmdle
t, function, script file, or operable program. Check the spelling of the name,
or if a path was included, verify that the path is correct and try again.
At C:\temp\broken-task\test.ps1:15 char:5
+ Set-Variable -Name "ErrorActionPreference" -Scope "Script" -Value ...
+ ~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Set-Variable:String) [], Comman
dNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Stop
What is happening above is that Set-Variable doesn't exist on line 2 of the process block in test.ps1, but exist on line 3 (we can see that $ErrorActionPreference has changed).
If I run either the cmd script or the ps1 as myself (a normal user) I will get the expected output with no errors:
Continue
Stop
So what's going on here? The Set-Variable command is in the Microsoft.PowerShell.Utility module. Is the module somehow loaded in between the first and second call? This also happen with other commands like Get-Item "C:\".
What might be even worse is that this does not always happen. I've seen a task work properly in one run and fail in the other.
Also note that I find it hard to create good examples and this does not always yield the same weird results (but the above example has currently failed without exception in my tests).
Is the combination of powershell, gmsa and task scheduler broken somehow?
I can't really trust the system to do as I which when it has this inconsistent behavior.
A workaround might be explicit loading of the Microsoft.PowerShell.Utility module before calling Set-Variable, but I'm not sure if this is due to timing or something else..
I'm trying to find a way to get PowerShell not to spawn a command window when running an executable using Start-Process.
If I call the executable directly within the script (e.g. .\program.exe) then the program runs (with its arguments) and the output is returned to the PowerShell window.
If I use Start-Process the program spawns a command window where the program runs and returns it's output.
If I try and use the -NoNewWindow switch of Start-Process the script then errors out saying it can't find the exe file.
I would prefer to use Start-Process to have access to the -Wait switch, as the programs and configurations the script makes can take some time individually to finish, and I don't want later commands starting up.
This code runs the executable in a separate command window:
Start-Process DeploymentServer.UI.CommandLine.exe -ArgumentList "download --autoDownloadOn --autoDownloadStartTime $StartTime --autoDownloadEndTime $EndTime" -Wait
This code runs the exe within the PowerShell console:
.\DeploymentServer.UI.CommandLine.exe download --autoDownloadOn --autoDownloadStartTime $StartTime --autoDownloadEndTime $EndTime
If I add the -NoNewWindow to the Start-Process code
Start-Process DeploymentServer.UI.CommandLine.exe -ArgumentList "download --autoDownloadOn --autoDownloadStartTime $StartTime --autoDownloadEndTime $EndTime" -Wait -NoNewWindow
I get the following error:
Start-Process : This command cannot be executed due to the error: The system
cannot find the file specifie
At C:\Temp\SOLUS3Installv1.3.ps1:398 char:22
+ Start-Process <<<< DeploymentServer.UI.CommandLine.exe -ArgumentList "download --autoDownloadStartTime $StartTime --autoDownloadEndTime $EndTime" -Wait -NoNewWindow
+ CategoryInfo : InvalidOperation: (:) [Start-Process], InvalidOperationException
+ FullyQualifiedErrorId : InvalidOperationException,Microsoft.PowerShell.Commands.StartProcessCommand
You should prefix the executable name with the current directory when you use the -NoNewWindow switch:
Start-Process .\DeploymentServer.UI.CommandLine.exe -ArgumentList "download --autoDownloadOn --autoDownloadStartTime $StartTime --autoDownloadEndTime $EndTime" -Wait -NoNewWindow
Background information:
The first thing Start-Process tries to do is to resolve the value of the -FilePath parameter by PowerShell rules. If it succeeds, it replaces the value value passed with the full path to the command. If not, it leaves the value untouched.
In the Windows API there are two ways to start a new process: CreateProcess and ShellExecute. ShellExecute is the default, but if you use a cmdlet parameter that requires CreateProcess (for example, -NoNewWindow), then CreateProcess will be used. The difference between them, which matters for this question, is that when looking for a command to execute, CreateProcess uses the current process' working directory, while ShellExecute uses the specified working directory (which Start-Process by default passes based on the current filesystem-provider location, unless explicitly specified via -WorkingDirectory).
PS Test:\> 1..3 |
>> ForEach-Object {
>> New-Item -Path $_ -ItemType Directory | Out-Null
>> Add-Type -TypeDefinition #"
>> static class Test {
>> static void Main(){
>> System.Console.WriteLine($_);
>> System.Console.ReadKey(true);
>> }
>> }
>> "# -OutputAssembly $_\Test.exe
>> }
PS Test:\> [IO.Directory]::SetCurrentDirectory((Convert-Path 2))
PS Test:\> Set-Location 1
PS Test:\1> Start-Process -FilePath Test -WorkingDirectory ..\3 -Wait # Use ShellExecute. Print 3 in new windows.
PS Test:\1> Start-Process -FilePath .\Test -WorkingDirectory ..\3 -Wait # Use ShellExecute. Print 1 in new windows.
PS Test:\1> Start-Process -FilePath Test -WorkingDirectory ..\3 -Wait -NoNewWindow # Use CreateProcess.
2
PS Test:\1> Start-Process -FilePath .\Test -WorkingDirectory ..\3 -Wait -NoNewWindow # Use CreateProcess.
1
PowerShell does not update the current process' working directory when you change the current location for the FileSystem provider, so the directories can differ.
When you type:
Start-Process DeploymentServer.UI.CommandLine.exe -Wait -NoNewWindow
Start-Process cannot resolve DeploymentServer.UI.CommandLine.exe by PowerShell rules, since it does not look in the current FileSystem location by default. And it uses CreateProcess, since you specify -NoNewWindow switch. So, it ends up looking for DeploymentServer.UI.CommandLine.exe in the current process' working directory, which does not contains this file and thus causes an error.
I have a BATCH script that makes symlinks with mklink. When I run it as an administrator or as a system account (with psexec -s -e) it works as it should. But when I try to use it in a GPO as a startup script it gives me an error "you do not have sufficient privilege to perform this operation" on a target computer. Windows 7 Pro SP1 x64. UAC is disabled.
Batch example:
mklink C:\log\cmd.link.exe C:\Windows\System32\cmd.exe >> C:\log\symlink.log 2>&1
I also tried to wrap it into a powershell script:
Start-Process -FilePath "$env:windir\system32\cmd.exe" -ArgumentList "/c mklink C:\log\cmd.link.exe C:\Windows\System32\cmd.exe >> C:\log\symlink.txt 2>&1" -Verb RunAs
but got the same error. What am I doing wrong?
Maybe there's another way to create a SymLink with GPO or PowerShell?
It appeared that the Group Policy Client (gpsvc) service (since GPO scripts runs with its privilegies) does not contain the privilege to create symolic links (SeCreateSymbolicLinkPrivilege):
C:\>sc qprivs gpsvc
[SC] QueryServiceConfig2 SUCCESS
SERVICE_NAME: gpsvc
PRIVILEGES : SeTakeOwnershipPrivilege
: SeIncreaseQuotaPrivilege
: SeAssignPrimaryTokenPrivilege
: SeSecurityPrivilege
: SeChangeNotifyPrivilege
: SeCreatePermanentPrivilege
: SeShutdownPrivilege
: SeLoadDriverPrivilege
: SeRestorePrivilege
: SeBackupPrivilege
If I want to use this privilege I should at first grant this privelege to the service. It can be done with this command:
sc privs gpsvc SeTakeOwnershipPrivilege/SeIncreaseQuotaPrivilege/SeAssignPrimaryTokenPrivilege/SeSecurityPrivilege/SeChangeNotifyPrivilege/SeCreatePermanentPrivilege/SeShutdownPrivilege/SeLoadDriverPrivilege/SeRestorePrivilege/SeBackupPrivilege/SeCreateSymbolicLinkPrivilege
After that you will be able to use mklink inside GPO scripts.
There are several caveats:
You should list all permissions (current + new). Otherwise you risk to replace all permissions with one.
The command needs System account permission to set privileges so you'll need to use psexec or GPO script (not sure).
If you intend to use psexec it will throw you an error about argument being too long. So you should save this command as a .bat file and then run it with psexec.
Many thanks to #PetSerAl who helped me to find this out.
I still had an issue running the sc.exe commands with PowerShell as a startup script via Group Policy. It was being denied access per Start-Transcript log file. I used the below PowerShell logic for example and it did not work for me in my case.
I tried several variations of multiple things and syntaxes using PowerShell.exe, -verb RunAs, Start-Process and slews of things short of running it as a local script with Task Scheduler as SYSTEM which I was trying to avoid.
Note: This is just a general example of one of the variations that failed with the same result and transcript output as all other
variations tried.
$privs = (sc.exe qprivs gpsvc).Split(":")[5..99] | % { Process { If( $_.Trim().Length -gt 0 ){ $_.Trim() } } };
$privs = $privs + "SeCreateSymbolicLinkPrivilege";
$privs = $privs -Join "/";
Invoke-Expression "sc.exe privs gpsvc $privs"
A solution that works (in my case)
I used the below PowerShell logic as a startup script via Group Policy and now creating symbolic links works. To keep the example simple, I used Google Chrome for generalization.
Basically I had to manipulate the multistring registry value of the correlated permissions for the service rather than using sc.exe appending the needed "SeCreateSymbolicLinkPrivilege" value that way.
#Start-Transcript -Path C:\Log\Transcript.txt
$v = (Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Services\gpsvc").RequiredPrivileges;
If ( $v -notcontains "SeCreateSymbolicLinkPrivilege" ) {
$v = $v + "SeCreateSymbolicLinkPrivilege";
Set-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Services\gpsvc" RequiredPrivileges $v -Type MultiString;
};
$Chrome86 = "C:\Program Files (x86)\Google\Chrome";
$Chrome = "C:\Program Files\Google\Chrome";
If(!(Test-Path $Chrome86)){
If(Test-Path $Chrome){New-Item -Path $Chrome86 -ItemType SymbolicLink -Value $Chrome -Force}
}
If(!(Test-Path $Chrome)){
If(Test-Path $Chrome86){New-Item -Path $Chrome -ItemType SymbolicLink -Value $Chrome86 -Force}
}
Here's what I'm trying to do:
#ECHO OFF
CALL powershell -ExecutionPolicy RemoteSigned -Command "$sh = new-object -com 'Shell.Application'; $sh.ShellExecute('powershell', '-NoExit -Command "$path = """HKLM:\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}""";echo $path"', '', 'runas')"
PAUSE
Basically, I want to have a batch file that I can double-click, which will run a powershell script that calls another powershell script but asks for admin privileges and runs that command as admin.
I'm having problems though, with the double-quotes I think... I've tried many things but can't seem to fix it, here's the powershell error message:
Bad numeric constant: 4D.
At line:1 char:57
+ $path = HKLM:\SYSTEM\CurrentControlSet\Control\Class\{4D <<<< 36E972-E325-11C
E-BFC1-08002BE10318};echo $path
+ CategoryInfo : ParserError: (4D:String) [], ParentContainsError
RecordException
+ FullyQualifiedErrorId : BadNumericConstant
PS C:\Windows\system32>
I would use the built-in command Start-Process rather than creating a shell object e.g.:
CALL powershell -ExecutionPolicy RemoteSigned -NoProfile -Command "& {Start-Process PowerShell -Verb runas -Arg '-NoExit -Command & {$path=''foo'';$path}'}"
For anything of significance the quoting is going to be annoying. Can you put the final script in a file and execute the script file using the -File parameter on PowerShell.exe?
I solved it, here's the long batch one-liner for my real problem, so people can see a real example:
CALL powershell -ExecutionPolicy RemoteSigned -Command "$sh = new-object -com 'Shell.Application'; $sh.ShellExecute('powershell', '-NoExit -Command ""$path = ''HKLM:\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}''; Get-Childitem $path -ErrorAction SilentlyContinue | Where { (Get-ItemProperty $_.PSPath DriverDesc) -Match ''VMnet'' } | Foreach { New-ItemProperty -ErrorAction SilentlyContinue $_.PSPath -Name ''*NdisDeviceType'' -Value ''1'' -PropertyType DWord }; netsh interface set interface name=''VMware Network Adapter VMnet1'' admin=DISABLED; netsh interface set interface name=''VMware Network Adapter VMnet1'' admin=ENABLED; netsh interface set interface name=''VMware Network Adapter VMnet8'' admin=DISABLED; netsh interface set interface name=''VMware Network Adapter VMnet8'' admin=ENABLED""', '', 'runas')"
P.S: In case anyone's wondering what it's for... I run this every time I install/update VMware Workstation to hide the virtual network adapters from appearing on the Network and Sharing Center in Windows Vista/7.