transfer CurrentDirectory from un-elevated script

2020-04-16 04:43发布

问题:

I need to copy my file "manufacturer.bmp", wich is located in the same directory as the script (in my flash drive), to the system32 directory.

I succeed, in getting the variables sourcefile, destinationdirectory, and to elevate my script, but when I elevate it, my sourcefile variable is lost, because of the use of CurrentDirectory, which differs in this mode.

Set shell = WScript.CreateObject("WScript.Shell")
Set fso = CreateObject("Scripting.FileSystemObject")

CurrentDirectory = fso.GetAbsolutePathName(".")
sourcefile = fso.buildpath(CurrentDirectory, "manufacturer.bmp")
MsgBox(sourcefile)

'Checks if the script is running elevated (UAC)
Function isElevated
  Set shell = CreateObject("WScript.Shell")
  Set whoami = shell.Exec("whoami /groups")
  Set whoamiOutput = whoami.StdOut
  strWhoamiOutput = whoamiOutput.ReadAll

  If InStr(1, strWhoamiOutput, "S-1-16-12288", vbTextCompare) Then 
    isElevated = True
  Else
    isElevated = False
  End If
End Function

'Re-runs the process prompting for priv elevation on re-run
Sub uacPrompt
  'Check if we need to run in C or W script
  interpreter = "wscript.exe"
  If InStr(1, WScript.FullName, "CScript", vbTextCompare) = 0 Then
    interpreter = "wscript.exe"
  Else
    interpreter = "cscript.exe"
  End If

  'Start a new instance with an elevation prompt first
  Set shellApp = CreateObject("Shell.Application")
  shellApp.ShellExecute interpreter, Chr(34) & WScript.ScriptFullName & _
    Chr(34) & " uac", "", "runas", 1

  'End the non-elevated instance
  WScript.Quit
End Sub

'Make sure we are running elevated, prompt if not
If Not isElevated Then uacPrompt

destinationdir = fso.buildpath(shell.ExpandEnvironmentStrings("%windir%"), _
                 "system32")
MsgBox(destinationdir)

fso.CopyFile sourcefile, destinationdir

Any idea of how to push my sourcefile var to the child elevated script?

回答1:

The ShellExecute method allows you to specify the working directory as the 3rd argument, so you can pass the current directory to the elevated script and build the sourcefile path after elevation. Also, your code could be streamlined quite a bit.

Const HKLM   = &h80000002
Const DELETE = &h10000

Set sh = CreateObject("WScript.Shell")

Set reg = GetObject("winmgmts://./root/default:StdRegProv")
reg.CheckAccess HKLM, "SYSTEM\CurrentControlSet", DELETE, isAdmin

If Not isAdmin Then
  If WScript.Arguments.Count = 0 Then
    CreateObject("Shell.Application").ShellExecute WScript.FullName, _
      Chr(34) & WScript.ScriptFullName & Chr(34) & " uac", _
      sh.CurrentDirectory, "runas", 1
    WScript.Quit 0
  Else
    WScript.Echo "Privilege elevation failed!"
    WScript.Quit 1
  End If
End If

Set fso = CreateObject("Scripting.FileSystemObject")

src = fso.BuildPath(sh.CurrentDirectory, "manufacturer.bmp")
dst = fso.buildpath(sh.ExpandEnvironmentStrings("%windir%"), "system32")

fso.CopyFile src, dst & "\"

Edit: or at least that's how it would work if you weren't elevating the process. According to this blog post from Raymond Chen the start directory is ignored when elevating processes, so that malicious DLLs from the current directory aren't loaded into elevated processes by mistake. Meaning that you must pass the working directory "manually", like this:

Const HKLM   = &h80000002
Const DELETE = &h10000

Set sh = CreateObject("WScript.Shell")

Set reg = GetObject("winmgmts://./root/default:StdRegProv")
reg.CheckAccess HKLM, "SYSTEM\CurrentControlSet", DELETE, isAdmin

If Not isAdmin Then
  If WScript.Arguments.Count = 0 Then
    CreateObject("Shell.Application").ShellExecute WScript.FullName, _
      Chr(34) & WScript.ScriptFullName & Chr(34) & " " & _
      Chr(34) & sh.CurrentDirectory & Chr(34), , "runas", 1
    WScript.Quit 0
  Else
    WScript.Echo "Privilege elevation failed!"
    WScript.Quit 1
  End If
End If

sh.CurrentDirectory = WScript.Arguments(0)

Set fso = CreateObject("Scripting.FileSystemObject")

src = fso.BuildPath(sh.CurrentDirectory, "manufacturer.bmp")
dst = fso.buildpath(sh.ExpandEnvironmentStrings("%windir%"), "system32")

fso.CopyFile src, dst & "\"

Note that since your destination path is a folder, it must have a trailing backslash (as documented).



标签: vbscript uac