【问题标题】:Get AzureAD email address from username using Windows API?使用 Windows API 从用户名获取 AzureAD 电子邮件地址?
【发布时间】:2022-08-08 22:03:31
【问题描述】:

我在用

WTSEnumerateSessionsEx(WTS_CURRENT_SERVER_HANDLE, &level, 0, &pSessionInfo, &count);

获取会话信息。它会告诉我所有登录的用户。如果我在其他用户登录的情况下在 Windows 11 上使用它,

WTS User: DESKTOP-VVVVVVV\\joew, session id: 1, state: 0, session name: Console
WTS User: AzureAD\\JoeWillcoxso_garbage, session id: 17, state: 4

从状态来看,joew 是活跃用户,JoeWillcoxso_garbage。不完全是这样,但我正在保护它……你明白了。

会话信息将为我提供域和用户名。当我使用非标准凭据提供程序登录到 AzureAD 的 Windows 时,我使用我的 AzureAD 电子邮件地址,并且 CP 足够聪明,可以使用 AzureAD 作为域名。但是,当机器加入 AzureAD 时,它为电子邮件地址创建了一个本地帐户,名为 JoeWillcoxso_garbage。 (我写了“创建了一个本地帐户”,但在 PowerShell 中,如果我写了get-localuser *,该用户不会出现在列表中。)

我可以使用LsaEnumerateLogonSessions()LsaGetLogonSessionData() 从本地安全机构获取会话数据。我可以使用会话 ID 和用户名匹配两个调用(LsaGetLogonSessionData 和 WTSEnumerateSessionsEx)之间的内容。但是,无法获取电子邮件地址。我可以在会话数据中获取 PSID,但不确定是否有办法将其转换为电子邮件地址。在我的本地机器上,我没有连接到 AD。只是作为 WORKGROUP 运行。

对于 AzureAD 用户,调用 NetUserGetInfo() 对于 AAD 用户总是会失败,即使在运行提升时也是如此。我还没有尝试作为 NT_AUTHORITY 帐户...

我正在寻找 API 或某种方式来查询 WMI 以将 AzureAD\\JoeWillcoxso_garbage 用户名转换为 joe@someaad.onmicrosoft.com 电子邮件地址。或者,可能需要一个 Web API 来访问 login.windows.net。注册表中有一些地方我可以找到电子邮件地址,但我不认为它们一定会一直存在。

由于用户可能已经登录(并且在具有快速切换功能的 Windows 10/11 上),有时解锁不是 CPUS_UNLOCK_WORKSTATION 而是 CPUS_LOGON。使用快速切换,如果我锁定,10 分钟后返回,然后解锁,这不是解锁而是登录 (CPUS_LOGON),尽管它的行为就像以前的解锁一样。


例如,在 HKEY_USERS\\THE_SID_OF_THE USER\\Software\\Microsoft\\Office\\Teams,HomeUserUpn 有电子邮件地址。我可以获得登录用户的 SID...所以我可以让电子邮件匹配...但是,假设密钥在那里。我想要一些更防弹的东西。

  • 嗨@JosephWillcoxson,建议的解决方案对您有用吗?如果它解决了您的问题,请告诉我,否则请分享更多详细信息,以便我进行故障排除或接受它以帮助其他社区成员。

标签: winapi azure-active-directory credential-providers


【解决方案1】:

• 您肯定可以通过以下powershell 命令从UPN 获取已登录用户的电子邮件地址,因为您很容易必须对网络中的系统具有远程脚本执行权限.

一个)哇阿米/upn--> 显示登录用户的完整电子邮件地址

b)"$env:USERNAME@$env:USERDNSDOMAIN"--> 显示完整的电子邮件地址及其条目映射到的 DNS 区域

C)$msAccountName = ([adsisearcher]"(samaccountname=$env:USERNAME)").FindOne().Properties.mail $msAccountName--> 显示来自在线 O365/Azure AD 帐户的电子邮件地址

因此,相应地根据上述 powershell 命令,您可以获取 Azure AD 的登录会话用户的电子邮件地址。此外,如果您想为此目的使用 WTS 查询功能,请参阅以下链接了解更多详细信息,因为它恰当地描述了 WTS 查询命令用于上述目的的用法: -

https://www.idrix.fr/Root/Samples/upn.cpp

【讨论】:

    【解决方案2】:

    我想从 Win32 中使用一些东西,因此标签。我确实发现,从作为 NT_System 帐户运行的进程中,我可以迭代所有 LSA 会话。

    我可以使用LSAEnumerateLogonSessions() 来获取所有会话的列表。

    一旦我有了会话,对于每个会话,我都可以调用LsaGetLogonSessionData(),这将返回一个PSECURITY_LOGON_SESSION_DATA,它重要的是返回会话ID、登录域、登录名和用户的SID。查看登录域,我可以知道它是否是 AzureAD,因为它实际上是 AzureAD。知道它是 AzureAD,然后我可以使用 SID 并在键(不是整个函数)上进行注册表查找:

    CString s;
    s.Format(L"SOFTWARE\\Microsoft\\IdentityStore\\Cache\\%s\\IdentityCache\\%s", lpwzSid, lpwzSid);
    
    ATL::CRegKey regKey;
    if (ERROR_SUCCESS == regKey.Open(HKEY_LOCAL_MACHINE, s, KEY_READ))
    {
        WCHAR szUserName[MAX_PATH] = { 0 };
        ULONG ulChars = MAX_PATH;
        if (ERROR_SUCCESS == regKey.QueryStringValue(L"UserName", szUserName, &ulChars) && ulChars > 0)
        {
            return CString(szUserName);
        }
    }
    

    这几乎可以工作,除了一点点……有时 AzureAD 用户已经注销,但仍然有一个打开的 LSA 会话。我不知道这是怎么发生的,但我在 Windows 11 上观察到了它。IDK 如果这适用于所有 AzureAD 用户,但我注意到用于加入 AzureAD 域的帐户可能是这种情况。因此,在这种情况下,有必要回查并使用WTSEnumerateSessionsEx() 并验证确实有一个打开的会话。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-16
      • 2015-01-23
      • 2023-01-25
      • 2020-09-16
      • 1970-01-01
      相关资源
      最近更新 更多