【问题标题】:How to use an EV Code Signing Certificate on a virtual machine to sign an MSI如何在虚拟机上使用 EV 代码签名证书来签署 MSI
【发布时间】:2013-04-01 03:59:42
【问题描述】:

我们最近从 DigiCert 购买了 EV 代码签名证书来签署我们的 MSI 以避开 Windows SmartScreen 警告消息。问题是证书被传递到不允许导出私钥的 USB 令牌。我们的构建环境位于托管 VM 上,因此我们无法将 USB 令牌插入主机 VM。

是否有人提供在托管 VM 上使用 EV 代码签名证书的解决方案?是否所有证书供应商都将此类证书交付给硬件令牌?您如何使用这种类型的证书在虚拟环境中对 MSI 进行代码签名?

【问题讨论】:

标签: code-signing code-signing-certificate


【解决方案1】:

SafeNet 客户端附带的加密提供程序正在使用 SmardCardAPI (winscard.dll) 访问 USB 令牌。由于智能卡还用于身份验证/登录目的,RDP 堆栈将始终重定向对 RDP 客户端计算机的任何访问。

https://docs.microsoft.com/en-us/windows/security/identity-protection/smart-cards/smart-card-and-remote-desktop-services

对于像代码签名这样的场景,这种行为可能非常麻烦。我们使用专用的虚拟机进行签名,每个有权访问该机器的开发人员都应该能够执行签名过程。对于 COVID-19 和所有在家工作的开发人员,使用本地 USB 端口的想法是不可行的。我们的 USB-Token 连接到专用机器上。每次您通过 RDP 连接到这台机器时,加密狗都无法再访问,因为 SmartCardAPI 将重定向访问。

但是有一个解决这个问题的方法: 智能卡堆栈使用 API 调用

ProcessIdToSessionId

WinStationGetCurrentSessionCapabilities

确定当前进程是否在 RDP 会话中运行。通过将 DLL 注入 signtool 并使用 Detours 框架,您可以挂钩这些 API 调用并报告本地会话,因此 SmardCardAPI 将访问连接到远程虚拟机的加密狗。

https://github.com/microsoft/Detours

迂回的函数很简单(代码简化为重要的东西,所以你可以理解)

DWORD WINAPI ProcessIdToSessionIdLocal(DWORD dwProcessId, DWORD *pSessionId)
{
  OutputDebugString("Detoured ProcessIdToSessionId\r\n");
  if (pSessionId)
     pSessionId = 0;
  return TRUE;
}

BOOL WINAPI WinStationGetCurrentSessionCapabilitiesLocal(DWORD flags, DWORD *pOutBuffer)
{
   BOOL bResult;
   
   OutputDebugString("Detoured WinStationGetCurrentSessionCapabilities\r\n");
   bResult = TrueGetCurStationCapabilities(flags,pOutBuffer);
   if (bResult)
      *pOutBuffer = 0;
   return bResult;
}

BOOL WINAPI DllMain (haDLL, dwReason, lpReserved)
    HANDLE haDLL;
    DWORD dwReason;
    LPVOID lpReserved;
{
    LONG error;
    TCHAR cBuffer[160];
    
    wsprintf(cBuffer,"DllMain Entry %08x\r\n",dwReason);
    OutputDebugString(cBuffer);
    if (DetourIsHelperProcess()) {
        return TRUE;
    }

    if (dwReason == DLL_PROCESS_ATTACH) {
        OutputDebugString("Starting Detour API Calls \r\n");
        hStaDLL = LoadLibrary("WINSTA.DLL");
        TrueGetCurStationCapabilities = GetProcAddress(hStaDLL,"WinStationGetCurrentSessionCapabilities");
        
        DetourRestoreAfterWith();
        DetourTransactionBegin();
        DetourUpdateThread(GetCurrentThread());
        DetourAttach((PVOID*)&TrueProcessIdToSessionId, ProcessIdToSessionIdLocal);
        DetourAttach((PVOID*)&TrueGetCurStationCapabilities, WinStationGetCurrentSessionCapabilitiesLocal);
        error = DetourTransactionCommit();

        if (error == NO_ERROR) {
        OutputDebugString("Successfully Detoured API Calls \r\n");

        }
        else {
            return FALSE;
        }
    }
    else if (dwReason == DLL_PROCESS_DETACH) {
        DetourTransactionBegin();
        DetourUpdateThread(GetCurrentThread());
        DetourDetach((PVOID*)&TrueProcessIdToSessionId, ProcessIdToSessionIdLocal);
        DetourDetach((PVOID*)&TrueGetCurStationCapabilities, WinStationGetCurrentSessionCapabilitiesLocal);
        error = DetourTransactionCommit();
        FreeLibrary(hStaDLL);
    }
    return TRUE;
}

