2015-12-04 2 views
1

Мне нужно уметь убивать процесс, выполняемый под другим пользователем. Вот пользователь scenerio 1 (администратор или стандартный пользователь) переключает пользователей, но оставляет приложение A запущенным. Пользователь 2 (стандартный пользователь) регистрируется на том же компьютере, когда регистрируется в приложении A. Мне нужно убить процесс, на котором выполняется приложение A под пользователем 1. У меня есть имя пользователя и пароль администратора по умолчанию в db. То, что я сделал, убьет процесс, если они оба являются администраторами, но не если пользователь 2 является стандартным пользователем. Как убить процессы как другого пользователя? вот что я до сих пор.Убейте процесс, принадлежащий другому пользователю в VB6

Const MAX_PATH& = 260 


Private Declare Function TerminateProcess Lib "kernel32" (ByVal ApphProcess As Long, ByVal uExitCode As Long) As Long 
Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal blnheritHandle As Long, ByVal dwAppProcessId As Long) As Long 
Private Declare Function ProcessFirst Lib "kernel32" Alias "Process32First" (ByVal hSnapshot As Long, uProcess As PROCESSENTRY32) As Long 
Private Declare Function ProcessNext Lib "kernel32" Alias "Process32Next" (ByVal hSnapshot As Long, uProcess As PROCESSENTRY32) As Long 
Private Declare Function CreateToolhelpSnapshot Lib "kernel32" Alias "CreateToolhelp32Snapshot" (ByVal lFlags As Long, lProcessID As Long) As Long 
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long 

Private Type LUID 
    lowpart As Long 
    highpart As Long 
End Type 

Private Type TOKEN_PRIVILEGES 
    PrivilegeCount As Long 
    LuidUDT As LUID 
    Attributes As Long 
End Type 

Const TOKEN_ADJUST_PRIVILEGES = &H20 
Const TOKEN_QUERY = &H8 
Const SE_PRIVILEGE_ENABLED = &H2 
Const PROCESS_ALL_ACCESS = &H1F0FFF 

Private Declare Function GetVersion Lib "kernel32"() As Long 
Private Declare Function GetCurrentProcess Lib "kernel32"() As Long 
Private Declare Function OpenProcessToken Lib "advapi32" (ByVal ProcessHandle As Long, ByVal DesiredAccess As Long, TokenHandle As Long) As Long 
Private Declare Function LookupPrivilegeValue Lib "advapi32" Alias "LookupPrivilegeValueA" (ByVal lpSystemName As String, ByVal lpName As String, lpLuid As LUID) As Long 
Private Declare Function AdjustTokenPrivileges Lib "advapi32" (ByVal TokenHandle As Long, ByVal DisableAllPrivileges As Long, NewState As TOKEN_PRIVILEGES, ByVal BufferLength As Long, PreviousState As Any, ReturnLength As Any) As Long 

Private Type PROCESSENTRY32 
    dwSize As Long 
    cntUsage As Long 
    th32ProcessID As Long 
    th32DefaultHeapID As Long 
    th32ModuleID As Long 
    cntThreads As Long 
    th32ParentProcessID As Long 
    pcPriClassBase As Long 
    dwFlags As Long 
    szexeFile As String * MAX_PATH 
End Type 

    Public Function KillApp(myName As String) As Boolean 
    On Error GoTo HandleError 

    Const TH32CS_SNAPPROCESS As Long = 2& 
    Const PROCESS_ALL_ACCESS = 0 
    Dim uProcess As PROCESSENTRY32 
    Dim rProcessFound As Long 
    Dim hSnapshot As Long 
    Dim szExename As String 
    Dim ExitCode As Long 
    Dim myProcess As Long 
    Dim AppKill As Boolean 
    Dim appCount As Integer 
    Dim i As Integer 
    Dim processKilled As Boolean 
    Dim WMI, QRY, ListOfProcesses, Item, ProcessUserName, colProperties 

    appCount = 0 

    uProcess.dwSize = Len(uProcess) 
    hSnapshot = CreateToolhelpSnapshot(TH32CS_SNAPPROCESS, 0&) 
    rProcessFound = ProcessFirst(hSnapshot, uProcess) 

    Do While rProcessFound 
     i = InStr(1, uProcess.szexeFile, Chr(0)) 
     szExename = LCase$(Left$(uProcess.szexeFile, i - 1)) 
     If Right$(szExename, Len(myName)) = LCase$(myName) Then 
      'set the queryfor the process object for this process 
      QRY = "SELECT * FROM Win32_Process WHERE Name = '" + myName + "'" 

      'Set up the Windows Management Instrumentation object 
      Set WMI = GetObject("winmgmts:{impersonationLevel=impersonate}\\.\root\cimv2") 

      Set ListOfProcesses = WMI.ExecQuery(QRY) 

      For Each Item In ListOfProcesses 
      'Get the user name 
      colProperties = Item.GetOwner(ProcessUserName) 
      'Only kill the processes if its not your user name 
       If Not ProcessUserName = Environ("USERNAME") Then 
        KillApp = True 
        appCount = appCount + 1 
        myProcess = OpenProcess(PROCESS_ALL_ACCESS, False, uProcess.th32ProcessID) 
        processKilled = KillProcess(uProcess.th32ProcessID, 0) 
       End If 
      Next 
     End If 
    rProcessFound = ProcessNext(hSnapshot, uProcess) 
    Loop 

    Call CloseHandle(hSnapshot) 

    Exit Function 
    HandleError: 
     bErrorHandler.Error_Handler_Debug Err.Number, "We have encountered an error while starting CAD. This is usually because there is another user logged on to this machine with CAD or Dispatch running and we could not close out there session. Please log off all other users and try to start CAD again. The following is an error message generated by the system: " + Err.Description, "frmCADMainMDI.KillApp" 
    End Function 

    Function KillProcess(ByVal hProcessID As Long, Optional ByVal ExitCode As Long) As Boolean 
    On Error GoTo HandleError 
    Dim htoken As Long 
    Dim hProcess As Long 
    Dim tp As TOKEN_PRIVILEGES 


    If GetVersion() >= 0 Then 

     If OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES Or TOKEN_QUERY, htoken) = 0 Then 
      GoTo CleanUp 
     End If 

     If LookupPrivilegeValue("", "SeDebugPrivilege", tp.LuidUDT) = 0 Then 
      GoTo CleanUp 
     End If 

     tp.PrivilegeCount = 1 
     tp.Attributes = SE_PRIVILEGE_ENABLED 

     If AdjustTokenPrivileges(htoken, False, tp, 0, ByVal 0&, ByVal 0&) = 0 Then 
      GoTo CleanUp 
     End If 
    End If 

    hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, hProcessID) 
    If hProcess Then 
     KillProcess = (TerminateProcess(hProcess, ExitCode) <> 0) 
     ' close the process handle 
     CloseHandle hProcess 
    End If 

    If GetVersion() >= 0 Then 
     ' under NT restore original privileges 
     tp.Attributes = 0 
     AdjustTokenPrivileges htoken, False, tp, 0, ByVal 0&, ByVal 0& 
    End If 

    CleanUp: 
    If htoken Then 
     CloseHandle htoken 
    End If 

    Exit Function 
    HandleError: 
     bErrorHandler.Error_Handler_Debug Err.Number, Err.Description, "frmCADMainMDI.KillProcess" 
    End Function 

