保护Excel工作簿中的代码?

Unk*_*der 18 c# excel visual-studio

我想生成一个包含专有公式和其他知识产权的Excel工作簿.我很可能使用C#在Visual Studio 2010中生成此工作簿.

这些项目中的代码有多受保护?C#中的反射问题仍然适用于这些工作簿项目吗?如果是这样,是否有针对这些类型工作簿的混淆工具?

添加到这个问题 - 好的'ole VBA怎么样?如果我们要去VBA路线,有没有办法保护这些代码呢?

Mat*_*don 19

正如其他答案所暗示的那样,Excel 2003(.xls)中的VBA安全性存在缺陷; 密码只是一点点烦恼,往往是开发者自己.恕我直言你最好用VSTO,即使Excel 2007+(.xlsx)中的VBA安全性要好得多,更不用说几个世纪以来没有看到改进的VBA IDE(尽管对于正确的VBE添加不是这样)-in ...).

一个解决方案是将敏感代码写入您的VSTO项目调用的单独库中; 而不是复杂的公式,可以将该功能这将显示为"黑盒子"(即公式的功能的抽象); 没有源代码的任何人都无法使用它如何实现,并且没有dll无法计算工作簿(将#NAME?遍布整个地方).

例如,=some proprietary formula returning a Smurf用户不会看到=Smurf(SomeTableColumnName, SomeRangeName, SomeRangeReference, SomeCellReference).当然,这需要一个性能成本,所以我只会做那些对保护非常重要的东西.

我认为设法从这样一个侧面库中提取专有公式的用户应该留下它们 - 在它和Alt + F11之间,这是一个很大的步骤; 专有代码与任何其他.net程序集一样受"保护".

UPDATE

仍然没有使用任何第三方库,如果私有代码并不需要 Excel协同,一个也许是更好的解决方案是创建函数在VBA(即离开Excel的互操作在Excel中的一部分),只有通过原始类型(VBA Integer=> .net Int16; VBA Long=> .net Int32,字符串等)到一个COM-visible库,它甚至不需要使用Excel互操作; 它将是COM互操作而不是Excel互操作,并且性能损失将显着降低,但仍然存在(它仍然是.net托管代码"与非托管COM谈话").

VBA代码的职责是读取和写入工作表,COM-visible库的作用是实现由VBA代码传递的值进行的计算; 当然,用户可以轻松访问VBA代码(Alt + F11),但他们再次无法访问实际的计算实现.然后VBA代码可以受密码保护,并且没有DLL的计算结果将是0或者#VALUE!,取决于VBA代码的实现方式.

关键是在Excel中保留特定于Excel的内容并使.net库可以在不引用Excel互操作程序集的情况下进行拾取 - 例如,VBA函数将获取单元格引用,获取其值(可能验证它)并传递它到.net程序集,它将返回VBA将返回到Excel的另一个基本类型.

另一个优点是,如果您要将Excel工作簿"转换"为Web应用程序,则可以重用具有专有计算的库代码.


stu*_*zor 10

供将来参考:以下是2种新的创新产品,可帮助您解决确切的问题:

1)https://HiveLink.io:-使用HiveLink,您可以创建电子表格的"轻量级"版本,您可以将其提供给您的用户,但它不包含任何敏感的VBA或计算公式.您从轻量级电子表格中删除了知识产权,并向您的用户发送邀请以下载此电子表格.当您的用户输入他们的输入数据时,HiveLink会将数据传送到原始电子表格以处理数据,然后自动将结果返回给用户.

这种方法的好处在于,无法使用.NET反射甚至汇编代码进行逆向工程 - 因为您完全从计算机中删除了代码.这是最安全的选择,如果您的模型适合输入/输出往返设计,那就太棒了 - 如果您需要立即发生的客户端交互式代码,那就太好了.如果您确实需要快速的客户端交互式代码,通常这不太敏感,您可以使用工作簿保护,甚至使用DoneEx Excel Compiler等编译基本代码,并使用Excel Compiler和HiveLink的组合进行保护.

2)http://FCell.io:这允许您直接在电子表格中构建.NET代码.它甚至在电子表格中附带了一个代码编辑器窗口,有点像用.NET代码编辑器替换现有的VBA代码编辑器.代码编辑器中的对象模型比普通代码模型稍微全面,但您也可以创建任务窗格并将它们嵌入到工作簿中进行分发,这样您的用户甚至不需要安装任何东西!我不确定您的代码嵌入到工作簿中有多安全,但我百分之百确定如果对您的代码非常重要,那么人们可以访问您的代码.

进一步评论Re Mat's Mug有用的回复:

