#RequireAdmin #include #include #include Func _PrepareForUIAccess() Local $bReturn = False Local $bChecked = __CheckForUIAccess() If Not $bChecked Then Local $hToken = _CreateUIAccessToken() If Not @error Then If @Compiled Then ;~ Local $sCommandLine = StringFormat('"%s" "-s"', @ScriptFullPath) Local $sCommandLine = StringFormat('"%s"', @ScriptFullPath) Else ;~ Local $sCommandLine = StringFormat('"%s" /AutoIt3ExecuteScript "%s" "-s"', @AutoItExe, @ScriptFullPath) Local $sCommandLine = StringFormat('"%s" /AutoIt3ExecuteScript "%s"', @AutoItExe, @ScriptFullPath) EndIf Local $tStartupInfo = DllStructCreate($tagSTARTUPINFO) Local $tProcessInfo = DllStructCreate($tagPROCESS_INFORMATION) Local $sDesktop = "winsta0\default" Local $lpDesktop = DllStructCreate("wchar[" & StringLen($sDesktop) + 1 & "]") DllStructSetData($lpDesktop, 1, $sDesktop) DllStructSetData($tStartupInfo, "Desktop", DllStructGetPtr($lpDesktop)) DllStructSetData($tStartupInfo, "Flags", 0x1) DllStructSetData($tStartupInfo, "ShowWindow", @SW_SHOW) DllStructSetData($tStartupInfo, "Size", DllStructGetSize($tStartupInfo)) DllStructSetData($tProcessInfo, "Size", DllStructGetSize($tProcessInfo)) Local $lpProcessAttributes = DllStructCreate($tagSECURITY_ATTRIBUTES) DllStructSetData($lpProcessAttributes, "Descriptor", "") DllStructSetData($lpProcessAttributes, "Length", DllStructGetSize($lpProcessAttributes)) Local $lpThreadAttributes = DllStructCreate($tagSECURITY_ATTRIBUTES) DllStructSetData($lpThreadAttributes, "Descriptor", "") DllStructSetData($lpThreadAttributes, "Length", DllStructGetSize($lpThreadAttributes)) Local $iResult = DllCall("advapi32.dll", "bool", "CreateProcessAsUserW", _ ;~ "ptr", $pEnvironment, _ ;$lpEnvironment "handle", $hToken, _ ;hToken "ptr", 0, _ ;lpApplicationName, _ "wstr", StringFormat("%s", $sCommandLine), _ "ptr", $lpProcessAttributes, _ "ptr", $lpThreadAttributes, _ "bool", 0, _ ;$bInheritHandles, _ "dword", BitOR($NORMAL_PRIORITY_CLASS, $CREATE_NEW_CONSOLE), _ "ptr", Null, _ ;$lpEnvironment "wstr", @SystemDir, _ ;$lpCurrentDirectory "ptr", DllStructGetPtr($tStartupInfo), _ ;$lpStartupInfo "ptr", DllStructGetPtr($tProcessInfo)) ;$lpProcessInformation If $iResult[0] Then _WinAPI_CloseHandle($hToken) _WinAPI_CloseHandle(DllStructGetData($tProcessInfo, "hProcess")) _WinAPI_CloseHandle(DllStructGetData($tProcessInfo, "hThread")) Exit Else Local $iError = _WinAPI_GetLastError() Local $errmsg = _WinAPI_GetLastErrorMessage() _WinAPI_CloseHandle($hToken) _WinAPI_CloseHandle(DllStructGetData($tProcessInfo, "hProcess")) _WinAPI_CloseHandle(DllStructGetData($tProcessInfo, "hThread")) Return SetError(1, $iError, $errmsg) EndIf Else Return SetError(2, @extended, @error) EndIf EndIf EndFunc ;==>_PrepareForUIAccess Func _CreateUIAccessToken() Local $hNewTokDuplicate, $iError = 0 Local $hToken = _Security__OpenProcessToken(_WinAPI_GetCurrentProcess(), BitOR($TOKEN_QUERY, $TOKEN_DUPLICATE)) If $hToken Then Local $tInfo = _Security__GetTokenInformation($hToken, $TokenSessionId) If $tInfo = 0 Then $iError = _WinAPI_GetLastError() Else Local $iTokenSessionId = DllStructGetData(DllStructCreate("int", DllStructGetPtr($tInfo)), 1) If $iTokenSessionId Then Local $hTokDuplicate = _DuplicateWinloginToken() If Not @error Then If __SetThreadToken(0, $hTokDuplicate) Then $hNewTokDuplicate = _Security__DuplicateTokenEx($hToken, BitOR($TOKEN_QUERY, $TOKEN_DUPLICATE, $TOKEN_ASSIGN_PRIMARY, $TOKEN_ADJUST_DEFAULT), $SECURITYANONYMOUS, $TOKENPRIMARY) ;创建一个重复现有令牌的新访问令牌 If Not @error Then Local $tTOKENUIACCESS = DllStructCreate("DWORD") DllStructSetData($tTOKENUIACCESS, 1, 1) Local $iResult = _Security__SetTokenInformation($hNewTokDuplicate, $TOKENUIACCESS, $tTOKENUIACCESS, DllStructGetSize($tTOKENUIACCESS)) ;设置指定访问令牌的TOKENINTEGRITYLEVEL信息 If $iResult Then $iError = 0 Else $iError = _WinAPI_GetLastError() EndIf ;~ MsgBox(0,0, $iResult) Else EndIf __RevertToSelf() Else $iError = @error EndIf _WinAPI_CloseHandle($hTokDuplicate) EndIf Else $iError = _WinAPI_GetLastError() EndIf EndIf _WinAPI_CloseHandle($hToken) Else $iError = _WinAPI_GetLastError() EndIf Return SetError($iError, 0, $hNewTokDuplicate) EndFunc ;==>_CreateUIAccessToken Func _DuplicateWinloginToken() Local $dwErr, $hTokDuplicate Local $vLUID = _Security__LookupPrivilegeValue("", $SE_TCB_NAME) If $vLUID Then Local $aProcessInfo = [['winlogon.exe', 'SYSTEM', -1]] Local $iTargetProcessPID = 0 For $i = 0 To UBound($aProcessInfo) - 1 $iTargetProcessPID = __GetTargetProcessPID($aProcessInfo[$i][0], $aProcessInfo[$i][1], $aProcessInfo[$i][2]) If $iTargetProcessPID > 0 Then ExitLoop Next If $iTargetProcessPID <> 0 Then Local $hTargetProcess = _WinAPI_OpenProcess($PROCESS_QUERY_LIMITED_INFORMATION, 0, $iTargetProcessPID) ;打开进程 If $hTargetProcess Then Local $hTargetProcessToken = _Security__OpenProcessToken($hTargetProcess, BitOR($TOKEN_QUERY, $TOKEN_DUPLICATE)) ;;返回与进程关联的访问令牌,包含复制权限 If $hTargetProcessToken Then $hTokDuplicate = _Security__DuplicateTokenEx($hTargetProcessToken, $TOKEN_IMPERSONATE, $SECURITYIMPERSONATION, $TOKENIMPERSONATION) ;创建一个重复现有令牌的新访问令牌 If Not @error Then $dwErr = 0 Else $dwErr = _WinAPI_GetLastError() EndIf _WinAPI_CloseHandle($hTargetProcessToken) Else $dwErr = _WinAPI_GetLastError() EndIf _WinAPI_CloseHandle($hTargetProcess) Else $dwErr = _WinAPI_GetLastError() EndIf EndIf Else $dwErr = _WinAPI_GetLastError() EndIf Return SetError($dwErr, 0, $hTokDuplicate) EndFunc ;==>_DuplicateWinloginToken Func __CheckForUIAccess($PID = 0) Local $bReturn = False, $iError = 0 Local $hToken,$hProcess If $PID = 0 Then $hToken = _Security__OpenProcessToken(_WinAPI_GetCurrentProcess(), $TOKEN_QUERY) Else $hProcess = _WinAPI_OpenProcess($PROCESS_QUERY_LIMITED_INFORMATION, 0, $PID) If $hProcess Then $hToken = _Security__OpenProcessToken($hProcess, $TOKEN_QUERY) _WinAPI_CloseHandle($hProcess) Else $iError = _WinAPI_GetLastError() EndIf EndIf If $hToken Then Local $tInfo = _Security__GetTokenInformation($hToken, $TokenUIAccess) If $tInfo = 0 Then $iError = _WinAPI_GetLastError() Else Local $bTokenUIAccess = DllStructGetData(DllStructCreate("int", DllStructGetPtr($tInfo)), 1) If $bTokenUIAccess Then $bReturn = True EndIf _WinAPI_CloseHandle($hToken) Else $iError = _WinAPI_GetLastError() EndIf Return SetError(0, 0, $bReturn) EndFunc ;==>_CheckForUIAccess Func __SetThreadToken($hThread = 0, $hToken = 0) Local $aRet = DllCall("AdvApi32.dll", "bool", "SetThreadToken", _ "ptr", $hThread, "handle", $hToken) Return SetError(_WinAPI_GetLastError(), 0, $aRet[0]) EndFunc ;==>__SetThreadToken Func __GetTargetProcessPID($sProcessName, $sUserName = 'SYSTEM', $iSessionId = 0) ;~ __SetRequirePrivilege() Local $aWinlogon If $iSessionId = -1 Then $iSessionId = _WTSGetActiveConsoleSessionId() $aWinlogon = ProcessList($sProcessName) For $i = 1 To $aWinlogon[0][0] If StringLower(__GetProcessUser($aWinlogon[$i][1])) == StringLower($sUserName) And _ProcessGetSessionID($aWinlogon[$i][1]) = $iSessionId Then Return $aWinlogon[$i][1] Next Return 0 EndFunc ;==>__GetTargetProcessPID Func __GetProcessUser($PID) Local $hProcess = _WinAPI_OpenProcess($PROCESS_QUERY_LIMITED_INFORMATION, 0, $PID) If @error Then Return SetError(1, _WinAPI_GetLastError(), _WinAPI_GetLastErrorMessage()) Local $hToken = _Security__OpenProcessToken($hProcess, $TOKEN_QUERY) _WinAPI_CloseHandle($hProcess) If Not $hToken Then Return SetError(2, _WinAPI_GetLastError(), _WinAPI_GetLastErrorMessage()) Local $tInfo = _Security__GetTokenInformation($hToken, $TOKEN_ASSIGN_PRIMARY) _WinAPI_CloseHandle($hToken) If $tInfo = 0 Then Return SetError(3, _WinAPI_GetLastError(), _WinAPI_GetLastErrorMessage()) Local $iTokenType = DllStructGetData(DllStructCreate("int_ptr", DllStructGetPtr($tInfo)), 1) Local $aSidInfo = _Security__LookupAccountSid($iTokenType) If Not @error Then Return SetError(0, 0, $aSidInfo[0]) Return SetError(4, _WinAPI_GetLastError(), _WinAPI_GetLastErrorMessage()) EndFunc ;==>__GetProcessUser Func __RevertToSelf() Local $aRet = DllCall("AdvApi32.dll", "bool", "RevertToSelf") Return SetError(_WinAPI_GetLastError(), 0, $aRet[0]) EndFunc ;==>__RevertToSelf Func _ProcessGetSessionID($vProcessID) Local $aRet = DllCall("Kernel32.dll", "bool", "ProcessIdToSessionId", "dword", $vProcessID, "dword*", 0) If @error Then Return SetError(2, @error, -1) If Not $aRet[0] Then Return SetError(3, 0, -1) Return $aRet[2] EndFunc ;==>_ProcessGetSessionID Func _WTSGetActiveConsoleSessionId() Local $aRet = DllCall('Kernel32.dll', 'dword', 'WTSGetActiveConsoleSessionId') Return $aRet[0] EndFunc ;==>_WTSGetActiveConsoleSessionId _PrepareForUIAccess()