Setting ACLs using alternate credentials

4 posts in this topic


I've been using this UDF to set ACL permissions to some network folders, everything works great (no issues). However, I want to apply these permissions using elevated domain credentials supplied by the user and not the user that's currently running the script. As a temporary solution, I've implemented a RunAs function, but that's not the solution I'm looking for. I'm not fluent with using Dlls, but I have been trying out different methods.

My RunAs Function:

Func _RunAs($sUser, $sPass)
    If @Compiled Then
        RunAs($sUser, @LogonDomain, $sPass, 4, FileGetShortName(@ScriptFullPath), "", @SW_MAXIMIZE)
        RunAs($sUser, @LogonDomain, $sPass, 4, FileGetShortName(@AutoItExe) & " " & FileGetShortName(@ScriptFullPath), "", @SW_MAXIMIZE)
EndFunc   ;==>_RunAs

I tried LogonUser and I know that I can take that token to ImpersonateLoggedOnUser, but I'm not sure how to implement that or if that's even the right method. I also need to RevertToSelf once completed.

Func _LogonUser($sUsername, $sPassword, $sServer = @LogonDomain) ; Returns True if user exists
    Local $stToken

    $stToken = DllStructCreate("int")
    Local $aRet = DllCall("advapi32.dll", "int", "LogonUser", _
            "str", $sUsername, "str", $sServer, "str", $sPassword, "dword", 3, "dword", 0, "ptr", DllStructGetPtr($stToken))
    ;$hToken = DllStructGetData($stToken, 1)
    If Not @error And $aRet[0] <> 0 Then
        Return True
    Return False
EndFunc   ;==>_LogonUser

Any assistance, suggestions or idea's would be helpful.


Share this post

Link to post
Share on other sites

 RunAs or RunAsWait does not give you full admin rights (Admin Token), even if the user has admin right on the PC.  One workaround you have is to use re-execution.  Have a look at this thread for an example.  You could also create another script that uses #RequireAdmin, but I prefer re-execution.  

Here is a more customized script for what I think you are trying to do,  it uses RunAsWait and ShellExecuteWait.  

Global $sAdminUser = "USERNAME"
Global $sAdminPassword = "PASSWORD"
Global $sDomain = @LogonDomain
Global $iLogOnFlag = 0
Global $sParameters = ""

;Run as the Admin account.
If @UserName <> $sAdminUser And Not IsAdmin() Then
    $sParameters = ""
    If Not @Compiled Then
        $sParameters = ' "' & @ScriptFullPath & '"'
    ;Use RunAsWait to run as AdminUser, to continue the script as the user that started it, and to wait for the Admin part to Finish.
    RunAsWait($sAdminUser, $sDomain, $sAdminPassword, $iLogOnFlag, @AutoItExe & $sParameters)
    If @error Then Exit MsgBox(16 + 262144, "ERROR!", "Unable to run under administrator account.")

;Request the Admin Token for the Admin account in Windows Vista and Higher.
If @UserName = $sAdminUser And Not IsAdmin() And Not StringRegExp(@OSVersion, "_(XP|200(0|3))") Then
    $sParameters = ""
    If Not @Compiled Then
        $sParameters = '"' & @ScriptFullPath & '"'
    ;Use ShellExecuteWait to run as AdminUser with Admin Token, to wait for the Admin part of the script to finish, and then to exit.
    ShellExecuteWait(@AutoItExe, $sParameters, "", "runas")
    If @error Then Exit MsgBox(16 + 262144, "ERROR!", "Unable to elevate to Admin due to UAC.")

MsgBox(16, @UserName, "Is " & (IsAdmin() ? "" : "Not " ) & "Admin") ;Example

;Admin part of script.
If IsAdmin() Then 
    MsgBox (0, "Admin Run Test", "Run Admin part of script and then exit to run as user who started the script.") ;Example
    ;Exit to finish Admin part of script.

