如何使用提升的权限创建一个显示用户名而不是SYSTEM的进程

时间:2014-03-13 20:25:55

标签: c# vb.net

我有一个作为本地系统运行的服务,它将在每个用户登录到计算机时创建一个具有提升权限的进程。为了提升此新进程的权限,该服务使用来自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

0 个答案:

没有答案