From 5fbda45d6d7c4904c39bd564b1ad8ba44c529123 Mon Sep 17 00:00:00 2001 From: de4dot Date: Sat, 8 Oct 2011 19:33:12 +0200 Subject: [PATCH] Add earlyDetect() method to IDeobfuscator --- de4dot.code/ObfuscatedFile.cs | 39 ++++++++++++++----- .../deobfuscators/CliSecure/Deobfuscator.cs | 6 +-- .../CliSecure/ProxyDelegateFinder.cs | 4 +- de4dot.code/deobfuscators/DeobfuscatorBase.cs | 6 ++- de4dot.code/deobfuscators/IDeobfuscator.cs | 9 ++++- .../deobfuscators/ProxyDelegateFinderBase.cs | 4 +- .../SmartAssembly/Deobfuscator.cs | 6 +-- .../SmartAssembly/ProxyDelegateFinder.cs | 4 +- .../deobfuscators/Unknown/Deobfuscator.cs | 32 +++++++++------ 9 files changed, 74 insertions(+), 36 deletions(-) diff --git a/de4dot.code/ObfuscatedFile.cs b/de4dot.code/ObfuscatedFile.cs index 6a355f36..7010af03 100644 --- a/de4dot.code/ObfuscatedFile.cs +++ b/de4dot.code/ObfuscatedFile.cs @@ -189,7 +189,6 @@ namespace de4dot { } void detectObfuscator(IEnumerable deobfuscators) { - IList memberReferences = new List(module.GetMemberReferences()); // The deobfuscators may call methods to deobfuscate control flow and decrypt // strings (statically) in order to detect the obfuscator. @@ -197,8 +196,8 @@ namespace de4dot { savedMethodBodies = new SavedMethodBodies(); foreach (var deob in deobfuscators) { + deob.init(module); deob.DeobfuscatedFile = this; - deob.init(module, memberReferences); } if (options.ForcedObfuscatorType != null) { @@ -209,17 +208,37 @@ namespace de4dot { } } } - else { - int detectVal = 0; - foreach (var deob in deobfuscators) { - int val = deob.detect(); + else + this.deob = earlyDetectObfuscator(deobfuscators) ?? detectObfuscator2(deobfuscators); + } + + IDeobfuscator earlyDetectObfuscator(IEnumerable deobfuscators) { + IDeobfuscator detected = null; + int detectVal = 0; + foreach (var deob in deobfuscators) { + int val = deob.earlyDetect(); + if (val > 0) Log.v("{0,3}: {1}", val, deob.Type); - if (val > detectVal) { - detectVal = val; - this.deob = deob; - } + if (val > detectVal) { + detectVal = val; + detected = deob; } } + return detected; + } + + IDeobfuscator detectObfuscator2(IEnumerable deobfuscators) { + IDeobfuscator detected = null; + int detectVal = 0; + foreach (var deob in deobfuscators) { + int val = deob.detect(); + Log.v("{0,3}: {1}", val, deob.Type); + if (val > detectVal) { + detectVal = val; + detected = deob; + } + } + return detected; } public void save() { diff --git a/de4dot.code/deobfuscators/CliSecure/Deobfuscator.cs b/de4dot.code/deobfuscators/CliSecure/Deobfuscator.cs index 7dfae7d5..ba2d8607 100644 --- a/de4dot.code/deobfuscators/CliSecure/Deobfuscator.cs +++ b/de4dot.code/deobfuscators/CliSecure/Deobfuscator.cs @@ -100,9 +100,8 @@ namespace de4dot.deobfuscators.CliSecure { this.options = options; } - public override void init(ModuleDefinition module, IList memberReferences) { - base.init(module, memberReferences); - proxyDelegateFinder = new ProxyDelegateFinder(module, memberReferences); + public override void init(ModuleDefinition module) { + base.init(module); } public override int detect() { @@ -121,6 +120,7 @@ namespace de4dot.deobfuscators.CliSecure { } protected override void scanForObfuscatorInternal() { + proxyDelegateFinder = new ProxyDelegateFinder(module); findCliSecureAttribute(); findCliSecureRtType(); findStringDecryptBuffer(); diff --git a/de4dot.code/deobfuscators/CliSecure/ProxyDelegateFinder.cs b/de4dot.code/deobfuscators/CliSecure/ProxyDelegateFinder.cs index 303dc221..1db27687 100644 --- a/de4dot.code/deobfuscators/CliSecure/ProxyDelegateFinder.cs +++ b/de4dot.code/deobfuscators/CliSecure/ProxyDelegateFinder.cs @@ -23,8 +23,8 @@ using Mono.Cecil; namespace de4dot.deobfuscators.CliSecure { class ProxyDelegateFinder : ProxyDelegateFinderBase { - public ProxyDelegateFinder(ModuleDefinition module, IList memberReferences) - : base(module, memberReferences) { + public ProxyDelegateFinder(ModuleDefinition module) + : base(module) { } protected override void getCallInfo(FieldDefinition field, out int methodIndex, out bool isVirtual) { diff --git a/de4dot.code/deobfuscators/DeobfuscatorBase.cs b/de4dot.code/deobfuscators/DeobfuscatorBase.cs index 13386e30..1576d047 100644 --- a/de4dot.code/deobfuscators/DeobfuscatorBase.cs +++ b/de4dot.code/deobfuscators/DeobfuscatorBase.cs @@ -81,10 +81,14 @@ namespace de4dot.deobfuscators { DefaultDecrypterType = DecrypterType.Static; } - public virtual void init(ModuleDefinition module, IList memberReferences) { + public virtual void init(ModuleDefinition module) { this.module = module; } + public virtual int earlyDetect() { + return 0; + } + protected void scanForObfuscator() { if (scanForObfuscatorCalled) return; diff --git a/de4dot.code/deobfuscators/IDeobfuscator.cs b/de4dot.code/deobfuscators/IDeobfuscator.cs index 64231b4f..5e21b3ff 100644 --- a/de4dot.code/deobfuscators/IDeobfuscator.cs +++ b/de4dot.code/deobfuscators/IDeobfuscator.cs @@ -52,10 +52,15 @@ namespace de4dot.deobfuscators { StringFeatures StringFeatures { get; } DecrypterType DefaultDecrypterType { get; } - // This is non-null only in init(), detect() and deobfuscateBegin(). + // This is non-null only in detect() and deobfuscateBegin(). IDeobfuscatedFile DeobfuscatedFile { get; set; } - void init(ModuleDefinition module, IList memberReferences); + void init(ModuleDefinition module); + + // Same as detect() but may be used by deobfuscators to detect obfuscator that decrypt + // metadata at runtime. Code in detect() assume they can access everything. 0 should be + // returned if not detected. + int earlyDetect(); // Returns 0 if it's not detected, or > 0 if detected (higher value => more likely true) int detect(); diff --git a/de4dot.code/deobfuscators/ProxyDelegateFinderBase.cs b/de4dot.code/deobfuscators/ProxyDelegateFinderBase.cs index 84f6f331..2b47313f 100644 --- a/de4dot.code/deobfuscators/ProxyDelegateFinderBase.cs +++ b/de4dot.code/deobfuscators/ProxyDelegateFinderBase.cs @@ -54,9 +54,9 @@ namespace de4dot.deobfuscators { get { return delegateCreatorMethod != null; } } - public ProxyDelegateFinderBase(ModuleDefinition module, IList memberReferences) { + public ProxyDelegateFinderBase(ModuleDefinition module) { this.module = module; - this.memberReferences = memberReferences; + this.memberReferences = new List(module.GetMemberReferences()); } public void setDelegateCreatorMethod(MethodDefinition delegateCreatorMethod) { diff --git a/de4dot.code/deobfuscators/SmartAssembly/Deobfuscator.cs b/de4dot.code/deobfuscators/SmartAssembly/Deobfuscator.cs index d776f5aa..cc23f29a 100644 --- a/de4dot.code/deobfuscators/SmartAssembly/Deobfuscator.cs +++ b/de4dot.code/deobfuscators/SmartAssembly/Deobfuscator.cs @@ -106,9 +106,8 @@ namespace de4dot.deobfuscators.SmartAssembly { StringFeatures = StringFeatures.AllowStaticDecryption; } - public override void init(ModuleDefinition module, IList memberReferences) { - base.init(module, memberReferences); - proxyDelegateFinder = new ProxyDelegateFinder(module, memberReferences); + public override void init(ModuleDefinition module) { + base.init(module); automatedErrorReportingFinder = new AutomatedErrorReportingFinder(module); tamperProtectionRemover = new TamperProtectionRemover(module); } @@ -134,6 +133,7 @@ namespace de4dot.deobfuscators.SmartAssembly { } protected override void scanForObfuscatorInternal() { + proxyDelegateFinder = new ProxyDelegateFinder(module); findSmartAssemblyAttributes(); findAutomatedErrorReportingType(); memoryManagerInfo = new MemoryManagerInfo(module); diff --git a/de4dot.code/deobfuscators/SmartAssembly/ProxyDelegateFinder.cs b/de4dot.code/deobfuscators/SmartAssembly/ProxyDelegateFinder.cs index 8ecdd6a2..1c78eecd 100644 --- a/de4dot.code/deobfuscators/SmartAssembly/ProxyDelegateFinder.cs +++ b/de4dot.code/deobfuscators/SmartAssembly/ProxyDelegateFinder.cs @@ -40,8 +40,8 @@ namespace de4dot.deobfuscators.SmartAssembly { specialCharsDict[specialChars[i]] = i; } - public ProxyDelegateFinder(ModuleDefinition module, IList memberReferences) - : base(module, memberReferences) { + public ProxyDelegateFinder(ModuleDefinition module) + : base(module) { } protected override void getCallInfo(FieldDefinition field, out int methodIndex, out bool isVirtual) { diff --git a/de4dot.code/deobfuscators/Unknown/Deobfuscator.cs b/de4dot.code/deobfuscators/Unknown/Deobfuscator.cs index 59afa76a..80e072b5 100644 --- a/de4dot.code/deobfuscators/Unknown/Deobfuscator.cs +++ b/de4dot.code/deobfuscators/Unknown/Deobfuscator.cs @@ -42,7 +42,7 @@ namespace de4dot.deobfuscators.Unknown { } class Deobfuscator : DeobfuscatorBase { - string obfuscatorName = "Unknown Obfuscator"; + string obfuscatorName; internal class Options : OptionsBase { } @@ -52,22 +52,34 @@ namespace de4dot.deobfuscators.Unknown { } public override string Name { - get { return obfuscatorName; } + get { return obfuscatorName ?? "Unknown Obfuscator"; } } public Deobfuscator(Options options) : base(options) { } - public override int detect() { - scanForObfuscator(); - return 1; + void setName(string name) { + if (obfuscatorName == null && name != null) + obfuscatorName = name; } - protected override void scanForObfuscatorInternal() { - var name = scanTypes(); - if (name != null) - obfuscatorName = name; + public override int earlyDetect() { + setName(earlyScanTypes()); + return obfuscatorName != null ? 1 : 0; + } + + string earlyScanTypes() { + foreach (var type in module.Types) { + if (type.FullName == "ConfusedByAttribute") + return "Confuser"; + } + return null; + } + + public override int detect() { + setName(scanTypes()); + return 1; } string scanTypes() { @@ -96,8 +108,6 @@ namespace de4dot.deobfuscators.Unknown { return "Spices.Net Obfuscator"; if (type.FullName == "YanoAttribute") return "Yano Obfuscator"; - if (type.FullName == "ConfusedByAttribute") - return "Confuser"; } return checkCryptoObfuscator(); }