;Put rest of the non Admin part of script here.

If you have any questions, please let me know.  



Share this post

Link to post
Share on other sites

Hey @AdamUL, I really appreciate your response and customized script. I read through your posts and it helped me a lot to understand the process. However, with my script I'm already using #RequireAdmin and my goal was to not to use re-execution (if possible). Luckily, after days of researching I was able to find the solution I was looking for.

I copied and modified an already existing function from this post: 


Hopefully, I've done this correctly but please correct me if needed.

Func _LogonOnUser($sUsername, $sPassword, $sServer = @LogonDomain)
    Local $aRet
    Local $stToken
    Local $phToken
    Local $nError = -1

    $stToken = DllStructCreate("int")
    $aRet = DllCall("advapi32.dll", "int", "LogonUser", _
            "str", $sUsername, _
            "str", $sServer, _
            "str", $sPassword, _
            "dword", 8, _ ; LOGON32_LOGON_NETWORK_CLEARTEXT
            "dword", 0, _
            "ptr", DllStructGetPtr($stToken))
    $phToken = DllStructGetData($stToken, 1)
    If Not @error And $aRet[0] <> 0 Then
        ;Return True ; Return True if user exists
        $aRet = DllCall("advapi32.dll", "int", "ImpersonateLoggedOnUser", "ptr", $phToken)
        If Not @error And $aRet[0] <> 0 Then
            ConsoleWrite("Impersonated User = " & @UserName & @CRLF)
            ; Do Impersonation Stuff Here
            _InitiatePermissionResources() ; Requires Permissions UDF
            $aet = DllCall("kernel32.dll", "int", "GetLastError")
            If Not @error Then $nError = $aRet[0]
        DllCall("kernel32.dll", "int", "CloseHandle", "ptr", $phToken)
        $aRet = DllCall("kernel32.dll", "int", "GetLastError")
        If Not @error Then $nError = $aRet[0]
    If $nError > -1 Then
        Return 0
    Return 1
EndFunc   ;==>_LogOnUser

Once the process is completed I then _LogOffUser and RevertToSelf

Func _LogOffUser()
    _ClosePermissionResources() ; Requires Permissions UDF
    DllCall("advapi32.dll", "int", "RevertToSelf")
    ConsoleWrite("RevertToSelf User = " & @UserName & @CRLF)

Permissions Applied Successfully!

If I don't use the _LogonOnUser function it errors out and I lose access to my network folders and it disappears! Luckily, I am able to recover it when I use this function.

1 person likes this

Share this post

Link to post
Share on other sites

@Surf243  Your welcome.  A very nice find, and nicely created functions.  I couldn't tell if the user that you were trying to run under was an admin user or not.  My script is used mostly with non admin users.  I'm glad your functions work for what you wanted to do.  I have added them to my script library.  The only issue, and it's really not an issue, is some of the DLL calls could be replaced by _WinAPI_* functions, such as _WinAPI_GetLastError and _WinAPI_CloseHandle.  

I'm also working with the Permissions UDF.  I have found a few issues with it, and have added comments to that thread.  




Share this post

