我有一个作为本地系统运行的服务,它将在每个用户登录到计算机时创建一个具有提升权限的进程。为了提升此新进程的权限,该服务使用来自winlogon的令牌(因为它以SYSTEM身份运行)使用OpenProcessToken。此服务根据explorer.exe进程检索所有登录的用户。 DuplicateTokenEx用于生成具有提升权限的主令牌,该权限传递给CreateProcessAsUser。这一切都很好,但是如何让创建的进程在任务管理器中显示为登录用户的用户名?它当前在“用户名”列中显示SYSTEM。模仿并不能实现这一目标。我想我可能必须在创建进程之前修改重复令牌的所有者SID,但我不确定如何执行此操作。任何帮助是极大的赞赏。 VB.NET或C#。
示例代码:
Public Shared Sub MonitorUserProcesses(ByVal CmdLine As String, ByVal args As String())
Try
Dim targetProcName As String = IO.Path.GetFileNameWithoutExtension(CmdLine)
Dim UIDs As List(Of WindowsIdentity) = Nothing
UIDs = GetLoggedInUsers()
If UIDs IsNot Nothing Then
For Each user As WindowsIdentity In UIDs
Try
Dim Processes As Process()
' Get all target process IDs
Processes = Process.GetProcessesByName(targetProcName)
Dim hToken As SafeTokenHandle = Nothing
Dim ProcessPrinciple As WindowsIdentity
Dim UserProcessExists As Boolean = False
For Each p As Process In Processes
' Get the user token handle
If OpenProcessToken(p.Handle, TokenAccessLevels.AllAccess, hToken) = False Then
' Write debug
WriteEvent("Error: Windows API OpenProcessToken function returns an error." + Environment.NewLine +
"Windows API error code: " + Marshal.GetLastWin32Error.ToString, EventLogEntryType.Error)
' Iterate the next process
Continue For
End If
' Get the windows identity
ProcessPrinciple = New WindowsIdentity(hToken.DangerousGetHandle)
hToken.Close()
If ProcessPrinciple.Name = user.Name Then
UserProcessExists = True
Exit For
End If
Next
If UserProcessExists = False AndAlso Not user.IsSystem Then
'start the process for this user
WriteEvent("Attempting to create process for user: " & user.Name, EventLogEntryType.Information)
LaunchProcess(CmdLine, args, user)
End If
Catch ex As Exception
WriteEvent(ex.ToString, EventLogEntryType.Error)
End Try
Next
End If
Catch ex As Exception
WriteEvent(ex.ToString, EventLogEntryType.Error)
End Try
End Sub
Public Shared Function GetLoggedInUsers() As List(Of WindowsIdentity)
Dim ret As New List(Of WindowsIdentity)
Try
Dim Processes As Process()
Dim hToken As SafeTokenHandle = Nothing
Dim principle As WindowsIdentity
' Get all explorer.exe IDs
Processes = Process.GetProcessesByName("explorer")
' Verify processes were found
If Processes.Length = 0 Then
' Write debug
WriteEvent("Warning: No explorer.exe processes found.", EventLogEntryType.Warning)
' Return
Return ret
End If
' Iterate each explorer.exe process
For Each hProcess As Process In Processes
' Get the user token handle
If OpenProcessToken(hProcess.Handle, TokenAccessLevels.AllAccess, hToken) = False Then
' Write debug
WriteEvent("Error: Windows API OpenProcessToken function returns an error." + Environment.NewLine +
"Windows API error code: " + Marshal.GetLastWin32Error.ToString, EventLogEntryType.Error)
' Iterate the next process
Continue For
End If
' Get the windows identity
principle = New WindowsIdentity(hToken.DangerousGetHandle)
If Not principle.IsSystem Then
ret.Add(principle)
End If
hToken.Close()
Next
Catch ex As Exception
WriteEvent(ex.ToString, EventLogEntryType.Error)
End Try
Return ret
End Function
Private Shared Function GetSystemToken() As SafeTokenHandle
Dim ret As SafeTokenHandle = Nothing
Try
'get our process that we want to duplicate
Dim pSys() As Process = Process.GetProcessesByName("winlogon")
If pSys.Length <= 0 Then
'can get elevated privileges
WriteEvent("Warning: No winlogon.exe processes found. Unable to elevate privileges.", EventLogEntryType.Warning)
End If
' Get the System token handle
If OpenProcessToken(pSys(0).Handle, TokenAccessLevels.AllAccess, ret) = False Then
' Write debug
WriteEvent("Error: Windows API OpenProcessToken function returns an error." + Environment.NewLine +
"Windows API error code: " + Marshal.GetLastWin32Error.ToString, EventLogEntryType.Error)
ret = Nothing
End If
Catch ex As Exception
WriteEvent(ex.ToString, EventLogEntryType.Error)
End Try
Return ret
End Function
Private Shared Function GetUserToken(winID As WindowsIdentity) As SafeTokenHandle
Dim ret As SafeTokenHandle = Nothing
Dim ExplorerProcesses As Process()
Dim principal As WindowsIdentity = Nothing
Try
' Get all explorer.exe IDs
ExplorerProcesses = Process.GetProcessesByName("explorer")
' Verify explorers were found
If ExplorerProcesses.Length = 0 Then
' Write debug
WriteEvent("Warning: No explorer.exe processes found.", EventLogEntryType.Warning)
' Return
Return ret
End If
'Iterate each explorer.exe process
For Each hProcess As Process In ExplorerProcesses
Dim hToken As SafeTokenHandle = Nothing
' Get the user token handle
If OpenProcessToken(hProcess.Handle, TokenAccessLevels.AllAccess, hToken) = False Then
' Write debug
WriteEvent("Error: Windows API OpenProcessToken function returns an error." + Environment.NewLine +
"Windows API error code: " + Marshal.GetLastWin32Error.ToString, EventLogEntryType.Error)
' Iterate the next process
Continue For
End If
' Get the windows identity
principal = New WindowsIdentity(hToken.DangerousGetHandle)
If principal.User = winID.User Then
'this is our user, get their token
ret = hToken
Exit For
End If
Next
Catch ex As Exception
WriteEvent(ex.ToString, EventLogEntryType.Error)
End Try
Return ret
End Function
Public Shared Sub LaunchProcess(ByVal CmdLine As String, ByVal args As String(), userID As WindowsIdentity)
' Local variables
Dim Arguments As String = ""
Dim principle As WindowsIdentity
Dim phNewToken As SafeTokenHandle = Nothing
Dim si As STARTUPINFO
Dim pi As PROCESS_INFORMATION
' Process arguments
For Each arg As String In args
' Build argument string
Arguments += " " + arg
Next
' Increase Privileges
If IncreasePrivileges() = False Then
' Write debug
WriteEvent("Warning: Failed to increase current process privileges.", EventLogEntryType.Warning)
End If
Dim userToken As SafeTokenHandle = Nothing
userToken = GetUserToken(userID)
If userToken Is Nothing Then
'user is not logged in
Exit Sub
End If
Dim dupToken As SafeTokenHandle = userToken
Dim sysToken As SafeTokenHandle = Nothing
sysToken = GetSystemToken()
If sysToken IsNot Nothing Then
'duplicate the sysToken privileges
dupToken = sysToken
End If
If Not DuplicateTokenEx(dupToken.DangerousGetHandle,
TokenAccessLevels.AllAccess,
Nothing,
SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation,
TOKEN_TYPE.TokenPrimary,
phNewToken) Then
' Write debug
WriteEvent("Error: Windows API DuplicateTokenEx function returns an error." + Environment.NewLine +
"Windows API error code: " + Marshal.GetLastWin32Error.ToString, EventLogEntryType.Error)
End If
Try
sysToken.Close()
Catch ex As Exception
End Try
Try
dupToken.Close()
Catch ex As Exception
End Try
Dim env As IntPtr = IntPtr.Zero
Try
'load user environment
If Not CreateEnvironmentBlock(env, userToken.DangerousGetHandle, False) Then
' Write debug
WriteEvent("Error: Windows API CreateEnvironmentBlock function returns an error." + Environment.NewLine +
"Windows API error code: " + Marshal.GetLastWin32Error.ToString, EventLogEntryType.Error)
End If
Catch ex As Exception
End Try
Try
Dim uPrincipal As New WindowsIdentity(phNewToken.DangerousGetHandle)
WindowsIdentity.Impersonate(userToken.DangerousGetHandle)
Catch ex As Exception
WriteEvent(ex.ToString, EventLogEntryType.Error)
End Try
Try
userToken.Close()
Catch ex As Exception
End Try
'HERE IS WHERE I THINK I NEED TO MAKE MY MOD
'ChangeSID(userID, phNewToken)
' Initialize process and startup info
pi = New PROCESS_INFORMATION
si = New STARTUPINFO
si.cb = Marshal.SizeOf(si)
si.lpDesktop = Nothing
' Launch the process in the client's logon session
If Not CreateProcessAsUser(phNewToken,
Nothing,
CmdLine + Arguments,
Nothing,
Nothing,
False,
CreateProcessFlags.CREATE_UNICODE_ENVIRONMENT,
env,
Nothing,
si,
pi) Then
' Write debug
WriteEvent("Error: Windows API CreateProcessAsUser function returns an error." + Environment.NewLine +
"Windows API error code: " + Marshal.GetLastWin32Error.ToString, EventLogEntryType.Error)
Else
' Write debug
WriteEvent("Created new user process: " + Environment.NewLine +
"User: " + userID.Name + Environment.NewLine +
"Process: " + CmdLine + Arguments + Environment.NewLine +
"PID: " + pi.dwProcessId.ToString, EventLogEntryType.Information)
End If
' Free resources
phNewToken.Close()
phNewToken = Nothing
principle = Nothing
pi = Nothing
si = Nothing
If env <> IntPtr.Zero Then
DestroyEnvironmentBlock(env)
End If
'Next
End Sub
Public Shared Function IncreasePrivileges() As Boolean
' Local variables
Dim hToken As SafeTokenHandle = Nothing
Dim luid As LUID
Dim NewState As TOKEN_PRIVILEGES
NewState.PrivilegeCount = 1
ReDim NewState.Privileges(0)
' Get current process token
If OpenProcessToken(Diagnostics.Process.GetCurrentProcess.Handle, TokenAccessLevels.AllAccess, hToken) = False Then
' Write debug
WriteEvent("Error: Windows API OpenProcessToken function returns an error." + Environment.NewLine +
"Windows API error code: " + Marshal.GetLastWin32Error.ToString, EventLogEntryType.Error)
' Return
Return False
End If
' Lookup SeIncreaseQuotaPrivilege
If Not LookupPrivilegeValue(Nothing, SE_INCREASE_QUOTA_NAME, luid) Then
' Write debug
WriteEvent("Error: Windows API LookupPrivilegeValue function returns an error." + Environment.NewLine +
"Windows API error code: " + Marshal.GetLastWin32Error.ToString, EventLogEntryType.Error)
' Return
Return False
End If
' Enable SeIncreaseQuotaPrivilege
NewState.Privileges(0).Luid = luid
NewState.Privileges(0).Attributes = SE_PRIVILEGE_ENABLED
' Adjust the token privileges
If Not AdjustTokenPrivileges(hToken, False, NewState, Marshal.SizeOf(NewState), Nothing, Nothing) Then
' Write debug
WriteEvent("Error: Windows API AdjustTokenPrivileges function returns an error." + Environment.NewLine +
"Windows API error code: " + Marshal.GetLastWin32Error.ToString, EventLogEntryType.Error)
' Return
Return False
End If
' Lookup SeAssignPrimaryTokenPrivilege
If Not LookupPrivilegeValue(Nothing, SE_ASSIGNPRIMARYTOKEN_NAME, luid) Then
' Write debug
WriteEvent("Error: Windows API LookupPrivilegeValue function returns an error." + Environment.NewLine +
"Windows API error code: " + Marshal.GetLastWin32Error.ToString, EventLogEntryType.Error)
' Return
Return False
End If
' Enable SeAssignPrimaryTokenPrivilege
NewState.Privileges(0).Luid = luid
NewState.Privileges(0).Attributes = SE_PRIVILEGE_ENABLED
' Adjust the token privileges
If Not AdjustTokenPrivileges(hToken, False, NewState, Marshal.SizeOf(NewState), Nothing, Nothing) Then
' Write debug
WriteEvent("Error: Windows API AdjustTokenPrivileges function returns an error." + Environment.NewLine +
"Windows API error code: " + Marshal.GetLastWin32Error.ToString, EventLogEntryType.Error)
' Return
Return False
End If
' Lookup SeTcbPrivilege
If Not LookupPrivilegeValue(Nothing, SE_TCB_NAME, luid) Then
' Write debug
WriteEvent("Error: Windows API LookupPrivilegeValue function returns an error." + Environment.NewLine +
"Windows API error code: " + Marshal.GetLastWin32Error.ToString, EventLogEntryType.Error)
' Return
Return False
End If
' Enable SeTcbPrivilege
NewState.Privileges(0).Luid = luid
NewState.Privileges(0).Attributes = SE_PRIVILEGE_ENABLED
' Adjust the token privileges
If Not AdjustTokenPrivileges(hToken, False, NewState, Marshal.SizeOf(NewState), Nothing, Nothing) Then
' Write debug
WriteEvent("Error: Windows API AdjustTokenPrivileges function returns an error." + Environment.NewLine +
"Windows API error code: " + Marshal.GetLastWin32Error.ToString, EventLogEntryType.Error)
' Return
Return False
End If
' Return
Return True
End Function