From 291040abfeb9b471386ceee1a805e831fc57d6a6 Mon Sep 17 00:00:00 2001 From: de4dot Date: Thu, 9 Aug 2012 11:47:18 +0200 Subject: [PATCH] Detect and print Confuser version --- de4dot.code/de4dot.code.csproj | 2 + .../deobfuscators/Confuser/AntiDebugger.cs | 7 +- .../deobfuscators/Confuser/AntiDumping.cs | 7 +- .../Confuser/ConstantsDecrypterBase.cs | 3 +- .../Confuser/ConstantsDecrypterV15.cs | 39 +++++++ .../Confuser/ConstantsDecrypterV17.cs | 45 ++++++++ .../Confuser/ConstantsDecrypterV18.cs | 26 ++++- .../deobfuscators/Confuser/Deobfuscator.cs | 70 +++++++++--- .../Confuser/IVersionProvider.cs | 24 ++++ .../Confuser/JitMethodsDecrypter.cs | 37 ++++++ .../Confuser/MemoryMethodsDecrypter.cs | 42 +++++++ .../Confuser/MethodsDecrypterBase.cs | 4 +- .../deobfuscators/Confuser/ProxyCallFixer.cs | 56 ++++++++- .../Confuser/ResourceDecrypter.cs | 37 +++++- .../deobfuscators/Confuser/StringDecrypter.cs | 38 +++++- .../deobfuscators/Confuser/Unpacker.cs | 62 +++++++++- .../deobfuscators/Confuser/VersionDetector.cs | 108 ++++++++++++++++++ 17 files changed, 584 insertions(+), 23 deletions(-) create mode 100644 de4dot.code/deobfuscators/Confuser/IVersionProvider.cs create mode 100644 de4dot.code/deobfuscators/Confuser/VersionDetector.cs diff --git a/de4dot.code/de4dot.code.csproj b/de4dot.code/de4dot.code.csproj index 86904b5c..c601dd14 100644 --- a/de4dot.code/de4dot.code.csproj +++ b/de4dot.code/de4dot.code.csproj @@ -86,6 +86,7 @@ + @@ -93,6 +94,7 @@ + diff --git a/de4dot.code/deobfuscators/Confuser/AntiDebugger.cs b/de4dot.code/deobfuscators/Confuser/AntiDebugger.cs index b2df7f99..93104fab 100644 --- a/de4dot.code/deobfuscators/Confuser/AntiDebugger.cs +++ b/de4dot.code/deobfuscators/Confuser/AntiDebugger.cs @@ -22,7 +22,7 @@ using Mono.Cecil.Cil; using de4dot.blocks; namespace de4dot.code.deobfuscators.Confuser { - class AntiDebugger { + class AntiDebugger : IVersionProvider { ModuleDefinition module; MethodDefinition initMethod; @@ -109,5 +109,10 @@ namespace de4dot.code.deobfuscators.Confuser { } return false; } + + public bool getRevisionRange(out int minRev, out int maxRev) { + minRev = maxRev = 0; + return false; + } } } diff --git a/de4dot.code/deobfuscators/Confuser/AntiDumping.cs b/de4dot.code/deobfuscators/Confuser/AntiDumping.cs index 50b479ae..c8958ec1 100644 --- a/de4dot.code/deobfuscators/Confuser/AntiDumping.cs +++ b/de4dot.code/deobfuscators/Confuser/AntiDumping.cs @@ -22,7 +22,7 @@ using Mono.Cecil.Cil; using de4dot.blocks; namespace de4dot.code.deobfuscators.Confuser { - class AntiDumping { + class AntiDumping : IVersionProvider { ModuleDefinition module; MethodDefinition initMethod; @@ -113,5 +113,10 @@ namespace de4dot.code.deobfuscators.Confuser { return true; } + + public bool getRevisionRange(out int minRev, out int maxRev) { + minRev = maxRev = 0; + return false; + } } } diff --git a/de4dot.code/deobfuscators/Confuser/ConstantsDecrypterBase.cs b/de4dot.code/deobfuscators/Confuser/ConstantsDecrypterBase.cs index 3ccbf86d..b575f449 100644 --- a/de4dot.code/deobfuscators/Confuser/ConstantsDecrypterBase.cs +++ b/de4dot.code/deobfuscators/Confuser/ConstantsDecrypterBase.cs @@ -27,7 +27,7 @@ using de4dot.blocks; using de4dot.PE; namespace de4dot.code.deobfuscators.Confuser { - abstract class ConstantsDecrypterBase { + abstract class ConstantsDecrypterBase : IVersionProvider { protected ModuleDefinition module; protected byte[] fileData; protected ISimpleDeobfuscator simpleDeobfuscator; @@ -258,6 +258,7 @@ namespace de4dot.code.deobfuscators.Confuser { this.simpleDeobfuscator = simpleDeobfuscator; } + public abstract bool getRevisionRange(out int minRev, out int maxRev); public abstract void initialize(); protected void add(DecrypterInfo info) { diff --git a/de4dot.code/deobfuscators/Confuser/ConstantsDecrypterV15.cs b/de4dot.code/deobfuscators/Confuser/ConstantsDecrypterV15.cs index 11ffbb9f..795c0b83 100644 --- a/de4dot.code/deobfuscators/Confuser/ConstantsDecrypterV15.cs +++ b/de4dot.code/deobfuscators/Confuser/ConstantsDecrypterV15.cs @@ -231,5 +231,44 @@ namespace de4dot.code.deobfuscators.Confuser { byte[] decryptConstant_v17_r73404_normal(DecrypterInfo info, byte[] encrypted, uint offs) { return ConfuserUtils.decrypt(info.key0 ^ offs, encrypted); } + + public override bool getRevisionRange(out int minRev, out int maxRev) { + switch (version) { + case ConfuserVersion.Unknown: + minRev = maxRev = 0; + return false; + + case ConfuserVersion.v15_r60785_normal: + case ConfuserVersion.v15_r60785_dynamic: + minRev = 60785; + maxRev = 72989; + return true; + + case ConfuserVersion.v17_r73404_normal: + minRev = 73404; + maxRev = 73605; + return true; + + case ConfuserVersion.v17_r73740_dynamic: + minRev = 73740; + maxRev = 73740; + return true; + + case ConfuserVersion.v17_r73764_dynamic: + case ConfuserVersion.v17_r73764_native: + minRev = 73764; + maxRev = 73791; + return true; + + case ConfuserVersion.v17_r73822_normal: + case ConfuserVersion.v17_r73822_dynamic: + case ConfuserVersion.v17_r73822_native: + minRev = 73822; + maxRev = 74637; + return true; + + default: throw new ApplicationException("Invalid version"); + } + } } } diff --git a/de4dot.code/deobfuscators/Confuser/ConstantsDecrypterV17.cs b/de4dot.code/deobfuscators/Confuser/ConstantsDecrypterV17.cs index f25ef4ec..de358479 100644 --- a/de4dot.code/deobfuscators/Confuser/ConstantsDecrypterV17.cs +++ b/de4dot.code/deobfuscators/Confuser/ConstantsDecrypterV17.cs @@ -438,5 +438,50 @@ namespace de4dot.code.deobfuscators.Confuser { } return -1; } + + public override bool getRevisionRange(out int minRev, out int maxRev) { + switch (version) { + case ConfuserVersion.Unknown: + minRev = maxRev = 0; + return false; + + case ConfuserVersion.v17_r74708_normal: + case ConfuserVersion.v17_r74708_dynamic: + case ConfuserVersion.v17_r74708_native: + minRev = 74708; + maxRev = 74708; + return true; + + case ConfuserVersion.v17_r74788_normal: + case ConfuserVersion.v17_r74788_dynamic: + case ConfuserVersion.v17_r74788_native: + minRev = 74788; + maxRev = 74788; + return true; + + case ConfuserVersion.v17_r74816_normal: + case ConfuserVersion.v17_r74816_dynamic: + case ConfuserVersion.v17_r74816_native: + minRev = 74816; + maxRev = 74852; + return true; + + case ConfuserVersion.v17_r75056_normal: + case ConfuserVersion.v17_r75056_dynamic: + case ConfuserVersion.v17_r75056_native: + minRev = 75056; + maxRev = 75184; + return true; + + case ConfuserVersion.v18_r75257_normal: + case ConfuserVersion.v18_r75257_dynamic: + case ConfuserVersion.v18_r75257_native: + minRev = 75257; + maxRev = 75349; + return true; + + default: throw new ApplicationException("Invalid version"); + } + } } } diff --git a/de4dot.code/deobfuscators/Confuser/ConstantsDecrypterV18.cs b/de4dot.code/deobfuscators/Confuser/ConstantsDecrypterV18.cs index 56fee0f9..976fb1b5 100644 --- a/de4dot.code/deobfuscators/Confuser/ConstantsDecrypterV18.cs +++ b/de4dot.code/deobfuscators/Confuser/ConstantsDecrypterV18.cs @@ -29,7 +29,7 @@ using de4dot.PE; namespace de4dot.code.deobfuscators.Confuser { // Since v1.8 r75367 - class ConstantsDecrypterV18 { + class ConstantsDecrypterV18 : IVersionProvider { ModuleDefinition module; byte[] fileData; ISimpleDeobfuscator simpleDeobfuscator; @@ -708,5 +708,29 @@ namespace de4dot.code.deobfuscators.Confuser { installMethod.Body.Instructions.Clear(); installMethod.Body.Instructions.Add(Instruction.Create(OpCodes.Ret)); } + + public bool getRevisionRange(out int minRev, out int maxRev) { + switch (version) { + case ConfuserVersion.Unknown: + minRev = maxRev = 0; + return false; + + case ConfuserVersion.v18_r75367_normal: + case ConfuserVersion.v18_r75367_dynamic: + case ConfuserVersion.v18_r75367_native: + minRev = 75367; + maxRev = 75367; + return true; + + case ConfuserVersion.v18_r75369_normal: + case ConfuserVersion.v18_r75369_dynamic: + case ConfuserVersion.v18_r75369_native: + minRev = 75369; + maxRev = int.MaxValue; + return true; + + default: throw new ApplicationException("Invalid version"); + } + } } } diff --git a/de4dot.code/deobfuscators/Confuser/Deobfuscator.cs b/de4dot.code/deobfuscators/Confuser/Deobfuscator.cs index e049157a..3bf3eea0 100644 --- a/de4dot.code/deobfuscators/Confuser/Deobfuscator.cs +++ b/de4dot.code/deobfuscators/Confuser/Deobfuscator.cs @@ -78,8 +78,8 @@ namespace de4dot.code.deobfuscators.Confuser { AntiDumping antiDumping; ResourceDecrypter resourceDecrypter; ConstantsDecrypterV18 constantsDecrypterV18; - ConstantsDecrypterV15 constantsDecrypterV15; ConstantsDecrypterV17 constantsDecrypterV17; + ConstantsDecrypterV15 constantsDecrypterV15; Int32ValueInliner int32ValueInliner; Int64ValueInliner int64ValueInliner; SingleValueInliner singleValueInliner; @@ -149,19 +149,22 @@ namespace de4dot.code.deobfuscators.Confuser { } protected override void scanForObfuscator() { - jitMethodsDecrypter = new JitMethodsDecrypter(module, DeobfuscatedFile); - try { - jitMethodsDecrypter.find(); - } - catch { - } - if (jitMethodsDecrypter.Detected) - return; - memoryMethodsDecrypter = new MemoryMethodsDecrypter(module, DeobfuscatedFile); - memoryMethodsDecrypter.find(); - if (memoryMethodsDecrypter.Detected) - return; - initTheRest(); + do { + jitMethodsDecrypter = new JitMethodsDecrypter(module, DeobfuscatedFile); + try { + jitMethodsDecrypter.find(); + } + catch { + } + if (jitMethodsDecrypter.Detected) + break; + memoryMethodsDecrypter = new MemoryMethodsDecrypter(module, DeobfuscatedFile); + memoryMethodsDecrypter.find(); + if (memoryMethodsDecrypter.Detected) + break; + initTheRest(); + } while (false); + initializeObfuscatorName(); } void initTheRest() { @@ -200,6 +203,41 @@ namespace de4dot.code.deobfuscators.Confuser { initializeStringDecrypter(); unpacker = new Unpacker(module); unpacker.find(DeobfuscatedFile, this); + initializeObfuscatorName(); + } + + void initializeObfuscatorName() { + var versionString = getVersionString(); + if (string.IsNullOrEmpty(versionString)) + obfuscatorName = DeobfuscatorInfo.THE_NAME; + else + obfuscatorName = string.Format("{0} {1}", DeobfuscatorInfo.THE_NAME, versionString); + } + + string getVersionString() { + var versionProviders = new IVersionProvider[] { + jitMethodsDecrypter, + memoryMethodsDecrypter, + proxyCallFixer, + antiDebugger, + antiDumping, + resourceDecrypter, + constantsDecrypterV18, + constantsDecrypterV17, + constantsDecrypterV15, + stringDecrypter, + unpacker, + }; + + var vd = new VersionDetector(); + foreach (var versionProvider in versionProviders) { + if (versionProvider == null) + continue; + int minRev, maxRev; + if (versionProvider.getRevisionRange(out minRev, out maxRev)) + vd.addRevs(minRev, maxRev); + } + return vd.getVersionString(); } byte[] getFileData() { @@ -313,6 +351,10 @@ namespace de4dot.code.deobfuscators.Confuser { public override void deobfuscateBegin() { base.deobfuscateBegin(); + var versionString = getVersionString(); + if (!string.IsNullOrEmpty(versionString)) + Log.v("Detected version: {0}", versionString); + removeObfuscatorAttribute(); initializeConstantsDecrypterV18(); initializeConstantsDecrypterV17(); diff --git a/de4dot.code/deobfuscators/Confuser/IVersionProvider.cs b/de4dot.code/deobfuscators/Confuser/IVersionProvider.cs new file mode 100644 index 00000000..25acc79c --- /dev/null +++ b/de4dot.code/deobfuscators/Confuser/IVersionProvider.cs @@ -0,0 +1,24 @@ +/* + Copyright (C) 2011-2012 de4dot@gmail.com + + This file is part of de4dot. + + de4dot is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + de4dot is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with de4dot. If not, see . +*/ + +namespace de4dot.code.deobfuscators.Confuser { + interface IVersionProvider { + bool getRevisionRange(out int minRev, out int maxRev); + } +} diff --git a/de4dot.code/deobfuscators/Confuser/JitMethodsDecrypter.cs b/de4dot.code/deobfuscators/Confuser/JitMethodsDecrypter.cs index 087ac374..6da4fdd6 100644 --- a/de4dot.code/deobfuscators/Confuser/JitMethodsDecrypter.cs +++ b/de4dot.code/deobfuscators/Confuser/JitMethodsDecrypter.cs @@ -58,6 +58,8 @@ namespace de4dot.code.deobfuscators.Confuser { public JitMethodsDecrypter(ModuleDefinition module, ISimpleDeobfuscator simpleDeobfuscator, JitMethodsDecrypter other) : base(module, simpleDeobfuscator, other) { + if (other != null) + this.version = other.version; } protected override bool checkType(TypeDefinition type, MethodDefinition initMethod) { @@ -689,5 +691,40 @@ namespace de4dot.code.deobfuscators.Confuser { sb.Append((char)(reader.ReadUInt16() ^ key5)); return sb.ToString(); } + + public override bool getRevisionRange(out int minRev, out int maxRev) { + switch (version) { + case ConfuserVersion.Unknown: + minRev = maxRev = 0; + return false; + + case ConfuserVersion.v17_r73404: + minRev = 73404; + maxRev = 73430; + return true; + + case ConfuserVersion.v17_r73477: + minRev = 73477; + maxRev = 73477; + return true; + + case ConfuserVersion.v17_r73479: + minRev = 73479; + maxRev = 73822; + return true; + + case ConfuserVersion.v17_r74021: + minRev = 74021; + maxRev = 75369; + return true; + + case ConfuserVersion.v18_r75402: + minRev = 75402; + maxRev = int.MaxValue; + return true; + + default: throw new ApplicationException("Invalid version"); + } + } } } diff --git a/de4dot.code/deobfuscators/Confuser/MemoryMethodsDecrypter.cs b/de4dot.code/deobfuscators/Confuser/MemoryMethodsDecrypter.cs index ba51e593..214587f4 100644 --- a/de4dot.code/deobfuscators/Confuser/MemoryMethodsDecrypter.cs +++ b/de4dot.code/deobfuscators/Confuser/MemoryMethodsDecrypter.cs @@ -46,6 +46,8 @@ namespace de4dot.code.deobfuscators.Confuser { public MemoryMethodsDecrypter(ModuleDefinition module, ISimpleDeobfuscator simpleDeobfuscator, MemoryMethodsDecrypter other) : base(module, simpleDeobfuscator, other) { + if (other != null) + this.version = other.version; } protected override bool checkType(TypeDefinition type, MethodDefinition initMethod) { @@ -381,5 +383,45 @@ namespace de4dot.code.deobfuscators.Confuser { } return true; } + + public override bool getRevisionRange(out int minRev, out int maxRev) { + switch (version) { + case ConfuserVersion.Unknown: + minRev = maxRev = 0; + return false; + + case ConfuserVersion.v14_r57884: + minRev = 57884; + maxRev = 57884; + return true; + + case ConfuserVersion.v14_r58004: + minRev = 58004; + maxRev = 58446; + return true; + + case ConfuserVersion.v14_r58564: + minRev = 58564; + maxRev = 58919; + return true; + + case ConfuserVersion.v15_r59014: + minRev = 59014; + maxRev = 70489; + return true; + + case ConfuserVersion.v16_r71742: + minRev = 71742; + maxRev = 72989; + return true; + + case ConfuserVersion.v17_r73605: + minRev = 73605; + maxRev = int.MaxValue; + return true; + + default: throw new ApplicationException("Invalid version"); + } + } } } diff --git a/de4dot.code/deobfuscators/Confuser/MethodsDecrypterBase.cs b/de4dot.code/deobfuscators/Confuser/MethodsDecrypterBase.cs index 175215ff..738d0e2d 100644 --- a/de4dot.code/deobfuscators/Confuser/MethodsDecrypterBase.cs +++ b/de4dot.code/deobfuscators/Confuser/MethodsDecrypterBase.cs @@ -27,7 +27,7 @@ using de4dot.blocks; using de4dot.PE; namespace de4dot.code.deobfuscators.Confuser { - abstract class MethodsDecrypterBase { + abstract class MethodsDecrypterBase : IVersionProvider { protected ModuleDefinition module; protected ISimpleDeobfuscator simpleDeobfuscator; protected MethodDefinition initMethod; @@ -64,6 +64,8 @@ namespace de4dot.code.deobfuscators.Confuser { return DeobUtils.lookup(module, def, errorMessage); } + public abstract bool getRevisionRange(out int minRev, out int maxRev); + public void find() { find(DotNetUtils.getModuleTypeCctor(module)); } diff --git a/de4dot.code/deobfuscators/Confuser/ProxyCallFixer.cs b/de4dot.code/deobfuscators/Confuser/ProxyCallFixer.cs index d423a90c..609c25ce 100644 --- a/de4dot.code/deobfuscators/Confuser/ProxyCallFixer.cs +++ b/de4dot.code/deobfuscators/Confuser/ProxyCallFixer.cs @@ -27,7 +27,7 @@ using de4dot.blocks; using de4dot.PE; namespace de4dot.code.deobfuscators.Confuser { - class ProxyCallFixer : ProxyCallFixer2 { + class ProxyCallFixer : ProxyCallFixer2, IVersionProvider { MethodDefinitionAndDeclaringTypeDict methodToInfo = new MethodDefinitionAndDeclaringTypeDict(); FieldDefinitionAndDeclaringTypeDict> fieldToMethods = new FieldDefinitionAndDeclaringTypeDict>(); string ourAsm; @@ -945,5 +945,59 @@ namespace de4dot.code.deobfuscators.Confuser { cctor.Body.Instructions.Clear(); cctor.Body.Instructions.Add(Instruction.Create(OpCodes.Ret)); } + + public bool getRevisionRange(out int minRev, out int maxRev) { + switch (version) { + case ConfuserVersion.Unknown: + minRev = maxRev = 0; + return false; + + case ConfuserVersion.v10_r42915: + minRev = 42915; + maxRev = 48509; + return true; + + case ConfuserVersion.v10_r48717: + minRev = 48717; + maxRev = 58446; + return true; + + case ConfuserVersion.v14_r58564: + minRev = 58564; + maxRev = 58852; + return true; + + case ConfuserVersion.v14_r58857: + minRev = 58857; + maxRev = 73605; + return true; + + case ConfuserVersion.v17_r73740_normal: + case ConfuserVersion.v17_r73740_native: + minRev = 73740; + maxRev = 74637; + return true; + + case ConfuserVersion.v17_r74708_normal: + case ConfuserVersion.v17_r74708_native: + minRev = 74708; + maxRev = 75349; + return true; + + case ConfuserVersion.v18_r75367_normal: + case ConfuserVersion.v18_r75367_native: + minRev = 75367; + maxRev = 75926; + return true; + + case ConfuserVersion.v19_r76101_normal: + case ConfuserVersion.v19_r76101_native: + minRev = 76101; + maxRev = int.MaxValue; + return true; + + default: throw new ApplicationException("Invalid version"); + } + } } } diff --git a/de4dot.code/deobfuscators/Confuser/ResourceDecrypter.cs b/de4dot.code/deobfuscators/Confuser/ResourceDecrypter.cs index 985fddb6..e9af082b 100644 --- a/de4dot.code/deobfuscators/Confuser/ResourceDecrypter.cs +++ b/de4dot.code/deobfuscators/Confuser/ResourceDecrypter.cs @@ -25,7 +25,7 @@ using Mono.Cecil.Cil; using de4dot.blocks; namespace de4dot.code.deobfuscators.Confuser { - class ResourceDecrypter { + class ResourceDecrypter : IVersionProvider { ModuleDefinition module; ISimpleDeobfuscator simpleDeobfuscator; MethodDefinition handler; @@ -386,5 +386,40 @@ namespace de4dot.code.deobfuscators.Confuser { return; ConfuserUtils.removeResourceHookCode(blocks, handler); } + + public bool getRevisionRange(out int minRev, out int maxRev) { + switch (version) { + case ConfuserVersion.Unknown: + minRev = maxRev = 0; + return false; + + case ConfuserVersion.v14_r55802: + minRev = 55802; + maxRev = 72989; + return true; + + case ConfuserVersion.v17_r73404: + minRev = 73404; + maxRev = 73791; + return true; + + case ConfuserVersion.v17_r73822: + minRev = 73822; + maxRev = 75349; + return true; + + case ConfuserVersion.v18_r75367: + minRev = 75367; + maxRev = 75367; + return true; + + case ConfuserVersion.v18_r75369: + minRev = 75369; + maxRev = int.MaxValue; + return true; + + default: throw new ApplicationException("Invalid version"); + } + } } } diff --git a/de4dot.code/deobfuscators/Confuser/StringDecrypter.cs b/de4dot.code/deobfuscators/Confuser/StringDecrypter.cs index ff70db0f..2206b4fb 100644 --- a/de4dot.code/deobfuscators/Confuser/StringDecrypter.cs +++ b/de4dot.code/deobfuscators/Confuser/StringDecrypter.cs @@ -26,7 +26,7 @@ using Mono.Cecil.Cil; using de4dot.blocks; namespace de4dot.code.deobfuscators.Confuser { - class StringDecrypter { + class StringDecrypter : IVersionProvider { ModuleDefinition module; MethodDefinition decryptMethod; EmbeddedResource resource; @@ -449,5 +449,41 @@ namespace de4dot.code.deobfuscators.Confuser { public string decrypt(MethodDefinition caller, int magic) { return decrypter.decrypt(caller, magic); } + + public bool getRevisionRange(out int minRev, out int maxRev) { + switch (version) { + case ConfuserVersion.Unknown: + minRev = maxRev = 0; + return false; + + case ConfuserVersion.v10_r42915: + minRev = 42915; + maxRev = 48771; + return true; + + case ConfuserVersion.v10_r48832: + minRev = 48832; + maxRev = 49238; + return true; + + case ConfuserVersion.v11_r49299: + minRev = 49299; + maxRev = 58741; + return true; + + case ConfuserVersion.v13_r55604_safe: + minRev = 55604; + maxRev = 58741; + return true; + + case ConfuserVersion.v14_r58802_safe: + case ConfuserVersion.v14_r58802_dynamic: + minRev = 58802; + maxRev = 60408; + return true; + + default: throw new ApplicationException("Invalid version"); + } + } } } diff --git a/de4dot.code/deobfuscators/Confuser/Unpacker.cs b/de4dot.code/deobfuscators/Confuser/Unpacker.cs index 387db2ff..b6fbfc67 100644 --- a/de4dot.code/deobfuscators/Confuser/Unpacker.cs +++ b/de4dot.code/deobfuscators/Confuser/Unpacker.cs @@ -64,7 +64,7 @@ namespace de4dot.code.deobfuscators.Confuser { } } - class Unpacker { + class Unpacker : IVersionProvider { ModuleDefinition module; EmbeddedResource mainAsmResource; uint key0, key1; @@ -537,5 +537,65 @@ namespace de4dot.code.deobfuscators.Confuser { return; ConfuserUtils.removeResourceHookCode(blocks, asmResolverMethod); } + + public bool getRevisionRange(out int minRev, out int maxRev) { + switch (version) { + case ConfuserVersion.Unknown: + minRev = maxRev = 0; + return false; + + case ConfuserVersion.v10_r42915: + minRev = 42915; + maxRev = 58446; + return true; + + case ConfuserVersion.v14_r58564: + minRev = 58564; + maxRev = 58741; + return true; + + case ConfuserVersion.v14_r58802: + minRev = 58802; + maxRev = 58817; + return true; + + case ConfuserVersion.v14_r58852: + minRev = 58852; + maxRev = 60408; + return true; + + case ConfuserVersion.v15_r60785: + minRev = 60785; + maxRev = 72989; + return true; + + case ConfuserVersion.v17_r73404: + minRev = 73404; + maxRev = 73430; + return true; + + case ConfuserVersion.v17_r73477: + minRev = 73477; + maxRev = 75056; + return true; + + case ConfuserVersion.v17_r75076: + minRev = 75076; + maxRev = 75158; + return true; + + case ConfuserVersion.v18_r75184: + minRev = 75184; + maxRev = 75349; + return true; + + case ConfuserVersion.v18_r75367: + minRev = 75367; + maxRev = int.MaxValue; + return true; + + default: throw new ApplicationException("Invalid version"); + } + } } } diff --git a/de4dot.code/deobfuscators/Confuser/VersionDetector.cs b/de4dot.code/deobfuscators/Confuser/VersionDetector.cs new file mode 100644 index 00000000..6bce8f85 --- /dev/null +++ b/de4dot.code/deobfuscators/Confuser/VersionDetector.cs @@ -0,0 +1,108 @@ +/* + Copyright (C) 2011-2012 de4dot@gmail.com + + This file is part of de4dot. + + de4dot is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + de4dot is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with de4dot. If not, see . +*/ + +using System; +using System.Collections.Generic; + +namespace de4dot.code.deobfuscators.Confuser { + class VersionDetector { + int minRev = -1, maxRev = int.MaxValue; + + static readonly int[] revs = new int[] { + 42519, 42915, 42916, 42917, 42919, 42960, 43055, 45527, + 48493, 48509, 48717, 48718, 48771, 48832, 48863, 49238, + 49299, 49300, 49966, 50359, 50378, 50661, 54225, 54254, + 54312, 54431, 54564, 54566, 54574, 55346, 55604, 55608, + 55609, 55764, 55802, 56535, 57588, 57593, 57699, 57778, + 57884, 58004, 58172, 58446, 58564, 58741, 58802, 58804, + 58817, 58852, 58857, 58919, 59014, 60052, 60054, 60111, + 60408, 60785, 60787, 61954, 62284, 64574, 65189, 65282, + 65297, 65298, 65299, 65747, 66631, 66853, 66883, 67015, + 67058, 69339, 69666, 70489, 71742, 71743, 71847, 72164, + 72434, 72819, 72853, 72868, 72989, 73404, 73430, 73477, + 73479, 73566, 73593, 73605, 73740, 73764, 73770, 73791, + 73822, 74021, 74184, 74476, 74482, 74520, 74574, 74578, + 74637, 74708, 74788, 74816, 74852, 75056, 75076, 75077, + 75131, 75152, 75158, 75184, 75257, 75267, 75288, 75291, + 75306, 75318, 75349, 75367, 75369, 75402, 75459, 75461, + 75573, 75719, 75720, 75725, 75806, 75807, 75926, 76101, + 76119, 76163, 76186, + }; + + static Dictionary revToVersion = new Dictionary { + { 42519, new Version(1, 0) }, // May 01 2010 + { 49299, new Version(1, 1) }, // Jul 13 2010 + { 50661, new Version(1, 2) }, // Jul 23 2010 + { 54574, new Version(1, 3) }, // Aug 31 2010 + { 55609, new Version(1, 4) }, // Sep 15 2010 + { 58919, new Version(1, 5) }, // Nov 29 2010 + { 60787, new Version(1, 6) }, // Jan 10 2011 + { 72989, new Version(1, 7) }, // Mar 09 2012 + { 75131, new Version(1, 8) }, // May 31 2012 + { 75461, new Version(1, 9) }, // Jun 23 2012 + }; + + static VersionDetector() { + Version currentVersion = null; + int prevRev = -1; + foreach (var rev in revs) { + if (rev <= prevRev) + throw new ApplicationException(); + Version version; + if (revToVersion.TryGetValue(rev, out version)) + currentVersion = version; + else if (currentVersion == null) + throw new ApplicationException(); + else + revToVersion[rev] = currentVersion; + } + } + + public void addRevs(int min, int max) { + if (min < 0 || max < 0 || min > max) + throw new ArgumentOutOfRangeException(); + if (!revToVersion.ContainsKey(min) || (max != int.MaxValue && !revToVersion.ContainsKey(max))) + throw new ArgumentOutOfRangeException(); + + if (min > minRev) + minRev = min; + if (max < maxRev) + maxRev = max; + } + + public string getVersionString() { + if (minRev > maxRev || minRev < 0) + return null; + var minVersion = revToVersion[minRev]; + if (maxRev == int.MaxValue) + return string.Format("v{0}.{1}+ (r{2}+)", minVersion.Major, minVersion.Minor, minRev); + var maxVersion = revToVersion[maxRev]; + if (minVersion == maxVersion) { + if (minRev == maxRev) + return string.Format("v{0}.{1} (r{2})", minVersion.Major, minVersion.Minor, minRev); + return string.Format("v{0}.{1} (r{2}-r{3})", minVersion.Major, minVersion.Minor, minRev, maxRev); + } + return string.Format("v{0}.{1} - v{2}.{3} (r{4}-r{5})", minVersion.Major, minVersion.Minor, maxVersion.Major, maxVersion.Minor, minRev, maxRev); + } + + public override string ToString() { + return getVersionString() ?? ""; + } + } +}