在使用自签名证书进行更新期间,ClickOnce绕过SmartScreenFilter

时间:2016-01-15 13:32:31

标签: c# .net windows clickonce

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

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

Essentialy我必须创建自签名的可信证书来签署我的应用程序,然后在首次运行时安装这些证书。现在没有远离它,但由于自签名证书,新机器将需要管理员权限(您实际上需要输入密码3次)。但对于企业用途,无论如何“你”自己设置机器并安装应用程序,这没关系。

详细信息在答案中:

1 个答案:

答案 0 :(得分:0)

第1步:创建自签名证书

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

(以管理员身份打开Visual Studio Developer命令提示符)

makecert -sv c:\users\Marko\Desktop\CA.pvk -pe -r -n "CN=My Certificate Authority" -sky signature -a sha512 -e 12/31/2099 -cy authority -ss My -sr LocalMachine c:\users\Marko\Desktop\CA.cer

makecert -sv c:\users\Marko\Desktop\cert.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:\users\Marko\Desktop\cert.cer

cert2spc c:\Users\Marko\Desktop\cert.cer c:\Users\Marko\Desktop\cert.spc

pvk2pfx -pvk c:\Users\Marko\Desktop\cert.pvk -pi mypassword -spc c:\users\Marko\Desktop\cert.spc -pfx c:\users\Marko\Desktop\cert.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 ,添加一个Post-Build任务来签署.exe。我选择Post-Build选项,因为它是最简单的,我也没有任何问题,如'{3}}所描述的'签名哈希不匹配清单'。我在Visual Studio中使用了以下命令项目属性 - > 构建活动标签 - > 制作后部分:

"C:\Program Files (x86)\Windows Kits\10\bin\x64\signtool.exe" sign /f "$(ProjectDir)cert.pfx" /p mypassword /v "$(ProjectDir)obj\$(ConfigurationName)\$(TargetFileName)"

步骤3:首次运行导入证书绕过SmartScreenFilter

这是关键部分。我们需要将证书导入Local Machine\RootLocal Machine\TrustedPublisher商店。首先,将 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(here),请单击“安装”按钮,下载Setup.exe。 Edge当然会警告,这个文件通常不会下载=无论如何都要运行。

第一次密码提示=运行setup.exe(SmartScreenFilter干扰)
第二个密码提示=运行已安装的应用程序(SmartScreenFilter干扰)
第三个密码提示=以管理员身份运行PowerShell。

但是,如果我现在发布我的应用程序的新版本,然后没有更多的密码提示,应用程序会更新并在没有SmartScreenFilter干扰的情况下运行:)

最后说明:

尽管cert.cer现在受到信任,但简单地导入CA.cer并没有帮助。但是导入CA.cer和cert.cer都没有。