将 DLL 注入到 signtool 中也很容易:只需在 IMPORTs 部分添加一个新条目,该条目将加载带有迂回函数的 DLL。这可以使用名为“Lord PE”的工具(用于 32 位可执行文件)来完成。

【讨论】:

    【解决方案2】:

    我对我们的完全没有问题。我们在不到 15 分钟的时间内从 PFX(文件)支持的标准代码签名证书切换到了 USB 令牌支持的 EV 代码签名证书。

    我只是将 USB 令牌设备设置为连接到 VMWare 中的 客户端 操作系统(请参阅客户端操作系统窗口右下方的图标以了解设备),安装必要的设备驱动程序,将选项设置为需要每个会话只能解锁一次的密码,然后就可以使用了。

    关于如何签名,您可以像使用任何其他证书一样进行签名。如果操作系统的证书存储中没有其他适用的代码签名证书,那么您甚至不必指定证书的位置

    我担心我们会遇到麻烦,但没有。所以,我认为你不会,也不知道你为什么会遇到麻烦。

    【讨论】:

    • 在 VM 上安装证书后,我可以使用 cmd 成功地对程序集进行签名,但每次构建代理(在我们的案例中为 Team City)尝试执行命令行或调用批处理文件时命令行,它返回“SignTool 错误:未找到符合所有给定条件的证书”。构建代理是该机器上的管理员。你遇到过这个吗?如果不是,也许您可​​以详细说明您的设置?
    • @NeilVarnas 将/debug添加到您的 signtool cmds 并确定 signtool 在 TeamCity 案例中消除所有证书的基础。您也许可以调整您的 signtool 调用,以向 signtool 提示选择哪个证书。
    • @NeilVarnas 不,我从来没有遇到过这样的事情。听起来像是特定于您的构建代理的东西。我所有的签名都是通过signtool.exe。
    • (在更新被拒绝后添加评论)更新:我后来切换到远程桌面会话进行开发,并且规则是这样的 - USB 令牌必须插入客户端计算机(你所在的那个,不是您远程登录的虚拟机)。如果将 USB 令牌插入主机而不是带有远程桌面的客户端,它将无法工作,它会立即断开 USB 令牌(我认为是设计使然)。但是,您可以使用 TeamViewer 或 VNC 并将令牌保留在主机上。我喜欢将它放在客户端上,因为我可以远程访问不同的虚拟机,并且它会像我一样连接到每个虚拟机。
    • 你需要在vm里面安装usb token软件/驱动。我只将它们放在插入令牌的机器上并且不起作用。在 vm 中安装它们确实解决了这个问题。
    【解决方案3】:

    对于遇到此问题的其他人,我们使用 VNC 服务器连接到上面有令牌的 VM。它不适用于仅 RDP 的 VNC。

    显然,VNC 就像拥有对盒子的控制台访问权限(就 EV 加密狗而言)。

    【讨论】:

      【解决方案4】:

      EV 代码签名证书需要使用特殊硬件来存储私钥。这就是使它们比标准证书更昂贵和更安全的部分原因。我的建议是使用 signtool.exe 作为构建后步骤在主机上签署可执行文件。

      普通代码签名证书没有硬件要求,但不像 EV 证书那样“SmartScreen Filter Friendly”。

      【讨论】:

        【解决方案5】:

        包括 VMware 在内的一些虚拟化软件允许重定向 USB 设备。

        【讨论】:

        • ...并确保您使用 vnc 连接到您的虚拟机,而不是远程桌面
        • @azhrei 你知道为什么使用远程桌面时加密狗似乎断开了吗?一旦我在 vmware 中使用控制台窗口,它似乎没问题(证书软件看到加密狗)
        • @NeilVarnas 我不知道为什么 - 我猜测加密狗驱动程序出于安全目的明确要求(并检查)您在控制台上
        猜你喜欢
        • 2014-02-03
        • 2018-01-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-07-09
        • 1970-01-01
        相关资源
        最近更新 更多