Jump to content

Howto get original user's profile dir when using UAC elevation?


Recommended Posts

Hi,

When a non compiled AU3 script is run with #RequireAdmin, then if the UAC prompt can be authorized due to the fact, that the currently loggedon user has local admin rights, then the macro @UserProfileDir correctly reflects the profile dir of the user of the windows logon session.

 

When the script with #RequireAdmin is started by a "normal user" without local admin rights, and I use a domain admin account to authorize the UAC prompt, then @UserProfileDir reflects the profile dir belonging to the AD-Admin account.

As the script originally was started using the "regular user" I'm wondering, if there is a chance to "pass" the original user's @UserProfileDir to the UAC elevated script?

 

As playing around with this feature I realize, that I basically don't know the exact mechanism of the UAC elevation authorization process:

  • The script is started by right mouse click, execute script
  • This is invoking e.g. "C:\Program Files (x86)\AutoIt3\AutoIt3.exe" "C:\Users\Rudi\Desktop\test.au3" as by this registy value:
Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\AutoIt3Script\Shell\Run\Command]
@="\"C:\\Program Files (x86)\\AutoIt3\\AutoIt3.exe\" \"%1\" %*"
  • But what I honestly don't know is, how does the UAC propt interact in the program startup? I guess, that Autoit3.exe is parsing the AU3 source, is seeing the #RequireAdmin and then "relaunches itself with the AU3 as %1" requesting UAC elevated rights "from windows"???
  • With Process Explorer I can see, that The commandline then is this one with a "!" before "%1"
    "C:\Program Files (x86)\AutoIt3\AutoIt3.exe" !"C:\Users\Rudi\Desktop\test.au3" 
  • It it should be something like this, then it might be possible to pass the original @UserProfileDir to the second, UAC elevated "Startup"???

<edit>

I just noticed:

When I use "WIN+R" and then directly use the command line, I see in Process Explorer, ...
"C:\Program Files (x86)\AutoIt3\AutoIt3.exe" !"C:\Users\Rudi\Desktop\test.au3"
... then this script with #RequireAdmin is started *WITHOUT* UAC elevation.

Guessing, that this is just reverting #RequireAdmin I tried the "opposite" one as well:

  • AU3 script without #RequireAdmin
  • Starting with "C:\Program Files (x86)\AutoIt3\AutoIt3.exe" !"C:\Users\Rudi\Desktop\test.au3" does not invoke UAC elevation prompt.
  • So to me it looks like, this ! is a "status flag from Autoit3.exe to Autoit3.exe", that the elevation process was done already?

amazing...

the topic Autoit on Windows Vista is telling no details of  this UAC process...

</edit>

 

Regards, Rudi.

Edited by rudi

Earth is flat, pigs can fly, and Nuclear Power is SAFE!

Link to comment
Share on other sites

If you knew how to self-elevate your script to run as admin, then you could send the UserProfile value to your script, as a parameter, upon elevation.  Don't ask me how to self-elevate to run as admin.  Discussing the details of the process have been deemed off limits in this forum.  However, there have been discussions of it in this forum in the past and there are language-independent discussions of how it can be done all over the Internet.  I found out how to do it several years ago and know that it works quite well.

Link to comment
Share on other sites

You can use something like:

;~ Script needs to be compiled to work
;~ Running directly will use the executors UserProfileDir as a switch and then prompt for UAC
;~ Can also use <@ScriptFullPath> --UserProfileDir %UserProfile%
#include <WinAPIProc.au3>

Global $g_sUserProfileDir = _GetCmdLineValue("UserProfileDir", @UserProfileDir)
If Not _WinAPI_IsElevated() Then
    ShellExecute(@ScriptFullPath, "--UserProfileDir " & $g_sUserProfileDir, "", "RunAs")
    Exit
EndIf

MsgBox(4096, "UserProfileDir", $g_sUserProfileDir)

