4

I accidentally deleted 180 users from my AD and they aren't recoverable. I have recreated the accounts in AD and what not. This creates a new profile on their laptops when they login because of the new SID. I'm trying to write a script that grants them access to their old profile folder and create a shortcut on their desktop that leads there.

I've got the script working fine with one problem. The environment variables that are used, end up referring back to the admin account that runs the script. The users themselves don't have permission to change security on their old folder. I need to try and have the environment variables refer to the user yet have the privilege of an admin account to rewrite the permissions.

Here is the script so far.. I'm deploying this with Task Scheduler at the moment, which is another can of worms in that I'm not entirely understanding of the credential side of things there. I mean ideally, the task would run as a domain admin, execute the script asap, and have the script resolve the environment variables to the logged on user.

$permission = ":(OI)(CI)M"
$sam = $env:USERNAME
$folderName = "C:\Users\$($sam)"

Invoke-Expression -Command ( 'ICACLS $folderName /grant:r $sam$($permission) /t' )

$WshShell = New-Object -comObject WScript.Shell
$Shortcut = $WshShell.CreateShortcut("$Home\Desktop\Profile Backup.lnk")
$Shortcut.TargetPath = $folderName
$Shortcut.Save()

Its the $env:USERNAME and $home variables that are giving me trouble..

Or is there another way I should be tackling this problem?

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
MagicMatt
  • 43
  • 4
  • What is the user's current folder versus their old folder name? They'll need administrative privileges unless you are specifying their SID in the command. – Maximilian Burszley Mar 28 '18 at 15:40
  • So the old folder name would be their username ie "charlie". The new folder name is charlie.domain. So to redo the permissions they do need admin privelege, which is my problem. To automate the whole thing through scripting, I need to use environment variables in the script to point to the correct folder and create a shortcut etc. Problem is, running the script with admin privileges causes the environment variables to resolve to the admin account, for example, $home will resolve to C:\Users\Administrator instead of C:\Users\charlie. And $env:USERNAME will resolve to Aministrator. – MagicMatt Mar 28 '18 at 21:52
  • @MagicMatt I have somewhat misunderstood the context. I have improved my answer in PowerShell. See if that will help you. – tukan Mar 29 '18 at 07:28

2 Answers2

2

You could use query session command to get the login name of the current logged on user. Then create NTAccount object based on that to retrieve SID and win32_userprofile WMI object to find out the profile path. Like this:

$m = query session | Select-String -Pattern "\>console\s*(\S*)\s"
$sam = $m.Matches[0].Groups[1].value

$acc = New-Object System.Security.Principal.NTAccount($sam)
$sid = $acc.Translate([System.Security.Principal.SecurityIdentifier]).Value

$profile = Get-CimInstance -ClassName win32_userprofile -Filter "SID='$sid'"
$folderName = $profile.LocalPath
Janne Tuukkanen
  • 1,620
  • 9
  • 13
  • Thanks, this looks like exactly what I'm looking for, I'll get a chance to test in the next week or two. I'll let you know how I go. – MagicMatt Mar 30 '18 at 02:22
  • Thankyou!! That worked a charm! Exactly what I was looking for. I had to make one minor adjustment on your query session filter, as the '>' would change places when executed under SYSTEM account during scheduled task. Heres the change I made: $m = query session | Select-String -Pattern "console\s*(\S*)\s" – MagicMatt Apr 09 '18 at 01:58
-1

Edit I have given it second thought over-night so I'll update the answer. You will be required to have domain admin password encrypted and then users will run the script.

It always sucks when something like this happens. I don't have a possibility to try this out, but I think the following approach would be feasible. The script asks user for password encrypts it and run the command as the user.

First phase would be to have a domain admin to encrypt his password to a file:

This is to be prepared by Domain Admin (distributed with the PS script) - I recommend changing password after the recovery is complete:

1) Read-Host -AsSecureString | ConvertFrom-SecureString | Out-File 'C:\<script_path>\admin_passwd.txt'

2) This is to be executed by user (you have to fill in the admin user id and have the password file distributed with the script). The script path can be obtained by (Get-Location).Path. I'm not adding it into the source code so you can decide how to implement it:

$permission = ":(OI)(CI)M"
$admin= "<your_admin_userid>"
$sam = $env:USERNAME
$domain = $env:UserDomain
$folderName = "C:\Users\$($sam)"

# get domain admin password
$encrypted_passwd = get-content 'C:\<script_path>\admin_passwd.txt' | ConvertTo-securestring

# Setting process invocation parameters.
$process_start_info = New-Object -TypeName System.Diagnostics.ProcessStartInfo
$process_start_info.CreateNoWindow = $true
$process_start_info.UseShellExecute = $false
$process_start_info.RedirectStandardOutput = $true
$process_start_info.RedirectStandardError = $true
$process_start_info.UserName = $admin
$process_start_info.Domain = $domain
$process_start_info.Password = $encrypted_passwd
$process_start_info.Verb = 'runas'
$process_start_info.FileName = 'ICACLS'
$process_start_info.Arguments = "$folderName /grant:r $sam$($permission) /t"

# Creating process object.
$process = New-Object -TypeName System.Diagnostics.Process
$process.StartInfo = $process_start_info

# Start the process
[Void]$process.Start()

$process.WaitForExit()

# synchronous output - captures everything
$output = $process.StandardOutput.ReadToEnd()
$output += $process.StandardError.ReadToEnd()

Write-Output $output


$WshShell = New-Object -comObject WScript.Shell
$Shortcut = $WshShell.CreateShortcut("$Home\Desktop\Profile Backup.lnk")
$Shortcut.TargetPath = $folderName
$Shortcut.Save()
tukan
  • 17,050
  • 1
  • 20
  • 48
  • Thanks tukan for the reply and solution. The problem here then would be that the user themselves doesnt have the required permission to make the changes to the folder. The only people with permission to change the permissions are the Local Administrators group and Domain Admins. Does this method somehow bypass that? – MagicMatt Mar 28 '18 at 09:47
  • @MagciMatt no this script is not bypassing this limitation. Could you list your exetion policy? `Get-ExecutionPolicy -List` – tukan Mar 28 '18 at 10:42
  • @MagicMatt you could also have an "emergency" situation and make the users temporary local admins. – tukan Mar 28 '18 at 10:56
  • Why are you using the Process class instead of just using `Start-Process`.. and passing the credentials makes no sense, nor does the ICACLS business considering it's the user's desktop and they don't have access to the other folder. – Maximilian Burszley Mar 28 '18 at 15:32
  • @TheIncorrigible1 you were partially right. If it is on the user's deskotp different approach is needed. I'm using the the `System.Diagnostics.Process` due to the (domain) security context change. If you can do it `Start-Process` please show me your code. – tukan Mar 29 '18 at 07:27
  • @MagicMatt now the script will fill in the user details with admin privileges. – tukan Mar 29 '18 at 07:39