Thursday, February 17, 2011

Vbscript detect whether UAC-elevated

I think the title says it all. How can my vbscript detect whether or not it is running in a UAC elevated context?

I have no problem detecting the user, and seeing if the user is within the Administrators group. But this still doesn't answer the question of whether the process has elevated privs or not, when running under Vista or Windows 2008. Please note, I need only to detect this status; not attempt to elevate or (err ..) de-elevate.

Thanks for any thoughts you can add!

From stackoverflow
  • The method I finally settled on depends on the fact that Vista and Windows 2008 have the whoami.exe utility, and it detects the integrity level of the user who owns the process. A couple of screenshots help here:

    WHOAMI, normal and elevated, on Vista

    You can see that when cmd is running elevated, whoami /groups reports a "High" mandatory integrity level and a different SID than when running non-elevated. In the pic, the top session is normal, the one underneath is running elevated after UAC prompt.

    Knowing that, here is the code I used. It essentially checks the OS version, and if it is Vista or Server 2008, calls CheckforElevation which runs whoami.exe /groups, and looks for the string S-1-16-12288 in the output. In this example I just echo status; in the real script I branch to different actions based on the result.

    sub GetOSVersion
    Dim strComputer, oWMIService, colOSInfo, oOSProperty, strCaption, strOSFamily
    strComputer = "."
    Set oWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
    Set colOSInfo = oWMIService.ExecQuery("Select * from Win32_OperatingSystem")
    'I hate looping through just to get one property. But dunno another way!
    For Each oOSProperty in colOSInfo 
      strCaption = oOSProperty.Caption 
    Next
    If InStr(1,strCaption, "Vista", vbTextCompare) Then strOSFamily = "Vista"
    If InStr(1,strCaption, "2008", vbTextCompare) Then strOSFamily = "2008"
    If InStr(1,strCaption, "XP", vbTextCompare) Then strOSFamily = "XP"
    If InStr(1,strCaption, "2003", vbTextCompare) Then strOSFamily = "2003"
    If InStr(1,strCaption, "2000", vbTextCompare) Then strOSFamily = "2000"
    If strOSFamily = "" Then 
        Wscript.Echo "No known OS found. (Script can detect Windows 2000, 2003, XP, Vista, 2008.)" 
    Else 
        Wscript.Echo "OS Family = " & strOSFamily
    End If
    Select Case strOSFamily 'if Vista/2008 then call CheckforElevation
    Case "Vista"
        CheckforElevation
    Case "2008"
        CheckforElevation
    Case Else
        Exit Sub
    End Select
    end sub
    
    sub CheckforElevation 'test whether user has elevated token 
    Dim oShell, oExecWhoami, oWhoamiOutput, strWhoamiOutput, boolHasElevatedToken
    Set oShell = CreateObject("WScript.Shell")
    Set oExecWhoami = oShell.Exec("whoami /groups")
    Set oWhoamiOutput = oExecWhoami.StdOut
    strWhoamiOutput = oWhoamiOutput.ReadAll
    If InStr(1, strWhoamiOutput, "S-1-16-12288", vbTextCompare) Then boolHasElevatedToken = True
    If boolHasElevatedToken Then
        Wscript.Echo "Current script is running with elevated privs."
    Else
        Wscript.Echo "Current script is NOT running with elevated privs."
    End If
    end sub
    
    quux : Of course this sucks. It would be cleaner to have access to the GetTokenInformation API. But apparently that's out of bounds for VBscript. Oh well - we do what we can.
  • The solution I am posting is a couple production ready VBScripts that leverage whoami to find this information. One cool thing about them is that they work with XP (for information that is available on XP) if you place a copy of the Resource Kit version of whoami.exe next to the script (or in the system32 folder of each machine).

    CSI_IsSession.vbs contains a single function that can tell you almost anything you want to know about UAC or the current session the script is running under.

    VBScriptUACKit.vbs (which uses CSI_IsSession.vbs) allows you to selectively prompt for UAC in a script by relaunching itself. Has been designed and debugged to work under many execution scenarios.

    Both scripts contain sample code that demonstrates how to use the core script code.

    quux : Wow, you really researched this! The blog article at your CSI_IsSession.vbs link is packed full of good info; thanks for that. It's still a bummer that vbscript can't do this without a call to whoami.exe, though.

0 comments:

Post a Comment