【问题标题】:Does LOGON32_LOGON_INTERACTIVE give restricted token?LOGON32_LOGON_INTERACTIVE 是否提供受限令牌?
【发布时间】:2017-08-21 20:04:22
【问题描述】:

我想了解的是LogonUserLOGON32_LOGON_INTERACTIVE 是否产生受限令牌?这是我的代码:

int davai()
{
FILE * fp;

fp = fopen ("C:\\tmp\\davai.txt", "a");
fprintf(fp, "shevedi davai");
fflush(fp);

HANDLE token = NULL;
HANDLE dupToken = NULL;

if(!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_DUPLICATE, &token))
{
  fprintf(fp, "davai: OpenProcessToken cheijva. %d\n", (int)GetLastError());
  fflush(fp);
}

if (DuplicateTokenEx(token, MAXIMUM_ALLOWED, NULL, SecurityDelegation,
                          TokenPrimary, &dupToken) == 0)
{
  fprintf(fp, "davai: OpenProcessToken DuplicateTokenEx. %d\n", (int)GetLastError());
  fflush(fp);
}

PTOKEN_GROUPS pPrivilegesToken = NULL;
DWORD cbSize = 0;

GetTokenInformation(dupToken, TokenGroups, NULL, 0, &cbSize);

pPrivilegesToken = (PTOKEN_GROUPS) LocalAlloc(LPTR, cbSize);

if (GetTokenInformation(dupToken, TokenGroups, 
                             pPrivilegesToken, cbSize, &cbSize) == FALSE)
{
  fprintf(fp, "davai: GetTokenInformation cheijva. %d\n", (int)GetLastError());
  fflush(fp);
}

char * gio;

for (ULONG i = 0; i < pPrivilegesToken->GroupCount; i++)
{
  if (ConvertSidToStringSid(pPrivilegesToken->Groups[i].Sid, &gio) == 0)
  {
    fprintf(fp, "davai: ConvertSidToStringSid cheijva. %d\n", (int)GetLastError());
    fflush(fp);
  }
 
  fprintf(fp, "Value: %s attribute -> %ld \n",gio, pPrivilegesToken->Groups[i].Attributes);
  fflush(fp);
}

LocalFree (gio);

return 1;
}

LOGON32_LOGON_INTERACTIVE 获得的令牌运行。我的输出是这样的:

Value: S-1-5-21-1018819917-2920201817-244685803-513 attribute -> 7 
Value: S-1-1-0 attribute -> 7 
Value: S-1-5-21-1018819917-2920201817-244685803-1000 attribute -> 7 
Value: S-1-5-32-544 attribute -> 16 
Value: S-1-5-32-545 attribute -> 7 
Value: S-1-5-4 attribute -> 7 
Value: S-1-2-1 attribute -> 7 
Value: S-1-5-11 attribute -> 7 
Value: S-1-5-15 attribute -> 7 
Value: S-1-5-5-0-19732224 attribute -> -1073741817 
Value: S-1-5-64-10 attribute -> 7 
Value: S-1-16-8192 attribute -> 96 

注意16Administrators Group。如果我使用LOGON32_LOGON_BATCH,我会得到这个:

S-1-5-21-1018819917-2920201817-244685803-513 attribute -> 7 
Value: S-1-1-0 attribute -> 7 
Value: S-1-5-21-1018819917-2920201817-244685803-1000 attribute -> 7 
Value: S-1-5-32-544 attribute -> 15 
Value: S-1-5-32-545 attribute -> 7 
Value: S-1-5-3 attribute -> 7 
Value: S-1-2-1 attribute -> 7 
Value: S-1-5-11 attribute -> 7 
Value: S-1-5-15 attribute -> 7 
Value: S-1-2-0 attribute -> 7 
Value: S-1-5-5-0-20537541 attribute -> -1073741817 
Value: S-1-5-64-10 attribute -> 7 
Value: S-1-16-12288 attribute -> 96 

我也发现有些人和我有同样的问题。

  1. IsAdminUser returns incorrect value
  2. In Windows: How do you programatically launch a process in administrator mode under another user context?
  3. How to call LogonUser() to get a non-restricted full token inside a Windows Service with UAC enabled?

在我看来LOGON32_LOGON_INTERACTIVE 会产生受限令牌(或者只是不同类型的登录会产生不同类型的令牌?),是否有任何文档可以验证我是对的?

