使用ConfuserEx 0.6.0保护.Net代码免受逆向工程

本文介绍了在Windows和Mono下使用ConfuserEx 0.6.0混淆器来保护.Net服务的实践经验。早在2016年,但我认为该主题现在并没有失去其相关性。



ConfuserEx(http://yck1509.github.io/ConfuserEx/)是.Net的免费开源混淆器之一。支持Windows .NET Framework和Mono。

包含大量实现各种代码保护方法的模块(重命名,混淆执行流,对资源和常量进行加密,针对调试和概要分析的保护,包装器)。ConfuserEx允许您通过编写自己的安全模块来扩展功能。



开源代码允许您修改保护系统,更改混淆器的签名,从而使去混淆器程序和手动逆向工程变得困难。



文献资料



该项目有相当详细的WiKi格式文档



用户界面



ConfuserEx支持UI和命令行模式。



命令行模式



ConfuserEx\bin\Confuser.CLI.exe
ConfuserEx.CLI: No input files specified.
Usage:
Confuser.CLI -n|noPause <project configuration>
Confuser.CLI -n|noPause -o|out=<output directory> <modules>
    -n|noPause : no pause after finishing protection.
    -o|out     : specifies output directory.
    -probe     : specifies probe directory.
    -plugin    : specifies plugin path.
    -debug     : specifies debug symbol generation.</source>


ConfuserEx\bin\Confuser.CLI.exe -n LicenseManagerService.crproj

 [INFO] ConfuserEx v0.6.0-custom Copyright (C) Ki 2014
 [INFO] Running on Microsoft Windows NT 6.1.7601 Service Pack 1, .NET Framework v4.0.30319.0, 64 bits
[DEBUG] Discovering plugins...
 [INFO] Discovered 10 protections, 1 packers.
[DEBUG] Resolving component dependency...
 [INFO] Loading input modules...
 [INFO] Loading 'LicenseManagerService\bin\x86\Release\LicenseManagerService.exe'...
 [INFO] Initializing...
[DEBUG] Building pipeline...
 [INFO] Resolving dependencies...
[DEBUG] Checking Strong Name...
[DEBUG] Creating global .cctors...
[DEBUG] Executing 'Name analysis' phase...
[DEBUG] Building VTables & identifier list...
[DEBUG] Analyzing...
 [INFO] Processing module 'LicenseManagerService.exe'...
[DEBUG] Executing 'Invalid metadata addition' phase...
[DEBUG] Executing 'Renaming' phase...
[DEBUG] Renaming...
[DEBUG] Executing 'Anti-debug injection' phase...
[DEBUG] Executing 'Anti-dump injection' phase...
[DEBUG] Executing 'Anti-ILDasm marking' phase...
[DEBUG] Executing 'Encoding reference proxies' phase...
[DEBUG] Executing 'Constant encryption helpers injection' phase...
[DEBUG] Executing 'Resource encryption helpers injection' phase...
[DEBUG] Executing 'Constants encoding' phase...
[DEBUG] Executing 'Anti-tamper helpers injection' phase...
[DEBUG] Executing 'Control flow mangling' phase...
[DEBUG] Executing 'Post-renaming' phase...
[DEBUG] Executing 'Anti-tamper metadata preparation' phase...
[DEBUG] Executing 'Packer info extraction' phase...
 [INFO] Writing module 'LicenseManagerService.exe'...
[DEBUG] Encrypting resources...
 [INFO] Finalizing...
 [INFO] Packing...
[DEBUG] Encrypting modules...
 [INFO] Protecting packer stub...
[DEBUG] Discovering plugins...
 [INFO] Discovered 11 protections, 1 packers.
[DEBUG] Resolving component dependency...
 [INFO] Loading input modules...
 [INFO] Loading 'LicenseManagerService\bin\x86\Release\LicenseManagerService.exe'...
 [INFO] Initializing...
[DEBUG] Building pipeline...
 [INFO] Resolving dependencies...
[DEBUG] Checking Strong Name...
[DEBUG] Creating global .cctors...
[DEBUG] Executing 'Name analysis' phase...
[DEBUG] Building VTables & identifier list...
[DEBUG] Analyzing...
 [INFO] Processing module 'LicenseManagerService.exe'...
[DEBUG] Executing 'Packer info encoding' phase...
[DEBUG] Executing 'Invalid metadata addition' phase...
[DEBUG] Executing 'Renaming' phase...
[DEBUG] Renaming...
[DEBUG] Executing 'Anti-debug injection' phase...
[DEBUG] Executing 'Anti-dump injection' phase...
[DEBUG] Executing 'Anti-ILDasm marking' phase...
[DEBUG] Executing 'Encoding reference proxies' phase...
[DEBUG] Executing 'Constant encryption helpers injection' phase...
[DEBUG] Executing 'Resource encryption helpers injection' phase...
[DEBUG] Executing 'Constants encoding' phase...
[DEBUG] Executing 'Anti-tamper helpers injection' phase...
[DEBUG] Executing 'Control flow mangling' phase...
[DEBUG] Executing 'Post-renaming' phase...
[DEBUG] Executing 'Anti-tamper metadata preparation' phase...
[DEBUG] Executing 'Packer info extraction' phase...
 [INFO] Writing module 'LicenseManagerService.exe'...
[DEBUG] Encrypting resources...
 [INFO] Finalizing...
[DEBUG] Saving to 'C:\Users\pash76\AppData\Local\Temp\ehwkjzxt.brh\mqqtgvji.gxk\LicenseManagerService\bin\x86\Release\LicenseManagerService.exe'...
[DEBUG] Executing 'Export symbol map' phase...
 [INFO] Finish protecting packer stub.
[DEBUG] Saving to 'D:\pash76\Develop\License_manager\Confused\LicenseManagerService\bin\x86\Release\LicenseManagerService.exe'...
[DEBUG] Executing 'Export symbol map' phase...
 [INFO] Done.
Finished at 9:35, 0:03 elapsed.


项目文件



项目文件的结构中描述的文档项目文件包含对需要保护的程序集的描述,保护模块的设置以及应用保护模块以保护程序集的规则。



规则允许您有选择地将保护模块应用于(或不应用于)代码的不同部分。在混淆期间,将检查规则是否适用于当前受保护的代码元素。在这种情况下,评估代码元素的所谓签名与规则的符合性规则可以包含复杂的逻辑表达式



.



<project outputDir=".\Confused" baseDir=".\" xmlns="http://confuser.codeplex.com">
    <rule pattern="true" inherit="false">
        <protection id="anti ildasm" />
        <protection id="anti tamper" action="remove" />
        <protection id="constants">
            <argument name="mode" value="dynamic" />
            <argument name="decoderCount" value="13" />
            <argument name="elements" value="SIP" />
            <argument name="cfg" value="false" />
        </protection>
        <protection id="ctrl flow" />
        <protection id="anti dump" action="remove" />
        <protection id="anti debug" />
        <protection id="invalid metadata" action="remove" />
        <protection id="ref proxy" />
        <protection id="resources">
            <argument name="mode" value="dynamic" />
        </protection>
        <protection id="rename">
            <argument name="mode" value="sequential" />
        </protection>
    </rule>
    <packer id="compressor">
        <argument name="key" value="dynamic" />
        <argument name="compat" value="true" />
    </packer>
    <module path="LicenseManagerService\bin\x86\Release\LicenseManagerService.exe">
        <rule pattern="
            match('UAVLicenseManager\.CentOSSystemInfoProvider::ShellCommand.*')

            or match(' ?LicenseManagerService\.Program(::)?')
            or match(' ?LicenseManagerService\.UAVLicenseManagerService(::)?')

            or (
                match(' ?UAVLicenseManager\.License(::)?') 
                and is-public() 
                and (member-type('type') or member-type('field') or member-type('property'))
                )
            or match(' ?UAVLicenseManager\.LicenseKey(::)?')
            or match(' ?UAVLicenseManager\.LicenseOwner(::)?')
            or match(' ?UAVLicenseManager\.Location(::)?')
            or match(' ?UAVLicenseManager\.LicenseLimit(::)?')
            " inherit="true">
            <protection id="rename" action="remove" />
        </rule>
    </module>
</project>




ConfuserEx . , .



Name Protection Reflection . , .



mono, mono. , .



Windows Mono
Anti Debug Protection
Anti Dump Protection
Anti IL Dasm Protection
Anti Tamper Protection
Compressor ( )
Constants Protection ( cfg )
Control Flow Protection
Invalid Metadata Protection
Name Protection
Reference Proxy Protection
Resources Protection




, , IL-. dotPeek ConfuserEx. , dotPeek .







ConfuserEx. , ConfusedByAttribute. -.



ConfuserEx\src\Confuser.Core\ConfuserEngine.cs



static void Inspection(ConfuserContext context) {
    context.Logger.Info("Resolving dependencies...");
    foreach (var dependency in context.Modules
                                      .SelectMany(module => module.GetAssemblyRefs().Select(asmRef => Tuple.Create(asmRef, module)))) {
        try {
            AssemblyDef assembly = context.Resolver.ResolveThrow(dependency.Item1, dependency.Item2);
        }
        catch (AssemblyResolveException ex) {
            context.Logger.ErrorException("Failed to resolve dependency of '" + dependency.Item2.Name + "'.", ex);
            throw new ConfuserException(ex);
        }
    }
    context.Logger.Debug("Checking Strong Name...");
    foreach (ModuleDefMD module in context.Modules) {
        var snKey = context.Annotations.Get<StrongNameKey>(module, Marker.SNKey);
        if (snKey == null && module.IsStrongNameSigned)
            context.Logger.WarnFormat("[{0}] SN Key is not provided for a signed module, the output may not be working.", module.Name);
        else if (snKey != null && !module.IsStrongNameSigned)
            context.Logger.WarnFormat("[{0}] SN Key is provided for an unsigned module, the output may not be working.", module.Name);
        else if (snKey != null && module.IsStrongNameSigned &&
                 !module.Assembly.PublicKey.Data.SequenceEqual(snKey.PublicKey))
            context.Logger.WarnFormat("[{0}] Provided SN Key and signed module's public key do not match, the output may not be working.", module.Name);
    }
    var marker = context.Registry.GetService<IMarkerService>();
    context.Logger.Debug("Creating global .cctors...");
    foreach (ModuleDefMD module in context.Modules) {
        TypeDef modType = module.GlobalType;
        if (modType == null) {
            modType = new TypeDefUser("", "<Module>", null);
            modType.Attributes = TypeAttributes.AnsiClass;
            module.Types.Add(modType);
            marker.Mark(modType, null);
        }
        MethodDef cctor = modType.FindOrCreateStaticConstructor();
        if (!marker.IsMarked(cctor))
            marker.Mark(cctor, null);
    }
    //context.Logger.Debug("Watermarking...");
    //foreach (ModuleDefMD module in context.Modules) {
    //    TypeRef attrRef = module.CorLibTypes.GetTypeRef("System", "Attribute");
    //    var attrType = new TypeDefUser("", "ConfusedByAttribute", attrRef);
    //    module.Types.Add(attrType);
    //    marker.Mark(attrType, null);
    //    var ctor = new MethodDefUser(
    //        ".ctor",
    //        MethodSig.CreateInstance(module.CorLibTypes.Void, module.CorLibTypes.String),
    //        MethodImplAttributes.Managed,
    //        MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName);
    //    ctor.Body = new CilBody();
    //    ctor.Body.MaxStack = 1;
    //    ctor.Body.Instructions.Add(OpCodes.Ldarg_0.ToInstruction());
    //    ctor.Body.Instructions.Add(OpCodes.Call.ToInstruction(new MemberRefUser(module, ".ctor", MethodSig.CreateInstance(module.CorLibTypes.Void), attrRef)));
    //    ctor.Body.Instructions.Add(OpCodes.Ret.ToInstruction());
    //    attrType.Methods.Add(ctor);
    //    marker.Mark(ctor, null);
    //    var attr = new CustomAttribute(ctor);
    //    attr.ConstructorArguments.Add(new CAArgument(module.CorLibTypes.String, Version));
    //    module.CustomAttributes.Add(attr);
    //}
}


, .net ConfuserEx. koi.



ConfuserEx\src\Confuser.Protections\Compress\Compressor.cs
ConfuserEx\src\Confuser.Runtime\Compressor.cs
ConfuserEx\src\Confuser.Protections\Compress\ExtractPhase.cs
ConfuserEx\src\Confuser.Protections\Compress\StubProtection.cs




( dotPeek). .





using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.ServiceProcess;
using System.Text;
using System.Threading.Tasks;
[assembly: InternalsVisibleTo("LicenseManagerServiceTests")]
namespace LicenseManagerService
{
    static class Program
    {
        /// <summary>
        ///     .
        /// </summary>
        ///
        static void Main()
        {
            ServiceBase[] ServicesToRun;
            ServicesToRun = new ServiceBase[]
            {
                new UAVLicenseManagerService()
            };
            ServiceBase.Run(ServicesToRun);
        }
    }
}


dotPeek





LicenseManagerService.Program, , Name Protection ( ). Control Flow Protection.



// Decompiled with JetBrains decompiler
// Type: LicenseManagerService.Program
// Assembly: LicenseManagerService, Version=1.0.5980.24716, Culture=neutral, PublicKeyToken=null
// MVID: A6EB17CC-65EE-4E2D-B66C-24E166429A4A
// Assembly location: D:\pash\Develop\License_manager\Confused\LicenseManagerService\bin\x86\Release\LicenseManagerService.exe
using System.Runtime.InteropServices;
using System.ServiceProcess;
namespace LicenseManagerService
{
  internal static class Program
  {
    private static void Main()
    {
      ServiceBase[] serviceBaseArray1 = new ServiceBase[1]
      {
        (ServiceBase) new UAVLicenseManagerService()
      };
label_1:
      int num1 = 1005209177;
      ServiceBase[] serviceBaseArray2;
      while (true)
      {
        int num2 = 1280737639;
        uint num3;
        switch ((num3 = (uint) (num1 ^ num2)) % 3U)
        {
          case 0U:
            goto label_1;
          case 1U:
            serviceBaseArray2 = serviceBaseArray1;
            num1 = (int) num3 * 1248105312 ^ 483770479;
            continue;
          default:
            goto label_4;
        }
      }
label_4:
      Program.\u200E‮‪‌‌‪‎‪‌‫‪‬‌‭‪‎‬‌‪‍‍‌‭‮(serviceBaseArray2);
    }
    static void \u200E‮‪‌‌‪‎‪‌‫‪‬‌‭‪‎‬‌‪‍‍‌‭‮([In] ServiceBase[] obj0)
    {
      ServiceBase.Run(obj0);
    }
  }
}




private readonly string ShellCommandNetworkAdapterMACAddress =
    @"ip -o link show | grep -m 1 'UP.*LOWER_UP.*ether\|LOWER_UP.*UP.*ether' | sed -n 's/.*ether \(.*\) brd.*/\1/p' | tr -d '\n[:blank:]'";




对于使用ShellCommand开头的所有代码元素,使用项目文件中的规则,名称保护模块已被禁用(名称已保留)。您可以看到“常量保护”模块的结果



internal sealed class _ob : _qA
{
  private readonly string ShellCommandNetworkAdapterMACAddress = \u003CModule\u003E.\u206E‬‌‭‭‬‏‮‬‬‪‮‫‭‌‌‬‭‪‎‮<string>(3331371713U);
  private readonly string ShellCommandNetworkAdapterCaption = \u003CModule\u003E.\u206F‌‬‍‫‭‍‌‏‪‬‫‎‭‎‮‮<string>(4243712535U);</source>



All Articles