KillApp вызывается во время события загрузки приложения с именемofprogram.exe в качестве параметра. Я стараюсь держаться подальше от вызовов оболочки, потому что есть некоторые случаи. Cmd строка и оболочка отключены в среде конечного пользователя.

+0

Возможно, я ошибаюсь, но я не думаю, что есть какие-либо простой способ сделать это. В конфигурации по умолчанию вы можете использовать CreateProcessWithLogonW, если включена встроенная учетная запись администратора, и у вас есть пароль, но это не будет работать для какой-либо другой учетной записи администратора. Во всяком случае, это не разумная вещь, потому что пользователь, не являющийся администратором Б, может украсть пароль администратора по умолчанию. Вместо этого вы можете использовать приложение A для прослушивания на TCP-порту и убить себя, если оно получает соединение, или вы можете установить системную службу для выполнения работы, требующей привилегии администратора. –

+0

Итак, вместо запуска приложения A в качестве пользователя запустите его как администратор по умолчанию, а затем я могу убить это приложение в качестве администратора по умолчанию. Как я могу указать, какой пользователь использовать, чтобы убить приложение? @HarryJohnston –

+0

Предполагая, что пользователям разрешено знать пароль администратора по умолчанию, и что не имеет значения, работает ли A в другом контексте, чем пользователь, который его использует (например, ему не нужно записывать файлы в папка с документами пользователя) - да, этот подход может работать. Гениальный! Вы можете запустить A в качестве администратора по умолчанию, используя CreateProcessWithLogonW. Обратите внимание, что A не будет запускаться с правами администратора, т. Е., он получит ограниченный токен, а не повышенный. Чтобы убить старый процесс в качестве администратора по умолчанию, просто запустите KillProcess из A или из любого другого процесса, запущенного в качестве администратора по умолчанию. –

ответ

1

Как убить процесс как другого пользователя?

Чтобы ответить на эту часть вопроса, так как это кажется тем аспектом, который вас больше всего интересует, я считаю, что (если ваша программа не работает с повышенной привилегией) единственный надежный способ убить цель процесс X, используя контекст конкретной учетной записи Y (для которой у вас есть учетные данные), заключается в запуске дочернего процесса, выполняющегося в контексте Y, чтобы убить X от вашего имени.

Вы можете сделать это, используя функцию CreateProcessWithLogonW.

Одно предупреждение: если Y является администратором, а UAC включен, дочерний процесс будет работать с ограниченным токеном, а не с повышенным токеном. Таким образом, вы не можете использовать этот подход для использования административных учетных данных. Однако, если разрешения на X предоставляют доступ непосредственно к Y, а не только к группе «Администраторы», он все равно должен работать.

(В вашем конкретном сценарии это может означать, что вам необходимо явно установить или изменить разрешения для процесса как часть запуска приложения A. Если вы используете CreateProcess, вы можете назначить явные разрешения для нового процесса, используя lpProcessAttributes параметр.)


Примечание, в частности, что вы не можете использовать олицетворение, если у вас нет SeImpersonatePrivilege, который по умолчанию предоставляется только для администраторов и системных служб, так что такой подход вряд ли будет успешным. (В документации указано, что вы можете выдавать маркер без SeImpersonatePrivilege, если вы сами создали токен, используя явные учетные данные, но на практике это не кажется истинным.)

+0

ok Я проверю это и вернусь к вам за вашу помощь. –

+0

Это действительно работает. Но не для моей ситуации, но она полностью отвечает на вопрос. –