Link to post
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

  • Similar Content

    • Traskiz
      Windows 10 RunAs script problem
      By Traskiz
      I have a problem, I cant run script as administrator in Windows 10:
      RegWrite('HKLM\SOFTWARE\Policies\Microsoft\Windows\BITS', 'EnableBITSMaxBandwidth','REG_DWORD',Number('1'))
      RegWrite('HKLM\SOFTWARE\Policies\Microsoft\Windows\BITS', 'MaxTransferRateOnSchedule','REG_DWORD',Number('100'))
      RegWrite('HKLM\SOFTWARE\Policies\Microsoft\Windows\BITS', 'MaxBandwidthValidFrom','REG_DWORD',Number('7'))
      RegWrite('HKLM\SOFTWARE\Policies\Microsoft\Windows\BITS', 'MaxBandwidthValidTo','REG_DWORD',Number('22'))
      RegWrite('HKLM\SOFTWARE\Policies\Microsoft\Windows\BITS', 'UseSystemMaximum','REG_DWORD',Number('1'))
      RegWrite('HKLM\SOFTWARE\Policies\Microsoft\Windows\BITS', 'MaxTransferRateOffSchedule','REG_DWORD',Number('400'))
      Global $sUserName = "administrator"
      Global $sPassword = "pass"
      Global $sDomain = "domain"
      RunAsWait($sUserName, $sDomain, $sPassword, 2, "main.exe", "", @TempDir)
      If I run "run.exe" it dont work...
      If  I change main.exe to this:
      and it runs and shows administrator in message box... but it cant elevate main.exe with RegWrite() command...
      I tried using #RequireAdmin in first line of main.exe, but it not worked... UAC is set to "do not notify"
      This method of elevation worked on Windows 7 and Windows XP...
      Please help!
    • Milas
      runas access is denied
      By Milas
      Hey guys,
               for some reason when I run this command with run as in autoit it returns access is denied. but when I run the same thing in an elevated command shell it works fine. Im not sure where I am messing up.
      global $rtech,$rcred, $IP $rtech = inputbox("","username") $rcred = InputBox("","password") $ip = inputbox("","enter IP") $pid = Runas ($rtech,"mhs", $rcred, 2 ,@ComSpec & ' /c reg query \\' & $ip & '"\hklm\software\microsoft\windows\currentversion\group policy\state\machine"|findstr /i "disting"', @SystemDir, @SW_hide, $STDERR_CHILD + $STDOUT_CHILD) Local $line While 1 $line &= StdoutRead($pid) If @error Then ExitLoop WEnd While 1 $line &= StderrRead($pid) If @error Then ExitLoop WEnd MsgBox(0, "", $line)  
    • WoodGrain
      Run() executes on some computers but not others
      By WoodGrain
      Hi All,
      I've got a script setup to drop a program into a temp folder and then run it from there, but I have mixed results, the Run() command will work on some computers but not others. The file will be placed into the temp folder in all cases. Running AutoIT The computers are all either Win 7 or 8.1, x64 (exe is compiled to x64 too), UAC is off, all have local admin rights - if I've missed something ask and I'll update the details.
      If Not FileExists (@TempDir & "\HCTB") Then DirCreate(@TempDir & "\HCTB") FileInstall("G:\IT\Downloads\TB\12.0.45471\Host\TB_Setup-sif7r8pgcq.exe", @TempDir & "\HCTB\TB_Setup-sif7r8pgcq.exe", 1) Local $iPID = Run(@TempDir & "\HCTB\TB_Setup-sif7r8pgcq.exe", "") Any suggestions?
    • JRZJulien
      How to add recoder into HOSTS with RunAs in Win7
      By JRZJulien
      i want add one recorder into HOSTS file file with following script in windows 7, but always failed, does anyone help me to correct it ?
      --script start--
      Local $sUserName = "Administrator"
      Local $sPassword = "abcd1234"
      RunAs($sUserName,@computername,$sPassword,0,"attrib -s -h -r C:\Windows\System32\drivers\etc\hosts")
      RunAs($sUserName,@computername,$sPassword,0,"echo" & @CRLF)
      RunAs($sUserName,@computername,$sPassword,0,"attrib +s +h +r C:\Windows\System32\drivers\etc\hosts")
      --script end--
    • lansti
      Add printer with RunAs
      By lansti
      Hi, i'm trying to add a printer with RunAs credentials in a domain environment.
      I'm loged on as a local user, and in the startupscript it says:
      runas("administrator","domain","******",1,runwait("rundll32 printui.dll,PrintUIEntry /in /n" & "\\printserver\printername" & " /q")) It will not connect to the domain, and therefor will not install printer.