eazfuscator.net documentation · visual studio 2005 – 2017 including express editions supports...
TRANSCRIPT
-
5.8
https://www.gapotchenko.com/eazfuscator.net
-
Eazfuscator.NETDocumentationCopyright©2017Gapotchenko
TableofContents
WhatIsEazfuscator.NET?
-
1.IntroductionDefinitionofObfuscationWhy.NETApplicationsNeedObfuscation
InTheoryInPractice
WhentoUseObfuscationDrawbacksofTheObfuscation
-
2.QuickStart
-
3.HowDoesEazfuscator.NETWork?ObfuscationTechniques
SymbolRenamingStringEncryptionConstantLiteralsPruningOverloadInductionClassHierarchyLinerizationXMLDocumentationFilterXAMLRenaming
OptimizationTechniquesMergingofStringLiteralDuplicatesSealingofTerminalClassesStringCompressionCodeOptimizations
-
4.AdvancedFeaturesAboutAdvancedFeaturesDeclarativeObfuscationUsingCustomAttributes
System.Reflection.ObfuscateAssemblyAttributeSystem.Reflection.ObfuscationAttribute.NETCompactFramework,Silverlight,WindowsStoreand.NETCoreProjectsIndirectDeclarativeObfuscationObfuscationAttributePriorities
ConditionalObfuscationTypeMembersOptionsareCombinableDiagnostics
SymbolNamesEncryptionAdvancedSymbolRenamingOptions
SymbolRenamingwithPrintableCharactersTypeRenamingPatterns
AdvancedStringEncryptionOptionsCodeControlFlowObfuscationAssembliesMerging
IntroductionInstructionsTuningInternalizationCustomParametersforMerging
AssembliesEmbeddingIntroductionWhat'sthepointforembeddingwhenwehavemerging(orviceversa)?InstructionsTuningTroubleshooting
ResourceEncryption
-
IntroductionInstructionsCompressionSelectiveResourceEncryptionOptionsareCombinable
SerializationTuningOverviewBinarySerializationandObfuscationSelf-InteroperabilityNon-stableSelf-InteroperableSerializationStableSelf-InteroperableSerialization
DebuggingIntroductiontoDebuggingAfterObfuscationHowItWorksPossibleSecurityRisksTuningDebugRenaming
PEVerifyIntegrationProbingPaths
AboutProbingPathsHowtoDefineProbingPaths?
ScriptVariables
-
5.SenseiFeaturesAboutSenseiFeaturesCodeInliningProtectedPrivateVisibilityCustomAttributesRemovalDesign-TimeUsageProtection
OverviewHowItWorksInstructionsTuning
ResourceSanitizationIntroductionInstructionsMinificationSelectiveResourceSanitizationOptionsareCombinable
-
6.VirtualizationIntroductionHowtoUseCodeVirtualizationHowtoUseDataVirtualization
-
7.TroubleshootingMyapplicationisnotworkingproperlyafterobfuscation.Whydoesithappen?TroubleshootingFeatures
StackTraceDecodingInspection-FriendlyObfuscation
PreservingtheOriginalNamesDisablingILDASMSuppression
AboutInternalsVisibleToAttributeSolution#1.DonotuseInternalsVisibleToAttributeatallSolution#2.SwapwithEditorBrowsableattributeSolution#3.HidethewarningSolution#4.Ignoretheattribute
"OptionStrictOff"CompatibilityforVB.NETIntroductionCompatibilityModeInstructions
NonintrusiveDebuggingIntroductionSampleScenario
WarningsandErrorsDisablingWarningsTreatWarningsasErrors
Long-TermCompatibilityCompatibilityVersionDemandingtheSpecificVersionofEazfuscator.NET
ErrorCodesKnowledgeBaseEF-1099:Unabletoloadinputassembly,reflectionloadfailedEF-3035:Assemblyorpartofitisalreadyobfuscated
-
8.BestPracticesIntroductionGeneralBestPracticesKeepingtheBalance
HumanFactorsKeepingItSimple
TheParalysisofSimplicity
-
9.DeploymentAboutEazfuscator.NETDeploymentMicrosoftInstaller(MSI)NuGetPackageManagerCommandLineInterface
GlossaryBibliography
-
5.8
https://www.gapotchenko.com/eazfuscator.net
-
WhatIsEazfuscator.NET?
Eazfuscator.NETisanobfuscatorandoptimizerfor.NETplatform.
Themainpurposeofobfuscatoristoprotectintellectualpropertyofthesoftware.
Keyfeatures:
Easytouseas1-2-3AutomaticcodeprotectionwithvarietyofsupportedobfuscationtechniquesAutomaticoptimizationsCanobfuscateany100%managed.NETassemblyProvideseasytouseGUIinterfaceaswellasclassicalcommandlineinterfaceMicrosoftVisualStudiointegration.SupportedversionsareMicrosoftVisualStudio2005–2017includingExpresseditionsSupportsautomaticbuilds
Supportedplatformsandtechnologies:
.NETFrameworkversions2.0 – 4.7XAMLwithintelligentrenamingofsymbolsEnterprise-gradetechnologies:ClickOnce,VSTO,VSIX,MEF,EntityFramework,ASP.NETandmanyothers.NETStandardversions1.0 – 2.0.NETCoreversions1.0 – 2.0UniversalWindowsPlatform(UWP)WindowsStoreapplicationsforWindows8 – 8.1andWindowsPhone7 – 8.1platformsSilverlight2 – 5XNAapplicationsforWindows,Xbox360andZuneplatforms.NETCompactFrameworkversions2.0and3.5
WhyEazfuscator.NETsooutstandingamongothers?
-
Toprotectyourintellectualpropertyyouneedtoperformjustseveralmouseclicks–donotwasteyourprecioushourstomanuallyenterallthecomplexsettingsandmakekilling-harddecisionsasyoudowiththemostotherobfuscatorsEazfuscator.NEThasasitsobjecttoautomaticallyprotectintellectualpropertytothemaximumpossibleextentbutwithoutbreaking.NETassemblyfunctionalityEazfuscator.NETappliescodeoptimizationstodeliverthebestperformancetoyourapplications.Furthemore,Eazfuscator.NETisbuilttodeliverthebestruntimeperformancefromgroundup.Itdoesnotusedirtytricks,hacksandincompatibletechniquesthatbreakapplicationreliability,performanceandsatisfactionofyourcustomers.Thehistoryofobfuscationtechnologyknowsthescore:
EverysingleobfuscatorbeforeEazfuscator.NETrequiredalotofmanualconfiguration,tuningandintegrationefforts.EverysingleobfuscatorafterEazfuscator.NETtendstoclaimitdoesnearlyeverythingoutofthebox.
Howtouseit?
SeeQuickStartguide.
-
5.8
https://www.gapotchenko.com/eazfuscator.net
-
Chapter1.Introduction
TableofContents
DefinitionofObfuscationWhy.NETApplicationsNeedObfuscation
InTheoryInPractice
WhentoUseObfuscationDrawbacksofTheObfuscation
-
DefinitionofObfuscation
Obfuscatedcodeisacodethatis(usuallyintentionally)veryhardtoreadandunderstand.Someprogramminglanguagesandtechnologiesaremorepronetoobfuscationthanothers.
Therearealsoprogramsknownasobfuscatorsthatmayoperateonsourcecode,objectcode,orboth,forthepurposeofdeterringreverseengineering.
Obfuscatingcodetopreventreverseengineeringistypicallydonetomanagerisksthatstemfromunauthorizedaccesstosourcecode.Theserisksincludelossofintellectualproperty,easeofprobingforapplicationvulnerabilitiesandlossofrevenuethatcanresultwhenapplicationsarereverseengineered,modifiedtocircumventmeteringorusagecontrolandthenrecompiled.Obfuscatingcodeis,therefore,alsoacompensatingcontroltomanagetheserisks.TheriskisgreaterincomputingenvironmentssuchasJavaandMicrosoft's.NETwhichtakeadvantageof"Just-in-Time"(JIT)compilationtechnologythatallowdeveloperstodeployanapplicationasintermediatecoderatherthancodewhichhasbeencompiledintonativemachinelanguagebeforebeingdeployed.[WikiObCode]
Eazfuscator.NETisanobfuscatorthatoperateson.NETobjectcodeentitledasCIL.
-
5.8
https://www.gapotchenko.com/eazfuscator.net
-
Why.NETApplicationsNeedObfuscation
InTheory
TraditionallyapplicationswerecompiledtothenativecodeofthetargetCPU.Duringthistranslationalltheinformationaboutthesourcecodewaslost.Howeveritisstillpossibletoinfertheprogramoperationusingdebuggingandhackingtoolsbutit'sdifficult,time-consumingandveryexpensivecraft.
Incontrast,.NETapplicationsarecompiledtotheCILcode.CILcodecontainsalotofadditionalmetadatawhichallowstoachievebetterinteroperabilityandrobustnessoftheapplication.ButCILmetadataallowstoinferprogramoperationmucheasieratthesametime.Usingspeciallydesignedtoolssuchasdecompilersitisevenpossibletoretrievesourcecodeofthe.NETapplication.Sowhen.NETapplicationpublishedwithoutbeingobfuscateditisequivalenttoreleasingitssourcecodewithallpainfulconsequences.
ObfuscationremovesredundantCILmetadataandscramblesandencryptstherest.Soafterobfuscationitismuchhardertodiginintoobfuscated.NETapplication.Howeveritisstillpossibletoinfertheprogramoperationusingspeciallydesignedtoolsbutitisdifficult,time-consumingandexpensivenowjustasincaseofthenativecode.
InPractice
Let'sperformsomepracticaljobtoundercoverthewayyour.NETapplicationcanbedecompiled.Firstofall,weneedsomesampleapplicationtodigin.Letmeintroduceoneofsuperstarapplicationswithambitioustitle"MyPreciousIdea"asasample.IshouldadmitthatthisapplicationisbasedontheMike'sGoldportofthevintage"SpaceInvaders"game.ThisC#applicationwascompiledinReleaseconfigurationwithMicrosoftVisualStudio.Hereisthelookofsampleapplicationwhenitisrunning:
-
Reallynice,isn'tit?Todecompiletheapplicationwewilluse.NETReflectortool.Thenjustopen"MyPreciousIdea.exe"filewith.NETReflector.Hereiswhatcanbeseenafteropening:
https://www.gapotchenko.com/go/reflector
-
Asyoucanseeinthescreenshotabove,allapplicationsourcescanbeeasilyobtainedjustwithseveralmouseclicks!Ifyourproductisnotobfuscatedthenhackershaveahugepossibilitiestotamperwithproductfeatures.Unsavorycompetitorsmayevencopy&pastepartsofyourcodeforuseintheirownproducts.
-
5.8
https://www.gapotchenko.com/eazfuscator.net
-
WhentoUseObfuscation
Youmayuseobfuscationinfreeware,sharewareoranykindofcommercialsoftwarewhenyouwanttoprotectyourintellectualproperty.
Obfuscationofopensourcesoftwarehasnosensebecauseapplicationsourcecodeisalwaysavailable.
-
5.8
https://www.gapotchenko.com/eazfuscator.net
-
DrawbacksofTheObfuscation
Exceptionstacktracesinobfuscatedassemblieswillcontainobfuscatedsymbolnamesinsteadofrealsymbolnames.Thisfactmakesdifficulttoresolvepossibleapplicationissues.Howeveritiseasytoovercomethisproblembyusingstacktracedecodingfeature.Obfuscatormaybreakassemblyfunctionalityincaseofusageofreflectiontechniquesintheobfuscatedapplication.HoweverEazfuscator.NETtriestominimizesuchfailuresbyheuristicdetectionofreflectionusagepatternsandthoroughlyanalyzinganassemblyitembeforeapplyinganyobfuscationtransformationstoit.Butbecauseofheuristicnatureofanalysisitisnot100%reliable.
Moreinformationaboutpossibleproblemsandtheirsolutionscanbefoundatthechapterabouttroubleshooting.
-
5.8
https://www.gapotchenko.com/eazfuscator.net
-
Chapter2.QuickStart
Areyoureadytoprotectyourintellectualproperty?Nowitisassimpleasneverwasbefore.
Firstofall,downloadandinstallEazfuscator.NET.IfyouinstallEazfuscator.NETforthefirsttimethenit'shighlyrecommendedtorestartVisualStudioifitwasrunningduringinstallation.
Then,launchEazfuscator.NETAssistantfromVisualStudiomenu.Todothat,gotoTools→Eazfuscator.NETAssistantmenuitemandclick:
Suchfloatingwindowwillappear:
https://www.gapotchenko.com/eazfuscator.net/download
-
Asyoucansee,thewindowaboveconsistsoftwomainzones—greenandred.Greenzoneisresponsibleforprotectionandredzoneisresponsibleforprotectionremoval.Wheneveryouwanttoprotecttheprojectyoucandraganddropittothegreenzone.
Afteryoudroptheprojectontoprotectionzonetheprogresswindowwillappear.Thiswindowisshownatthepicturebelow.Youshouldcloseitwhenprotectioniscompleted.
-
WhenyoureturntoVisualStudioitwillaskyoutoreloadmodifiedproject.ClickReloadbutton.
Onceprotectionhadbeenappliedtotheproject,itwillbeobfuscatedduringeverybuildinReleaseconfiguration.
That'sall!
Nextyoumayfindusefultoreadthechapteraboutthebestpractices.
Note
-
QuickStartguidecoversjustthemostcommonusagepattern.
-
5.8
https://www.gapotchenko.com/eazfuscator.net
-
Chapter3.HowDoesEazfuscator.NETWork?
TableofContents
ObfuscationTechniquesSymbolRenamingStringEncryptionConstantLiteralsPruningOverloadInductionClassHierarchyLinerizationXMLDocumentationFilterXAMLRenaming
OptimizationTechniquesMergingofStringLiteralDuplicatesSealingofTerminalClassesStringCompressionCodeOptimizations
-
ObfuscationTechniques
Eazfuscator.NETworksontheCILlevelsoany100%managed.NETassemblycanbeobfuscated.Automaticobfuscationofsatelliteassembliesisfullysupported.AssemblieswithembeddednativecodearenotsupportedbyEazfuscator.NET.ObfuscatedassembliesproducedbyEazfuscator.NETcanworkonalternative.NETruntimeimplementationssuchasMono.
Eazfuscator.NETusesseveraltechniquestoobfuscatethecode.
Eazfuscator.NETautomaticallyselectsappropriateobfuscationmethodsforeveryitemin.NETassembly.NotalltheitemscanbeobfuscatedwithoutbreakingassemblyfunctionalityandsoEazfuscator.NETthoroughlyanalyzesanitembeforeapplyingobfuscationtransformationstoit.Eazfuscator.NEThasasitsobjecttoprotectintellectualpropertytothemaximumpossibleextentbutwithoutbreakingassemblyfunctionality.IfintellectualpropertysafetyisendangeredthenEazfuscator.NETproducesawarningmessagebutalmostneveroverobfuscatesatcostofbreakingassemblyfunctionality.
Let'soverviewmainobfuscationtechniquesusedbyEazfuscator.NET.
SymbolRenaming
Symbolrenamingisthemostpowerfulobfuscationmethod.Classes,methods,properties,fieldsandmethod'sparametersgetrenamedwitharandomlygeneratedorencryptedtitlewheneveritisapplicable.NewnameusuallyconsistsofunprintableorchaoticUnicodecharacters.
Example3.1.Sourcecoderetrievedwithdecompilerbeforesymbolrenaming
classMainForm{…privatebool_UseStartupShutdownEffects;privatebool_FadeDirection;privatebool_LargeFadeStep;privateSystem.Windows.Forms.Timer_OpacityTimer;…
https://www.gapotchenko.com/go/mono
-
privatevoidMainForm_Load(objectsender,EventArgse){if(this.DesignMode)return;this.Icon=Icon.ExtractAssociatedIcon(Assembly.GetEntryAssembly().Location);
if(this._UseStartupShutdownEffects){this.Opacity=0;this._FadeDirection=true;this._LargeFadeStep=true;this._OpacityTimer.Start();}else{Application.DoEvents();Pointpoint1=this.Location;this.Location=newPoint(Int32.MinValue,Int32.MinValue);this.Show();Application.DoEvents();this.Location=point1;}}…}
Example3.2.Sourcecoderetrievedwithdecompileraftersymbolrenaming
class {…privatebool ;privatebool ;privatebool ;privateSystem.Windows.Forms.Timer ;…privatevoid (object ,EventArgs ){if(this.DesignMode)return;this.Icon=Icon.ExtractAssociatedIcon(Assembly.GetEntryAssembly().Location);
if(this. )
-
{this.Opacity=0;this. =true;this. =true;this. .Start();}else{Application.DoEvents();Pointpoint1=this.Location;this.Location=newPoint(Int32.MinValue,Int32.MinValue);this.Show();Application.DoEvents();this.Location=point1;}}…}
Thereareadvancedoptionsavailableforsymbolrenamingfeature.
StringEncryption
Stringisoneofthemostwidelyuseddatatypeinapplications.Atthesametime,unencryptedstringvaluesallowtoeasilyinfertheprogramoperationwithanextremebrutality.Toavoidthat,everystringvaluegetsencryptedduringobfuscation.
Example3.3.Sourcecoderetrievedwithdecompilerbeforestringencryption
classLicenseManager{…internalboolCanRun(){if(LicenseContainer.Get("License").IsValidFor(_CurrentCustomer))returntrue;elsereturnfalse;}
-
…}
Example3.4.Sourcecoderetrievedwithdecompilerafterstringencryption
classLicenseManager{…internalboolCanRun(){if(LicenseContainer.Get( . (-2942637)).IsValidFor(_CurrentCustomer))returntrue;elsereturnfalse;}…}
Thereareadvancedoptionsavailableforstringencryptionfeature.
ConstantLiteralsPruning
Constantliteralspruningremovesredundantmetainformationfromtheobfuscated.NETassemblywheneveritispossible.Thisinformationisoftennotnecessaryattheruntime,anditisusefulatcompiletimeonly.Howeveritspresenceinthecompiledassemblycanleadtoadditionalweaknessfordecompilation.
Example3.5.Sourcecoderetrievedwithdecompilerbeforeconstantliteralspruning
classLicenseManager{…publicenumDecision{Allow,Deny,
-
UnrestrictedDeveloperMode,Lock}internalDecisionMakeDecision(){if(CanRun())returnDecision.Allow;if(IsDeveloperSite())returnDecision.UnrestrictedDeveloperMode;intint1=UnlicensedRunCount;if(int1>MaxUnlicensedRunCount)returnDecision.Lock;int1++;UnlicensedRunCount=int1;returnDecision.Deny;}…}
Example3.6.Sourcecoderetrievedwithdecompilerafterconstantliteralspruning
classLicenseManager{…publicenumDecision{}internalDecisionMakeDecision(){if(CanRun())return0;if(IsDeveloperSite())return2;intint1=UnlicensedRunCount;if(int1>MaxUnlicensedRunCount)return3;int1++;UnlicensedRunCount=int1;return1;}
-
…}
OverloadInduction
Overloadinductionisacomplementaryobfuscationmethodtosymbolrenamingtechnique.Formally,overloadinductionalgorithmminimizesthenumberofuniquesymbolnamesintheobfuscatedassembly.Asaresult,obfuscatedclasses,fields,propertiesandmethodsmayhavethesamenameaslongasitdoesn'tviolatesymbolresolutionrulesusedby.NETruntime.Suchsymbolnamessamenessmakespryingintruderabsolutelyentangled.
Example3.7.Sourcecoderetrievedwithdecompilerbeforesymbolrenamingusingoverloadinduction
classMainForm{…privatebool_UseStartupShutdownEffects;privatebool_FadeDirection;privatebool_LargeFadeStep;privateSystem.Windows.Forms.Timer_OpacityTimer;…privatevoidMainForm_Load(objectsender,EventArgse){if(this.DesignMode)return;this.Icon=Icon.ExtractAssociatedIcon(Assembly.GetEntryAssembly().Location);
if(this._UseStartupShutdownEffects){this.Opacity=0;this._FadeDirection=true;this._LargeFadeStep=true;this._OpacityTimer.Start();}else{Application.DoEvents();Pointpoint1=this.Location;
-
this.Location=newPoint(Int32.MinValue,Int32.MinValue);this.Show();Application.DoEvents();this.Location=point1;}}privateintCalculateSize(){returnthis.Width*2/3;}…}
Example3.8.Sourcecoderetrievedwithdecompileraftersymbolrenamingusingoverloadinduction
Note
Inthislistingunprintablecharactersinsymbolnameswerereplacedwithvisibleones(A,B,C,…)toshowupnames'uniquenessdistribution.
classA{…privateboolA;privateboolB;privateboolC;privateSystem.Windows.Forms.TimerD;…privatevoidA(objectA,EventArgsB){if(this.DesignMode)return;this.Icon=Icon.ExtractAssociatedIcon(Assembly.GetEntryAssembly().Location);
if(this.A){
-
this.Opacity=0;this.B=true;this.C=true;this.D.Start();}else{Application.DoEvents();Pointpoint1=this.Location;this.Location=newPoint(Int32.MinValue,Int32.MinValue);this.Show();Application.DoEvents();this.Location=point1;}}
privateintA(){returnthis.Width*2/3;}…}
ClassHierarchyLinerization
Classhierarchylinearizationisacomplementaryobfuscationmethodtosymbolrenamingtechnique.Thismethodisappliedtotheclassnamesonly.Duringobfuscationalltheinformationaboutclassnamespacesisirreversiblydestroyedwhenit'spossible.Aftertheobfuscation,allobfuscatedclassesarelinearlylocatedatthelargerootnamespace,soalltheinformationaboutclassaffiliationwithapplication'ssubsystemsispruned.
Example3.9.Sourcecoderetrievedwithdecompilerbeforesymbolrenamingusingclasshierarchylinearization
namespaceMyPreciousIdea{namespaceLicensing{classLicense
-
{…}
classManager{…}}
namespaceUI{classMainForm{…}classSettingsForm{…}
classLicensingForm{…}}
…}
Example3.10.Sourcecoderetrievedwithdecompileraftersymbolrenamingusingclasshierarchylinearization
class {…}
class {…}
-
class {…}class {…}
class {…}
…
XMLDocumentationFilter
Some.NETlanguagesprovideaneasywaytoautomaticallycreateXMLdocumentationforprojects.YoucanautomaticallygenerateanXMLskeletonforyourtypesandmembers,andthenprovidesummaries,descriptivedocumentationforeachparameter,andotherremarks.Withtheappropriatesetup,theXMLdocumentationisautomaticallyemittedintoanXMLfilewiththesamenameasyourprojectandthe.xmlextension.Thisfileislocatedinthesamedirectoryastheoutput.exeor.dllfileofyourproject.
EverythingseemsgooduntilitisdiscoveredthatXMLdocumentationfilecontainsdescriptionsnotonlyforpubliclyvisibleclassesandmembers,butforprivateitemstoo.
Eazfuscator.NETstopsthatthreatbyinstantlyapplyingXMLdocumentationfilteroneveryobfuscationrun.XMLdocumentationforallnon-publicclasses,methods,fields,propertiesandeventsisautomaticallyprunedsothatessentialknowledgeaboutcomponentinternalsdoesnotleaktotherestoftheworldanymore.Thisfeatureisessentialforcomponentdevelopersandpublishers.
XAMLRenaming
-
XAMLmarkuplanguageisusedbyWPF,Silverlight,WindowsStoreapplicationstodefineelements,events,databindingsandotheraspectsofuserinterface.XAMLrenamingistheprocessofsimultaneousrenamingofrelatedsymbolsincodeandXAMLduringobfuscation.
Eazfuscator.NETfindsallconnectionsbetweenXAMLandcode:
Then,therelatedsymbolsgetrenamed.SynchronouslyandconsistentlyincodeandXAML:
-
Asaresult,XAMLrenamingdelivershigherobfuscationcoverageandensuresthatallrelateditemsareaccordinglyandcorrectlyprocessedinXAMLandcode.
-
5.8
https://www.gapotchenko.com/eazfuscator.net
-
OptimizationTechniques
Eazfuscator.NETperformsseveralcodeandmetadataoptimizationsduringobfuscation.
MergingofStringLiteralDuplicates
Mergingofstringliteralduplicatesisacomplementaryoptimizationmethodtostringencryptionobfuscationtechnique.Formally,thisoptimizationensuresthatallencryptedstringvaluesareuniqueinone.NETassembly.Suchkindofoptimizationalsowidelyknownasstringpooling.
Example3.11.Hypotheticalstringtablebeforeencryption
StringValuesAbracadabraSiamFooAbracadabraFooBar
Example3.12.Hypotheticalstringtableafterencryptionwithduplicatesmerging
OriginalStringValues EncryptedStringValuesAbracadabra }S£tP)€_9€[]Siam @!€NayfI*Foo !>@"buY]Bar E)€a£J
SealingofTerminalClasses
-
Sealedclassisaspeciallymarkedclasswhichcannotbeinherited..NETruntimeusesaknowledgeaboutsuchclassestoperformanoptimizationonvirtualmethodcalls,suchoptimizationhasconsiderableimpactonoverallapplicationperformance.ThereforeEazfuscator.NETanalyzestheclassesof.NETassemblyandmarksallnotinheritableonesassealedwhenitispossible.However,thisoptimizationdoesnotenhanceobfuscation;informationaboutclassinheritancecanbeusedbyahackerasanadditionalinformationtoinfertheprogramoperation.Butinthiscasetheriskislowerthanperformancebenefits.
Example3.13.Sourcecoderetrievedwithdecompilerbeforesealingofterminalclasses
classShape{…}
classCircle:Shape{…}
Example3.14.Sourcecoderetrievedwithdecompileraftersealingofterminalclasses
classShape{…}
sealedclassCircle:Shape{…}
StringCompression
-
Stringcompressionisanautomaticsizeoptimizationwhichresultsinsmallerassemblies.Largestringsarecompressedduringobfuscation.Thecompressedstringsareuncompressedondemandduringtheruntime.Thedecompressionalgorithmisincrediblyfast,sothereisnoperformancepenaltyobserved—theactualdecompressionspeedcomesveryclosetothespeedofasimplememorycopy.
Stringcompressionisapartofstringencryptiontechniqueandisonbydefault.
CodeOptimizations
Eazfuscator.NETappliescodeoptimizationstodeliverthebestperformancetoyourapplications..NETcompilerssuchasC#,VB.NETandJITalreadydoaprettydecentjobinthisarea.Butwhattheyalldonotdoishigh-leveloptimizations.
High-leveloptimizationisafreshtrendinoptimizationtechnologyandEazfuscator.NETestablishesitselfasthefirsttooltodeliverthistechnologytothewide.NETuserbase.Thebestwaytobrieflydescribehigh-leveloptimizationistostartthinkingasdeveloperthinks:weallknowthattherearesomemethodsandcodepatternswhicharefasterthanothers.WhatEazfuscator.NETdoesisthis:itfindstheslowcodeandswapsitwithfasterone.Eazfuscator.NETusesapreciouslybrewedknowledgebaseofcommonandefficientcodepatternsthatyoucanmeetinevery.NETapplication.
Atfirstglance,high-leveloptimizationisverysimilartoawell-knownpeepholeoptimizationapproach.Butthemaindifferenceisthattheclassicalpeepholeoptimizationworksonlyonasmallwindowoftargetmachineinstructions,whilehigh-leveloptimizationworksattheapplication-widelevelandconsiderscontrolanddataflowsaswellasthesacredknowledgeaboutspecificframeworkssuchasLINQ,MEFandothers.
Let'stakealookatexample.
Example3.15.Theslowcode
[Flags]enumRunOptions{None=0x00,
-
PrepareDatabase=0x01,SkipPlugins=0x02}
classEngine{publicvoidRun(RunOptionsoptions){if(options.HasFlag(RunOptions.PrepareDatabase))InitializeDatabase();…}
…}
ThecodeaboveusesEnum.HasFlagmethodtocheckwhetherPrepareDatabaseflagisset.Beingsweetinsyntax,thecodehasastonishinglybadperformanceduetoboxingoperationsthatareinvisilblygeneratedbyC#compiler.
Example3.16.Thefastcode.ProducedbyEazfuscator.NETafteroptimizingtheslowcode
publicvoidRun(RunOptionsoptions){if((options&RunOptions.PrepareDatabase)==RunOptions.PrepareDatabase)InitializeDatabase();…}
Asyoucansee,Eazfuscator.NETemittedfunctionallyequivalentcode.Theresultofoptimizationis500xspeedimprovementofconditionevaluationoveroriginalslowcode.
Theoptimizerisonbydefaultandworksbehindthescenesduringobfuscation.
Togetinformationaboutadvancedobfuscationalgorithmspleasereadthenextchapter.
-
5.8
https://www.gapotchenko.com/eazfuscator.net
-
Chapter4.AdvancedFeatures
TableofContents
AboutAdvancedFeaturesDeclarativeObfuscationUsingCustomAttributes
System.Reflection.ObfuscateAssemblyAttributeSystem.Reflection.ObfuscationAttribute.NETCompactFramework,Silverlight,WindowsStoreand.NETCoreProjectsIndirectDeclarativeObfuscationObfuscationAttributePriorities
ConditionalObfuscationTypeMembersOptionsareCombinableDiagnostics
SymbolNamesEncryptionAdvancedSymbolRenamingOptions
SymbolRenamingwithPrintableCharactersTypeRenamingPatterns
AdvancedStringEncryptionOptionsCodeControlFlowObfuscationAssembliesMerging
IntroductionInstructionsTuningInternalizationCustomParametersforMerging
AssembliesEmbeddingIntroductionWhat'sthepointforembeddingwhenwehavemerging(orviceversa)?InstructionsTuning
-
TroubleshootingResourceEncryption
IntroductionInstructionsCompressionSelectiveResourceEncryptionOptionsareCombinable
SerializationTuningOverviewBinarySerializationandObfuscationSelf-InteroperabilityNon-stableSelf-InteroperableSerializationStableSelf-InteroperableSerialization
DebuggingIntroductiontoDebuggingAfterObfuscationHowItWorksPossibleSecurityRisksTuningDebugRenaming
PEVerifyIntegrationProbingPaths
AboutProbingPathsHowtoDefineProbingPaths?
ScriptVariables
-
AboutAdvancedFeatures
Youmaywanttogetmorecontrolonobfuscationprocesswhenyoubecomemorefamilarwithobfuscation.AdvancedfeaturesofEazfuscator.NETallowyoutoachievethis.
Tostartwithadvancedfeaturesitisrecommendedtoreadaboutdeclarativeobfuscation.
-
5.8
https://www.gapotchenko.com/eazfuscator.net
-
DeclarativeObfuscationUsingCustomAttributes
The.NETFrameworksinceversion2.0providestwocustomattributesdesignedtomakeiteasytochangeobfuscationbehavior.UsingthesetwoattributesitispossibletooverridedefaultdecisionsmadebyEazfuscator.NETduringobfuscation.AlsotheseattributescanbeusedtoconfigureadvancedEazfuscator.NETfeatures.Itisassumedthatyouhaveaknowledgeaboutcustomattributesandhowtoapplytheminyourdevelopmentlanguage.
System.Reflection.ObfuscateAssemblyAttribute
Thisattributecanbeappliedtoanassemblytotellobfuscatorhowtotreatit.SettingtheAssemblyIsPrivatepropertytofalsetellsobfuscatortotreatanassemblyasalibrary.SettingtheAssemblyIsPrivatepropertytotruetellsobfuscatortotreatanassemblyasanexecutable.ThedifferenceishowEazfuscator.NETrenamesandsealspublictypesandtheirpublicmembers.Incaseofanexecutableallpublictypesandtheirpublicmembersareconsideredterminalsotheygetsrenamed.Incaseofalibrary,thosetypesandmembersmaybeusedbyotherassemblies,thustheydonotgetrenamed.
Thedefaultobfuscatorbehavioristotreatall.dllassembliesaslibrariesandall.exeand.comassembliesasexecutables.Iftheassemblyhasanotherfileextension(nor.dllneither.exe/.com)thenEazfuscator.NETtreatssuchassembliesdependingontheentrypointpresence.Iftheassemblyhastheentrypointthenitistreatedasanexecutable,otherwiseitistreatedasalibrary.
System.Reflection.ObfuscationAttribute
Thisattributeisthemaintroubleshooterofthereflectionrelatedproblemsthatmayoccurduringobfuscation.AsitwasmentionedaboveEazfuscator.NEThasnoformalreflectionscenariosanalysisengineanditusesheuristicalgorithmsinstead.DecisionsproducedbythosealgorithmsmaybewronginsomerarecasessoyoumayneedtooverridethembyusingSystem.Reflection.ObfuscationAttribute
System.Reflection.ObfuscationAttributecanbeappliedtoatype.Possiblefeaturepropertyvaluesare"all"(bydefault),"renaming"and"properties
-
renaming".Soifyouwanttodisablerenamingofyourclassyoumaywritesomethinglikeanexamplebelow(C#):
Example4.1.Disablingclassrenaming
[System.Reflection.ObfuscationAttribute(Feature="renaming",ApplyToMembers=false)]classMyOneThousandAndFirstClass{…}
Ifyouwanttodisablerenamingofyourclassandallitsmembersyoumaywrite:
Example4.2.Disablingclassanditsmembersrenaming
[System.Reflection.ObfuscationAttribute(Feature="renaming",ApplyToMembers=true)]classMyOneThousandAndSecondClass{…}
Ifyouwanttodisablerenamingofthepropertiesinyourclassyoumaywrite:
Example4.3.Disablingclasspropertiesrenaming
[System.Reflection.ObfuscationAttribute(Feature="propertiesrenaming")]classMyOneThousandAndThirdClass{…}
Sometimesitmaybeusefultodisablejustsingleorseveralpropertiesinaclass.Inordertodothatyoumaywrite:
Example4.4.Disablingsingleclasspropertyrenaming
classMyOneThousandAndFourthClass
-
{[System.Reflection.ObfuscationAttribute(Feature="renaming")]publicstringDisplayName{get;set;}}
Insomerarecasesyoumaywanttodisabletherenamingofpropertiesforanonymoustypes.Inordertodothat,youshouldapplythefollowingattributeattheassemblylevel:
Example4.5.Disablingtherenamingofanonymoustypeproperties
usingSystem.Reflection;
[assembly:Obfuscation(Feature="anonymoustypepropertiesrenaming",Exclude=true)]
AnotherapplianceofSystem.Reflection.ObfuscationAttributeistoconfigureEazfuscator.NETfeatures.Youmayfindmoreinformationaboutthisatthefollowingplaces:
AdvancedsymbolrenamingoptionsAdvancedstringencryptionoptionsCodecontrolflowobfuscationAssembliesmergingAssembliesembeddingResourceencryptionDebugging
.NETCompactFramework,Silverlight,WindowsStoreand.NETCoreProjects
-
TherearenoSystem.Reflection.ObfuscateAssemblyAttributeandSystem.Reflection.ObfuscationAttributeattributesavailablein.NETCompactFramework,SilverlightandWinRTruntimes.Soifyouwanttousedeclarativeobfuscationyoumustdefinecorrespondingattributesinyourassembly.Theeasiestwaytodothisistoaddready-to-usefileObfuscationAttributes.cs(forC#)orObfuscationAttributes.vb(forVB.NET)toyourproject.ThesefilescanbefoundatStartMenu→Eazfuscator.NET→Eazfuscator.NETCodeSnippetsmenuitem.AlternativelytheycanbefoundatC:\ProgramFiles\Eazfuscator.NET\CodeSnippetspath.
Note
Thepathmaydifferdependingontheinstallationoptionsandoperatingsystem.Forexample,thispathmaylooklikeC:\ProgramFiles(x86)\Eazfuscator.NET\CodeSnippetson64-bitoperatingsystems.
IndirectDeclarativeObfuscation
Sometimesitmaynotbepossibletoaccesstheclassdefinitiondirectlytoapplyacustomattributeforobfuscationtuning.Iflatteristhecasethenindirectdeclarativeobfuscationcomestotherescue.Itallowstoindirectlytunetheobfuscationbyusingcustomattributesdefinedattheassemblylevel.
Let'stakeacloserlookonanexample.SupposethereisaclassMyNamespace.ResourceClass1anditsdeclarationcannotbechangedbecauseitwasautomaticallygeneratedbyatool.Sohowtodisabletherenamingofthatclassduringobfuscation?Thesolutionistouseindirectdeclarativeobfuscation.Inordertodothat,youshouldapplythefollowingattributeattheassemblylevel(C#):
Example4.6.Indirectlydisabletherenamingofaclass
usingSystem.Reflection;
[assembly:Obfuscation(Feature="ApplytotypeMyNamespace.ResourceClass1:renaming",Exclude=true,ApplyToMembers=false)]
-
Pleasenote,thefeaturestringstartswith"Applytotype"expressioninthesampleabove.ThatexpressionsignalsEazfuscator.NETthatfeatureshouldberedirectedtoMyNamespace.ResourceClass1class.Thereisasemicolonaftertheclassname;justnexttoit,thereisarealfeaturename"renaming".So,theabovesamplecodeisvirtuallyequivalenttothecodeshownbelow(C#):
namespaceMyNamespace{[System.Reflection.ObfuscationAttribute(Feature="renaming",Exclude=true,ApplyToMembers=false)]classResourceClass1{…}}
Theclassnameinindirectexpressioncancontainmaskcharacterssuchas*and?,sooneindirectexpressioncanmatchseveralclasses.*standsforseveralanycharacters,?standsforanycharacter.
Asforexample,it'spossibletodisableallobfuscationfeaturesforallclassesinsideagivennamespace.Thefollowingattributeshouldbeappliedattheassemblylevelinordertodothat(C#):
Example4.7.Indirectlydisableallobfuscationfeaturesforagivennamespace
usingSystem.Reflection;
[assembly:Obfuscation(Feature="ApplytotypeSomeExcludedNamespace.*:all",Exclude=true,ApplyToMembers=true)]
Amorepowerfulconfigurationsyntaxisavailableinconditionalobfuscation.
ObfuscationAttributePriorities
-
Introduction
Sometimesyoumaywanttodefineobfuscationattributesinseveralplaces.
Forexample,thegivenassemblymaybeconfiguredbytwofiles.Onefile,ObfuscationSettings.cs,definestheobfuscationdirectivesdirectlyrelatedtothegivenassembly.Anotherfile,CommonObfuscationSettings.cs,definestheobfuscationdirectivescommontoallobfuscatedassembliesinawholeproject.Thatfileissharedamongallobfuscatedassembliesinaproject.
Thenyoudecidethatstringencryptionisnotneededformostassemblies,soyoujustdisableitatthecommonlevelinCommonObfuscationSettings.csfile:
[assembly:Obfuscation(Feature="stringencryption",Exclude=true)]
Sometimeafter,itturnsoutthataparticularassemblyContosoEngine.dllshouldhavestringencryptionenabled.ObfuscationSettings.csfiledefinedinContosoEngineassemblylookslikethis:
[assembly:Obfuscation(Feature="stringencryption",Exclude=false)]
PleasenotethatbothObfuscationSettings.csandCommonObfuscationSettings.csfilesareincludedincompilationofContosoEngineassemblyassourcecodefiles.SobothdirectivesfindtheirwaysintoresultingcompiledContosoEngine.dllfile.
WhathappenswhenEazfuscator.NETseesconflictingobfuscationdirectivesininputassembly?Theexactsemanticsdependsonadirective.Eazfuscator.NETmayjusttaketheleastpermissivedirectiveforfeatureslikestringencryption.Anotherstrategyistotaketheveryfirstdirectiveandabandontherest(notethatC#andmanyother.NETcompilersdonotguaranteetheorderofcustomattributesinresultingcompiledassembly).Neverthelessthisisnotwhatyouwantwhenitcomestoseveralconfigurationsourceswhereyouwanttohavepriorities.E.g.directivesdefinedinObfuscationSettings.csfileshouldhavehigherprioritythanthosedefinedinCommonObfuscationSettings.csfile.
Sohowtoachievetheprioritizationofobfuscationattributes?Justfollow
-
prioritysyntaxdescribedbelow.
PrioritySyntax
Priorityisdefinedbyanumericprefix:
[Obfuscation(Feature="1.")]
Theideabehindpriorityprefixesistoformanaturallist:
[Obfuscation(Feature="1.")][Obfuscation(Feature="2.")][Obfuscation(Feature="3.")]
wherethefirstitemhasthehighestpriority,thesecondislessimportantandsoon.JustlikeyourtypicalTODOlist.
Note
Priorityprefixcanonlycontainanaturalnumber(apositiveinteger).Zeroandnegativeprioritiesarenotallowed.
CompleteExample
Sohereishowtheaforementionedconfigurationfilesshouldbedefinedtomaketheprioritizationworkaccordingtothetaskdescribedinintroduction.ThecontentofCommonObfuscationSettings.csfile:
[assembly:Obfuscation(Feature="2.stringencryption",Exclude=true)]
ThecontentofObfuscationSettings.csfileforContosoEngineassembly:
[assembly:Obfuscation(Feature="1.stringencryption",Exclude=false)]
-
5.8
https://www.gapotchenko.com/eazfuscator.net
-
ConditionalObfuscation
Conditionalobfuscationisanextensionfeaturetoindirectdeclarativeobfuscation.Conditionalobfuscationallowstoprocessthetypesinabulkaccordingtotheirnaturalpropertiessuchasvisibility(public,internal,protected,private),subtype(class,struct,enum,delegate)andothers.
Thisfunctionalityisachievedbywhenconditionalclausewhichcanbespecifiedinanobfuscationattribute.Sothefullconditionalattributenotationhasthefollowingform:
[assembly:Obfuscation(Feature="Applytotype[namemask]when[condition]:[feature]")]
where[condition]isastringdefiningtheconditionforamatch.
ConditionisdefinedasabooleanpredicatewithPascalsyntax.Quickexampleofanconditionalattributeisshownbelow.
Example4.8.Indirectlydisablerenamingofallinternalenumsandtheirmembers
usingSystem.Reflection;
[assembly:Obfuscation(Feature="Applytotype*wheninternalandenum:renaming",Exclude=true,ApplyToMembers=true)]
Pleasetakeacloserlookatinternalandenumpredicateinthesampleabove.Whatitsaysisthis:theresultofpredicateistruewheninternalvariableequalstotrueandenumvariableequalstotruetoo;otherwisetheresultofpredicateisfalse.Thevaluesofinternalandenumvariablesarecalculatedforeverytypeintheassembly,describingthenaturalpropertiesofaCLRtypeinbooleanform.
Thelistofavailablevariablesispresentedinthetablebelow.
Table4.1.Thelistofavailablevariablesforconditionalobfuscationoftypes
-
Variable Descriptionabstract trueifthetypeisabstract;otherwise,false
anonymous trueifthetypeisanonymous;otherwise,falseclass trueifthetypeisaclass;otherwise,falsedelegate trueifthetypeisadelegate;otherwise,falseenum trueifthetypeisanenumeration;otherwise,falsegeneric trueifthetypeisgeneric;otherwise,falseinterface trueifthetypeisaninterface;otherwise,falseinternal trueifthetypeisinternal;otherwise,falsenested trueifthetypeisnested;otherwise,false
private trueifthetypeisprivate;otherwise,false.Appliestonestedtypesonly;falseifthetypeisnotnested
protected trueifthetypeisprotected;otherwise,false.Appliestonestedtypesonly;falseifthetypeisnotnestedpublic trueifthetypeispublic;otherwise,falsesealed trueifthetypeissealed;otherwise,falseserializable trueifthetypeisserializable;otherwise,falsestatic trueifthetypeisstatic;otherwise,falsestruct trueifthetypeisastructure;otherwise,false
Predefinedconstantscanbeusedinexpressionsaswell.Thelistofavailableconstantsispresentedinthetablebelow.
Table4.2.Thelistofavailableconstantsforconditionalobfuscation
Constant Descriptionfalse falsevaluetrue truevalue
Built-infunctionscanbeusedinexpressionstoo.Thelistofavailablefunctionsispresentedinthetablebelow.
-
Table4.3.Built-infunctionsforconditionalobfuscation
Function Description
inherits('type_name')
Returnstrueifthetypeinheritsanothertypespecifiedbyparameter;otherwise,false.Inheritsfunctionconsidersbaseandallinheritedtypesincludinginterfaces.Typenameparametercancontaineitherthefulltypenameoramaskforabulkmatch
extends('type_name')
Returnstrueifthetypeextendsanothertypespecifiedbyparameter;otherwise,false.Extendsfunctiononlychecksthebasetype,butallimplementedandinheritedinterfacesareconsidered.Typenameparametercancontaineitherthefulltypenameoramaskforabulkmatch
has_attribute('type_name')
Returnstrueifthetypeormemberhasacustomattributespecifiedbytype_nameparameter;otherwise,false.Typenameparametercancontaineitherthefulltypenameoramaskforabulkmatch.Example:has_attribute('System.ComponentModel.DisplayNameAttribute
Variables,functionsandconstantscanbecombinedbyoperators.TheyhavethestandardPascalprecedence.Thelistofavailableoperatorsispresentedinthetablebelow.
Table4.4.Thelistofavailableoperatorsforconditionalobfuscation
Operator Description Prioritynot Unaryoperatorforbooleannegation Highestand Binaryoperatorforbooleanandoperation Mediumor Binaryoperatorforbooleanoroperation Lower= Binaryoperatorforbooleanequaloperation Lowest Binaryoperatorforbooleannotequaloperation Lowest
Theprecedenceofoperationscanbechangedbyparentheses.
Let'stakealookonexamples.
-
Example4.9.Disablerenamingofalltypesexceptenums
usingSystem.Reflection;
[assembly:Obfuscation(Feature="Applytotype*whennotenum:renaming",Exclude=true)]
Example4.10.Disablerenamingofallinternalnestedandserializabletypestogetherwiththeirmembers
usingSystem.Reflection;
[assembly:Obfuscation(Feature="Applytotype*wheninternaland(nestedorserializable):renaming",Exclude=true,ApplyToMembers=true)]
Example4.11.Disablerenamingofalltypesexceptinternalnestedandserializabletypes
usingSystem.Reflection;
[assembly:Obfuscation(Feature="Applytotype*whennot(internaland(nestedorserializable)):renaming",Exclude=true)]
Example4.12.DisablerenamingofallinterfacesinContoso.Core.Servicesnamespace
usingSystem.Reflection;
[assembly:Obfuscation(Feature="ApplytotypeContoso.Core.Services.*wheninterface:renaming",Exclude=true)]
-
Example4.13.DisablerenamingofallclassesderivedfromSystem.IDisposableinterface.Renamingofmembersformatchedclassesisdisabledtoo
usingSystem.Reflection;
[assembly:Obfuscation(Feature="Applytotype*whenclassandextends('System.IDisposable'):renaming",Exclude=true,ApplyToMembers=true)]
Asyoucanseetheconditionscanhaveanycomplexityandcanbefreelydefinedtoachieveyourspecificgoals.
TypeMembers
Itwasdescribedhowtotunetheobfuscationoftypesinabulkwayinthesectionabove.Butwhatabouttypememberssuchasmethods,fields,propertiesandothers?Sometimesitmaybebeneficialtoprocesstheminabulkwaytoo.
Thedeclarativeattributeforconditionalobfuscationoftypemembershasthefollowingform:
usingSystem.Reflection;
[Obfuscation(Feature="Applytomember[namemask]when[condition]:[feature]")]classSample1{…}
[namemask]isapatternwhichselectsthemembersaccordingtotheirnames.[condition]allowstospecifyabooleanpredicatetoselectmembersaccordingtotheirproperties.Therulesareallthesameasfortypes;theonlydifferenceisasetofvariableswhichcanbeusedinabooleanpredicate.Thelistofavailablevariablesispresentedbelow.
Table4.5.Thelistofavailablevariablesforconditionalobfuscationoftypemembers
-
Variable Descriptionabstract trueifthememberisabstract;otherwise,false
const trueifthememberdefinesaliteralconstant;otherwise,false.Appliestofieldsonly;falseifthememberisnotafieldconstructor trueifthememberisaconstructor;otherwise,falseevent trueifthememberisanevent;otherwise,falsefield trueifthememberisafield;otherwise,false
generic trueifthememberisgeneric;otherwise,false.Appliestomethodsonly;falseifthememberisnotamethodinternal trueifthememberisinternal;otherwise,falsemethod trueifthememberisamethod;otherwise,falseprivate trueifthememberisprivate;otherwise,falseproperty trueifthememberisaproperty;otherwise,falseprotected trueifthememberisprotected;otherwise,falsepublic trueifthememberispublic;otherwise,false
readonlytrueifthememberisread-only;otherwise,false.Appliestofieldsandpropertiesonly;falseifthememberisneitherafieldnoraproperty
static trueifthememberisstatic;otherwise,falsevirtual trueifthememberisvirtual;otherwise,false
Theinformationonthistopicisextremelybare,solet'stakearelaxedlookonsomereal-lifesamples.
Example4.14.Disablerenamingofpublicproperties
usingSystem.Reflection;
[Obfuscation(Feature="Applytomember*whenpropertyandpublic:renaming",Exclude=true)]classImageQualityService{…}
-
Example4.15.Disablerenamingofallmethods
usingSystem.Reflection;
[Obfuscation(Feature="Applytomember*whenmethod:renaming",Exclude=true)]classCellCallEngine{…}
Example4.16.Disablerenamingofinternalfields
usingSystem.Reflection;
[Obfuscation(Feature="Applytomember*whenfieldandinternal:renaming",Exclude=true)]classContosoHeadquarters{…}
OptionsareCombinable
Conditionalobfuscationoftypesandtypememberscanbeeasilycombinedtoachievespecificgoalsinanelegantandpowerfulway.
Justtakealookatthesamplesbelow.
Example4.17.DisablerenamingofpropertyContosointypeAcme.Services
usingSystem.Reflection;
[assembly:Obfuscation(Feature="ApplytotypeAcme.Services:applytomemberContosowhenproperty:renaming",Exclude=true)]
-
Example4.18.Disablerenamingofallpublicpropertiesinalltypes
usingSystem.Reflection;
[assembly:Obfuscation(Feature="Applytotype*:applytomember*whenpublicandproperty:renaming",Exclude=true)]
Example4.19.DisablerenamingofallpublicpropertiesintypesdefinedinMyNamespace
usingSystem.Reflection;
[assembly:Obfuscation(Feature="ApplytotypeMyNamespace.*:applytomember*whenpublicandproperty:renaming",Exclude=true)]
Example4.20.Disablerenamingofallinternaleventsinallpublictypes
usingSystem.Reflection;
[assembly:Obfuscation(Feature="Applytotype*whenpublic:applytomember*wheneventandinternal:renaming",Exclude=true)]
Diagnostics
Howdoyouknowwhichclassesormembersconditionalobfuscationappliesto?
Sometimesitmaybeusefultogetthefulllistofclassesandmembersthataretargetedbyspecificconditionalobfuscationstatement.Toachievethat,youcanuselogfeatureasshownbelow:
-
Example4.21.Logallaffectedmembersofallpublicclasses
usingSystem.Reflection;
[assembly:Obfuscation(Feature="Applytotype*whenpublic:applytomember*:log")]
Note
Loggingdoesnotaffectobfuscationinanyway.ItjustdumpsthelistofitemsatEazfuscator.NET'sconsoleoutput.ToseethislistinVisualStudio,pleasetakealookatOutputWindowwithView→Output(Ctrl+W,O)rightafterobfuscation.
-
5.8
https://www.gapotchenko.com/eazfuscator.net
-
SymbolNamesEncryption
Symbolnamesencryptionisacomplementaryfeaturetosymbolrenamingtechnique.Encryptionfeatureisusefulinproductionscenarioswhenit'snecessarytoresolvepossibleissueswithyourproduct.Suchissuesareveryoftenreportedvialogfilesanderrorstacktraces.
Butasyoumightknow,symbolnamesarerenamedwithrandomlygeneratedtitlesandbecomeirreversiblylostafterobfuscation.Thismakesitnearlyimpossibletoanalyzestacktracesbecauseit'shardtoestablishacorrelationbetweenerrorstacktraceandoriginalsourcecode.Symbolnamesencryptioncanbeusedtoovercomethisproblem.Itencryptsobfuscatedsymbolnamesinsteadofrandomgeneration.
Symbolnamesencryptiontechnologyusessymmetricalcryptoalgorithmunderneath.UsedcryptoalgorithmisAESwith256bitskeystrength.Cryptographickeyforthealgorithmisderivedfromthepassword.SymbolnamesencryptionproducesprintableASCIIcharactersinencryptedsymbolnames,soerrordumpscanbeeasilytransferedwithE-mailorsomeotherkindoftextualerrorreporting.
Bydefault,symbolnamesencryptionisnotusedduringobfuscationoftheassembly.
Toenablesymbolnamesencryptionyoushouldapplyspeciallyformedattributetoyourassembly.Inordertodothatyoucanusetheinstructionsbelow.
Instructionsonenablingsymbolnamesencryption
1. OpenobfuscatableprojectinsidetheIDE2. AddnewsourcefiletotheprojectandcallitObfuscationSettings.cs(for
C#)orObfuscationSettings.vb(forVisualBasic.NET).YoumayprefertouseanothernameinsteadofObfuscationSettings.csorObfuscationSettings.vb
3. FillObfuscationSettings.cswiththefollowingcontent(C#):
usingSystem;
-
usingSystem.Reflection;
[assembly:Obfuscation(Feature="encryptsymbolnameswithpasswordXXXXXX",Exclude=false)]
ForVisualBasic.NET,fillObfuscationSettings.vbwiththefollowingcontent:
ImportsSystemImportsSystem.Reflection
Note
ChangeXXXXXXwithyourpassword.Keepthepasswordinsecret.
Passwordswithagreaterlengtharemorepreferablethanshortones.Longerpasswordshaveabetterinformationalentropythusgreatlyimprovingcryptographicstrengthoftheencrypteddata.It'ssuggestedtohaveapasswordwhichatleastconsistsof8characters.
Whensymbolnamesencryptionisenabledonyourprojectthenyouabletousestacktracedecodingfeature.
Tip
Ifyourproductorsolutionconsistsofseveralprojectsthenyoumostlikelywanttogivethemallthesameencryptionpassword.Inordertodothatglobally,youcancreateCommonObfuscationSettings.cs(or.vb)filethatissharedamongalltheprojectsinthesolution.NotethatMicrosoftVisualStudiosupportsaddingofaprojectfileasareference,soyoucanaddareferencetothesameglobalCommonObfuscationSettings.*fileinseveralprojects.Please
-
alsonote,thatareferencetoglobalCommonObfuscationSettings.*filemaybeaddedjusttooneprojectandthenjustdraganddroppedtoallotherprojects.
-
5.8
https://www.gapotchenko.com/eazfuscator.net
-
AdvancedSymbolRenamingOptions
SymbolRenamingwithPrintableCharacters
Symbolrenamingalgorithmusesunprintableunicodecharactersbydefault.ButsometimesitmaybeusefultouseprintableASCIIcharactersinstead.Inordertodothatyoucanusetheinstructionsbelow.Alternativelyyoumayusesymbolnamesencryptionforthesamepurpose.
Instructionsonenablingprintablecharactersforsymbolrenaming
1. OpenobfuscatableprojectinsidetheIDE2. AddnewsourcefiletotheprojectandcallitObfuscationSettings.cs(for
C#)orObfuscationSettings.vb(forVisualBasic.NET).YoumayprefertouseanothernameinsteadofObfuscationSettings.csorObfuscationSettings.vb
3. FillObfuscationSettings.cswiththefollowingcontent(C#):
usingSystem;usingSystem.Reflection;
[assembly:Obfuscation(Feature="renamesymbolnameswithprintablecharacters",Exclude=false)]
ForVisualBasic.NET,fillObfuscationSettings.vbwiththefollowingcontent:
ImportsSystemImportsSystem.Reflection
Note
-
Pleasenotethatprintablecharactersinsymbolnamescanbecontrolledattheassemblylevelonly.Forexample,itisimpossibletouseprintablecharactersforsomespecificclassormethod;itispossibletodothisjustforawholeassembly.
TypeRenamingPatterns
Eazfuscator.NETremovesthenamespacesofrenamedtypesbydefault.Thiscanleadtosomeissueswhenbadlywrittencodetriestogetanamespaceofanrenamedtypeviareflection.
Let'sseeonexamplewhatkindofflawedcodecansufferfromtheabsenceofnamespaces.
Example4.22.ExamplecodewhichfailswithNullReferenceExceptionwhenthegiventypehasnonamespace
boolSampleMethod(Typetype){if(type!=null&&type.Namespace.StartsWith("System.Data"))returntrue;returnfalse;}
Asyoucanseeinthesampleabove,themethodcanfailwithNullReferenceExceptionwhentype.Namespacepropertyreturnsnullindicatingthatthegiventypehasnonamespace.Thisissuecanbeeasilyfixedifyouhaveaccesstothesourcecode,butsometimestheflawedcodehasthebinaryformonly.
Toworkaroundpossibleproblems,acustomtyperenamingpatterncanbedefinedforanassembly,foratypeorforagroupoftypes.Theexamplesbelowshowthepossibledefinitions.
Example4.23.Add'b'namespacetoallrenamedtypesinassembly
usingSystem;usingSystem.Reflection;
-
[assembly:Obfuscation(Feature="typerenamingpattern'b'.*",Exclude=false)]
Example4.24.Add'b'namespacetoaclass
usingSystem;usingSystem.Reflection;
namespaceApp{[Obfuscation(Feature="typerenamingpattern'b'.*",Exclude=false)]classClass1{...}}
Example4.25.Add'b'namespacetoagroupofrenamedclasses.Allclasseswith'Impl'nameendingareaffected
usingSystem;usingSystem.Reflection;
[assembly:Obfuscation(Feature="Applytotype*Impl:typerenamingpattern'b'.*",Exclude=false)]
Tip
Ofcourseyouarefreetochooseanynamespaceinapattern.
-
5.8
https://www.gapotchenko.com/eazfuscator.net
-
AdvancedStringEncryptionOptions
Stringencryptionisatechniquewhichencryptseverystringintheassembly.Itisalwaysturnedonbydefault.
Howeverinsomesituationsyoumayprefertoturnthisfeatureoff.Inordertodothatyoucanusetheinstructionsbelow.
Instructionsondisablingstringencryption
1. OpenobfuscatableprojectinsidetheIDE2. AddnewsourcefiletotheprojectandcallitObfuscationSettings.cs(for
C#)orObfuscationSettings.vb(forVisualBasic.NET).YoumayprefertouseanothernameinsteadofObfuscationSettings.csorObfuscationSettings.vb
3. FillObfuscationSettings.cswiththefollowingcontent(C#):
usingSystem;usingSystem.Reflection;
[assembly:Obfuscation(Feature="stringencryption",Exclude=true)]
ForVisualBasic.NET,fillObfuscationSettings.vbwiththefollowingcontent:
ImportsSystemImportsSystem.Reflection
Note
Pleasenotethatstringencryptioncanbecontrolledattheassemblylevelonly.Forexample,itisimpossibletodisablestringencryptionforsomespecificclassormethod;itispossibletodothisjustforawholeassembly.
-
5.8
https://www.gapotchenko.com/eazfuscator.net
-
CodeControlFlowObfuscation
CodecontrolflowobfuscationallowstomakeILcodemoreentangled.Decompilersoftencrashonsuchcode,sothecodemaybeconsideredasmuchbetterprotected.
Bydefault,codecontrolflowobfuscationfeatureisnotusedduringobfuscationoftheassembly.
Toenablecodecontrolflowobfuscationfeatureyoushouldapplyaspeciallyformedattributetoyourassembly.Inordertodothatyoucanusetheinstructionsbelow.
Instructionsonenablingcontrolflowobfuscation
1. OpenobfuscatableprojectinsidetheIDE2. AddnewsourcefiletotheprojectandcallitObfuscationSettings.cs(for
C#)orObfuscationSettings.vb(forVisualBasic.NET).YoumayprefertouseanothernameinsteadofObfuscationSettings.csorObfuscationSettings.vb
3. FillObfuscationSettings.cswiththefollowingcontent(C#):
usingSystem;usingSystem.Reflection;
[assembly:Obfuscation(Feature="codecontrolflowobfuscation",Exclude=false)]
ForVisualBasic.NET,fillObfuscationSettings.vbwiththefollowingcontent:
ImportsSystemImportsSystem.Reflection
-
5.8
https://www.gapotchenko.com/eazfuscator.net
-
AssembliesMerging
Introduction
Assembliesmergingallowstomergeseveralassembliesintoone.Thismaybebeneficialfromthedeploymentandsecuritypointsofview.
Bydefault,assembliesmergingisnotusedduringobfuscationoftheassembly.
Instructions
Toenableassembliesmergingyoushouldapplyspeciallyformedattribute(s)toyourassembly.Inordertodothatyoucanusetheinstructionsbelow.
Instructionsonenablingassembliesmerging
1. OpenobfuscatableprojectinsidetheIDE2. AddnewsourcefiletotheprojectandcallitObfuscationSettings.cs(for
C#)orObfuscationSettings.vb(forVisualBasic.NET).YoumayprefertouseanothernameinsteadofObfuscationSettings.csorObfuscationSettings.vb
3. FillObfuscationSettings.cswiththefollowingcontent(C#):
usingSystem;usingSystem.Reflection;
[assembly:Obfuscation(Feature="mergewithXXXXXX.dll",Exclude=false)]
ForVisualBasic.NET,fillObfuscationSettings.vbwiththefollowingcontent:
ImportsSystemImportsSystem.Reflection
-
Note
ChangeXXXXXX.dllwiththefilenameoftheassemblyyouwanttomergewith.
Tip
Eazfuscator.NETautomaticallyfindstheassemblypathwhenonlythefilenameissupplied.Ifyouprefertospecifytheexactfilepathtoassemblythenyoucanusescriptvariables:
[assembly:Obfuscation(Feature=@"mergewith$(InputDir)\Lib\AssemblyToMerge.dll",Exclude=false)]
Tip
Ifyouwanttomergewithseveralassembliesthenjustaddseveralattributes:
usingSystem;usingSystem.Reflection;
[assembly:Obfuscation(Feature="mergewithAssembly1.dll",Exclude=false)][assembly:Obfuscation(Feature="mergewithAnotherAssembly2.dll",Exclude=false)]…
Note
Usageofassembliesmergingmayleadtosomesideeffectswhichmaymakeobfuscationtofail.Ifsuchisthecasethenusetheprincipleoftheleastcommondenominator–mergejustthoseassemblieswhichdonotcauseobfuscationfailure.
-
Assembliesembeddingcanbeusedinconjunctionorasanalternativetoassembliesmerging.
Tuning
Thesatelliteassembliesarenotmergedbydefault.YoumayprefertochangethatbyinstructingEazfuscator.NETtoautomaticallymergethemforyou.Inordertodothat,pleasereadthenotesbelow.
Thefullnotationofacustomattributeforassemblymerginghasthefollowingform:
[assembly:Obfuscation(Feature="mergewith[flags]XXXXXX.dll",Exclude=false)]
where[flags]isanoptionalenumerationofflagsseparatedbyspaces.
Thelistofavailableflagsispresentedinthetablebelow.
Table4.6.Thelistofflagsforassemblymergingattribute
Flag Descriptionsatellites Enablesautomaticmergingofsatelliteassemblies
internalization=auto
InstructsEazfuscator.NETtoautomaticallydecidewhichpublicmergedtypesshouldbeinternalized.Thisisthedefaultsetting.Thetypicaldecisionistointernalizeagiventype.Atthesametimethetypeinternalizationcanbeinhibited,forexample,bythefactthatsomekindsofWPFcontrolscannothaveinternalvisibility
internalization=none Disablestheinternalizationofpublicmergedtypes
internalization=full InstructsEazfuscator.NETtointernalizeallpublicmergedtypes
Let'stakealookonexamples.
-
Example4.26.Mergewithassemblyanditssatelliteassemblies
usingSystem;usingSystem.Reflection;
[assembly:Obfuscation(Feature="mergewith[satellites]XXXXXX.dll",Exclude=false)]
Example4.27.Mergewithassemblyanditssatelliteassemblies;donotinternalizepublicmergedtypes
usingSystem;usingSystem.Reflection;
[assembly:Obfuscation(Feature="mergewith[satellitesinternalization=none]XXXXXX.dll",Exclude=false)]
Internalization
Internalizationchangesthevisibilityofmergedclassesfrompublictointernal.Bydefault,classesfrommergedassembliesareautomaticallyinternalizedinordertoimproveobfuscationcoverage.
That'sfineforthemostscenariosbutsometimesyoumaywanttochangethatforsomespecificclasses.Pleasefollowtheinstructionsbelowtoachieveit.
Instructionsondisablinginternalizationforspecificclass
1. Openthesourcecodeofaclass
2. Addacustomattributeasshownbelow(C#):
usingSystem;usingSystem.Reflection;
[Obfuscation(Feature="internalization",Exclude=true)]publicclassYourClass
-
{...}
ForVisualBasic.NET:
ImportsSystemImportsSystem.Reflection
ClassYourClass...EndClass
Important
Conditionalobfuscationisnotavailableforthisfeature.
CustomParametersforMerging
Sometimesyoumayneedtopasscustomparametersforassemblymerging.Forexample,youmayprefertocontrolclassinternalizationyourselforusesometrickymergingfeature.
HistoricallyEazfuscator.NETreliedonILMergeutilityinthepast.Nowitisequippedwithitsowncompatiblemergersinceversion4.1.ThenewmergerunderstandsmostofILMergeconfigurationparametersandcanbeconfiguredintheverysameway.PleaserefertoILMergedocumentationforthelistofavailableparameters.
Instructionsonpassingcustomparameterstomerger
1. OpenobfuscatableprojectinsidetheIDE2. AddnewsourcefiletotheprojectandcallitObfuscationSettings.cs(for
C#)orObfuscationSettings.vb(forVisualBasic.NET).YoumayprefertouseanothernameinsteadofObfuscationSettings.csorObfuscationSettings.vb
3. FillObfuscationSettings.cswiththefollowingcontent(C#):
https://www.gapotchenko.com/go/ilmergehttps://www.gapotchenko.com/go/ilmerge/documentation
-
usingSystem;usingSystem.Reflection;
[assembly:Obfuscation(Feature="ilmergecustomparameters:",Exclude=false)]
ForVisualBasic.NET,fillObfuscationSettings.vbwiththefollowingcontent:
ImportsSystemImportsSystem.Reflection
Note
Changewiththeparametersyouwanttopasstomerger.Eazfuscator.NETpasses/internalize/ndebugparametersbydefaultwhennoattributedefined.Ifyoudonotwanttopassanyparameterstomergerthenchangewithnonestring.
-
5.8
https://www.gapotchenko.com/eazfuscator.net
-
AssembliesEmbedding
Introduction
Assembliesembeddingallowstoembedassembly'sdependenciesintoassemblyitself.Thismaybebeneficialfromthedeploymentandsecuritypointsofview.
Assembliesembeddingissimilartomerging.Themaindifferenceisthattheassembliesarenotmergedintosingleassemblywhentheyareembedded.Theyjustgetencryptedandpackedastheassemblyresources.Asaresult,thereisasingleassemblyattheoutputanditcontainsthepackeddependenciesatthesamefile.
What'sthepointforembeddingwhenwehavemerging(orviceversa)?
Assembliesmergingdeliversthebestperformancefortheresultingassemblies.TheycanbeNGEN'ed,theyworkinallconstrainedenvironments(WindowsPhone,CompactFrameworketc.).FilemappingsandJIT'tedcodecanbecachedbytheoperatingsystemforsuchassemblies,bringingtheblindingfastapplicationstartups.Assemblymergingdefinitelyrocks.
Theonlydownsideofmergingisthatit'snotalwayspossibletoapplyitwithoutbreakingtheapplication.Sothisisthepointwhereassembliesembeddingcomestotherescue.
Embeddedassembliesareeasygoalstoachieveandtheyworkoutofthebox.Downsides?Well,theyarepresent.EmbeddedassembliescannotbeNGEN'ed,theydonotworkinsomeconstrainedenvironments(Xbox,WindowsPhoneandCompactFramefork).Theextractionofembeddedassembliesduringtheapplicationloadisaperformancepenalty(penaltyisprettysmall,soit'sunlikelyyouareabletonoticeit).
Assembliesembeddingbringssomebenefitsaswell.Theembeddedassembliesareencrypted,sothisisasecurtyhardeningagainstthehackers.Embeddedassembliesarecompressed,bringingthesizereductionoftheresultingassembly.Andofcourseassembliesembeddingistheeasiestwaytoachievesingle-file
-
deployment,makingyourapplicationtoconsistofasingle.exe(or.dll)file.
Instructions
Toenableassembliesembeddingyoushouldapplyspeciallyformedattribute(s)toyourassembly.Inordertodothatyoucanusetheinstructionsbelow.
Instructionsonenablingassembliesembedding
1. OpenobfuscatableprojectinsidetheIDE2. AddnewsourcefiletotheprojectandcallitObfuscationSettings.cs(for
C#)orObfuscationSettings.vb(forVisualBasic.NET).YoumayprefertouseanothernameinsteadofObfuscationSettings.csorObfuscationSettings.vb
3. FillObfuscationSettings.cswiththefollowingcontent(C#):
usingSystem;usingSystem.Reflection;
[assembly:Obfuscation(Feature="embedXXXXXX.dll",Exclude=false)]
ForVisualBasic.NET,fillObfuscationSettings.vbwiththefollowingcontent:
ImportsSystemImportsSystem.Reflection
Note
ChangeXXXXXX.dllwiththefilenameoftheassemblyyouwanttoembed.
Important
-
Itisrecommendedtoobsuscatetheembeddedassemblies.
Tip
Eazfuscator.NETautomaticallyfindstheassemblypathwhenonlythefilenameissupplied.Ifyouprefertospecifytheexactfilepathtoassemblythenyoucanusescriptvariables:
[assembly:Obfuscation(Feature=@"embed$(InputDir)\Lib\AssemblyToEmbed.dll",Exclude=false)]
Tip
Ifyouwanttoembedseveralassembliesthenjustaddseveralattributes:
[assembly:Obfuscation(Feature="embedAssembly1.dll",Exclude=false)][assembly:Obfuscation(Feature="embedAnotherAssembly2.dll",Exclude=false)]…
Tuning
Embeddedassembliesarecompressedandencryptedbydefault.Youmayprefertoturnoffthecompression,encryptionorthemboth.Inordertodothat,pleasereadthenotesbelow.
Thefullnotationofacustomattributeforassemblyembeddinghasthefollowingform:
[assembly:Obfuscation(Feature="embed[flags]XXXXXX.dll",Exclude=false)]
-
where[flags]isanoptionalenumerationofflagsseparatedbyspaces.
Thelistofavailableflagsispresentedinthetablebelow.
Table4.7.Thelistofflagsforassemblyembeddingattribute
Flag Descriptionno_compress Disablesthecompressionno_encrypt Disablestheencryptionno_satellites Disablesautomaticembeddingofsatelliteassemblies
load_from_file
InstructsEazfuscator.NETtoloadtheembeddedassemblyfromfileinsteadofmemoryduringtheobfuscatedassemblyrun-time.ThiscanbeusedtopreserveameaningfulvalueofLocationpropertyfromSystem.Reflection.Assemblytype.
immediate_load
InstructsEazfuscator.NETtoloadtheembeddedassemblyimmediatelyonamodulestart.Thismayberequiredtosatisfythetechnologiesthatrelyonacustomassemblyresolutionmechanism.AnexampleofsuchtechnologyisWPFwhichusesXmlnsDefinitionAttributetolocatetheassembliesatruntime.PleasenotethatEazfuscator.NETautomaticallydetectsthemostofaffectedtechnologiesandappliestheflagautomaticallywhenrequired.
Let'stakealookonexamples.
Example4.28.Embedassemblywithoutcompressionandencryption
usingSystem;usingSystem.Reflection;
[assembly:Obfuscation(Feature="embed[no_compressno_encrypt]XXXXXX.dll",Exclude=false)]
Example4.29.Embedassemblywithoutencryption;compressionisenabled
-
usingSystem;usingSystem.Reflection;
[assembly:Obfuscation(Feature="embed[no_encrypt]XXXXXX.dll",Exclude=false)]
Example4.30.Embedassembly;compressionandencryptionareenabled
usingSystem;usingSystem.Reflection;
[assembly:Obfuscation(Feature="embedXXXXXX.dll",Exclude=false)]
Example4.31.Embedownsatelliteassemblies;compressionandencryptionareenabled
usingSystem;usingSystem.Reflection;
[assembly:Obfuscation(Feature="embedsatellites",Exclude=false)]
Troubleshooting
Whileassemblyembeddingisthemostnon-intrusivewaytolinktheassembly,somerareissuesmayoccur.Possibleissuesaredescribedinthischaptertogetherwithcorrespondingsolutionstoavoidthem.
PossibleIssue#1:LocationPropertyofSystem.Reflection.AssemblyClass
Issuesummary.LocationpropertyofSystem.Reflection.Assemblyclassisoftenusedtofindthepathsoffilesneartheassembly.Whilenotbeingacorrectsolution,thisworksformostdeploymentscenarios.
-
Whatmaygowrong?Firstofall,Locationpropertycanhaveacompletelyunexpectedvaluewhenassemblyshadowcopyingisused,thusbreakingtheintendedapplicationlogic.Secondly,Locationpropertyhasanullvaluewhenacorrespondingassemblyisembedded.
Solution.UseEscapedCodeBasepropertyinstead.Thispropertyalwayshasacorrectvalueinalldeploymentscenarios.Pleasetakealookatthesamplebelow.
usingSystem;
classProgram{staticstringGetEulaPath(){varassembly=typeof(Program).Assembly;//stringlocation=assembly.Location;//Pleasedonotusethis.Thisisaflawedapproachstringlocation=newUri(assembly.EscapedCodeBase).LocalPath;//
-
Solution.Useimmediate_loadflagfortheembeddedassembly.ThiswillinstructEazfuscator.NETtoimmediatelyloadtheassemblyatthemodulestartup.
-
5.8
https://www.gapotchenko.com/eazfuscator.net
-
ResourceEncryption
Introduction
Resourceencryptionfeatureallowstoencryptandoptionallycompresstheembeddedresourcesofanassembly.
Instructions
Toenableresourceencryptionyoushouldapplyanattributetoyourassembly.Inordertodothatyoucanusetheinstructionsbelow.
Instructionsonenablingresourceencryption
1. OpenobfuscatableprojectinsidetheIDE2. AddnewsourcefiletotheprojectandcallitObfuscationSettings.cs(for
C#)orObfuscationSettings.vb(forVisualBasic.NET).YoumayprefertouseanothernameinsteadofObfuscationSettings.csorObfuscationSettings.vb
3. FillObfuscationSettings.cswiththefollowingcontent(C#):
usingSystem;usingSystem.Reflection;
[assembly:Obfuscation(Feature="encryptresources",Exclude=false)]
ForVisualBasic.NET,fillObfuscationSettings.vbwiththefollowingcontent:
ImportsSystemImportsSystem.Reflection
Compression
-
Assemblyresourcesarenotcompressedbydefault.Ifyouwanttoachievesmallersizeofanoutputassemblythenyoumayconsidertoturnontheresourcecompression.The[compress]flagturnsonthecompressionwhenspecified,asshowninthesamplebelow.
Example4.32.Encryptandcompressallresources
usingSystem;usingSystem.Reflection;
[assembly:Obfuscation(Feature="encryptresources[compress]",Exclude=false)]
SelectiveResourceEncryption
Sometimesitmaybebeneficialtoencryptjustsomeresourceswhileleavingtheothersintact.The[exclude]flagcanbeusedinordertodothat,asshowninthesamplebelow.
Example4.33.Encryptallresourcesexcept.pngfiles
usingSystem;usingSystem.Reflection;
[assembly:Obfuscation(Feature="encryptresources",Exclude=false)][assembly:Obfuscation(Feature="encryptresources[exclude]*.png",Exclude=false)]
Itmaybeprofitabletogootherwayaroundbyexplicitlyspecifyingjustthoseresourcesthatshouldbeencrypted.Thistechniqueisshowninthesamplebelow.
Example4.34.Encryptsecret.txtandall.sqlresources;theothersareleftintact
usingSystem;usingSystem.Reflection;
[assembly:Obfuscation(Feature="encryptresourcessecret.txt",
-
Exclude=false)][assembly:Obfuscation(Feature="encryptresources*.sql",Exclude=false)]
OptionsareCombinable
Thegivenoptionscanbecombinedinafreewaygivingyouthepowertochoosethebestcombinationforperformance,securityandpossiblyobscuritytomisleadthehacker.
Ifyouarenotsurewhichcombinationtochoosethenjustgowithasimplestone:encryptallresources.
Ifyouknowwhatyouaredoingthenyoucanendupwithsomethinglikethat:
Example4.35.Advancedresourceencryptionconfiguration
usingSystem;usingSystem.Reflection;
[assembly:Obfuscation(Feature="encryptresources",Exclude=false)][assembly:Obfuscation(Feature="encryptresources[exclude]License.txt",Exclude=false)][assembly:Obfuscation(Feature="encryptresources[exclude]CommandLineOptions.txt",Exclude=false)][assembly:Obfuscation(Feature="encryptresources[compress]*.dat",Exclude=false)][assembly:Obfuscation(Feature="encryptresources[compress]*.sql",Exclude=false)]
-
5.8
https://www.gapotchenko.com/eazfuscator.net
-
SerializationTuning
Overview
Serializationcanbedefinedastheprocessofstoringthestateofanobjecttoastoragemedium.Therearetwomainkindsofserializationavailablein.NET:
XMLserializationBinaryserialization
Thischaptercoversthebinaryserialization.
Binaryserializationisoftenusedinapplicationstatepersistence,offlinecachesandremotingcommunication..NETplatformhasrichservicesthatallowtoperformbinaryserializationofobjectswithinseverallinesofcode.Allserializableclassesandstructuresaremarkedwith[Serializable](orinVB.NET)customattribute,so.NETruntimeisawareaboutserialization-abilityofeveryclassandstructure.
BinarySerializationandObfuscation
.NETserializationservicesusereflectiontoretrievethedataoftheserializableobjects.Thatmeansthatobfuscatorshouldtakesomeprecautionswhenittriestoobfuscateserializableelements.Eazfuscator.NETusesthesafestapproachbydefault—allserializableclasses,structuresandfieldsareautomaticallyexcludedfromsymbolrenaming.Thisguaranteesthatobfuscationhastheminimalimpactonapplicationfunctionalityandinteroperability.Atthesametime,thisapproachhasonedrawback—allserializableelementsaretooobviouslyvisibleduringreverseengineering.
Self-Interoperability
Sometimesabsoluteinteroperabilityofbinaryserializationisnotrequiredforanapplication.It'saverycommonsituationwhenapplicationserializesanddeserializestheobjectsbyitself,sonootherapplicationsaremeanttohaveanaccesstotheserializeddata.Iflatteristhecasethenitispossibletoimprovetheobfuscationofserializableelementsinyourapplicationbyusingself-
-
interoperableserialization.
Non-stableSelf-InteroperableSerialization
Ifserializeddatadonotleavetheboundariesoftheapplicationprocessthennon-stablebinaryserializationcanbeusedinsteadoffullyinteroperableone.Thiskindofserializationiscallednon-stablebecausethenamesofserializableelementsarechangedoneveryobfuscationoftheapplication.Technically,non-stableserializationisachievedbyenablingtherenamingofserializableelements,sotheyarenotexcludedfromsymbolrenamingprocessanymore.
Toenablenon-stableself-interoperableserializationyoushouldapplyspeciallyformedattributetoyourassembly.Inordertodothatyoucanusetheinstructionsbelow.
Instructionsonenablingnon-stableself-interoperableserialization
1. OpenobfuscatableprojectinsidetheIDE2. AddnewsourcefiletotheprojectandcallitObfuscationSettings.cs(for
C#)orObfuscationSettings.vb(forVisualBasic.NET).YoumayprefertouseanothernameinsteadofObfuscationSettings.csorObfuscationSettings.vb
3. FillObfuscationSettings.cswiththefollowingcontent(C#):
usingSystem;usingSystem.Reflection;
[assembly:Obfuscation(Feature="renameserializablesymbols",Exclude=false)]
ForVisualBasic.NET,fillObfuscationSettings.vbwiththefollowingcontent:
ImportsSystemImportsSystem.Reflection
-
StableSelf-InteroperableSerialization
Stableserializationshouldbeusedwhentheserializeddatacanleavetheboundariesoftheapplicationprocess.Thiskindofserializationiscalledstablebecausethenamesofserializableelementsstaythesamebetweentheobfuscationsoftheapplication.Someobfuscatorvendorsusethetermincrementalobfuscationwhentheywanttosaythatsymbolnamesremainthesamebetweenseveralobfuscations.Technically,stableserializationisachievedbyencryptingthenamesofserializableelementswithapassword.Theencryptionalgorithmisthesameasinsymbolnamesencryption.
Toenablestableself-interoperableserializationyoushouldapplyspeciallyformedattributetoyourassembly.Inordertodothatyoucanusetheinstructionsbelow.
Instructionsonenablingstableself-interoperableserialization
1. OpenobfuscatableprojectinsidetheIDE2. AddnewsourcefiletotheprojectandcallitObfuscationSettings.cs(for
C#)orObfuscationSettings.vb(forVisualBasic.NET).YoumayprefertouseanothernameinsteadofObfuscationSettings.csorObfuscationSettings.vb
3. FillObfuscationSettings.cswiththefollowingcontent(C#):
usingSystem;usingSystem.Reflection;
[assembly:Obfuscation(Feature="encryptserializablesymbolnameswithpassword'XXXXXX'",Exclude=false)]
ForVisualBasic.NET,fillObfuscationSettings.vbwiththefollowingcontent:
ImportsSystemImportsSystem.Reflection
-
Note
ChangeXXXXXXwithyourpassword.Keepthepasswordinsecret.
Passwordswithagreaterlengtharemorepreferablethanshortones.Longerpasswordshaveabetterinformationalentropythusgreatlyimprovingcryptographicstrengthoftheencrypteddata.It'ssuggestedtohaveapasswordwhichatleastconsistsof8characters.
Tip
Ifyouusesymbolnamesencryptionandwanttousethesamepasswordforthestableserializationthenapply"encryptserializablesymbolnameswithpassword"insteadof"encryptserializablesymbolnameswithpassword'XXXXXX'"tokenatthecustomattributeshownabove.
-
5.8
https://www.gapotchenko.com/eazfuscator.net
-
Debugging
IntroductiontoDebuggingAfterObfuscation
AssemblycanbeeasilydebuggedinDebugprojectconfigurationwhennoobfuscationtakesplace.
ButyoumaywanttodebugyourassemblyinReleaseconfigurationwhenobfuscationdoestakeplace.Therearenotmuchreasonstodoso,howeversometimesitmaybealife-saver.That'swhydebuggingafterobfuscationissupportedbyEazfuscator.NET.
ThedebuggingfeatureofEazfuscator.NETisturnedoffbydefaulttoallowfasterbuildsandbetteroptimizations.Ifyouwanttoenabledebuggingthenpleasefollowtheinstructionsbelow:
Instructionsonenablingdebugsupportforanoutputassembly
1. OpenobfuscatableprojectinsidetheIDE2. AddnewsourcefiletotheprojectandcallitObfuscationSettings.cs(for
C#)orObfuscationSettings.vb(forVisualBasic.NET).YoumayprefertouseanothernameinsteadofObfuscationSettings.csorObfuscationSettings.vb
3. FillObfuscationSettings.cswiththefollowingcontent(C#):
usingSystem;usingSystem.Reflection;
[assembly:Obfuscation(Feature="debug",Exclude=false)]
ForVisualBasic.NET,fillObfuscationSettings.vbwiththefollowingcontent:
ImportsSystemImportsSystem.Reflection
-
Note
Debuggingexperiencemayslightlysufferifusedtogetherwithcodecontrolflowobfuscationfeature.
HowItWorks
Eazfuscator.NETchangesassemblycontentsduringobfuscation,sothedebugginginformationgetsoutofsyncwhennospecialprovisionsaremade.Iftheinputassemblycontainsanapplied"debug"attributethatwasdiscussedabovethenEazfuscator.NETtakescareofdebugginginformationandtransformsitaccordingtotheappliedassemblychanges.That'swhythedebuginformationisalwaysinsyncwhendebugsupportisonforagivenassembly.
Thedebuginformationisstoredin.pdbfilewhichislocatedneartheassembly.Forexample,MyAssembly.dllmayhaveacorrespondingMyAssembly.pdbfile.Whenyoustartadebugsessionthedebuggertriestofindthe.pdbfilesforallloadedassemblies.Iftheright.pdbfileisfoundthenyouareabletosetbreakpointsandwatchvariablesindebugger.
PossibleSecurityRisks
.pdbfilesstorethefollowinginformation:
Thenamesofsourcefiles(includingtheirfullpaths)LinenumbersAssociationsbetweenILinstructionoffsets,linenumbersandsourcefiles
Thenamesofsourcefilescanbeusedtofindtheoriginalclassnameswhencorresponding.pdbfileisavailabletoareverse-engineer.Sopleaseuse.pdbfileswithcare—theycanweakentheprotectionstrength.
Thesecurityof.pdbfilescanbeimprovedbyusingsecuredebugging.
Tuning
-
Thedebuggingdirectiveprovidesabasicexperiencebydefault.Thisisenoughtoquicklystepthroughyourcodeandspotexceptions.Youmayalsooptintotheimprovedsecurityandreadabilityofdebugginginformation.Inordertodothat,pleasereadthenotesbelow.
Thefullnotationofacustomattributefordebugginghasthefollowingform:
[assembly:Obfuscation(Feature="debug[flags]",Exclude=false)]
where[flags]isanoptionalenumerationofflagsseparatedbyspaces.
Thelistofavailableflagsispresentedinthetablebelow.
Table4.8.Thelistofflagsfordebuggingdirective
Flag Descriptionsecure Activatessecuredebuggingrelative_file_paths Instructstoproducerelativefilepathsinresulting.pdbfile
nonintrusiveAllowstoperformnonintrusivedebuggingsessionstocatchhard-to-reproducebugssensitivetotime,sizeorothernonlinearfactors
SecureDebugging
Debuginformationcanbeaweakpointinsecurityofanobfuscatedapplication.Butwhatifyouwanttogetthelinenumbersandfilenameswithoutcompromisingthesecurity?Well,thisgoaliseasilyachievable.Allyouhavetodoistosupply[secure]flagtoanobfuscationattributelikesoinC#:
[assembly:Obfuscation(Feature="debug[secure]",Exclude=false)]
orinVB.NET:
-
Whathappensthen?Eazfuscator.NETstartstoencryptsourcefilenamesin.pdbfileintheverysamewayasitdoesforotheritemssuchasclassandmethodnames.So,wheneveryouhavesymbolnamesencryptionsetupforyourassemblyitwillbealsoappliedtothecontentof.pdbfile.
Tip
Ifyoudonotwanttoapplysymbolnamesencryptiontothewholeassemblythenjustprovideapasswordasshownbelow:
[assembly:Obfuscation(Feature="debug[secure]withpasswordXXXXXX",Exclude=false)]
ChangeXXXXXXwithyourpassword.Keepthepasswordinsecret.
Obviously,thesecuredebuggingmakessteppingthroughthecodeimpossibleasadebuggernolongerknowshowtofindthesourcefiles:theirnamesarenowencryptedanddebuggerhasnomeanstodecryptthem.Thisisalittlesacrificeforthebigbenefit:allloggedexceptionswillcontainthefullinformationyouneedinanencryptedandsafeform.Classnames,methodnames,argumentnames,filenamesandlinenumbersarealltheretohelpyoutopreciselylocatetheproblematiccode.Andnowyoucansafelydistribute.pdbfilestoyourcustomerswithouttheriskofsecuritybreach.
Tip
Securedebuggingisessentialfeaturewhenyouwanttodistribute.pdbfilestoyourcustomersasasolepartofyourproduct.Smallerapplicationssurelycanlivewithoutit.Applicationsofalargerscale,notablybusiness-orientedones,mayhavethehardtimesunlesssecuredebuggingisemployedfortheobfuscatedcode.
RelativeFilePaths
-
.pdbfilestoresthefullpathsofsourcefilesbydefault.That'sanexcellentideaforaninteractivedebuggerbecauseitcanfindthesourcefileseasily.Howeverthiscanbeanoverheadwhenyouonlyneedstacktracesorsecuredebugging.That'swhyyoumayprefertosavesomestoragebitsbyusingrelativefilepaths.Theyareshorter,aswellasaresulting.pdbfile.Stacktracesgetshortertoo,theirreadibilityimproves.Ifyouuseautomatederrorreportingthenyouwillbenefitfromsmallerworkloads.Touserelativefilepaths,pleasesupply[relative_file_paths]flagtoanobfuscationattributelikesoinC#:
[assembly:Obfuscation(Feature="debug[relative_file_paths]",Exclude=false)]
orinVB.NET:
DebugRenaming
Debugrenamingisaspecialrenamingtechniquefordebuggingofobfuscatedapplications.Theresultofthistechniqueisthepresenceofhumanreadablesymbolnamesinoutputassemblies.Suchsymbolnamesallowtoinstantlywatchvariablesandstacktracesbyanunaidedeye.
Debugrenamingworksbyapplying_x_prefixtoeveryrenamedclassandclassmember.Thenamepartafterprefixequalstooriginalitemname.
Instructionsonenablingdebugrenamingforanoutputassembly
1. OpenobfuscatableprojectinsidetheIDE2. AddnewsourcefiletotheprojectandcallitObfuscationSettings.cs(for
C#)orObfuscationSettings.vb(forVisualBasic.NET).YoumayprefertouseanothernameinsteadofObfuscationSettings.csorObfuscationSettings.vb
3. FillObfuscationSettings.cswiththefollowingcontent(C#):
usingSystem;usingSystem.Reflection;
-
[assembly:Obfuscation(Feature="debugrenaming",Exclude=false)]
ForVisualBasic.NET,fillObfuscationSettings.vbwiththefollowingcontent:
ImportsSystemImportsSystem.Reflection
Caution
Debugrenamingisexclusivelyadebuggingfeature.Neverleavethisfeatureenabledforproductionassemblies,otherwiseoriginalsymbolnamescanleaktotheoutsideworld.
-
5.8
https://www.gapotchenko.com/eazfuscator.net
-
PEVerifyIntegration
PEVerifytoolallowstocheckassembliestodeterminewhetherMSILcodeandassociatedmetadatameettypesafetyrequirements..NETverificationhasthespecialmeaninginsecurityconstrainedenvironmentssuchasWindowsPhone,WinRTandSilverlight,whererunningtheunverifiablecodecanproduceunexpectedresults,sometimesrenderingtheapplicationunworkable.
Eazfuscator.NETmodifiesmetadataandMSILassemblycodeduringobfuscation.Soitmaybeprofitabletoensurethattheoutputassemblystillmeetstypesafetyrequirements.
PEVerify.exeisdistributedasapartof.NETSDKwhichisinstalledtogetherwithMicrosoftVisualStudioandcanbeinvokedmanually.ButEazfuscator.NETprovidesamuchbetteroption:anabilitytoautomaticallyinvokePEVerifytoolafterobfuscation.Pleaseusetheinstructionsbelowinordertousethelatterfeature.
InstructionsonturningonthePEVerifytoolforanoutputassembly
1. OpenobfuscatableprojectinsidetheIDE2. AddnewsourcefiletotheprojectandcallitObfuscationSettings.cs(for
C#)orObfuscationSettings.vb(forVisualBasic.NET).YoumayprefertouseanothernameinsteadofObfuscationSettings.csorObfuscationSettings.vb
3. FillObfuscationSettings.cswiththefollowingcontent(C#):
usingSystem;usingSystem.Reflection;
[assembly:Obfuscation(Feature="PEVerify",Exclude=false)]
ForVisualBasic.NET,fillObfuscationSettings.vbwiththefollowingcontent:
ImportsSystem
-
ImportsSystem.Reflection
-
5.8
https://www.gapotchenko.com/eazfuscator.net
-
ProbingPaths
AboutProbingPaths
ProbingpathsisasetofplacesatthefilesystemwhereEazfuscator.NETcansearchfordependenciesofinputassembly.Eazfuscator.NETissmartenoughtodeductthesepathsfrominstalledassembliesandfromprojectsettings,howeveritmightbeneccessarytodefineprobingpathsmanuallywhensomecomplexscenarioisinvolved.
HowtoDefineProbingPaths?
Therearetwowaystodefineprobingpaths:bydeclarativeobfuscationattributesorbycommandlineoption.
Defineprobingpathsbydeclarativeobfuscationattributes(therecommendedway)
Todefineaprobingpathyoushouldapplyanattributetoyourassembly.Inordertodothatyoucanusetheinstructionsbelow.
Instructionsondefiningtheprobingpathbydeclarativeobfuscationattribute
1. OpenobfuscatableprojectinsidetheIDE2. AddnewsourcefiletotheprojectandcallitObfuscationSettings.cs(for
C#)orObfuscationSettings.vb(forVisualBasic.NET).YoumayprefertouseanothernameinsteadofObfuscationSettings.csorObfuscationSettings.vb
3. FillObfuscationSettings.cswiththefollowingcontent(C#):
usingSystem;usingSystem.Reflection;
[assembly:Obfuscation(Feature=@"assemblyprobingpathC:\Example\Lib")]
-
ForVisualBasic.NET,fillObfuscationSettings.vbwiththefollowingcontent:
ImportsSystemImportsSystem.Reflection
Note
ChangeC:\Example\Libwiththedirectorynameyouwanttobeprobedforassemblydependencies.
Tip
Itisrecommendedtouserelativedirectorypathswithscriptvariables:
[assembly:Obfuscation(Feature=@"assemblyprobingpath$(InputDir)\Lib")]
Tip
Ifyouwanttodefineseveralprobingpathsthenjustaddseveralattributes:
[assembly:Obfuscation(Feature=@"assemblyprobingpathC:\Example\Lib1")][assembly:Obfuscation(Feature=@"assemblyprobingpathC:\Example\Lib2")]…
Defineprobingpathsbycommandlineoption
Thereisacommandlineoption--probing-paths"C:\Example\Lib"whichcanbespecifiedtoachievethisfunctionality.Ifyouwanttodefineseveral
-
probingpathsthenpleaseusesemicolonasalistseparator:--probing-paths"C:\Example\Lib1;C:\Example\Lib2".
Note
ChangeC:\Example\Libwiththedirectorynameyouwanttobeprobedforassemblydependencies.
Warning
Donotputatrailingslashattheendofthepath,otherwisetheoperatingsystemwillinterpretitasanescapesymbol.
-
5.8
https://www.gapotchenko.com/eazfuscator.net
-
ScriptVariables
Eazfuscator.NETprovidessupportforscriptvariablesthatcanbeusedtoconfigureprobingpaths,assembliesmergingandassemblyembedding.Thelistofavailablescriptvariablesispresentedinthetablebelow.
Table4.9.Thelistofavailablescriptvariables
Variable Description Examplevalue
$(InputDir) Directorypathoftheinputassembly
C:\Dev\Project1\bin\Release
$(ProjectDir) DirectorypathoftheMSBuildproject
C:\Dev\Project1
$(SolutionDir)DirectorypathoftheMSBuildsolution
C:\Dev
$(ConfigurationName)NameofMSBuildprojectconfiguration
Release
Environmentvariablescanbereferencedaswell.Pleaseusepattern%VARIABLE%toreferenceacorrespondingenvironmentvariable.
-
5.8
https://www.gapotchenko.com/eazfuscator.net
-
Chapter5.SenseiFeatures
TableofContents
AboutSenseiFeaturesCodeInliningProtectedPrivateVisibilityCustomAttributesRemovalDesign-TimeUsageProtection
OverviewHowItWorksInstructionsTuning
ResourceSanitizationIntroductionInstructionsMinificationSelectiveResourceSanitizationOptionsareCombinable
-
AboutSenseiFeatures
Sensei()isaJapanesewordthatisusedtoshowrespecttosomeonewhohasachievedacertainlevelofmasteryinanartformorsomeotherskill.Obfuscationisnotexception.
Senseiobfuscationfeaturesarepowerfulanddemanding.Withagreatpowercomesgreatresponsibility.Notallofthemaredesignedforacommoneverydayusage.Still,youmaywantthemoneday.Especiallywhenyouworkonalicensingcodeorwanttoimproveobfuscationcoverageevenfurther.
-
5.8
https://www.gapotchenko.com/eazfuscator.net
-
CodeInlining
Methodbodiescanbeinlinedtotheircallsitesduringobfuscation.Pleasetakealookatexample(C#):
Example5.1.Beforeobfuscation
usingSystem;usingSystem.Reflection;
classProgram{staticvoidMain(string[]args){Console.WriteLine("Inliningtest");SecretMethod();}
[Obfuscation(Feature="inline",Exclude=false)]staticvoidSecretMethod(){Console.WriteLine("Secret");}}
Example5.2.Afterobfuscation
usingSystem;usingSystem.Reflection;
classProgram{staticvoidMain(string[]args){Console.WriteLine("Inliningtest");Console.WriteLine("Secret");}}
Codeinliningbringsobvioussecuritybenefits:
-
Oncemethodisinlined,it'snolongerasubjectofhacker'sspecialattention
Callsitegetslargerasittakesinlinedinstructionsofthemethod.Thismakescodeanalysisahardertaskforanintruder
Codeinliningmaybeusefulinsuchscenariosaslicensingchecksandknow-howalgorithms.
Instructionsonenablingmethodinlining
1. Openthesourcecodeofamethodyouwanttoinline
2. Addacustomattributeasshownbelow(C#):
usingSystem;usingSystem.Reflection;
classYourClass{[Obfuscation(Feature="inline",Exclude=false)]voidYourMethod(){...}}
ForVisualBasic.NET:
ImportsSystemImportsSystem.Reflection
ClassYourClass
SubYourMethod()...EndSubEndClass
-
5.8
https://www.gapotchenko.com/eazfuscator.net
-
ProtectedPrivateVisibility
.NETlanguagesofferafewkeywordsforvisibilitycontrolbetweenassemblies,classesandmembers.Forexample,C#haspublic,internal,protected,protectedinternalandprivateaccessmodifiers.
Sometimesyoumayneedaspecialaccesslevel:protectedprivate.ItexistsinC++butabsentinC#andVB.NET.ItcorrespondstoFamANDAssemvisibilityscopeintermsof.NETCLR.
Thisisindeedararerequirement.Let'stakealookonspecificexample.SupposeyouhaveaDLLassemblywritteninC#thatdoesXMLserializationforsomeentities:
Example5.3.Originalcode
usingSystem;usingSystem.Xml.Serialization;
//ThisclassisusedbySystem.Xml.Serialization.XmlSerializer.publicclassCard{publicstringID{get;set;}
protectedvirtualvoidValidate(){}}
//ThisclassisusedbySystem.Xml.Serialization.XmlSerializer.publicclassVerticalCard:Card{publicintHeight{get;set;}
http://msdn.microsoft.com/en-us/library/system.reflection.fieldinfo.isfamilyandassembly.aspx
-
protectedoverridevoidValidate(){if(Height
-
Example5.4.Modifiedcodetoallowfamilyandassemblyvisibilityforspecifiedmethods
usingSystem;usingSystem.Xml.Serialization;usingSystem.Reflection;
//ThisclassisusedbySystem.Xml.Serialization.XmlSerializer.publicclassCard{publicstringID{get;set;}
[Obfuscation(Feature="familyandassemblyvisibility",Exclude=false)]protectedvirtualvoidValidate(){}}
//ThisclassisusedbySystem.Xml.Serialization.XmlSerializer.publicclassVerticalCard:Card{publicintHeight{get;set;}
[Obfuscation(Feature="familyandassemblyvisibility",Exclude=false)]protectedoverridevoidValidate(){if(Height
-
visibletootherassemblies.
Inst