1

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 (i.e. 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)

Community
  • 1
  • 1

2 Answers2

1
  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

FredS
  • 680
  • 1
  • 5
  • 6
  • Thanks Fred, I'll give that a go later tonight, I just wanted to confirm the kind of source that I need to drive the activation of rights, is it something like [this](https://www.nexusdb.com/support/index.php?q=node/26886)? – Ross Harvey Oct 04 '16 at 11:46
  • Sorry this is definately an area I'm unfamiliar with. From what you've said I understand there are two actions here - the **activation** which is the process of assigning the privilege to the user (presumably is persistent), then the **enabling** which presumably happens before calling OpenProcessToken()? You've helped me not just on this but on another question as well and I truly appreciate it, it's mildly embarrassing as your answer should be enough for me to go on, but if you have any pointers, API functions you've used, that would help me along that would really be appreciated. – Ross Harvey Oct 04 '16 at 20:05
  • @Ross, Adding or Activating can be done with GPO or LSA, you still need to enable it using AdjustTokenPrivileges which is used in your original post so one would think you know what that is doing.. and yes, you must enable it before calls are made which require it. I Enable those for the process in form.create. – FredS Oct 04 '16 at 20:28
  • Thanks Fred, can I ask when you say you enable privileges on form.create, do you mean you AdjustTokenPrivileges of your own process before opening the process, because I use AdjustTokenPrivileges after OpenProcessToken, which has already failed by then. As for adding or activating, I tried this with GPO and the LSP, I'm using a domain account which is also a local admin, but 'whoami /priv' didn't seem to show it being enabled, I'd like to try programatically so that it is explicit (rather than configuring the GPO which seemed to be applied but as above didn't take effect). – Ross Harvey Oct 04 '16 at 22:21
  • @Ross correct you need to Enable the Priviledges for your own Process before you call anything else. – FredS Oct 04 '16 at 22:48
  • Thanks Fred, your help has got me much closer now. I've applied the privileges by GPO, including SE_TCB_NAME, SE_ASSIGNPRIMARYTOKEN_NAME and SE_INCREASE_QUOTA_NAME. I've confirmed within my service that these are correctly applied (`whoami /priv` shows these as enabled). I'm using NTSetPrivilege() to set these same privileges, performed before calling LaunchProcess(), and is only called once (presumably these privileges only need to be set once for the process). However despite that my OpenProcessToken() still fails with "Access is Denied". Do I have all of the required privileges set? – Ross Harvey Oct 05 '16 at 02:51
  • I've analysed the differences between LocalSystem and my domain account the service is running under, the Se privileges which the domain account is missing are as follows: `SeLockMemoryPrivilege`, `SeSystemProfilePrivilege`, `SeProfileSingleProcessPrivilege`, `SeIncreaseBasePriorityPrivilege`, `SeCreatePagefilePrivilege`, `SeCreatePermanentPrivilege`, `SeDebugPrivilege`, `SeAuditPrivilege`, `SeIncreaseWorkingSetPrivilege`, `SeTimeZonePrivilege` and `SeCreateSymbolicLinkPrivilege`. Could any of those be required, say `SeDebugPrivilege`? Thanks Fred. – Ross Harvey Oct 05 '16 at 09:16
0

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.

Pat Heuvel
  • 96
  • 4