├── .gitattributes ├── .gitignore ├── .gitmodules ├── .nuget ├── NuGet.Config └── NuGet.targets ├── Build ├── 7z.exe ├── Build.cmd ├── UpdateVersion.cs ├── UpdateVersion.csproj └── files.lst ├── Confuser.CLI ├── Confuser.CLI.csproj ├── Options.cs ├── Program.cs └── Properties │ └── AssemblyInfo.cs ├── Confuser.Core ├── API │ ├── APIStore.cs │ ├── IDataStore.cs │ └── IOpaquePredicate.cs ├── Annotations.cs ├── Confuser.Core.csproj ├── ConfuserComponent.cs ├── ConfuserContext.cs ├── ConfuserEngine.cs ├── ConfuserException.cs ├── ConfuserParameters.cs ├── CoreComponent.cs ├── DependencyResolver.cs ├── DnlibUtils.cs ├── Helpers │ ├── ControlFlowGraph.cs │ ├── InjectHelper.cs │ ├── KeySequence.cs │ └── MutationHelper.cs ├── ILogger.cs ├── LZMA │ ├── Common │ │ ├── CRC.cs │ │ ├── InBuffer.cs │ │ └── OutBuffer.cs │ ├── Compress │ │ ├── LZ │ │ │ ├── IMatchFinder.cs │ │ │ ├── LzBinTree.cs │ │ │ ├── LzInWindow.cs │ │ │ └── LzOutWindow.cs │ │ ├── LZMA │ │ │ ├── LzmaBase.cs │ │ │ ├── LzmaDecoder.cs │ │ │ └── LzmaEncoder.cs │ │ └── RangeCoder │ │ │ ├── RangeCoder.cs │ │ │ ├── RangeCoderBit.cs │ │ │ └── RangeCoderBitTree.cs │ └── ICoder.cs ├── Marker.cs ├── MarkerResult.cs ├── ModuleSorter.cs ├── ModuleWriterListener.cs ├── NativeEraser.cs ├── NullLogger.cs ├── ObfAttrMarker.cs ├── ObfAttrParser.cs ├── Packer.cs ├── PluginDiscovery.cs ├── Project │ ├── ConfuserPrj.xsd │ ├── ConfuserProject.cs │ ├── InvalidPatternException.cs │ ├── PatternParser.cs │ ├── PatternToken.cs │ ├── PatternTokenizer.cs │ └── Patterns │ │ ├── AndOperator.cs │ │ ├── DeclTypeFunction.cs │ │ ├── FullNameFunction.cs │ │ ├── HasAttrFunction.cs │ │ ├── InheritsFunction.cs │ │ ├── IsPublicFunction.cs │ │ ├── IsTypeFunction.cs │ │ ├── LiteralExpression.cs │ │ ├── MatchFunction.cs │ │ ├── MemberTypeFunction.cs │ │ ├── ModuleFunction.cs │ │ ├── NameFunction.cs │ │ ├── NamespaceFunction.cs │ │ ├── NotOperator.cs │ │ ├── OrOperator.cs │ │ ├── PatternExpression.cs │ │ ├── PatternFunction.cs │ │ └── PatternOperator.cs ├── Properties │ └── AssemblyInfo.cs ├── Protection.cs ├── ProtectionDependencyAttributes.cs ├── ProtectionParameters.cs ├── ProtectionPhase.cs ├── ProtectionPipeline.cs ├── ProtectionPreset.cs ├── ProtectionSettings.cs ├── ProtectionTargets.cs ├── ServiceRegistry.cs ├── Services │ ├── CompressionService.cs │ ├── MarkerService.cs │ ├── RandomService.cs │ ├── RuntimeService.cs │ └── TraceService.cs ├── UnreachableException.cs └── Utils.cs ├── Confuser.DynCipher ├── AST │ ├── ArrayIndexExpression.cs │ ├── AssignmentStatement.cs │ ├── BinOpExpression.cs │ ├── Expression.cs │ ├── LiteralExpression.cs │ ├── LoopStatement.cs │ ├── Statement.cs │ ├── StatementBlock.cs │ ├── UnaryOpExpression.cs │ ├── Variable.cs │ └── VariableExpression.cs ├── Confuser.DynCipher.csproj ├── DynCipherComponent.cs ├── DynCipherService.cs ├── Elements │ ├── AddKey.cs │ ├── BinOp.cs │ ├── CryptoElement.cs │ ├── Matrix.cs │ ├── NumOp.cs │ ├── RotateBit.cs │ └── Swap.cs ├── Generation │ ├── CILCodeGen.cs │ ├── CipherGenContext.cs │ ├── CipherGenerator.cs │ ├── DMCodeGen.cs │ ├── ExpressionGenerator.cs │ └── x86CodeGen.cs ├── Properties │ └── AssemblyInfo.cs ├── Transforms │ ├── ConvertVariables.cs │ ├── ExpansionTransform.cs │ ├── MulToShiftTransform.cs │ ├── NormalizeBinOpTransform.cs │ └── ShuffleTransform.cs └── Utils.cs ├── Confuser.Protections ├── AntiDebugProtection.cs ├── AntiDumpProtection.cs ├── AntiILDasmProtection.cs ├── AntiTamper │ ├── AntiTamperProtection.cs │ ├── DynamicDeriver.cs │ ├── IKeyDeriver.cs │ ├── IModeHandler.cs │ ├── JITBody.cs │ ├── JITMode.cs │ ├── NormalDeriver.cs │ └── NormalMode.cs ├── Compress │ ├── Compressor.cs │ ├── CompressorContext.cs │ ├── DynamicDeriver.cs │ ├── ExtractPhase.cs │ ├── IKeyDeriver.cs │ ├── NormalDeriver.cs │ └── StubProtection.cs ├── Confuser.Protections.csproj ├── Constants │ ├── CEContext.cs │ ├── ConstantProtection.cs │ ├── DynamicMode.cs │ ├── EncodeElements.cs │ ├── EncodePhase.cs │ ├── IEncodeMode.cs │ ├── InjectPhase.cs │ ├── Mode.cs │ ├── NormalMode.cs │ ├── ReferenceReplacer.cs │ └── x86Mode.cs ├── ControlFlow │ ├── BlockParser.cs │ ├── Blocks.cs │ ├── CFContext.cs │ ├── ControlFlowPhase.cs │ ├── ControlFlowProtection.cs │ ├── ExpressionPredicate.cs │ ├── IPredicate.cs │ ├── JumpMangler.cs │ ├── ManglerBase.cs │ ├── NormalPredicate.cs │ ├── SwitchMangler.cs │ └── x86Predicate.cs ├── InvalidMetadataProtection.cs ├── Properties │ └── AssemblyInfo.cs ├── ReferenceProxy │ ├── ExpressionEncoding.cs │ ├── IRPEncoding.cs │ ├── MildMode.cs │ ├── NormalEncoding.cs │ ├── RPContext.cs │ ├── RPMode.cs │ ├── ReferenceProxyPhase.cs │ ├── ReferenceProxyProtection.cs │ ├── StrongMode.cs │ └── x86Encoding.cs └── Resources │ ├── DynamicMode.cs │ ├── IEncodeMode.cs │ ├── InjectPhase.cs │ ├── MDPhase.cs │ ├── Mode.cs │ ├── NormalMode.cs │ ├── REContext.cs │ └── ResourceProtection.cs ├── Confuser.Renamer ├── AnalyzePhase.cs ├── Analyzers │ ├── CaliburnAnalyzer.cs │ ├── InterReferenceAnalyzer.cs │ ├── JsonAnalyzer.cs │ ├── LdtokenEnumAnalyzer.cs │ ├── ResourceAnalyzer.cs │ ├── TypeBlobAnalyzer.cs │ ├── VTableAnalyzer.cs │ ├── WPFAnalyzer.cs │ └── WinFormsAnalyzer.cs ├── BAML │ ├── BAMLAnalyzer.cs │ ├── BAMLPropertyReference.cs │ ├── BAMLStringReference.cs │ ├── BamlDocument.cs │ ├── BamlElement.cs │ ├── BamlRW.cs │ ├── BamlRecords.cs │ ├── IBAMLReference.cs │ ├── IKnownThings.cs │ ├── KnownThingsv3.cs │ ├── KnownThingsv4.cs │ └── PropertyPath.cs ├── Confuser.Renamer.csproj ├── GenericArgumentResolver.cs ├── INameReference.cs ├── IRenamer.cs ├── NameProtection.cs ├── NameService.cs ├── PostRenamePhase.cs ├── Properties │ └── AssemblyInfo.cs ├── References │ ├── BAMLAttributeReference.cs │ ├── BAMLConverterMemberReference.cs │ ├── BAMLConverterTypeReference.cs │ ├── BAMLEnumReference.cs │ ├── BAMLPathTypeReference.cs │ ├── BAMLTypeReference.cs │ ├── CAMemberReference.cs │ ├── MemberRefReference.cs │ ├── OverrideDirectiveReference.cs │ ├── ResourceReference.cs │ ├── StringTypeReference.cs │ └── TypeRefReference.cs ├── RenameMode.cs ├── RenamePhase.cs ├── ReversibleRenamer.cs ├── RickRoller.cs └── VTable.cs ├── Confuser.Runtime ├── AntiDebug.Antinet.cs ├── AntiDebug.Safe.cs ├── AntiDebug.Win32.cs ├── AntiDump.cs ├── AntiTamper.JIT.cs ├── AntiTamper.Normal.cs ├── Compressor.Compat.cs ├── Compressor.cs ├── Confuser.Runtime.csproj ├── Constant.cs ├── Lzma.cs ├── Mutation.cs ├── Properties │ └── AssemblyInfo.cs ├── RefProxy.Strong.cs ├── Resource.cs └── antinet │ ├── ABOUT │ ├── AntiManagedDebugger.cs │ ├── AntiManagedProfiler.cs │ ├── HandleProcessCorruptedStateExceptionsAttribute.cs │ └── PEInfo.cs ├── Confuser2.mono.sln ├── Confuser2.sln ├── ConfuserEx.snk ├── ConfuserEx ├── App.xaml ├── App.xaml.cs ├── BoolToVisibilityConverter.cs ├── BrushToColorConverter.cs ├── CompComboBox.xaml ├── CompComboBox.xaml.cs ├── ComponentConverter.cs ├── ComponentDiscovery.cs ├── ConfuserEx.csproj ├── ConfuserEx.ico ├── EnumValuesExtension.cs ├── FileDragDrop.cs ├── InvertBoolConverter.cs ├── MainWindow.xaml ├── MainWindow.xaml.cs ├── Properties │ └── AssemblyInfo.cs ├── Resources │ ├── CREDITS │ ├── Decode.png │ ├── Error.png │ ├── FontAwesome.otf │ ├── New.png │ ├── Open.png │ ├── Save.png │ ├── TeamLogo.png │ └── Tools.png ├── Skin.cs ├── Skin.xaml ├── StackTraceDecoder.xaml ├── StackTraceDecoder.xaml.cs ├── ViewModel │ ├── IViewModel.cs │ ├── Project │ │ ├── ProjectModuleVM.cs │ │ ├── ProjectRuleVM.cs │ │ ├── ProjectSettingVM.cs │ │ └── ProjectVM.cs │ ├── StringItem.cs │ ├── UI │ │ ├── AboutTabVM.cs │ │ ├── AppVM.cs │ │ ├── ProjectTabVM.cs │ │ ├── ProtectTabVM.cs │ │ ├── SettingsTabVM.cs │ │ └── TabViewModel.cs │ ├── Utils.cs │ └── ViewModelBase.cs ├── Views.xaml ├── Views │ ├── AboutTabView.xaml │ ├── ProjectModuleView.xaml │ ├── ProjectModuleView.xaml.cs │ ├── ProjectRuleView.xaml │ ├── ProjectRuleView.xaml.cs │ ├── ProjectTabAdvancedView.xaml │ ├── ProjectTabAdvancedView.xaml.cs │ ├── ProjectTabView.xaml │ ├── ProtectTabView.xaml │ └── SettingsTabView.xaml ├── app.config └── packages.config ├── GlobalAssemblyInfo.Template.cs ├── LICENSE ├── README.md ├── VERSION ├── additional ├── Icon.pdn ├── Icon16.pdn ├── Icon256.pdn ├── Icon32.pdn ├── Icon48.pdn ├── Icon64.pdn ├── ilspy.crproj └── pdn.crproj ├── deps └── Ookii.Dialogs.Wpf.dll └── docs ├── DeclarativeObfuscation.txt ├── ProjectFormat.md └── docs.shfbproj /.gitattributes: -------------------------------------------------------------------------------- 1 | *.cs diff=csharp 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | #ignore thumbnails created by windows 3 | Thumbs.db 4 | #Ignore files build by Visual Studio 5 | *.obj 6 | *.exe 7 | *.pdb 8 | *.user 9 | *.aps 10 | *.pch 11 | *.vspscc 12 | *_i.c 13 | *_p.c 14 | *.ncb 15 | *.suo 16 | *.tlb 17 | *.tlh 18 | *.bak 19 | *.cache 20 | *.ilk 21 | *.log 22 | [Bb]in 23 | [Dd]ebug*/ 24 | *.lib 25 | *.sbr 26 | obj/ 27 | [Rr]elease*/ 28 | _ReSharper*/ 29 | [Tt]est[Rr]esult* 30 | 31 | !packages/*/build/ 32 | packages/ 33 | /Confuser.Test 34 | *.sln.* 35 | gh-pages/ 36 | GlobalAssemblyInfo.cs 37 | /Build/*.zip 38 | !Build/7z.exe -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "dnlib"] 2 | path = dnlib 3 | url = https://github.com/yck1509/dnlib.git 4 | -------------------------------------------------------------------------------- /.nuget/NuGet.Config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Build/7z.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yck1509/ConfuserEx/3e3e4ae8ef01e3a169591e9b7803408e38cce7ca/Build/7z.exe -------------------------------------------------------------------------------- /Build/Build.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | %windir%\microsoft.net\framework\v4.0.30319\msbuild ..\Confuser2.sln /p:Configuration=Release "/p:Platform=Any CPU" 4 | 5 | IF %ERRORLEVEL% NEQ 0 GOTO err 6 | 7 | 7z a ConfuserEx_bin.zip -tzip @files.lst 8 | EXIT /B 0 9 | 10 | :err 11 | PAUSE 12 | EXIT /B 1 -------------------------------------------------------------------------------- /Build/UpdateVersion.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.IO; 4 | 5 | public static class Program { 6 | public static int Main(string[] args) { 7 | if (args.Length != 1) { 8 | Console.WriteLine("invalid argument length."); 9 | return -1; 10 | } 11 | 12 | string dir = args[0]; 13 | string ver = File.ReadAllText(Path.Combine(dir, "VERSION")); 14 | string tag = null; 15 | 16 | string gitDir = Path.Combine(dir, ".git"); 17 | if (!Directory.Exists(gitDir)) { 18 | Console.WriteLine("git repository not found."); 19 | } 20 | else { 21 | try { 22 | var info = new ProcessStartInfo("git", "describe"); 23 | info.RedirectStandardOutput = true; 24 | info.UseShellExecute = false; 25 | using (Process ps = Process.Start(info)) { 26 | tag = ps.StandardOutput.ReadLine(); 27 | string[] infos = tag.Split('-'); 28 | if (infos.Length >= 3) 29 | ver = ver + "." + infos[infos.Length - 2]; 30 | else 31 | ver = infos[0].Substring(1); 32 | ps.WaitForExit(); 33 | if (ps.ExitCode != 0) { 34 | Console.WriteLine("error when executing git describe: " + ps.ExitCode); 35 | } 36 | } 37 | } 38 | catch { 39 | Console.WriteLine("error when executing git describe."); 40 | } 41 | } 42 | tag = tag ?? "v" + ver + "-custom"; 43 | 44 | string template = Path.Combine(dir, "GlobalAssemblyInfo.Template.cs"); 45 | string output = Path.Combine(dir, "GlobalAssemblyInfo.cs"); 46 | 47 | string verInfo = File.ReadAllText(template); 48 | verInfo = verInfo.Replace("{{VER}}", ver); 49 | verInfo = verInfo.Replace("{{TAG}}", tag); 50 | File.WriteAllText(output, verInfo); 51 | Console.WriteLine("Version updated."); 52 | return 0; 53 | } 54 | } -------------------------------------------------------------------------------- /Build/UpdateVersion.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Release 5 | AnyCPU 6 | {1e74b523-aa86-42a0-8116-fff7cebfcba7} 7 | Exe 8 | UpdateVersion 9 | UpdateVersion 10 | v2.0 11 | 12 | 13 | false 14 | None 15 | true 16 | .\ 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Build/files.lst: -------------------------------------------------------------------------------- 1 | ..\Release\bin\Confuser.CLI.exe 2 | ..\Release\bin\Confuser.CLI.pdb 3 | ..\Release\bin\Confuser.Core.* 4 | ..\Release\bin\Confuser.DynCipher.* 5 | ..\Release\bin\Confuser.Protections.* 6 | ..\Release\bin\Confuser.Renamer.* 7 | ..\Release\bin\Confuser.Runtime.* 8 | ..\Release\bin\dnlib.* 9 | ..\Release\bin\ConfuserEx.exe 10 | ..\Release\bin\ConfuserEx.exe.config 11 | ..\Release\bin\ConfuserEx.pdb 12 | ..\Release\bin\System.Threading.dll 13 | ..\Release\bin\GalaSoft.MvvmLight.Extras.WPF4.dll 14 | ..\Release\bin\GalaSoft.MvvmLight.WPF4.dll 15 | ..\Release\bin\Microsoft.Practices.ServiceLocation.dll 16 | ..\Release\bin\Ookii.Dialogs.Wpf.dll 17 | ..\Release\bin\System.Windows.Interactivity.dll -------------------------------------------------------------------------------- /Confuser.CLI/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | 4 | [assembly: AssemblyTitle("ConfuserEx Command-line")] 5 | [assembly: AssemblyDescription("Command-line interface of ConfuserEx")] -------------------------------------------------------------------------------- /Confuser.Core/API/IDataStore.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using dnlib.DotNet; 3 | using dnlib.DotNet.Emit; 4 | 5 | namespace Confuser.Core.API { 6 | /// 7 | /// A data store. 8 | /// 9 | public interface IDataStore { 10 | /// 11 | /// Gets the priority of this data store; higher priority means it 12 | /// would be tried earlier. 13 | /// 14 | /// The priority of this data store. 15 | int Priority { get; } 16 | 17 | /// 18 | /// Gets the number of keys this predicate has. 19 | /// 20 | /// 21 | /// Keys are used by the data store to encrypt data/whatever purpose. 22 | /// 23 | /// The number of keys this data store has. 24 | int KeyCount { get; } 25 | 26 | /// 27 | /// Determines whether this data store can be used in the specified method. 28 | /// 29 | /// The method. 30 | /// true if this data store can be used in the specified method; otherwise, false. 31 | bool IsUsable(MethodDef method); 32 | 33 | /// 34 | /// Creates an accessor of this data store for the specified method. 35 | /// 36 | /// The method. 37 | /// The keys. 38 | /// The data to store. 39 | /// A newly accessor of this data store. 40 | IDataStoreAccessor CreateAccessor(MethodDef method, uint[] keys, byte[] data); 41 | } 42 | 43 | /// 44 | /// An accessor of data store. 45 | /// 46 | public interface IDataStoreAccessor { 47 | /// 48 | /// Emits the runtime instruction sequence for this accessor. 49 | /// 50 | /// An instruction sequence that returns the stored data. 51 | Instruction[] Emit(); 52 | } 53 | } -------------------------------------------------------------------------------- /Confuser.Core/ConfuserComponent.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Confuser.Core { 4 | /// 5 | /// Represent a component in Confuser 6 | /// 7 | public abstract class ConfuserComponent { 8 | /// 9 | /// Gets the name of component. 10 | /// 11 | /// The name of component. 12 | public abstract string Name { get; } 13 | 14 | /// 15 | /// Gets the description of component. 16 | /// 17 | /// The description of component. 18 | public abstract string Description { get; } 19 | 20 | /// 21 | /// Gets the identifier of component used by users. 22 | /// 23 | /// The identifier of component. 24 | public abstract string Id { get; } 25 | 26 | /// 27 | /// Gets the full identifier of component used in Confuser. 28 | /// 29 | /// The full identifier of component. 30 | public abstract string FullId { get; } 31 | 32 | /// 33 | /// Initializes the component. 34 | /// 35 | /// The working context. 36 | protected internal abstract void Initialize(ConfuserContext context); 37 | 38 | /// 39 | /// Inserts protection stages into processing pipeline. 40 | /// 41 | /// The processing pipeline. 42 | protected internal abstract void PopulatePipeline(ProtectionPipeline pipeline); 43 | } 44 | } -------------------------------------------------------------------------------- /Confuser.Core/ConfuserException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Confuser.Core { 4 | /// 5 | /// The exception that is thrown when a handled error occurred during the protection process. 6 | /// 7 | public class ConfuserException : Exception { 8 | /// 9 | /// Initializes a new instance of the class. 10 | /// 11 | /// The inner exception, or null if no exception is associated with the error. 12 | public ConfuserException(Exception innerException) 13 | : base("Exception occurred during the protection process.", innerException) { } 14 | } 15 | } -------------------------------------------------------------------------------- /Confuser.Core/ConfuserParameters.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Confuser.Core.Project; 3 | 4 | namespace Confuser.Core { 5 | /// 6 | /// Parameters that passed to . 7 | /// 8 | public class ConfuserParameters { 9 | /// 10 | /// Gets or sets the project that would be processed. 11 | /// 12 | /// The Confuser project. 13 | public ConfuserProject Project { get; set; } 14 | 15 | /// 16 | /// Gets or sets the logger that used to log the protection process. 17 | /// 18 | /// The logger, or null if logging is not needed. 19 | public ILogger Logger { get; set; } 20 | 21 | internal bool PackerInitiated { get; set; } 22 | 23 | /// 24 | /// Gets or sets the plugin discovery service. 25 | /// 26 | /// The plugin discovery service, or null if default discovery is used. 27 | public PluginDiscovery PluginDiscovery { get; set; } 28 | 29 | /// 30 | /// Gets or sets the marker. 31 | /// 32 | /// The marker, or null if default marker is used. 33 | public Marker Marker { get; set; } 34 | 35 | /// 36 | /// Gets the actual non-null logger. 37 | /// 38 | /// The logger. 39 | internal ILogger GetLogger() { 40 | return Logger ?? NullLogger.Instance; 41 | } 42 | 43 | /// 44 | /// Gets the actual non-null plugin discovery service. 45 | /// 46 | /// The plugin discovery service. 47 | internal PluginDiscovery GetPluginDiscovery() { 48 | return PluginDiscovery ?? PluginDiscovery.Instance; 49 | } 50 | 51 | /// 52 | /// Gets the actual non-null marker. 53 | /// 54 | /// The marker. 55 | internal Marker GetMarker() { 56 | return Marker ?? new ObfAttrMarker(); 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /Confuser.Core/LZMA/Common/CRC.cs: -------------------------------------------------------------------------------- 1 | // Common/CRC.cs 2 | 3 | using System; 4 | 5 | namespace SevenZip { 6 | internal class CRC { 7 | 8 | public static readonly uint[] Table; 9 | 10 | private uint _value = 0xFFFFFFFF; 11 | 12 | static CRC() { 13 | Table = new uint[256]; 14 | const uint kPoly = 0xEDB88320; 15 | for (uint i = 0; i < 256; i++) { 16 | uint r = i; 17 | for (int j = 0; j < 8; j++) 18 | if ((r & 1) != 0) 19 | r = (r >> 1) ^ kPoly; 20 | else 21 | r >>= 1; 22 | Table[i] = r; 23 | } 24 | } 25 | 26 | public void Init() { 27 | _value = 0xFFFFFFFF; 28 | } 29 | 30 | public void UpdateByte(byte b) { 31 | _value = Table[(((byte)(_value)) ^ b)] ^ (_value >> 8); 32 | } 33 | 34 | public void Update(byte[] data, uint offset, uint size) { 35 | for (uint i = 0; i < size; i++) 36 | _value = Table[(((byte)(_value)) ^ data[offset + i])] ^ (_value >> 8); 37 | } 38 | 39 | public uint GetDigest() { 40 | return _value ^ 0xFFFFFFFF; 41 | } 42 | 43 | private static uint CalculateDigest(byte[] data, uint offset, uint size) { 44 | var crc = new CRC(); 45 | // crc.Init(); 46 | crc.Update(data, offset, size); 47 | return crc.GetDigest(); 48 | } 49 | 50 | private static bool VerifyDigest(uint digest, byte[] data, uint offset, uint size) { 51 | return (CalculateDigest(data, offset, size) == digest); 52 | } 53 | 54 | } 55 | } -------------------------------------------------------------------------------- /Confuser.Core/LZMA/Common/InBuffer.cs: -------------------------------------------------------------------------------- 1 | // InBuffer.cs 2 | 3 | using System; 4 | using System.IO; 5 | 6 | namespace SevenZip.Buffer { 7 | internal class InBuffer { 8 | 9 | private readonly byte[] m_Buffer; 10 | private readonly uint m_BufferSize; 11 | private uint m_Limit; 12 | private uint m_Pos; 13 | private ulong m_ProcessedSize; 14 | private Stream m_Stream; 15 | private bool m_StreamWasExhausted; 16 | 17 | public InBuffer(uint bufferSize) { 18 | m_Buffer = new byte[bufferSize]; 19 | m_BufferSize = bufferSize; 20 | } 21 | 22 | public void Init(Stream stream) { 23 | m_Stream = stream; 24 | m_ProcessedSize = 0; 25 | m_Limit = 0; 26 | m_Pos = 0; 27 | m_StreamWasExhausted = false; 28 | } 29 | 30 | public bool ReadBlock() { 31 | if (m_StreamWasExhausted) 32 | return false; 33 | m_ProcessedSize += m_Pos; 34 | int aNumProcessedBytes = m_Stream.Read(m_Buffer, 0, (int)m_BufferSize); 35 | m_Pos = 0; 36 | m_Limit = (uint)aNumProcessedBytes; 37 | m_StreamWasExhausted = (aNumProcessedBytes == 0); 38 | return (!m_StreamWasExhausted); 39 | } 40 | 41 | 42 | public void ReleaseStream() { 43 | // m_Stream.Close(); 44 | m_Stream = null; 45 | } 46 | 47 | public bool ReadByte(byte b) // check it 48 | { 49 | if (m_Pos >= m_Limit) 50 | if (!ReadBlock()) 51 | return false; 52 | b = m_Buffer[m_Pos++]; 53 | return true; 54 | } 55 | 56 | public byte ReadByte() { 57 | // return (byte)m_Stream.ReadByte(); 58 | if (m_Pos >= m_Limit) 59 | if (!ReadBlock()) 60 | return 0xFF; 61 | return m_Buffer[m_Pos++]; 62 | } 63 | 64 | public ulong GetProcessedSize() { 65 | return m_ProcessedSize + m_Pos; 66 | } 67 | 68 | } 69 | } -------------------------------------------------------------------------------- /Confuser.Core/LZMA/Common/OutBuffer.cs: -------------------------------------------------------------------------------- 1 | // OutBuffer.cs 2 | 3 | using System; 4 | using System.IO; 5 | 6 | namespace SevenZip.Buffer { 7 | internal class OutBuffer { 8 | 9 | private readonly byte[] m_Buffer; 10 | private readonly uint m_BufferSize; 11 | private uint m_Pos; 12 | private ulong m_ProcessedSize; 13 | private Stream m_Stream; 14 | 15 | public OutBuffer(uint bufferSize) { 16 | m_Buffer = new byte[bufferSize]; 17 | m_BufferSize = bufferSize; 18 | } 19 | 20 | public void SetStream(Stream stream) { 21 | m_Stream = stream; 22 | } 23 | 24 | public void FlushStream() { 25 | m_Stream.Flush(); 26 | } 27 | 28 | public void CloseStream() { 29 | m_Stream.Close(); 30 | } 31 | 32 | public void ReleaseStream() { 33 | m_Stream = null; 34 | } 35 | 36 | public void Init() { 37 | m_ProcessedSize = 0; 38 | m_Pos = 0; 39 | } 40 | 41 | public void WriteByte(byte b) { 42 | m_Buffer[m_Pos++] = b; 43 | if (m_Pos >= m_BufferSize) 44 | FlushData(); 45 | } 46 | 47 | public void FlushData() { 48 | if (m_Pos == 0) 49 | return; 50 | m_Stream.Write(m_Buffer, 0, (int)m_Pos); 51 | m_Pos = 0; 52 | } 53 | 54 | public ulong GetProcessedSize() { 55 | return m_ProcessedSize + m_Pos; 56 | } 57 | 58 | } 59 | } -------------------------------------------------------------------------------- /Confuser.Core/LZMA/Compress/LZ/IMatchFinder.cs: -------------------------------------------------------------------------------- 1 | // IMatchFinder.cs 2 | 3 | using System; 4 | using System.IO; 5 | 6 | namespace SevenZip.Compression.LZ { 7 | internal interface IInWindowStream { 8 | 9 | void SetStream(Stream inStream); 10 | void Init(); 11 | void ReleaseStream(); 12 | Byte GetIndexByte(Int32 index); 13 | UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit); 14 | UInt32 GetNumAvailableBytes(); 15 | 16 | } 17 | 18 | internal interface IMatchFinder : IInWindowStream { 19 | 20 | void Create(UInt32 historySize, UInt32 keepAddBufferBefore, 21 | UInt32 matchMaxLen, UInt32 keepAddBufferAfter); 22 | 23 | UInt32 GetMatches(UInt32[] distances); 24 | void Skip(UInt32 num); 25 | 26 | } 27 | } -------------------------------------------------------------------------------- /Confuser.Core/LZMA/Compress/LZ/LzOutWindow.cs: -------------------------------------------------------------------------------- 1 | // LzOutWindow.cs 2 | 3 | using System; 4 | using System.IO; 5 | 6 | namespace SevenZip.Compression.LZ { 7 | internal class OutWindow { 8 | 9 | public uint TrainSize = 0; 10 | private byte[] _buffer; 11 | private uint _pos; 12 | private Stream _stream; 13 | private uint _streamPos; 14 | private uint _windowSize; 15 | 16 | public void Create(uint windowSize) { 17 | if (_windowSize != windowSize) { 18 | // System.GC.Collect(); 19 | _buffer = new byte[windowSize]; 20 | } 21 | _windowSize = windowSize; 22 | _pos = 0; 23 | _streamPos = 0; 24 | } 25 | 26 | public void Init(Stream stream, bool solid) { 27 | ReleaseStream(); 28 | _stream = stream; 29 | if (!solid) { 30 | _streamPos = 0; 31 | _pos = 0; 32 | TrainSize = 0; 33 | } 34 | } 35 | 36 | public bool Train(Stream stream) { 37 | long len = stream.Length; 38 | uint size = (len < _windowSize) ? (uint)len : _windowSize; 39 | TrainSize = size; 40 | stream.Position = len - size; 41 | _streamPos = _pos = 0; 42 | while (size > 0) { 43 | uint curSize = _windowSize - _pos; 44 | if (size < curSize) 45 | curSize = size; 46 | int numReadBytes = stream.Read(_buffer, (int)_pos, (int)curSize); 47 | if (numReadBytes == 0) 48 | return false; 49 | size -= (uint)numReadBytes; 50 | _pos += (uint)numReadBytes; 51 | _streamPos += (uint)numReadBytes; 52 | if (_pos == _windowSize) 53 | _streamPos = _pos = 0; 54 | } 55 | return true; 56 | } 57 | 58 | public void ReleaseStream() { 59 | Flush(); 60 | _stream = null; 61 | } 62 | 63 | public void Flush() { 64 | uint size = _pos - _streamPos; 65 | if (size == 0) 66 | return; 67 | _stream.Write(_buffer, (int)_streamPos, (int)size); 68 | if (_pos >= _windowSize) 69 | _pos = 0; 70 | _streamPos = _pos; 71 | } 72 | 73 | public void CopyBlock(uint distance, uint len) { 74 | uint pos = _pos - distance - 1; 75 | if (pos >= _windowSize) 76 | pos += _windowSize; 77 | for (; len > 0; len--) { 78 | if (pos >= _windowSize) 79 | pos = 0; 80 | _buffer[_pos++] = _buffer[pos++]; 81 | if (_pos >= _windowSize) 82 | Flush(); 83 | } 84 | } 85 | 86 | public void PutByte(byte b) { 87 | _buffer[_pos++] = b; 88 | if (_pos >= _windowSize) 89 | Flush(); 90 | } 91 | 92 | public byte GetByte(uint distance) { 93 | uint pos = _pos - distance - 1; 94 | if (pos >= _windowSize) 95 | pos += _windowSize; 96 | return _buffer[pos]; 97 | } 98 | 99 | } 100 | } -------------------------------------------------------------------------------- /Confuser.Core/MarkerResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using dnlib.DotNet; 4 | 5 | namespace Confuser.Core { 6 | /// 7 | /// Result of the marker. 8 | /// 9 | public class MarkerResult { 10 | /// 11 | /// Initializes a new instance of the class. 12 | /// 13 | /// The modules. 14 | /// The packer. 15 | /// The external modules. 16 | public MarkerResult(IList modules, Packer packer, IList extModules) { 17 | Modules = modules; 18 | Packer = packer; 19 | ExternalModules = extModules; 20 | } 21 | 22 | /// 23 | /// Gets a list of modules that is marked. 24 | /// 25 | /// The list of modules. 26 | public IList Modules { get; private set; } 27 | 28 | /// 29 | /// Gets a list of external modules. 30 | /// 31 | /// The list of external modules. 32 | public IList ExternalModules { get; private set; } 33 | 34 | /// 35 | /// Gets the packer if exists. 36 | /// 37 | /// The packer, or null if no packer exists. 38 | public Packer Packer { get; private set; } 39 | } 40 | } -------------------------------------------------------------------------------- /Confuser.Core/ModuleSorter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Linq; 5 | using dnlib.DotNet; 6 | 7 | namespace Confuser.Core { 8 | /// 9 | /// Sort modules according dependencies. 10 | /// 11 | internal class ModuleSorter { 12 | readonly List modules; 13 | 14 | public ModuleSorter(IEnumerable modules) { 15 | this.modules = modules.ToList(); 16 | } 17 | 18 | public IList Sort() { 19 | var edges = new List(); 20 | var roots = new HashSet(modules); 21 | var asmMap = modules.GroupBy(module => module.Assembly.ToAssemblyRef(), AssemblyNameComparer.CompareAll) 22 | .ToDictionary(gp => gp.Key, gp => gp.ToList(), AssemblyNameComparer.CompareAll); 23 | 24 | foreach (ModuleDefMD m in modules) 25 | foreach (AssemblyRef nameRef in m.GetAssemblyRefs()) { 26 | if (!asmMap.ContainsKey(nameRef)) 27 | continue; 28 | 29 | foreach (var asmModule in asmMap[nameRef]) 30 | edges.Add(new DependencyGraphEdge(asmModule, m)); 31 | roots.Remove(m); 32 | } 33 | 34 | var sorted = SortGraph(roots, edges).ToList(); 35 | Debug.Assert(sorted.Count == modules.Count); 36 | return sorted; 37 | } 38 | 39 | IEnumerable SortGraph(IEnumerable roots, IList edges) { 40 | var visited = new HashSet(); 41 | var queue = new Queue(roots); 42 | do { 43 | while (queue.Count > 0) { 44 | var node = queue.Dequeue(); 45 | visited.Add(node); 46 | 47 | Debug.Assert(!edges.Where(edge => edge.To == node).Any()); 48 | yield return node; 49 | 50 | foreach (DependencyGraphEdge edge in edges.Where(edge => edge.From == node).ToList()) { 51 | edges.Remove(edge); 52 | if (!edges.Any(e => e.To == edge.To)) 53 | queue.Enqueue(edge.To); 54 | } 55 | } 56 | if (edges.Count > 0) { 57 | foreach (var edge in edges) { 58 | if (!visited.Contains(edge.From)) { 59 | queue.Enqueue(edge.From); 60 | break; 61 | } 62 | } 63 | } 64 | } while (edges.Count > 0); 65 | } 66 | 67 | class DependencyGraphEdge { 68 | public DependencyGraphEdge(ModuleDefMD from, ModuleDefMD to) { 69 | From = from; 70 | To = to; 71 | } 72 | 73 | public ModuleDefMD From { get; private set; } 74 | public ModuleDefMD To { get; private set; } 75 | } 76 | } 77 | } -------------------------------------------------------------------------------- /Confuser.Core/ModuleWriterListener.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using dnlib.DotNet; 3 | using dnlib.DotNet.Writer; 4 | 5 | namespace Confuser.Core { 6 | /// 7 | /// The listener of module writer event. 8 | /// 9 | public class ModuleWriterListener : IModuleWriterListener { 10 | /// 11 | void IModuleWriterListener.OnWriterEvent(ModuleWriterBase writer, ModuleWriterEvent evt) { 12 | if (evt == ModuleWriterEvent.PESectionsCreated) 13 | NativeEraser.Erase(writer as NativeModuleWriter, writer.Module as ModuleDefMD); 14 | if (OnWriterEvent != null) { 15 | OnWriterEvent(writer, new ModuleWriterListenerEventArgs(evt)); 16 | } 17 | } 18 | 19 | /// 20 | /// Occurs when a module writer event is triggered. 21 | /// 22 | public event EventHandler OnWriterEvent; 23 | } 24 | 25 | /// 26 | /// Indicates the triggered writer event. 27 | /// 28 | public class ModuleWriterListenerEventArgs : EventArgs { 29 | /// 30 | /// Initializes a new instance of the class. 31 | /// 32 | /// The triggered writer event. 33 | public ModuleWriterListenerEventArgs(ModuleWriterEvent evt) { 34 | WriterEvent = evt; 35 | } 36 | 37 | /// 38 | /// Gets the triggered writer event. 39 | /// 40 | /// The triggered writer event. 41 | public ModuleWriterEvent WriterEvent { get; private set; } 42 | } 43 | } -------------------------------------------------------------------------------- /Confuser.Core/NullLogger.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using dnlib.DotNet; 3 | 4 | namespace Confuser.Core { 5 | /// 6 | /// An implementation that doesn't actually do any logging. 7 | /// 8 | internal class NullLogger : ILogger { 9 | /// 10 | /// The singleton instance of . 11 | /// 12 | public static readonly NullLogger Instance = new NullLogger(); 13 | 14 | /// 15 | /// Prevents a default instance of the class from being created. 16 | /// 17 | NullLogger() { } 18 | 19 | /// 20 | public void Debug(string msg) { } 21 | 22 | /// 23 | public void DebugFormat(string format, params object[] args) { } 24 | 25 | /// 26 | public void Info(string msg) { } 27 | 28 | /// 29 | public void InfoFormat(string format, params object[] args) { } 30 | 31 | /// 32 | public void Warn(string msg) { } 33 | 34 | /// 35 | public void WarnFormat(string format, params object[] args) { } 36 | 37 | /// 38 | public void WarnException(string msg, Exception ex) { } 39 | 40 | /// 41 | public void Error(string msg) { } 42 | 43 | /// 44 | public void ErrorFormat(string format, params object[] args) { } 45 | 46 | /// 47 | public void ErrorException(string msg, Exception ex) { } 48 | 49 | /// 50 | public void Progress(int overall, int progress) { } 51 | 52 | /// 53 | public void EndProgress() { } 54 | 55 | /// 56 | public void Finish(bool successful) { } 57 | 58 | /// 59 | public void BeginModule(ModuleDef module) { } 60 | 61 | /// 62 | public void EndModule(ModuleDef module) { } 63 | } 64 | } -------------------------------------------------------------------------------- /Confuser.Core/Project/InvalidPatternException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Confuser.Core.Project { 4 | /// 5 | /// The exception that is thrown when attempted to parse an invalid pattern. 6 | /// 7 | public class InvalidPatternException : Exception { 8 | /// 9 | /// Initializes a new instance of the class. 10 | /// 11 | /// The message that describes the error. 12 | public InvalidPatternException(string message) 13 | : base(message) { } 14 | 15 | /// 16 | /// Initializes a new instance of the class. 17 | /// 18 | /// The error message that explains the reason for the exception. 19 | /// 20 | /// The exception that is the cause of the current exception, or a null reference (Nothing in 21 | /// Visual Basic) if no inner exception is specified. 22 | /// 23 | public InvalidPatternException(string message, Exception innerException) 24 | : base(message, innerException) { } 25 | } 26 | } -------------------------------------------------------------------------------- /Confuser.Core/Project/PatternTokenizer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Text; 4 | 5 | namespace Confuser.Core.Project { 6 | internal class PatternTokenizer { 7 | int index; 8 | string rulePattern; 9 | 10 | public void Initialize(string pattern) { 11 | rulePattern = pattern; 12 | index = 0; 13 | } 14 | 15 | void SkipWhitespace() { 16 | while (index < rulePattern.Length && char.IsWhiteSpace(rulePattern[index])) 17 | index++; 18 | } 19 | 20 | char? PeekChar() { 21 | if (index >= rulePattern.Length) 22 | return null; 23 | return rulePattern[index]; 24 | } 25 | 26 | char NextChar() { 27 | if (index >= rulePattern.Length) 28 | throw new InvalidPatternException("Unexpected end of pattern."); 29 | return rulePattern[index++]; 30 | } 31 | 32 | string ReadLiteral() { 33 | var ret = new StringBuilder(); 34 | char delim = NextChar(); 35 | Debug.Assert(delim == '"' || delim == '\''); 36 | 37 | char chr = NextChar(); 38 | while (chr != delim) { 39 | // Escape sequence 40 | if (chr == '\\') 41 | ret.Append(NextChar()); 42 | else 43 | ret.Append(chr); 44 | chr = NextChar(); 45 | } 46 | return ret.ToString(); 47 | } 48 | 49 | string ReadIdentifier() { 50 | var ret = new StringBuilder(); 51 | 52 | char? chr = PeekChar(); 53 | while (chr != null && (char.IsLetterOrDigit(chr.Value) || chr == '_' || chr == '-')) { 54 | ret.Append(NextChar()); 55 | chr = PeekChar(); 56 | } 57 | 58 | return ret.ToString(); 59 | } 60 | 61 | public PatternToken? NextToken() { 62 | if (rulePattern == null) 63 | throw new InvalidOperationException("Tokenizer not initialized."); 64 | 65 | SkipWhitespace(); 66 | char? tokenBegin = PeekChar(); 67 | if (tokenBegin == null) 68 | return null; 69 | 70 | int pos = index; 71 | switch (tokenBegin.Value) { 72 | case ',': 73 | index++; 74 | return new PatternToken(pos, TokenType.Comma); 75 | case '(': 76 | index++; 77 | return new PatternToken(pos, TokenType.LParens); 78 | case ')': 79 | index++; 80 | return new PatternToken(pos, TokenType.RParens); 81 | 82 | case '"': 83 | case '\'': 84 | return new PatternToken(pos, TokenType.Literal, ReadLiteral()); 85 | 86 | default: 87 | if (!char.IsLetter(tokenBegin.Value)) 88 | throw new InvalidPatternException(string.Format("Unknown token '{0}' at position {1}.", tokenBegin, pos)); 89 | 90 | return new PatternToken(pos, TokenType.Identifier, ReadIdentifier()); 91 | } 92 | } 93 | } 94 | } -------------------------------------------------------------------------------- /Confuser.Core/Project/Patterns/AndOperator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using dnlib.DotNet; 3 | 4 | namespace Confuser.Core.Project.Patterns { 5 | /// 6 | /// The AND operator. 7 | /// 8 | public class AndOperator : PatternOperator { 9 | internal const string OpName = "and"; 10 | 11 | /// 12 | public override string Name { 13 | get { return OpName; } 14 | } 15 | 16 | /// 17 | public override bool IsUnary { 18 | get { return false; } 19 | } 20 | 21 | /// 22 | public override object Evaluate(IDnlibDef definition) { 23 | var a = (bool)OperandA.Evaluate(definition); 24 | if (!a) return false; 25 | return (bool)OperandB.Evaluate(definition); 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /Confuser.Core/Project/Patterns/DeclTypeFunction.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using dnlib.DotNet; 3 | 4 | namespace Confuser.Core.Project.Patterns { 5 | /// 6 | /// A function that compare the full name of declaring type. 7 | /// 8 | public class DeclTypeFunction : PatternFunction { 9 | internal const string FnName = "decl-type"; 10 | 11 | /// 12 | public override string Name { 13 | get { return FnName; } 14 | } 15 | 16 | /// 17 | public override int ArgumentCount { 18 | get { return 1; } 19 | } 20 | 21 | /// 22 | public override object Evaluate(IDnlibDef definition) { 23 | if (!(definition is IMemberDef) || ((IMemberDef)definition).DeclaringType == null) 24 | return false; 25 | object fullName = Arguments[0].Evaluate(definition); 26 | return ((IMemberDef)definition).DeclaringType.FullName == fullName.ToString(); 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /Confuser.Core/Project/Patterns/FullNameFunction.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using dnlib.DotNet; 3 | 4 | namespace Confuser.Core.Project.Patterns { 5 | /// 6 | /// A function that compare the full name of definition. 7 | /// 8 | public class FullNameFunction : PatternFunction { 9 | internal const string FnName = "full-name"; 10 | 11 | /// 12 | public override string Name { 13 | get { return FnName; } 14 | } 15 | 16 | /// 17 | public override int ArgumentCount { 18 | get { return 1; } 19 | } 20 | 21 | /// 22 | public override object Evaluate(IDnlibDef definition) { 23 | object name = Arguments[0].Evaluate(definition); 24 | return definition.FullName == name.ToString(); 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /Confuser.Core/Project/Patterns/HasAttrFunction.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using dnlib.DotNet; 3 | 4 | namespace Confuser.Core.Project.Patterns { 5 | /// 6 | /// A function that indicate whether the item has the given custom attribute. 7 | /// 8 | public class HasAttrFunction : PatternFunction { 9 | internal const string FnName = "has-attr"; 10 | 11 | /// 12 | public override string Name { 13 | get { return FnName; } 14 | } 15 | 16 | /// 17 | public override int ArgumentCount { 18 | get { return 1; } 19 | } 20 | 21 | /// 22 | public override object Evaluate(IDnlibDef definition) { 23 | string attrName = Arguments[0].Evaluate(definition).ToString(); 24 | return definition.CustomAttributes.IsDefined(attrName); 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /Confuser.Core/Project/Patterns/InheritsFunction.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using dnlib.DotNet; 3 | 4 | namespace Confuser.Core.Project.Patterns { 5 | /// 6 | /// A function that indicate whether the type inherits from the specified type. 7 | /// 8 | public class InheritsFunction : PatternFunction { 9 | internal const string FnName = "inherits"; 10 | 11 | /// 12 | public override string Name { 13 | get { return FnName; } 14 | } 15 | 16 | /// 17 | public override int ArgumentCount { 18 | get { return 1; } 19 | } 20 | 21 | /// 22 | public override object Evaluate(IDnlibDef definition) { 23 | string name = Arguments[0].Evaluate(definition).ToString(); 24 | 25 | var type = definition as TypeDef; 26 | if (type == null && definition is IMemberDef) 27 | type = ((IMemberDef)definition).DeclaringType; 28 | if (type == null) 29 | return false; 30 | 31 | if (type.InheritsFrom(name) || type.Implements(name)) 32 | return true; 33 | 34 | return false; 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /Confuser.Core/Project/Patterns/IsPublicFunction.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using dnlib.DotNet; 3 | 4 | namespace Confuser.Core.Project.Patterns { 5 | /// 6 | /// A function that indicate the visibility of members. 7 | /// 8 | public class IsPublicFunction : PatternFunction { 9 | internal const string FnName = "is-public"; 10 | 11 | /// 12 | public override string Name { 13 | get { return FnName; } 14 | } 15 | 16 | /// 17 | public override int ArgumentCount { 18 | get { return 0; } 19 | } 20 | 21 | /// 22 | public override object Evaluate(IDnlibDef definition) { 23 | var member = definition as IMemberDef; 24 | if (member == null) 25 | return false; 26 | 27 | var declType = ((IMemberDef)definition).DeclaringType; 28 | while (declType != null) { 29 | if (!declType.IsPublic) 30 | return false; 31 | declType = declType.DeclaringType; 32 | } 33 | 34 | if (member is MethodDef) 35 | return ((MethodDef)member).IsPublic; 36 | if (member is FieldDef) 37 | return ((FieldDef)member).IsPublic; 38 | if (member is PropertyDef) 39 | return ((PropertyDef)member).IsPublic(); 40 | if (member is EventDef) 41 | return ((EventDef)member).IsPublic(); 42 | if (member is TypeDef) 43 | return ((TypeDef)member).IsPublic || ((TypeDef)member).IsNestedPublic; 44 | 45 | throw new NotSupportedException(); 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /Confuser.Core/Project/Patterns/IsTypeFunction.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using System.Text.RegularExpressions; 4 | using dnlib.DotNet; 5 | 6 | namespace Confuser.Core.Project.Patterns { 7 | /// 8 | /// A function that indicate the type of type(?). 9 | /// 10 | public class IsTypeFunction : PatternFunction { 11 | internal const string FnName = "is-type"; 12 | 13 | /// 14 | public override string Name { 15 | get { return FnName; } 16 | } 17 | 18 | /// 19 | public override int ArgumentCount { 20 | get { return 1; } 21 | } 22 | 23 | /// 24 | public override object Evaluate(IDnlibDef definition) { 25 | TypeDef type = definition as TypeDef; 26 | if (type == null && definition is IMemberDef) 27 | type = ((IMemberDef)definition).DeclaringType; 28 | if (type == null) 29 | return false; 30 | 31 | string typeRegex = Arguments[0].Evaluate(definition).ToString(); 32 | 33 | var typeType = new StringBuilder(); 34 | 35 | if (type.IsEnum) 36 | typeType.Append("enum "); 37 | 38 | if (type.IsInterface) 39 | typeType.Append("interface "); 40 | 41 | if (type.IsValueType) 42 | typeType.Append("valuetype "); 43 | 44 | if (type.IsDelegate()) 45 | typeType.Append("delegate "); 46 | 47 | if (type.IsAbstract) 48 | typeType.Append("abstract "); 49 | 50 | if (type.IsNested) 51 | typeType.Append("nested "); 52 | 53 | if (type.IsSerializable) 54 | typeType.Append("serializable "); 55 | 56 | return Regex.IsMatch(typeType.ToString(), typeRegex); 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /Confuser.Core/Project/Patterns/LiteralExpression.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using dnlib.DotNet; 4 | 5 | namespace Confuser.Core.Project.Patterns { 6 | /// 7 | /// A literal expression. 8 | /// 9 | public class LiteralExpression : PatternExpression { 10 | /// 11 | /// Initializes a new instance of the class. 12 | /// 13 | /// The literal. 14 | public LiteralExpression(object literal) { 15 | Literal = literal; 16 | } 17 | 18 | /// 19 | /// Gets the value of literal. 20 | /// 21 | /// The value of literal. 22 | public object Literal { get; private set; } 23 | 24 | /// 25 | public override object Evaluate(IDnlibDef definition) { 26 | return Literal; 27 | } 28 | 29 | /// 30 | public override void Serialize(IList tokens) { 31 | if (Literal is bool) { 32 | var value = (bool)Literal; 33 | tokens.Add(new PatternToken(TokenType.Identifier, value.ToString().ToLowerInvariant())); 34 | } 35 | else 36 | tokens.Add(new PatternToken(TokenType.Literal, Literal.ToString())); 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /Confuser.Core/Project/Patterns/MatchFunction.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text.RegularExpressions; 3 | using dnlib.DotNet; 4 | 5 | namespace Confuser.Core.Project.Patterns { 6 | /// 7 | /// A function that match the full name of the definition with specified RegEx. 8 | /// 9 | public class MatchFunction : PatternFunction { 10 | internal const string FnName = "match"; 11 | 12 | /// 13 | public override string Name { 14 | get { return FnName; } 15 | } 16 | 17 | /// 18 | public override int ArgumentCount { 19 | get { return 1; } 20 | } 21 | 22 | /// 23 | public override object Evaluate(IDnlibDef definition) { 24 | string regex = Arguments[0].Evaluate(definition).ToString(); 25 | return Regex.IsMatch(definition.FullName, regex); 26 | } 27 | } 28 | 29 | /// 30 | /// A function that match the name of the definition with specified RegEx. 31 | /// 32 | public class MatchNameFunction : PatternFunction { 33 | internal const string FnName = "match-name"; 34 | 35 | /// 36 | public override string Name { 37 | get { return FnName; } 38 | } 39 | 40 | /// 41 | public override int ArgumentCount { 42 | get { return 1; } 43 | } 44 | 45 | /// 46 | public override object Evaluate(IDnlibDef definition) { 47 | string regex = Arguments[0].Evaluate(definition).ToString(); 48 | return Regex.IsMatch(definition.Name, regex); 49 | } 50 | } 51 | 52 | /// 53 | /// A function that match the name of declaring type with specified RegEx. 54 | /// 55 | public class MatchTypeNameFunction : PatternFunction { 56 | internal const string FnName = "match-type-name"; 57 | 58 | /// 59 | public override string Name { 60 | get { return FnName; } 61 | } 62 | 63 | /// 64 | public override int ArgumentCount { 65 | get { return 1; } 66 | } 67 | 68 | /// 69 | public override object Evaluate(IDnlibDef definition) { 70 | if (definition is TypeDef) { 71 | string regex = Arguments[0].Evaluate(definition).ToString(); 72 | return Regex.IsMatch(definition.Name, regex); 73 | } 74 | if (definition is IMemberDef && ((IMemberDef)definition).DeclaringType != null) { 75 | string regex = Arguments[0].Evaluate(definition).ToString(); 76 | return Regex.IsMatch(((IMemberDef)definition).DeclaringType.Name, regex); 77 | } 78 | return false; 79 | } 80 | } 81 | } -------------------------------------------------------------------------------- /Confuser.Core/Project/Patterns/MemberTypeFunction.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using System.Text.RegularExpressions; 4 | using dnlib.DotNet; 5 | 6 | namespace Confuser.Core.Project.Patterns { 7 | /// 8 | /// A function that compare the type of definition. 9 | /// 10 | public class MemberTypeFunction : PatternFunction { 11 | internal const string FnName = "member-type"; 12 | 13 | /// 14 | public override string Name { 15 | get { return FnName; } 16 | } 17 | 18 | /// 19 | public override int ArgumentCount { 20 | get { return 1; } 21 | } 22 | 23 | /// 24 | public override object Evaluate(IDnlibDef definition) { 25 | string typeRegex = Arguments[0].Evaluate(definition).ToString(); 26 | 27 | var memberType = new StringBuilder(); 28 | 29 | if (definition is TypeDef) 30 | memberType.Append("type "); 31 | 32 | if (definition is MethodDef) { 33 | memberType.Append("method "); 34 | 35 | var method = (MethodDef)definition; 36 | if (method.IsGetter) 37 | memberType.Append("propertym getter "); 38 | else if (method.IsSetter) 39 | memberType.Append("propertym setter "); 40 | else if (method.IsAddOn) 41 | memberType.Append("eventm add "); 42 | else if (method.IsRemoveOn) 43 | memberType.Append("eventm remove "); 44 | else if (method.IsFire) 45 | memberType.Append("eventm fire "); 46 | else if (method.IsOther) 47 | memberType.Append("other "); 48 | } 49 | 50 | if (definition is FieldDef) 51 | memberType.Append("field "); 52 | 53 | if (definition is PropertyDef) 54 | memberType.Append("property "); 55 | 56 | if (definition is EventDef) 57 | memberType.Append("event "); 58 | 59 | if (definition is ModuleDef) 60 | memberType.Append("module "); 61 | 62 | return Regex.IsMatch(memberType.ToString(), typeRegex); 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /Confuser.Core/Project/Patterns/ModuleFunction.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using dnlib.DotNet; 3 | 4 | namespace Confuser.Core.Project.Patterns { 5 | /// 6 | /// A function that compare the module of definition. 7 | /// 8 | public class ModuleFunction : PatternFunction { 9 | internal const string FnName = "module"; 10 | 11 | /// 12 | public override string Name { 13 | get { return FnName; } 14 | } 15 | 16 | /// 17 | public override int ArgumentCount { 18 | get { return 1; } 19 | } 20 | 21 | /// 22 | public override object Evaluate(IDnlibDef definition) { 23 | if (!(definition is IOwnerModule) && !(definition is IModule)) 24 | return false; 25 | object name = Arguments[0].Evaluate(definition); 26 | if (definition is IModule) 27 | return ((IModule)definition).Name == name.ToString(); 28 | return ((IOwnerModule)definition).Module.Name == name.ToString(); 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /Confuser.Core/Project/Patterns/NameFunction.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using dnlib.DotNet; 3 | 4 | namespace Confuser.Core.Project.Patterns { 5 | /// 6 | /// A function that compare the name of definition. 7 | /// 8 | public class NameFunction : PatternFunction { 9 | internal const string FnName = "name"; 10 | 11 | /// 12 | public override string Name { 13 | get { return FnName; } 14 | } 15 | 16 | /// 17 | public override int ArgumentCount { 18 | get { return 1; } 19 | } 20 | 21 | /// 22 | public override object Evaluate(IDnlibDef definition) { 23 | object name = Arguments[0].Evaluate(definition); 24 | return definition.Name == name.ToString(); 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /Confuser.Core/Project/Patterns/NamespaceFunction.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text.RegularExpressions; 3 | using dnlib.DotNet; 4 | 5 | namespace Confuser.Core.Project.Patterns { 6 | /// 7 | /// A function that compare the namespace of definition. 8 | /// 9 | public class NamespaceFunction : PatternFunction { 10 | internal const string FnName = "namespace"; 11 | 12 | /// 13 | public override string Name { 14 | get { return FnName; } 15 | } 16 | 17 | /// 18 | public override int ArgumentCount { 19 | get { return 1; } 20 | } 21 | 22 | /// 23 | public override object Evaluate(IDnlibDef definition) { 24 | if (!(definition is TypeDef) && !(definition is IMemberDef)) 25 | return false; 26 | var ns = "^" + Arguments[0].Evaluate(definition).ToString() + "$"; 27 | 28 | var type = definition as TypeDef; 29 | if (type == null) 30 | type = ((IMemberDef)definition).DeclaringType; 31 | 32 | if (type == null) 33 | return false; 34 | 35 | while (type.IsNested) 36 | type = type.DeclaringType; 37 | 38 | return type != null && Regex.IsMatch(type.Namespace ?? "", ns); 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /Confuser.Core/Project/Patterns/NotOperator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using dnlib.DotNet; 3 | 4 | namespace Confuser.Core.Project.Patterns { 5 | /// 6 | /// The NOT operator. 7 | /// 8 | public class NotOperator : PatternOperator { 9 | internal const string OpName = "not"; 10 | 11 | /// 12 | public override string Name { 13 | get { return OpName; } 14 | } 15 | 16 | /// 17 | public override bool IsUnary { 18 | get { return true; } 19 | } 20 | 21 | /// 22 | public override object Evaluate(IDnlibDef definition) { 23 | return !(bool)OperandA.Evaluate(definition); 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /Confuser.Core/Project/Patterns/OrOperator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using dnlib.DotNet; 3 | 4 | namespace Confuser.Core.Project.Patterns { 5 | /// 6 | /// The OR operator. 7 | /// 8 | public class OrOperator : PatternOperator { 9 | internal const string OpName = "or"; 10 | 11 | /// 12 | public override string Name { 13 | get { return OpName; } 14 | } 15 | 16 | /// 17 | public override bool IsUnary { 18 | get { return false; } 19 | } 20 | 21 | /// 22 | public override object Evaluate(IDnlibDef definition) { 23 | var a = (bool)OperandA.Evaluate(definition); 24 | if (a) return true; 25 | return (bool)OperandB.Evaluate(definition); 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /Confuser.Core/Project/Patterns/PatternExpression.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using dnlib.DotNet; 4 | 5 | namespace Confuser.Core.Project.Patterns { 6 | /// 7 | /// A pattern expression. 8 | /// 9 | public abstract class PatternExpression { 10 | /// 11 | /// Evaluates the expression on the specified definition. 12 | /// 13 | /// The definition. 14 | /// The result value. 15 | public abstract object Evaluate(IDnlibDef definition); 16 | 17 | /// 18 | /// Serializes the expression into tokens. 19 | /// 20 | /// The output list of tokens. 21 | public abstract void Serialize(IList tokens); 22 | } 23 | } -------------------------------------------------------------------------------- /Confuser.Core/Project/Patterns/PatternFunction.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Confuser.Core.Project.Patterns { 5 | /// 6 | /// A pattern function. 7 | /// 8 | public abstract class PatternFunction : PatternExpression { 9 | /// 10 | /// Gets the name of function. 11 | /// 12 | /// The name. 13 | public abstract string Name { get; } 14 | 15 | /// 16 | /// Gets the number of arguments of the function. 17 | /// 18 | /// The number of arguments. 19 | public abstract int ArgumentCount { get; } 20 | 21 | /// 22 | /// Gets or sets the arguments of function. 23 | /// 24 | /// The arguments. 25 | public IList Arguments { get; set; } 26 | 27 | /// 28 | public override void Serialize(IList tokens) { 29 | tokens.Add(new PatternToken(TokenType.Identifier, Name)); 30 | tokens.Add(new PatternToken(TokenType.LParens)); 31 | for (int i = 0; i < Arguments.Count; i++) { 32 | if (i != 0) 33 | tokens.Add(new PatternToken(TokenType.Comma)); 34 | Arguments[i].Serialize(tokens); 35 | } 36 | tokens.Add(new PatternToken(TokenType.RParens)); 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /Confuser.Core/Project/Patterns/PatternOperator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Confuser.Core.Project.Patterns { 5 | /// 6 | /// A pattern operator. 7 | /// 8 | public abstract class PatternOperator : PatternExpression { 9 | /// 10 | /// Gets the name of operator. 11 | /// 12 | /// The name. 13 | public abstract string Name { get; } 14 | 15 | /// 16 | /// Gets a value indicating whether this is an unary operator. 17 | /// 18 | /// true if this is an unary operator; otherwise, false. 19 | public abstract bool IsUnary { get; } 20 | 21 | /// 22 | /// Gets or sets the first operand. 23 | /// 24 | /// The first operand. 25 | public PatternExpression OperandA { get; set; } 26 | 27 | /// 28 | /// Gets or sets the second operand. 29 | /// 30 | /// The second operand. 31 | public PatternExpression OperandB { get; set; } 32 | 33 | /// 34 | public override void Serialize(IList tokens) { 35 | if (IsUnary) { 36 | tokens.Add(new PatternToken(TokenType.Identifier, Name)); 37 | OperandA.Serialize(tokens); 38 | } 39 | else { 40 | OperandA.Serialize(tokens); 41 | tokens.Add(new PatternToken(TokenType.Identifier, Name)); 42 | OperandB.Serialize(tokens); 43 | } 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /Confuser.Core/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | 4 | [assembly: AssemblyTitle("ConfuserEx Core")] 5 | [assembly: AssemblyDescription("Core framework of ConfuserEx")] -------------------------------------------------------------------------------- /Confuser.Core/Protection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Confuser.Core { 4 | /// 5 | /// Base class of Confuser protections. 6 | /// 7 | /// 8 | /// A parameterless constructor must exists in derived classes to enable plugin discovery. 9 | /// 10 | public abstract class Protection : ConfuserComponent { 11 | /// 12 | /// Gets the preset this protection is in. 13 | /// 14 | /// The protection's preset. 15 | public abstract ProtectionPreset Preset { get; } 16 | } 17 | } -------------------------------------------------------------------------------- /Confuser.Core/ProtectionDependencyAttributes.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Confuser.Core { 4 | /// 5 | /// Indicates the must initialize before the specified protections. 6 | /// 7 | [AttributeUsage(AttributeTargets.Class)] 8 | public class BeforeProtectionAttribute : Attribute { 9 | /// 10 | /// Initializes a new instance of the class. 11 | /// 12 | /// The full IDs of the specified protections. 13 | public BeforeProtectionAttribute(params string[] ids) { 14 | Ids = ids; 15 | } 16 | 17 | /// 18 | /// Gets the full IDs of the specified protections. 19 | /// 20 | /// The IDs of protections. 21 | public string[] Ids { get; private set; } 22 | } 23 | 24 | /// 25 | /// Indicates the must initialize after the specified protections. 26 | /// 27 | [AttributeUsage(AttributeTargets.Class)] 28 | public class AfterProtectionAttribute : Attribute { 29 | /// 30 | /// Initializes a new instance of the class. 31 | /// 32 | /// The full IDs of the specified protections. 33 | public AfterProtectionAttribute(params string[] ids) { 34 | Ids = ids; 35 | } 36 | 37 | /// 38 | /// Gets the full IDs of the specified protections. 39 | /// 40 | /// The IDs of protections. 41 | public string[] Ids { get; private set; } 42 | } 43 | } -------------------------------------------------------------------------------- /Confuser.Core/ProtectionPhase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Confuser.Core { 4 | /// 5 | /// Base class of protection phases. 6 | /// 7 | public abstract class ProtectionPhase { 8 | /// 9 | /// Initializes a new instance of the class. 10 | /// 11 | /// The parent component of this phase. 12 | public ProtectionPhase(ConfuserComponent parent) { 13 | Parent = parent; 14 | } 15 | 16 | /// 17 | /// Gets the parent component. 18 | /// 19 | /// The parent component. 20 | public ConfuserComponent Parent { get; private set; } 21 | 22 | /// 23 | /// Gets the targets of protection. 24 | /// 25 | /// The protection targets. 26 | public abstract ProtectionTargets Targets { get; } 27 | 28 | /// 29 | /// Gets the name of the phase. 30 | /// 31 | /// The name of phase. 32 | public abstract string Name { get; } 33 | 34 | /// 35 | /// Gets a value indicating whether this phase process all targets, not just the targets that requires the component. 36 | /// 37 | /// true if this phase process all targets; otherwise, false. 38 | public virtual bool ProcessAll { 39 | get { return false; } 40 | } 41 | 42 | /// 43 | /// Executes the protection phase. 44 | /// 45 | /// The working context. 46 | /// The parameters of protection. 47 | protected internal abstract void Execute(ConfuserContext context, ProtectionParameters parameters); 48 | } 49 | } -------------------------------------------------------------------------------- /Confuser.Core/ProtectionPreset.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Confuser.Core { 4 | /// 5 | /// Various presets of protections. 6 | /// 7 | public enum ProtectionPreset { 8 | /// The protection does not belong to any preset. 9 | None = 0, 10 | 11 | /// The protection provides basic security. 12 | Minimum = 1, 13 | 14 | /// The protection provides normal security for public release. 15 | Normal = 2, 16 | 17 | /// The protection provides better security with observable performance impact. 18 | Aggressive = 3, 19 | 20 | /// The protection provides strongest security with possible incompatibility. 21 | Maximum = 4 22 | } 23 | } -------------------------------------------------------------------------------- /Confuser.Core/ProtectionSettings.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Confuser.Core { 5 | /// 6 | /// Protection settings for a certain component 7 | /// 8 | public class ProtectionSettings : Dictionary> { 9 | /// 10 | /// Initializes a new instance of the class. 11 | /// 12 | public ProtectionSettings() { } 13 | 14 | /// 15 | /// Initializes a new instance of the class 16 | /// from an existing . 17 | /// 18 | /// The settings to copy from. 19 | public ProtectionSettings(ProtectionSettings settings) { 20 | if (settings == null) 21 | return; 22 | 23 | foreach (var i in settings) 24 | Add(i.Key, new Dictionary(i.Value)); 25 | } 26 | 27 | /// 28 | /// Determines whether the settings is empty. 29 | /// 30 | /// true if the settings is empty; otherwise, false. 31 | public bool IsEmpty() { 32 | return Count == 0; 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /Confuser.Core/ProtectionTargets.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Confuser.Core { 4 | /// 5 | /// Targets of protection. 6 | /// 7 | [Flags] 8 | public enum ProtectionTargets { 9 | /// Type definitions. 10 | Types = 1, 11 | 12 | /// Method definitions. 13 | Methods = 2, 14 | 15 | /// Field definitions. 16 | Fields = 4, 17 | 18 | /// Event definitions. 19 | Events = 8, 20 | 21 | /// Property definitions. 22 | Properties = 16, 23 | 24 | /// All member definitions (i.e. type, methods, fields, events and properties). 25 | AllMembers = Types | Methods | Fields | Events | Properties, 26 | 27 | /// Module definitions. 28 | Modules = 32, 29 | 30 | /// All definitions (i.e. All member definitions and modules). 31 | AllDefinitions = AllMembers | Modules 32 | } 33 | } -------------------------------------------------------------------------------- /Confuser.Core/ServiceRegistry.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Confuser.Core { 5 | /// 6 | /// A registry of different services provided by protections 7 | /// 8 | public class ServiceRegistry : IServiceProvider { 9 | readonly HashSet serviceIds = new HashSet(); 10 | readonly Dictionary services = new Dictionary(); 11 | 12 | /// 13 | object IServiceProvider.GetService(Type serviceType) { 14 | return services.GetValueOrDefault(serviceType, null); 15 | } 16 | 17 | /// 18 | /// Retrieves the service of type . 19 | /// 20 | /// The type of service. 21 | /// The service instance. 22 | public T GetService() { 23 | return (T)services.GetValueOrDefault(typeof(T), null); 24 | } 25 | 26 | /// 27 | /// Registers the service with specified ID . 28 | /// 29 | /// The service identifier. 30 | /// The service type. 31 | /// The service. 32 | /// Service with same ID or type has already registered. 33 | public void RegisterService(string serviceId, Type serviceType, object service) { 34 | if (!serviceIds.Add(serviceId)) 35 | throw new ArgumentException("Service with ID '" + serviceIds + "' has already registered.", "serviceId"); 36 | if (services.ContainsKey(serviceType)) 37 | throw new ArgumentException("Service with type '" + service.GetType().Name + "' has already registered.", "service"); 38 | services.Add(serviceType, service); 39 | } 40 | 41 | /// 42 | /// Determines whether the service with specified identifier has already registered. 43 | /// 44 | /// The service identifier. 45 | /// true if the service with specified identifier has already registered; otherwise, false. 46 | public bool Contains(string serviceId) { 47 | return serviceIds.Contains(serviceId); 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /Confuser.Core/Services/RuntimeService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Reflection; 4 | using dnlib.DotNet; 5 | 6 | namespace Confuser.Core.Services { 7 | internal class RuntimeService : IRuntimeService { 8 | ModuleDef rtModule; 9 | 10 | /// 11 | public TypeDef GetRuntimeType(string fullName) { 12 | if (rtModule == null) { 13 | Module module = typeof(RuntimeService).Assembly.ManifestModule; 14 | string rtPath = "Confuser.Runtime.dll"; 15 | if (module.FullyQualifiedName[0] != '<') 16 | rtPath = Path.Combine(Path.GetDirectoryName(module.FullyQualifiedName), rtPath); 17 | rtModule = ModuleDefMD.Load(rtPath, new ModuleCreationOptions() { TryToLoadPdbFromDisk = true }); 18 | rtModule.EnableTypeDefFindCache = true; 19 | } 20 | return rtModule.Find(fullName, true); 21 | } 22 | } 23 | 24 | /// 25 | /// Provides methods to obtain runtime library injection type. 26 | /// 27 | public interface IRuntimeService { 28 | /// 29 | /// Gets the specified runtime type for injection. 30 | /// 31 | /// The full name of the runtime type. 32 | /// The requested runtime type. 33 | TypeDef GetRuntimeType(string fullName); 34 | } 35 | } -------------------------------------------------------------------------------- /Confuser.Core/UnreachableException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Confuser.Core { 4 | /// 5 | /// The exception that is thrown when supposedly unreachable code is executed. 6 | /// 7 | public class UnreachableException : SystemException { 8 | /// 9 | /// Initializes a new instance of the class. 10 | /// 11 | public UnreachableException() : 12 | base("Unreachable code reached.") { } 13 | } 14 | } -------------------------------------------------------------------------------- /Confuser.DynCipher/AST/ArrayIndexExpression.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Confuser.DynCipher.AST { 4 | public class ArrayIndexExpression : Expression { 5 | public Expression Array { get; set; } 6 | public int Index { get; set; } 7 | 8 | public override string ToString() { 9 | return string.Format("{0}[{1}]", Array, Index); 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /Confuser.DynCipher/AST/AssignmentStatement.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Confuser.DynCipher.AST { 4 | public class AssignmentStatement : Statement { 5 | public Expression Target { get; set; } 6 | public Expression Value { get; set; } 7 | 8 | public override string ToString() { 9 | return string.Format("{0} = {1};", Target, Value); 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /Confuser.DynCipher/AST/BinOpExpression.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Confuser.DynCipher.AST { 4 | public enum BinOps { 5 | Add, 6 | Sub, 7 | Div, 8 | Mul, 9 | Or, 10 | And, 11 | Xor, 12 | Lsh, 13 | Rsh 14 | } 15 | 16 | public class BinOpExpression : Expression { 17 | public Expression Left { get; set; } 18 | public Expression Right { get; set; } 19 | public BinOps Operation { get; set; } 20 | 21 | public override string ToString() { 22 | string op; 23 | switch (Operation) { 24 | case BinOps.Add: 25 | op = "+"; 26 | break; 27 | case BinOps.Sub: 28 | op = "-"; 29 | break; 30 | case BinOps.Div: 31 | op = "/"; 32 | break; 33 | case BinOps.Mul: 34 | op = "*"; 35 | break; 36 | case BinOps.Or: 37 | op = "|"; 38 | break; 39 | case BinOps.And: 40 | op = "&"; 41 | break; 42 | case BinOps.Xor: 43 | op = "^"; 44 | break; 45 | case BinOps.Lsh: 46 | op = "<<"; 47 | break; 48 | case BinOps.Rsh: 49 | op = ">>"; 50 | break; 51 | default: 52 | throw new Exception(); 53 | } 54 | return string.Format("({0} {1} {2})", Left, op, Right); 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /Confuser.DynCipher/AST/Expression.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Confuser.DynCipher.AST { 4 | public abstract class Expression { 5 | public object Tag { get; set; } 6 | public abstract override string ToString(); 7 | 8 | public static BinOpExpression operator +(Expression a, Expression b) { 9 | return new BinOpExpression { 10 | Left = a, 11 | Right = b, 12 | Operation = BinOps.Add 13 | }; 14 | } 15 | 16 | public static BinOpExpression operator -(Expression a, Expression b) { 17 | return new BinOpExpression { 18 | Left = a, 19 | Right = b, 20 | Operation = BinOps.Sub 21 | }; 22 | } 23 | 24 | public static BinOpExpression operator *(Expression a, Expression b) { 25 | return new BinOpExpression { 26 | Left = a, 27 | Right = b, 28 | Operation = BinOps.Mul 29 | }; 30 | } 31 | 32 | public static BinOpExpression operator >>(Expression a, int b) { 33 | return new BinOpExpression { 34 | Left = a, 35 | Right = (LiteralExpression)(uint)b, 36 | Operation = BinOps.Rsh 37 | }; 38 | } 39 | 40 | public static BinOpExpression operator <<(Expression a, int b) { 41 | return new BinOpExpression { 42 | Left = a, 43 | Right = (LiteralExpression)(uint)b, 44 | Operation = BinOps.Lsh 45 | }; 46 | } 47 | 48 | public static BinOpExpression operator |(Expression a, Expression b) { 49 | return new BinOpExpression { 50 | Left = a, 51 | Right = b, 52 | Operation = BinOps.Or 53 | }; 54 | } 55 | 56 | public static BinOpExpression operator &(Expression a, Expression b) { 57 | return new BinOpExpression { 58 | Left = a, 59 | Right = b, 60 | Operation = BinOps.And 61 | }; 62 | } 63 | 64 | public static BinOpExpression operator ^(Expression a, Expression b) { 65 | return new BinOpExpression { 66 | Left = a, 67 | Right = b, 68 | Operation = BinOps.Xor 69 | }; 70 | } 71 | 72 | public static UnaryOpExpression operator ~(Expression val) { 73 | return new UnaryOpExpression { 74 | Value = val, 75 | Operation = UnaryOps.Not 76 | }; 77 | } 78 | 79 | public static UnaryOpExpression operator -(Expression val) { 80 | return new UnaryOpExpression { 81 | Value = val, 82 | Operation = UnaryOps.Negate 83 | }; 84 | } 85 | } 86 | } -------------------------------------------------------------------------------- /Confuser.DynCipher/AST/LiteralExpression.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Confuser.DynCipher.AST { 4 | public class LiteralExpression : Expression { 5 | public uint Value { get; set; } 6 | 7 | public static implicit operator LiteralExpression(uint val) { 8 | return new LiteralExpression { Value = val }; 9 | } 10 | 11 | public override string ToString() { 12 | return Value.ToString("x8") + "h"; 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /Confuser.DynCipher/AST/LoopStatement.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | 4 | namespace Confuser.DynCipher.AST { 5 | // i.e. for loop 6 | public class LoopStatement : StatementBlock { 7 | public int Begin { get; set; } 8 | public int Limit { get; set; } 9 | 10 | public override string ToString() { 11 | var ret = new StringBuilder(); 12 | ret.AppendFormat("for (int i = {0}; i < {1}; i++)", Begin, Limit); 13 | ret.AppendLine(); 14 | ret.Append(base.ToString()); 15 | return ret.ToString(); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /Confuser.DynCipher/AST/Statement.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Confuser.DynCipher.AST { 4 | public abstract class Statement { 5 | public object Tag { get; set; } 6 | public abstract override string ToString(); 7 | } 8 | } -------------------------------------------------------------------------------- /Confuser.DynCipher/AST/StatementBlock.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Confuser.DynCipher.AST { 6 | public class StatementBlock : Statement { 7 | public StatementBlock() { 8 | Statements = new List(); 9 | } 10 | 11 | public IList Statements { get; private set; } 12 | 13 | public override string ToString() { 14 | var sb = new StringBuilder(); 15 | sb.AppendLine("{"); 16 | foreach (Statement i in Statements) 17 | sb.AppendLine(i.ToString()); 18 | sb.AppendLine("}"); 19 | return sb.ToString(); 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /Confuser.DynCipher/AST/UnaryOpExpression.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Confuser.DynCipher.AST { 4 | public enum UnaryOps { 5 | Not, 6 | Negate 7 | } 8 | 9 | public class UnaryOpExpression : Expression { 10 | public Expression Value { get; set; } 11 | public UnaryOps Operation { get; set; } 12 | 13 | public override string ToString() { 14 | string op; 15 | switch (Operation) { 16 | case UnaryOps.Not: 17 | op = "~"; 18 | break; 19 | case UnaryOps.Negate: 20 | op = "-"; 21 | break; 22 | default: 23 | throw new Exception(); 24 | } 25 | return op + Value; 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /Confuser.DynCipher/AST/Variable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Confuser.DynCipher.AST { 4 | public class Variable { 5 | public Variable(string name) { 6 | Name = name; 7 | } 8 | 9 | public string Name { get; set; } 10 | public object Tag { get; set; } 11 | 12 | public override string ToString() { 13 | return Name; 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /Confuser.DynCipher/AST/VariableExpression.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Confuser.DynCipher.AST { 4 | public class VariableExpression : Expression { 5 | public Variable Variable { get; set; } 6 | 7 | public override string ToString() { 8 | return Variable.Name; 9 | } 10 | } 11 | } -------------------------------------------------------------------------------- /Confuser.DynCipher/DynCipherComponent.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Confuser.Core; 3 | 4 | namespace Confuser.DynCipher { 5 | internal class DynCipherComponent : ConfuserComponent { 6 | public const string _ServiceId = "Confuser.DynCipher"; 7 | 8 | public override string Name { 9 | get { return "Dynamic Cipher"; } 10 | } 11 | 12 | public override string Description { 13 | get { return "Provides dynamic cipher generation services."; } 14 | } 15 | 16 | public override string Id { 17 | get { return _ServiceId; } 18 | } 19 | 20 | public override string FullId { 21 | get { return _ServiceId; } 22 | } 23 | 24 | protected override void Initialize(ConfuserContext context) { 25 | context.Registry.RegisterService(_ServiceId, typeof(IDynCipherService), new DynCipherService()); 26 | } 27 | 28 | protected override void PopulatePipeline(ProtectionPipeline pipeline) { 29 | // 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /Confuser.DynCipher/DynCipherService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Confuser.Core.Services; 3 | using Confuser.DynCipher.AST; 4 | using Confuser.DynCipher.Generation; 5 | 6 | namespace Confuser.DynCipher { 7 | public interface IDynCipherService { 8 | void GenerateCipherPair(RandomGenerator random, out StatementBlock encrypt, out StatementBlock decrypt); 9 | void GenerateExpressionPair(RandomGenerator random, Expression var, Expression result, int depth, out Expression expression, out Expression inverse); 10 | } 11 | 12 | internal class DynCipherService : IDynCipherService { 13 | public void GenerateCipherPair(RandomGenerator random, out StatementBlock encrypt, out StatementBlock decrypt) { 14 | CipherGenerator.GeneratePair(random, out encrypt, out decrypt); 15 | } 16 | 17 | public void GenerateExpressionPair(RandomGenerator random, Expression var, Expression result, int depth, out Expression expression, out Expression inverse) { 18 | ExpressionGenerator.GeneratePair(random, var, result, depth, out expression, out inverse); 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /Confuser.DynCipher/Elements/AddKey.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Confuser.Core.Services; 3 | using Confuser.DynCipher.AST; 4 | using Confuser.DynCipher.Generation; 5 | 6 | namespace Confuser.DynCipher.Elements { 7 | internal class AddKey : CryptoElement { 8 | public AddKey(int index) 9 | : base(0) { 10 | Index = index; 11 | } 12 | 13 | public int Index { get; private set; } 14 | 15 | public override void Initialize(RandomGenerator random) { } 16 | 17 | void EmitCore(CipherGenContext context) { 18 | Expression val = context.GetDataExpression(Index); 19 | 20 | context.Emit(new AssignmentStatement { 21 | Value = val ^ context.GetKeyExpression(Index), 22 | Target = val 23 | }); 24 | } 25 | 26 | public override void Emit(CipherGenContext context) { 27 | EmitCore(context); 28 | } 29 | 30 | public override void EmitInverse(CipherGenContext context) { 31 | EmitCore(context); 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /Confuser.DynCipher/Elements/BinOp.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Confuser.Core.Services; 3 | using Confuser.DynCipher.AST; 4 | using Confuser.DynCipher.Generation; 5 | 6 | namespace Confuser.DynCipher.Elements { 7 | internal enum CryptoBinOps { 8 | Add, 9 | Xor, 10 | Xnor 11 | } 12 | 13 | internal class BinOp : CryptoElement { 14 | public BinOp() 15 | : base(2) { } 16 | 17 | public CryptoBinOps Operation { get; private set; } 18 | 19 | public override void Initialize(RandomGenerator random) { 20 | Operation = (CryptoBinOps)random.NextInt32(3); 21 | } 22 | 23 | public override void Emit(CipherGenContext context) { 24 | Expression a = context.GetDataExpression(DataIndexes[0]); 25 | Expression b = context.GetDataExpression(DataIndexes[1]); 26 | switch (Operation) { 27 | case CryptoBinOps.Add: 28 | context.Emit(new AssignmentStatement { 29 | Value = a + b, 30 | Target = a 31 | }); 32 | break; 33 | case CryptoBinOps.Xor: 34 | context.Emit(new AssignmentStatement { 35 | Value = a ^ b, 36 | Target = a 37 | }); 38 | break; 39 | case CryptoBinOps.Xnor: 40 | context.Emit(new AssignmentStatement { 41 | Value = ~(a ^ b), 42 | Target = a 43 | }); 44 | break; 45 | } 46 | } 47 | 48 | public override void EmitInverse(CipherGenContext context) { 49 | Expression a = context.GetDataExpression(DataIndexes[0]); 50 | Expression b = context.GetDataExpression(DataIndexes[1]); 51 | switch (Operation) { 52 | case CryptoBinOps.Add: 53 | context.Emit(new AssignmentStatement { 54 | Value = a - b, 55 | Target = a 56 | }); 57 | break; 58 | case CryptoBinOps.Xor: 59 | context.Emit(new AssignmentStatement { 60 | Value = a ^ b, 61 | Target = a 62 | }); 63 | break; 64 | case CryptoBinOps.Xnor: 65 | context.Emit(new AssignmentStatement { 66 | Value = a ^ (~b), 67 | Target = a 68 | }); 69 | break; 70 | } 71 | } 72 | } 73 | } -------------------------------------------------------------------------------- /Confuser.DynCipher/Elements/CryptoElement.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Confuser.Core.Services; 3 | using Confuser.DynCipher.Generation; 4 | 5 | namespace Confuser.DynCipher.Elements { 6 | internal abstract class CryptoElement { 7 | public CryptoElement(int count) { 8 | DataCount = count; 9 | DataIndexes = new int[count]; 10 | } 11 | 12 | public int DataCount { get; private set; } 13 | public int[] DataIndexes { get; private set; } 14 | 15 | public abstract void Initialize(RandomGenerator random); 16 | public abstract void Emit(CipherGenContext context); 17 | public abstract void EmitInverse(CipherGenContext context); 18 | } 19 | } -------------------------------------------------------------------------------- /Confuser.DynCipher/Elements/RotateBit.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Confuser.Core.Services; 3 | using Confuser.DynCipher.AST; 4 | using Confuser.DynCipher.Generation; 5 | 6 | namespace Confuser.DynCipher.Elements { 7 | internal class RotateBit : CryptoElement { 8 | public RotateBit() 9 | : base(1) { } 10 | 11 | public int Bits { get; private set; } 12 | public bool IsAlternate { get; private set; } 13 | 14 | public override void Initialize(RandomGenerator random) { 15 | Bits = random.NextInt32(1, 32); 16 | IsAlternate = (random.NextInt32() % 2 == 0); 17 | } 18 | 19 | public override void Emit(CipherGenContext context) { 20 | Expression val = context.GetDataExpression(DataIndexes[0]); 21 | VariableExpression tmp; 22 | using (context.AcquireTempVar(out tmp)) { 23 | if (IsAlternate) 24 | context.Emit(new AssignmentStatement { 25 | Value = (val >> (32 - Bits)), 26 | Target = tmp 27 | }).Emit(new AssignmentStatement { 28 | Value = (val << Bits) | tmp, 29 | Target = val 30 | }); 31 | else 32 | context.Emit(new AssignmentStatement { 33 | Value = (val << (32 - Bits)), 34 | Target = tmp 35 | }).Emit(new AssignmentStatement { 36 | Value = (val >> Bits) | tmp, 37 | Target = val 38 | }); 39 | } 40 | } 41 | 42 | public override void EmitInverse(CipherGenContext context) { 43 | Expression val = context.GetDataExpression(DataIndexes[0]); 44 | VariableExpression tmp; 45 | using (context.AcquireTempVar(out tmp)) { 46 | if (IsAlternate) 47 | context.Emit(new AssignmentStatement { 48 | Value = (val << (32 - Bits)), 49 | Target = tmp 50 | }).Emit(new AssignmentStatement { 51 | Value = (val >> Bits) | tmp, 52 | Target = val 53 | }); 54 | else 55 | context.Emit(new AssignmentStatement { 56 | Value = (val >> (32 - Bits)), 57 | Target = tmp 58 | }).Emit(new AssignmentStatement { 59 | Value = (val << Bits) | tmp, 60 | Target = val 61 | }); 62 | } 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /Confuser.DynCipher/Elements/Swap.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Confuser.Core.Services; 3 | using Confuser.DynCipher.AST; 4 | using Confuser.DynCipher.Generation; 5 | 6 | namespace Confuser.DynCipher.Elements { 7 | internal class Swap : CryptoElement { 8 | public Swap() 9 | : base(2) { } 10 | 11 | public uint Mask { get; private set; } 12 | public uint Key { get; private set; } 13 | 14 | public override void Initialize(RandomGenerator random) { 15 | if (random.NextInt32(3) == 0) 16 | Mask = 0xffffffff; 17 | else 18 | Mask = random.NextUInt32(); 19 | Key = random.NextUInt32() | 1; 20 | } 21 | 22 | void EmitCore(CipherGenContext context) { 23 | Expression a = context.GetDataExpression(DataIndexes[0]); 24 | Expression b = context.GetDataExpression(DataIndexes[1]); 25 | VariableExpression tmp; 26 | 27 | if (Mask == 0xffffffff) { 28 | /* t = a * k; 29 | a = b; 30 | b = t * k^-1; 31 | */ 32 | using (context.AcquireTempVar(out tmp)) { 33 | context.Emit(new AssignmentStatement { 34 | Value = a * (LiteralExpression)Key, 35 | Target = tmp 36 | }).Emit(new AssignmentStatement { 37 | Value = b, 38 | Target = a 39 | }).Emit(new AssignmentStatement { 40 | Value = tmp * (LiteralExpression)MathsUtils.modInv(Key), 41 | Target = b 42 | }); 43 | } 44 | } 45 | else { 46 | var mask = (LiteralExpression)Mask; 47 | var notMask = (LiteralExpression)~Mask; 48 | /* t = (a & mask) * k; 49 | a = a & (~mask) | (b & mask); 50 | b = b & (~mask) | (t * k^-1); 51 | */ 52 | using (context.AcquireTempVar(out tmp)) { 53 | context.Emit(new AssignmentStatement { 54 | Value = (a & mask) * (LiteralExpression)Key, 55 | Target = tmp 56 | }).Emit(new AssignmentStatement { 57 | Value = (a & notMask) | (b & mask), 58 | Target = a 59 | }).Emit(new AssignmentStatement { 60 | Value = (b & notMask) | (tmp * (LiteralExpression)MathsUtils.modInv(Key)), 61 | Target = b 62 | }); 63 | } 64 | } 65 | } 66 | 67 | public override void Emit(CipherGenContext context) { 68 | EmitCore(context); 69 | } 70 | 71 | public override void EmitInverse(CipherGenContext context) { 72 | EmitCore(context); 73 | } 74 | } 75 | } -------------------------------------------------------------------------------- /Confuser.DynCipher/Generation/CipherGenContext.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Confuser.Core.Services; 4 | using Confuser.DynCipher.AST; 5 | 6 | namespace Confuser.DynCipher.Generation { 7 | internal class CipherGenContext { 8 | readonly Variable[] dataVars; 9 | readonly Variable keyVar = new Variable("{KEY}"); 10 | readonly RandomGenerator random; 11 | readonly List tempVars = new List(); 12 | int tempVarCounter; 13 | 14 | public CipherGenContext(RandomGenerator random, int dataVarCount) { 15 | this.random = random; 16 | Block = new StatementBlock(); // new LoopStatement() { Begin = 0, Limit = 4 }; 17 | dataVars = new Variable[dataVarCount]; 18 | for (int i = 0; i < dataVarCount; i++) 19 | dataVars[i] = new Variable("v" + i) { Tag = i }; 20 | } 21 | 22 | public StatementBlock Block { get; private set; } 23 | 24 | public Expression GetDataExpression(int index) { 25 | return new VariableExpression { Variable = dataVars[index] }; 26 | } 27 | 28 | public Expression GetKeyExpression(int index) { 29 | return new ArrayIndexExpression { 30 | Array = new VariableExpression { Variable = keyVar }, 31 | Index = index 32 | }; 33 | } 34 | 35 | public CipherGenContext Emit(Statement statement) { 36 | Block.Statements.Add(statement); 37 | return this; 38 | } 39 | 40 | public IDisposable AcquireTempVar(out VariableExpression exp) { 41 | Variable var; 42 | if (tempVars.Count == 0) 43 | var = new Variable("t" + tempVarCounter++); 44 | else { 45 | var = tempVars[random.NextInt32(tempVars.Count)]; 46 | tempVars.Remove(var); 47 | } 48 | exp = new VariableExpression { Variable = var }; 49 | return new TempVarHolder(this, var); 50 | } 51 | 52 | struct TempVarHolder : IDisposable { 53 | readonly CipherGenContext parent; 54 | readonly Variable tempVar; 55 | 56 | public TempVarHolder(CipherGenContext p, Variable v) { 57 | parent = p; 58 | tempVar = v; 59 | } 60 | 61 | public void Dispose() { 62 | parent.tempVars.Add(tempVar); 63 | } 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /Confuser.DynCipher/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | 4 | [assembly: AssemblyTitle("ConfuserEx Dynamic Cipher Library")] 5 | [assembly: AssemblyDescription("Cipher generator of ConfuserEx")] -------------------------------------------------------------------------------- /Confuser.DynCipher/Transforms/ConvertVariables.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Confuser.DynCipher.AST; 3 | 4 | namespace Confuser.DynCipher.Transforms { 5 | internal class ConvertVariables { 6 | static Expression ReplaceVar(Expression exp, Variable buff) { 7 | if (exp is VariableExpression) { 8 | if (((VariableExpression)exp).Variable.Name[0] != 'v') return exp; 9 | return new ArrayIndexExpression { 10 | Array = new VariableExpression { Variable = buff }, 11 | Index = (int)(exp as VariableExpression).Variable.Tag 12 | }; 13 | } 14 | if (exp is ArrayIndexExpression) { 15 | ((ArrayIndexExpression)exp).Array = ReplaceVar(((ArrayIndexExpression)exp).Array, buff); 16 | } 17 | else if (exp is BinOpExpression) { 18 | ((BinOpExpression)exp).Left = ReplaceVar(((BinOpExpression)exp).Left, buff); 19 | ((BinOpExpression)exp).Right = ReplaceVar(((BinOpExpression)exp).Right, buff); 20 | } 21 | else if (exp is UnaryOpExpression) { 22 | ((UnaryOpExpression)exp).Value = ReplaceVar(((UnaryOpExpression)exp).Value, buff); 23 | } 24 | return exp; 25 | } 26 | 27 | static Statement ReplaceVar(Statement st, Variable buff) { 28 | if (st is AssignmentStatement) { 29 | ((AssignmentStatement)st).Value = ReplaceVar(((AssignmentStatement)st).Value, buff); 30 | ((AssignmentStatement)st).Target = ReplaceVar(((AssignmentStatement)st).Target, buff); 31 | } 32 | return st; 33 | } 34 | 35 | public static void Run(StatementBlock block) { 36 | var mainBuff = new Variable("{BUFFER}"); 37 | for (int i = 0; i < block.Statements.Count; i++) 38 | block.Statements[i] = ReplaceVar(block.Statements[i], mainBuff); 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /Confuser.DynCipher/Transforms/ExpansionTransform.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using Confuser.DynCipher.AST; 4 | 5 | namespace Confuser.DynCipher.Transforms { 6 | internal class ExpansionTransform { 7 | static bool ProcessStatement(Statement st, StatementBlock block) { 8 | if (st is AssignmentStatement) { 9 | var assign = (AssignmentStatement)st; 10 | if (assign.Value is BinOpExpression) { 11 | var exp = (BinOpExpression)assign.Value; 12 | if ((exp.Left is BinOpExpression || exp.Right is BinOpExpression) && 13 | exp.Left != assign.Target) { 14 | block.Statements.Add(new AssignmentStatement { 15 | Target = assign.Target, 16 | Value = exp.Left 17 | }); 18 | block.Statements.Add(new AssignmentStatement { 19 | Target = assign.Target, 20 | Value = new BinOpExpression { 21 | Left = assign.Target, 22 | Operation = exp.Operation, 23 | Right = exp.Right 24 | } 25 | }); 26 | return true; 27 | } 28 | } 29 | } 30 | block.Statements.Add(st); 31 | return false; 32 | } 33 | 34 | public static void Run(StatementBlock block) { 35 | bool workDone; 36 | do { 37 | workDone = false; 38 | Statement[] copy = block.Statements.ToArray(); 39 | block.Statements.Clear(); 40 | foreach (Statement st in copy) 41 | workDone |= ProcessStatement(st, block); 42 | } while (workDone); 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /Confuser.DynCipher/Transforms/MulToShiftTransform.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using Confuser.DynCipher.AST; 5 | 6 | namespace Confuser.DynCipher.Transforms { 7 | internal class MulToShiftTransform { 8 | static uint NumberOfSetBits(uint i) { 9 | i = i - ((i >> 1) & 0x55555555); 10 | i = (i & 0x33333333) + ((i >> 2) & 0x33333333); 11 | return (((i + (i >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24; 12 | } 13 | 14 | static Expression ProcessExpression(Expression exp) { 15 | if (exp is BinOpExpression) { 16 | var binOp = (BinOpExpression)exp; 17 | if (binOp.Operation == BinOps.Mul && binOp.Right is LiteralExpression) { 18 | // Decompose multiplication into shifts, e.g. x * 3 => x << 1 + x 19 | uint literal = ((LiteralExpression)binOp.Right).Value; 20 | if (literal == 0) return (LiteralExpression)0; 21 | if (literal == 1) return binOp.Left; 22 | 23 | uint bits = NumberOfSetBits(literal); 24 | if (bits <= 2) { 25 | var sum = new List(); 26 | int n = 0; 27 | while (literal != 0) { 28 | if ((literal & 1) != 0) { 29 | if (n == 0) 30 | sum.Add(binOp.Left); 31 | else 32 | sum.Add(binOp.Left << n); 33 | } 34 | literal >>= 1; 35 | n++; 36 | } 37 | BinOpExpression x = sum.OfType().First(); 38 | foreach (Expression i in sum.Except(new[] { x })) 39 | x += i; 40 | return x; 41 | } 42 | } 43 | else { 44 | binOp.Left = ProcessExpression(binOp.Left); 45 | binOp.Right = ProcessExpression(binOp.Right); 46 | } 47 | } 48 | else if (exp is ArrayIndexExpression) { 49 | ((ArrayIndexExpression)exp).Array = ProcessExpression(((ArrayIndexExpression)exp).Array); 50 | } 51 | else if (exp is UnaryOpExpression) { 52 | ((UnaryOpExpression)exp).Value = ProcessExpression(((UnaryOpExpression)exp).Value); 53 | } 54 | return exp; 55 | } 56 | 57 | static void ProcessStatement(Statement st) { 58 | if (st is AssignmentStatement) { 59 | var assign = (AssignmentStatement)st; 60 | assign.Target = ProcessExpression(assign.Target); 61 | assign.Value = ProcessExpression(assign.Value); 62 | } 63 | } 64 | 65 | public static void Run(StatementBlock block) { 66 | foreach (Statement st in block.Statements) 67 | ProcessStatement(st); 68 | } 69 | } 70 | } -------------------------------------------------------------------------------- /Confuser.DynCipher/Transforms/NormalizeBinOpTransform.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Confuser.DynCipher.AST; 3 | 4 | namespace Confuser.DynCipher.Transforms { 5 | internal class NormalizeBinOpTransform { 6 | static Expression ProcessExpression(Expression exp) { 7 | if (exp is BinOpExpression) { 8 | var binOp = (BinOpExpression)exp; 9 | var binOpRight = binOp.Right as BinOpExpression; 10 | // a + (b + c) => (a + b) + c 11 | if (binOpRight != null && binOpRight.Operation == binOp.Operation && 12 | (binOp.Operation == BinOps.Add || binOp.Operation == BinOps.Mul || 13 | binOp.Operation == BinOps.Or || binOp.Operation == BinOps.And || 14 | binOp.Operation == BinOps.Xor)) { 15 | binOp.Left = new BinOpExpression { 16 | Left = binOp.Left, 17 | Operation = binOp.Operation, 18 | Right = binOpRight.Left 19 | }; 20 | binOp.Right = binOpRight.Right; 21 | } 22 | 23 | binOp.Left = ProcessExpression(binOp.Left); 24 | binOp.Right = ProcessExpression(binOp.Right); 25 | 26 | if (binOp.Right is LiteralExpression && ((LiteralExpression)binOp.Right).Value == 0 && 27 | binOp.Operation == BinOps.Add) // x + 0 => x 28 | return binOp.Left; 29 | } 30 | else if (exp is ArrayIndexExpression) { 31 | ((ArrayIndexExpression)exp).Array = ProcessExpression(((ArrayIndexExpression)exp).Array); 32 | } 33 | else if (exp is UnaryOpExpression) { 34 | ((UnaryOpExpression)exp).Value = ProcessExpression(((UnaryOpExpression)exp).Value); 35 | } 36 | return exp; 37 | } 38 | 39 | static void ProcessStatement(Statement st) { 40 | if (st is AssignmentStatement) { 41 | var assign = (AssignmentStatement)st; 42 | assign.Target = ProcessExpression(assign.Target); 43 | assign.Value = ProcessExpression(assign.Value); 44 | } 45 | } 46 | 47 | public static void Run(StatementBlock block) { 48 | foreach (Statement st in block.Statements) 49 | ProcessStatement(st); 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /Confuser.Protections/AntiDumpProtection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using Confuser.Core; 5 | using Confuser.Core.Helpers; 6 | using Confuser.Core.Services; 7 | using Confuser.Renamer; 8 | using dnlib.DotNet; 9 | using dnlib.DotNet.Emit; 10 | 11 | namespace Confuser.Protections { 12 | [BeforeProtection("Ki.ControlFlow")] 13 | internal class AntiDumpProtection : Protection { 14 | public const string _Id = "anti dump"; 15 | public const string _FullId = "Ki.AntiDump"; 16 | 17 | public override string Name { 18 | get { return "Anti Dump Protection"; } 19 | } 20 | 21 | public override string Description { 22 | get { return "This protection prevents the assembly from being dumped from memory."; } 23 | } 24 | 25 | public override string Id { 26 | get { return _Id; } 27 | } 28 | 29 | public override string FullId { 30 | get { return _FullId; } 31 | } 32 | 33 | public override ProtectionPreset Preset { 34 | get { return ProtectionPreset.Maximum; } 35 | } 36 | 37 | protected override void Initialize(ConfuserContext context) { 38 | // 39 | } 40 | 41 | protected override void PopulatePipeline(ProtectionPipeline pipeline) { 42 | pipeline.InsertPreStage(PipelineStage.ProcessModule, new AntiDumpPhase(this)); 43 | } 44 | 45 | class AntiDumpPhase : ProtectionPhase { 46 | public AntiDumpPhase(AntiDumpProtection parent) 47 | : base(parent) { } 48 | 49 | public override ProtectionTargets Targets { 50 | get { return ProtectionTargets.Modules; } 51 | } 52 | 53 | public override string Name { 54 | get { return "Anti-dump injection"; } 55 | } 56 | 57 | protected override void Execute(ConfuserContext context, ProtectionParameters parameters) { 58 | TypeDef rtType = context.Registry.GetService().GetRuntimeType("Confuser.Runtime.AntiDump"); 59 | 60 | var marker = context.Registry.GetService(); 61 | var name = context.Registry.GetService(); 62 | 63 | foreach (ModuleDef module in parameters.Targets.OfType()) { 64 | IEnumerable members = InjectHelper.Inject(rtType, module.GlobalType, module); 65 | 66 | MethodDef cctor = module.GlobalType.FindStaticConstructor(); 67 | var init = (MethodDef)members.Single(method => method.Name == "Initialize"); 68 | cctor.Body.Instructions.Insert(0, Instruction.Create(OpCodes.Call, init)); 69 | 70 | foreach (IDnlibDef member in members) 71 | name.MarkHelper(member, marker, (Protection)Parent); 72 | } 73 | } 74 | } 75 | } 76 | } -------------------------------------------------------------------------------- /Confuser.Protections/AntiILDasmProtection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using Confuser.Core; 4 | using dnlib.DotNet; 5 | 6 | namespace Confuser.Protections { 7 | internal class AntiILDasmProtection : Protection { 8 | public const string _Id = "anti ildasm"; 9 | public const string _FullId = "Ki.AntiILDasm"; 10 | 11 | public override string Name { 12 | get { return "Anti IL Dasm Protection"; } 13 | } 14 | 15 | public override string Description { 16 | get { return "This protection marks the module with a attribute that discourage ILDasm from disassembling it."; } 17 | } 18 | 19 | public override string Id { 20 | get { return _Id; } 21 | } 22 | 23 | public override string FullId { 24 | get { return _FullId; } 25 | } 26 | 27 | public override ProtectionPreset Preset { 28 | get { return ProtectionPreset.Minimum; } 29 | } 30 | 31 | protected override void Initialize(ConfuserContext context) { 32 | // 33 | } 34 | 35 | protected override void PopulatePipeline(ProtectionPipeline pipeline) { 36 | pipeline.InsertPreStage(PipelineStage.ProcessModule, new AntiILDasmPhase(this)); 37 | } 38 | 39 | class AntiILDasmPhase : ProtectionPhase { 40 | public AntiILDasmPhase(AntiILDasmProtection parent) 41 | : base(parent) { } 42 | 43 | public override ProtectionTargets Targets { 44 | get { return ProtectionTargets.Modules; } 45 | } 46 | 47 | public override string Name { 48 | get { return "Anti-ILDasm marking"; } 49 | } 50 | 51 | protected override void Execute(ConfuserContext context, ProtectionParameters parameters) { 52 | foreach (ModuleDef module in parameters.Targets.OfType()) { 53 | TypeRef attrRef = module.CorLibTypes.GetTypeRef("System.Runtime.CompilerServices", "SuppressIldasmAttribute"); 54 | var ctorRef = new MemberRefUser(module, ".ctor", MethodSig.CreateInstance(module.CorLibTypes.Void), attrRef); 55 | 56 | var attr = new CustomAttribute(ctorRef); 57 | module.CustomAttributes.Add(attr); 58 | } 59 | } 60 | } 61 | } 62 | } -------------------------------------------------------------------------------- /Confuser.Protections/AntiTamper/DynamicDeriver.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Confuser.Core; 4 | using Confuser.Core.Services; 5 | using Confuser.DynCipher; 6 | using Confuser.DynCipher.AST; 7 | using Confuser.DynCipher.Generation; 8 | using dnlib.DotNet; 9 | using dnlib.DotNet.Emit; 10 | 11 | namespace Confuser.Protections.AntiTamper { 12 | internal class DynamicDeriver : IKeyDeriver { 13 | StatementBlock derivation; 14 | Action encryptFunc; 15 | 16 | public void Init(ConfuserContext ctx, RandomGenerator random) { 17 | StatementBlock dummy; 18 | ctx.Registry.GetService().GenerateCipherPair(random, out derivation, out dummy); 19 | 20 | var dmCodeGen = new DMCodeGen(typeof(void), new[] { 21 | Tuple.Create("{BUFFER}", typeof(uint[])), 22 | Tuple.Create("{KEY}", typeof(uint[])) 23 | }); 24 | dmCodeGen.GenerateCIL(derivation); 25 | encryptFunc = dmCodeGen.Compile>(); 26 | } 27 | 28 | public uint[] DeriveKey(uint[] a, uint[] b) { 29 | var ret = new uint[0x10]; 30 | Buffer.BlockCopy(a, 0, ret, 0, a.Length * sizeof(uint)); 31 | encryptFunc(ret, b); 32 | return ret; 33 | } 34 | 35 | public IEnumerable EmitDerivation(MethodDef method, ConfuserContext ctx, Local dst, Local src) { 36 | var ret = new List(); 37 | var codeGen = new CodeGen(dst, src, method, ret); 38 | codeGen.GenerateCIL(derivation); 39 | codeGen.Commit(method.Body); 40 | return ret; 41 | } 42 | 43 | class CodeGen : CILCodeGen { 44 | readonly Local block; 45 | readonly Local key; 46 | 47 | public CodeGen(Local block, Local key, MethodDef method, IList instrs) 48 | : base(method, instrs) { 49 | this.block = block; 50 | this.key = key; 51 | } 52 | 53 | protected override Local Var(Variable var) { 54 | if (var.Name == "{BUFFER}") 55 | return block; 56 | if (var.Name == "{KEY}") 57 | return key; 58 | return base.Var(var); 59 | } 60 | } 61 | } 62 | } -------------------------------------------------------------------------------- /Confuser.Protections/AntiTamper/IKeyDeriver.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Confuser.Core; 4 | using Confuser.Core.Services; 5 | using dnlib.DotNet; 6 | using dnlib.DotNet.Emit; 7 | 8 | namespace Confuser.Protections.AntiTamper { 9 | internal enum Mode { 10 | Normal, 11 | Dynamic 12 | } 13 | 14 | internal interface IKeyDeriver { 15 | void Init(ConfuserContext ctx, RandomGenerator random); 16 | uint[] DeriveKey(uint[] a, uint[] b); 17 | IEnumerable EmitDerivation(MethodDef method, ConfuserContext ctx, Local dst, Local src); 18 | } 19 | } -------------------------------------------------------------------------------- /Confuser.Protections/AntiTamper/IModeHandler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Confuser.Core; 3 | 4 | namespace Confuser.Protections.AntiTamper { 5 | internal interface IModeHandler { 6 | void HandleInject(AntiTamperProtection parent, ConfuserContext context, ProtectionParameters parameters); 7 | void HandleMD(AntiTamperProtection parent, ConfuserContext context, ProtectionParameters parameters); 8 | } 9 | } -------------------------------------------------------------------------------- /Confuser.Protections/AntiTamper/NormalDeriver.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Confuser.Core; 4 | using Confuser.Core.Services; 5 | using dnlib.DotNet; 6 | using dnlib.DotNet.Emit; 7 | 8 | namespace Confuser.Protections.AntiTamper { 9 | internal class NormalDeriver : IKeyDeriver { 10 | public void Init(ConfuserContext ctx, RandomGenerator random) { 11 | // 12 | } 13 | 14 | public uint[] DeriveKey(uint[] a, uint[] b) { 15 | var ret = new uint[0x10]; 16 | for (int i = 0; i < 0x10; i++) { 17 | switch (i % 3) { 18 | case 0: 19 | ret[i] = a[i] ^ b[i]; 20 | break; 21 | case 1: 22 | ret[i] = a[i] * b[i]; 23 | break; 24 | case 2: 25 | ret[i] = a[i] + b[i]; 26 | break; 27 | } 28 | } 29 | return ret; 30 | } 31 | 32 | public IEnumerable EmitDerivation(MethodDef method, ConfuserContext ctx, Local dst, Local src) { 33 | for (int i = 0; i < 0x10; i++) { 34 | yield return Instruction.Create(OpCodes.Ldloc, dst); 35 | yield return Instruction.Create(OpCodes.Ldc_I4, i); 36 | yield return Instruction.Create(OpCodes.Ldloc, dst); 37 | yield return Instruction.Create(OpCodes.Ldc_I4, i); 38 | yield return Instruction.Create(OpCodes.Ldelem_U4); 39 | yield return Instruction.Create(OpCodes.Ldloc, src); 40 | yield return Instruction.Create(OpCodes.Ldc_I4, i); 41 | yield return Instruction.Create(OpCodes.Ldelem_U4); 42 | switch (i % 3) { 43 | case 0: 44 | yield return Instruction.Create(OpCodes.Xor); 45 | break; 46 | case 1: 47 | yield return Instruction.Create(OpCodes.Mul); 48 | break; 49 | case 2: 50 | yield return Instruction.Create(OpCodes.Add); 51 | break; 52 | } 53 | yield return Instruction.Create(OpCodes.Stelem_I4); 54 | } 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /Confuser.Protections/Compress/CompressorContext.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Confuser.Core.Services; 4 | using dnlib.DotNet; 5 | 6 | namespace Confuser.Protections.Compress { 7 | internal class CompressorContext { 8 | public AssemblyDef Assembly; 9 | public IKeyDeriver Deriver; 10 | public byte[] EncryptedModule; 11 | public MethodDef EntryPoint; 12 | public uint EntryPointToken; 13 | public byte[] KeySig; 14 | public uint KeyToken; 15 | public ModuleKind Kind; 16 | public List> ManifestResources; 17 | public int ModuleIndex; 18 | public string ModuleName; 19 | public byte[] OriginModule; 20 | public ModuleDef OriginModuleDef; 21 | public bool CompatMode; 22 | 23 | public byte[] Encrypt(ICompressionService compress, byte[] data, uint seed, Action progressFunc) { 24 | data = (byte[])data.Clone(); 25 | var dst = new uint[0x10]; 26 | var src = new uint[0x10]; 27 | ulong state = seed; 28 | for (int i = 0; i < 0x10; i++) { 29 | state = (state * state) % 0x143fc089; 30 | src[i] = (uint)state; 31 | dst[i] = (uint)((state * state) % 0x444d56fb); 32 | } 33 | uint[] key = Deriver.DeriveKey(dst, src); 34 | 35 | var z = (uint)(state % 0x8a5cb7); 36 | for (int i = 0; i < data.Length; i++) { 37 | data[i] ^= (byte)state; 38 | if ((i & 0xff) == 0) 39 | state = (state * state) % 0x8a5cb7; 40 | } 41 | data = compress.Compress(data, progressFunc); 42 | Array.Resize(ref data, (data.Length + 3) & ~3); 43 | 44 | var encryptedData = new byte[data.Length]; 45 | int keyIndex = 0; 46 | for (int i = 0; i < data.Length; i += 4) { 47 | var datum = (uint)(data[i + 0] | (data[i + 1] << 8) | (data[i + 2] << 16) | (data[i + 3] << 24)); 48 | uint encrypted = datum ^ key[keyIndex & 0xf]; 49 | key[keyIndex & 0xf] = (key[keyIndex & 0xf] ^ datum) + 0x3ddb2819; 50 | encryptedData[i + 0] = (byte)(encrypted >> 0); 51 | encryptedData[i + 1] = (byte)(encrypted >> 8); 52 | encryptedData[i + 2] = (byte)(encrypted >> 16); 53 | encryptedData[i + 3] = (byte)(encrypted >> 24); 54 | keyIndex++; 55 | } 56 | 57 | return encryptedData; 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /Confuser.Protections/Compress/DynamicDeriver.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Confuser.Core; 4 | using Confuser.Core.Services; 5 | using Confuser.DynCipher; 6 | using Confuser.DynCipher.AST; 7 | using Confuser.DynCipher.Generation; 8 | using dnlib.DotNet; 9 | using dnlib.DotNet.Emit; 10 | 11 | namespace Confuser.Protections.Compress { 12 | internal class DynamicDeriver : IKeyDeriver { 13 | StatementBlock derivation; 14 | Action encryptFunc; 15 | 16 | public void Init(ConfuserContext ctx, RandomGenerator random) { 17 | StatementBlock dummy; 18 | ctx.Registry.GetService().GenerateCipherPair(random, out derivation, out dummy); 19 | 20 | var dmCodeGen = new DMCodeGen(typeof(void), new[] { 21 | Tuple.Create("{BUFFER}", typeof(uint[])), 22 | Tuple.Create("{KEY}", typeof(uint[])) 23 | }); 24 | dmCodeGen.GenerateCIL(derivation); 25 | encryptFunc = dmCodeGen.Compile>(); 26 | } 27 | 28 | public uint[] DeriveKey(uint[] a, uint[] b) { 29 | var ret = new uint[0x10]; 30 | Buffer.BlockCopy(a, 0, ret, 0, a.Length * sizeof(uint)); 31 | encryptFunc(ret, b); 32 | return ret; 33 | } 34 | 35 | public IEnumerable EmitDerivation(MethodDef method, ConfuserContext ctx, Local dst, Local src) { 36 | var ret = new List(); 37 | var codeGen = new CodeGen(dst, src, method, ret); 38 | codeGen.GenerateCIL(derivation); 39 | codeGen.Commit(method.Body); 40 | return ret; 41 | } 42 | 43 | class CodeGen : CILCodeGen { 44 | readonly Local block; 45 | readonly Local key; 46 | 47 | public CodeGen(Local block, Local key, MethodDef method, IList instrs) 48 | : base(method, instrs) { 49 | this.block = block; 50 | this.key = key; 51 | } 52 | 53 | protected override Local Var(Variable var) { 54 | if (var.Name == "{BUFFER}") 55 | return block; 56 | if (var.Name == "{KEY}") 57 | return key; 58 | return base.Var(var); 59 | } 60 | } 61 | } 62 | } -------------------------------------------------------------------------------- /Confuser.Protections/Compress/IKeyDeriver.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Confuser.Core; 4 | using Confuser.Core.Services; 5 | using dnlib.DotNet; 6 | using dnlib.DotNet.Emit; 7 | 8 | namespace Confuser.Protections.Compress { 9 | internal enum Mode { 10 | Normal, 11 | Dynamic 12 | } 13 | 14 | internal interface IKeyDeriver { 15 | void Init(ConfuserContext ctx, RandomGenerator random); 16 | uint[] DeriveKey(uint[] a, uint[] b); 17 | IEnumerable EmitDerivation(MethodDef method, ConfuserContext ctx, Local dst, Local src); 18 | } 19 | } -------------------------------------------------------------------------------- /Confuser.Protections/Constants/CEContext.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Confuser.Core; 4 | using Confuser.Core.Services; 5 | using Confuser.DynCipher; 6 | using Confuser.Renamer; 7 | using dnlib.DotNet; 8 | using dnlib.DotNet.Emit; 9 | 10 | namespace Confuser.Protections.Constants { 11 | internal class CEContext { 12 | public ConfuserContext Context; 13 | public ConstantProtection Protection; 14 | public ModuleDef Module; 15 | 16 | public FieldDef BufferField; 17 | public FieldDef DataField; 18 | public TypeDef DataType; 19 | public MethodDef InitMethod; 20 | 21 | public int DecoderCount; 22 | public List> Decoders; 23 | 24 | public EncodeElements Elements; 25 | public List EncodedBuffer; 26 | 27 | public Mode Mode; 28 | public IEncodeMode ModeHandler; 29 | 30 | public IDynCipherService DynCipher; 31 | public IMarkerService Marker; 32 | public INameService Name; 33 | public RandomGenerator Random; 34 | 35 | public TypeDef CfgCtxType; 36 | public MethodDef CfgCtxCtor; 37 | public MethodDef CfgCtxNext; 38 | public Dictionary>> ReferenceRepl; 39 | } 40 | 41 | internal class DecoderDesc { 42 | public object Data; 43 | public byte InitializerID; 44 | public byte NumberID; 45 | public byte StringID; 46 | } 47 | } -------------------------------------------------------------------------------- /Confuser.Protections/Constants/ConstantProtection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Confuser.Core; 3 | using Confuser.Protections.Constants; 4 | using dnlib.DotNet; 5 | 6 | namespace Confuser.Protections { 7 | public interface IConstantService { 8 | void ExcludeMethod(ConfuserContext context, MethodDef method); 9 | } 10 | 11 | [BeforeProtection("Ki.ControlFlow"), AfterProtection("Ki.RefProxy")] 12 | internal class ConstantProtection : Protection, IConstantService { 13 | public const string _Id = "constants"; 14 | public const string _FullId = "Ki.Constants"; 15 | public const string _ServiceId = "Ki.Constants"; 16 | internal static readonly object ContextKey = new object(); 17 | 18 | public override string Name { 19 | get { return "Constants Protection"; } 20 | } 21 | 22 | public override string Description { 23 | get { return "This protection encodes and compresses constants in the code."; } 24 | } 25 | 26 | public override string Id { 27 | get { return _Id; } 28 | } 29 | 30 | public override string FullId { 31 | get { return _FullId; } 32 | } 33 | 34 | public override ProtectionPreset Preset { 35 | get { return ProtectionPreset.Normal; } 36 | } 37 | 38 | public void ExcludeMethod(ConfuserContext context, MethodDef method) { 39 | ProtectionParameters.GetParameters(context, method).Remove(this); 40 | } 41 | 42 | protected override void Initialize(ConfuserContext context) { 43 | context.Registry.RegisterService(_ServiceId, typeof(IConstantService), this); 44 | } 45 | 46 | protected override void PopulatePipeline(ProtectionPipeline pipeline) { 47 | pipeline.InsertPreStage(PipelineStage.ProcessModule, new InjectPhase(this)); 48 | pipeline.InsertPostStage(PipelineStage.ProcessModule, new EncodePhase(this)); 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /Confuser.Protections/Constants/EncodeElements.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Confuser.Protections.Constants { 4 | [Flags] 5 | internal enum EncodeElements { 6 | Strings = 1, 7 | Numbers = 2, 8 | Primitive = 4, 9 | Initializers = 8 10 | } 11 | } -------------------------------------------------------------------------------- /Confuser.Protections/Constants/IEncodeMode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using dnlib.DotNet; 4 | using dnlib.DotNet.Emit; 5 | 6 | namespace Confuser.Protections.Constants { 7 | internal interface IEncodeMode { 8 | IEnumerable EmitDecrypt(MethodDef init, CEContext ctx, Local block, Local key); 9 | uint[] Encrypt(uint[] data, int offset, uint[] key); 10 | 11 | object CreateDecoder(MethodDef decoder, CEContext ctx); 12 | uint Encode(object data, CEContext ctx, uint id); 13 | } 14 | } -------------------------------------------------------------------------------- /Confuser.Protections/Constants/Mode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Confuser.Protections.Constants { 4 | internal enum Mode { 5 | Normal, 6 | Dynamic, 7 | x86 8 | } 9 | } -------------------------------------------------------------------------------- /Confuser.Protections/Constants/NormalMode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using Confuser.Core.Helpers; 5 | using Confuser.DynCipher; 6 | using dnlib.DotNet; 7 | using dnlib.DotNet.Emit; 8 | 9 | namespace Confuser.Protections.Constants { 10 | internal class NormalMode : IEncodeMode { 11 | public IEnumerable EmitDecrypt(MethodDef init, CEContext ctx, Local block, Local key) { 12 | for (int i = 0; i < 0x10; i++) { 13 | yield return Instruction.Create(OpCodes.Ldloc, block); 14 | yield return Instruction.Create(OpCodes.Ldc_I4, i); 15 | yield return Instruction.Create(OpCodes.Ldloc, block); 16 | yield return Instruction.Create(OpCodes.Ldc_I4, i); 17 | yield return Instruction.Create(OpCodes.Ldelem_U4); 18 | yield return Instruction.Create(OpCodes.Ldloc, key); 19 | yield return Instruction.Create(OpCodes.Ldc_I4, i); 20 | yield return Instruction.Create(OpCodes.Ldelem_U4); 21 | yield return Instruction.Create(OpCodes.Xor); 22 | yield return Instruction.Create(OpCodes.Stelem_I4); 23 | } 24 | } 25 | 26 | public uint[] Encrypt(uint[] data, int offset, uint[] key) { 27 | var ret = new uint[key.Length]; 28 | for (int i = 0; i < key.Length; i++) 29 | ret[i] = data[i + offset] ^ key[i]; 30 | return ret; 31 | } 32 | 33 | public object CreateDecoder(MethodDef decoder, CEContext ctx) { 34 | uint k1 = ctx.Random.NextUInt32() | 1; 35 | uint k2 = ctx.Random.NextUInt32(); 36 | MutationHelper.ReplacePlaceholder(decoder, arg => { 37 | var repl = new List(); 38 | repl.AddRange(arg); 39 | repl.Add(Instruction.Create(OpCodes.Ldc_I4, (int)MathsUtils.modInv(k1))); 40 | repl.Add(Instruction.Create(OpCodes.Mul)); 41 | repl.Add(Instruction.Create(OpCodes.Ldc_I4, (int)k2)); 42 | repl.Add(Instruction.Create(OpCodes.Xor)); 43 | return repl.ToArray(); 44 | }); 45 | return Tuple.Create(k1, k2); 46 | } 47 | 48 | public uint Encode(object data, CEContext ctx, uint id) { 49 | var key = (Tuple)data; 50 | uint ret = (id ^ key.Item2) * key.Item1; 51 | Debug.Assert(((ret * MathsUtils.modInv(key.Item1)) ^ key.Item2) == id); 52 | return ret; 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /Confuser.Protections/ControlFlow/ControlFlowProtection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Confuser.Core; 3 | using Confuser.Protections.ControlFlow; 4 | using dnlib.DotNet; 5 | 6 | namespace Confuser.Protections { 7 | public interface IControlFlowService { 8 | void ExcludeMethod(ConfuserContext context, MethodDef method); 9 | } 10 | 11 | internal class ControlFlowProtection : Protection, IControlFlowService { 12 | public const string _Id = "ctrl flow"; 13 | public const string _FullId = "Ki.ControlFlow"; 14 | public const string _ServiceId = "Ki.ControlFlow"; 15 | 16 | public override string Name { 17 | get { return "Control Flow Protection"; } 18 | } 19 | 20 | public override string Description { 21 | get { return "This protection mangles the code in the methods so that decompilers cannot decompile the methods."; } 22 | } 23 | 24 | public override string Id { 25 | get { return _Id; } 26 | } 27 | 28 | public override string FullId { 29 | get { return _FullId; } 30 | } 31 | 32 | public override ProtectionPreset Preset { 33 | get { return ProtectionPreset.Normal; } 34 | } 35 | 36 | public void ExcludeMethod(ConfuserContext context, MethodDef method) { 37 | ProtectionParameters.GetParameters(context, method).Remove(this); 38 | } 39 | 40 | protected override void Initialize(ConfuserContext context) { 41 | context.Registry.RegisterService(_ServiceId, typeof(IControlFlowService), this); 42 | } 43 | 44 | protected override void PopulatePipeline(ProtectionPipeline pipeline) { 45 | pipeline.InsertPreStage(PipelineStage.OptimizeMethods, new ControlFlowPhase(this)); 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /Confuser.Protections/ControlFlow/ExpressionPredicate.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Confuser.DynCipher.AST; 4 | using Confuser.DynCipher.Generation; 5 | using dnlib.DotNet.Emit; 6 | 7 | namespace Confuser.Protections.ControlFlow { 8 | internal class ExpressionPredicate : IPredicate { 9 | readonly CFContext ctx; 10 | Func expCompiled; 11 | Expression expression; 12 | 13 | bool inited; 14 | List invCompiled; 15 | Expression inverse; 16 | Local stateVar; 17 | 18 | public ExpressionPredicate(CFContext ctx) { 19 | this.ctx = ctx; 20 | } 21 | 22 | public void Init(CilBody body) { 23 | if (inited) 24 | return; 25 | stateVar = new Local(ctx.Method.Module.CorLibTypes.Int32); 26 | body.Variables.Add(stateVar); 27 | body.InitLocals = true; 28 | Compile(body); 29 | inited = true; 30 | } 31 | 32 | public void EmitSwitchLoad(IList instrs) { 33 | instrs.Add(Instruction.Create(OpCodes.Stloc, stateVar)); 34 | foreach (Instruction instr in invCompiled) 35 | instrs.Add(instr.Clone()); 36 | } 37 | 38 | public int GetSwitchKey(int key) { 39 | return expCompiled(key); 40 | } 41 | 42 | void Compile(CilBody body) { 43 | var var = new Variable("{VAR}"); 44 | var result = new Variable("{RESULT}"); 45 | 46 | ctx.DynCipher.GenerateExpressionPair( 47 | ctx.Random, 48 | new VariableExpression { Variable = var }, new VariableExpression { Variable = result }, 49 | ctx.Depth, out expression, out inverse); 50 | 51 | expCompiled = new DMCodeGen(typeof(int), new[] { Tuple.Create("{VAR}", typeof(int)) }) 52 | .GenerateCIL(expression) 53 | .Compile>(); 54 | 55 | invCompiled = new List(); 56 | new CodeGen(stateVar, ctx, invCompiled).GenerateCIL(inverse); 57 | body.MaxStack += (ushort)ctx.Depth; 58 | } 59 | 60 | class CodeGen : CILCodeGen { 61 | readonly Local state; 62 | 63 | public CodeGen(Local state, CFContext ctx, IList instrs) 64 | : base(ctx.Method, instrs) { 65 | this.state = state; 66 | } 67 | 68 | protected override Local Var(Variable var) { 69 | if (var.Name == "{RESULT}") 70 | return state; 71 | return base.Var(var); 72 | } 73 | } 74 | } 75 | } -------------------------------------------------------------------------------- /Confuser.Protections/ControlFlow/IPredicate.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using dnlib.DotNet.Emit; 4 | 5 | namespace Confuser.Protections.ControlFlow { 6 | internal interface IPredicate { 7 | void Init(CilBody body); 8 | void EmitSwitchLoad(IList instrs); 9 | int GetSwitchKey(int key); 10 | } 11 | } -------------------------------------------------------------------------------- /Confuser.Protections/ControlFlow/ManglerBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using dnlib.DotNet.Emit; 4 | 5 | namespace Confuser.Protections.ControlFlow { 6 | internal abstract class ManglerBase { 7 | protected static IEnumerable GetAllBlocks(ScopeBlock scope) { 8 | foreach (BlockBase child in scope.Children) { 9 | if (child is InstrBlock) 10 | yield return (InstrBlock)child; 11 | else { 12 | foreach (InstrBlock block in GetAllBlocks((ScopeBlock)child)) 13 | yield return block; 14 | } 15 | } 16 | } 17 | 18 | public abstract void Mangle(CilBody body, ScopeBlock root, CFContext ctx); 19 | } 20 | } -------------------------------------------------------------------------------- /Confuser.Protections/ControlFlow/NormalPredicate.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using dnlib.DotNet.Emit; 4 | 5 | namespace Confuser.Protections.ControlFlow { 6 | internal class NormalPredicate : IPredicate { 7 | readonly CFContext ctx; 8 | bool inited; 9 | int xorKey; 10 | 11 | public NormalPredicate(CFContext ctx) { 12 | this.ctx = ctx; 13 | } 14 | 15 | public void Init(CilBody body) { 16 | if (inited) 17 | return; 18 | 19 | xorKey = ctx.Random.NextInt32(); 20 | inited = true; 21 | } 22 | 23 | public void EmitSwitchLoad(IList instrs) { 24 | instrs.Add(Instruction.Create(OpCodes.Ldc_I4, xorKey)); 25 | instrs.Add(Instruction.Create(OpCodes.Xor)); 26 | } 27 | 28 | public int GetSwitchKey(int key) { 29 | return key ^ xorKey; 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /Confuser.Protections/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | 4 | [assembly: AssemblyTitle("ConfuserEx Protections")] 5 | [assembly: AssemblyDescription("Protections and packers of ConfuserEx")] -------------------------------------------------------------------------------- /Confuser.Protections/ReferenceProxy/ExpressionEncoding.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Confuser.DynCipher.AST; 4 | using Confuser.DynCipher.Generation; 5 | using dnlib.DotNet; 6 | using dnlib.DotNet.Emit; 7 | 8 | namespace Confuser.Protections.ReferenceProxy { 9 | internal class ExpressionEncoding : IRPEncoding { 10 | readonly Dictionary>> keys = new Dictionary>>(); 11 | 12 | public Instruction[] EmitDecode(MethodDef init, RPContext ctx, Instruction[] arg) { 13 | Tuple> key = GetKey(ctx, init); 14 | 15 | var invCompiled = new List(); 16 | new CodeGen(arg, ctx.Method, invCompiled).GenerateCIL(key.Item1); 17 | init.Body.MaxStack += (ushort)ctx.Depth; 18 | return invCompiled.ToArray(); 19 | } 20 | 21 | public int Encode(MethodDef init, RPContext ctx, int value) { 22 | Tuple> key = GetKey(ctx, init); 23 | return key.Item2(value); 24 | } 25 | 26 | void Compile(RPContext ctx, CilBody body, out Func expCompiled, out Expression inverse) { 27 | var var = new Variable("{VAR}"); 28 | var result = new Variable("{RESULT}"); 29 | 30 | Expression expression; 31 | ctx.DynCipher.GenerateExpressionPair( 32 | ctx.Random, 33 | new VariableExpression { Variable = var }, new VariableExpression { Variable = result }, 34 | ctx.Depth, out expression, out inverse); 35 | 36 | expCompiled = new DMCodeGen(typeof(int), new[] { Tuple.Create("{VAR}", typeof(int)) }) 37 | .GenerateCIL(expression) 38 | .Compile>(); 39 | } 40 | 41 | Tuple> GetKey(RPContext ctx, MethodDef init) { 42 | Tuple> ret; 43 | if (!keys.TryGetValue(init, out ret)) { 44 | Func keyFunc; 45 | Expression inverse; 46 | Compile(ctx, init.Body, out keyFunc, out inverse); 47 | keys[init] = ret = Tuple.Create(inverse, keyFunc); 48 | } 49 | return ret; 50 | } 51 | 52 | class CodeGen : CILCodeGen { 53 | readonly Instruction[] arg; 54 | 55 | public CodeGen(Instruction[] arg, MethodDef method, IList instrs) 56 | : base(method, instrs) { 57 | this.arg = arg; 58 | } 59 | 60 | protected override void LoadVar(Variable var) { 61 | if (var.Name == "{RESULT}") { 62 | foreach (Instruction instr in arg) 63 | Emit(instr); 64 | } 65 | else 66 | base.LoadVar(var); 67 | } 68 | } 69 | } 70 | } -------------------------------------------------------------------------------- /Confuser.Protections/ReferenceProxy/IRPEncoding.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using dnlib.DotNet; 3 | using dnlib.DotNet.Emit; 4 | 5 | namespace Confuser.Protections.ReferenceProxy { 6 | internal interface IRPEncoding { 7 | Instruction[] EmitDecode(MethodDef init, RPContext ctx, Instruction[] arg); 8 | int Encode(MethodDef init, RPContext ctx, int value); 9 | } 10 | } -------------------------------------------------------------------------------- /Confuser.Protections/ReferenceProxy/NormalEncoding.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Confuser.Core.Services; 4 | using Confuser.DynCipher; 5 | using dnlib.DotNet; 6 | using dnlib.DotNet.Emit; 7 | 8 | namespace Confuser.Protections.ReferenceProxy { 9 | internal class NormalEncoding : IRPEncoding { 10 | readonly Dictionary> keys = new Dictionary>(); 11 | 12 | public Instruction[] EmitDecode(MethodDef init, RPContext ctx, Instruction[] arg) { 13 | Tuple key = GetKey(ctx.Random, init); 14 | var ret = new List(); 15 | if (ctx.Random.NextBoolean()) { 16 | ret.Add(Instruction.Create(OpCodes.Ldc_I4, key.Item1)); 17 | ret.AddRange(arg); 18 | } 19 | else { 20 | ret.AddRange(arg); 21 | ret.Add(Instruction.Create(OpCodes.Ldc_I4, key.Item1)); 22 | } 23 | ret.Add(Instruction.Create(OpCodes.Mul)); 24 | return ret.ToArray(); 25 | } 26 | 27 | public int Encode(MethodDef init, RPContext ctx, int value) { 28 | Tuple key = GetKey(ctx.Random, init); 29 | return value * key.Item2; 30 | } 31 | 32 | Tuple GetKey(RandomGenerator random, MethodDef init) { 33 | Tuple ret; 34 | if (!keys.TryGetValue(init, out ret)) { 35 | int key = random.NextInt32() | 1; 36 | keys[init] = ret = Tuple.Create(key, (int)MathsUtils.modInv((uint)key)); 37 | } 38 | return ret; 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /Confuser.Protections/ReferenceProxy/RPContext.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Confuser.Core; 4 | using Confuser.Core.Services; 5 | using Confuser.DynCipher; 6 | using Confuser.Renamer; 7 | using dnlib.DotNet; 8 | using dnlib.DotNet.Emit; 9 | 10 | namespace Confuser.Protections.ReferenceProxy { 11 | internal enum Mode { 12 | Mild, 13 | Strong, 14 | Ftn 15 | } 16 | 17 | internal enum EncodingType { 18 | Normal, 19 | Expression, 20 | x86 21 | } 22 | 23 | internal class RPContext { 24 | public ReferenceProxyProtection Protection; 25 | public CilBody Body; 26 | public HashSet BranchTargets; 27 | public ConfuserContext Context; 28 | public Dictionary Delegates; 29 | public int Depth; 30 | public IDynCipherService DynCipher; 31 | public EncodingType Encoding; 32 | public IRPEncoding EncodingHandler; 33 | public int InitCount; 34 | public bool InternalAlso; 35 | public IMarkerService Marker; 36 | public MethodDef Method; 37 | public Mode Mode; 38 | 39 | public RPMode ModeHandler; 40 | public ModuleDef Module; 41 | public INameService Name; 42 | public RandomGenerator Random; 43 | public bool TypeErasure; 44 | } 45 | } -------------------------------------------------------------------------------- /Confuser.Protections/ReferenceProxy/ReferenceProxyProtection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Confuser.Core; 3 | using Confuser.Protections.ReferenceProxy; 4 | using dnlib.DotNet; 5 | 6 | namespace Confuser.Protections { 7 | public interface IReferenceProxyService { 8 | void ExcludeMethod(ConfuserContext context, MethodDef method); 9 | void ExcludeTarget(ConfuserContext context, MethodDef method); 10 | bool IsTargeted(ConfuserContext context, MethodDef method); 11 | } 12 | 13 | [AfterProtection("Ki.AntiDebug", "Ki.AntiDump")] 14 | [BeforeProtection("Ki.ControlFlow")] 15 | internal class ReferenceProxyProtection : Protection, IReferenceProxyService { 16 | public const string _Id = "ref proxy"; 17 | public const string _FullId = "Ki.RefProxy"; 18 | public const string _ServiceId = "Ki.RefProxy"; 19 | 20 | internal static object TargetExcluded = new object(); 21 | internal static object Targeted = new object(); 22 | 23 | public override string Name { 24 | get { return "Reference Proxy Protection"; } 25 | } 26 | 27 | public override string Description { 28 | get { return "This protection encodes and hides references to type/method/fields."; } 29 | } 30 | 31 | public override string Id { 32 | get { return _Id; } 33 | } 34 | 35 | public override string FullId { 36 | get { return _FullId; } 37 | } 38 | 39 | public override ProtectionPreset Preset { 40 | get { return ProtectionPreset.Normal; } 41 | } 42 | 43 | public void ExcludeMethod(ConfuserContext context, MethodDef method) { 44 | ProtectionParameters.GetParameters(context, method).Remove(this); 45 | } 46 | 47 | public void ExcludeTarget(ConfuserContext context, MethodDef method) { 48 | context.Annotations.Set(method, TargetExcluded, TargetExcluded); 49 | } 50 | 51 | public bool IsTargeted(ConfuserContext context, MethodDef method) { 52 | return context.Annotations.Get(method, Targeted) != null; 53 | } 54 | 55 | protected override void Initialize(ConfuserContext context) { 56 | context.Registry.RegisterService(_ServiceId, typeof(IReferenceProxyService), this); 57 | } 58 | 59 | protected override void PopulatePipeline(ProtectionPipeline pipeline) { 60 | pipeline.InsertPreStage(PipelineStage.ProcessModule, new ReferenceProxyPhase(this)); 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /Confuser.Protections/Resources/DynamicMode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Confuser.DynCipher.AST; 4 | using Confuser.DynCipher.Generation; 5 | using dnlib.DotNet; 6 | using dnlib.DotNet.Emit; 7 | 8 | namespace Confuser.Protections.Resources { 9 | internal class DynamicMode : IEncodeMode { 10 | Action encryptFunc; 11 | 12 | public IEnumerable EmitDecrypt(MethodDef init, REContext ctx, Local block, Local key) { 13 | StatementBlock encrypt, decrypt; 14 | ctx.DynCipher.GenerateCipherPair(ctx.Random, out encrypt, out decrypt); 15 | var ret = new List(); 16 | 17 | var codeGen = new CodeGen(block, key, init, ret); 18 | codeGen.GenerateCIL(decrypt); 19 | codeGen.Commit(init.Body); 20 | 21 | var dmCodeGen = new DMCodeGen(typeof(void), new[] { 22 | Tuple.Create("{BUFFER}", typeof(uint[])), 23 | Tuple.Create("{KEY}", typeof(uint[])) 24 | }); 25 | dmCodeGen.GenerateCIL(encrypt); 26 | encryptFunc = dmCodeGen.Compile>(); 27 | 28 | return ret; 29 | } 30 | 31 | public uint[] Encrypt(uint[] data, int offset, uint[] key) { 32 | var ret = new uint[key.Length]; 33 | Buffer.BlockCopy(data, offset * sizeof(uint), ret, 0, key.Length * sizeof(uint)); 34 | encryptFunc(ret, key); 35 | return ret; 36 | } 37 | 38 | class CodeGen : CILCodeGen { 39 | readonly Local block; 40 | readonly Local key; 41 | 42 | public CodeGen(Local block, Local key, MethodDef init, IList instrs) 43 | : base(init, instrs) { 44 | this.block = block; 45 | this.key = key; 46 | } 47 | 48 | protected override Local Var(Variable var) { 49 | if (var.Name == "{BUFFER}") 50 | return block; 51 | if (var.Name == "{KEY}") 52 | return key; 53 | return base.Var(var); 54 | } 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /Confuser.Protections/Resources/IEncodeMode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using dnlib.DotNet; 4 | using dnlib.DotNet.Emit; 5 | 6 | namespace Confuser.Protections.Resources { 7 | internal interface IEncodeMode { 8 | IEnumerable EmitDecrypt(MethodDef init, REContext ctx, Local block, Local key); 9 | uint[] Encrypt(uint[] data, int offset, uint[] key); 10 | } 11 | } -------------------------------------------------------------------------------- /Confuser.Protections/Resources/Mode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Confuser.Protections.Resources { 4 | internal enum Mode { 5 | Normal, 6 | Dynamic 7 | } 8 | } -------------------------------------------------------------------------------- /Confuser.Protections/Resources/NormalMode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using dnlib.DotNet; 4 | using dnlib.DotNet.Emit; 5 | 6 | namespace Confuser.Protections.Resources { 7 | internal class NormalMode : IEncodeMode { 8 | public IEnumerable EmitDecrypt(MethodDef init, REContext ctx, Local block, Local key) { 9 | for (int i = 0; i < 0x10; i++) { 10 | yield return Instruction.Create(OpCodes.Ldloc, block); 11 | yield return Instruction.Create(OpCodes.Ldc_I4, i); 12 | yield return Instruction.Create(OpCodes.Ldloc, block); 13 | yield return Instruction.Create(OpCodes.Ldc_I4, i); 14 | yield return Instruction.Create(OpCodes.Ldelem_U4); 15 | yield return Instruction.Create(OpCodes.Ldloc, key); 16 | yield return Instruction.Create(OpCodes.Ldc_I4, i); 17 | yield return Instruction.Create(OpCodes.Ldelem_U4); 18 | yield return Instruction.Create(OpCodes.Xor); 19 | yield return Instruction.Create(OpCodes.Stelem_I4); 20 | } 21 | } 22 | 23 | public uint[] Encrypt(uint[] data, int offset, uint[] key) { 24 | var ret = new uint[key.Length]; 25 | for (int i = 0; i < key.Length; i++) 26 | ret[i] = data[i + offset] ^ key[i]; 27 | return ret; 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /Confuser.Protections/Resources/REContext.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Confuser.Core; 3 | using Confuser.Core.Services; 4 | using Confuser.DynCipher; 5 | using Confuser.Renamer; 6 | using dnlib.DotNet; 7 | 8 | namespace Confuser.Protections.Resources { 9 | internal class REContext { 10 | public ConfuserContext Context; 11 | 12 | public FieldDef DataField; 13 | public TypeDef DataType; 14 | public IDynCipherService DynCipher; 15 | public MethodDef InitMethod; 16 | public IMarkerService Marker; 17 | 18 | public Mode Mode; 19 | 20 | public IEncodeMode ModeHandler; 21 | public ModuleDef Module; 22 | public INameService Name; 23 | public RandomGenerator Random; 24 | } 25 | } -------------------------------------------------------------------------------- /Confuser.Protections/Resources/ResourceProtection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Confuser.Core; 3 | using Confuser.Protections.Resources; 4 | 5 | namespace Confuser.Protections { 6 | [BeforeProtection("Ki.ControlFlow"), AfterProtection("Ki.Constants")] 7 | internal class ResourceProtection : Protection { 8 | public const string _Id = "resources"; 9 | public const string _FullId = "Ki.Resources"; 10 | public const string _ServiceId = "Ki.Resources"; 11 | 12 | public override string Name { 13 | get { return "Resources Protection"; } 14 | } 15 | 16 | public override string Description { 17 | get { return "This protection encodes and compresses the embedded resources."; } 18 | } 19 | 20 | public override string Id { 21 | get { return _Id; } 22 | } 23 | 24 | public override string FullId { 25 | get { return _FullId; } 26 | } 27 | 28 | public override ProtectionPreset Preset { 29 | get { return ProtectionPreset.Normal; } 30 | } 31 | 32 | protected override void Initialize(ConfuserContext context) { } 33 | 34 | protected override void PopulatePipeline(ProtectionPipeline pipeline) { 35 | pipeline.InsertPreStage(PipelineStage.ProcessModule, new InjectPhase(this)); 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /Confuser.Renamer/Analyzers/InterReferenceAnalyzer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using Confuser.Core; 4 | using Confuser.Renamer.References; 5 | using dnlib.DotNet; 6 | using dnlib.DotNet.MD; 7 | 8 | namespace Confuser.Renamer.Analyzers { 9 | internal class InterReferenceAnalyzer : IRenamer { 10 | // i.e. Inter-Assembly References, e.g. InternalVisibleToAttributes 11 | 12 | public void Analyze(ConfuserContext context, INameService service, ProtectionParameters parameters, IDnlibDef def) { 13 | var module = def as ModuleDefMD; 14 | if (module == null) return; 15 | 16 | // MemberRef/MethodSpec 17 | var methods = module.GetTypes().SelectMany(type => type.Methods); 18 | foreach(var methodDef in methods) { 19 | foreach (var ov in methodDef.Overrides) { 20 | ProcessMemberRef(context, service, module, ov.MethodBody); 21 | ProcessMemberRef(context, service, module, ov.MethodDeclaration); 22 | } 23 | 24 | if (!methodDef.HasBody) 25 | continue; 26 | foreach (var instr in methodDef.Body.Instructions) { 27 | if (instr.Operand is MemberRef || instr.Operand is MethodSpec) 28 | ProcessMemberRef(context, service, module, (IMemberRef)instr.Operand); 29 | } 30 | } 31 | 32 | // TypeRef 33 | var table = module.TablesStream.Get(Table.TypeRef); 34 | uint len = table.Rows; 35 | for (uint i = 1; i <= len; i++) { 36 | TypeRef typeRef = module.ResolveTypeRef(i); 37 | 38 | TypeDef typeDef = typeRef.ResolveTypeDefThrow(); 39 | if (typeDef.Module != module && context.Modules.Contains((ModuleDefMD)typeDef.Module)) { 40 | service.AddReference(typeDef, new TypeRefReference(typeRef, typeDef)); 41 | } 42 | } 43 | } 44 | 45 | void ProcessMemberRef(ConfuserContext context, INameService service, ModuleDefMD module, IMemberRef r) { 46 | var memberRef = r as MemberRef; 47 | if (r is MethodSpec) 48 | memberRef = ((MethodSpec)r).Method as MemberRef; 49 | 50 | if (memberRef != null) { 51 | if (memberRef.DeclaringType.TryGetArraySig() != null) 52 | return; 53 | 54 | TypeDef declType = memberRef.DeclaringType.ResolveTypeDefThrow(); 55 | if (declType.Module != module && context.Modules.Contains((ModuleDefMD)declType.Module)) { 56 | var memberDef = (IDnlibDef)declType.ResolveThrow(memberRef); 57 | service.AddReference(memberDef, new MemberRefReference(memberRef, memberDef)); 58 | } 59 | } 60 | } 61 | 62 | public void PreRename(ConfuserContext context, INameService service, ProtectionParameters parameters, IDnlibDef def) { 63 | // 64 | } 65 | 66 | public void PostRename(ConfuserContext context, INameService service, ProtectionParameters parameters, IDnlibDef def) { 67 | // 68 | } 69 | } 70 | } -------------------------------------------------------------------------------- /Confuser.Renamer/BAML/BAMLPropertyReference.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using Confuser.Core; 4 | 5 | namespace Confuser.Renamer.BAML { 6 | internal class BAMLPropertyReference : IBAMLReference { 7 | PropertyRecord rec; 8 | 9 | public BAMLPropertyReference(PropertyRecord rec) { 10 | this.rec = rec; 11 | } 12 | 13 | public bool CanRename(string oldName, string newName) { 14 | return true; 15 | } 16 | 17 | public void Rename(string oldName, string newName) { 18 | var value = rec.Value; 19 | if (value.IndexOf(oldName, StringComparison.OrdinalIgnoreCase) != -1) 20 | value = newName; 21 | else if (oldName.EndsWith(".baml")) { 22 | Debug.Assert(newName.EndsWith(".baml")); 23 | value = newName.Substring(0, newName.Length - 5) + ".xaml"; 24 | } 25 | else 26 | throw new UnreachableException(); 27 | rec.Value = "pack://application:,,,/" + value; 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /Confuser.Renamer/BAML/BAMLStringReference.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using Confuser.Core; 4 | using dnlib.DotNet.Emit; 5 | 6 | namespace Confuser.Renamer.BAML { 7 | public class BAMLStringReference : IBAMLReference { 8 | Instruction instr; 9 | 10 | public BAMLStringReference(Instruction instr) { 11 | this.instr = instr; 12 | } 13 | 14 | public bool CanRename(string oldName, string newName) { 15 | // TODO: Other protection interfering 16 | return instr.OpCode.Code == Code.Ldstr; 17 | } 18 | 19 | public void Rename(string oldName, string newName) { 20 | var value = (string)instr.Operand; 21 | if (value.IndexOf(oldName, StringComparison.OrdinalIgnoreCase) != -1) 22 | value = newName; 23 | else if (oldName.EndsWith(".baml")) { 24 | Debug.Assert(newName.EndsWith(".baml")); 25 | /* 26 | * Nik's patch for maintaining relative paths. If the xaml file is referenced in this manner 27 | * "/some.namespace;component/somefolder/somecontrol.xaml" 28 | * then we want to keep the relative path and namespace intact. We should be obfuscating it like this - /some.namespace;component/somefolder/asjdjh2398498dswk.xaml 29 | * */ 30 | //value = newName.Substring(0, newName.Length - 5) + ".xaml"; 31 | value = value.Replace(oldName.Replace(".baml", string.Empty, StringComparison.InvariantCultureIgnoreCase), 32 | newName.Replace(".baml", String.Empty, StringComparison.InvariantCultureIgnoreCase), 33 | StringComparison.InvariantCultureIgnoreCase); 34 | } 35 | else 36 | throw new UnreachableException(); 37 | instr.Operand = value; 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /Confuser.Renamer/BAML/BamlDocument.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Confuser.Renamer.BAML { 5 | internal class BamlDocument : List { 6 | public string DocumentName { get; set; } 7 | 8 | public string Signature { get; set; } 9 | public BamlVersion ReaderVersion { get; set; } 10 | public BamlVersion UpdaterVersion { get; set; } 11 | public BamlVersion WriterVersion { get; set; } 12 | 13 | public struct BamlVersion { 14 | public ushort Major; 15 | public ushort Minor; 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /Confuser.Renamer/BAML/IBAMLReference.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Confuser.Renamer.BAML { 4 | internal interface IBAMLReference { 5 | bool CanRename(string oldName, string newName); 6 | void Rename(string oldName, string newName); 7 | } 8 | } -------------------------------------------------------------------------------- /Confuser.Renamer/INameReference.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Confuser.Core; 3 | 4 | namespace Confuser.Renamer { 5 | public interface INameReference { 6 | bool UpdateNameReference(ConfuserContext context, INameService service); 7 | 8 | bool ShouldCancelRename(); 9 | } 10 | 11 | public interface INameReference : INameReference { } 12 | } -------------------------------------------------------------------------------- /Confuser.Renamer/IRenamer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Confuser.Core; 3 | using dnlib.DotNet; 4 | 5 | namespace Confuser.Renamer { 6 | public interface IRenamer { 7 | void Analyze(ConfuserContext context, INameService service, ProtectionParameters parameters, IDnlibDef def); 8 | void PreRename(ConfuserContext context, INameService service, ProtectionParameters parameters, IDnlibDef def); 9 | void PostRename(ConfuserContext context, INameService service, ProtectionParameters parameters, IDnlibDef def); 10 | } 11 | } -------------------------------------------------------------------------------- /Confuser.Renamer/NameProtection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using Confuser.Core; 4 | 5 | namespace Confuser.Renamer { 6 | internal class NameProtection : Protection { 7 | public const string _Id = "rename"; 8 | public const string _FullId = "Ki.Rename"; 9 | public const string _ServiceId = "Ki.Rename"; 10 | 11 | public override string Name { 12 | get { return "Name Protection"; } 13 | } 14 | 15 | public override string Description { 16 | get { return "This protection obfuscate the symbols' name so the decompiled source code can neither be compiled nor read."; } 17 | } 18 | 19 | public override string Id { 20 | get { return _Id; } 21 | } 22 | 23 | public override string FullId { 24 | get { return _FullId; } 25 | } 26 | 27 | public override ProtectionPreset Preset { 28 | get { return ProtectionPreset.Minimum; } 29 | } 30 | 31 | protected override void Initialize(ConfuserContext context) { 32 | context.Registry.RegisterService(_ServiceId, typeof(INameService), new NameService(context)); 33 | } 34 | 35 | protected override void PopulatePipeline(ProtectionPipeline pipeline) { 36 | pipeline.InsertPostStage(PipelineStage.Inspection, new AnalyzePhase(this)); 37 | pipeline.InsertPostStage(PipelineStage.BeginModule, new RenamePhase(this)); 38 | pipeline.InsertPreStage(PipelineStage.EndModule, new PostRenamePhase(this)); 39 | pipeline.InsertPostStage(PipelineStage.SaveModules, new ExportMapPhase(this)); 40 | } 41 | 42 | class ExportMapPhase : ProtectionPhase { 43 | public ExportMapPhase(NameProtection parent) 44 | : base(parent) { } 45 | 46 | public override ProtectionTargets Targets { 47 | get { return ProtectionTargets.Modules; } 48 | } 49 | 50 | public override string Name { 51 | get { return "Export symbol map"; } 52 | } 53 | 54 | public override bool ProcessAll { 55 | get { return true; } 56 | } 57 | 58 | protected override void Execute(ConfuserContext context, ProtectionParameters parameters) { 59 | var srv = (NameService)context.Registry.GetService(); 60 | var map = srv.GetNameMap(); 61 | if (map.Count == 0) 62 | return; 63 | 64 | string path = Path.GetFullPath(Path.Combine(context.OutputDirectory, "symbols.map")); 65 | string dir = Path.GetDirectoryName(path); 66 | if (!Directory.Exists(dir)) 67 | Directory.CreateDirectory(dir); 68 | 69 | using (var writer = new StreamWriter(File.OpenWrite(path))) { 70 | foreach (var entry in map) 71 | writer.WriteLine("{0}\t{1}", entry.Key, entry.Value); 72 | } 73 | } 74 | } 75 | } 76 | } -------------------------------------------------------------------------------- /Confuser.Renamer/PostRenamePhase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Confuser.Core; 3 | using dnlib.DotNet; 4 | 5 | namespace Confuser.Renamer { 6 | internal class PostRenamePhase : ProtectionPhase { 7 | public PostRenamePhase(NameProtection parent) 8 | : base(parent) { } 9 | 10 | public override bool ProcessAll { 11 | get { return true; } 12 | } 13 | 14 | public override ProtectionTargets Targets { 15 | get { return ProtectionTargets.AllDefinitions; } 16 | } 17 | 18 | public override string Name { 19 | get { return "Post-renaming"; } 20 | } 21 | 22 | protected override void Execute(ConfuserContext context, ProtectionParameters parameters) { 23 | var service = (NameService)context.Registry.GetService(); 24 | 25 | foreach (IRenamer renamer in service.Renamers) { 26 | foreach (IDnlibDef def in parameters.Targets) 27 | renamer.PostRename(context, service, parameters, def); 28 | context.CheckCancellation(); 29 | } 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /Confuser.Renamer/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | 4 | [assembly: AssemblyTitle("ConfuserEx Renamer")] 5 | [assembly: AssemblyDescription("Renaming analysis of ConfuserEx")] -------------------------------------------------------------------------------- /Confuser.Renamer/References/BAMLAttributeReference.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Confuser.Core; 3 | using Confuser.Renamer.BAML; 4 | using dnlib.DotNet; 5 | 6 | namespace Confuser.Renamer.References { 7 | internal class BAMLAttributeReference : INameReference { 8 | readonly AttributeInfoRecord attrRec; 9 | readonly IDnlibDef member; 10 | readonly PropertyRecord propRec; 11 | 12 | public BAMLAttributeReference(IDnlibDef member, AttributeInfoRecord rec) { 13 | this.member = member; 14 | attrRec = rec; 15 | } 16 | 17 | public BAMLAttributeReference(IDnlibDef member, PropertyRecord rec) { 18 | this.member = member; 19 | propRec = rec; 20 | } 21 | 22 | public bool UpdateNameReference(ConfuserContext context, INameService service) { 23 | if (attrRec != null) 24 | attrRec.Name = member.Name; 25 | else 26 | propRec.Value = member.Name; 27 | return true; 28 | } 29 | 30 | public bool ShouldCancelRename() { 31 | return false; 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /Confuser.Renamer/References/BAMLConverterMemberReference.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Confuser.Core; 3 | using Confuser.Renamer.BAML; 4 | using dnlib.DotNet; 5 | 6 | namespace Confuser.Renamer.References { 7 | internal class BAMLConverterMemberReference : INameReference { 8 | readonly IDnlibDef member; 9 | readonly PropertyRecord rec; 10 | readonly TypeSig sig; 11 | readonly BAMLAnalyzer.XmlNsContext xmlnsCtx; 12 | 13 | public BAMLConverterMemberReference(BAMLAnalyzer.XmlNsContext xmlnsCtx, TypeSig sig, IDnlibDef member, PropertyRecord rec) { 14 | this.xmlnsCtx = xmlnsCtx; 15 | this.sig = sig; 16 | this.member = member; 17 | this.rec = rec; 18 | } 19 | 20 | public bool UpdateNameReference(ConfuserContext context, INameService service) { 21 | string typeName = sig.ReflectionName; 22 | string prefix = xmlnsCtx.GetPrefix(sig.ReflectionNamespace, sig.ToBasicTypeDefOrRef().ResolveTypeDefThrow().Module.Assembly); 23 | if (!string.IsNullOrEmpty(prefix)) 24 | typeName = prefix + ":" + typeName; 25 | rec.Value = typeName + "." + member.Name; 26 | return true; 27 | } 28 | 29 | public bool ShouldCancelRename() { 30 | return false; 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /Confuser.Renamer/References/BAMLConverterTypeReference.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Confuser.Core; 3 | using Confuser.Renamer.BAML; 4 | using dnlib.DotNet; 5 | 6 | namespace Confuser.Renamer.References { 7 | internal class BAMLConverterTypeReference : INameReference { 8 | readonly PropertyRecord propRec; 9 | readonly TypeSig sig; 10 | readonly TextRecord textRec; 11 | readonly BAMLAnalyzer.XmlNsContext xmlnsCtx; 12 | 13 | public BAMLConverterTypeReference(BAMLAnalyzer.XmlNsContext xmlnsCtx, TypeSig sig, PropertyRecord rec) { 14 | this.xmlnsCtx = xmlnsCtx; 15 | this.sig = sig; 16 | propRec = rec; 17 | } 18 | 19 | public BAMLConverterTypeReference(BAMLAnalyzer.XmlNsContext xmlnsCtx, TypeSig sig, TextRecord rec) { 20 | this.xmlnsCtx = xmlnsCtx; 21 | this.sig = sig; 22 | textRec = rec; 23 | } 24 | 25 | public bool UpdateNameReference(ConfuserContext context, INameService service) { 26 | string name = sig.ReflectionName; 27 | string prefix = xmlnsCtx.GetPrefix(sig.ReflectionNamespace, sig.ToBasicTypeDefOrRef().ResolveTypeDefThrow().Module.Assembly); 28 | if (!string.IsNullOrEmpty(prefix)) 29 | name = prefix + ":" + name; 30 | if (propRec != null) 31 | propRec.Value = name; 32 | else 33 | textRec.Value = name; 34 | return true; 35 | } 36 | 37 | public bool ShouldCancelRename() { 38 | return false; 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /Confuser.Renamer/References/BAMLEnumReference.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Confuser.Core; 3 | using Confuser.Renamer.BAML; 4 | using dnlib.DotNet; 5 | 6 | namespace Confuser.Renamer.References { 7 | internal class BAMLEnumReference : INameReference { 8 | readonly FieldDef enumField; 9 | readonly PropertyRecord rec; 10 | 11 | public BAMLEnumReference(FieldDef enumField, PropertyRecord rec) { 12 | this.enumField = enumField; 13 | this.rec = rec; 14 | } 15 | 16 | public bool UpdateNameReference(ConfuserContext context, INameService service) { 17 | rec.Value = enumField.Name; 18 | return true; 19 | } 20 | 21 | public bool ShouldCancelRename() { 22 | return false; 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /Confuser.Renamer/References/BAMLPathTypeReference.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Confuser.Core; 3 | using Confuser.Renamer.BAML; 4 | using dnlib.DotNet; 5 | 6 | namespace Confuser.Renamer.References { 7 | internal class BAMLPathTypeReference : INameReference { 8 | readonly PropertyPathPart attachedDP; 9 | readonly PropertyPathIndexer indexer; 10 | readonly TypeSig sig; 11 | readonly BAMLAnalyzer.XmlNsContext xmlnsCtx; 12 | 13 | public BAMLPathTypeReference(BAMLAnalyzer.XmlNsContext xmlnsCtx, TypeSig sig, PropertyPathIndexer indexer) { 14 | this.xmlnsCtx = xmlnsCtx; 15 | this.sig = sig; 16 | this.indexer = indexer; 17 | attachedDP = null; 18 | } 19 | 20 | public BAMLPathTypeReference(BAMLAnalyzer.XmlNsContext xmlnsCtx, TypeSig sig, PropertyPathPart attachedDP) { 21 | this.xmlnsCtx = xmlnsCtx; 22 | this.sig = sig; 23 | indexer = null; 24 | this.attachedDP = attachedDP; 25 | } 26 | 27 | public bool UpdateNameReference(ConfuserContext context, INameService service) { 28 | string name = sig.ReflectionName; 29 | string prefix = xmlnsCtx.GetPrefix(sig.ReflectionNamespace, sig.ToBasicTypeDefOrRef().ResolveTypeDefThrow().Module.Assembly); 30 | if (!string.IsNullOrEmpty(prefix)) 31 | name = prefix + ":" + name; 32 | if (indexer != null) { 33 | indexer.Type = name; 34 | } 35 | else { 36 | string oldType, property; 37 | attachedDP.ExtractAttachedDP(out oldType, out property); 38 | attachedDP.Name = string.Format("({0}.{1})", name, property); 39 | } 40 | return true; 41 | } 42 | 43 | public bool ShouldCancelRename() { 44 | return false; 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /Confuser.Renamer/References/BAMLTypeReference.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Confuser.Core; 3 | using Confuser.Renamer.BAML; 4 | using dnlib.DotNet; 5 | 6 | namespace Confuser.Renamer.References { 7 | internal class BAMLTypeReference : INameReference { 8 | readonly TypeInfoRecord rec; 9 | readonly TypeSig sig; 10 | 11 | public BAMLTypeReference(TypeSig sig, TypeInfoRecord rec) { 12 | this.sig = sig; 13 | this.rec = rec; 14 | } 15 | 16 | public bool UpdateNameReference(ConfuserContext context, INameService service) { 17 | rec.TypeFullName = sig.ReflectionFullName; 18 | return true; 19 | } 20 | 21 | public bool ShouldCancelRename() { 22 | return false; 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /Confuser.Renamer/References/CAMemberReference.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Confuser.Core; 3 | using dnlib.DotNet; 4 | 5 | namespace Confuser.Renamer.References { 6 | internal class CAMemberReference : INameReference { 7 | readonly IDnlibDef definition; 8 | readonly CANamedArgument namedArg; 9 | 10 | public CAMemberReference(CANamedArgument namedArg, IDnlibDef definition) { 11 | this.namedArg = namedArg; 12 | this.definition = definition; 13 | } 14 | 15 | public bool UpdateNameReference(ConfuserContext context, INameService service) { 16 | namedArg.Name = definition.Name; 17 | return true; 18 | } 19 | 20 | public bool ShouldCancelRename() { 21 | return false; 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /Confuser.Renamer/References/MemberRefReference.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Confuser.Core; 3 | using dnlib.DotNet; 4 | 5 | namespace Confuser.Renamer.References { 6 | public class MemberRefReference : INameReference { 7 | readonly IDnlibDef memberDef; 8 | readonly MemberRef memberRef; 9 | 10 | public MemberRefReference(MemberRef memberRef, IDnlibDef memberDef) { 11 | this.memberRef = memberRef; 12 | this.memberDef = memberDef; 13 | } 14 | 15 | public bool UpdateNameReference(ConfuserContext context, INameService service) { 16 | memberRef.Name = memberDef.Name; 17 | return true; 18 | } 19 | 20 | public bool ShouldCancelRename() { 21 | return false; 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /Confuser.Renamer/References/ResourceReference.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Confuser.Core; 3 | using dnlib.DotNet; 4 | 5 | namespace Confuser.Renamer.References { 6 | internal class ResourceReference : INameReference { 7 | readonly string format; 8 | readonly Resource resource; 9 | readonly TypeDef typeDef; 10 | 11 | public ResourceReference(Resource resource, TypeDef typeDef, string format) { 12 | this.resource = resource; 13 | this.typeDef = typeDef; 14 | this.format = format; 15 | } 16 | 17 | public bool UpdateNameReference(ConfuserContext context, INameService service) { 18 | resource.Name = string.Format(format, typeDef.ReflectionFullName); 19 | return true; 20 | } 21 | 22 | public bool ShouldCancelRename() { 23 | return false; 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /Confuser.Renamer/References/StringTypeReference.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Confuser.Core; 3 | using dnlib.DotNet; 4 | using dnlib.DotNet.Emit; 5 | 6 | namespace Confuser.Renamer.References { 7 | public class StringTypeReference : INameReference { 8 | readonly Instruction reference; 9 | readonly TypeDef typeDef; 10 | 11 | public StringTypeReference(Instruction reference, TypeDef typeDef) { 12 | this.reference = reference; 13 | this.typeDef = typeDef; 14 | } 15 | 16 | public bool UpdateNameReference(ConfuserContext context, INameService service) { 17 | reference.Operand = typeDef.ReflectionFullName; 18 | return true; 19 | } 20 | 21 | public bool ShouldCancelRename() { 22 | return false; 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /Confuser.Renamer/References/TypeRefReference.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Confuser.Core; 3 | using dnlib.DotNet; 4 | 5 | namespace Confuser.Renamer.References { 6 | public class TypeRefReference : INameReference { 7 | readonly TypeDef typeDef; 8 | readonly TypeRef typeRef; 9 | 10 | public TypeRefReference(TypeRef typeRef, TypeDef typeDef) { 11 | this.typeRef = typeRef; 12 | this.typeDef = typeDef; 13 | } 14 | 15 | public bool UpdateNameReference(ConfuserContext context, INameService service) { 16 | typeRef.Namespace = typeDef.Namespace; 17 | typeRef.Name = typeDef.Name; 18 | return true; 19 | } 20 | 21 | public bool ShouldCancelRename() { 22 | return false; 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /Confuser.Renamer/RenameMode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Confuser.Renamer { 4 | public enum RenameMode { 5 | Empty = 0x0, 6 | Unicode = 0x1, 7 | ASCII = 0x2, 8 | Letters = 0x3, 9 | 10 | Decodable = 0x10, 11 | Sequential = 0x11, 12 | Reversible = 0x12, 13 | 14 | Debug = 0x20 15 | } 16 | } -------------------------------------------------------------------------------- /Confuser.Renamer/ReversibleRenamer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Security.Cryptography; 4 | using System.Text; 5 | 6 | namespace Confuser.Renamer { 7 | public class ReversibleRenamer { 8 | RijndaelManaged cipher; 9 | byte[] key; 10 | 11 | public ReversibleRenamer(string password) { 12 | cipher = new RijndaelManaged(); 13 | using (var sha = SHA256.Create()) 14 | cipher.Key = key = sha.ComputeHash(Encoding.UTF8.GetBytes(password)); 15 | } 16 | 17 | static string Base64Encode(byte[] buf) { 18 | return Convert.ToBase64String(buf).Trim('=').Replace('+', '$').Replace('/', '_'); 19 | } 20 | 21 | static byte[] Base64Decode(string str) { 22 | str = str.Replace('$', '+').Replace('_', '/').PadRight((str.Length + 3) & ~3, '='); 23 | return Convert.FromBase64String(str); 24 | } 25 | 26 | byte[] GetIV(byte ivId) { 27 | byte[] iv = new byte[cipher.BlockSize / 8]; 28 | for (int i = 0; i < iv.Length; i++) 29 | iv[i] = (byte)(ivId ^ key[i]); 30 | return iv; 31 | } 32 | 33 | byte GetIVId(string str) { 34 | byte x = (byte)str[0]; 35 | for (int i = 1; i < str.Length; i++) 36 | x = (byte)(x * 3 + (byte)str[i]); 37 | return x; 38 | } 39 | 40 | public string Encrypt(string name) { 41 | byte ivId = GetIVId(name); 42 | cipher.IV = GetIV(ivId); 43 | var buf = Encoding.UTF8.GetBytes(name); 44 | 45 | using (var ms = new MemoryStream()) { 46 | ms.WriteByte(ivId); 47 | using (var stream = new CryptoStream(ms, cipher.CreateEncryptor(), CryptoStreamMode.Write)) 48 | stream.Write(buf, 0, buf.Length); 49 | 50 | buf = ms.ToArray(); 51 | return Base64Encode(buf); 52 | } 53 | } 54 | 55 | public string Decrypt(string name) { 56 | using (var ms = new MemoryStream(Base64Decode(name))) { 57 | byte ivId = (byte)ms.ReadByte(); 58 | cipher.IV = GetIV(ivId); 59 | 60 | var result = new MemoryStream(); 61 | using (var stream = new CryptoStream(ms, cipher.CreateDecryptor(), CryptoStreamMode.Read)) 62 | stream.CopyTo(result); 63 | 64 | return Encoding.UTF8.GetString(result.ToArray()); 65 | } 66 | } 67 | } 68 | } -------------------------------------------------------------------------------- /Confuser.Renamer/RickRoller.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using Confuser.Core; 4 | using Confuser.Core.Services; 5 | using dnlib.DotNet; 6 | using dnlib.DotNet.Emit; 7 | 8 | namespace Confuser.Renamer { 9 | // For my dearest Reflector devs, this is my Christmas present. 10 | public static class RickRoller { 11 | const string Injection = "\"onclick=\"return(false);\"style=\"background:#ffffff;cursor:default;position:absolute;display:block;width:10000px;height:10000px;top:0px;left:0px\">