单击一次在使用自签名证书进行更新期间绕过智能屏幕筛选器



我正在开发自己的.NET应用程序供私营企业使用,通过HTTP上的ClickOnce分发。我遇到的困难之一是SmartScreenFilter(内置于Win 8/10中)干扰了更新。每次更新后,都需要管理员权限(密码)才能首次运行更新的应用程序。

参考这些链接 - 链接1,链接2 - 以及一些试验和错误,我能够绕过SmartScreenFilter。

本质上,我必须创建自签名的受信任证书来对我的应用程序进行签名,然后在首次运行时安装这些证书。现在无法摆脱它,但由于自签名证书,新机器将需要管理员权限(实际上您需要输入密码 3 次)。但是对于企业使用,"您"无论如何都会自己设置机器并安装应用程序,这没关系。

详情见答案:

步骤 1:创建自签名证书

1)我们需要其中两个。第一个是证书颁发机构,第二个是用于对应用进行签名的实际证书。有关详细信息,请参阅 Link2。我使用了以下命令:

(以管理员身份打开 Visual Studio Developer Command Prompt)

makecert -sv c:usersMarkoDesktopCA.pvk -pe -r -n "CN=My Certificate Authority" -sky signature -a sha512 -e 12/31/2099 -cy authority -ss My -sr LocalMachine c:usersMarkoDesktopCA.cer
makecert -sv c:usersMarkoDesktopcert.pvk -ss My -sr Localmachine -pe -n "CN=MyPublisherName" -eku "1.3.6.1.5.5.7.3.3,1.3.6.1.4.1.311.10.3.13" -sky signature -a sha512 -e 12/31/2099 -in "My Certificate Authority" -is My -ir LocalMachine c:usersMarkoDesktopcert.cer
cert2spc c:UsersMarkoDesktopcert.cer c:UsersMarkoDesktopcert.spc
pvk2pfx -pvk c:UsersMarkoDesktopcert.pvk -pi mypassword -spc c:usersMarkoDesktopcert.spc -pfx c:usersMarkoDesktopcert.pfx -po mypassword

确保对所有密码提示使用相同的mypassword。还要在这些命令中相应地修改文件夹路径。

步骤 2:对应用程序程序集、清单和.exe进行签名

在 Visual Studio 中,将 cert.pfx 文件导入/添加到解决方案中。转到项目属性 -> 签名选项卡。勾选Sign the ClickOnce manifests复选框并使用 cert.pfx 文件进行签名(Select from file按钮)。然后勾选Sign the assembly复选框并从组合框中选择 cert.pfx 文件。

参考 Link1,添加生成后任务以对.exe进行签名。我选择"后期构建"选项,因为它是最简单的,而且我没有遇到此处所述的"签名哈希与清单不匹配"的任何问题。我在Visual Studio Project属性->"生成事件"选项卡->"后期生成"部分中使用了以下命令:

"C:Program Files (x86)Windows Kits10binx64signtool.exe" sign /f "$(ProjectDir)cert.pfx" /p mypassword /v "$(ProjectDir)obj$(ConfigurationName)$(TargetFileName)"

步骤 3:通过在首次运行时导入证书来绕过智能屏幕筛选器

这是关键部分。我们需要将证书导入Local MachineRootLocal MachineTrustedPublisher存储。首先,将 CA.cer 和 cert.cer 文件添加到解决方案中。将其生成操作设置为 Content复制到输出目录Copy if newer 。然后在项目属性 -> Pulish 选项卡 -> 应用程序文件按钮 ->(勾选 Show all files )下,将.cer文件设置为 Publish Status = Data File

对于实际导入,我在 Window_Loaded() 事件处理程序中调用了 PowerShell:

if (MyApp.Properties.Settings.Default.FirstRun) // I used a custom project setting called 'FirstRun'
{
    try
    {
        using (System.Diagnostics.Process prcs = new System.Diagnostics.Process()) // import certificates
        {
            var dir = (ApplicationDeployment.IsNetworkDeployed ? ApplicationDeployment.CurrentDeployment.DataDirectory :
                System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location));
            var filePath = System.IO.Path.Combine(dir, "CA.cer");
            var filePath2 = System.IO.Path.Combine(dir, "cert.cer");
            prcs.StartInfo.Verb = "runas";
            prcs.StartInfo.FileName = "powershell.exe";
            prcs.StartInfo.Arguments = "Import-Certificate -Filepath '" + filePath + "' -CertStoreLocation cert:\LocalMachine\Root;" +
                "Import-Certificate -Filepath '" + filePath + "' -CertStoreLocation cert:\LocalMachine\TrustedPublisher;" +
                "Import-Certificate -Filepath '" + filePath2 + "' -CertStoreLocation cert:\LocalMachine\Root;" +
                "Import-Certificate -Filepath '" + filePath2 + "' -CertStoreLocation cert:\LocalMachine\TrustedPublisher";
            prcs.Start();
            prcs.WaitForExit();
        }
        MyApp.Properties.Settings.Default.FirstRun = false;
        MyApp.Properties.Settings.Default.Save();
    }
    catch (Exception ex) // if you cancel the UAC dialog for instance
    {
        MessageBox.Show(ex.ToString());
        this.Close();
    }
}

最终结果:

在 Win 10 下,标准本地用户帐户。
如果我转到我的应用程序的已发布 URL(http://somedomain.com/MyApp),请单击"安装"按钮,安装程序.exe 将下载。Edge 当然会警告,此文件不常下载 = 无论如何都要运行。

第一个密码提示 = 运行安装程序.exe(智能屏幕筛选器会干扰)
第二个密码提示 = 运行已安装的应用程序(智能屏幕筛选器会干扰)
第三个密码提示 = 以管理员身份运行 PowerShell。

但是,如果我现在发布应用程序的新版本,则不再有密码提示,应用程序将更新并运行,而不会受到 SmartScreenFilter 干扰:)

结语:

简单地导入 CA.cer 并没有帮助,尽管证书现在.cer是可信的。但是导入 CA.cer 和证书.cer做到了。

最新更新