另一个帐户上有SeDebugPrivilege和OpenProcess

时间:2015-12-29 13:03:04

标签: delphi winapi

我正在尝试打开另一个用户帐户上运行的进程,当我以管理员身份运行我的应用程序时(右键单击>以管理员身份运行),我成功获取它,但我需要该应用程序自行提升权限,这就是我到目前为止:

procedure ChangePrivilege;
var
  NewState: TTokenPrivileges;
  luid: TLargeInteger;
  hToken: THandle;
  ReturnLength: DWord;
begin
  if OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, hToken) then
  begin
   if LookupPrivilegeValue(nil, PChar('SeDebugPrivilege'), luid) then
   begin
    NewState.PrivilegeCount:= 1;
    NewState.Privileges[0].Luid := luid;
    NewState.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
    if AdjustTokenPrivileges(hToken, False, NewState, 0, nil, ReturnLength) then
      WriteLn('Privileged');
   end;
    CloseHandle(hToken);
  end;
end;

这个函数执行得很好,我得到了“Privileged”输出,但在我的OpenProcess上,我没有看到其他帐户上运行的进程名称:

procedure ProcEnum;
var
  Snapshot, ProcessPID: THandle;
  pe: TProcessEntry32;
begin
  Snapshot := CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);
  try
    pe.dwSize := SizeOf(pe);
    if Process32First(Snapshot, pe) then
      while Process32Next(Snapshot, pe) do
      begin
        try
          ProcessPID:= OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_OPERATION or
                                        PROCESS_VM_READ, false, pe.th32ProcessID);

          if (ProcessPID <> 0) then
            WriteLn(pe.szExeFile);
        finally
          ProcessPID:= 0;
          CloseHandle(ProcessPID);
        end;
      end;
  finally
    CloseHandle(Snapshot);
  end;
end;

有什么东西我不见了吗? 我刚刚在Windows 2008 Server上尝试过相同的代码,但它确实有效。但是在使用Windows 10时,问题仍然存在。

2 个答案:

答案 0 :(得分:1)

1。 试着看看Enabling and Disabling Privileges in C++。 从此,您似乎必须更改ChangePrivilege以指定TTokenPrivilegesAdjustTokenPrivileges的大小。现在是0。为了解决这类问题,我认为这就是为什么他们建议仔细检查GetLastError <> ERROR_NOT_ALL_ASSIGNED。 希望这些修改能有所帮助:

procedure ChangePrivilegeModified;
var
  NewState: TTokenPrivileges;
  luid: TLargeInteger;
  hToken: THandle;
  ReturnLength: DWord;
begin
  if OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, hToken) then
  begin
   if LookupPrivilegeValue(nil, PChar('SeDebugPrivilege'), luid) then
   begin
    NewState.PrivilegeCount:= 1;
    NewState.Privileges[0].Luid := luid;
    NewState.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
    if AdjustTokenPrivileges(hToken, False, NewState, SizeOf(TTokenPrivileges), nil, ReturnLength) then
    begin
      if GetLastError = ERROR_NOT_ALL_ASSIGNED then
        WriteLn('Change privilege failed: Not all assigned')
      else
        WriteLn('Privileged');
    end;
   end;
    CloseHandle(hToken);
  end;
end;

2。 如果OpenProcess仍然失败,那么从文档OpenProcess function开始,存在访问权限注意事项,这些注意事项在Process Security and Access Rights中详细说明。要对OpenProcess进行问题排查,请尝试缩小PROCESS_QUERY_LIMITED_INFORMATION = $1000的权限范围:

ProcessPID:= OpenProcess( PROCESS_QUERY_LIMITED_INFORMATION, false, pe.th32ProcessID );

这会成功吗?

答案 1 :(得分:0)

Process32First返回时,它包含有关快照中第一个进程的信息。您可以通过调用Process32Next来忽略该过程。也许第一个过程,即您未能处理的过程,就是您正在寻找的过程。

您在代码中还有其他问题:

  1. 您不能以一致的方式检查错误的返回值。
  2. 您将进程句柄错误地命名为PID。
  3. 您泄漏了进程句柄,因为您没有关闭它们。而是反复拨打CloseHandle(0)
  4. 我可能没有发现更多错误。