【问题讨论】:

  • Win32:API 是用 C 语言编写的(作为 XS 模块),您可以查看 IsAdminUser here 的实现
  • 您是在询问 UAC 提升令牌吗?受限令牌是一个特定的东西,请不要使用该术语,除非您实际上是在谈论受限令牌!受限令牌比您的常规登录令牌更受限制。
  • 是的。它为您提供了一个 UAC(“LUA”)过滤令牌。文档?不是真的,也没有理由。 UAC 上的文档说你得到了一个过滤的令牌。有趣的部分是其他登录类型(BATCH 等)不会产生过滤令牌。这才是真正需要文档的地方。它在哪里说有免于 UAC 的登录类型?
  • @Anders:你是对的,但是文档(和符号)已经够混乱了,所以可以理解。过滤的令牌“比您的常规登录令牌更受限制”,因此您的解释没有描述差异。用来证明这些东西的复杂性。
  • ... 跟进我之前的评论,事实证明,为了使用该方法获得可用的提升令牌,您必须拥有 SeTcbPrivilege。通常,如果您作为本地系统运行,您将只有此权限。否则,您将不得不使用前面讨论过的LOGON32_LOGON_BATCH

标签: c windows winapi


【解决方案1】:

LOGON32_LOGON_INTERACTIVE 是否提供受限令牌?

是的,对于所有交互式 logon types :{ Interactive, RemoteInteractive, CachedInteractive, CachedRemoteInteractive }

让调试 lsass.exe 并查看在调用 LsaApLogonUserEx2 期间发生了什么(当客户端进程调用 LsaLogonUser 或它时,此函数在 lsass 的上下文中调用壳LogonUser)

如果登录成功,lsass 必须为登录用户创建新令牌。这是在函数LsaBuildAndCreateToken 中完成的(当然这是内部实现,这个函数的名称可以从一个版本更改为另一个版本,但一般它是如何工作的 - 不变)。所以我在调试器下跟踪这个函数 - 查看右侧的调用树(这是用于交互式登录)

寻找红色乡绅 - ESI - LogonType - SECURITY_LOGON_TYPE 枚举值

所以一般的代码是下一个:

    SECURITY_LOGON_TYPE LogonType;
    switch (LogonType)
    {
    case Interactive://2
    case RemoteInteractive://10 
    case CachedInteractive://11
    case CachedRemoteInteractive://12
        // optimization (LogonType == 2) || (LogonType - 10) <= 2
        BOOLEAN b, c;
        if (0 <= LsapShouldSplitToken(Sid, &b,&c) && b)
        {
            LsaSplitElevatedToken(..)
        }
        break;
    }

这意味着 lsass 尝试限制 ONLY INTERACTIVE 登录类型,如果将是另一种登录类型,例如 Batch - 永远不会过滤令牌.

下一个有趣的点——让我们寻找LsapShouldSplitToken函数

谁知道 x64 - 可以理解代码 :) 如果 LUA 未启用 - 不要过滤令牌。如果全局变量 LsapGlobalFilterAdministratorToken 为假 - 检查用户是否为内置管理员 - 检查 SidRID - 是否为 0x1f4 - DOMAIN_USER_RID_ADMIN(换句话说,内置 -仅当 LsapGlobalFilterAdministratorToken 为 true 时在管理员中受限 - 基于全局补偿政治 (gpedit.msc) - 并返回查询结果 10+4=0x14=TokenElevation 和返回值 TokenIsElevated

所以如果TokenIsElevated 为真 lsass 调用(不要忘记仅适用于 Interactive 登录类型)LsaSplitElevatedToken - 此函数的作用在图像中可见:

创建了额外的登录会话(同一用户在不同的登录会话中运行的提升而不提升的进程),创建了一个令牌(LsapCreateTokenObject)并通过调用NtFilterToken(hToken, LUA_TOKEN, 0, 0, 0, &amp;hNewToken)过滤(win32 apiCreateRestrictedToken是shell over NtFilterToken)

【讨论】:

  • 还有一个问题,您使用的是什么调试器?我也想学:)
  • @Rasty - 不幸的是,这个调试器只存在于单一版本中,没有人对此感兴趣。使用更好的WinDbg
猜你喜欢
  • 2013-02-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-28
  • 1970-01-01
  • 2022-01-02
  • 2016-07-30
  • 1970-01-01
相关资源
最近更新 更多