Der Artikel beschreibt die Erfahrungen mit der Verwendung des ConfuserEx 0.6.0-Verschleierers zum Schutz des .Net-Dienstes unter Windows und Mono im Kampf. Es war im Jahr 2016, aber ich denke, das Thema hat jetzt nicht seine Relevanz verloren.
ConfuserEx ( http://yck1509.github.io/ConfuserEx/ ) ist einer der kostenlosen Open-Source-Verschleierer für .Net. Unterstützt Windows .NET Framework und Mono.
Enthält eine große Anzahl von Modulen, die verschiedene Methoden des Codeschutzes implementieren (Umbenennen, Verschleierung des Ausführungsflusses, Verschlüsselung von Ressourcen und Konstanten, Schutz vor Debugging und Profiling, Wrapper). Mit ConfuserEx können Sie die Funktionalität erweitern, indem Sie Ihre eigenen Sicherheitsmodule schreiben.
Mit Open Source Code können Sie das Schutzsystem ändern, die Signatur des Obfuscators ändern und so die De-Obfuscator-Programme und das manuelle Reverse Engineering erschweren.
Dokumentation
Das Projekt verfügt über eine ziemlich detaillierte Dokumentation im WiKi- Format .
Benutzeroberfläche
ConfuserEx unterstützt die Benutzeroberfläche und den Befehlszeilenmodus.
Befehlszeilenmodus
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.
Projektdatei
Die Struktur der Projektdatei ist in der Dokumentation beschrieben . Die Projektdatei enthält eine Beschreibung der zu schützenden Baugruppen, Einstellungen für Schutzmodule und die Regeln, nach denen Schutzmodule zum Schutz von Baugruppen angewendet werden.
Mit Regeln können Sie Schutzmodule selektiv auf verschiedene Teile des Codes anwenden (oder nicht anwenden). Während der Verschleierung wird die Regel auf ihre Anwendbarkeit auf das aktuelle geschützte Codeelement überprüft. In diesem Fall wird die Übereinstimmung der sogenannten Signatur des Codeelements mit der Regel bewertet . Die Regeln können komplexe logische Ausdrücke enthalten .
.
<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 | ![]() |
![]() |
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:]'";
Für alle Codeelemente , die mit ShellCommand beginnen und die Regeln in der Projektdatei verwenden, wurde das Namensschutzmodul deaktiviert (die Namen bleiben erhalten). Die Ergebnisse des Konstantenschutzmoduls sind sichtbar .
internal sealed class _ob : _qA
{
private readonly string ShellCommandNetworkAdapterMACAddress = \u003CModule\u003E.\u206E<string>(3331371713U);
private readonly string ShellCommandNetworkAdapterCaption = \u003CModule\u003E.\u206F<string>(4243712535U);</source>