Support Confuser 1.7 r74708 constants encrypter

This commit is contained in:
de4dot 2012-08-07 14:40:51 +02:00
parent 9db99626f2
commit 6baa3f0e2f
7 changed files with 460 additions and 144 deletions

View File

@ -75,6 +75,7 @@
<Compile Include="deobfuscators\Confuser\ConstantsDecrypterBase.cs" />
<Compile Include="deobfuscators\Confuser\ConstantsDecrypterUtils.cs" />
<Compile Include="deobfuscators\Confuser\ConstantsDecrypterV15.cs" />
<Compile Include="deobfuscators\Confuser\ConstantsDecrypterV17.cs" />
<Compile Include="deobfuscators\Confuser\ConstantsFolder.cs" />
<Compile Include="deobfuscators\Confuser\ConstantsInliner.cs" />
<Compile Include="deobfuscators\Confuser\Deobfuscator.cs" />

View File

@ -121,7 +121,7 @@ namespace de4dot.code.deobfuscators.Confuser {
ushort _c = (ushort)seed;
ushort m = _c; ushort c = _m;
for (int i = 0; i < decrypted.Length; i++) {
decrypted[i] = (byte)(encrypted[i] ^ ((seed * m + c) & 0xFF));
decrypted[i] = (byte)(encrypted[i] ^ (seed * m + c));
m = (ushort)(seed * m + _m);
c = (ushort)(seed * c + _c);
}

View File

@ -24,12 +24,14 @@ using System.Text;
using Mono.Cecil;
using Mono.Cecil.Cil;
using de4dot.blocks;
using de4dot.PE;
namespace de4dot.code.deobfuscators.Confuser {
abstract class ConstantsDecrypterBase {
protected ModuleDefinition module;
protected byte[] fileData;
protected ISimpleDeobfuscator simpleDeobfuscator;
protected MethodDefinition nativeMethod;
MethodDefinitionAndDeclaringTypeDict<DecrypterInfo> methodToDecrypterInfo = new MethodDefinitionAndDeclaringTypeDict<DecrypterInfo>();
FieldDefinitionAndDeclaringTypeDict<bool> fields = new FieldDefinitionAndDeclaringTypeDict<bool>();
protected EmbeddedResource resource;
@ -37,7 +39,6 @@ namespace de4dot.code.deobfuscators.Confuser {
public class DecrypterInfo {
public MethodDefinition decryptMethod;
public MethodDefinition nativeMethod;
public uint key0, key1, key2, key3;
public byte doubleType, singleType, int32Type, int64Type, stringType;
@ -48,7 +49,7 @@ namespace de4dot.code.deobfuscators.Confuser {
throw new ApplicationException("Could not find all type codes");
}
bool initializeKeys() {
protected virtual bool initializeKeys() {
if (!findKey0(decryptMethod, out key0))
return false;
if (!findKey1(decryptMethod, out key1))
@ -59,7 +60,7 @@ namespace de4dot.code.deobfuscators.Confuser {
return true;
}
static bool findKey0(MethodDefinition method, out uint key) {
protected static bool findKey0(MethodDefinition method, out uint key) {
var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count - 5; i++) {
if (!DotNetUtils.isLdloc(instrs[i]))
@ -104,7 +105,7 @@ namespace de4dot.code.deobfuscators.Confuser {
return false;
}
static bool findKey2Key3(MethodDefinition method, out uint key2, out uint key3) {
protected static bool findKey2Key3(MethodDefinition method, out uint key2, out uint key3) {
var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count - 3; i++) {
var ldci4_1 = instrs[i];
@ -231,6 +232,10 @@ namespace de4dot.code.deobfuscators.Confuser {
public abstract bool Detected { get; }
public MethodDefinition NativeMethod {
get { return nativeMethod; }
}
public EmbeddedResource Resource {
get { return resource; }
}
@ -273,6 +278,129 @@ namespace de4dot.code.deobfuscators.Confuser {
}
}
protected void setConstantsData(byte[] constants) {
reader = new BinaryReader(new MemoryStream(constants));
}
protected EmbeddedResource findResource(MethodDefinition method) {
return DotNetUtils.getResource(module, DotNetUtils.getCodeStrings(method)) as EmbeddedResource;
}
protected static MethodDefinition findNativeMethod(MethodDefinition method) {
var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count; i++) {
var call = instrs[i];
if (call.OpCode.Code != Code.Call)
continue;
var calledMethod = call.Operand as MethodDefinition;
if (calledMethod == null || !calledMethod.IsStatic || !calledMethod.IsNative)
continue;
if (!DotNetUtils.isMethod(calledMethod, "System.Int32", "(System.Int32)"))
continue;
return calledMethod;
}
return null;
}
static VariableDefinition getDynamicLocal_v17_r73740(MethodDefinition method) {
var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count; i++) {
i = ConfuserUtils.findCallMethod(instrs, i, Code.Callvirt, "System.Byte System.IO.BinaryReader::ReadByte()");
if (i < 0 || i + 5 >= instrs.Count)
break;
if (!DotNetUtils.isStloc(instrs[i + 1]))
continue;
var ldloc = instrs[i + 2];
if (!DotNetUtils.isLdloc(ldloc))
continue;
if (!DotNetUtils.isLdloc(instrs[i + 3]))
continue;
var ldci4 = instrs[i + 4];
if (!DotNetUtils.isLdcI4(ldci4) || DotNetUtils.getLdcI4Value(ldci4) != 0x7F)
continue;
if (instrs[i + 5].OpCode.Code != Code.And)
continue;
return DotNetUtils.getLocalVar(method.Body.Variables, ldloc);
}
return null;
}
static int getDynamicEndIndex_v17_r73740(MethodDefinition method, VariableDefinition local) {
var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count - 5; i++) {
var stloc = instrs[i];
if (!DotNetUtils.isStloc(stloc) || DotNetUtils.getLocalVar(method.Body.Variables, stloc) != local)
continue;
if (!DotNetUtils.isLdloc(instrs[i + 1]))
continue;
if (!DotNetUtils.isLdloc(instrs[i + 2]))
continue;
var ldloc = instrs[i + 3];
if (!DotNetUtils.isLdloc(ldloc) || DotNetUtils.getLocalVar(method.Body.Variables, ldloc) != local)
continue;
if (instrs[i + 4].OpCode.Code != Code.Conv_U1)
continue;
if (instrs[i + 5].OpCode.Code != Code.Stelem_I1)
continue;
return i;
}
return -1;
}
static int getDynamicStartIndex_v17_r73740(MethodDefinition method, int endIndex) {
if (endIndex < 0)
return -1;
var instrs = method.Body.Instructions;
for (int i = endIndex; i >= 0; i--) {
if (i == 0)
return i == endIndex ? -1 : i + 1;
if (instrs[i].OpCode.FlowControl == FlowControl.Next)
continue;
return i + 1;
}
return -1;
}
protected byte[] decryptConstant_v17_r73740_dynamic(DecrypterInfo info, byte[] encrypted, uint offs, uint key) {
var local = getDynamicLocal_v17_r73740(info.decryptMethod);
if (local == null)
throw new ApplicationException("Could not find local");
int endIndex = getDynamicEndIndex_v17_r73740(info.decryptMethod, local);
int startIndex = getDynamicStartIndex_v17_r73740(info.decryptMethod, endIndex);
if (startIndex < 0)
throw new ApplicationException("Could not find start/end index");
var constReader = new ConstantsReader(info.decryptMethod);
return decrypt(encrypted, key, magic => {
constReader.setConstantInt32(local, magic);
int index = startIndex, result;
if (!constReader.getNextInt32(ref index, out result) || index != endIndex)
throw new ApplicationException("Could not decrypt integer");
return (byte)result;
});
}
protected byte[] decryptConstant_v17_r73764_native(DecrypterInfo info, byte[] encrypted, uint offs, uint key) {
var x86Emu = new x86Emulator(new PeImage(fileData));
return decrypt(encrypted, key, magic => (byte)x86Emu.emulate((uint)nativeMethod.RVA, magic));
}
static byte[] decrypt(byte[] encrypted, uint key, Func<uint, byte> decryptFunc) {
var reader = new BinaryReader(new MemoryStream(encrypted));
var decrypted = new byte[reader.ReadInt32() ^ key];
for (int i = 0; i < decrypted.Length; i++) {
uint magic = Utils.readEncodedUInt32(reader);
decrypted[i] = decryptFunc(magic);
}
return decrypted;
}
public object decryptInt32(MethodDefinition caller, MethodDefinition decryptMethod, object[] args) {
var info = methodToDecrypterInfo.find(decryptMethod);
byte typeCode;

View File

@ -71,6 +71,14 @@ namespace de4dot.code.deobfuscators.Confuser {
}
public static FieldDefinition findStreamField(MethodDefinition method, TypeDefinition declaringType) {
return findStreamField(method, declaringType, "System.IO.Stream");
}
public static FieldDefinition findMemoryStreamField(MethodDefinition method, TypeDefinition declaringType) {
return findStreamField(method, declaringType, "System.IO.MemoryStream");
}
public static FieldDefinition findStreamField(MethodDefinition method, TypeDefinition declaringType, string fieldTypeName) {
var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count - 1; i++) {
var newobj = instrs[i];
@ -86,7 +94,7 @@ namespace de4dot.code.deobfuscators.Confuser {
var field = stsfld.Operand as FieldDefinition;
if (field == null || field.DeclaringType != declaringType)
continue;
if (field.FieldType.FullName != "System.IO.MemoryStream")
if (field.FieldType.FullName != fieldTypeName)
continue;
return field;

View File

@ -23,7 +23,6 @@ using System.IO;
using Mono.Cecil;
using Mono.Cecil.Cil;
using de4dot.blocks;
using de4dot.PE;
namespace de4dot.code.deobfuscators.Confuser {
class ConstantsDecrypterV15 : ConstantsDecrypterBase {
@ -91,7 +90,7 @@ namespace de4dot.code.deobfuscators.Confuser {
version = ConfuserVersion.v17_r73740_dynamic;
}
else if (DotNetUtils.callsMethod(method, "System.String System.Text.Encoding::GetString(System.Byte[],System.Int32,System.Int32)")) {
if ((info.nativeMethod = findNativeMethod(method)) == null)
if ((nativeMethod = findNativeMethod(method)) == null)
version = ConfuserVersion.v17_r73764_dynamic;
else
version = ConfuserVersion.v17_r73764_native;
@ -104,7 +103,7 @@ namespace de4dot.code.deobfuscators.Confuser {
DeobUtils.hasInteger(method, 0x10000) &&
DeobUtils.hasInteger(method, 0xFFFF))
version = ConfuserVersion.v17_r73822_normal;
else if ((info.nativeMethod = findNativeMethod(method)) == null)
else if ((nativeMethod = findNativeMethod(method)) == null)
version = ConfuserVersion.v17_r73822_dynamic;
else
version = ConfuserVersion.v17_r73822_native;
@ -119,23 +118,6 @@ namespace de4dot.code.deobfuscators.Confuser {
}
}
static MethodDefinition findNativeMethod(MethodDefinition method) {
var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count; i++) {
var call = instrs[i];
if (call.OpCode.Code != Code.Call)
continue;
var calledMethod = call.Operand as MethodDefinition;
if (calledMethod == null || !calledMethod.IsStatic || !calledMethod.IsNative)
continue;
if (!DotNetUtils.isMethod(calledMethod, "System.Int32", "(System.Int32)"))
continue;
return calledMethod;
}
return null;
}
public override void initialize() {
if ((resource = findResource(theDecrypterInfo.decryptMethod)) == null)
throw new ApplicationException("Could not find encrypted consts resource");
@ -144,8 +126,7 @@ namespace de4dot.code.deobfuscators.Confuser {
if (!initializeFields(theDecrypterInfo))
throw new ApplicationException("Could not find all fields");
var constants = DeobUtils.inflate(resource.GetResourceData(), true);
reader = new BinaryReader(new MemoryStream(constants));
setConstantsData(DeobUtils.inflate(resource.GetResourceData(), true));
}
bool initializeFields(DecrypterInfo info) {
@ -155,7 +136,7 @@ namespace de4dot.code.deobfuscators.Confuser {
case ConfuserVersion.v17_r73822_native:
if (!add(ConstantsDecrypterUtils.findDictField(info.decryptMethod, info.decryptMethod.DeclaringType)))
return false;
if (!add(ConstantsDecrypterUtils.findStreamField(info.decryptMethod, info.decryptMethod.DeclaringType)))
if (!add(ConstantsDecrypterUtils.findMemoryStreamField(info.decryptMethod, info.decryptMethod.DeclaringType)))
return false;
break;
@ -166,10 +147,6 @@ namespace de4dot.code.deobfuscators.Confuser {
return true;
}
EmbeddedResource findResource(MethodDefinition method) {
return DotNetUtils.getResource(module, DotNetUtils.getCodeStrings(method)) as EmbeddedResource;
}
protected override byte[] decryptData(DecrypterInfo info, MethodDefinition caller, object[] args, out byte typeCode) {
uint offs = info.calcHash(caller.MetadataToken.ToUInt32()) ^ (uint)args[0];
reader.BaseStream.Position = offs;
@ -188,12 +165,12 @@ namespace de4dot.code.deobfuscators.Confuser {
case ConfuserVersion.v15_r60785_normal: return decryptConstant_v15_r60785_normal(info, encrypted, offs);
case ConfuserVersion.v15_r60785_dynamic: return decryptConstant_v15_r60785_dynamic(info, encrypted, offs);
case ConfuserVersion.v17_r73404_normal: return decryptConstant_v17_r73404_normal(info, encrypted, offs);
case ConfuserVersion.v17_r73740_dynamic: return decryptConstant_v17_r73740_dynamic(info, encrypted, offs);
case ConfuserVersion.v17_r73764_dynamic: return decryptConstant_v17_r73740_dynamic(info, encrypted, offs);
case ConfuserVersion.v17_r73764_native: return decryptConstant_v17_r73764_native(info, encrypted, offs);
case ConfuserVersion.v17_r73740_dynamic: return decryptConstant_v17_r73740_dynamic(info, encrypted, offs, 0);
case ConfuserVersion.v17_r73764_dynamic: return decryptConstant_v17_r73740_dynamic(info, encrypted, offs, 0);
case ConfuserVersion.v17_r73764_native: return decryptConstant_v17_r73764_native(info, encrypted, offs, 0);
case ConfuserVersion.v17_r73822_normal: return decryptConstant_v17_r73404_normal(info, encrypted, offs);
case ConfuserVersion.v17_r73822_dynamic: return decryptConstant_v17_r73740_dynamic(info, encrypted, offs);
case ConfuserVersion.v17_r73822_native: return decryptConstant_v17_r73764_native(info, encrypted, offs);
case ConfuserVersion.v17_r73822_dynamic: return decryptConstant_v17_r73740_dynamic(info, encrypted, offs, 0);
case ConfuserVersion.v17_r73822_native: return decryptConstant_v17_r73764_native(info, encrypted, offs, 0);
default: throw new ApplicationException("Invalid version");
}
}
@ -254,103 +231,5 @@ namespace de4dot.code.deobfuscators.Confuser {
byte[] decryptConstant_v17_r73404_normal(DecrypterInfo info, byte[] encrypted, uint offs) {
return ConfuserUtils.decrypt(info.key0 ^ offs, encrypted);
}
static VariableDefinition getDynamicLocal_v17_r73740(MethodDefinition method) {
var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count; i++) {
i = ConfuserUtils.findCallMethod(instrs, i, Code.Callvirt, "System.Byte System.IO.BinaryReader::ReadByte()");
if (i < 0 || i + 5 >= instrs.Count)
break;
if (!DotNetUtils.isStloc(instrs[i + 1]))
continue;
var ldloc = instrs[i + 2];
if (!DotNetUtils.isLdloc(ldloc))
continue;
if (!DotNetUtils.isLdloc(instrs[i + 3]))
continue;
var ldci4 = instrs[i + 4];
if (!DotNetUtils.isLdcI4(ldci4) || DotNetUtils.getLdcI4Value(ldci4) != 0x7F)
continue;
if (instrs[i + 5].OpCode.Code != Code.And)
continue;
return DotNetUtils.getLocalVar(method.Body.Variables, ldloc);
}
return null;
}
static int getDynamicEndIndex_v17_r73740(MethodDefinition method, VariableDefinition local) {
var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count - 5; i++) {
var stloc = instrs[i];
if (!DotNetUtils.isStloc(stloc) || DotNetUtils.getLocalVar(method.Body.Variables, stloc) != local)
continue;
if (!DotNetUtils.isLdloc(instrs[i + 1]))
continue;
if (!DotNetUtils.isLdloc(instrs[i + 2]))
continue;
var ldloc = instrs[i + 3];
if (!DotNetUtils.isLdloc(ldloc) || DotNetUtils.getLocalVar(method.Body.Variables, ldloc) != local)
continue;
if (instrs[i + 4].OpCode.Code != Code.Conv_U1)
continue;
if (instrs[i + 5].OpCode.Code != Code.Stelem_I1)
continue;
return i;
}
return -1;
}
static int getDynamicStartIndex_v17_r73740(MethodDefinition method, int endIndex) {
if (endIndex < 0)
return -1;
var instrs = method.Body.Instructions;
for (int i = endIndex; i >= 0; i--) {
if (i == 0)
return i == endIndex ? -1 : i + 1;
if (instrs[i].OpCode.FlowControl == FlowControl.Next)
continue;
return i + 1;
}
return -1;
}
byte[] decryptConstant_v17_r73740_dynamic(DecrypterInfo info, byte[] encrypted, uint offs) {
var local = getDynamicLocal_v17_r73740(info.decryptMethod);
if (local == null)
throw new ApplicationException("Could not find local");
int endIndex = getDynamicEndIndex_v17_r73740(info.decryptMethod, local);
int startIndex = getDynamicStartIndex_v17_r73740(info.decryptMethod, endIndex);
if (startIndex < 0)
throw new ApplicationException("Could not find start/end index");
var constReader = new ConstantsReader(info.decryptMethod);
return decrypt(encrypted, magic => {
constReader.setConstantInt32(local, magic);
int index = startIndex, result;
if (!constReader.getNextInt32(ref index, out result) || index != endIndex)
throw new ApplicationException("Could not decrypt integer");
return (byte)result;
});
}
byte[] decryptConstant_v17_r73764_native(DecrypterInfo info, byte[] encrypted, uint offs) {
var x86Emu = new x86Emulator(new PeImage(fileData));
return decrypt(encrypted, magic => (byte)x86Emu.emulate((uint)info.nativeMethod.RVA, magic));
}
byte[] decrypt(byte[] encrypted, Func<uint, byte> decryptFunc) {
var reader = new BinaryReader(new MemoryStream(encrypted));
var decrypted = new byte[reader.ReadInt32()];
for (int i = 0; i < decrypted.Length; i++) {
uint magic = Utils.readEncodedUInt32(reader);
decrypted[i] = decryptFunc(magic);
}
return decrypted;
}
}
}

View File

@ -0,0 +1,276 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using Mono.Cecil;
using Mono.Cecil.Cil;
using de4dot.blocks;
namespace de4dot.code.deobfuscators.Confuser {
// Since v1.7 r74708
class ConstantsDecrypterV17 : ConstantsDecrypterBase {
MethodDefinition initMethod;
ConfuserVersion version = ConfuserVersion.Unknown;
enum ConfuserVersion {
Unknown,
v17_r74708_normal,
v17_r74708_dynamic,
v17_r74708_native,
}
class DecrypterInfoV17 : DecrypterInfo {
public readonly ConfuserVersion version = ConfuserVersion.Unknown;
public uint key4;
public DecrypterInfoV17(ConfuserVersion version, MethodDefinition decryptMethod) {
this.version = version;
this.decryptMethod = decryptMethod;
}
protected override bool initializeKeys() {
if (!findKey0(decryptMethod, out key0))
return false;
if (!findKey1_v17(decryptMethod, out key1))
return false;
if (!findKey2Key3(decryptMethod, out key2, out key3))
return false;
if (!findKey4(decryptMethod, out key4))
return false;
return true;
}
static bool findKey1_v17(MethodDefinition method, out uint key) {
var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count - 4; i++) {
var stloc = instrs[i];
if (!DotNetUtils.isStloc(stloc))
continue;
var ldci4 = instrs[i + 1];
if (!DotNetUtils.isLdcI4(ldci4))
continue;
var ldcloc = instrs[i + 2];
if (!DotNetUtils.isLdloc(ldcloc))
continue;
if (DotNetUtils.getLocalVar(method.Body.Variables, stloc) != DotNetUtils.getLocalVar(method.Body.Variables, ldcloc))
continue;
if (instrs[i + 3].OpCode.Code != Code.Xor)
continue;
if (!DotNetUtils.isStloc(instrs[i + 4]))
continue;
key = (uint)DotNetUtils.getLdcI4Value(ldci4);
return true;
}
key = 0;
return false;
}
bool findKey4(MethodDefinition method, out uint key) {
switch (version) {
case ConfuserVersion.v17_r74708_normal: return findKey4_normal(method, out key);
case ConfuserVersion.v17_r74708_dynamic: return findKey4_other(method, out key);
case ConfuserVersion.v17_r74708_native: return findKey4_other(method, out key);
default:
throw new ApplicationException("Invalid version");
}
}
static bool findKey4_normal(MethodDefinition method, out uint key) {
var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count - 5; i++) {
if (!DotNetUtils.isLdloc(instrs[i]))
continue;
if (!DotNetUtils.isLdloc(instrs[i + 1]))
continue;
if (instrs[i + 2].OpCode.Code != Code.Add)
continue;
var ldci4 = instrs[i + 3];
if (!DotNetUtils.isLdcI4(ldci4))
continue;
if (instrs[i + 4].OpCode.Code != Code.Mul)
continue;
if (!DotNetUtils.isStloc(instrs[i + 5]))
continue;
key = (uint)DotNetUtils.getLdcI4Value(ldci4);
return true;
}
key = 0;
return false;
}
static bool findKey4_other(MethodDefinition method, out uint key) {
var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count; i++) {
int index = ConfuserUtils.findCallMethod(instrs, i, Code.Callvirt, "System.Int32 System.IO.BinaryReader::ReadInt32()");
if (index < 0)
break;
if (index + 1 >= instrs.Count)
break;
var ldci4 = instrs[index + 1];
if (!DotNetUtils.isLdcI4(ldci4))
continue;
key = (uint)DotNetUtils.getLdcI4Value(ldci4);
return true;
}
key = 0;
return false;
}
}
public override bool Detected {
get { return initMethod != null; }
}
public ConstantsDecrypterV17(ModuleDefinition module, byte[] fileData, ISimpleDeobfuscator simpleDeobfuscator)
: base(module, fileData, simpleDeobfuscator) {
}
static readonly string[] requiredLocalsCctor = new string[] {
"System.Reflection.Assembly",
"System.IO.Compression.DeflateStream",
"System.Byte[]",
"System.Int32",
};
public void find() {
var cctor = DotNetUtils.getModuleTypeCctor(module);
if (cctor == null)
return;
if (!new LocalTypes(cctor).all(requiredLocalsCctor))
return;
simpleDeobfuscator.deobfuscate(cctor, true);
if (!add(ConstantsDecrypterUtils.findDictField(cctor, cctor.DeclaringType)))
return;
if (!add(ConstantsDecrypterUtils.findStreamField(cctor, cctor.DeclaringType)))
return;
var method = getDecryptMethod();
if (method == null)
return;
if (DeobUtils.hasInteger(method, 0x100) &&
DeobUtils.hasInteger(method, 0x10000) &&
DeobUtils.hasInteger(method, 0xFFFF))
version = ConfuserVersion.v17_r74708_normal;
else if ((nativeMethod = findNativeMethod(method)) == null)
version = ConfuserVersion.v17_r74708_dynamic;
else
version = ConfuserVersion.v17_r74708_native;
initMethod = cctor;
}
MethodDefinition getDecryptMethod() {
foreach (var type in module.Types) {
if (type.Attributes != (TypeAttributes.Abstract | TypeAttributes.Sealed))
continue;
if (!checkMethods(type.Methods))
continue;
foreach (var method in type.Methods) {
if (!DotNetUtils.isMethod(method, "System.Object", "(System.UInt32,System.UInt32)"))
continue;
return method;
}
}
return null;
}
protected override byte[] decryptData(DecrypterInfo info2, MethodDefinition caller, object[] args, out byte typeCode) {
var info = (DecrypterInfoV17)info2;
uint offs = info.calcHash(info2.decryptMethod.MetadataToken.ToUInt32() ^ (info2.decryptMethod.DeclaringType.MetadataToken.ToUInt32() * (uint)args[0])) ^ (uint)args[1];
reader.BaseStream.Position = offs;
typeCode = reader.ReadByte();
if (typeCode != info.int32Type && typeCode != info.int64Type &&
typeCode != info.singleType && typeCode != info.doubleType &&
typeCode != info.stringType)
throw new ApplicationException("Invalid type code");
var encrypted = reader.ReadBytes(reader.ReadInt32());
return decryptConstant(info, encrypted, offs, typeCode);
}
byte[] decryptConstant(DecrypterInfoV17 info, byte[] encrypted, uint offs, byte typeCode) {
switch (info.version) {
case ConfuserVersion.v17_r74708_normal: return decryptConstant_v17_r74708_normal(info, encrypted, offs, typeCode);
case ConfuserVersion.v17_r74708_dynamic: return decryptConstant_v17_r74708_dynamic(info, encrypted, offs, typeCode);
case ConfuserVersion.v17_r74708_native: return decryptConstant_v17_r74708_native(info, encrypted, offs, typeCode);
default:
throw new ApplicationException("Invalid version");
}
}
byte[] decryptConstant_v17_r74708_normal(DecrypterInfoV17 info, byte[] encrypted, uint offs, byte typeCode) {
return ConfuserUtils.decrypt(info.key4 * (offs + typeCode), encrypted);
}
byte[] decryptConstant_v17_r74708_dynamic(DecrypterInfoV17 info, byte[] encrypted, uint offs, byte typeCode) {
return decryptConstant_v17_r73740_dynamic(info, encrypted, offs, info.key4);
}
byte[] decryptConstant_v17_r74708_native(DecrypterInfoV17 info, byte[] encrypted, uint offs, byte typeCode) {
return decryptConstant_v17_r73764_native(info, encrypted, offs, info.key4);
}
public override void initialize() {
if ((resource = findResource(initMethod)) == null)
throw new ApplicationException("Could not find encrypted consts resource");
findDecrypterInfos();
initializeDecrypterInfos();
setConstantsData(DeobUtils.inflate(resource.GetResourceData(), true));
}
void findDecrypterInfos() {
foreach (var type in module.Types) {
if (type.Attributes != (TypeAttributes.Abstract | TypeAttributes.Sealed))
continue;
if (!checkMethods(type.Methods))
continue;
foreach (var method in type.Methods) {
if (!DotNetUtils.isMethod(method, "System.Object", "(System.UInt32,System.UInt32)"))
continue;
var info = new DecrypterInfoV17(version, method);
add(info);
}
}
}
static bool checkMethods(IEnumerable<MethodDefinition> methods) {
int numMethods = 0;
foreach (var method in methods) {
if (method.Name == ".ctor" || method.Name == ".cctor")
return false;
if (method.Attributes != (MethodAttributes.Static | MethodAttributes.HideBySig | MethodAttributes.CompilerControlled))
return false;
if (!DotNetUtils.isMethod(method, "System.Object", "(System.UInt32,System.UInt32)"))
return false;
numMethods++;
}
return numMethods > 0;
}
}
}

View File

@ -80,6 +80,7 @@ namespace de4dot.code.deobfuscators.Confuser {
ResourceDecrypter resourceDecrypter;
ConstantsDecrypter constantsDecrypter;
ConstantsDecrypterV15 constantsDecrypterV15;
ConstantsDecrypterV17 constantsDecrypterV17;
Int32ValueInliner int32ValueInliner;
Int64ValueInliner int64ValueInliner;
SingleValueInliner singleValueInliner;
@ -140,6 +141,7 @@ namespace de4dot.code.deobfuscators.Confuser {
toInt32(resourceDecrypter != null ? resourceDecrypter.Detected : false) +
toInt32(constantsDecrypter != null ? constantsDecrypter.Detected : false) +
toInt32(constantsDecrypterV15 != null ? constantsDecrypterV15.Detected : false) +
toInt32(constantsDecrypterV17 != null ? constantsDecrypterV17.Detected : false) +
toInt32(stringDecrypter != null ? stringDecrypter.Detected : false) +
toInt32(unpacker != null ? unpacker.Detected : false);
if (sum > 0)
@ -167,15 +169,28 @@ namespace de4dot.code.deobfuscators.Confuser {
void initTheRest() {
resourceDecrypter = new ResourceDecrypter(module, DeobfuscatedFile);
resourceDecrypter.find();
constantsDecrypter = new ConstantsDecrypter(module, getFileData(), DeobfuscatedFile);
constantsDecrypter.find();
constantsDecrypterV17 = new ConstantsDecrypterV17(module, getFileData(), DeobfuscatedFile);
constantsDecrypterV15 = new ConstantsDecrypterV15(module, getFileData(), DeobfuscatedFile);
if (!constantsDecrypter.Detected)
do {
constantsDecrypter.find();
if (constantsDecrypter.Detected) {
initializeConstantsDecrypter();
break;
}
constantsDecrypterV17.find();
if (constantsDecrypterV17.Detected) {
initializeConstantsDecrypter17();
break;
}
constantsDecrypterV15.find();
if (constantsDecrypter.Detected)
initializeConstantsDecrypter();
else if (constantsDecrypterV15.Detected)
initializeConstantsDecrypter15();
if (constantsDecrypterV15.Detected) {
initializeConstantsDecrypter15();
break;
}
} while (false);
proxyCallFixer = new ProxyCallFixer(module, getFileData(), DeobfuscatedFile);
proxyCallFixer.findDelegateCreator();
if (!proxyCallFixer.Detected) {
@ -431,6 +446,11 @@ namespace de4dot.code.deobfuscators.Confuser {
initialize(constantsDecrypterV15, ref hasInitializedConstantsDecrypter15);
}
bool hasInitializedConstantsDecrypter17 = false;
void initializeConstantsDecrypter17() {
initialize(constantsDecrypterV17, ref hasInitializedConstantsDecrypter17);
}
void initialize(ConstantsDecrypterBase constDecrypter, ref bool hasInitialized) {
if (hasInitialized || (constDecrypter == null || !constDecrypter.Detected))
return;
@ -455,10 +475,14 @@ namespace de4dot.code.deobfuscators.Confuser {
doubleValueInliner.RemoveUnbox = true;
DeobfuscatedFile.stringDecryptersAdded();
addFieldsToBeRemoved(constDecrypter.Fields, "Constants decrypter field");
var moduleType = DotNetUtils.getModuleType(module);
foreach (var info in constDecrypter.DecrypterInfos) {
addMethodToBeRemoved(info.decryptMethod, "Constants decrypter method");
addMethodToBeRemoved(info.nativeMethod, "Constants decrypter native method");
if (info.decryptMethod.DeclaringType == moduleType)
addMethodToBeRemoved(info.decryptMethod, "Constants decrypter method");
else
addTypeToBeRemoved(info.decryptMethod.DeclaringType, "Constants decrypter type");
}
addMethodToBeRemoved(constDecrypter.NativeMethod, "Constants decrypter native method");
addResourceToBeRemoved(constDecrypter.Resource, "Encrypted constants");
}