SAMPro
SAMPro

Reputation: 1099

OpenProcess() returns ERROR_ACCESS_DENIED if program isn't elevated

I have successfully wrote a script to get memory consumption (TProcessMemoryCounters) of any process. However I need to run my program elevated (run as admin) in order to get these information for some system or elevated process (otherwise OpenProcess returns ERROR_ACCESS_DENIED). Programs like Process Explorer didn't need elevated mode.

My script to get memory information of a process:

  function GetProcessMemory(ProcID: Cardinal): Cardinal;
  var
    MemCounters: TProcessMemoryCounters;
    HProc: THandle;
  begin
    Result:= 0;
    HProc:= OpenProcess(
      PROCESS_QUERY_LIMITED_INFORMATION //or SYNCHRONIZE
      , False, ProcID);
    //HProc: 5 = ERROR_ACCESS_DENIED

    if GetProcessMemoryInfo(HProc, @MemCounters, SizeOf(TProcessMemoryCounters)) then
      Result :=
        MemCounters.WorkingSetSize;
  end;

With the following script I got memory information for all process, but still my program needs to be elevated:

  function EnableDebugPriv(): Boolean;
  const
    SE_DEBUG_NAME = 'SeDebugPrivilege';
  var
    HToken: NativeUInt;
    LUID: Int64;
    Tkp: TTokenPrivileges;
    AA: Cardinal;
  begin
    OpenProcessToken(GetCurrentProcess,
      TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY,
      HToken
    );

    LookupPrivilegeValue(nil, SE_DEBUG_NAME, LUID);

    Tkp.PrivilegeCount:= 1;
    Tkp.Privileges[0].Luid:= LUID;
    Tkp.Privileges[0].Attributes:= SE_PRIVILEGE_ENABLED;

    AdjustTokenPrivileges(HToken, False, Tkp, SizeOf(Tkp), nil, AA);

    CloseHandle(HToken);
  end;

Q: How to make my script get memory information of all process (include systems) without elevated mode?

Upvotes: 0

Views: 864

Answers (1)

Remy Lebeau
Remy Lebeau

Reputation: 595349

To use GetProcessMemoryInfo(), you must specify the PROCESS_VM_READ access right as well, as stated by the documentation:

Process

A handle to the process. The handle must have the PROCESS_QUERY_INFORMATION or PROCESS_QUERY_LIMITED_INFORMATION access right and the PROCESS_VM_READ access right. For more information, see Process Security and Access Rights.

Windows Server 2003 and Windows XP:  The handle must have the PROCESS_QUERY_INFORMATION and PROCESS_VM_READ access rights.

You are also leaking the handle if it were able to be opened successfully.

Try this instead:

function GetProcessMemory(ProcID: DWORD): DWORD;
var
  MemCounters: TProcessMemoryCounters;
  HProc: THandle;
begin
  Result := 0;
  HProc := OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION or PROCESS_VM_READ, False, ProcID);
  if HProc <> 0 then
  begin
    if GetProcessMemoryInfo(HProc, @MemCounters, SizeOf(TProcessMemoryCounters)) then
      Result := MemCounters.WorkingSetSize;
    CloseHandle(HProc);
  end;
end;

Upvotes: 2

Related Questions