Func _GetCmdLineValue($sCmdLine, $vResult = Null)
    For $i = 1 To $CmdLine[0]
        If $CmdLine[$i] = "/" & $sCmdLine Or $CmdLine[$i] = "-" & $sCmdLine Or $CmdLine[$i] = "--" & $sCmdLine Then
            If $CmdLine[0] >= $i + 1 Then
                If StringLeft($CmdLine[$i + 1], 1) = "/" Or StringLeft($CmdLine[$i + 1], 1) = "-" Or StringLeft($CmdLine[$i + 1], 2) = "--" Then
                    Return $vResult
                Else
                    Return $CmdLine[$i + 1]
                EndIf
            EndIf
        EndIf
    Next
    Return $vResult
EndFunc

 

Link to comment
Share on other sites

18 hours ago, TheXman said:

If you knew how to self-elevate your script to run as admin, then you could send the UserProfile value to your script, as a parameter, upon elevation.  Don't ask me how to self-elevate to run as admin.  Discussing the details of the process have been deemed off limits in this forum.  However, there have been discussions of it in this forum in the past and there are language-independent discussions of how it can be done all over the Internet.  I found out how to do it several years ago and know that it works quite well.

I'm *NOT* interested in *SELF* elevating the script. Exactly that's, what I don't want to work: The regular users shall not be granted the possibility to bypass UAC in any means.

What I need is to write few registry values to parts of the registry, the normal user has no write access to. (An for security reasons *SHALL* not have write access to! It would be an easy thing to simply grant write access to the "Local-User-Windows-Group", but that's what I don't want to do)

 

I want to *PASS* the information of the currently-logged-on-userprofile-dir-path to the script to be processed within the script itself, after I personally entered the credentials for the UAC elevation process.

Earth is flat, pigs can fly, and Nuclear Power is SAFE!

Link to comment
Share on other sites

19 hours ago, rudi said:

As the script originally was started using the "regular user" I'm wondering, if there is a chance to "pass" the original user's @UserProfileDir to the UAC elevated script?

If i understand corretly, i believe so, a simple question of setting that macro @UserProfileDir into a variable on the top of the script, and then use it afterwards.

As an extreme measure, you could have another exe, that runs and writes to an ini file the profile dir, and then your main script would read from ini.

Or maybe im just complicating things without need.

Edited by careca
Spoiler

Renamer - Rename files and folders, remove portions of text from the filename etc.

GPO Tool - Export/Import Group policy settings.

MirrorDir - Synchronize/Backup/Mirror Folders

BeatsPlayer - Music player.

Params Tool - Right click an exe to see it's parameters or execute them.

String Trigger - Triggers pasting text or applications or internet links on specific strings.

Inconspicuous - Hide files in plain sight, not fully encrypted.

Regedit Control - Registry browsing history, quickly jump into any saved key.

Time4Shutdown - Write the time for shutdown in minutes.

Power Profiles Tool - Set a profile as active, delete, duplicate, export and import.

Finished Task Shutdown - Shuts down pc when specified window/Wndl/process closes.

NetworkSpeedShutdown - Shuts down pc if download speed goes under "X" Kb/s.

IUIAutomation - Topic with framework and examples

Au3Record.exe

Link to comment
Share on other sites

Thanks for your reply.

that's doing quite exactly, what I was asking for. Except, that the script has to be compiled.

;~ must *NOT* be used: #RequireAdmin
;~ Script needs to be compiled to work
;~ Running directly will use the executors UserProfileDir as a switch and then prompt for UAC
;~ Can also use <@ScriptFullPath> --UserProfileDir %UserProfile%
#include <WinAPIProc.au3>

Global $g_sUserProfileDir = _GetCmdLineValue("UserProfileDir", @UserProfileDir)
If Not _WinAPI_IsElevated() Then
    ShellExecute(@ScriptFullPath, "--UserProfileDir " & $g_sUserProfileDir, "", "RunAs")
    Exit
EndIf

