用SmartAssembly也很久了,之前用着也是一知半解地随意用用,从来没有深入研究过,到底能使用到哪种程度,心里也没有底。
今天索性再过一遍,记录下来,以供大家一起参考学习。也算是快乐助人。
逐个抠字不易,尊重版权,转载请注明出处,谢谢。
https://www.cnblogs.com/honk/p/12719171.html
程序的主要模块
Selected Software
选择软件
打开项目并配置混淆加密输出的文件名
建议您使用原始文件名,并将程序集存储在与原始文件不同的文件夹中。经过测试,这里保存出去的文件名未来会影响到程序集的命名空间。
Strong Name Signing
强命名
关于强命名的概念由于篇幅有限,就不多做介绍,主要介绍功能。
使用强名称密钥对程序集进行签名可以保护程序集的名称,并防止修改程序集。
此功能可以创建一个新的或使用旧的SNK密钥来进行程序集签名。
选项:
我不要签名我的程序集
我要使用强名称对程序集进行签名。
我要添加防篡改。
建议:
在SmartAssembly Professional和Developer版本中,您可以启用其他完整性检查以提供增强的保护。为此,选择我要添加防篡改。启用防篡改功能可使程序集的加载速度稍慢。强烈建议您启用防篡改功能,同时启用字符串编码。
解决强名称密钥签名问题:
如果您具有未签名的依赖项(没有强名称的依赖项)并且主程序集已签名,则CLR可能会拒绝加载该依赖项。出于安全原因这样做。为此原因:
如果编写了DLL,则也需要对其进行签名。
如果它是第三方DLL,则需要请求DLL的签名版本。
Automated Error Reporting
自动错误报告
您可以修改软件,以使其自动拦截未处理的异常并向您报告详细信息。
要报告异常,请在"项目设置"窗口中,转到" 自动错误报告"或单击工具栏中的图标。
选择我要在应用程序中报告错误。
选择要使用的模板。
完成申请名称,公司名称和项目名称。
如果您希望应用程序在发生异常后继续运行,请选择始终继续。
确定是否选择" 提高性能"。
Feature Usage Reporting
功能统计报告
1.将功能使用情况报告添加到代码中
将ReportUsageAttribute或ReportUsageAttribute(string)添加到方法或构造函数
使用以下命令将功能使用情况报告添加到代码中ReportUsageAttribute:
在Visual Studio中,添加对%ProgramFiles%\ Red Gate \ SmartAssembly 6 \ SDK \ bin \ SmartAssembly.ReportUsage.dll的引用
添加ReportUsageAttribute 到您感兴趣的方法或构造函数。
如有必要,请在功能使用报告中提供一个字符串以命名功能:
对于构造函数,必须提供一个字符串。
对于方法,默认情况下,方法名称用于功能名称;您可以根据ReportUsageAttribute(string)需要提供其他名称。
添加ReportUsageAttribute到应用程序首次启动时调用的方法。
这样可确保在启动时出现要求用户允许参与功能使用情况报告的对话框。
将UsageCounter.ReportUsage添加到您的代码中
要在运行时命名功能,或报告不是方法或构造函数的功能的使用情况,请执行以下操作:
在Visual Studio中,添加对%ProgramFiles%\ Red Gate \ SmartAssembly 6 \ SDK \ bin \ SmartAssembly.ReportUsage.dll的引用
UsageCounter.ReportUsage(string) 在要报告功能的位置添加到代码中,并提供将用于功能名称的字符串。
可以在运行时创建该字符串。但是,请确保该字符串不是唯一的;太多不同的功能名称将减慢功能使用情况报告的下载。
2.在SmartAssembly中启用功能使用情况报告
要启用功能使用情况报告:
要报告功能使用情况,请在"项目设置"窗口中转到" 功能使用情况报告"或单击工具栏中的图标。
选择我希望我的应用程序报告其使用方式。
选择要使用的模板。
如果启用了错误报告,则功能使用情况报告也会使用"自动错误报告"设置中定义的应用程序名称,公司名称和项目名称:
如果未启用错误报告,请填写" 应用程序名称"," 公司名称"和" 项目名称":
启用功能使用情况报告后,工具栏图标下方和功能选项左侧的彩色条为绿色。如果禁用,则条形为橙色。
标准模板
SmartAssembly为功能使用情况报告提供了三个标准模板。
要在最终用户首次使用该应用程序时征求最终用户的同意参与功能使用情况报告,请在首次运行时选择带有同意对话框。
您可以在第二次运行时选择" 具有同意"对话框,以要求最终用户第二次使用该应用程序。如果您的应用程序具有一个安装对话框,该对话框在首次安装该程序时显示,并且您不想在首次运行时同时显示两者,这将很有用。
如果您不希望用户控制是否发送功能使用情况报告,请选择" 自动"(无对话框)。报告将自动生成并发送。
自定义模板(仅限SmartAssembly Developer和Professional)
您可以使用自定义功能报告模板来选择自定义同意对话框。您可以使用SmartAssembly SDK中提供的示例代码在Visual Studio中创建模板。有关如何创建和启用自定义模板的详细信息,请参阅SDK。
Dependencies Merging
依赖合并
依赖项合并将依赖项的代码与主程序集的代码集成在一起。合并后,依赖项与主程序集是分不开的。
您可以使用与主程序集中的代码相同的方式对合并的依赖项中的代码进行混淆和删节。
使用依赖合并
要合并依赖项,请在"项目设置"窗口中转到" 依赖项合并"或单击工具栏中的图标。
选择要合并的依赖项。要刷新列表,请单击重新扫描依赖项。
如果选择的依赖项本身具有列表中的依赖项,则会自动选择这些依赖项。
启用依赖项合并后,工具栏图标下方和功能选项左侧的彩色条为绿色。启用依赖项合并时,用于依赖项嵌入的彩色条也会变为绿色,因为相比于嵌入,首选合并。如果禁用合并,则条形为橙色。
合并前的代码:
DLL1:
internalclassInvalidDocumentContentsException:Exception
publicsealedclassDiscoveryDocument;
DLL2:
internalclassInvalidDocumentContentsException:Exception
internalclassLinkGrep
MainExe:
publicsealedclassDiscoveryClientResult
internalstructCallId
合并后的代码:
MainExe:
publicsealedclassDiscoveryClientResult
internalstructCallId
internalclassInvalidDocumentContentsException:Exception
internalsealedclassDiscoveryDocument
internalclassInvalidDocumentContentsException:Exception
internalclassLinkGrep
Dependencies Embedding
依赖嵌入
嵌入依赖关系可简化软件的部署和维护,减小软件的总大小,并确保依赖关系始终可用。
使用依赖项嵌入
要嵌入依赖项,请在"项目设置"窗口中转到" 依赖项嵌入"或单击工具栏中的图标。
选择要嵌入的依赖项。要刷新列表,请单击重新扫描依赖项。
启用依赖项嵌入后,工具栏图标下方和功能选项左侧的彩色条为绿色。如果禁用,则条形为橙色。
依赖项的压缩和加密
启用依赖项嵌入后,您还可以选择压缩和/或加密嵌入的依赖项。单击列表中每个依赖项旁边的 图标,以选择是压缩还是加密该依赖项。
嵌入前
DLL1:
internalclassInvalidDocumentContentsException:Exception
publicsealedclassDiscoveryDocument
DLL2:
internalclassInvalidDocumentContentsException:Exception
internalclassLinkGrep
MainExe:
publicsealedclassDiscoveryClientResult
internalstructCallId
嵌入后
MainExe:
publicsealedclassDiscoveryClientResult
internalstructCallId
Resource1(containing compressed/encoded contents ofDLL1)
Resource2(containing compressed/encoded contents ofDLL2)
合并和嵌入之间有什么区别?
合并
当您将依赖项与主程序集合并时,两个程序集中的代码将合并为一个程序集。结果程序集不包含对依赖项的引用。呼叫不再是公用的(按名称),而是内部的(按成员ID),这提供了更好的保护并且更加快捷。
您可以通过以常规方式混淆整个程序集来保护合并的依赖项。
嵌入
嵌入依赖项时,它将存储在主程序集中。您也可以选择压缩和加密依赖项的内容。如果嵌入依赖关系,则不会修改主部件。
在运行时,第一次需要DLL时,将对其进行解密和解压缩(如果适用),然后创建程序集并将其加载到内存中。嵌入式程序集会保留其标识和完整性。
要保护依赖关系,请先将其保护在单独的SmartAssembly项目中,然后嵌入经过混淆的DLL。
其实这两个选项都是可选项,不一定适用所有程序。至少我开发几个ASP.NET就无法进行合并和嵌入。
Pruning
裁剪
裁剪会删除永远不会在运行时执行的代码。裁剪还删除元数据,例如设计属性以及事件和属性的名称。
裁剪可减少装配体的尺寸,并改善加载时间和性能。删除无用的元数据可以使代码更难理解,从而可以保护您的代码。
SmartAssembly不会裁剪DLL文件的公共成员,因为会导致DLL将无法使用。
实测这个功能比较鸡肋,它会裁剪掉一些"它"认为无用的代码,但实际上会真实调用的,比如SQL查询、反射和AOP。
所以能不用,尽量不要用!否则,指不定你程序的某个功能就会出现???的错误,根本无法定位。
裁剪前
[DefaultMember("Item")]
publicsealedclassDiscoveryClientResultCollection:CollectionBase
[XmlRoot("discovery",Namespace="http://schemas.xmlsoap.org/disco/")]
publicsealedclassDiscoveryDocument
publicclassDiscoveryDocumentLinksPattern:DiscoverySearchPattern
[XmlRoot("discoveryRef",Namespace="http://schemas.xmlsoap.org/disco/")]
publicsealedclassDiscoveryDocumentReference:DiscoveryReference
publicsealedclassDiscoveryDocumentSearchPattern:DiscoverySearchPattern
internalTraceMethod(objecttarget,stringname,paramsobject[]args);
internalstaticstringCallString(objecttarget,stringmethod,paramsobject[]args);
privatestaticstringHashString(objectobjectValue);
internalstaticstringMethodId(objecttarget,stringmethod);
publicoverridestringToString();
privatestaticvoidWriteObjectId(StringBuildersb,objecto);
privatestaticvoidWriteValue(StringBuildersb,objecto);
裁剪后
[DefaultMember("Item")]
publicsealedclassDiscoveryClientResultCollection:CollectionBase
publicsealedclassDiscoveryDocumentSearchPattern:DiscoverySearchPattern
internalTraceMethod(object1,string1,paramsobject[]strings);
privatestaticstringHashString(object1);
internalstaticstringMethodId(object1,string1);
Obfuscation
混淆
名称处理将类和方法的名称更改为不可读的字符,使您的代码更难以理解。SmartAssembly自动检测不可混淆的代码或元数据。
通过更改类型,方法和字段的名称使您的代码更难理解。
最主要的功能之一了,这个选项必选。
这里主要注意以下三点:
SmartAssembly不会混淆DLL文件的公共类名称或者公共成员(字段、属性、方法),因为混淆后会导致DLL将无法使用。
当使用ASCII字符名称修饰混淆程序集时,SmartAssembly不会在不同程序集之间重用混淆的类型和方法名称。
如果不同类中的方法具有相同的方法名称,则可能必须使用 高级重命名来混淆那些方法名称。
类型/方法名称修改选项
ASCII characters | ASCII字符 | 使用ASCII字符重命名类型和方法。例如,类型FullScreenSplash被混淆为#dc。 |
Unicode unprintable characters | Unicode不可打印字符 | 使用Unicode不可打印字符重命名类型和方法。例如,类型FullScreenSplash被混淆为U + 1D11E(不可打印)。 |
Unicode unprintable characters and advanced renaming algorithm | Unicode不可打印字符和高级重命名算法 | 使用Unicode不可打印字符重命名类型和方法,并重命名具有相同名称的多个项目。例如,类型FullScreenSplash和FontStyle都被混淆为U + 017D。 |
字段名称修改选项
One-to-one renaming scheme | 一对一重命名方案 | 更改所有类中的所有字段,使其具有不同的名称。字段名称在部件中是唯一的。 以与选定类型/方法名称重整相同的样式进行混淆。 |
Standard renaming | 标准重命名 | 更改字段名称,使其在一个类中是唯一的,但是该名称通常在程序集中的其他类中使用。例如,#A:字符串,#B:布尔,#C:字符串,#D:布尔。 以与选定类型/方法名称重整相同的样式进行混淆。 |
Advanced renaming | 高级重命名 | 更改字段名称,但是它在类中不是唯一的,并且可以重用。不同类型的字段将具有相同的名称。例如,#a:string,#a:boolean,#b:string,#b:boolean。 以与选定类型/方法名称重整相同的样式进行混淆。 |
父级方法混淆
方法父混淆将方法移动到程序集中的其他类型,这使得很难发现它们属于哪个类。
请注意,方法父级混淆可能不适用于某些类型的程序集。
混淆前:
publicClientLicenceGetLicence(ItemTypetype);
publicboolIsFileInProject(stringfileName);
publicvoidResolveAssemblyReferences();
publicvoidSave();
privatevoidSetMemento(Propertiesmemento);
publicvoidStart(boolwithDebugging);
privatevoidStartBuild(ProjectBuildOptionsbuildOptions,IBuildFeedbackSinkfeedbackSink);
混淆后:
无法显示无法打印的字符。就本示例而言,不可打印字符用星号(*)表示。
public.*(.);
publicbool*(string);
publicvoid*();
publicvoid*();
privatevoid*(.);
publicvoid*(bool);
privatevoid*(.,.);
Control Flow Obfuscation
控制流混淆
控制混淆会更改方法中的代码,并将其转换为"spaghetti code"。
要使用控制流模糊处理,请在"项目设置"窗口中转到" 控制流模糊处理"或单击工具栏中的图标。
选择控制流混淆的级别:
(None) | (没有) | 选择是否不想应用控制流模糊化,或者使用属性来管理控制流模糊化。请参阅使用自定义属性。 |
Basic | 基本的 | 简单的混淆。 |
Strictly valid. Supports Mono | 严格有效。支持Mono | 严格遵守.NET IL可验证性规则,并与Mono兼容。 |
Strongest | 最强 | 最大程度的混淆。可能会违反IL的规则,并且无法在Mono上运行。 |
Unverifiable | 无法验证 | 从方法中删除局部变量。此选项提供了增强的混淆级别,但是它使用了无法验证的代码。 |
无论选择哪种设置,都可以通过使用[ObfuscateControlFlow]属性将"最强"级别应用于任何方法。要从"控制流模糊处理"中排除某种方法,请使用[DoNotObfuscateControlFlow]属性。有关更多信息,请参见自定义属性。
References Dynamic Proxy
引用动态代理
引用动态代理会从程序集中隐藏外部调用的最终目标。
如果在程序集外部进行调用,则在对字符串进行编码和控制流混淆之后,这些调用在代码中仍将可见。例如,如果调用消息框,即使启用了字符串编码和控件混淆,仍然可以在反汇编的应用程序中找到该调用。通过这样的外部调用,其他人仍然有可能理解您的代码部分。
要解决此问题,可以使用SmartAssembly在运行时创建代理。此代理使您很难理解代码,因为所有外部调用似乎都发送给了代理,而不是发送给最终接收到它的外部方法,属性或字段。
此功能可防止对程序集进行任何修改,因此,如果在SmartAssembly之后使用其他工具来修改程序集,则无法使用此功能。
不错的一个可用功能。
Resources Compression and Encryption
资源压缩加密
压缩代码中使用的资源可使代码更高效,而加密代码中使用的资源会使代码更难以理解。当首次需要每种资源时,这些资源会在运行时自动解压缩和解密。
请注意,此选项对嵌入式依赖关系无效:您可以使用" 依赖关系嵌入"功能设置窗格上的选项来压缩和加密嵌入式依赖关系(这是因为您可能需要禁用某些嵌入式依赖关系的加密)。有关更多信息,请参见嵌入依赖性。
使用资源压缩和加密
要压缩和加密资源,请在"项目设置"窗口中,转到" 资源压缩和加密" 或单击工具栏中的图标。
选择要压缩和加密的资源。
在以下情况下,您不能使用资源压缩和加密:
如果要使用GetManifestResourceNames. (即,获取资源名称)
对于使用任何版本的Silverlight,Windows Phone 7.x XNA,Xbox XNA或Windows Phone 7.x的程序集。
使用SQL CLR程序集。
Strings Encoding
字符串编码
托管软件将所有字符串存储在一个地方,结构清晰。这使得在反汇编程序集中查找字符串变得容易。通过遵循对这些字符串的引用,即使经过混淆,也有可能理解代码的目的。
字符串编码可以防止这种情况。
选择 "我要通过对软件中的所有字符串进行编码来隐藏重要信息"
const string 无法被编码. 你必须改为使用 static readonly string.
以下字符串编码选项可用:
I want to use strings encoding with improved protection | 我想使用具有更好保护的字符串编码 | 防止装配修改。如果在SmartAssembly之后使用其他工具修改程序集,则不能使用此功能。您不能将此组件用于使用任何版本的Silverlight,Windows Phone 7.x XNA,Xbox XNA或Windows Phone 7.x的组件,也不能与SQL CLR组件一起使用。 |
I want to compress and encrypt the encoded strings | 我想压缩和加密编码的字符串 | 增强保护并减小装配尺寸。您不能对使用Xbox XNA的程序集或SQL CLR程序集使用此选项。 |
I want my application to cache strings when decoded | 我希望我的应用程序在解码时缓存字符串 | 使字符串可以快速加载。您可以将此选项与SmartAssembly支持的所有技术一起使用。 |
必要时,在运行时会自动解码字符串。
编码前:
"Fred.gate@hotmail.com"
"p@ssw0rd1"
"licensingUrl=http://licensing.red-gate.com/licensingactivation.asmx"
编码后:
"FNRFk1TTJZM016VTPQ==.bmV1dSBzcGVjaWZpZWQ9sbGVjdGlvbi4=L"
对枚举使用字符串编码
请注意,通常会混淆枚举,但是您不希望在用户界面中显示混淆的枚举值。SmartAssembly假设已是枚举值Format,GetName,GetNames,Parse,或ToString要求他们将显示给用户,所以这些枚举从混淆自动排除。
如果您的代码以其他方式使用枚举,则可以从混淆中排除所有枚举:
关闭SmartAssembly
使用XML编辑器打开SmartAssembly项目的* .saproj文件
在该<Options> 部分中,添加以下元素:
<DoNotObfuscateAnyEnums/>保存* .saproj文件,然后在SmartAssembly中重新打开该项目。
MSIL Disassembler Protection
MSIL反汇编保护
SmartAssembly可以向您的程序集添加一个属性,以防止Microsoft的通用中间语言(IL)反汇编程序(ildasm.exe)打开您的程序集。
DLL中使用这个功能没用(反编译打开后还是能看到部分逻辑的),只有exe中才能起到保护作用(反汇编无法打开任何代码)。
other optimizations
减少未使用和私有类的内存分配
不继承的加密类
SmartAssembly可以保护未继承的类。
I want to automatically seal classes whenever possible.
我希望尽可能的自动保护类
I want to reduce unused allocated memory.
我希望降低未使用的已分配内存
Generate Debugging Information
生成调试信息
生成.pdb文件使您可以在IDE中调试生成的程序集。
无论是否选择此选项,工具栏图标下方和功能选项左侧的彩色条始终为绿色。
您可以通过选择我要混淆.pdb 文件中的文档的URL来混淆记录在.pdb文件中的源代码的文件路径。
注意:如果需要在IDE中调试程序集,则不能使用此选项(因为IDE将无法找到源代码)。
有关调试和.pdb文件的更多信息
如果您依靠错误报告功能来调试应用程序,则无需生成.pdb文件。
如果您仍想使用堆栈跟踪来调试程序集,建议您生成.pdb文件。
如果混淆文档的URL(源文件名和路径),则.pdb文件中不会存储任何关键信息。这使您可以在应用程序中分发.pdb文件,从而在堆栈跟踪中添加源行号。
如果希望能够在调试器中使用断点来调试程序集,建议您不要混淆文档的URL。
SmartAssembly还允许您为受保护的程序集生成一个新的.pdb文件。
ASP.NET中使用SmartAssembly
ASP.NET网站可以根据需要在服务器上动态编译,但是SmartAssembly只能保护预编译的.NET程序集。这使得不清楚如何使用SmartAssembly保护网站。
如果您项目中有使用SmartAssembly error reporting的功能,则必须分别保护所有dll,因为合并和嵌入可能会破坏错误报告功能。
要在ASP.NET中实现SmartAssembly保护和错误报告:
1. 在Web项目中添加对%ProgramFiles%\Red Gate\Smartassembly 6\SDK\bin\SmartAssembly.ReportException.dll 的引用 。
2. 在记事本或Visual Studio中打开 Global.asax (Global.aspx.cs)代码隐藏文件。
3. 如果 protected void Application_Error(Object sender, EventArgs e) 方法不存在,请创建它。
该方法应包含以下几行:
Exception exc = Server.GetLastError().GetBaseException();
SmartAssembly.ReportException.ExceptionReporting.Report(exc);
4. 保存Global.asax.cs (or vb)
5. 编译并生成web项目文件
6. 设置与依赖DLL相关的错误报告,但不要合并或嵌入依赖关系。
7. 将所有不是DLL的文件从原始编译的网站复制到刚创建的网站:
xcopy c:\mynewwebsite c:\mynewSAwebsite /E /EXCLUDE:\bin\
8. 现在,已编译并受保护的网站位于 c:\mynewSAwebsite 文件夹中。将该文件夹配置为IIS Web应用程序,以使其对网站的用户可用。
高级开发
自定义混淆或加密属性:
您可以使用自定义属性来专门从混淆,修剪,密封和错误报告中排除部分代码。
要定义属性,请执行以下任一操作:
在Visual Studio中,添加对项目中SmartAssembly.Attributes.dll(位于%ProgramFiles%\ SmartAssembly 6 \ Attributes文件夹中)的引用。
源代码文件添加到您的项目(SmartAssembly.Attributes.cs对于C#项目,或SmartAssembly.Attributes.vb了VB.NET项目)。
这两个文件都位于Smartassembly \ attributes文件夹中。如果选择此选项,则可以更改名称空间以匹配您自己的名称空间,从而简化了这些属性的使用。
DoNotObfuscate | Excludes the member from obfuscation. Can be added to assembly, class, delegate, enum, field, interface, method, module, and struct. |
DoNotObfuscateType | Excludes the type definition, as well as all the type's members from obfuscation. Can be added to any type (class, enum, interface, and struct). |
DoNotPrune | Excludes the type definition from pruning. Can be added to any type (class, enum, interface, and struct). |
DoNotPruneType | Excludes the type definition, as well as all type's members, from pruning. Can be added to any type (class, enum, interface, and struct). |
DoNotSealType | Does not seal the type. This overrides the option to automatically seal all possible classes. Can be added to any type (class, enum, interface, and struct). |
ObfuscateControlFlow | This overrides the control flow obfuscation level set in the SmartAssembly project. When you add this attribute to your assembly, you can set an alternative obfuscation level for 'flagged methods' (methods with the attribute) in the SmartAssembly user interface. Can be added to any class, method, and struct. |
DoNotObfuscateControlFlow | Does not apply Control Flow Obfuscation. Can be added to any class, method, and struct. |
StayPublic | When SmartAssembly obfuscates some members, they may become internal. This can stop other applications from post-processing the obfuscated code. Apply the StayPublicAttribute to ensure that the member remains public after obfuscation. Can be added to any class, enum, and interface. |
ForceObfuscate | Forces element to be obfuscated, even if it was excluded by safety mechanisms. Takes precedence over DoNotObfuscate attribute! Has an optional useHashAsName parameter. If true, uses MD5 hash of a method name prefixed with _. Otherwise, uses default Name Mangling setting. Can be added to any property, field, class, method, and struct. |
Attributes for Automatic error reporting
ReportException | Reports any unhandled exception, which occurs in this method. This is useful for DLLs because it saves you catching exceptions yourself and passing the exceptions to SmartAssembly. Can be added to any method. |
DoNotCapture | When added to any type (class, enum, interface, or struct), prevents that type's fields from being included in error reports. When added to a field, prevents that field from being included in error reports. |
DoNotCaptureVariables | Prevents variables from being included in error reports. Can be added to any method. |