65.9K
CodeProject 正在变化。 阅读更多。
Home

Internet Explorer 凭据的秘密

starIconstarIconstarIconstarIconstarIcon

5.00/5 (9投票s)

2017年1月30日

CPOL

3分钟阅读

viewsIcon

33393

downloadIcon

209

几篇文章中的第三篇,涵盖获取浏览器存储(和加密)凭据的秘密

引言

本文是介绍如何获取浏览器(以及其他应用程序,例如:MS Outlook)存储的(和加密的)凭据的系列文章中的第三篇。第一篇文章介绍了 Wi-Fi 凭据。第二篇文章介绍了 Chrome 的凭据。本文介绍 Internet Explorer,以及如何存储凭据并从中获取凭据。

保险库

自 Windows 7 以来,创建了一个保险库来存储任何敏感数据,其中包括 Internet Explorer 的凭据。实际上,保险库是一个 LocalSystem 服务 - vaultsvc.dll

Internet Explorer 允许两种凭据存储方法:网站凭据(例如:您的 Facebook 用户名和密码)和自动完成数据。自版本 10 以来,引入了一个新术语来代替注册表:Windows Vault。 Windows Vault 是凭据管理器信息的默认存储保险库。要使用“保险库”,您需要加载名为“vaultcli.dll”的 DLL,并根据需要访问其函数。

Vaultcli DLL

vaultcli.dll 用于封装访问 Vault 所需的函数。
获取存储的凭据的第一步是从这个 DLL 映射必要的函数。

BOOL InitVault(VOID) 
{
    BOOL bStatus = FALSE;

    hVaultLib = LoadLibrary(L"vaultcli.dll");

    if (hVaultLib != NULL) 
    {
        pVaultEnumerateItems = (VaultEnumerateItems)GetProcAddress
                                                  (hVaultLib, "VaultEnumerateItems");
        pVaultEnumerateVaults = (VaultEnumerateVaults)GetProcAddress
                                                  (hVaultLib, "VaultEnumerateVaults");
        pVaultFree = (VaultFree)GetProcAddress(hVaultLib, "VaultFree");
        pVaultGetItemW7 = (VaultGetItemW7)GetProcAddress(hVaultLib, "VaultGetItem");
        pVaultGetItemW8 = (VaultGetItemW8)GetProcAddress(hVaultLib, "VaultGetItem");
        pVaultOpenVault = (VaultOpenVault)GetProcAddress(hVaultLib, "VaultOpenVault");
        pVaultCloseVault = (VaultCloseVault)GetProcAddress(hVaultLib, "VaultCloseVault");

        bStatus = (pVaultEnumerateVaults != NULL)
            && (pVaultFree != NULL)
            && (pVaultGetItemW7 != NULL)
            && (pVaultGetItemW8 != NULL)
            && (pVaultOpenVault != NULL)
            && (pVaultCloseVault != NULL)
            && (pVaultEnumerateItems != NULL);
    }
    return bStatus;
}

流程

您需要检查正在运行的操作系统。 如果是 Windows 8 或更高版本,则调用 VaultGetItemW8。 如果不是,则调用 VaultGetItemW7

下一步是枚举保险库。 这是通过调用来实现的

dwError = pVaultEnumerateVaults(NULL, &dwVaults, &ppVaultGuids);

pVaultEnumerateVaults(实际上是“VaultEnumerateVaults”)是一个 API 调用,用于枚举所有保险库,以便查看它们的内容。

接下来,我们打开每个保险库并枚举它包含的每个项目。 代码如下所示

    for (DWORD i = 0; i < dwVaults; i++) 
    {
        dwError = pVaultOpenVault(&ppVaultGuids[i], 0, &hVault);
        // open it
        
        if (dwError == ERROR_SUCCESS) 
        {
            PVOID ppItems;
            DWORD dwItems;

            // enumerate items
            dwError = pVaultEnumerateItems
                      (hVault, VAULT_ENUMERATE_ALL_ITEMS, &dwItems, &ppItems);

            if (dwError == ERROR_SUCCESS) 
            {
                // for each item
                for (DWORD j = 0; j < dwItems; j++) 
                {
                    VAULT_ITEM item;
                    BOOL bResult = FALSE;
                    memset(&item, 0, sizeof(VAULT_ITEM));

                    if (bWin80rGreater) 
                    {
                        bResult = GetItemW8(hVault, (PVAULT_ITEM_W8)ppItems, j, item);
                    }
                    else 
                    {
                        bResult = GetItemW7(hVault, (PVAULT_ITEM_W7)ppItems, j, item);
                    }
...

现在我们需要讨论我们自己的数据结构,用于存储浏览器(和其他程序)的凭据。

此时,“item”包含单个凭据条目,我们需要将其存储在我们自己的数据结构中,该结构是我们设计用于存储来自各种来源的凭据的结构。

SGBrowserCredentials 数据结构

SGBrowserCredentials (Secured Globe Browser Credentials) 用于获取浏览器凭据的任何过程,并且能够保存所有浏览器通用的相关字段。

我们定义了单个元素和一个 CSimpleArray ,用于收集我们程序的结果。 我们还使用 CTime 作为每个条目的日期/时间戳。 我们这样做是为了能够比较来自不同来源(浏览器)的凭据,因为每个浏览器使用不同的方法来存储日期和时间。 日期/时间对于我们程序的范围的重要性在于,能够稍后使用它来过滤结果。 例如:能够知道自 2017 年 1 月 1 日或自上次检查以来创建了哪些新凭据。

typedef struct _SGBrowserCredentials
{
    int Browser; // 0 = chrome, 1 = ie, 2 = firefox, 
    TCHAR Site[256];
    TCHAR UserName[80];
    TCHAR Password[256];
    CTime DateCreated;
    _SGBrowserCredentials()
    {
        Site[0] = 0;
        UserName[0] = 0;
        Password[0] = 0;
        DateCreated = NULL;
    }
} SGBrowserCredentials;

typedef CSimpleArray<SGBrowserCredentials> SGBrowserCredentialsArray;

在我们的例子中,我们希望我们的工具只显示设置了实际密码的凭据。 还有一些没有存储密码的网站的存储条目,但这些网站也存储在保险库中。

if (bResult && wcscmp(item.Password.c_str(), L"") && wcscmp(item.Password.c_str(), L" "))
{
    SGBrowserCredentials singleItem;
    wcscpy(singleItem.UserName, item.Account.c_str());     // User name
    wcscpy(singleItem.Site, item.Url.c_str());             // URL
    singleItem.Browser = 1; // better replace this value with enum{chrome, ie, firefox} ...
    singleItem.DateCreated = CTime(item.LastModified);     // Date stored as CTime
    wcscpy(singleItem.Password, item.Password.c_str());    // Password
    credentials->Add(singleItem);        
}

使用此动态数组,我们可以在用户界面中显示它,也可以将其添加到文本报告中(事实上,我们两者都做)。 用于下载的源代码稍后添加。

工具

当您启动 Internet Explorer Credentials Viewer 时,片刻之后,您将看到类似于此屏幕的屏幕。 您所有存储的凭据都将显示出来。

 

更多链接

请访问我的 Github repos。 还有我另一篇关于 Chrome 的文章

历史

  • 2017 年 1 月 30 日:初始版本
  • 7 月 18 日,修复了内存泄漏。
© . All rights reserved.