MsgBox(4096, "UserProfileDir", $g_sUserProfileDir)

Func _GetCmdLineValue($sCmdLine, $vResult = Null)
    For $i = 1 To $CmdLine[0]
        If $CmdLine[$i] = "/" & $sCmdLine Or $CmdLine[$i] = "-" & $sCmdLine Or $CmdLine[$i] = "--" & $sCmdLine Then
            If $CmdLine[0] >= $i + 1 Then
                If StringLeft($CmdLine[$i + 1], 1) = "/" Or StringLeft($CmdLine[$i + 1], 1) = "-" Or StringLeft($CmdLine[$i + 1], 2) = "--" Then
                    Return $vResult
                Else
                    Return $CmdLine[$i + 1]
                EndIf
            EndIf
        EndIf
    Next
    Return $vResult
EndFunc

 

Earth is flat, pigs can fly, and Nuclear Power is SAFE!

Link to comment
Share on other sites

Could create a batch file that hopefuly grabs the original username

$RF = Random(100000, 999999, 1) & '.bat'
$FO = FileOpen($RF, 10)
$FW = FileWrite($FO, 'cd %UserProfile%' & @CRLF & 'pause'); 'del ' & $RF)
FileClose($FO)
Run($RF)

This is a proof of concept, if it does work, this can be changed to write into a txt file or something.

Edited by careca
Spoiler

Renamer - Rename files and folders, remove portions of text from the filename etc.

GPO Tool - Export/Import Group policy settings.

MirrorDir - Synchronize/Backup/Mirror Folders

BeatsPlayer - Music player.

Params Tool - Right click an exe to see it's parameters or execute them.

String Trigger - Triggers pasting text or applications or internet links on specific strings.

Inconspicuous - Hide files in plain sight, not fully encrypted.

Regedit Control - Registry browsing history, quickly jump into any saved key.

Time4Shutdown - Write the time for shutdown in minutes.

Power Profiles Tool - Set a profile as active, delete, duplicate, export and import.

Finished Task Shutdown - Shuts down pc when specified window/Wndl/process closes.

NetworkSpeedShutdown - Shuts down pc if download speed goes under "X" Kb/s.

IUIAutomation - Topic with framework and examples

Au3Record.exe

Link to comment
Share on other sites

Here is the script without being compiled:

;~ Script does not need to be compiled to work
;~ Running directly will use the executors UserProfileDir as a switch and then prompt for UAC
;~ Can also use <@ScriptFullPath> --UserProfileDir %UserProfile%
#include <WinAPIProc.au3>

Global $g_sUserProfileDir = _GetCmdLineValue("UserProfileDir", @UserProfileDir)
If Not _WinAPI_IsElevated() Then
    ;~ Using RegRead assumes AutoIt is installed, otherwise manually configure the AutoIt3.exe example: ShellExecute(@ProgramFilesDir & "\AutoIt3\AutoIt3.exe", ...)
    ShellExecute(RegRead("HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\AutoIt3.exe", ""), '"' & @ScriptFullPath & '" --UserProfileDir ' & $g_sUserProfileDir, "", "RunAs")
    Exit
EndIf

MsgBox(4096, "UserProfileDir", $g_sUserProfileDir)

Func _GetCmdLineValue($sCmdLine, $vResult = Null)
    For $i = 1 To $CmdLine[0]
        If $CmdLine[$i] = "/" & $sCmdLine Or $CmdLine[$i] = "-" & $sCmdLine Or $CmdLine[$i] = "--" & $sCmdLine Then
            If $CmdLine[0] >= $i + 1 Then
                If StringLeft($CmdLine[$i + 1], 1) = "/" Or StringLeft($CmdLine[$i + 1], 1) = "-" Or StringLeft($CmdLine[$i + 1], 2) = "--" Then
                    Return $vResult
                Else
                    Return $CmdLine[$i + 1]
                EndIf
            EndIf
        EndIf
    Next
    Return $vResult
EndFunc

 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...