【提问求助】以服务运行指定程序,权限不继承
在论坛上找到的解决方案是将自己的程序注册为一项服务,赋予它system权限,目前的功能是通过服务启动其他程序。然而,我遇到的问题是服务在启动程序时,权限会一直沿用system级别。是否有方法能让服务在启动第一个程序(比如A)时使用system权限,而当A程序进一步启动其他程序(比如B)时,以当前运行用户的权限执行呢?
目标是确保服务启动链的第一步(如A程序)利用system权限,后续步骤则切换到当前用户权限,以提高安全性和灵活性。
Const $hAdvApi32Dll = DllOpen("AdvApi32.dll")
Const $hKernel32Dll = DllOpen("Kernel32.dll")
Const $tagSERVICE_TABLE_ENTRY = "ptr ServiceName;ptr ServiceMain"
Const $tagSERVICE_STATUS = "dword ServiceType;dword CurrentState;dword ControlsAccepted;dword Win32ExitCode;dword ServiceSpecificExitCode;dword CheckPoint;dword WaitHint"
Global $hServiceStatus, $tServiceStatus, $pServiceStatus
Global $hServiceMain, $pServiceMain, $tServiceTable, $pServiceTable
Global $hServiceHandlerEx, $pServiceHandlerEx
Global $Type, $Start, $ErrorControl, $Description
InstallService("0x00000110", "0x00000002", "0x00000001", "服务验证示例")
;说明:将自身注册为系统服务的函数
;语法:InstallService($Type,$Start,$ErrorControl,$Description)
;$Type,服务类型,"0x00000110"为与桌面交互
;$Start,启动方式,"0x00000002"为自动启动
;$ErrorControl,错误控制,"0x00000001"为无操作
;$Description,描述
Func InstallService($Type, $Start, $ErrorControl, $Description)
$hServiceMain = DllCallbackRegister("_ServiceMain", "none", "dword;ptr")
$pServiceMain = DllCallbackGetPtr($hServiceMain)
$hServiceHandlerEx = DllCallbackRegister("_ServiceHandlerEx", "dword", "dword;dword;ptr;ptr")
$pServiceHandlerEx = DllCallbackGetPtr($hServiceHandlerEx)
$pServiceTable = _ServiceHeapAlloc(32)
$tServiceTable = DllStructCreate($tagSERVICE_TABLE_ENTRY, $pServiceTable)
DllStructSetData($tServiceTable, "ServiceName", $pServiceTable + 16)
DllStructSetData($tServiceTable, "ServiceMain", $pServiceMain)
$tServiceName = DllStructCreate("char ServiceName", $pServiceTable + 16)
DllStructSetData($tServiceName, "ServiceName", @ScriptName)
$tServiceStatus = DllStructCreate($tagSERVICE_STATUS)
$pServiceStatus = DllStructGetPtr($tServiceStatus)
DllStructSetData($tServiceStatus, "ServiceType", 16)
DllStructSetData($tServiceStatus, "ControlsAccepted", 3)
_StartServiceCtrlDispatcher($pServiceTable)
;注册服务
RegWrite('HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\PcLimit')
RegWrite('HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\PcLimit', 'Type', 'REG_DWORD', $Type)
RegWrite('HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\PcLimit', 'Start', 'REG_DWORD', $Start)
RegWrite('HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\PcLimit', 'ErrorControl', 'REG_DWORD', $ErrorControl)
RegWrite('HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\PcLimit', 'ImagePath', 'REG_EXPAND_SZ', @ScriptFullPath)
RegWrite('HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\PcLimit', 'DisplayName', 'REG_SZ', @ScriptName)
RegWrite('HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\PcLimit', 'ObjectName', 'REG_SZ', 'LocalSystem')
RegWrite('HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\PcLimit', 'Description', 'REG_SZ', $Description)
RegWrite('HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\PcLimit\Enum')
RegWrite('HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\PcLimit\Enum', '0', 'REG_SZ', 'Root\LEGACY_PCLIMIT\0000')
RegWrite('HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\PcLimit\Enum', 'Count', 'REG_DWORD', '0x00000001')
RegWrite('HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\PcLimit\Enum', 'NextInstance', 'REG_DWORD', '0x00000001')
EndFunc ;==>InstallService
Func _StartServiceCtrlDispatcher($pServiceTable)
Local $iResult
$iResult = DllCall($hAdvApi32Dll, "int", "StartServiceCtrlDispatcher", "ptr", $pServiceTable)
Return SetError(_ServiceLastError(), 0, $iResult)
EndFunc ;==>_StartServiceCtrlDispatcher
Func _SetServiceStatus($hServiceStatus, $pServiceStatus)
Local $iResult
$iResult = DllCall($hAdvApi32Dll, "int", "SetServiceStatus", "hWnd", $hServiceStatus, _
"ptr", $pServiceStatus)
Return SetError(_ServiceLastError(), 0, $iResult)
EndFunc ;==>_SetServiceStatus
Func _RegisterServiceCtrlHandlerEx($sServiceName, $pHandlerEx, $pContext = 0)
Local $iResult
$iResult = DllCall($hAdvApi32Dll, "hWnd", "RegisterServiceCtrlHandlerEx", _
"str", $sServiceName, "ptr", $pHandlerEx, "ptr", $pContext)
Return SetError(_ServiceLastError(), 0, $iResult)
EndFunc ;==>_RegisterServiceCtrlHandlerEx
Func _ServiceHandlerEx($iRequest, $iEventType, $pEventData, $pContext)
Switch $iRequest
Case 1
DllStructSetData($tServiceStatus, "CurrentState", 1)
_SetServiceStatus($hServiceStatus, $pServiceStatus)
Return 0
Case 2
DllStructSetData($tServiceStatus, "CurrentState", 7)
_SetServiceStatus($hServiceStatus, $pServiceStatus)
Return 0
Case 3
DllStructSetData($tServiceStatus, "CurrentState", 5)
_SetServiceStatus($hServiceStatus, $pServiceStatus)
Sleep(5000)
DllStructSetData($tServiceStatus, "CurrentState", 4)
_SetServiceStatus($hServiceStatus, $pServiceStatus)
Return 0
Case 4
_SetServiceStatus($hServiceStatus, $pServiceStatus)
Return 0
EndSwitch
EndFunc ;==>_ServiceHandlerEx
Func _ServiceHeapAlloc($iSize, $iFlags = 8)
If $iSize < 1 Then Return SetError(87, 0, 0)
Local $hHeap, $iResult
$hHeap = DllCall($hKernel32Dll, "hWnd", "GetProcessHeap")
$iResult = DllCall($hKernel32Dll, "ptr", "HeapAlloc", "hWnd", $hHeap, _
"dword", $iFlags, "dword", $iSize)
Return $iResult
EndFunc ;==>_ServiceHeapAlloc
Func _ServiceHeapFree(ByRef $pBuffer)
If $pBuffer = 0 Then Return SetError(87, 0, 0)
Local $iResult, $hHeap
$hHeap = DllCall($hKernel32Dll, "hWnd", "GetProcessHeap")
$iResult = DllCall($hKernel32Dll, "int", "HeapFree", "hWnd", $hHeap, _
"dword", 0, "ptr", $pBuffer)
If $iResult Then $pBuffer = 0
Return $iResult
EndFunc ;==>_ServiceHeapFree
Func _ServiceHeapSize(ByRef $pBuffer)
If $pBuffer = 0 Then Return SetError(87, 0, 0)
Local $iResult, $hHeap
$hHeap = DllCall($hKernel32Dll, "hWnd", "GetProcessHeap")
$iResult = DllCall($hKernel32Dll, "int", "HeapSize", "hWnd", $hHeap, _
"dword", 0, "ptr", $pBuffer)
Return $iResult
EndFunc ;==>_ServiceHeapSize
Func _ServiceLastError()
Local $iResult
$iResult = DllCall($hKernel32Dll, "dword", "GetLastError")
Return $iResult
EndFunc ;==>_ServiceLastError
Func _ServiceMain($iNumberofArgs, $pArgs)
$hServiceStatus = _RegisterServiceCtrlHandlerEx(@ScriptName, $pServiceHandlerEx)
DllStructSetData($tServiceStatus, "CurrentState", 4)
_SetServiceStatus($hServiceStatus, $pServiceStatus)
EndFunc ;==>_ServiceMain
#include-once
#cs ----------------------------------------------------------------------------
必须运行在服务(system)权限下,用于系统服务程序启动第三方程序与用户桌面进行交互
Opt('MustDeclareVars', 1)
RunOnDesktop(@ComSpec, False)
#ce ----------------------------------------------------------------------------
#include <winapi.au3>
#include <array.au3>
#include <security.au3>
#include <StructureConstants.au3>
#include <WinAPISys.au3>
#CS
$NULL = 0
$WTS_CURRENT_SERVER_HANDLE = $NULL
$WTSActive = 0
$WTSShadow = 1
$WTSConnectQuery = 2
$CREATE_UNICODE_ENVIRONMENT = 0x00000400
$DETACHED_PROCESS = 0x00000008
$MAX_PATH = 260
$PROCESS_ALL_ACCESS = 0x001F0FFF
;~ $TOKEN_ALL_ACCESS = 0xf01ff
$ERROR_SUCCESS = 0
Global Const $tagWTS_SESSION_INFO = 'dword SessionId;ptr WinStationName;uint State'
$NORMAL_PRIORITY_CLASS = 0x20
#CE
Func RunOnDesktop($app_path, $UseSystemRights = False)
;~ Local $bReturn = False
Local $hToken = 0
Local $env = 0
Local $iConsoleID = 0
Local $iProcessPID = 0
Local $hCur = 0
Local $hCurToken = 0
Local $CREATE_NEW_CONSOLE = 0x00000010
Local $CREATE_UNICODE_ENVIRONMENT = 0x00000400
Local $NORMAL_PRIORITY_CLASS = 0x20
;Get active Desktop ID
$iConsoleID = WTSGetActiveConsoleSessionId()
$hToken = WTSQueryUserToken($iConsoleID)
CreateEnvironmentBlock($env, $hToken, False) ;设定所有帐户运行在当前桌面用户环境变量
If $UseSystemRights Then
;~ Local $iWinlogonPID = 0
;~ Local $hWinlogon = 0
;~ Local $PROCESS_ALL_ACCESS = 0x001F0FFF
;~ $iWinlogonPID = _GetWinLogonPID($iConsoleID)
;~ $hWinlogon = _WinAPI_OpenProcess($PROCESS_ALL_ACCESS, False, $iWinlogonPID) ;_ProcessGetHandle($iWinlogonPID)
;~ Local $hWinLogonToken = _Security__OpenProcessToken($hWinlogon, $TOKEN_ALL_ACCESS) ;_OpenProcessToken($hWinlogon)
;~ $hToken = _Security__DuplicateTokenEx($hWinLogonToken, $TOKEN_ALL_ACCESS, $SECURITYIMPERSONATION, $TOKENPRIMARY) ;_DuplicateToken($hToken)
;~ _WinAPI_CloseHandle($hWinLogonToken) ;
;~ _WinAPI_CloseHandle($hWinlogon) ;
$hCur = _WinAPI_GetCurrentProcess()
$hCurToken = _Security__OpenProcessToken($hCur, $TOKEN_ALL_ACCESS)
$hToken = _Security__DuplicateTokenEx($hCurToken, $TOKEN_ALL_ACCESS, $SECURITYIMPERSONATION, $TOKENPRIMARY)
Local $tTOKENSESSIONID = DllStructCreate("DWORD")
DllStructSetData($tTOKENSESSIONID, 1, $iConsoleID)
Local $ret = _Security__SetTokenInformation($hToken, $TOKENSESSIONID, $tTOKENSESSIONID, DllStructGetSize($tTOKENSESSIONID))
If $bDebug Then _DebugPrint('_Security__SetTokenInformation:' & $ret) ;debug
_WinAPI_CloseHandle($hCurToken) ;
EndIf
Local $si = DllStructCreate($tagSTARTUPINFO)
Local $pi = DllStructCreate($tagPROCESS_INFORMATION)
Local $lpProcessAttributes = DllStructCreate($tagSECURITY_ATTRIBUTES)
Local $lpThreadAttributes = DllStructCreate($tagSECURITY_ATTRIBUTES)
DllStructSetData($lpThreadAttributes, "Descriptor", "")
Local $ta_size = DllStructGetSize($lpThreadAttributes)
DllStructSetData($lpThreadAttributes, "Length", $ta_size)
DllStructSetData($lpProcessAttributes, "Descriptor", "")
Local $pa_size = DllStructGetSize($lpProcessAttributes)
DllStructSetData($lpProcessAttributes, "Length", $pa_size)
DllStructSetData($si, "Desktop", "Winsta0//Default")
DllStructSetData($si, "Flags", $STARTF_USESHOWWINDOW)
DllStructSetData($si, "ShowWindow", @SW_SHOW)
Local $pi_size = DllStructGetSize($pi)
Local $si_size = DllStructGetSize($si)
DllStructSetData($pi, "Size", $pi_size)
DllStructSetData($si, "Size", $si_size)
;~ Local $ret = CreateProcessAsUser($hToken, 0, $app_path, DllStructGetPtr($lpProcessAttributes), DllStructGetPtr($lpThreadAttributes), 0, $NORMAL_PRIORITY_CLASS + $CREATE_NEW_CONSOLE, $env, "", DllStructGetPtr($si), DllStructGetPtr($pi))
Local $ret = CreateProcessAsUser($hToken, 0, $app_path, DllStructGetPtr($lpProcessAttributes), DllStructGetPtr($lpThreadAttributes), 0, $NORMAL_PRIORITY_CLASS + $CREATE_NEW_CONSOLE + $CREATE_UNICODE_ENVIRONMENT, $env, 0, DllStructGetPtr($si), DllStructGetPtr($pi))
If @error And $bDebug Then _DebugPrint('CreateProcessAsUser error:' & $ret) ;debug
$iProcessPID = DllStructGetData($pi, "ProcessID")
_WinAPI_CloseHandle(DllStructGetData($pi, "hProcess")) ;
_WinAPI_CloseHandle(DllStructGetData($pi, "hThread")) ;
_WinAPI_CloseHandle($hToken) ;
Return $iProcessPID
EndFunc ;==>RunOnDesktop
Func SetTBCPrivileges()
$dwPID = @AutoItPID
$hToken = 0
$hProcess = 0
$tpDebug = DllStructCreate($tagTOKEN_PRIVILEGES)
$hProcess = _WinAPI_OpenProcess($PROCESS_ALL_ACCESS, False, $dwPID)
If Not $hProcess Then Return False
;If not _WinAPI_OpenProcessToken($hProcess,$TOKEN_ALL_ACCESS,$hToken) Then return False
$hToken = _Security__OpenProcessToken($hProcess, $TOKEN_ALL_ACCESS)
If @error Then Return False
$LUID = _Security__LookupPrivilegeValue("", $SE_DEBUG_NAME)
If $LUID == 0 Then Return False
DllStructSetData($tpDebug, "Count", 1)
DllStructSetData($tpDebug, "LUID", $LUID, 1)
DllStructSetData($tpDebug, "Attributes", $SE_PRIVILEGE_ENABLED, 1)
If _Security__AdjustTokenPrivileges($hToken, False, DllStructGetPtr($tpDebug), DllStructGetSize($tpDebug), 0, 0) = False Then Return False
If _WinAPI_GetLastError() <> 0 Then Return False
_WinAPI_CloseHandle($hToken) ;
_WinAPI_CloseHandle($hProcess) ;
Return True
EndFunc ;==>SetTBCPrivileges
Func CreateEnvironmentBlock(ByRef $lpEnvironment, $hToken, $bInherit)
Local $struct = DllStructCreate("ptr")
Local $ret = DllCall('Userenv.dll', 'bool', 'CreateEnvironmentBlock', _
'ptr', DllStructGetPtr($struct), _
'HANDLE', $hToken, _
'bool', $bInherit)
$lpEnvironment = DllStructGetData($struct, 1)
Return $ret
EndFunc ;==>CreateEnvironmentBlock
Func WTSGetActiveConsoleSessionId()
Local $ret = DllCall('Kernel32.dll', 'dword', 'WTSGetActiveConsoleSessionId')
Return $ret
EndFunc ;==>WTSGetActiveConsoleSessionId
Func WTSQueryUserToken($SessionId)
Local $struct = DllStructCreate("HANDLE")
Local $ret = DllCall('wtsapi32.dll', 'bool', 'WTSQueryUserToken', _
'ULONG', $SessionId, _
'ptr*', DllStructGetPtr($struct))
Return $ret
EndFunc ;==>WTSQueryUserToken
Func ImpersonateLoggedOnUser(ByRef $hToken)
Local $aResult = DllCall("advapi32.dll", "int", "ImpersonateLoggedOnUser", "hwnd", $hToken)
If @error Then Return SetError(@error, @extended, 0)
Return SetError(0, 0, $aResult <> 0)
EndFunc
Func _TSSendConsoleMessage($ButtonSet, $TitleText, $MessageText, $Timeout = 10, $Wait = False)
$TitleText = StringToBinary($TitleText, 1)
Local $pTitle = DllStructCreate('byte Title[' & BinaryLen($TitleText) + 1 & ']')
DllStructSetData($pTitle, 'Title', $TitleText)
$MessageText = StringToBinary($MessageText, 1)
Local $pMessage = DllStructCreate('byte Message[' & BinaryLen($MessageText) + 1 & ']')
DllStructSetData($pMessage, 'Message', $MessageText)
Local $pResponse = DllStructCreate("DWORD Response")
Local $SessionId = WTSGetActiveConsoleSessionId()
DllStructSetData($pTitle, "Title", $TitleText)
DllStructSetData($pMessage, "Message", $MessageText)
Local $Res = DllCall("Wtsapi32.dll", "BOOL", "WTSSendMessageA", "HANDLE", "WTS_CURRENT_SERVER_HANDLE", "DWORD", $SessionId, "ptr", DllStructGetPtr($pTitle), "DWORD", DllStructGetSize($pTitle), "ptr", DllStructGetPtr($pMessage), "DWORD", DllStructGetSize($pMessage), "DWORD", $ButtonSet, "DWORD", $Timeout, "DWORD", DllStructGetPtr($pResponse), "BOOL", $Wait)
Return $Res
EndFunc ;==>_TSSendConsoleMessage
Func CreateProcessAsUser($hToken, $lpApplicationName, $lpCommandline, $lpProcessAttributes, $lpThreadAttributes, $bInheritHandles, $dwCreationFlags, $lpEnvironment, $lpCurrentDirectory, $lpStartupInfo, $lpProcessInformation)
Local $ret = DllCall("advapi32.dll", "bool", "CreateProcessAsUserW", _ ; W is better
"handle", $hToken, _
"ptr", $lpApplicationName, _ ;$lpApplicationName, _
"wstr", $lpCommandline, _ ; wstr for CreateProcessAsUserW
"ptr", $lpProcessAttributes, _
"ptr", $lpThreadAttributes, _
"bool", $bInheritHandles, _ ;$bInheritHandles, _
"dword", $dwCreationFlags, _
"ptr", $lpEnvironment, _
"ptr", $lpCurrentDirectory, _
"ptr", $lpStartupInfo, _
"ptr", $lpProcessInformation)
;If $ret = 0 Then _MsgBox(16, "proc e "&@error&" "&$hToken, _WinAPI_GetLastErrorMessage())
If $ret = 0 Then Return SetError(_WinAPI_GetLastError(), 0, _WinAPI_GetLastErrorMessage())
Return $ret
EndFunc ;==>CreateProcessAsUser
Func _GetWinLogonPID($iActiveSession)
Local $aWinlogon, $i
$aWinlogon = ProcessList("winlogon.exe")
For $i = 1 To $aWinlogon
If $iActiveSession = _ProcessGetSessionID($aWinlogon[$i]) Then
Return $aWinlogon[$i]
EndIf
Next
Return 0
EndFunc ;==>_GetWinLogonPID
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 Then Return SetError(3, 0, -1)
Return $aRet
EndFunc ;==>_ProcessGetSessionID
Func _GetUserName()
Local $aDLL = DllCall("Advapi32.dll", "int", "GetUserNameW", "wstr", "", "dword*", 255)
If @error Then Return SetError(@error, 0, '')
Return $aDLL
EndFunc ;==>_GetUserName
Func _ProcessListOWNER_WTS($PID = 0)
;~ $temp="Process"
;~ $temp="ProcessId"
;~ $temp="SessionId"
;~ $temp="ProcessOWNER"
Local $tag_WTS_PROCESS_INFO = _
"DWORD SessionId;" & _
"DWORD ProcessId;" & _
"PTR pProcessName;" & _
"PTR pUserSid"
Local $i, $ret, $ret1, $mem, $string
$ret = DllCall("WTSApi32.dll", "int", "WTSEnumerateProcesses", "int", 0, "int", 0, "int", 1, "ptr*", 0, "int*", 0)
Local $array[$ret]
$mem = DllStructCreate($tag_WTS_PROCESS_INFO, $ret)
For $i = 0 To $ret - 1
$mem = DllStructCreate($tag_WTS_PROCESS_INFO, $ret + ($i * DllStructGetSize($mem)))
;if DllStructGetData($mem, "pProcessName") Then
$string = DllStructCreate("char", DllStructGetData($mem, "pProcessName"))
$array[$i] = DllStructGetData($string, 1)
;EndIf
$array[$i] = DllStructGetData($mem, "ProcessId")
$array[$i] = DllStructGetData($mem, "SessionId")
;if DllStructGetData($mem, "pUserSid") Then
$ret1 = _Security__LookupAccountSid(DllStructGetData($mem, "pUserSid"))
If IsArray($ret1) Then $array[$i] = $ret1
;EndIf
Next
DllCall("WTSApi32.dll", "int", "WTSFreeMemory", "int", $ret)
If $PID Then
For $i = 0 To UBound($array, 1) - 1
If $array[$i] = $PID Then
Return $array[$i] & '|' & $array[$i]
EndIf
Next
EndIf
Return $array
EndFunc ;==>_ProcessListOWNER_WTS
由于是脚本中剥离
1.把debug 的相关语句注释掉.
2.几个常量里面没有包含必需的常量,添加几个包含文件即可.
3.可能需要你自己改造一下,几个API不懂的话,可以百度一下它的用途.
4.如果没有system权限,搜索我的另一作品,ExecRunAs
#include <WindowsConstants.au3>
#include <ProcessConstants.au3>
#include-once
#cs ----------------------------------------------------------------------------
必须运行在服务(system)权限下,用于系统服务程序启动第三方程序与用户桌面进行交互
Opt('MustDeclareVars', 1)
RunOnDesktop(@ComSpec, False)
#ce ----------------------------------------------------------------------------
#include <winapi.au3>
#include <array.au3>
#include <security.au3>
#include <StructureConstants.au3>
#include <WinAPISys.au3>
#CS
$NULL = 0
$WTS_CURRENT_SERVER_HANDLE = $NULL
$WTSActive = 0
$WTSShadow = 1
$WTSConnectQuery = 2
$CREATE_UNICODE_ENVIRONMENT = 0x00000400
$DETACHED_PROCESS = 0x00000008
$MAX_PATH = 260
$PROCESS_ALL_ACCESS = 0x001F0FFF
;~ $TOKEN_ALL_ACCESS = 0xf01ff
$ERROR_SUCCESS = 0
Global Const $tagWTS_SESSION_INFO = 'dword SessionId;ptr WinStationName;uint State'
$NORMAL_PRIORITY_CLASS = 0x20
#CE
RunOnDesktop(StringFormat('"%s" /k whoami /all', @ComSpec), False) ;这是测试命令,编译后用system权限运行
Func RunOnDesktop($app_path, $UseSystemRights = False)
;~ Local $bReturn = False
Local $hToken = 0
Local $env = 0
Local $iConsoleID = 0
Local $iProcessPID = 0
Local $hCur = 0
Local $hCurToken = 0
Local $CREATE_NEW_CONSOLE = 0x00000010
Local $CREATE_UNICODE_ENVIRONMENT = 0x00000400
Local $NORMAL_PRIORITY_CLASS = 0x20
;Get active Desktop ID
$iConsoleID = WTSGetActiveConsoleSessionId()
$hToken = WTSQueryUserToken($iConsoleID)
CreateEnvironmentBlock($env, $hToken, False) ;设定所有帐户运行在当前桌面用户环境变量
If $UseSystemRights Then
;~ Local $iWinlogonPID = 0
;~ Local $hWinlogon = 0
;~ Local $PROCESS_ALL_ACCESS = 0x001F0FFF
;~ $iWinlogonPID = _GetWinLogonPID($iConsoleID)
;~ $hWinlogon = _WinAPI_OpenProcess($PROCESS_ALL_ACCESS, False, $iWinlogonPID) ;_ProcessGetHandle($iWinlogonPID)
;~ Local $hWinLogonToken = _Security__OpenProcessToken($hWinlogon, $TOKEN_ALL_ACCESS) ;_OpenProcessToken($hWinlogon)
;~ $hToken = _Security__DuplicateTokenEx($hWinLogonToken, $TOKEN_ALL_ACCESS, $SECURITYIMPERSONATION, $TOKENPRIMARY) ;_DuplicateToken($hToken)
;~ _WinAPI_CloseHandle($hWinLogonToken) ;
;~ _WinAPI_CloseHandle($hWinlogon) ;
$hCur = _WinAPI_GetCurrentProcess()
$hCurToken = _Security__OpenProcessToken($hCur, $TOKEN_ALL_ACCESS)
$hToken = _Security__DuplicateTokenEx($hCurToken, $TOKEN_ALL_ACCESS, $SECURITYIMPERSONATION, $TOKENPRIMARY)
Local $tTOKENSESSIONID = DllStructCreate("DWORD")
DllStructSetData($tTOKENSESSIONID, 1, $iConsoleID)
Local $ret = _Security__SetTokenInformation($hToken, $TOKENSESSIONID, $tTOKENSESSIONID, DllStructGetSize($tTOKENSESSIONID))
;~ If $bDebug Then _DebugPrint('_Security__SetTokenInformation:' & $ret) ;debug
_WinAPI_CloseHandle($hCurToken) ;
EndIf
Local $si = DllStructCreate($tagSTARTUPINFO)
Local $pi = DllStructCreate($tagPROCESS_INFORMATION)
Local $lpProcessAttributes = DllStructCreate($tagSECURITY_ATTRIBUTES)
Local $lpThreadAttributes = DllStructCreate($tagSECURITY_ATTRIBUTES)
DllStructSetData($lpThreadAttributes, "Descriptor", "")
Local $ta_size = DllStructGetSize($lpThreadAttributes)
DllStructSetData($lpThreadAttributes, "Length", $ta_size)
DllStructSetData($lpProcessAttributes, "Descriptor", "")
Local $pa_size = DllStructGetSize($lpProcessAttributes)
DllStructSetData($lpProcessAttributes, "Length", $pa_size)
DllStructSetData($si, "Desktop", "Winsta0//Default")
DllStructSetData($si, "Flags", $STARTF_USESHOWWINDOW)
DllStructSetData($si, "ShowWindow", @SW_SHOW)
Local $pi_size = DllStructGetSize($pi)
Local $si_size = DllStructGetSize($si)
DllStructSetData($pi, "Size", $pi_size)
DllStructSetData($si, "Size", $si_size)
;~ Local $ret = CreateProcessAsUser($hToken, 0, $app_path, DllStructGetPtr($lpProcessAttributes), DllStructGetPtr($lpThreadAttributes), 0, $NORMAL_PRIORITY_CLASS + $CREATE_NEW_CONSOLE, $env, "", DllStructGetPtr($si), DllStructGetPtr($pi))
Local $ret = CreateProcessAsUser($hToken, 0, $app_path, DllStructGetPtr($lpProcessAttributes), DllStructGetPtr($lpThreadAttributes), 0, $NORMAL_PRIORITY_CLASS + $CREATE_NEW_CONSOLE + $CREATE_UNICODE_ENVIRONMENT, $env, 0, DllStructGetPtr($si), DllStructGetPtr($pi))
$iProcessPID = DllStructGetData($pi, "ProcessID")
_WinAPI_CloseHandle(DllStructGetData($pi, "hProcess")) ;
_WinAPI_CloseHandle(DllStructGetData($pi, "hThread")) ;
_WinAPI_CloseHandle($hToken) ;
Return $iProcessPID
EndFunc ;==>RunOnDesktop
Func SetTBCPrivileges()
$dwPID = @AutoItPID
$hToken = 0
$hProcess = 0
$tpDebug = DllStructCreate($tagTOKEN_PRIVILEGES)
$hProcess = _WinAPI_OpenProcess($PROCESS_ALL_ACCESS, False, $dwPID)
If Not $hProcess Then Return False
;If not _WinAPI_OpenProcessToken($hProcess,$TOKEN_ALL_ACCESS,$hToken) Then return False
$hToken = _Security__OpenProcessToken($hProcess, $TOKEN_ALL_ACCESS)
If @error Then Return False
$LUID = _Security__LookupPrivilegeValue("", $SE_DEBUG_NAME)
If $LUID == 0 Then Return False
DllStructSetData($tpDebug, "Count", 1)
DllStructSetData($tpDebug, "LUID", $LUID, 1)
DllStructSetData($tpDebug, "Attributes", $SE_PRIVILEGE_ENABLED, 1)
If _Security__AdjustTokenPrivileges($hToken, False, DllStructGetPtr($tpDebug), DllStructGetSize($tpDebug), 0, 0) = False Then Return False
If _WinAPI_GetLastError() <> 0 Then Return False
_WinAPI_CloseHandle($hToken) ;
_WinAPI_CloseHandle($hProcess) ;
Return True
EndFunc ;==>SetTBCPrivileges
Func CreateEnvironmentBlock(ByRef $lpEnvironment, $hToken, $bInherit)
Local $struct = DllStructCreate("ptr")
Local $ret = DllCall('Userenv.dll', 'bool', 'CreateEnvironmentBlock', _
'ptr', DllStructGetPtr($struct), _
'HANDLE', $hToken, _
'bool', $bInherit)
$lpEnvironment = DllStructGetData($struct, 1)
Return $ret
EndFunc ;==>CreateEnvironmentBlock
Func WTSGetActiveConsoleSessionId()
Local $ret = DllCall('Kernel32.dll', 'dword', 'WTSGetActiveConsoleSessionId')
Return $ret
EndFunc ;==>WTSGetActiveConsoleSessionId
Func WTSQueryUserToken($SessionId)
Local $struct = DllStructCreate("HANDLE")
Local $ret = DllCall('wtsapi32.dll', 'bool', 'WTSQueryUserToken', _
'ULONG', $SessionId, _
'ptr*', DllStructGetPtr($struct))
Return $ret
EndFunc ;==>WTSQueryUserToken
Func ImpersonateLoggedOnUser(ByRef $hToken)
Local $aResult = DllCall("advapi32.dll", "int", "ImpersonateLoggedOnUser", "hwnd", $hToken)
If @error Then Return SetError(@error, @extended, 0)
Return SetError(0, 0, $aResult <> 0)
EndFunc
Func _TSSendConsoleMessage($ButtonSet, $TitleText, $MessageText, $Timeout = 10, $Wait = False)
$TitleText = StringToBinary($TitleText, 1)
Local $pTitle = DllStructCreate('byte Title[' & BinaryLen($TitleText) + 1 & ']')
DllStructSetData($pTitle, 'Title', $TitleText)
$MessageText = StringToBinary($MessageText, 1)
Local $pMessage = DllStructCreate('byte Message[' & BinaryLen($MessageText) + 1 & ']')
DllStructSetData($pMessage, 'Message', $MessageText)
Local $pResponse = DllStructCreate("DWORD Response")
Local $SessionId = WTSGetActiveConsoleSessionId()
DllStructSetData($pTitle, "Title", $TitleText)
DllStructSetData($pMessage, "Message", $MessageText)
Local $Res = DllCall("Wtsapi32.dll", "BOOL", "WTSSendMessageA", "HANDLE", "WTS_CURRENT_SERVER_HANDLE", "DWORD", $SessionId, "ptr", DllStructGetPtr($pTitle), "DWORD", DllStructGetSize($pTitle), "ptr", DllStructGetPtr($pMessage), "DWORD", DllStructGetSize($pMessage), "DWORD", $ButtonSet, "DWORD", $Timeout, "DWORD", DllStructGetPtr($pResponse), "BOOL", $Wait)
Return $Res
EndFunc ;==>_TSSendConsoleMessage
Func CreateProcessAsUser($hToken, $lpApplicationName, $lpCommandline, $lpProcessAttributes, $lpThreadAttributes, $bInheritHandles, $dwCreationFlags, $lpEnvironment, $lpCurrentDirectory, $lpStartupInfo, $lpProcessInformation)
Local $ret = DllCall("advapi32.dll", "bool", "CreateProcessAsUserW", _ ; W is better
"handle", $hToken, _
"ptr", $lpApplicationName, _ ;$lpApplicationName, _
"wstr", $lpCommandline, _ ; wstr for CreateProcessAsUserW
"ptr", $lpProcessAttributes, _
"ptr", $lpThreadAttributes, _
"bool", $bInheritHandles, _ ;$bInheritHandles, _
"dword", $dwCreationFlags, _
"ptr", $lpEnvironment, _
"ptr", $lpCurrentDirectory, _
"ptr", $lpStartupInfo, _
"ptr", $lpProcessInformation)
;If $ret = 0 Then _MsgBox(16, "proc e "&@error&" "&$hToken, _WinAPI_GetLastErrorMessage())
If $ret = 0 Then Return SetError(_WinAPI_GetLastError(), 0, _WinAPI_GetLastErrorMessage())
Return $ret
EndFunc ;==>CreateProcessAsUser
Func _GetWinLogonPID($iActiveSession)
Local $aWinlogon, $i
$aWinlogon = ProcessList("winlogon.exe")
For $i = 1 To $aWinlogon
If $iActiveSession = _ProcessGetSessionID($aWinlogon[$i]) Then
Return $aWinlogon[$i]
EndIf
Next
Return 0
EndFunc ;==>_GetWinLogonPID
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 Then Return SetError(3, 0, -1)
Return $aRet
EndFunc ;==>_ProcessGetSessionID
Func _GetUserName()
Local $aDLL = DllCall("Advapi32.dll", "int", "GetUserNameW", "wstr", "", "dword*", 255)
If @error Then Return SetError(@error, 0, '')
Return $aDLL
EndFunc ;==>_GetUserName
Func _ProcessListOWNER_WTS($PID = 0)
;~ $temp="Process"
;~ $temp="ProcessId"
;~ $temp="SessionId"
;~ $temp="ProcessOWNER"
Local $tag_WTS_PROCESS_INFO = _
"DWORD SessionId;" & _
"DWORD ProcessId;" & _
"PTR pProcessName;" & _
"PTR pUserSid"
Local $i, $ret, $ret1, $mem, $string
$ret = DllCall("WTSApi32.dll", "int", "WTSEnumerateProcesses", "int", 0, "int", 0, "int", 1, "ptr*", 0, "int*", 0)
Local $array[$ret]
$mem = DllStructCreate($tag_WTS_PROCESS_INFO, $ret)
For $i = 0 To $ret - 1
$mem = DllStructCreate($tag_WTS_PROCESS_INFO, $ret + ($i * DllStructGetSize($mem)))
;if DllStructGetData($mem, "pProcessName") Then
$string = DllStructCreate("char", DllStructGetData($mem, "pProcessName"))
$array[$i] = DllStructGetData($string, 1)
;EndIf
$array[$i] = DllStructGetData($mem, "ProcessId")
$array[$i] = DllStructGetData($mem, "SessionId")
;if DllStructGetData($mem, "pUserSid") Then
$ret1 = _Security__LookupAccountSid(DllStructGetData($mem, "pUserSid"))
If IsArray($ret1) Then $array[$i] = $ret1
;EndIf
Next
DllCall("WTSApi32.dll", "int", "WTSFreeMemory", "int", $ret)
If $PID Then
For $i = 0 To UBound($array, 1) - 1
If $array[$i] = $PID Then
Return $array[$i] & '|' & $array[$i]
EndIf
Next
EndIf
Return $array
EndFunc ;==>_ProcessListOWNER_WTS
tubaba 发表于 2024-10-15 11:24
由于是脚本中剥离
非常感谢您的快速回应。目前,我遇到的问题是在将程序编译为32位之后,运行时遇到困难。具体来说,我未能在服务列表中找到与该程序相关的服务进程,即使在电脑重启之后也是如此,程序并未自启动或者执行我指定的任务。当我尝试双击运行该程序时,它以我当前的用户身份直接打开了指定的应用,而非作为服务进程运行。
tubaba 发表于 2024-10-15 11:24
由于是脚本中剥离
在使用了您提供的代码来调用之前以服务形式运行的指定exe之后,权限继承的问题依然存在。 本帖最后由 tubaba 于 2024-10-15 14:59 编辑
以上演示 第一次execrunas以管理员身份启动, 然后用system权限启动自身,可以看到标题栏的用户名是system,然后用它启动test3.exe,可以看到,此时cmd.exe是运行在标准用户权限下.(test3.exe即由楼上的代码编译)
我不知道你做成服务的方式,有两种方法
一种是用第三方程序,比如使用Instsrv.exe和Srvany.exe 安装windows服务
另一种,自己用au3编写服务,论坛也有介绍.
你应该明白的是,服务是运行在system帐户下,环境变量与登录用户的环境变量完全不一样,比如@temp这种宏,指向的目录是不一样的.
你可以先测试你的exe,在system帐户下运行时,其功能是否可以达到你的预期.
最后一点,服务程序是运行在session0下,而桌面用户在session1,2,3......以上,这也就意味着,你服务程序里如果有msgbox等弹出的GUI,在桌面用户下是看不到的,也就是通常所说的无法交互.我提供的方法中,是创建当前sessionID下的进程,所以可以交互
页:
[1]