Win7 UAC 提权 和 降权 的问题【已解决】
本帖最后由 wanghong01 于 2011-5-19 23:37 编辑大家好!!{:face (396):}
我有一个问题,就是当我的脚本在win7提权运行后就无法降权了,比如我的脚本要重启资源管理器,可资源管理器也同时具有了管理员权限,这不是我要的。以前我也询问过,得到的回答都是采用与RANAS类似的方式。可是Win7UAC提权并没有使用另外的用户运行程序啊。那种方式是不行的。在Autoit官方论坛找到了一个Win7提权和降权的脚本,可是在我的Win7SP1运行降权出错,谁能帮帮我吗?谢谢。
#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Res_requestedExecutionLevel=asInvoker
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
#region ;**** Directives created by AutoIt3Wrapper_GUI ****s
#include <GUIButton.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
$sTitle = "UAC Elevate and DeElevate Example"
If StringRegExp(@OSVersion, "_(XP|200(0|3))") Then
MsgBox(16 + 262144, $sTitle, "Example only works for Vista+ OSs")
Exit
ElseIf Not @Compiled Then
MsgBox(16 + 262144, $sTitle, "Example only works compiled")
Exit
EndIf
$hGui = GUICreate($sTitle, 340, 90, Default,Default,Default, $WS_EX_TOPMOST)
If IsAdmin() Then
GUICtrlCreateLabel("Script is running in elevated mode (with admin rights)", 10, 10, 320, 20, $SS_CENTER)
Else
GUICtrlCreateLabel("Script is not running in elevated mode (with standard user rights)", 10, 10, 320, 20, $SS_CENTER)
EndIf
$c_Btn_Elevate = GUICtrlCreateButton("Elevate Script", 25, 30, 130, 30)
If IsAdmin() Then GUICtrlSetState(-1, $GUI_DISABLE)
_GUICtrlButton_SetShield(GUICtrlGetHandle($c_Btn_Elevate))
$c_Btn_DeElevate = GUICtrlCreateButton("Remove Elevation", 165, 30, 130, 30)
If Not IsAdmin() Then GUICtrlSetState(-1, $GUI_DISABLE)
$c_ChkB_Elavate_Always = GUICtrlCreateCheckbox("Auto-Elevate script on Start", 25, 65)
GUICtrlSetTip(-1, "Checking this box will add an ""Application Compatibility Flag"" to the registry at" & @CRLF & @CRLF & _
"HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers" & @CRLF & @CRLF & _
",adding the executable URL as the Key with the value RUNASADMIN." & @CRLF & @CRLF & _
"Before moving or deleting the script make sure that the checkbox is unchecked (the registry" & @CRLF & _
"key is deleted) to not produce an orphaned RegKey.", "Auto-Elevate", 1, 1)
If Not IsAdmin() Then
GUICtrlSetState(-1, $GUI_DISABLE)
Else
If RegRead("HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers", @ScriptFullPath) = "RUNASADMIN" Then GUICtrlSetState(-1, $GUI_CHECKED)
EndIf
GUISetState(@SW_SHOW)
While 1
Switch GUIGetMsg()
Case $GUI_EVENT_CLOSE
ExitLoop
Case $c_Btn_Elevate
If ShellExecute(@ScriptName, "", "", "runas") Then
Exit
Else
MsgBox(16 + 262144, $sTitle & " - Error", "Something went wrong, you canceled the UAC prompt?")
EndIf
Case $c_Btn_DeElevate
$iPID = _RunWithReducedPrivileges(@ScriptName, "", @ScriptDir)
$iError = @error
If ProcessExists($iPID) Then
Exit
Else
MsgBox(16 + 262144, $sTitle & " - Error", "Something went wrong..." & @CRLF & "Error code: " & $iError)
EndIf
Case $c_ChkB_Elavate_Always
$sRegString = "HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers"
Switch GUICtrlRead($c_ChkB_Elavate_Always)
Case 1
If Not RegWrite("HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers", @ScriptFullPath, "REG_SZ", "RUNASADMIN") Then
MsgBox(16 + 262144, $sTitle & " - Error", "Something went wrong, could not write AppCompatFlag to Registry.")
GUICtrlSetState($c_ChkB_Elavate_Always, $GUI_UNCHECKED)
Else
MsgBox(16 + 262144, $sTitle, "RUNASADMIN added.")
EndIf
Case Else
If Not RegDelete("HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers", @ScriptFullPath) Then
MsgBox(16 + 262144, $sTitle & " - Error", "Something went wrong, could not write AppCompatFlag to Registry.")
GUICtrlSetState($c_ChkB_Elavate_Always, $GUI_UNCHECKED)
Else
MsgBox(16 + 262144, $sTitle & " - Error", "RUNASADMIN removed.")
EndIf
EndSwitch
EndSwitch
WEnd
Exit
; ===============================================================================================================================
; <_RunWithReducedPrivileges.au3>
;
; Function to run a program with reduced privileges.
; Useful when running in a higher privilege mode, but need to start a program with reduced privileges.
; - A common problem this fixes is drag-and-drop not working, and misc functions (sendmessage, etc) not working.
;
; Functions:
; _RunWithReducedPrivileges() ; runs a process with reduced privileges if currently running in a higher privilege mode
;
; INTERNAL Functions:
; _RWRPCleanup() ; Helper function for the above
;
; Reference:
; See 'Creating a process with Medium Integration Level from the process with High Integration Level in Vista'
; @ http://www.codeproject.com/KB/vista-security/createprocessexplorerleve.aspx
; See Elmue's comment 'Here the cleaned and bugfixed code'
; Also see: 'High elevation can be bad for your application: How to start a non-elevated process at the end of the installation'
; @ http://www.codeproject.com/KB/vista-security/RunNonElevated.aspx
; (Elmue has the same code here too in his response to FaxedHead's comment ('Another alternative to this method'))
; Another alternative using COM methods:
; 'Getting the shell to run an application for you - Part 2:How | BrandonLive'
; @ http://brandonlive.com/2008/04/27/gettin...o-run-an-application-for-you-p
;
; Author: Ascend4nt, based on code by Elmue's fixed version of Alexey Gavrilov's code
; ===============================================================================================================================
; ===================================================================================================================
; Func _RunWithReducedPrivileges($sPath,$sCmd='',$sFolder='',$iShowFlag=@SW_SHOWNORMAL,$bWait=False)
;
; Function to run a program with reduced privileges.
; Useful when running in a higher privilege mode, but need to start a program with reduced privileges.
; - A common problem this fixes is drag-and-drop not working, and misc functions (sendmessage, etc) not working.
;
; $sPath = Path to executable
; $sCmd = Command-line (optional)
; $sFolder = Folder to start in (optional)
; $iShowFlag = how the program should appear on startup. Default is @SW_SHOWNORMAL.
; All the regular @SW_SHOW* macros should work here
; $bWait = If True, waits for the process to finish before returning with an exit code
; If False, it returns without waiting for the process to finish, with the process ID #
;
; Returns:
; Success: If $bWait=True, the exit code of the Process. If $bWait=False, then the Process ID # of the process
; Failure: 0, with @error set:
; @error = 2 = DLLCall error. @extended contains the DLLCall error code (see AutoIt Help)
; @error = 3 = API returned failure. Call 'GetLastError' API function to get more info.
;
; Author: Ascend4nt, based on code by Elmue's fixed version of Alexey Gavrilov's code
; ===================================================================================================================
Func _RunWithReducedPrivileges($sPath, $sCmd = '', $sFolder = '', $iShowFlag = @SW_SHOWNORMAL, $bWait = False)
Local $aRet, $iErr, $iRet = 1, $hProcess, $hToken, $hDupToken, $stStartupInfo, $stProcInfo
Local $sCmdType = "wstr", $sFolderType = "wstr"
;~Run normally if not in an elevated state, or if pre-Vista O/S
If Not IsAdmin() Or StringRegExp(@OSVersion, "_(XP|200(0|3))") Then ; XP, XPe, 2000, or 2003?
If $bWait Then Return RunWait($sPath & ' ' & $sCmd, $sFolder)
Return Run($sPath & ' ' & $sCmd, $sFolder)
EndIf
;~Check Parameters and adjust DLLCall types accordingly
If Not IsString($sCmd) Or $sCmd = '' Then
$sCmdType = "ptr"
$sCmd = 0
EndIf
If Not IsString($sFolder) Or $sFolder = '' Then
$sFolderType = "ptr"
$sFolder = 0
EndIf
#cs
; STARTUPINFOW struct: cb,lpReserved,lpDesktop,lpTitle,dwX,dwY,dwXSize,dwYSize,dwXCountChars,dwYCountChars,dwFillAttribute,
; dwFlags,wShowWindow,cbReserved2,lpReserved2,hStdInput,hStdOutput,hStdError
; NOTE: This is for process creation info. Also, not sure if the Std I/O can be redirected..?
#ce
$stStartupInfo = DllStructCreate("dword;ptr;dword;dword;word;word;ptr;handle")
DllStructSetData($stStartupInfo, 1, DllStructGetSize($stStartupInfo))
DllStructSetData($stStartupInfo, 4, 1) ; STARTF_USESHOWWINDOW
DllStructSetData($stStartupInfo, 5, $iShowFlag)
; PROCESS_INFORMATION struct: hProcess, hThread, dwProcessId, dwThreadId
; This is for *receiving* info
$stProcInfo = DllStructCreate("handle;handle;dword;dword")
;~Open a handle to the Process
; Explorer runs under a lower privilege, so it is the basis for our security info.
; Open the process with PROCESS_QUERY_INFORMATION (0x0400) access
$aRet = DllCall("kernel32.dll", "handle", "OpenProcess", "dword", 0x0400, "bool", False, "dword", ProcessExists("explorer.exe"))
If @error Then Return SetError(2, @error, 0)
If Not $aRet Then Return SetError(3, 0, 0)
$hProcess = $aRet
;~Open a handle to the Process's token (for duplication)
; TOKEN_DUPLICATE = 0x0002
$aRet = DllCall("advapi32.dll", "bool", "OpenProcessToken", "handle", $hProcess, "dword", 2, "handle*", 0)
If @error Then Return SetError(_RWRPCleanup($hProcess, 0, 0, 2, @error), @extended, 0)
If $aRet = 0 Then Return SetError(_RWRPCleanup($hProcess, 0, 0, 3), @extended, 0)
$hToken = $aRet
;~Duplicate the token handle
; TOKEN_ALL_ACCESS = 0xF01FF, SecurityImpersonation = 2, TokenPrimary = 1,
$aRet = DllCall("advapi32.dll", "bool", "DuplicateTokenEx", "handle", $hToken, "dword", 0xF01FF, "ptr", 0, "int", 2, "int", 1, "handle*", 0)
If @error Then Return SetError(_RWRPCleanup($hProcess, $hToken, 0, 2, @error), @extended, 0)
If Not $aRet Then Return SetError(_RWRPCleanup($hProcess, $hToken, 0, 3), @extended, 0)
$hDupToken = $aRet
;~Create the process using 'CreateProcessWithTokenW' (Vista+ O/S function)
$aRet = DllCall("advapi32.dll", "bool", "CreateProcessWithTokenW", "handle", $hDupToken, "dword", 0, "wstr", $sPath, $sCmdType, $sCmd, _
"dword", 0, "ptr", 0, $sFolderType, $sFolder, "ptr", DllStructGetPtr($stStartupInfo), "ptr", DllStructGetPtr($stProcInfo))
$iErr = @error
_RWRPCleanup($hProcess, $hToken, $hDupToken, 2, @error)
If $iErr Then Return SetError(2, $iErr, 0)
If Not $aRet Then Return SetError(3, 0, 0)
;~MsgBox(0,"Info","Process info data: Process handle:"&DllStructGetData($stProcInfo,1)&", Thread handle:"&DllStructGetData($stProcInfo,2)& _
;~ ", Process ID:"&DllStructGetData($stProcInfo,3)&", Thread ID:"&DllStructGetData($stProcInfo,4)&@CRLF)
$iRet = DllStructGetData($stProcInfo, 3) ; Process ID
;~If called in 'RunWait' style, wait for the process to close
If $bWait Then
ProcessWaitClose($iRet)
$iRet = @extended ; Exit code
EndIf
;~Close Thread and then Process handles (order here is important):
_RWRPCleanup(0, DllStructGetData($stProcInfo, 2), DllStructGetData($stProcInfo, 1), 0)
Return $iRet
EndFunc ;==>_RunWithReducedPrivileges
; ===================================================================================================================
; Func _RWRPCleanup($hProcess,$hToken,$hDupToken,$iErr=0,$iExt=0)
;
; INTERNAL: Helper function for _RunWithReducedPrivileges()
;
; Author: Ascend4nt
; ===================================================================================================================
Func _RWRPCleanup($hProcess, $hToken, $hDupToken, $iErr = 0, $iExt = 0)
Local $aHandles = [$hToken, $hDupToken, $hProcess] ; order is important
For $i = 0 To 2
If $aHandles[$i] <> 0 Then DllCall("kernel32.dll", "bool", "CloseHandle", "handle", $aHandles[$i])
Next
Return SetExtended($iExt, $iErr)
EndFunc ;==>_RWRPCleanup
本帖最后由 daiyu116 于 2011-5-19 15:27 编辑
回复 1# wanghong01
最近也在使用UAC,发现论坛里面对UAC关注不太多,可能是因为中国使用盗版系统太多了,大部分都在安装操作系统的时候把UAC关掉了,所以测试的机会很少。
LZ所写的脚本不是太懂,请关注一下其中这一句:
If Not $aRet Then Return SetError(3, 0, 0)
另外,贴上我自己曾经用过的UAC降权脚本,也是需要用户互动才可以,其实如果用户不互动的话他也没办法继续运行后面的函数。
#RequireAdmin ;必须添加本行,否则在UAC状态下不起作用。
$value1=RegRead("HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Policies\System", "ConsentPromptBehaviorAdmin")
$value2=RegRead("HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Policies\System", "EnableLUA")
$value3=RegRead("HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Policies\System", "PromptOnSecureDesktop")
If $value2=0 Then ;说明没有开启UAC
install()
ElseIf $value2=1Then
MsgBox(0,"系统启用UAC","您的操作系统启用了UAC,运行本程序将弹出确认对话框,请点击确定,否则无法正常运行!")
$value_2=RegWrite("HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Policies\System", "ConsentPromptBehaviorAdmin","REG_DWORD","0")
$value_3=RegWrite("HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Policies\System", "PromptOnSecureDesktop","REG_DWORD","0")
$value_1=RegWrite("HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Policies\System", "EnableLUA","REG_DWORD","0")
If $value_2=1 And $value_3=1 And $value_1=1 Then
install()
Else
MsgBox(0,"修改UAC设置未成功","请确认在运行本程序时对系统弹出的对话框确认!请重新运行本程序,否则请联络系统管理员处理!"&@error)
Exit
EndIf
#comments-start
;以下三项ElseIf综合起来为方式二,但不如方式一便捷直接
ElseIf $value1=2 And $value2=1 And $value3=1 Then ;对应UAC最高权限
;Run(@WindowsDir&"\System32\UserAccountControlSettings.exe")
;WinSetOnTop("","",1)
;WinWaitActive("")
;ControlFocus ("","","msctls_trackbar321")
;Send("{DOWN 4}")
;ControlClick("","","Button1")
;install()
ElseIf $value1=5 And $value2=1 And $value3=1 Then ;对应UAC中等权限
Run(@WindowsDir&"\System32\UserAccountControlSettings.exe")
WinWaitActive("")
ControlFocus ("","","msctls_trackbar321")
Send("{DOWN 3}")
ControlClick("","","Button1")
MsgBox(0,"修改UAC设置","chongqi")
install()
ElseIf $value1=5 And $value2=1 And $value3=0 Then ;对应UAC最低权限
Run(@WindowsDir&"\System32\UserAccountControlSettings.exe")
WinWaitActive("")
ControlFocus ("","","msctls_trackbar321")
Send("{DOWN 2}")
ControlClick("","","Button1")
MsgBox(0,"修改UAC设置","chongqi")
install()
#comments-end
EndIf
FUNC INSTALL()
.......................这里是我自己的函数,就不贴了
ENDFUNC
谢谢楼上的!
可是并没有解决我的问题。
我不是要关闭UAC,只是要降权运行另外的程序。
就像Win7的任务管理器一样,在管理员模式也可以降权运行其他程序,但不是以另外的身份运行程序。 重装系统,问题解决了。 收藏备用,学习Win7 回复 2# daiyu116
感谢
页:
[1]