简体   繁体   中英

OpenProcessToken() gives "Access is denied"

As part of a project which runs as a service that spawns a process in the login screen (for desktop control) we call OpenProcessToken(), which is then duplicated and a process created. This works successfully as expected under LocalSystem, however this does not work under a domain account. The code fragment is below...

procedure LaunchProcess;
var dwPid, dwSessionId: DWord;
  hUserToken, hProcess: THANDLE;
begin
  dwPid := GetProcessID('winlogon.exe', WTSGetActiveConsoleSessionId);
  hProcess := OpenProcess(MAXIMUM_ALLOWED, FALSE, dwPid);
  if (not OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY or TOKEN_DUPLICATE or
    TOKEN_ASSIGN_PRIMARY or TOKEN_ADJUST_SESSIONID or TOKEN_READ or TOKEN_WRITE, hUserToken)) then
      raise Exception.Create('OpenProcessToken failed (' + SysErrorMessage(GetLastError) + ').');

  {...go on to duplicate token, create environment and launch process...}

end;

Full source of the surrounding supporting function can be found here .

This is where it gets a little vague. I understand OpenProcessToken() requires privileges, which is ultimately why I am getting the error, however it wasn't clear what privilege I require, and how to effectively assign that against a domain account.

This would suggest that the required privilege is SeTcbPrivilege ("Act as part of the operating system").

I've read the Microsoft page (can't link, not enough reputation - sorry) on privileges which suggests that the SeTcbPrivilege can be assigned to a domain account using Local or Group Security Policy. It has also been suggested that the destination process (ie winlogon.exe) may simply not allow anything other than LocalSystem to obtain its token.

I have tried to configure the domain account explicitly using account the service, but in the Local Security and Group Policy, have restarted and performed gporesult to ensure the policy has taken effect, but each time whoami /priv returns SeTcbPrivilege is disabled

My question is if this is even possible (can I obtain winlogon.exe token using a domain account) and if so can the privilege be set programmatically, or does this need to be through GPO? (and if so, given my previous attempts at using GPO had no effect, how is it possible)

  1. You can Activate Rights using LsaAddAccountRights, you still need to at least log off/on possibly reboot.
  2. You then need to enable the Privileges for those rights in your code. Lots of things happen automatically for Local-system that do not for Users.
  3. For a quick test I Activated and Enabled SE_TCB_NAME, SE_ASSIGNPRIMARYTOKEN_NAME and SE_INCREASE_QUOTA_NAME
  4. I was then able to successfully call OpenProcessToken with only TOKEN_DUPLICATE
  5. Activating those right gave me a new SessionID after Log off/on. SessionID of 2 so your call to WTSGetActiveConsoleSessionId would have falsely returned 1

All this was done as elevated Admin

Does your application run successfully when you run it with administrator privileges? If so, go to your project options, select Application and check "Enable Administrator Privileges" under Manifest File.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM