Windows Vista contains a new feature that allows an administrator to work with less privileges. Every time a user who belongs to the administrator group logs on, the LogonUser API creates two tokens. One tokens contains the real power of the user and the second contains only restricted access. We call such a token restricted token. This feature was implemented way back in Windows 2000 . The changes on the restricted token starts with removed privileges and ends with setting the administrator group in the token groups to use for deny only. A deny only Sid is only used for access control entries that deny access. So in our case the access to a file which allows Administrators full access may be disallowed if there is not any other positive element that grants us the access.
Back to the topic. The token groups contains a special Sid that is called an integrity Sid. The token that has the administrator group enabled receives a high integrity Sid. Tthe medium integrity Sid goes to the groups of the restricted token.
The token returned bei LogonUser is always the restricted one. Although you can retrieve the the twin token, you cannot do anything with it if you are not a SYSTEM process or an administrator. However a SYSTEM process may return the powerful token to create a process with full administrator rights. UAC does not do anything else. It gets the user’s credentials, logs on and uses the twin token (if any, otherwise it prompts for an administrator account credentials) to create the process.

uses JwaWindows, JwsclExceptions, JwsclToken;var Token,
    TwinToken : TJwSecurityToken;
  Token := TJwSecurityToken.CreateTokenEffective(MAXIMUM_ALLOWED);
    TwinToken := Token.LinkedToken;
    On E : EJwsclSecurityException do
      //error logic here
    //do stuff here

Both tokens are linked together. Thus the following conditions are true.

Token.LinkedToken = TwinToken
TwinToken.LinkedToken = Token

You can use the twin token in any way you treat a token if you are powerful enough. Use it in CreateProcess or impersonate the user to do things as the user.

At the end I post a quite useful piece of code that displays primary information about a token.

uses …, JwsclSecurityId,…;
procedure PrintTokenInfo(const Token : TJwSecurityToken);
var SID, SID2 : TJwSecurityID;
  writeln(‘Access: ‘,JwFormatAccessRights(Token.AccessMask,TokenMapping ));

  Sid := Token.TokenUser;
  writeln(‘TokenUser: ‘,SID.GetText(true));

  Sid := Token.TokenOwner;
  writeln(‘TokenOwner: ‘,SID.GetText(true));

  writeln(‘TokenGroups: ‘#13#10,Token.TokenGroups.GetText(true));

Tell me how you liked this blog entry by adding a comment.