Re:性能成本 - 实际上,您可能会注意到通过在.NET中实现的东西可以获得显着的性能提升,特别是如果您利用多线程,Excel根本不会使用UDF或宏.我已经看到100x的重写在.NET库中重写了我的一些客户端代码(用于繁重的处理计算).您可能还发现维护和改进.NET代码要比VBA容易得多.我已经将很多VBA代码和功能转换为.NET代码,并且在正确完成时从未出现过明显的性能问题.

Re:用户应该通过反映.NET库来获取访问权限? - 我完全不同意这一点.这是非常容易使用反射来获取访问.NET代码,也许不是更容易破解Excel的弱密码.如果您确实需要保护敏感计算,那么最好使用像HiveLink这样的东西来完全消除逆向工程的可能性,或者使用混淆来使其变得更加困难/非常烦人.对于混淆,我使用CryptoObfuscator($)和Dotfuscator($$$).如果没有这个,我不会在.NET库中为excel共享客户端的敏感模型VBA代码.我有时也使用CryptoLicensing来允许他们通过为每个用户创建许可来控制谁可以访问他们的DLL功能.

回复:让VBA代码负责写入/读取工作表 - 我也高度反对这一点.我建议尽可能少地在VBA中保留代码并对.NET进行高级调用,将读/写写入.NET插件.在工作表中使用命名范围来标识输入/输出和数据位置,然后在.NET库中将这些命名范围定义为常量.在您的库中,您可以非常轻松地从范围读取并写入范围.这种方式更清洁,更容易维护.

在为要从VBA调用外部功能的Excel构建任何扩展库时,必须使库COM可见.有几种方法可以做到这一点:我强烈建议避免使用regsvr32在Windows COM列表中注册您的库 - 不惜一切代价避免它!

注册库的最佳方法是使用ExcelDna加载它,它允许您在每次启动Excel时动态加载DLL,而无需在注册表中使用COM接口永久定义每个类(更新版本时的噩梦).您最终创建了一个XLL文件,该文件可以将DLL打包在内部 - 您可以通过在注册表中放置一个密钥来告诉Excel每次启动时加载XLL.好处是,这不需要您将整个COM接口存储在注册表中,因此管理新版本非常容易.

因此,您的VBA代码可能类似于:

Sub Button_Click()
    Call ThisWorkbook.EnsureLibraryInitialized
    Call ThisWorkbook.MyLibrary.ReadRangesAndWriteResults(someInputParam)
End Sub
Run Code Online (Sandbox Code Playgroud)

请注意,VBA将在运行时查找此方法ReadRangesAndWriteResults.如果您在VBA中公开编译时的方法,那么您必须在注册表中注册其COM接口签名 - 值得避免不惜一切代价!

ThisWorkbook模块:

Public MyLibrary as Object

public sub Workbook_Open()
    EnsureLibraryInitialized
End Sub

public Sub EnsureLibraryInitialized()
    Dim addin As COMAddIn
    If MyLibrary is Nothing Then
        For Each addin In Application.COMAddIns
            If InStr(addin.Description, "MyLibrary.COMHelper") Then
                If addin.object Is Nothing Then
                    'complain it can't connect to library, tell user to reinstall it
                Else
                    Set MyLibrary = addin.object
                Exit For
            End If
        Next
    End if
End Sub
Run Code Online (Sandbox Code Playgroud)

Re:Excel Interop和.NET库 - 好点Mat's Mug,使用普通的Microsoft.Office.Interop.Excel时这可能是一场噩梦.因为您正在从托管.NET环境访问本机代码,所以您必须确保正确清理.NET COM包装器对象,或者即使在关闭Excel后它也会出现挂起/僵尸进程,它看起来已经消失了/关闭(查看任务管理器,他们可能仍然在那里!)

我发现处理此问题的最佳方法是使用NetOffice,它基本上是Excel互操作模型的克隆,但是为了安全地管理所有这些问题而创建.最好还要注意COM对象的良好安全处理,例如此处此处.

祝好运!


Cha*_*ams 7

如果使用密码保存工作簿以作为XLSB打开(请注意,请勿保护工作簿结构等),工作簿将使用合理安全的加密进行加密(在Excel 2013中更强).
但是用户必须提供密码才能打开它,这不适合某些使用场景.

所有其他形式的Excel保护相对较弱.

最好使用C++ XLL在Excel中保护代码.
接下来最好是一个VB6 DLL(但现在这是一个死技术,不能在64位Excel中工作)
下一个最好是混淆.NET,但你真的需要使用Addin Express提供的那种.NET XLL接口或XL DNA,以避免.NET Interop和VSTO的糟糕性能特征.

  • 我编辑了我的答案以澄清我的意思是VB6 DLL在64位Excel中不起作用 (2认同)