Use standard .NET naming convention

This commit is contained in:
de4dot 2013-01-19 13:09:49 +01:00
parent 08ca871406
commit 40083ad33a
22 changed files with 1286 additions and 1286 deletions

View File

@ -58,12 +58,12 @@ namespace de4dot.code.deobfuscators.Confuser {
this.module = module; this.module = module;
} }
public void find() { public void Find() {
if (checkMethod(DotNetUtils.getModuleTypeCctor(module))) if (CheckMethod(DotNetUtils.GetModuleTypeCctor(module)))
return; return;
} }
bool checkMethod(MethodDef method) { bool CheckMethod(MethodDef method) {
if (method == null || method.Body == null) if (method == null || method.Body == null)
return false; return false;
@ -73,13 +73,13 @@ namespace de4dot.code.deobfuscators.Confuser {
var calledMethod = instr.Operand as MethodDef; var calledMethod = instr.Operand as MethodDef;
if (calledMethod == null || !calledMethod.IsStatic) if (calledMethod == null || !calledMethod.IsStatic)
continue; continue;
if (!DotNetUtils.isMethod(calledMethod, "System.Void", "()")) if (!DotNetUtils.IsMethod(calledMethod, "System.Void", "()"))
continue; continue;
var type = calledMethod.DeclaringType; var type = calledMethod.DeclaringType;
if (type == null) if (type == null)
continue; continue;
if (checkMethod_normal(type, calledMethod) || checkMethod_safe(type, calledMethod)) { if (CheckMethod_normal(type, calledMethod) || CheckMethod_safe(type, calledMethod)) {
initMethod = calledMethod; initMethod = calledMethod;
return true; return true;
} }
@ -88,27 +88,27 @@ namespace de4dot.code.deobfuscators.Confuser {
return false; return false;
} }
static bool checkProfilerStrings1(MethodDef method) { static bool CheckProfilerStrings1(MethodDef method) {
if (!DotNetUtils.hasString(method, "COR_ENABLE_PROFILING")) if (!DotNetUtils.HasString(method, "COR_ENABLE_PROFILING"))
return false; return false;
if (!DotNetUtils.hasString(method, "COR_PROFILER")) if (!DotNetUtils.HasString(method, "COR_PROFILER"))
return false; return false;
return true; return true;
} }
static bool checkProfilerStrings2(MethodDef method) { static bool CheckProfilerStrings2(MethodDef method) {
if (!DotNetUtils.hasString(method, "COR_")) if (!DotNetUtils.HasString(method, "COR_"))
return false; return false;
if (!DotNetUtils.hasString(method, "ENABLE_PROFILING")) if (!DotNetUtils.HasString(method, "ENABLE_PROFILING"))
return false; return false;
if (!DotNetUtils.hasString(method, "PROFILER")) if (!DotNetUtils.HasString(method, "PROFILER"))
return false; return false;
return true; return true;
} }
static MethodDef getAntiDebugMethod(TypeDef type, MethodDef initMethod) { static MethodDef GetAntiDebugMethod(TypeDef type, MethodDef initMethod) {
foreach (var method in type.Methods) { foreach (var method in type.Methods) {
if (method.Body == null || method == initMethod) if (method.Body == null || method == initMethod)
continue; continue;
@ -116,7 +116,7 @@ namespace de4dot.code.deobfuscators.Confuser {
continue; continue;
if (!method.IsPrivate) if (!method.IsPrivate)
continue; continue;
if (!DotNetUtils.isMethod(method, "System.Void", "()") && !DotNetUtils.isMethod(method, "System.Void", "(System.Object)")) if (!DotNetUtils.IsMethod(method, "System.Void", "()") && !DotNetUtils.IsMethod(method, "System.Void", "(System.Object)"))
continue; continue;
return method; return method;
@ -124,59 +124,59 @@ namespace de4dot.code.deobfuscators.Confuser {
return null; return null;
} }
bool checkMethod_normal(TypeDef type, MethodDef initMethod) { bool CheckMethod_normal(TypeDef type, MethodDef initMethod) {
var ntQueryInformationProcess = DotNetUtils.getPInvokeMethod(type, "ntdll", "NtQueryInformationProcess"); var ntQueryInformationProcess = DotNetUtils.GetPInvokeMethod(type, "ntdll", "NtQueryInformationProcess");
if (ntQueryInformationProcess == null) if (ntQueryInformationProcess == null)
return false; return false;
if (DotNetUtils.getPInvokeMethod(type, "ntdll", "NtSetInformationProcess") == null) if (DotNetUtils.GetPInvokeMethod(type, "ntdll", "NtSetInformationProcess") == null)
return false; return false;
if (DotNetUtils.getPInvokeMethod(type, "kernel32", "CloseHandle") == null) if (DotNetUtils.GetPInvokeMethod(type, "kernel32", "CloseHandle") == null)
return false; return false;
var antiDebugMethod = getAntiDebugMethod(type, initMethod); var antiDebugMethod = GetAntiDebugMethod(type, initMethod);
if (antiDebugMethod == null) if (antiDebugMethod == null)
return false; return false;
if (!DotNetUtils.hasString(antiDebugMethod, "Debugger detected (Managed)")) if (!DotNetUtils.HasString(antiDebugMethod, "Debugger detected (Managed)"))
return false; return false;
if (DotNetUtils.callsMethod(initMethod, "System.Void System.Threading.Thread::.ctor(System.Threading.ParameterizedThreadStart)")) { if (DotNetUtils.CallsMethod(initMethod, "System.Void System.Threading.Thread::.ctor(System.Threading.ParameterizedThreadStart)")) {
int failFastCalls = ConfuserUtils.countCalls(antiDebugMethod, "System.Void System.Environment::FailFast(System.String)"); int failFastCalls = ConfuserUtils.CountCalls(antiDebugMethod, "System.Void System.Environment::FailFast(System.String)");
if (failFastCalls != 6 && failFastCalls != 8) if (failFastCalls != 6 && failFastCalls != 8)
return false; return false;
if (!checkProfilerStrings1(initMethod)) if (!CheckProfilerStrings1(initMethod))
return false; return false;
if (!DotNetUtils.callsMethod(antiDebugMethod, "System.Void System.Threading.Thread::.ctor(System.Threading.ParameterizedThreadStart)")) { if (!DotNetUtils.CallsMethod(antiDebugMethod, "System.Void System.Threading.Thread::.ctor(System.Threading.ParameterizedThreadStart)")) {
if (ConfuserUtils.countCalls(antiDebugMethod, ntQueryInformationProcess) != 2) if (ConfuserUtils.CountCalls(antiDebugMethod, ntQueryInformationProcess) != 2)
return false; return false;
version = ConfuserVersion.v16_r61954_normal; version = ConfuserVersion.v16_r61954_normal;
} }
else if (failFastCalls == 8) { else if (failFastCalls == 8) {
if (ConfuserUtils.countCalls(antiDebugMethod, ntQueryInformationProcess) != 2) if (ConfuserUtils.CountCalls(antiDebugMethod, ntQueryInformationProcess) != 2)
return false; return false;
version = ConfuserVersion.v17_r73822_normal; version = ConfuserVersion.v17_r73822_normal;
} }
else if (failFastCalls == 6) { else if (failFastCalls == 6) {
if (DotNetUtils.getPInvokeMethod(type, "IsDebuggerPresent") == null) if (DotNetUtils.GetPInvokeMethod(type, "IsDebuggerPresent") == null)
return false; return false;
if (ConfuserUtils.countCalls(antiDebugMethod, ntQueryInformationProcess) != 0) if (ConfuserUtils.CountCalls(antiDebugMethod, ntQueryInformationProcess) != 0)
return false; return false;
version = ConfuserVersion.v17_r74021_normal; version = ConfuserVersion.v17_r74021_normal;
} }
else else
return false; return false;
} }
else if (!DotNetUtils.callsMethod(initMethod, "System.Void System.Threading.ThreadStart::.ctor(System.Object,System.IntPtr)")) { else if (!DotNetUtils.CallsMethod(initMethod, "System.Void System.Threading.ThreadStart::.ctor(System.Object,System.IntPtr)")) {
if (!DotNetUtils.callsMethod(initMethod, "System.Void System.Diagnostics.Process::EnterDebugMode()")) if (!DotNetUtils.CallsMethod(initMethod, "System.Void System.Diagnostics.Process::EnterDebugMode()"))
return false; return false;
if (!checkProfilerStrings1(antiDebugMethod)) if (!CheckProfilerStrings1(antiDebugMethod))
return false; return false;
version = ConfuserVersion.v14_r57588_normal; version = ConfuserVersion.v14_r57588_normal;
} }
else { else {
if (!DotNetUtils.callsMethod(initMethod, "System.Void System.Diagnostics.Process::EnterDebugMode()")) if (!DotNetUtils.CallsMethod(initMethod, "System.Void System.Diagnostics.Process::EnterDebugMode()"))
return false; return false;
if (!checkProfilerStrings1(antiDebugMethod)) if (!CheckProfilerStrings1(antiDebugMethod))
return false; return false;
version = ConfuserVersion.v14_r60785_normal; version = ConfuserVersion.v14_r60785_normal;
} }
@ -184,45 +184,45 @@ namespace de4dot.code.deobfuscators.Confuser {
return true; return true;
} }
bool checkMethod_safe(TypeDef type, MethodDef initMethod) { bool CheckMethod_safe(TypeDef type, MethodDef initMethod) {
if (type == DotNetUtils.getModuleType(module)) { if (type == DotNetUtils.GetModuleType(module)) {
if (!DotNetUtils.hasString(initMethod, "Debugger detected (Managed)")) if (!DotNetUtils.HasString(initMethod, "Debugger detected (Managed)"))
return false; return false;
if (!checkProfilerStrings1(initMethod)) if (!CheckProfilerStrings1(initMethod))
return false; return false;
version = ConfuserVersion.v14_r57588_safe; version = ConfuserVersion.v14_r57588_safe;
} }
else { else {
var ntQueryInformationProcess = DotNetUtils.getPInvokeMethod(type, "ntdll", "NtQueryInformationProcess"); var ntQueryInformationProcess = DotNetUtils.GetPInvokeMethod(type, "ntdll", "NtQueryInformationProcess");
if (ntQueryInformationProcess == null) if (ntQueryInformationProcess == null)
return false; return false;
if (DotNetUtils.getPInvokeMethod(type, "ntdll", "NtSetInformationProcess") == null) if (DotNetUtils.GetPInvokeMethod(type, "ntdll", "NtSetInformationProcess") == null)
return false; return false;
if (DotNetUtils.getPInvokeMethod(type, "kernel32", "CloseHandle") == null) if (DotNetUtils.GetPInvokeMethod(type, "kernel32", "CloseHandle") == null)
return false; return false;
var antiDebugMethod = getAntiDebugMethod(type, initMethod); var antiDebugMethod = GetAntiDebugMethod(type, initMethod);
if (antiDebugMethod == null) if (antiDebugMethod == null)
return false; return false;
if (!DotNetUtils.hasString(antiDebugMethod, "Debugger detected (Managed)") && if (!DotNetUtils.HasString(antiDebugMethod, "Debugger detected (Managed)") &&
!DotNetUtils.hasString(antiDebugMethod, "Debugger is detected (Managed)")) !DotNetUtils.HasString(antiDebugMethod, "Debugger is detected (Managed)"))
return false; return false;
if (!DotNetUtils.callsMethod(initMethod, "System.Void System.Threading.Thread::.ctor(System.Threading.ParameterizedThreadStart)")) if (!DotNetUtils.CallsMethod(initMethod, "System.Void System.Threading.Thread::.ctor(System.Threading.ParameterizedThreadStart)"))
return false; return false;
if (ConfuserUtils.countCalls(antiDebugMethod, ntQueryInformationProcess) != 0) if (ConfuserUtils.CountCalls(antiDebugMethod, ntQueryInformationProcess) != 0)
return false; return false;
if (!checkProfilerStrings1(initMethod) && !checkProfilerStrings2(initMethod)) if (!CheckProfilerStrings1(initMethod) && !CheckProfilerStrings2(initMethod))
return false; return false;
int failFastCalls = ConfuserUtils.countCalls(antiDebugMethod, "System.Void System.Environment::FailFast(System.String)"); int failFastCalls = ConfuserUtils.CountCalls(antiDebugMethod, "System.Void System.Environment::FailFast(System.String)");
if (failFastCalls != 2) if (failFastCalls != 2)
return false; return false;
if (!DotNetUtils.callsMethod(antiDebugMethod, "System.Void System.Threading.Thread::.ctor(System.Threading.ParameterizedThreadStart)")) if (!DotNetUtils.CallsMethod(antiDebugMethod, "System.Void System.Threading.Thread::.ctor(System.Threading.ParameterizedThreadStart)"))
version = ConfuserVersion.v16_r61954_safe; version = ConfuserVersion.v16_r61954_safe;
else if (DotNetUtils.getPInvokeMethod(type, "IsDebuggerPresent") == null) else if (DotNetUtils.GetPInvokeMethod(type, "IsDebuggerPresent") == null)
version = ConfuserVersion.v17_r73822_safe; version = ConfuserVersion.v17_r73822_safe;
else if (checkProfilerStrings1(initMethod)) else if (CheckProfilerStrings1(initMethod))
version = ConfuserVersion.v17_r74021_safe; version = ConfuserVersion.v17_r74021_safe;
else else
version = ConfuserVersion.v19_r76119_safe; version = ConfuserVersion.v19_r76119_safe;
@ -231,7 +231,7 @@ namespace de4dot.code.deobfuscators.Confuser {
return true; return true;
} }
public bool getRevisionRange(out int minRev, out int maxRev) { public bool GetRevisionRange(out int minRev, out int maxRev) {
switch (version) { switch (version) {
case ConfuserVersion.Unknown: case ConfuserVersion.Unknown:
minRev = maxRev = 0; minRev = maxRev = 0;

View File

@ -55,12 +55,12 @@ namespace de4dot.code.deobfuscators.Confuser {
this.module = module; this.module = module;
} }
public void find(ISimpleDeobfuscator simpleDeobfuscator) { public void Find(ISimpleDeobfuscator simpleDeobfuscator) {
if (checkMethod(simpleDeobfuscator, DotNetUtils.getModuleTypeCctor(module))) if (CheckMethod(simpleDeobfuscator, DotNetUtils.GetModuleTypeCctor(module)))
return; return;
} }
bool checkMethod(ISimpleDeobfuscator simpleDeobfuscator, MethodDef method) { bool CheckMethod(ISimpleDeobfuscator simpleDeobfuscator, MethodDef method) {
if (method == null || method.Body == null) if (method == null || method.Body == null)
return false; return false;
@ -72,14 +72,14 @@ namespace de4dot.code.deobfuscators.Confuser {
continue; continue;
if (calledMethod == null || !calledMethod.IsStatic) if (calledMethod == null || !calledMethod.IsStatic)
continue; continue;
if (!DotNetUtils.isMethod(calledMethod, "System.Void", "()")) if (!DotNetUtils.IsMethod(calledMethod, "System.Void", "()"))
continue; continue;
var type = calledMethod.DeclaringType; var type = calledMethod.DeclaringType;
if (type.NestedTypes.Count > 0) if (type.NestedTypes.Count > 0)
continue; continue;
simpleDeobfuscator.deobfuscate(calledMethod, true); simpleDeobfuscator.Deobfuscate(calledMethod, true);
if (checkType(type, calledMethod)) { if (CheckType(type, calledMethod)) {
initMethod = calledMethod; initMethod = calledMethod;
return true; return true;
} }
@ -87,52 +87,52 @@ namespace de4dot.code.deobfuscators.Confuser {
return false; return false;
} }
bool checkType(TypeDef type, MethodDef initMethod) { bool CheckType(TypeDef type, MethodDef initMethod) {
return checkType_v14_r58564(type, initMethod) || return CheckType_v14_r58564(type, initMethod) ||
checkType_v14_r58852(type, initMethod); CheckType_v14_r58852(type, initMethod);
} }
bool checkType_v14_r58564(TypeDef type, MethodDef initMethod) { bool CheckType_v14_r58564(TypeDef type, MethodDef initMethod) {
var virtualProtect = DotNetUtils.getPInvokeMethod(type, "VirtualProtect"); var virtualProtect = DotNetUtils.GetPInvokeMethod(type, "VirtualProtect");
if (virtualProtect == null) if (virtualProtect == null)
return false; return false;
if (!DotNetUtils.callsMethod(initMethod, "System.IntPtr System.Runtime.InteropServices.Marshal::GetHINSTANCE(System.Reflection.Module)")) if (!DotNetUtils.CallsMethod(initMethod, "System.IntPtr System.Runtime.InteropServices.Marshal::GetHINSTANCE(System.Reflection.Module)"))
return false; return false;
if (ConfuserUtils.countCalls(initMethod, virtualProtect) != 3) if (ConfuserUtils.CountCalls(initMethod, virtualProtect) != 3)
return false; return false;
if (!DeobUtils.hasInteger(initMethod, 224)) if (!DeobUtils.HasInteger(initMethod, 224))
return false; return false;
if (!DeobUtils.hasInteger(initMethod, 240)) if (!DeobUtils.HasInteger(initMethod, 240))
return false; return false;
if (!DeobUtils.hasInteger(initMethod, 267)) if (!DeobUtils.HasInteger(initMethod, 267))
return false; return false;
version = ConfuserVersion.v14_r58564; version = ConfuserVersion.v14_r58564;
return true; return true;
} }
bool checkType_v14_r58852(TypeDef type, MethodDef initMethod) { bool CheckType_v14_r58852(TypeDef type, MethodDef initMethod) {
var virtualProtect = DotNetUtils.getPInvokeMethod(type, "VirtualProtect"); var virtualProtect = DotNetUtils.GetPInvokeMethod(type, "VirtualProtect");
if (virtualProtect == null) if (virtualProtect == null)
return false; return false;
if (!DotNetUtils.callsMethod(initMethod, "System.IntPtr System.Runtime.InteropServices.Marshal::GetHINSTANCE(System.Reflection.Module)")) if (!DotNetUtils.CallsMethod(initMethod, "System.IntPtr System.Runtime.InteropServices.Marshal::GetHINSTANCE(System.Reflection.Module)"))
return false; return false;
int virtualProtectCalls = ConfuserUtils.countCalls(initMethod, virtualProtect); int virtualProtectCalls = ConfuserUtils.CountCalls(initMethod, virtualProtect);
if (virtualProtectCalls != 14 && virtualProtectCalls != 16) if (virtualProtectCalls != 14 && virtualProtectCalls != 16)
return false; return false;
if (!DeobUtils.hasInteger(initMethod, 0x3C)) if (!DeobUtils.HasInteger(initMethod, 0x3C))
return false; return false;
if (!DeobUtils.hasInteger(initMethod, 0x6c64746e)) if (!DeobUtils.HasInteger(initMethod, 0x6c64746e))
return false; return false;
if (!DeobUtils.hasInteger(initMethod, 0x6c642e6c)) if (!DeobUtils.HasInteger(initMethod, 0x6c642e6c))
return false; return false;
if (!DeobUtils.hasInteger(initMethod, 0x6f43744e)) if (!DeobUtils.HasInteger(initMethod, 0x6f43744e))
return false; return false;
if (!DeobUtils.hasInteger(initMethod, 0x6e69746e)) if (!DeobUtils.HasInteger(initMethod, 0x6e69746e))
return false; return false;
int locallocs = ConfuserUtils.countOpCode(initMethod, Code.Localloc); int locallocs = ConfuserUtils.CountOpCode(initMethod, Code.Localloc);
if (DeobUtils.hasInteger(initMethod, 0x18)) if (DeobUtils.HasInteger(initMethod, 0x18))
version = ConfuserVersion.v14_r58852; version = ConfuserVersion.v14_r58852;
else if (virtualProtectCalls == 16) else if (virtualProtectCalls == 16)
version = ConfuserVersion.v16_r69339; version = ConfuserVersion.v16_r69339;
@ -140,9 +140,9 @@ namespace de4dot.code.deobfuscators.Confuser {
if (locallocs == 2) if (locallocs == 2)
version = ConfuserVersion.v17_r74708; version = ConfuserVersion.v17_r74708;
else if (locallocs == 1) { else if (locallocs == 1) {
if (DotNetUtils.hasString(initMethod, "<Unknown>")) if (DotNetUtils.HasString(initMethod, "<Unknown>"))
version = ConfuserVersion.v18_r75257; version = ConfuserVersion.v18_r75257;
else if (isRev75725(initMethod)) else if (IsRev75725(initMethod))
version = ConfuserVersion.v19_r75725; version = ConfuserVersion.v19_r75725;
else else
version = ConfuserVersion.v19_r76186; version = ConfuserVersion.v19_r76186;
@ -156,7 +156,7 @@ namespace de4dot.code.deobfuscators.Confuser {
return true; return true;
} }
static bool isRev75725(MethodDef method) { static bool IsRev75725(MethodDef method) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count - 9; i++) { for (int i = 0; i < instrs.Count - 9; i++) {
if (!instrs[i].IsLdcI4() || instrs[i].GetLdcI4Value() != 8) if (!instrs[i].IsLdcI4() || instrs[i].GetLdcI4Value() != 8)
@ -197,7 +197,7 @@ namespace de4dot.code.deobfuscators.Confuser {
return false; return false;
} }
public bool getRevisionRange(out int minRev, out int maxRev) { public bool GetRevisionRange(out int minRev, out int maxRev) {
switch (version) { switch (version) {
case ConfuserVersion.Unknown: case ConfuserVersion.Unknown:
minRev = maxRev = 0; minRev = maxRev = 0;

View File

@ -37,7 +37,7 @@ namespace de4dot.code.deobfuscators.Confuser {
: base(instrs, emulateConvInstrs) { : base(instrs, emulateConvInstrs) {
} }
protected override bool processInstructionInt64(ref int index, Stack<ConstantInfo<long>> stack) { protected override bool ProcessInstructionInt64(ref int index, Stack<ConstantInfo<long>> stack) {
if (!firstTime) if (!firstTime)
return false; return false;
firstTime = false; firstTime = false;

View File

@ -26,9 +26,9 @@ using de4dot.blocks;
namespace de4dot.code.deobfuscators.Confuser { namespace de4dot.code.deobfuscators.Confuser {
static class ConfuserUtils { static class ConfuserUtils {
public static int findCallMethod(IList<Instruction> instrs, int index, Code callCode, string methodFullName) { public static int FindCallMethod(IList<Instruction> instrs, int index, Code callCode, string methodFullName) {
for (int i = index; i < instrs.Count; i++) { for (int i = index; i < instrs.Count; i++) {
if (!isCallMethod(instrs[i], callCode, methodFullName)) if (!IsCallMethod(instrs[i], callCode, methodFullName))
continue; continue;
return i; return i;
@ -36,9 +36,9 @@ namespace de4dot.code.deobfuscators.Confuser {
return -1; return -1;
} }
public static int findCallMethod(IList<Instr> instrs, int index, Code callCode, string methodFullName) { public static int FindCallMethod(IList<Instr> instrs, int index, Code callCode, string methodFullName) {
for (int i = index; i < instrs.Count; i++) { for (int i = index; i < instrs.Count; i++) {
if (!isCallMethod(instrs[i].Instruction, callCode, methodFullName)) if (!IsCallMethod(instrs[i].Instruction, callCode, methodFullName))
continue; continue;
return i; return i;
@ -46,24 +46,24 @@ namespace de4dot.code.deobfuscators.Confuser {
return -1; return -1;
} }
public static bool isCallMethod(Instruction instr, Code callCode, string methodFullName) { public static bool IsCallMethod(Instruction instr, Code callCode, string methodFullName) {
if (instr.OpCode.Code != callCode) if (instr.OpCode.Code != callCode)
return false; return false;
var calledMethod = instr.Operand as IMethod; var calledMethod = instr.Operand as IMethod;
return calledMethod != null && calledMethod.FullName == methodFullName; return calledMethod != null && calledMethod.FullName == methodFullName;
} }
public static bool removeResourceHookCode(Blocks blocks, MethodDef handler) { public static bool RemoveResourceHookCode(Blocks blocks, MethodDef handler) {
return removeResolveHandlerCode(blocks, handler, "System.Void System.AppDomain::add_ResourceResolve(System.ResolveEventHandler)"); return RemoveResolveHandlerCode(blocks, handler, "System.Void System.AppDomain::add_ResourceResolve(System.ResolveEventHandler)");
} }
public static bool removeAssemblyHookCode(Blocks blocks, MethodDef handler) { public static bool RemoveAssemblyHookCode(Blocks blocks, MethodDef handler) {
return removeResolveHandlerCode(blocks, handler, "System.Void System.AppDomain::add_AssemblyResolve(System.ResolveEventHandler)"); return RemoveResolveHandlerCode(blocks, handler, "System.Void System.AppDomain::add_AssemblyResolve(System.ResolveEventHandler)");
} }
static bool removeResolveHandlerCode(Blocks blocks, MethodDef handler, string installHandlerMethod) { static bool RemoveResolveHandlerCode(Blocks blocks, MethodDef handler, string installHandlerMethod) {
bool modified = false; bool modified = false;
foreach (var block in blocks.MethodBlocks.getAllBlocks()) { foreach (var block in blocks.MethodBlocks.GetAllBlocks()) {
var instrs = block.Instructions; var instrs = block.Instructions;
for (int i = 0; i < instrs.Count - 4; i++) { for (int i = 0; i < instrs.Count - 4; i++) {
var call = instrs[i]; var call = instrs[i];
@ -96,19 +96,19 @@ namespace de4dot.code.deobfuscators.Confuser {
if (calledMethod == null || calledMethod.FullName != installHandlerMethod) if (calledMethod == null || calledMethod.FullName != installHandlerMethod)
continue; continue;
block.remove(i, 5); block.Remove(i, 5);
modified = true; modified = true;
} }
} }
return modified; return modified;
} }
public static byte[] decryptCompressedInt32Data(Arg64ConstantsReader constReader, int exprStart, int exprEnd, IBinaryReader reader, byte[] decrypted) { public static byte[] DecryptCompressedInt32Data(Arg64ConstantsReader constReader, int exprStart, int exprEnd, IBinaryReader reader, byte[] decrypted) {
for (int i = 0; i < decrypted.Length; i++) { for (int i = 0; i < decrypted.Length; i++) {
constReader.Arg = reader.Read7BitEncodedInt32(); constReader.Arg = reader.Read7BitEncodedInt32();
int index = exprStart; int index = exprStart;
long result; long result;
if (!constReader.getInt64(ref index, out result) || index != exprEnd) if (!constReader.GetInt64(ref index, out result) || index != exprEnd)
throw new ApplicationException("Could not decrypt integer"); throw new ApplicationException("Could not decrypt integer");
decrypted[i] = (byte)result; decrypted[i] = (byte)result;
} }
@ -116,11 +116,11 @@ namespace de4dot.code.deobfuscators.Confuser {
} }
static readonly byte[] defaultDecryptKey = new byte[1]; static readonly byte[] defaultDecryptKey = new byte[1];
public static byte[] decrypt(uint seed, byte[] encrypted) { public static byte[] Decrypt(uint seed, byte[] encrypted) {
return decrypt(seed, encrypted, defaultDecryptKey); return Decrypt(seed, encrypted, defaultDecryptKey);
} }
public static byte[] decrypt(uint seed, byte[] encrypted, byte[] key) { public static byte[] Decrypt(uint seed, byte[] encrypted, byte[] key) {
var decrypted = new byte[encrypted.Length]; var decrypted = new byte[encrypted.Length];
ushort _m = (ushort)(seed >> 16); ushort _m = (ushort)(seed >> 16);
ushort _c = (ushort)seed; ushort _c = (ushort)seed;
@ -133,7 +133,7 @@ namespace de4dot.code.deobfuscators.Confuser {
return decrypted; return decrypted;
} }
public static int countCalls(MethodDef method, string methodFullName) { public static int CountCalls(MethodDef method, string methodFullName) {
if (method == null || method.Body == null) if (method == null || method.Body == null)
return 0; return 0;
int count = 0; int count = 0;
@ -147,7 +147,7 @@ namespace de4dot.code.deobfuscators.Confuser {
return count; return count;
} }
public static int countCalls(MethodDef method, MethodDef calledMethod) { public static int CountCalls(MethodDef method, MethodDef calledMethod) {
if (method == null || method.Body == null) if (method == null || method.Body == null)
return 0; return 0;
int count = 0; int count = 0;
@ -160,7 +160,7 @@ namespace de4dot.code.deobfuscators.Confuser {
return count; return count;
} }
public static int countOpCode(MethodDef method, Code code) { public static int CountOpCode(MethodDef method, Code code) {
if (method == null || method.Body == null) if (method == null || method.Body == null)
return 0; return 0;

View File

@ -41,25 +41,25 @@ namespace de4dot.code.deobfuscators.Confuser {
public uint key0, key1, key2, key3; public uint key0, key1, key2, key3;
public byte doubleType, singleType, int32Type, int64Type, stringType; public byte doubleType, singleType, int32Type, int64Type, stringType;
public void initialize() { public void Initialize() {
if (!initializeKeys()) if (!InitializeKeys())
throw new ApplicationException("Could not find all keys"); throw new ApplicationException("Could not find all keys");
if (!initializeTypeCodes()) if (!InitializeTypeCodes())
throw new ApplicationException("Could not find all type codes"); throw new ApplicationException("Could not find all type codes");
} }
protected virtual bool initializeKeys() { protected virtual bool InitializeKeys() {
if (!findKey0(decryptMethod, out key0)) if (!FindKey0(decryptMethod, out key0))
return false; return false;
if (!findKey1(decryptMethod, out key1)) if (!FindKey1(decryptMethod, out key1))
return false; return false;
if (!findKey2Key3(decryptMethod, out key2, out key3)) if (!FindKey2Key3(decryptMethod, out key2, out key3))
return false; return false;
return true; return true;
} }
protected static bool findKey0(MethodDef method, out uint key) { protected static bool FindKey0(MethodDef method, out uint key) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count - 5; i++) { for (int i = 0; i < instrs.Count - 5; i++) {
if (!instrs[i].IsLdloc()) if (!instrs[i].IsLdloc())
@ -83,10 +83,10 @@ namespace de4dot.code.deobfuscators.Confuser {
return false; return false;
} }
static bool findKey1(MethodDef method, out uint key) { static bool FindKey1(MethodDef method, out uint key) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count; i++) { for (int i = 0; i < instrs.Count; i++) {
int index = ConfuserUtils.findCallMethod(instrs, i, Code.Callvirt, "System.Int32 System.Reflection.MemberInfo::get_MetadataToken()"); int index = ConfuserUtils.FindCallMethod(instrs, i, Code.Callvirt, "System.Int32 System.Reflection.MemberInfo::get_MetadataToken()");
if (index < 0) if (index < 0)
break; break;
if (index + 2 > instrs.Count) if (index + 2 > instrs.Count)
@ -104,7 +104,7 @@ namespace de4dot.code.deobfuscators.Confuser {
return false; return false;
} }
protected static bool findKey2Key3(MethodDef method, out uint key2, out uint key3) { protected static bool FindKey2Key3(MethodDef method, out uint key2, out uint key3) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count - 3; i++) { for (int i = 0; i < instrs.Count - 3; i++) {
var ldci4_1 = instrs[i]; var ldci4_1 = instrs[i];
@ -127,31 +127,31 @@ namespace de4dot.code.deobfuscators.Confuser {
return false; return false;
} }
bool initializeTypeCodes() { bool InitializeTypeCodes() {
var allBlocks = new Blocks(decryptMethod).MethodBlocks.getAllBlocks(); var allBlocks = new Blocks(decryptMethod).MethodBlocks.GetAllBlocks();
if (!findTypeCode(allBlocks, out doubleType, Code.Call, "System.Double System.BitConverter::ToDouble(System.Byte[],System.Int32)")) if (!FindTypeCode(allBlocks, out doubleType, Code.Call, "System.Double System.BitConverter::ToDouble(System.Byte[],System.Int32)"))
return false; return false;
if (!findTypeCode(allBlocks, out singleType, Code.Call, "System.Single System.BitConverter::ToSingle(System.Byte[],System.Int32)")) if (!FindTypeCode(allBlocks, out singleType, Code.Call, "System.Single System.BitConverter::ToSingle(System.Byte[],System.Int32)"))
return false; return false;
if (!findTypeCode(allBlocks, out int32Type, Code.Call, "System.Int32 System.BitConverter::ToInt32(System.Byte[],System.Int32)")) if (!FindTypeCode(allBlocks, out int32Type, Code.Call, "System.Int32 System.BitConverter::ToInt32(System.Byte[],System.Int32)"))
return false; return false;
if (!findTypeCode(allBlocks, out int64Type, Code.Call, "System.Int64 System.BitConverter::ToInt64(System.Byte[],System.Int32)")) if (!FindTypeCode(allBlocks, out int64Type, Code.Call, "System.Int64 System.BitConverter::ToInt64(System.Byte[],System.Int32)"))
return false; return false;
if (!findTypeCode(allBlocks, out stringType, Code.Callvirt, "System.String System.Text.Encoding::GetString(System.Byte[])") && if (!FindTypeCode(allBlocks, out stringType, Code.Callvirt, "System.String System.Text.Encoding::GetString(System.Byte[])") &&
!findTypeCode(allBlocks, out stringType, Code.Callvirt, "System.String System.Text.Encoding::GetString(System.Byte[],System.Int32,System.Int32)")) !FindTypeCode(allBlocks, out stringType, Code.Callvirt, "System.String System.Text.Encoding::GetString(System.Byte[],System.Int32,System.Int32)"))
return false; return false;
return true; return true;
} }
static bool findTypeCode(IList<Block> allBlocks, out byte typeCode, Code callCode, string bitConverterMethod) { static bool FindTypeCode(IList<Block> allBlocks, out byte typeCode, Code callCode, string bitConverterMethod) {
foreach (var block in allBlocks) { foreach (var block in allBlocks) {
if (block.Sources.Count != 1) if (block.Sources.Count != 1)
continue; continue;
int index = ConfuserUtils.findCallMethod(block.Instructions, 0, callCode, bitConverterMethod); int index = ConfuserUtils.FindCallMethod(block.Instructions, 0, callCode, bitConverterMethod);
if (index < 0) if (index < 0)
continue; continue;
if (!findTypeCode(block.Sources[0], out typeCode)) if (!FindTypeCode(block.Sources[0], out typeCode))
continue; continue;
return true; return true;
@ -160,10 +160,10 @@ namespace de4dot.code.deobfuscators.Confuser {
return false; return false;
} }
static Block fixBlock(Block block) { static Block FixBlock(Block block) {
if (block.Sources.Count != 1) if (block.Sources.Count != 1)
return block; return block;
if (block.getOnlyTarget() == null) if (block.GetOnlyTarget() == null)
return block; return block;
if (block.Instructions.Count == 0) { if (block.Instructions.Count == 0) {
} }
@ -174,8 +174,8 @@ namespace de4dot.code.deobfuscators.Confuser {
return block.Sources[0]; return block.Sources[0];
} }
static bool findTypeCode(Block block, out byte typeCode) { static bool FindTypeCode(Block block, out byte typeCode) {
block = fixBlock(block); block = FixBlock(block);
var instrs = block.Instructions; var instrs = block.Instructions;
int numCeq = 0; int numCeq = 0;
@ -197,7 +197,7 @@ namespace de4dot.code.deobfuscators.Confuser {
return false; return false;
} }
public uint calcHash(uint x) { public uint CalcHash(uint x) {
uint h0 = key1 ^ x; uint h0 = key1 ^ x;
uint h1 = key2; uint h1 = key2;
uint h2 = key3; uint h2 = key3;
@ -240,7 +240,7 @@ namespace de4dot.code.deobfuscators.Confuser {
} }
public IEnumerable<FieldDef> Fields { public IEnumerable<FieldDef> Fields {
get { return fields.getKeys(); } get { return fields.GetKeys(); }
} }
protected bool HasDecrypterInfos { protected bool HasDecrypterInfos {
@ -248,7 +248,7 @@ namespace de4dot.code.deobfuscators.Confuser {
} }
public IEnumerable<DecrypterInfo> DecrypterInfos { public IEnumerable<DecrypterInfo> DecrypterInfos {
get { return methodToDecrypterInfo.getValues(); } get { return methodToDecrypterInfo.GetValues(); }
} }
public ConstantsDecrypterBase(ModuleDefMD module, byte[] fileData, ISimpleDeobfuscator simpleDeobfuscator) { public ConstantsDecrypterBase(ModuleDefMD module, byte[] fileData, ISimpleDeobfuscator simpleDeobfuscator) {
@ -257,36 +257,36 @@ namespace de4dot.code.deobfuscators.Confuser {
this.simpleDeobfuscator = simpleDeobfuscator; this.simpleDeobfuscator = simpleDeobfuscator;
} }
public abstract bool getRevisionRange(out int minRev, out int maxRev); public abstract bool GetRevisionRange(out int minRev, out int maxRev);
public abstract void initialize(); public abstract void Initialize();
protected void add(DecrypterInfo info) { protected void Add(DecrypterInfo info) {
methodToDecrypterInfo.add(info.decryptMethod, info); methodToDecrypterInfo.Add(info.decryptMethod, info);
} }
protected bool add(FieldDef field) { protected bool Add(FieldDef field) {
if (field == null) if (field == null)
return false; return false;
fields.add(field, true); fields.Add(field, true);
return true; return true;
} }
protected void initializeDecrypterInfos() { protected void InitializeDecrypterInfos() {
foreach (var info in methodToDecrypterInfo.getValues()) { foreach (var info in methodToDecrypterInfo.GetValues()) {
simpleDeobfuscator.deobfuscate(info.decryptMethod); simpleDeobfuscator.Deobfuscate(info.decryptMethod);
info.initialize(); info.Initialize();
} }
} }
protected void setConstantsData(byte[] constants) { protected void SetConstantsData(byte[] constants) {
reader = MemoryImageStream.Create(constants); reader = MemoryImageStream.Create(constants);
} }
protected EmbeddedResource findResource(MethodDef method) { protected EmbeddedResource FindResource(MethodDef method) {
return DotNetUtils.getResource(module, DotNetUtils.getCodeStrings(method)) as EmbeddedResource; return DotNetUtils.GetResource(module, DotNetUtils.GetCodeStrings(method)) as EmbeddedResource;
} }
protected static MethodDef findNativeMethod(MethodDef method) { protected static MethodDef FindNativeMethod(MethodDef method) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count; i++) { for (int i = 0; i < instrs.Count; i++) {
var call = instrs[i]; var call = instrs[i];
@ -295,7 +295,7 @@ namespace de4dot.code.deobfuscators.Confuser {
var calledMethod = call.Operand as MethodDef; var calledMethod = call.Operand as MethodDef;
if (calledMethod == null || !calledMethod.IsStatic || !calledMethod.IsNative) if (calledMethod == null || !calledMethod.IsStatic || !calledMethod.IsNative)
continue; continue;
if (!DotNetUtils.isMethod(calledMethod, "System.Int32", "(System.Int32)")) if (!DotNetUtils.IsMethod(calledMethod, "System.Int32", "(System.Int32)"))
continue; continue;
return calledMethod; return calledMethod;
@ -303,10 +303,10 @@ namespace de4dot.code.deobfuscators.Confuser {
return null; return null;
} }
static Local getDynamicLocal_v17_r73740(MethodDef method) { static Local GetDynamicLocal_v17_r73740(MethodDef method) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count; i++) { for (int i = 0; i < instrs.Count; i++) {
i = ConfuserUtils.findCallMethod(instrs, i, Code.Callvirt, "System.Byte System.IO.BinaryReader::ReadByte()"); i = ConfuserUtils.FindCallMethod(instrs, i, Code.Callvirt, "System.Byte System.IO.BinaryReader::ReadByte()");
if (i < 0 || i + 5 >= instrs.Count) if (i < 0 || i + 5 >= instrs.Count)
break; break;
if (!instrs[i + 1].IsStloc()) if (!instrs[i + 1].IsStloc())
@ -327,7 +327,7 @@ namespace de4dot.code.deobfuscators.Confuser {
return null; return null;
} }
static int getDynamicEndIndex_v17_r73740(MethodDef method, Local local) { static int GetDynamicEndIndex_v17_r73740(MethodDef method, Local local) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count - 5; i++) { for (int i = 0; i < instrs.Count - 5; i++) {
int index = i; int index = i;
@ -358,7 +358,7 @@ namespace de4dot.code.deobfuscators.Confuser {
return -1; return -1;
} }
static int getDynamicEndIndex_v17_r74788(MethodDef method, Local local) { static int GetDynamicEndIndex_v17_r74788(MethodDef method, Local local) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count - 11; i++) { for (int i = 0; i < instrs.Count - 11; i++) {
var stloc = instrs[i]; var stloc = instrs[i];
@ -393,7 +393,7 @@ namespace de4dot.code.deobfuscators.Confuser {
return -1; return -1;
} }
static int getDynamicStartIndex_v17_r73740(MethodDef method, int endIndex) { static int GetDynamicStartIndex_v17_r73740(MethodDef method, int endIndex) {
if (endIndex < 0) if (endIndex < 0)
return -1; return -1;
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
@ -409,42 +409,42 @@ namespace de4dot.code.deobfuscators.Confuser {
} }
static readonly byte[] defaultDecryptKey_v17 = new byte[1]; static readonly byte[] defaultDecryptKey_v17 = new byte[1];
protected byte[] decryptConstant_v17_r73740_dynamic(DecrypterInfo info, byte[] encrypted, uint offs, uint key) { protected byte[] DecryptConstant_v17_r73740_dynamic(DecrypterInfo info, byte[] encrypted, uint offs, uint key) {
return decryptConstant_v17_r73740_dynamic(info, encrypted, offs, key, defaultDecryptKey_v17); return DecryptConstant_v17_r73740_dynamic(info, encrypted, offs, key, defaultDecryptKey_v17);
} }
protected byte[] decryptConstant_v17_r73740_dynamic(DecrypterInfo info, byte[] encrypted, uint offs, uint key1, byte[] key2) { protected byte[] DecryptConstant_v17_r73740_dynamic(DecrypterInfo info, byte[] encrypted, uint offs, uint key1, byte[] key2) {
var local = getDynamicLocal_v17_r73740(info.decryptMethod); var local = GetDynamicLocal_v17_r73740(info.decryptMethod);
if (local == null) if (local == null)
throw new ApplicationException("Could not find local"); throw new ApplicationException("Could not find local");
int endIndex = getDynamicEndIndex_v17_r73740(info.decryptMethod, local); int endIndex = GetDynamicEndIndex_v17_r73740(info.decryptMethod, local);
if (endIndex < 0) if (endIndex < 0)
endIndex = getDynamicEndIndex_v17_r74788(info.decryptMethod, local); endIndex = GetDynamicEndIndex_v17_r74788(info.decryptMethod, local);
int startIndex = getDynamicStartIndex_v17_r73740(info.decryptMethod, endIndex); int startIndex = GetDynamicStartIndex_v17_r73740(info.decryptMethod, endIndex);
if (startIndex < 0) if (startIndex < 0)
throw new ApplicationException("Could not find start/end index"); throw new ApplicationException("Could not find start/end index");
var constReader = new ConstantsReader(info.decryptMethod); var constReader = new ConstantsReader(info.decryptMethod);
return decrypt(encrypted, key1, (magic, i) => { return Decrypt(encrypted, key1, (magic, i) => {
constReader.setConstantInt32(local, magic); constReader.SetConstantInt32(local, magic);
int index = startIndex, result; int index = startIndex, result;
if (!constReader.getNextInt32(ref index, out result) || index != endIndex) if (!constReader.GetNextInt32(ref index, out result) || index != endIndex)
throw new ApplicationException("Could not decrypt integer"); throw new ApplicationException("Could not decrypt integer");
return (byte)(result ^ key2[i % key2.Length]); return (byte)(result ^ key2[i % key2.Length]);
}); });
} }
protected byte[] decryptConstant_v17_r73764_native(DecrypterInfo info, byte[] encrypted, uint offs, uint key) { protected byte[] DecryptConstant_v17_r73764_native(DecrypterInfo info, byte[] encrypted, uint offs, uint key) {
return decryptConstant_v17_r73764_native(info, encrypted, offs, key, defaultDecryptKey_v17); return DecryptConstant_v17_r73764_native(info, encrypted, offs, key, defaultDecryptKey_v17);
} }
protected byte[] decryptConstant_v17_r73764_native(DecrypterInfo info, byte[] encrypted, uint offs, uint key1, byte[] key2) { protected byte[] DecryptConstant_v17_r73764_native(DecrypterInfo info, byte[] encrypted, uint offs, uint key1, byte[] key2) {
using (var x86Emu = new x86Emulator(fileData)) using (var x86Emu = new x86Emulator(fileData))
return decrypt(encrypted, key1, (magic, i) => (byte)(x86Emu.emulate((uint)nativeMethod.RVA, magic) ^ key2[i % key2.Length])); return Decrypt(encrypted, key1, (magic, i) => (byte)(x86Emu.Emulate((uint)nativeMethod.RVA, magic) ^ key2[i % key2.Length]));
} }
static byte[] decrypt(byte[] encrypted, uint key, Func<uint, int, byte> decryptFunc) { static byte[] Decrypt(byte[] encrypted, uint key, Func<uint, int, byte> decryptFunc) {
var reader = MemoryImageStream.Create(encrypted); var reader = MemoryImageStream.Create(encrypted);
var decrypted = new byte[reader.ReadInt32() ^ key]; var decrypted = new byte[reader.ReadInt32() ^ key];
for (int i = 0; i < decrypted.Length; i++) { for (int i = 0; i < decrypted.Length; i++) {
@ -455,10 +455,10 @@ namespace de4dot.code.deobfuscators.Confuser {
return decrypted; return decrypted;
} }
public object decryptInt32(MethodDef caller, MethodDef decryptMethod, object[] args) { public object DecryptInt32(MethodDef caller, MethodDef decryptMethod, object[] args) {
var info = methodToDecrypterInfo.find(decryptMethod); var info = methodToDecrypterInfo.Find(decryptMethod);
byte typeCode; byte typeCode;
var data = decryptData(info, caller, args, out typeCode); var data = DecryptData(info, caller, args, out typeCode);
if (typeCode != info.int32Type) if (typeCode != info.int32Type)
return null; return null;
if (data.Length != 4) if (data.Length != 4)
@ -466,10 +466,10 @@ namespace de4dot.code.deobfuscators.Confuser {
return BitConverter.ToInt32(data, 0); return BitConverter.ToInt32(data, 0);
} }
public object decryptInt64(MethodDef caller, MethodDef decryptMethod, object[] args) { public object DecryptInt64(MethodDef caller, MethodDef decryptMethod, object[] args) {
var info = methodToDecrypterInfo.find(decryptMethod); var info = methodToDecrypterInfo.Find(decryptMethod);
byte typeCode; byte typeCode;
var data = decryptData(info, caller, args, out typeCode); var data = DecryptData(info, caller, args, out typeCode);
if (typeCode != info.int64Type) if (typeCode != info.int64Type)
return null; return null;
if (data.Length != 8) if (data.Length != 8)
@ -477,10 +477,10 @@ namespace de4dot.code.deobfuscators.Confuser {
return BitConverter.ToInt64(data, 0); return BitConverter.ToInt64(data, 0);
} }
public object decryptSingle(MethodDef caller, MethodDef decryptMethod, object[] args) { public object DecryptSingle(MethodDef caller, MethodDef decryptMethod, object[] args) {
var info = methodToDecrypterInfo.find(decryptMethod); var info = methodToDecrypterInfo.Find(decryptMethod);
byte typeCode; byte typeCode;
var data = decryptData(info, caller, args, out typeCode); var data = DecryptData(info, caller, args, out typeCode);
if (typeCode != info.singleType) if (typeCode != info.singleType)
return null; return null;
if (data.Length != 4) if (data.Length != 4)
@ -488,10 +488,10 @@ namespace de4dot.code.deobfuscators.Confuser {
return BitConverter.ToSingle(data, 0); return BitConverter.ToSingle(data, 0);
} }
public object decryptDouble(MethodDef caller, MethodDef decryptMethod, object[] args) { public object DecryptDouble(MethodDef caller, MethodDef decryptMethod, object[] args) {
var info = methodToDecrypterInfo.find(decryptMethod); var info = methodToDecrypterInfo.Find(decryptMethod);
byte typeCode; byte typeCode;
var data = decryptData(info, caller, args, out typeCode); var data = DecryptData(info, caller, args, out typeCode);
if (typeCode != info.doubleType) if (typeCode != info.doubleType)
return null; return null;
if (data.Length != 8) if (data.Length != 8)
@ -499,15 +499,15 @@ namespace de4dot.code.deobfuscators.Confuser {
return BitConverter.ToDouble(data, 0); return BitConverter.ToDouble(data, 0);
} }
public string decryptString(MethodDef caller, MethodDef decryptMethod, object[] args) { public string DecryptString(MethodDef caller, MethodDef decryptMethod, object[] args) {
var info = methodToDecrypterInfo.find(decryptMethod); var info = methodToDecrypterInfo.Find(decryptMethod);
byte typeCode; byte typeCode;
var data = decryptData(info, caller, args, out typeCode); var data = DecryptData(info, caller, args, out typeCode);
if (typeCode != info.stringType) if (typeCode != info.stringType)
return null; return null;
return Encoding.UTF8.GetString(data); return Encoding.UTF8.GetString(data);
} }
protected abstract byte[] decryptData(DecrypterInfo info, MethodDef caller, object[] args, out byte typeCode); protected abstract byte[] DecryptData(DecrypterInfo info, MethodDef caller, object[] args, out byte typeCode);
} }
} }

View File

@ -22,7 +22,7 @@ using dnlib.DotNet.Emit;
namespace de4dot.code.deobfuscators.Confuser { namespace de4dot.code.deobfuscators.Confuser {
static class ConstantsDecrypterUtils { static class ConstantsDecrypterUtils {
public static FieldDef findDictField(MethodDef method, TypeDef declaringType) { public static FieldDef FindDictField(MethodDef method, TypeDef declaringType) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count - 1; i++) { for (int i = 0; i < instrs.Count - 1; i++) {
var newobj = instrs[i]; var newobj = instrs[i];
@ -46,7 +46,7 @@ namespace de4dot.code.deobfuscators.Confuser {
return null; return null;
} }
public static FieldDef findDataField(MethodDef method, TypeDef declaringType) { public static FieldDef FindDataField(MethodDef method, TypeDef declaringType) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count - 1; i++) { for (int i = 0; i < instrs.Count - 1; i++) {
var callvirt = instrs[i]; var callvirt = instrs[i];
@ -70,15 +70,15 @@ namespace de4dot.code.deobfuscators.Confuser {
return null; return null;
} }
public static FieldDef findStreamField(MethodDef method, TypeDef declaringType) { public static FieldDef FindStreamField(MethodDef method, TypeDef declaringType) {
return findStreamField(method, declaringType, "System.IO.Stream"); return FindStreamField(method, declaringType, "System.IO.Stream");
} }
public static FieldDef findMemoryStreamField(MethodDef method, TypeDef declaringType) { public static FieldDef FindMemoryStreamField(MethodDef method, TypeDef declaringType) {
return findStreamField(method, declaringType, "System.IO.MemoryStream"); return FindStreamField(method, declaringType, "System.IO.MemoryStream");
} }
public static FieldDef findStreamField(MethodDef method, TypeDef declaringType, string fieldTypeName) { public static FieldDef FindStreamField(MethodDef method, TypeDef declaringType, string fieldTypeName) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count - 1; i++) { for (int i = 0; i < instrs.Count - 1; i++) {
var newobj = instrs[i]; var newobj = instrs[i];

View File

@ -69,28 +69,28 @@ namespace de4dot.code.deobfuscators.Confuser {
"System.IO.Compression.DeflateStream", "System.IO.Compression.DeflateStream",
"System.Reflection.Assembly", "System.Reflection.Assembly",
}; };
public void find() { public void Find() {
var type = DotNetUtils.getModuleType(module); var type = DotNetUtils.GetModuleType(module);
if (type == null) if (type == null)
return; return;
foreach (var method in type.Methods) { foreach (var method in type.Methods) {
if (!method.IsStatic || method.Body == null) if (!method.IsStatic || method.Body == null)
continue; continue;
if (!DotNetUtils.isMethod(method, "System.Object", "(System.UInt32)")) if (!DotNetUtils.IsMethod(method, "System.Object", "(System.UInt32)"))
continue; continue;
DecrypterInfo info = new DecrypterInfo(); DecrypterInfo info = new DecrypterInfo();
var localTypes = new LocalTypes(method); var localTypes = new LocalTypes(method);
if (localTypes.all(requiredLocals1)) { if (localTypes.All(requiredLocals1)) {
if (localTypes.exists("System.Collections.BitArray")) // or System.Random if (localTypes.Exists("System.Collections.BitArray")) // or System.Random
version = ConfuserVersion.v15_r60785_normal; version = ConfuserVersion.v15_r60785_normal;
else if (DeobUtils.hasInteger(method, 0x100) && else if (DeobUtils.HasInteger(method, 0x100) &&
DeobUtils.hasInteger(method, 0x10000) && DeobUtils.HasInteger(method, 0x10000) &&
DeobUtils.hasInteger(method, 0xFFFF)) DeobUtils.HasInteger(method, 0xFFFF))
version = ConfuserVersion.v17_r73404_normal; version = ConfuserVersion.v17_r73404_normal;
else if (DotNetUtils.callsMethod(method, "System.String System.Text.Encoding::GetString(System.Byte[])")) { else if (DotNetUtils.CallsMethod(method, "System.String System.Text.Encoding::GetString(System.Byte[])")) {
if (findInstruction(method.Body.Instructions, 0, Code.Conv_I8) >= 0) { if (FindInstruction(method.Body.Instructions, 0, Code.Conv_I8) >= 0) {
if (DotNetUtils.callsMethod(method, "System.Void System.Console::WriteLine()")) if (DotNetUtils.CallsMethod(method, "System.Void System.Console::WriteLine()"))
version = ConfuserVersion.v15_r60785_dynamic; version = ConfuserVersion.v15_r60785_dynamic;
else else
version = ConfuserVersion.v17_r72989_dynamic; version = ConfuserVersion.v17_r72989_dynamic;
@ -98,8 +98,8 @@ namespace de4dot.code.deobfuscators.Confuser {
else else
version = ConfuserVersion.v17_r73740_dynamic; version = ConfuserVersion.v17_r73740_dynamic;
} }
else if (DotNetUtils.callsMethod(method, "System.String System.Text.Encoding::GetString(System.Byte[],System.Int32,System.Int32)")) { else if (DotNetUtils.CallsMethod(method, "System.String System.Text.Encoding::GetString(System.Byte[],System.Int32,System.Int32)")) {
if ((nativeMethod = findNativeMethod(method)) == null) if ((nativeMethod = FindNativeMethod(method)) == null)
version = ConfuserVersion.v17_r73764_dynamic; version = ConfuserVersion.v17_r73764_dynamic;
else else
version = ConfuserVersion.v17_r73764_native; version = ConfuserVersion.v17_r73764_native;
@ -107,18 +107,18 @@ namespace de4dot.code.deobfuscators.Confuser {
else else
continue; continue;
} }
else if (localTypes.all(requiredLocals2)) { else if (localTypes.All(requiredLocals2)) {
if (DeobUtils.hasInteger(method, 0x100) && if (DeobUtils.HasInteger(method, 0x100) &&
DeobUtils.hasInteger(method, 0x10000) && DeobUtils.HasInteger(method, 0x10000) &&
DeobUtils.hasInteger(method, 0xFFFF)) DeobUtils.HasInteger(method, 0xFFFF))
version = ConfuserVersion.v17_r73822_normal; version = ConfuserVersion.v17_r73822_normal;
else if (DotNetUtils.callsMethod(method, "System.Int32 System.Object::GetHashCode()")) { else if (DotNetUtils.CallsMethod(method, "System.Int32 System.Object::GetHashCode()")) {
if ((nativeMethod = findNativeMethod(method)) == null) if ((nativeMethod = FindNativeMethod(method)) == null)
version = ConfuserVersion.v17_r74021_dynamic; version = ConfuserVersion.v17_r74021_dynamic;
else else
version = ConfuserVersion.v17_r74021_native; version = ConfuserVersion.v17_r74021_native;
} }
else if ((nativeMethod = findNativeMethod(method)) == null) else if ((nativeMethod = FindNativeMethod(method)) == null)
version = ConfuserVersion.v17_r73822_dynamic; version = ConfuserVersion.v17_r73822_dynamic;
else else
version = ConfuserVersion.v17_r73822_native; version = ConfuserVersion.v17_r73822_native;
@ -128,32 +128,32 @@ namespace de4dot.code.deobfuscators.Confuser {
info.decryptMethod = method; info.decryptMethod = method;
theDecrypterInfo = info; theDecrypterInfo = info;
add(info); Add(info);
break; break;
} }
} }
public override void initialize() { public override void Initialize() {
if ((resource = findResource(theDecrypterInfo.decryptMethod)) == null) if ((resource = FindResource(theDecrypterInfo.decryptMethod)) == null)
throw new ApplicationException("Could not find encrypted consts resource"); throw new ApplicationException("Could not find encrypted consts resource");
initializeDecrypterInfos(); InitializeDecrypterInfos();
if (!initializeFields(theDecrypterInfo)) if (!InitializeFields(theDecrypterInfo))
throw new ApplicationException("Could not find all fields"); throw new ApplicationException("Could not find all fields");
setConstantsData(DeobUtils.inflate(resource.GetResourceData(), true)); SetConstantsData(DeobUtils.Inflate(resource.GetResourceData(), true));
} }
bool initializeFields(DecrypterInfo info) { bool InitializeFields(DecrypterInfo info) {
switch (version) { switch (version) {
case ConfuserVersion.v17_r73822_normal: case ConfuserVersion.v17_r73822_normal:
case ConfuserVersion.v17_r73822_dynamic: case ConfuserVersion.v17_r73822_dynamic:
case ConfuserVersion.v17_r73822_native: case ConfuserVersion.v17_r73822_native:
case ConfuserVersion.v17_r74021_dynamic: case ConfuserVersion.v17_r74021_dynamic:
case ConfuserVersion.v17_r74021_native: case ConfuserVersion.v17_r74021_native:
if (!add(ConstantsDecrypterUtils.findDictField(info.decryptMethod, info.decryptMethod.DeclaringType))) if (!Add(ConstantsDecrypterUtils.FindDictField(info.decryptMethod, info.decryptMethod.DeclaringType)))
return false; return false;
if (!add(ConstantsDecrypterUtils.findMemoryStreamField(info.decryptMethod, info.decryptMethod.DeclaringType))) if (!Add(ConstantsDecrypterUtils.FindMemoryStreamField(info.decryptMethod, info.decryptMethod.DeclaringType)))
return false; return false;
break; break;
@ -164,8 +164,8 @@ namespace de4dot.code.deobfuscators.Confuser {
return true; return true;
} }
protected override byte[] decryptData(DecrypterInfo info, MethodDef caller, object[] args, out byte typeCode) { protected override byte[] DecryptData(DecrypterInfo info, MethodDef caller, object[] args, out byte typeCode) {
uint offs = info.calcHash(caller.MDToken.ToUInt32()) ^ (uint)args[0]; uint offs = info.CalcHash(caller.MDToken.ToUInt32()) ^ (uint)args[0];
reader.Position = offs; reader.Position = offs;
typeCode = reader.ReadByte(); typeCode = reader.ReadByte();
if (typeCode != info.int32Type && typeCode != info.int64Type && if (typeCode != info.int32Type && typeCode != info.int64Type &&
@ -174,28 +174,28 @@ namespace de4dot.code.deobfuscators.Confuser {
throw new ApplicationException("Invalid type code"); throw new ApplicationException("Invalid type code");
var encrypted = reader.ReadBytes(reader.ReadInt32()); var encrypted = reader.ReadBytes(reader.ReadInt32());
return decryptConstant(info, encrypted, offs); return DecryptConstant(info, encrypted, offs);
} }
byte[] decryptConstant(DecrypterInfo info, byte[] encrypted, uint offs) { byte[] DecryptConstant(DecrypterInfo info, byte[] encrypted, uint offs) {
switch (version) { switch (version) {
case ConfuserVersion.v15_r60785_normal: return decryptConstant_v15_r60785_normal(info, encrypted, offs); 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.v15_r60785_dynamic: return DecryptConstant_v15_r60785_dynamic(info, encrypted, offs);
case ConfuserVersion.v17_r72989_dynamic: return decryptConstant_v15_r60785_dynamic(info, encrypted, offs); case ConfuserVersion.v17_r72989_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_r73404_normal: return DecryptConstant_v17_r73404_normal(info, encrypted, offs);
case ConfuserVersion.v17_r73740_dynamic: return decryptConstant_v17_r73740_dynamic(info, encrypted, offs, 0); 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_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_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_normal: return DecryptConstant_v17_r73404_normal(info, encrypted, offs);
case ConfuserVersion.v17_r73822_dynamic: return decryptConstant_v17_r73740_dynamic(info, encrypted, offs, 0); 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); case ConfuserVersion.v17_r73822_native: return DecryptConstant_v17_r73764_native(info, encrypted, offs, 0);
case ConfuserVersion.v17_r74021_dynamic: return decryptConstant_v17_r73740_dynamic(info, encrypted, offs, 0); case ConfuserVersion.v17_r74021_dynamic: return DecryptConstant_v17_r73740_dynamic(info, encrypted, offs, 0);
case ConfuserVersion.v17_r74021_native: return decryptConstant_v17_r73764_native(info, encrypted, offs, 0); case ConfuserVersion.v17_r74021_native: return DecryptConstant_v17_r73764_native(info, encrypted, offs, 0);
default: throw new ApplicationException("Invalid version"); default: throw new ApplicationException("Invalid version");
} }
} }
byte[] decryptConstant_v15_r60785_normal(DecrypterInfo info, byte[] encrypted, uint offs) { byte[] DecryptConstant_v15_r60785_normal(DecrypterInfo info, byte[] encrypted, uint offs) {
var rand = new Random((int)(info.key0 ^ offs)); var rand = new Random((int)(info.key0 ^ offs));
var decrypted = new byte[encrypted.Length]; var decrypted = new byte[encrypted.Length];
rand.NextBytes(decrypted); rand.NextBytes(decrypted);
@ -204,30 +204,30 @@ namespace de4dot.code.deobfuscators.Confuser {
return decrypted; return decrypted;
} }
byte[] decryptConstant_v15_r60785_dynamic(DecrypterInfo info, byte[] encrypted, uint offs) { byte[] DecryptConstant_v15_r60785_dynamic(DecrypterInfo info, byte[] encrypted, uint offs) {
var instrs = info.decryptMethod.Body.Instructions; var instrs = info.decryptMethod.Body.Instructions;
int startIndex = getDynamicStartIndex_v15_r60785(instrs); int startIndex = GetDynamicStartIndex_v15_r60785(instrs);
int endIndex = getDynamicEndIndex_v15_r60785(instrs, startIndex); int endIndex = GetDynamicEndIndex_v15_r60785(instrs, startIndex);
if (endIndex < 0) if (endIndex < 0)
throw new ApplicationException("Could not find start/endIndex"); throw new ApplicationException("Could not find start/endIndex");
var dataReader = MemoryImageStream.Create(encrypted); var dataReader = MemoryImageStream.Create(encrypted);
var decrypted = new byte[dataReader.ReadInt32()]; var decrypted = new byte[dataReader.ReadInt32()];
var constReader = new Arg64ConstantsReader(instrs, false); var constReader = new Arg64ConstantsReader(instrs, false);
ConfuserUtils.decryptCompressedInt32Data(constReader, startIndex, endIndex, dataReader, decrypted); ConfuserUtils.DecryptCompressedInt32Data(constReader, startIndex, endIndex, dataReader, decrypted);
return decrypted; return decrypted;
} }
static int getDynamicStartIndex_v15_r60785(IList<Instruction> instrs) { static int GetDynamicStartIndex_v15_r60785(IList<Instruction> instrs) {
int index = findInstruction(instrs, 0, Code.Conv_I8); int index = FindInstruction(instrs, 0, Code.Conv_I8);
if (index < 0) if (index < 0)
return -1; return -1;
if (findInstruction(instrs, index + 1, Code.Conv_I8) >= 0) if (FindInstruction(instrs, index + 1, Code.Conv_I8) >= 0)
return -1; return -1;
return index; return index;
} }
static int getDynamicEndIndex_v15_r60785(IList<Instruction> instrs, int index) { static int GetDynamicEndIndex_v15_r60785(IList<Instruction> instrs, int index) {
if (index < 0) if (index < 0)
return -1; return -1;
for (int i = index; i < instrs.Count; i++) { for (int i = index; i < instrs.Count; i++) {
@ -240,7 +240,7 @@ namespace de4dot.code.deobfuscators.Confuser {
return -1; return -1;
} }
static int findInstruction(IList<Instruction> instrs, int index, Code code) { static int FindInstruction(IList<Instruction> instrs, int index, Code code) {
for (int i = index; i < instrs.Count; i++) { for (int i = index; i < instrs.Count; i++) {
if (instrs[i].OpCode.Code == code) if (instrs[i].OpCode.Code == code)
return i; return i;
@ -248,11 +248,11 @@ namespace de4dot.code.deobfuscators.Confuser {
return -1; return -1;
} }
byte[] decryptConstant_v17_r73404_normal(DecrypterInfo info, byte[] encrypted, uint offs) { byte[] DecryptConstant_v17_r73404_normal(DecrypterInfo info, byte[] encrypted, uint offs) {
return ConfuserUtils.decrypt(info.key0 ^ offs, encrypted); return ConfuserUtils.Decrypt(info.key0 ^ offs, encrypted);
} }
public override bool getRevisionRange(out int minRev, out int maxRev) { public override bool GetRevisionRange(out int minRev, out int maxRev) {
switch (version) { switch (version) {
case ConfuserVersion.Unknown: case ConfuserVersion.Unknown:
minRev = maxRev = 0; minRev = maxRev = 0;

View File

@ -62,22 +62,22 @@ namespace de4dot.code.deobfuscators.Confuser {
this.decryptMethod = decryptMethod; this.decryptMethod = decryptMethod;
} }
protected override bool initializeKeys() { protected override bool InitializeKeys() {
if (!findKey0(decryptMethod, out key0)) if (!FindKey0(decryptMethod, out key0))
return false; return false;
if (!findKey1_v17(decryptMethod, out key1)) if (!FindKey1_v17(decryptMethod, out key1))
return false; return false;
if (!findKey2Key3(decryptMethod, out key2, out key3)) if (!FindKey2Key3(decryptMethod, out key2, out key3))
return false; return false;
if (!findKey4(decryptMethod, out key4)) if (!FindKey4(decryptMethod, out key4))
return false; return false;
if (!findKey5(decryptMethod, out key5)) if (!FindKey5(decryptMethod, out key5))
return false; return false;
return true; return true;
} }
static bool findKey1_v17(MethodDef method, out uint key) { static bool FindKey1_v17(MethodDef method, out uint key) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count - 4; i++) { for (int i = 0; i < instrs.Count - 4; i++) {
var stloc = instrs[i]; var stloc = instrs[i];
@ -103,14 +103,14 @@ namespace de4dot.code.deobfuscators.Confuser {
return false; return false;
} }
bool findKey4(MethodDef method, out uint key) { bool FindKey4(MethodDef method, out uint key) {
switch (version) { switch (version) {
case ConfuserVersion.v17_r74708_normal: case ConfuserVersion.v17_r74708_normal:
case ConfuserVersion.v17_r74788_normal: case ConfuserVersion.v17_r74788_normal:
case ConfuserVersion.v17_r74816_normal: case ConfuserVersion.v17_r74816_normal:
case ConfuserVersion.v17_r75056_normal: case ConfuserVersion.v17_r75056_normal:
case ConfuserVersion.v18_r75257_normal: case ConfuserVersion.v18_r75257_normal:
return findKey4_normal(method, out key); return FindKey4_normal(method, out key);
case ConfuserVersion.v17_r74708_dynamic: case ConfuserVersion.v17_r74708_dynamic:
case ConfuserVersion.v17_r74708_native: case ConfuserVersion.v17_r74708_native:
case ConfuserVersion.v17_r74788_dynamic: case ConfuserVersion.v17_r74788_dynamic:
@ -121,13 +121,13 @@ namespace de4dot.code.deobfuscators.Confuser {
case ConfuserVersion.v17_r75056_native: case ConfuserVersion.v17_r75056_native:
case ConfuserVersion.v18_r75257_dynamic: case ConfuserVersion.v18_r75257_dynamic:
case ConfuserVersion.v18_r75257_native: case ConfuserVersion.v18_r75257_native:
return findKey4_other(method, out key); return FindKey4_other(method, out key);
default: default:
throw new ApplicationException("Invalid version"); throw new ApplicationException("Invalid version");
} }
} }
static bool findKey4_normal(MethodDef method, out uint key) { static bool FindKey4_normal(MethodDef method, out uint key) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count - 5; i++) { for (int i = 0; i < instrs.Count - 5; i++) {
if (!instrs[i].IsLdloc()) if (!instrs[i].IsLdloc())
@ -151,10 +151,10 @@ namespace de4dot.code.deobfuscators.Confuser {
return false; return false;
} }
static bool findKey4_other(MethodDef method, out uint key) { static bool FindKey4_other(MethodDef method, out uint key) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count; i++) { for (int i = 0; i < instrs.Count; i++) {
int index = ConfuserUtils.findCallMethod(instrs, i, Code.Callvirt, "System.Int32 System.IO.BinaryReader::ReadInt32()"); int index = ConfuserUtils.FindCallMethod(instrs, i, Code.Callvirt, "System.Int32 System.IO.BinaryReader::ReadInt32()");
if (index < 0) if (index < 0)
break; break;
if (index + 1 >= instrs.Count) if (index + 1 >= instrs.Count)
@ -170,7 +170,7 @@ namespace de4dot.code.deobfuscators.Confuser {
return false; return false;
} }
bool findKey5(MethodDef method, out uint key) { bool FindKey5(MethodDef method, out uint key) {
switch (version) { switch (version) {
case ConfuserVersion.v17_r74788_normal: case ConfuserVersion.v17_r74788_normal:
case ConfuserVersion.v17_r74788_dynamic: case ConfuserVersion.v17_r74788_dynamic:
@ -184,17 +184,17 @@ namespace de4dot.code.deobfuscators.Confuser {
case ConfuserVersion.v18_r75257_normal: case ConfuserVersion.v18_r75257_normal:
case ConfuserVersion.v18_r75257_dynamic: case ConfuserVersion.v18_r75257_dynamic:
case ConfuserVersion.v18_r75257_native: case ConfuserVersion.v18_r75257_native:
return findKey5_v17_r74788(method, out key); return FindKey5_v17_r74788(method, out key);
default: default:
key = 0; key = 0;
return true; return true;
} }
} }
static bool findKey5_v17_r74788(MethodDef method, out uint key) { static bool FindKey5_v17_r74788(MethodDef method, out uint key) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count; i++) { for (int i = 0; i < instrs.Count; i++) {
i = ConfuserUtils.findCallMethod(instrs, i, Code.Callvirt, "System.Reflection.Module System.Reflection.Assembly::GetModule(System.String)"); i = ConfuserUtils.FindCallMethod(instrs, i, Code.Callvirt, "System.Reflection.Module System.Reflection.Assembly::GetModule(System.String)");
if (i < 0) if (i < 0)
break; break;
if (i + 1 >= instrs.Count) if (i + 1 >= instrs.Count)
@ -225,64 +225,64 @@ namespace de4dot.code.deobfuscators.Confuser {
"System.Byte[]", "System.Byte[]",
"System.Int32", "System.Int32",
}; };
public void find() { public void Find() {
var cctor = DotNetUtils.getModuleTypeCctor(module); var cctor = DotNetUtils.GetModuleTypeCctor(module);
if (cctor == null) if (cctor == null)
return; return;
if (!new LocalTypes(cctor).all(requiredLocalsCctor)) if (!new LocalTypes(cctor).All(requiredLocalsCctor))
return; return;
simpleDeobfuscator.deobfuscate(cctor, true); simpleDeobfuscator.Deobfuscate(cctor, true);
if (!add(ConstantsDecrypterUtils.findDictField(cctor, cctor.DeclaringType))) if (!Add(ConstantsDecrypterUtils.FindDictField(cctor, cctor.DeclaringType)))
return; return;
if (!add(ConstantsDecrypterUtils.findStreamField(cctor, cctor.DeclaringType))) if (!Add(ConstantsDecrypterUtils.FindStreamField(cctor, cctor.DeclaringType)))
return; return;
var method = getDecryptMethod(); var method = GetDecryptMethod();
if (method == null) if (method == null)
return; return;
resourceName = getResourceName(cctor); resourceName = GetResourceName(cctor);
if (resourceName != null) { if (resourceName != null) {
simpleDeobfuscator.deobfuscate(method); simpleDeobfuscator.Deobfuscate(method);
keyArraySize = getKeyArraySize(method); keyArraySize = GetKeyArraySize(method);
if (keyArraySize == 8) if (keyArraySize == 8)
initVersion(method, ConfuserVersion.v17_r75056_normal, ConfuserVersion.v17_r75056_dynamic, ConfuserVersion.v17_r75056_native); InitVersion(method, ConfuserVersion.v17_r75056_normal, ConfuserVersion.v17_r75056_dynamic, ConfuserVersion.v17_r75056_native);
else if (keyArraySize == 16) else if (keyArraySize == 16)
initVersion(method, ConfuserVersion.v18_r75257_normal, ConfuserVersion.v18_r75257_dynamic, ConfuserVersion.v18_r75257_native); InitVersion(method, ConfuserVersion.v18_r75257_normal, ConfuserVersion.v18_r75257_dynamic, ConfuserVersion.v18_r75257_native);
else else
return; return;
} }
else if (DotNetUtils.callsMethod(method, "System.String System.Reflection.Module::get_ScopeName()")) else if (DotNetUtils.CallsMethod(method, "System.String System.Reflection.Module::get_ScopeName()"))
initVersion(method, ConfuserVersion.v17_r74816_normal, ConfuserVersion.v17_r74816_dynamic, ConfuserVersion.v17_r74816_native); InitVersion(method, ConfuserVersion.v17_r74816_normal, ConfuserVersion.v17_r74816_dynamic, ConfuserVersion.v17_r74816_native);
else if (DotNetUtils.callsMethod(method, "System.Reflection.Module System.Reflection.Assembly::GetModule(System.String)")) else if (DotNetUtils.CallsMethod(method, "System.Reflection.Module System.Reflection.Assembly::GetModule(System.String)"))
initVersion(method, ConfuserVersion.v17_r74788_normal, ConfuserVersion.v17_r74788_dynamic, ConfuserVersion.v17_r74788_native); InitVersion(method, ConfuserVersion.v17_r74788_normal, ConfuserVersion.v17_r74788_dynamic, ConfuserVersion.v17_r74788_native);
else else
initVersion(method, ConfuserVersion.v17_r74708_normal, ConfuserVersion.v17_r74708_dynamic, ConfuserVersion.v17_r74708_native); InitVersion(method, ConfuserVersion.v17_r74708_normal, ConfuserVersion.v17_r74708_dynamic, ConfuserVersion.v17_r74708_native);
initMethod = cctor; initMethod = cctor;
} }
void initVersion(MethodDef method, ConfuserVersion normal, ConfuserVersion dynamic, ConfuserVersion native) { void InitVersion(MethodDef method, ConfuserVersion normal, ConfuserVersion dynamic, ConfuserVersion native) {
if (DeobUtils.hasInteger(method, 0x100) && if (DeobUtils.HasInteger(method, 0x100) &&
DeobUtils.hasInteger(method, 0x10000) && DeobUtils.HasInteger(method, 0x10000) &&
DeobUtils.hasInteger(method, 0xFFFF)) DeobUtils.HasInteger(method, 0xFFFF))
version = normal; version = normal;
else if ((nativeMethod = findNativeMethod(method)) == null) else if ((nativeMethod = FindNativeMethod(method)) == null)
version = dynamic; version = dynamic;
else else
version = native; version = native;
} }
MethodDef getDecryptMethod() { MethodDef GetDecryptMethod() {
foreach (var type in module.Types) { foreach (var type in module.Types) {
if (type.Attributes != (TypeAttributes.Abstract | TypeAttributes.Sealed)) if (type.Attributes != (TypeAttributes.Abstract | TypeAttributes.Sealed))
continue; continue;
if (!checkMethods(type.Methods)) if (!CheckMethods(type.Methods))
continue; continue;
foreach (var method in type.Methods) { foreach (var method in type.Methods) {
if (!DotNetUtils.isMethod(method, "System.Object", "(System.UInt32,System.UInt32)")) if (!DotNetUtils.IsMethod(method, "System.Object", "(System.UInt32,System.UInt32)"))
continue; continue;
return method; return method;
@ -291,9 +291,9 @@ namespace de4dot.code.deobfuscators.Confuser {
return null; return null;
} }
protected override byte[] decryptData(DecrypterInfo info2, MethodDef caller, object[] args, out byte typeCode) { protected override byte[] DecryptData(DecrypterInfo info2, MethodDef caller, object[] args, out byte typeCode) {
var info = (DecrypterInfoV17)info2; var info = (DecrypterInfoV17)info2;
uint offs = info.calcHash(info2.decryptMethod.MDToken.ToUInt32() ^ (info2.decryptMethod.DeclaringType.MDToken.ToUInt32() * (uint)args[0])) ^ (uint)args[1]; uint offs = info.CalcHash(info2.decryptMethod.MDToken.ToUInt32() ^ (info2.decryptMethod.DeclaringType.MDToken.ToUInt32() * (uint)args[0])) ^ (uint)args[1];
reader.Position = offs; reader.Position = offs;
typeCode = reader.ReadByte(); typeCode = reader.ReadByte();
if (typeCode != info.int32Type && typeCode != info.int64Type && if (typeCode != info.int32Type && typeCode != info.int64Type &&
@ -302,100 +302,100 @@ namespace de4dot.code.deobfuscators.Confuser {
throw new ApplicationException("Invalid type code"); throw new ApplicationException("Invalid type code");
var encrypted = reader.ReadBytes(reader.ReadInt32()); var encrypted = reader.ReadBytes(reader.ReadInt32());
return decryptConstant(info, encrypted, offs, typeCode); return DecryptConstant(info, encrypted, offs, typeCode);
} }
byte[] decryptConstant(DecrypterInfoV17 info, byte[] encrypted, uint offs, byte typeCode) { byte[] DecryptConstant(DecrypterInfoV17 info, byte[] encrypted, uint offs, byte typeCode) {
switch (info.version) { switch (info.version) {
case ConfuserVersion.v17_r74708_normal: return decryptConstant_v17_r74708_normal(info, encrypted, offs, typeCode); 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_dynamic: return DecryptConstant_v17_r74708_dynamic(info, encrypted, offs, typeCode);
case ConfuserVersion.v17_r74708_native: return decryptConstant_v17_r74708_native(info, encrypted, offs, typeCode); case ConfuserVersion.v17_r74708_native: return DecryptConstant_v17_r74708_native(info, encrypted, offs, typeCode);
case ConfuserVersion.v17_r74788_normal: return decryptConstant_v17_r74788_normal(info, encrypted, offs, typeCode); case ConfuserVersion.v17_r74788_normal: return DecryptConstant_v17_r74788_normal(info, encrypted, offs, typeCode);
case ConfuserVersion.v17_r74788_dynamic: return decryptConstant_v17_r74788_dynamic(info, encrypted, offs, typeCode); case ConfuserVersion.v17_r74788_dynamic: return DecryptConstant_v17_r74788_dynamic(info, encrypted, offs, typeCode);
case ConfuserVersion.v17_r74788_native: return decryptConstant_v17_r74788_native(info, encrypted, offs, typeCode); case ConfuserVersion.v17_r74788_native: return DecryptConstant_v17_r74788_native(info, encrypted, offs, typeCode);
case ConfuserVersion.v17_r74816_normal: return decryptConstant_v17_r74788_normal(info, encrypted, offs, typeCode); case ConfuserVersion.v17_r74816_normal: return DecryptConstant_v17_r74788_normal(info, encrypted, offs, typeCode);
case ConfuserVersion.v17_r74816_dynamic: return decryptConstant_v17_r74788_dynamic(info, encrypted, offs, typeCode); case ConfuserVersion.v17_r74816_dynamic: return DecryptConstant_v17_r74788_dynamic(info, encrypted, offs, typeCode);
case ConfuserVersion.v17_r74816_native: return decryptConstant_v17_r74788_native(info, encrypted, offs, typeCode); case ConfuserVersion.v17_r74816_native: return DecryptConstant_v17_r74788_native(info, encrypted, offs, typeCode);
case ConfuserVersion.v17_r75056_normal: return decryptConstant_v17_r74788_normal(info, encrypted, offs, typeCode); case ConfuserVersion.v17_r75056_normal: return DecryptConstant_v17_r74788_normal(info, encrypted, offs, typeCode);
case ConfuserVersion.v17_r75056_dynamic: return decryptConstant_v17_r74788_dynamic(info, encrypted, offs, typeCode); case ConfuserVersion.v17_r75056_dynamic: return DecryptConstant_v17_r74788_dynamic(info, encrypted, offs, typeCode);
case ConfuserVersion.v17_r75056_native: return decryptConstant_v17_r74788_native(info, encrypted, offs, typeCode); case ConfuserVersion.v17_r75056_native: return DecryptConstant_v17_r74788_native(info, encrypted, offs, typeCode);
case ConfuserVersion.v18_r75257_normal: return decryptConstant_v17_r74788_normal(info, encrypted, offs, typeCode); case ConfuserVersion.v18_r75257_normal: return DecryptConstant_v17_r74788_normal(info, encrypted, offs, typeCode);
case ConfuserVersion.v18_r75257_dynamic: return decryptConstant_v17_r74788_dynamic(info, encrypted, offs, typeCode); case ConfuserVersion.v18_r75257_dynamic: return DecryptConstant_v17_r74788_dynamic(info, encrypted, offs, typeCode);
case ConfuserVersion.v18_r75257_native: return decryptConstant_v17_r74788_native(info, encrypted, offs, typeCode); case ConfuserVersion.v18_r75257_native: return DecryptConstant_v17_r74788_native(info, encrypted, offs, typeCode);
default: default:
throw new ApplicationException("Invalid version"); throw new ApplicationException("Invalid version");
} }
} }
byte[] decryptConstant_v17_r74708_normal(DecrypterInfoV17 info, byte[] encrypted, uint offs, byte typeCode) { byte[] DecryptConstant_v17_r74708_normal(DecrypterInfoV17 info, byte[] encrypted, uint offs, byte typeCode) {
return ConfuserUtils.decrypt(info.key4 * (offs + typeCode), encrypted); return ConfuserUtils.Decrypt(info.key4 * (offs + typeCode), encrypted);
} }
byte[] decryptConstant_v17_r74708_dynamic(DecrypterInfoV17 info, byte[] encrypted, uint offs, byte typeCode) { byte[] DecryptConstant_v17_r74708_dynamic(DecrypterInfoV17 info, byte[] encrypted, uint offs, byte typeCode) {
return decryptConstant_v17_r73740_dynamic(info, encrypted, offs, info.key4); return DecryptConstant_v17_r73740_dynamic(info, encrypted, offs, info.key4);
} }
byte[] decryptConstant_v17_r74708_native(DecrypterInfoV17 info, byte[] encrypted, uint offs, byte typeCode) { byte[] DecryptConstant_v17_r74708_native(DecrypterInfoV17 info, byte[] encrypted, uint offs, byte typeCode) {
return decryptConstant_v17_r73764_native(info, encrypted, offs, info.key4); return DecryptConstant_v17_r73764_native(info, encrypted, offs, info.key4);
} }
byte[] decryptConstant_v17_r74788_normal(DecrypterInfoV17 info, byte[] encrypted, uint offs, byte typeCode) { byte[] DecryptConstant_v17_r74788_normal(DecrypterInfoV17 info, byte[] encrypted, uint offs, byte typeCode) {
return ConfuserUtils.decrypt(info.key4 * (offs + typeCode), encrypted, getKey_v17_r74788(info)); return ConfuserUtils.Decrypt(info.key4 * (offs + typeCode), encrypted, GetKey_v17_r74788(info));
} }
byte[] decryptConstant_v17_r74788_dynamic(DecrypterInfoV17 info, byte[] encrypted, uint offs, byte typeCode) { byte[] DecryptConstant_v17_r74788_dynamic(DecrypterInfoV17 info, byte[] encrypted, uint offs, byte typeCode) {
return decryptConstant_v17_r73740_dynamic(info, encrypted, offs, info.key4, getKey_v17_r74788(info)); return DecryptConstant_v17_r73740_dynamic(info, encrypted, offs, info.key4, GetKey_v17_r74788(info));
} }
byte[] decryptConstant_v17_r74788_native(DecrypterInfoV17 info, byte[] encrypted, uint offs, byte typeCode) { byte[] DecryptConstant_v17_r74788_native(DecrypterInfoV17 info, byte[] encrypted, uint offs, byte typeCode) {
return decryptConstant_v17_r73764_native(info, encrypted, offs, info.key4, getKey_v17_r74788(info)); return DecryptConstant_v17_r73764_native(info, encrypted, offs, info.key4, GetKey_v17_r74788(info));
} }
byte[] getKey_v17_r74788(DecrypterInfoV17 info) { byte[] GetKey_v17_r74788(DecrypterInfoV17 info) {
var key = module.ReadBlob(info.decryptMethod.MDToken.ToUInt32() ^ info.key5); var key = module.ReadBlob(info.decryptMethod.MDToken.ToUInt32() ^ info.key5);
if (key.Length != keyArraySize) if (key.Length != keyArraySize)
throw new ApplicationException("Invalid key size"); throw new ApplicationException("Invalid key size");
return key; return key;
} }
public override void initialize() { public override void Initialize() {
if (resourceName != null) if (resourceName != null)
resource = DotNetUtils.getResource(module, resourceName) as EmbeddedResource; resource = DotNetUtils.GetResource(module, resourceName) as EmbeddedResource;
else else
resource = findResource(initMethod); resource = FindResource(initMethod);
if (resource == null) if (resource == null)
throw new ApplicationException("Could not find encrypted consts resource"); throw new ApplicationException("Could not find encrypted consts resource");
findDecrypterInfos(); FindDecrypterInfos();
initializeDecrypterInfos(); InitializeDecrypterInfos();
setConstantsData(DeobUtils.inflate(resource.GetResourceData(), true)); SetConstantsData(DeobUtils.Inflate(resource.GetResourceData(), true));
} }
void findDecrypterInfos() { void FindDecrypterInfos() {
foreach (var type in module.Types) { foreach (var type in module.Types) {
if (type.Attributes != (TypeAttributes.Abstract | TypeAttributes.Sealed)) if (type.Attributes != (TypeAttributes.Abstract | TypeAttributes.Sealed))
continue; continue;
if (!checkMethods(type.Methods)) if (!CheckMethods(type.Methods))
continue; continue;
foreach (var method in type.Methods) { foreach (var method in type.Methods) {
if (!DotNetUtils.isMethod(method, "System.Object", "(System.UInt32,System.UInt32)")) if (!DotNetUtils.IsMethod(method, "System.Object", "(System.UInt32,System.UInt32)"))
continue; continue;
var info = new DecrypterInfoV17(version, method); var info = new DecrypterInfoV17(version, method);
add(info); Add(info);
} }
} }
} }
static bool checkMethods(IEnumerable<MethodDef> methods) { static bool CheckMethods(IEnumerable<MethodDef> methods) {
int numMethods = 0; int numMethods = 0;
foreach (var method in methods) { foreach (var method in methods) {
if (method.Name == ".ctor" || method.Name == ".cctor") if (method.Name == ".ctor" || method.Name == ".cctor")
return false; return false;
if (method.Attributes != (MethodAttributes.Static | MethodAttributes.HideBySig | MethodAttributes.CompilerControlled)) if (method.Attributes != (MethodAttributes.Static | MethodAttributes.HideBySig | MethodAttributes.CompilerControlled))
return false; return false;
if (!DotNetUtils.isMethod(method, "System.Object", "(System.UInt32,System.UInt32)")) if (!DotNetUtils.IsMethod(method, "System.Object", "(System.UInt32,System.UInt32)"))
return false; return false;
numMethods++; numMethods++;
@ -403,10 +403,10 @@ namespace de4dot.code.deobfuscators.Confuser {
return numMethods > 0; return numMethods > 0;
} }
static string getResourceName(MethodDef method) { static string GetResourceName(MethodDef method) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count; i++) { for (int i = 0; i < instrs.Count; i++) {
i = ConfuserUtils.findCallMethod(instrs, i, Code.Call, "System.Byte[] System.BitConverter::GetBytes(System.Int32)"); i = ConfuserUtils.FindCallMethod(instrs, i, Code.Call, "System.Byte[] System.BitConverter::GetBytes(System.Int32)");
if (i < 0) if (i < 0)
break; break;
if (i == 0) if (i == 0)
@ -419,7 +419,7 @@ namespace de4dot.code.deobfuscators.Confuser {
return null; return null;
} }
static int getKeyArraySize(MethodDef method) { static int GetKeyArraySize(MethodDef method) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count - 4; i++) { for (int i = 0; i < instrs.Count - 4; i++) {
if (!instrs[i].IsLdloc()) if (!instrs[i].IsLdloc())
@ -439,7 +439,7 @@ namespace de4dot.code.deobfuscators.Confuser {
return -1; return -1;
} }
public override bool getRevisionRange(out int minRev, out int maxRev) { public override bool GetRevisionRange(out int minRev, out int maxRev) {
switch (version) { switch (version) {
case ConfuserVersion.Unknown: case ConfuserVersion.Unknown:
minRev = maxRev = 0; minRev = maxRev = 0;

View File

@ -65,28 +65,28 @@ namespace de4dot.code.deobfuscators.Confuser {
this.version = version; this.version = version;
} }
public string decryptString(uint magic1, ulong magic2) { public string DecryptString(uint magic1, ulong magic2) {
return Encoding.UTF8.GetString(decrypt(magic1, magic2)); return Encoding.UTF8.GetString(Decrypt(magic1, magic2));
} }
public int decryptInt32(uint magic1, ulong magic2) { public int DecryptInt32(uint magic1, ulong magic2) {
return BitConverter.ToInt32(decrypt(magic1, magic2), 0); return BitConverter.ToInt32(Decrypt(magic1, magic2), 0);
} }
public long decryptInt64(uint magic1, ulong magic2) { public long DecryptInt64(uint magic1, ulong magic2) {
return BitConverter.ToInt64(decrypt(magic1, magic2), 0); return BitConverter.ToInt64(Decrypt(magic1, magic2), 0);
} }
public float decryptSingle(uint magic1, ulong magic2) { public float DecryptSingle(uint magic1, ulong magic2) {
return BitConverter.ToSingle(decrypt(magic1, magic2), 0); return BitConverter.ToSingle(Decrypt(magic1, magic2), 0);
} }
public double decryptDouble(uint magic1, ulong magic2) { public double DecryptDouble(uint magic1, ulong magic2) {
return BitConverter.ToDouble(decrypt(magic1, magic2), 0); return BitConverter.ToDouble(Decrypt(magic1, magic2), 0);
} }
byte[] decrypt(uint magic1, ulong magic2) { byte[] Decrypt(uint magic1, ulong magic2) {
ulong info = hash(method.DeclaringType.MDToken.ToUInt32() * magic1) ^ magic2; ulong info = Hash(method.DeclaringType.MDToken.ToUInt32() * magic1) ^ magic2;
int offset = (int)(info >> 32); int offset = (int)(info >> 32);
int len = (int)info; int len = (int)info;
var decrypted = new byte[len]; var decrypted = new byte[len];
@ -96,22 +96,22 @@ namespace de4dot.code.deobfuscators.Confuser {
return decrypted; return decrypted;
} }
ulong hash(uint magic) { ulong Hash(uint magic) {
switch (version) { switch (version) {
case ConfuserVersion.v18_r75367_normal: case ConfuserVersion.v18_r75367_normal:
case ConfuserVersion.v18_r75367_dynamic: case ConfuserVersion.v18_r75367_dynamic:
case ConfuserVersion.v18_r75367_native: case ConfuserVersion.v18_r75367_native:
return hash1(key0l ^ magic); return Hash1(key0l ^ magic);
case ConfuserVersion.v18_r75369_normal: case ConfuserVersion.v18_r75369_normal:
case ConfuserVersion.v18_r75369_dynamic: case ConfuserVersion.v18_r75369_dynamic:
case ConfuserVersion.v18_r75369_native: case ConfuserVersion.v18_r75369_native:
return hash1(key0l * magic); return Hash1(key0l * magic);
default: default:
throw new ApplicationException("Invalid version"); throw new ApplicationException("Invalid version");
} }
} }
ulong hash1(ulong h0) { ulong Hash1(ulong h0) {
ulong h1 = key1l; ulong h1 = key1l;
ulong h2 = key2l; ulong h2 = key2l;
h1 *= h0; h1 *= h0;
@ -132,7 +132,7 @@ namespace de4dot.code.deobfuscators.Confuser {
public IEnumerable<TypeDef> Types { public IEnumerable<TypeDef> Types {
get { get {
var types = new List<TypeDef>(); var types = new List<TypeDef>();
foreach (var info in decrypters.getValues()) foreach (var info in decrypters.GetValues())
types.Add(info.method.DeclaringType); types.Add(info.method.DeclaringType);
return types; return types;
} }
@ -156,7 +156,7 @@ namespace de4dot.code.deobfuscators.Confuser {
} }
public IEnumerable<DecrypterInfo> Decrypters { public IEnumerable<DecrypterInfo> Decrypters {
get { return decrypters.getValues(); } get { return decrypters.GetValues(); }
} }
public bool Detected { public bool Detected {
@ -169,78 +169,78 @@ namespace de4dot.code.deobfuscators.Confuser {
this.simpleDeobfuscator = simpleDeobfuscator; this.simpleDeobfuscator = simpleDeobfuscator;
} }
public void find() { public void Find() {
var cctor = DotNetUtils.getModuleTypeCctor(module); var cctor = DotNetUtils.GetModuleTypeCctor(module);
if (cctor == null) if (cctor == null)
return; return;
simpleDeobfuscator.deobfuscate(cctor, true); simpleDeobfuscator.Deobfuscate(cctor, true);
if ((dictField = ConstantsDecrypterUtils.findDictField(cctor, cctor.DeclaringType)) == null) if ((dictField = ConstantsDecrypterUtils.FindDictField(cctor, cctor.DeclaringType)) == null)
return; return;
if ((dataField = ConstantsDecrypterUtils.findDataField(cctor, cctor.DeclaringType)) == null) if ((dataField = ConstantsDecrypterUtils.FindDataField(cctor, cctor.DeclaringType)) == null)
return; return;
nativeMethod = findNativeMethod(cctor, cctor.DeclaringType); nativeMethod = FindNativeMethod(cctor, cctor.DeclaringType);
var method = getDecryptMethod(); var method = GetDecryptMethod();
if (method == null) if (method == null)
return; return;
simpleDeobfuscator.deobfuscate(method); simpleDeobfuscator.Deobfuscate(method);
var info = new DecrypterInfo(this, method, ConfuserVersion.Unknown); var info = new DecrypterInfo(this, method, ConfuserVersion.Unknown);
if (findKeys_v18_r75367(info)) if (FindKeys_v18_r75367(info))
initVersion(cctor, ConfuserVersion.v18_r75367_normal, ConfuserVersion.v18_r75367_dynamic, ConfuserVersion.v18_r75367_native); InitVersion(cctor, ConfuserVersion.v18_r75367_normal, ConfuserVersion.v18_r75367_dynamic, ConfuserVersion.v18_r75367_native);
else if (findKeys_v18_r75369(info)) else if (FindKeys_v18_r75369(info))
initVersion(cctor, ConfuserVersion.v18_r75369_normal, ConfuserVersion.v18_r75369_dynamic, ConfuserVersion.v18_r75369_native); InitVersion(cctor, ConfuserVersion.v18_r75369_normal, ConfuserVersion.v18_r75369_dynamic, ConfuserVersion.v18_r75369_native);
else else
return; return;
installMethod = cctor; installMethod = cctor;
} }
void initVersion(MethodDef installMethod, ConfuserVersion normal, ConfuserVersion dynamic, ConfuserVersion native) { void InitVersion(MethodDef installMethod, ConfuserVersion normal, ConfuserVersion dynamic, ConfuserVersion native) {
if (nativeMethod != null) if (nativeMethod != null)
version = native; version = native;
else if (DeobUtils.hasInteger(installMethod, 0x10000)) else if (DeobUtils.HasInteger(installMethod, 0x10000))
version = normal; version = normal;
else else
version = dynamic; version = dynamic;
} }
public void initialize() { public void Initialize() {
if (installMethod == null) if (installMethod == null)
return; return;
if (!findKeys()) if (!FindKeys())
throw new ApplicationException("Could not find keys"); throw new ApplicationException("Could not find keys");
if ((resource = findResource(key0)) == null) if ((resource = FindResource(key0)) == null)
throw new ApplicationException("Could not find resource"); throw new ApplicationException("Could not find resource");
constants = decryptResource(resource.GetResourceData()); constants = DecryptResource(resource.GetResourceData());
findDecrypters(); FindDecrypters();
} }
EmbeddedResource findResource(uint magic) { EmbeddedResource FindResource(uint magic) {
var name = Encoding.UTF8.GetString(BitConverter.GetBytes(magic)); var name = Encoding.UTF8.GetString(BitConverter.GetBytes(magic));
return DotNetUtils.getResource(module, name) as EmbeddedResource; return DotNetUtils.GetResource(module, name) as EmbeddedResource;
} }
bool findKeys() { bool FindKeys() {
if (!findKey0(installMethod, out key0)) if (!FindKey0(installMethod, out key0))
return false; return false;
if (!findKey0d(installMethod, out key0d)) if (!FindKey0d(installMethod, out key0d))
return false; return false;
return true; return true;
} }
static bool findKey0(MethodDef method, out uint key) { static bool FindKey0(MethodDef method, out uint key) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count; i++) { for (int i = 0; i < instrs.Count; i++) {
int index = ConfuserUtils.findCallMethod(instrs, i, Code.Call, "System.Text.Encoding System.Text.Encoding::get_UTF8()"); int index = ConfuserUtils.FindCallMethod(instrs, i, Code.Call, "System.Text.Encoding System.Text.Encoding::get_UTF8()");
if (index < 0) if (index < 0)
break; break;
int index2 = ConfuserUtils.findCallMethod(instrs, i, Code.Call, "System.Byte[] System.BitConverter::GetBytes(System.Int32)"); int index2 = ConfuserUtils.FindCallMethod(instrs, i, Code.Call, "System.Byte[] System.BitConverter::GetBytes(System.Int32)");
if (index2 - index != 2) if (index2 - index != 2)
continue; continue;
var ldci4 = instrs[index + 1]; var ldci4 = instrs[index + 1];
@ -255,13 +255,13 @@ namespace de4dot.code.deobfuscators.Confuser {
return false; return false;
} }
static bool findKey0d(MethodDef method, out uint key) { static bool FindKey0d(MethodDef method, out uint key) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count; i++) { for (int i = 0; i < instrs.Count; i++) {
int index = ConfuserUtils.findCallMethod(instrs, i, Code.Callvirt, "System.Reflection.Module System.Reflection.MemberInfo::get_Module()"); int index = ConfuserUtils.FindCallMethod(instrs, i, Code.Callvirt, "System.Reflection.Module System.Reflection.MemberInfo::get_Module()");
if (index < 0) if (index < 0)
break; break;
int index2 = ConfuserUtils.findCallMethod(instrs, i, Code.Callvirt, "System.Int32 System.Reflection.MemberInfo::get_MetadataToken()"); int index2 = ConfuserUtils.FindCallMethod(instrs, i, Code.Callvirt, "System.Int32 System.Reflection.MemberInfo::get_MetadataToken()");
if (index2 - index != 3) if (index2 - index != 3)
continue; continue;
var ldci4 = instrs[index + 1]; var ldci4 = instrs[index + 1];
@ -278,7 +278,7 @@ namespace de4dot.code.deobfuscators.Confuser {
return false; return false;
} }
static MethodDef findNativeMethod(MethodDef method, TypeDef declaringType) { static MethodDef FindNativeMethod(MethodDef method, TypeDef declaringType) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count; i++) { for (int i = 0; i < instrs.Count; i++) {
if (!instrs[i].IsLdloc()) if (!instrs[i].IsLdloc())
@ -289,7 +289,7 @@ namespace de4dot.code.deobfuscators.Confuser {
var calledMethod = call.Operand as MethodDef; var calledMethod = call.Operand as MethodDef;
if (calledMethod == null || !calledMethod.IsStatic || !calledMethod.IsNative) if (calledMethod == null || !calledMethod.IsStatic || !calledMethod.IsNative)
continue; continue;
if (!DotNetUtils.isMethod(calledMethod, "System.Int32", "(System.Int32)")) if (!DotNetUtils.IsMethod(calledMethod, "System.Int32", "(System.Int32)"))
continue; continue;
return calledMethod; return calledMethod;
@ -297,26 +297,26 @@ namespace de4dot.code.deobfuscators.Confuser {
return null; return null;
} }
MethodDef getDecryptMethod() { MethodDef GetDecryptMethod() {
foreach (var type in module.Types) { foreach (var type in module.Types) {
if (type.Attributes != (TypeAttributes.Abstract | TypeAttributes.Sealed)) if (type.Attributes != (TypeAttributes.Abstract | TypeAttributes.Sealed))
continue; continue;
if (!checkMethods(type.Methods)) if (!CheckMethods(type.Methods))
continue; continue;
foreach (var method in type.Methods) { foreach (var method in type.Methods) {
if (isDecryptMethodSignature(method)) if (IsDecryptMethodSignature(method))
return method; return method;
} }
} }
return null; return null;
} }
static bool checkMethods(IEnumerable<MethodDef> methods) { static bool CheckMethods(IEnumerable<MethodDef> methods) {
int numMethods = 0; int numMethods = 0;
foreach (var method in methods) { foreach (var method in methods) {
if (method.Name == ".ctor" || method.Name == ".cctor") if (method.Name == ".ctor" || method.Name == ".cctor")
return false; return false;
if (!isDecryptMethodSignature(method)) if (!IsDecryptMethodSignature(method))
return false; return false;
numMethods++; numMethods++;
@ -324,7 +324,7 @@ namespace de4dot.code.deobfuscators.Confuser {
return numMethods > 0; return numMethods > 0;
} }
static bool isDecryptMethodSignature(MethodDef method) { static bool IsDecryptMethodSignature(MethodDef method) {
if (method == null || method.Body == null) if (method == null || method.Body == null)
return false; return false;
if (method.Attributes != (MethodAttributes.Static | MethodAttributes.HideBySig | MethodAttributes.CompilerControlled)) if (method.Attributes != (MethodAttributes.Static | MethodAttributes.HideBySig | MethodAttributes.CompilerControlled))
@ -345,68 +345,68 @@ namespace de4dot.code.deobfuscators.Confuser {
return true; return true;
} }
void findDecrypters() { void FindDecrypters() {
foreach (var type in module.Types) { foreach (var type in module.Types) {
if (type.Attributes != (TypeAttributes.Abstract | TypeAttributes.Sealed)) if (type.Attributes != (TypeAttributes.Abstract | TypeAttributes.Sealed))
continue; continue;
if (!checkMethods(type.Methods)) if (!CheckMethods(type.Methods))
continue; continue;
foreach (var method in type.Methods) { foreach (var method in type.Methods) {
var info = createDecrypterInfo(method); var info = CreateDecrypterInfo(method);
if (info != null) if (info != null)
decrypters.add(info.method, info); decrypters.Add(info.method, info);
} }
} }
} }
DecrypterInfo createDecrypterInfo(MethodDef method) { DecrypterInfo CreateDecrypterInfo(MethodDef method) {
if (!isDecryptMethodSignature(method)) if (!IsDecryptMethodSignature(method))
return null; return null;
simpleDeobfuscator.deobfuscate(method); simpleDeobfuscator.Deobfuscate(method);
var info = new DecrypterInfo(this, method, version); var info = new DecrypterInfo(this, method, version);
if (!findKeys(info)) if (!FindKeys(info))
return null; return null;
return info; return info;
} }
bool findKeys(DecrypterInfo info) { bool FindKeys(DecrypterInfo info) {
switch (version) { switch (version) {
case ConfuserVersion.v18_r75367_normal: case ConfuserVersion.v18_r75367_normal:
case ConfuserVersion.v18_r75367_dynamic: case ConfuserVersion.v18_r75367_dynamic:
case ConfuserVersion.v18_r75367_native: case ConfuserVersion.v18_r75367_native:
return findKeys_v18_r75367(info); return FindKeys_v18_r75367(info);
case ConfuserVersion.v18_r75369_normal: case ConfuserVersion.v18_r75369_normal:
case ConfuserVersion.v18_r75369_dynamic: case ConfuserVersion.v18_r75369_dynamic:
case ConfuserVersion.v18_r75369_native: case ConfuserVersion.v18_r75369_native:
return findKeys_v18_r75369(info); return FindKeys_v18_r75369(info);
default: default:
throw new ApplicationException("Invalid version"); throw new ApplicationException("Invalid version");
} }
} }
static bool findKeys_v18_r75367(DecrypterInfo info) { static bool FindKeys_v18_r75367(DecrypterInfo info) {
if (!findLKeys_v18_r75367(info)) if (!FindLKeys_v18_r75367(info))
return false; return false;
if (!findKey0_v18_r75367(info)) if (!FindKey0_v18_r75367(info))
return false; return false;
if (!findKey0d_v18_r75367(info)) if (!FindKey0d_v18_r75367(info))
return false; return false;
return true; return true;
} }
static bool findKeys_v18_r75369(DecrypterInfo info) { static bool FindKeys_v18_r75369(DecrypterInfo info) {
if (!findLKeys_v18_r75369(info)) if (!FindLKeys_v18_r75369(info))
return false; return false;
if (!findKey0_v18_r75369(info)) if (!FindKey0_v18_r75369(info))
return false; return false;
if (!findKey0d_v18_r75367(info)) if (!FindKey0d_v18_r75367(info))
return false; return false;
return true; return true;
} }
static bool findLKeys_v18_r75367(DecrypterInfo info) { static bool FindLKeys_v18_r75367(DecrypterInfo info) {
var instrs = info.method.Body.Instructions; var instrs = info.method.Body.Instructions;
for (int i = 0; i < instrs.Count - 10; i++) { for (int i = 0; i < instrs.Count - 10; i++) {
var ldci4_1 = instrs[i]; var ldci4_1 = instrs[i];
@ -443,7 +443,7 @@ namespace de4dot.code.deobfuscators.Confuser {
return false; return false;
} }
static bool findKey0_v18_r75367(DecrypterInfo info) { static bool FindKey0_v18_r75367(DecrypterInfo info) {
var instrs = info.method.Body.Instructions; var instrs = info.method.Body.Instructions;
for (int i = 0; i < instrs.Count - 4; i++) { for (int i = 0; i < instrs.Count - 4; i++) {
if (instrs[i].OpCode.Code != Code.Xor) if (instrs[i].OpCode.Code != Code.Xor)
@ -464,13 +464,13 @@ namespace de4dot.code.deobfuscators.Confuser {
return false; return false;
} }
static bool findKey0d_v18_r75367(DecrypterInfo info) { static bool FindKey0d_v18_r75367(DecrypterInfo info) {
var instrs = info.method.Body.Instructions; var instrs = info.method.Body.Instructions;
for (int i = 0; i < instrs.Count; i++) { for (int i = 0; i < instrs.Count; i++) {
int index = ConfuserUtils.findCallMethod(instrs, i, Code.Callvirt, "System.Int32 System.Reflection.MemberInfo::get_MetadataToken()"); int index = ConfuserUtils.FindCallMethod(instrs, i, Code.Callvirt, "System.Int32 System.Reflection.MemberInfo::get_MetadataToken()");
if (index < 0) if (index < 0)
break; break;
int index2 = ConfuserUtils.findCallMethod(instrs, index, Code.Call, "System.Byte[] System.BitConverter::GetBytes(System.Int32)"); int index2 = ConfuserUtils.FindCallMethod(instrs, index, Code.Call, "System.Byte[] System.BitConverter::GetBytes(System.Int32)");
if (index2 < 0) if (index2 < 0)
break; break;
if (index2 - index != 3) if (index2 - index != 3)
@ -487,7 +487,7 @@ namespace de4dot.code.deobfuscators.Confuser {
return false; return false;
} }
static bool findLKeys_v18_r75369(DecrypterInfo info) { static bool FindLKeys_v18_r75369(DecrypterInfo info) {
var instrs = info.method.Body.Instructions; var instrs = info.method.Body.Instructions;
for (int i = 0; i < instrs.Count - 8; i++) { for (int i = 0; i < instrs.Count - 8; i++) {
var ldci8_1 = instrs[i]; var ldci8_1 = instrs[i];
@ -520,7 +520,7 @@ namespace de4dot.code.deobfuscators.Confuser {
return false; return false;
} }
static bool findKey0_v18_r75369(DecrypterInfo info) { static bool FindKey0_v18_r75369(DecrypterInfo info) {
var instrs = info.method.Body.Instructions; var instrs = info.method.Body.Instructions;
for (int i = 0; i < instrs.Count - 4; i++) { for (int i = 0; i < instrs.Count - 4; i++) {
if (!instrs[i].IsLdloc()) if (!instrs[i].IsLdloc())
@ -541,36 +541,36 @@ namespace de4dot.code.deobfuscators.Confuser {
return false; return false;
} }
byte[] decryptResource(byte[] encrypted) { byte[] DecryptResource(byte[] encrypted) {
switch (version) { switch (version) {
case ConfuserVersion.v18_r75367_normal: case ConfuserVersion.v18_r75367_normal:
case ConfuserVersion.v18_r75369_normal: case ConfuserVersion.v18_r75369_normal:
return decryptResource_v18_r75367_normal(encrypted); return DecryptResource_v18_r75367_normal(encrypted);
case ConfuserVersion.v18_r75367_dynamic: case ConfuserVersion.v18_r75367_dynamic:
case ConfuserVersion.v18_r75369_dynamic: case ConfuserVersion.v18_r75369_dynamic:
return decryptResource_v18_r75367_dynamic(encrypted); return DecryptResource_v18_r75367_dynamic(encrypted);
case ConfuserVersion.v18_r75367_native: case ConfuserVersion.v18_r75367_native:
case ConfuserVersion.v18_r75369_native: case ConfuserVersion.v18_r75369_native:
return decryptResource_v18_r75367_native(encrypted); return DecryptResource_v18_r75367_native(encrypted);
default: default:
throw new ApplicationException("Unknown version"); throw new ApplicationException("Unknown version");
} }
} }
byte[] getSigKey() { byte[] GetSigKey() {
return module.ReadBlob(key0d ^ installMethod.MDToken.ToUInt32()); return module.ReadBlob(key0d ^ installMethod.MDToken.ToUInt32());
} }
byte[] decryptResource_v18_r75367_normal(byte[] encrypted) { byte[] DecryptResource_v18_r75367_normal(byte[] encrypted) {
var key = getSigKey(); var key = GetSigKey();
var decrypted = ConfuserUtils.decrypt(BitConverter.ToUInt32(key, 12) * (uint)key0, encrypted); var decrypted = ConfuserUtils.Decrypt(BitConverter.ToUInt32(key, 12) * (uint)key0, encrypted);
return DeobUtils.inflate(DeobUtils.aesDecrypt(decrypted, key, DeobUtils.md5Sum(key)), true); return DeobUtils.Inflate(DeobUtils.AesDecrypt(decrypted, key, DeobUtils.Md5Sum(key)), true);
} }
static int getDynamicStartIndex(IList<Instruction> instrs, int ldlocIndex) { static int GetDynamicStartIndex(IList<Instruction> instrs, int ldlocIndex) {
for (int i = ldlocIndex - 1; i >= 0; i--) { for (int i = ldlocIndex - 1; i >= 0; i--) {
if (instrs[i].OpCode.FlowControl != FlowControl.Next) if (instrs[i].OpCode.FlowControl != FlowControl.Next)
return i + 1; return i + 1;
@ -578,7 +578,7 @@ namespace de4dot.code.deobfuscators.Confuser {
return 0; return 0;
} }
int getDynamicEndIndex(int startIndex, Local local) { int GetDynamicEndIndex(int startIndex, Local local) {
if (startIndex < 0) if (startIndex < 0)
return -1; return -1;
var instrs = installMethod.Body.Instructions; var instrs = installMethod.Body.Instructions;
@ -590,10 +590,10 @@ namespace de4dot.code.deobfuscators.Confuser {
return -1; return -1;
} }
Local getDynamicLocal(out int instrIndex) { Local GetDynamicLocal(out int instrIndex) {
var instrs = installMethod.Body.Instructions; var instrs = installMethod.Body.Instructions;
for (int i = 0; i < instrs.Count; i++) { for (int i = 0; i < instrs.Count; i++) {
i = ConfuserUtils.findCallMethod(instrs, i, Code.Callvirt, "System.Void System.IO.BinaryWriter::Write(System.Byte)"); i = ConfuserUtils.FindCallMethod(instrs, i, Code.Callvirt, "System.Void System.IO.BinaryWriter::Write(System.Byte)");
if (i < 0) if (i < 0)
break; break;
int index = i - 2; int index = i - 2;
@ -612,24 +612,24 @@ namespace de4dot.code.deobfuscators.Confuser {
return null; return null;
} }
byte[] decryptResource_v18_r75367_dynamic(byte[] encrypted) { byte[] DecryptResource_v18_r75367_dynamic(byte[] encrypted) {
int ldlocIndex; int ldlocIndex;
var local = getDynamicLocal(out ldlocIndex); var local = GetDynamicLocal(out ldlocIndex);
if (local == null) if (local == null)
throw new ApplicationException("Could not find local"); throw new ApplicationException("Could not find local");
var instrs = installMethod.Body.Instructions; var instrs = installMethod.Body.Instructions;
int startIndex = getDynamicStartIndex(instrs, ldlocIndex); int startIndex = GetDynamicStartIndex(instrs, ldlocIndex);
int endIndex = getDynamicEndIndex(startIndex, local); int endIndex = GetDynamicEndIndex(startIndex, local);
if (endIndex < 0) if (endIndex < 0)
throw new ApplicationException("Could not find endIndex"); throw new ApplicationException("Could not find endIndex");
var constReader = new ConstantsReader(installMethod); var constReader = new ConstantsReader(installMethod);
return decryptResource(encrypted, magic => { return DecryptResource(encrypted, magic => {
constReader.setConstantInt32(local, magic); constReader.SetConstantInt32(local, magic);
int index = startIndex, result; int index = startIndex, result;
if (!constReader.getNextInt32(ref index, out result)) if (!constReader.GetNextInt32(ref index, out result))
throw new ApplicationException("Could not get constant"); throw new ApplicationException("Could not get constant");
if (index != endIndex) if (index != endIndex)
throw new ApplicationException("Wrong constant"); throw new ApplicationException("Wrong constant");
@ -637,16 +637,16 @@ namespace de4dot.code.deobfuscators.Confuser {
}); });
} }
byte[] decryptResource_v18_r75367_native(byte[] encrypted) { byte[] DecryptResource_v18_r75367_native(byte[] encrypted) {
using (var x86Emu = new x86Emulator(fileData)) using (var x86Emu = new x86Emulator(fileData))
return decryptResource(encrypted, magic => (byte)x86Emu.emulate((uint)nativeMethod.RVA, magic)); return DecryptResource(encrypted, magic => (byte)x86Emu.Emulate((uint)nativeMethod.RVA, magic));
} }
byte[] decryptResource(byte[] encrypted, Func<uint, byte> decryptFunc) { byte[] DecryptResource(byte[] encrypted, Func<uint, byte> decryptFunc) {
var key = getSigKey(); var key = GetSigKey();
var decrypted = DeobUtils.aesDecrypt(encrypted, key, DeobUtils.md5Sum(key)); var decrypted = DeobUtils.AesDecrypt(encrypted, key, DeobUtils.Md5Sum(key));
decrypted = DeobUtils.inflate(decrypted, true); decrypted = DeobUtils.Inflate(decrypted, true);
var reader = MemoryImageStream.Create(decrypted); var reader = MemoryImageStream.Create(decrypted);
var result = new MemoryStream(); var result = new MemoryStream();
@ -659,7 +659,7 @@ namespace de4dot.code.deobfuscators.Confuser {
return result.ToArray(); return result.ToArray();
} }
static bool verifyGenericArg(MethodSpec gim, ElementType etype) { static bool VerifyGenericArg(MethodSpec gim, ElementType etype) {
if (gim == null) if (gim == null)
return false; return false;
var gims = gim.GenericInstMethodSig; var gims = gim.GenericInstMethodSig;
@ -668,42 +668,42 @@ namespace de4dot.code.deobfuscators.Confuser {
return gims.GenericArguments[0].GetElementType() == etype; return gims.GenericArguments[0].GetElementType() == etype;
} }
public string decryptString(MethodDef method, MethodSpec gim, uint magic1, ulong magic2) { public string DecryptString(MethodDef method, MethodSpec gim, uint magic1, ulong magic2) {
if (!verifyGenericArg(gim, ElementType.String)) if (!VerifyGenericArg(gim, ElementType.String))
return null; return null;
var info = decrypters.find(method); var info = decrypters.Find(method);
return info.decryptString(magic1, magic2); return info.DecryptString(magic1, magic2);
} }
public object decryptInt32(MethodDef method, MethodSpec gim, uint magic1, ulong magic2) { public object DecryptInt32(MethodDef method, MethodSpec gim, uint magic1, ulong magic2) {
if (!verifyGenericArg(gim, ElementType.I4)) if (!VerifyGenericArg(gim, ElementType.I4))
return null; return null;
var info = decrypters.find(method); var info = decrypters.Find(method);
return info.decryptInt32(magic1, magic2); return info.DecryptInt32(magic1, magic2);
} }
public object decryptInt64(MethodDef method, MethodSpec gim, uint magic1, ulong magic2) { public object DecryptInt64(MethodDef method, MethodSpec gim, uint magic1, ulong magic2) {
if (!verifyGenericArg(gim, ElementType.I8)) if (!VerifyGenericArg(gim, ElementType.I8))
return null; return null;
var info = decrypters.find(method); var info = decrypters.Find(method);
return info.decryptInt64(magic1, magic2); return info.DecryptInt64(magic1, magic2);
} }
public object decryptSingle(MethodDef method, MethodSpec gim, uint magic1, ulong magic2) { public object DecryptSingle(MethodDef method, MethodSpec gim, uint magic1, ulong magic2) {
if (!verifyGenericArg(gim, ElementType.R4)) if (!VerifyGenericArg(gim, ElementType.R4))
return null; return null;
var info = decrypters.find(method); var info = decrypters.Find(method);
return info.decryptSingle(magic1, magic2); return info.DecryptSingle(magic1, magic2);
} }
public object decryptDouble(MethodDef method, MethodSpec gim, uint magic1, ulong magic2) { public object DecryptDouble(MethodDef method, MethodSpec gim, uint magic1, ulong magic2) {
if (!verifyGenericArg(gim, ElementType.R8)) if (!VerifyGenericArg(gim, ElementType.R8))
return null; return null;
var info = decrypters.find(method); var info = decrypters.Find(method);
return info.decryptDouble(magic1, magic2); return info.DecryptDouble(magic1, magic2);
} }
public void cleanUp() { public void CleanUp() {
if (installMethod == null) if (installMethod == null)
return; return;
@ -712,7 +712,7 @@ namespace de4dot.code.deobfuscators.Confuser {
installMethod.Body.Instructions.Add(Instruction.Create(OpCodes.Ret)); installMethod.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));
} }
public bool getRevisionRange(out int minRev, out int maxRev) { public bool GetRevisionRange(out int minRev, out int maxRev) {
switch (version) { switch (version) {
case ConfuserVersion.Unknown: case ConfuserVersion.Unknown:
minRev = maxRev = 0; minRev = maxRev = 0;

View File

@ -24,42 +24,42 @@ using de4dot.blocks.cflow;
namespace de4dot.code.deobfuscators.Confuser { namespace de4dot.code.deobfuscators.Confuser {
class ConstantsFolder : BlockDeobfuscator { class ConstantsFolder : BlockDeobfuscator {
protected override bool deobfuscate(Block block) { protected override bool Deobfuscate(Block block) {
bool modified = false; bool modified = false;
var instrs = block.Instructions; var instrs = block.Instructions;
var constantsReader = createConstantsReader(instrs); var constantsReader = CreateConstantsReader(instrs);
for (int i = 0; i < instrs.Count; i++) { for (int i = 0; i < instrs.Count; i++) {
int index = 0; int index = 0;
Instruction newInstr = null; Instruction newInstr = null;
var instr = instrs[i]; var instr = instrs[i];
if (constantsReader.isLoadConstantInt32(instr.Instruction)) { if (constantsReader.IsLoadConstantInt32(instr.Instruction)) {
index = i; index = i;
int val; int val;
if (!constantsReader.getInt32(ref index, out val)) if (!constantsReader.GetInt32(ref index, out val))
continue; continue;
newInstr = Instruction.CreateLdcI4(val); newInstr = Instruction.CreateLdcI4(val);
} }
else if (constantsReader.isLoadConstantInt64(instr.Instruction)) { else if (constantsReader.IsLoadConstantInt64(instr.Instruction)) {
index = i; index = i;
long val; long val;
if (!constantsReader.getInt64(ref index, out val)) if (!constantsReader.GetInt64(ref index, out val))
continue; continue;
newInstr = Instruction.Create(OpCodes.Ldc_I8, val); newInstr = Instruction.Create(OpCodes.Ldc_I8, val);
} }
else if (constantsReader.isLoadConstantDouble(instr.Instruction)) { else if (constantsReader.IsLoadConstantDouble(instr.Instruction)) {
index = i; index = i;
double val; double val;
if (!constantsReader.getDouble(ref index, out val)) if (!constantsReader.GetDouble(ref index, out val))
continue; continue;
newInstr = Instruction.Create(OpCodes.Ldc_R8, val); newInstr = Instruction.Create(OpCodes.Ldc_R8, val);
} }
if (newInstr != null && index - i > 1) { if (newInstr != null && index - i > 1) {
block.insert(index++, Instruction.Create(OpCodes.Pop)); block.Insert(index++, Instruction.Create(OpCodes.Pop));
block.insert(index++, newInstr); block.Insert(index++, newInstr);
i = index - 1; i = index - 1;
constantsReader = createConstantsReader(instrs); constantsReader = CreateConstantsReader(instrs);
modified = true; modified = true;
continue; continue;
} }
@ -101,8 +101,8 @@ namespace de4dot.code.deobfuscators.Confuser {
break; break;
} }
if (newInstr != null) { if (newInstr != null) {
block.replace(i, 2, newInstr); block.Replace(i, 2, newInstr);
constantsReader = createConstantsReader(instrs); constantsReader = CreateConstantsReader(instrs);
modified = true; modified = true;
continue; continue;
} }
@ -112,7 +112,7 @@ namespace de4dot.code.deobfuscators.Confuser {
return modified; return modified;
} }
static ConstantsReader createConstantsReader(IList<Instr> instrs) { static ConstantsReader CreateConstantsReader(IList<Instr> instrs) {
return new ConstantsReader(instrs, false); return new ConstantsReader(instrs, false);
} }
} }

View File

@ -38,17 +38,17 @@ namespace de4dot.code.deobfuscators.Confuser {
this.doubleValueInliner = doubleValueInliner; this.doubleValueInliner = doubleValueInliner;
} }
public void deobfuscateBegin(Blocks blocks) { public void DeobfuscateBegin(Blocks blocks) {
this.blocks = blocks; this.blocks = blocks;
} }
public bool deobfuscate(List<Block> allBlocks) { public bool Deobfuscate(List<Block> allBlocks) {
bool modified = false; bool modified = false;
foreach (var block in allBlocks) { foreach (var block in allBlocks) {
modified |= int32ValueInliner.decrypt(blocks.Method, allBlocks) != 0; modified |= int32ValueInliner.Decrypt(blocks.Method, allBlocks) != 0;
modified |= int64ValueInliner.decrypt(blocks.Method, allBlocks) != 0; modified |= int64ValueInliner.Decrypt(blocks.Method, allBlocks) != 0;
modified |= singleValueInliner.decrypt(blocks.Method, allBlocks) != 0; modified |= singleValueInliner.Decrypt(blocks.Method, allBlocks) != 0;
modified |= doubleValueInliner.decrypt(blocks.Method, allBlocks) != 0; modified |= doubleValueInliner.Decrypt(blocks.Method, allBlocks) != 0;
} }
return modified; return modified;
} }

View File

@ -34,9 +34,9 @@ namespace de4dot.code.deobfuscators.Confuser {
public DeobfuscatorInfo() public DeobfuscatorInfo()
: base() { : base() {
removeAntiDebug = new BoolOption(null, makeArgName("antidb"), "Remove anti debug code", true); removeAntiDebug = new BoolOption(null, MakeArgName("antidb"), "Remove anti debug code", true);
removeAntiDump = new BoolOption(null, makeArgName("antidump"), "Remove anti dump code", true); removeAntiDump = new BoolOption(null, MakeArgName("antidump"), "Remove anti dump code", true);
decryptMainAsm = new BoolOption(null, makeArgName("decrypt-main"), "Decrypt main embedded assembly", true); decryptMainAsm = new BoolOption(null, MakeArgName("decrypt-main"), "Decrypt main embedded assembly", true);
} }
public override string Name { public override string Name {
@ -47,7 +47,7 @@ namespace de4dot.code.deobfuscators.Confuser {
get { return THE_TYPE; } get { return THE_TYPE; }
} }
public override IDeobfuscator createDeobfuscator() { public override IDeobfuscator CreateDeobfuscator() {
return new Deobfuscator(new Deobfuscator.Options { return new Deobfuscator(new Deobfuscator.Options {
ValidNameRegex = validNameRegex.get(), ValidNameRegex = validNameRegex.get(),
RemoveAntiDebug = removeAntiDebug.get(), RemoveAntiDebug = removeAntiDebug.get(),
@ -56,7 +56,7 @@ namespace de4dot.code.deobfuscators.Confuser {
}); });
} }
protected override IEnumerable<Option> getOptionsInternal() { protected override IEnumerable<Option> GetOptionsInternal() {
return new List<Option>() { return new List<Option>() {
removeAntiDebug, removeAntiDebug,
removeAntiDump, removeAntiDump,
@ -128,88 +128,88 @@ namespace de4dot.code.deobfuscators.Confuser {
StringFeatures = StringFeatures.AllowStaticDecryption | StringFeatures.AllowDynamicDecryption; StringFeatures = StringFeatures.AllowStaticDecryption | StringFeatures.AllowDynamicDecryption;
} }
protected override int detectInternal() { protected override int DetectInternal() {
int val = 0; int val = 0;
int sum = toInt32(jitMethodsDecrypter != null ? jitMethodsDecrypter.Detected : false) + int sum = ToInt32(jitMethodsDecrypter != null ? jitMethodsDecrypter.Detected : false) +
toInt32(memoryMethodsDecrypter != null ? memoryMethodsDecrypter.Detected : false) + ToInt32(memoryMethodsDecrypter != null ? memoryMethodsDecrypter.Detected : false) +
toInt32(proxyCallFixer != null ? proxyCallFixer.Detected : false) + ToInt32(proxyCallFixer != null ? proxyCallFixer.Detected : false) +
toInt32(antiDebugger != null ? antiDebugger.Detected : false) + ToInt32(antiDebugger != null ? antiDebugger.Detected : false) +
toInt32(antiDumping != null ? antiDumping.Detected : false) + ToInt32(antiDumping != null ? antiDumping.Detected : false) +
toInt32(resourceDecrypter != null ? resourceDecrypter.Detected : false) + ToInt32(resourceDecrypter != null ? resourceDecrypter.Detected : false) +
toInt32(constantsDecrypterV18 != null ? constantsDecrypterV18.Detected : false) + ToInt32(constantsDecrypterV18 != null ? constantsDecrypterV18.Detected : false) +
toInt32(constantsDecrypterV15 != null ? constantsDecrypterV15.Detected : false) + ToInt32(constantsDecrypterV15 != null ? constantsDecrypterV15.Detected : false) +
toInt32(constantsDecrypterV17 != null ? constantsDecrypterV17.Detected : false) + ToInt32(constantsDecrypterV17 != null ? constantsDecrypterV17.Detected : false) +
toInt32(stringDecrypter != null ? stringDecrypter.Detected : false) + ToInt32(stringDecrypter != null ? stringDecrypter.Detected : false) +
toInt32(unpacker != null ? unpacker.Detected : false); ToInt32(unpacker != null ? unpacker.Detected : false);
if (sum > 0) if (sum > 0)
val += 100 + 10 * (sum - 1); val += 100 + 10 * (sum - 1);
return val; return val;
} }
protected override void scanForObfuscator() { protected override void ScanForObfuscator() {
removeObfuscatorAttribute(); RemoveObfuscatorAttribute();
jitMethodsDecrypter = new JitMethodsDecrypter(module, DeobfuscatedFile); jitMethodsDecrypter = new JitMethodsDecrypter(module, DeobfuscatedFile);
try { try {
jitMethodsDecrypter.find(); jitMethodsDecrypter.Find();
} }
catch { catch {
} }
if (jitMethodsDecrypter.Detected) { if (jitMethodsDecrypter.Detected) {
initializeObfuscatorName(); InitializeObfuscatorName();
return; return;
} }
memoryMethodsDecrypter = new MemoryMethodsDecrypter(module, DeobfuscatedFile); memoryMethodsDecrypter = new MemoryMethodsDecrypter(module, DeobfuscatedFile);
memoryMethodsDecrypter.find(); memoryMethodsDecrypter.Find();
if (memoryMethodsDecrypter.Detected) { if (memoryMethodsDecrypter.Detected) {
initializeObfuscatorName(); InitializeObfuscatorName();
return; return;
} }
initTheRest(null); InitializeTheRest(null);
} }
void initTheRest(Deobfuscator oldOne) { void InitializeTheRest(Deobfuscator oldOne) {
resourceDecrypter = new ResourceDecrypter(module, DeobfuscatedFile); resourceDecrypter = new ResourceDecrypter(module, DeobfuscatedFile);
resourceDecrypter.find(); resourceDecrypter.Find();
constantsDecrypterV18 = new ConstantsDecrypterV18(module, getFileData(), DeobfuscatedFile); constantsDecrypterV18 = new ConstantsDecrypterV18(module, GetFileData(), DeobfuscatedFile);
constantsDecrypterV17 = new ConstantsDecrypterV17(module, getFileData(), DeobfuscatedFile); constantsDecrypterV17 = new ConstantsDecrypterV17(module, GetFileData(), DeobfuscatedFile);
constantsDecrypterV15 = new ConstantsDecrypterV15(module, getFileData(), DeobfuscatedFile); constantsDecrypterV15 = new ConstantsDecrypterV15(module, GetFileData(), DeobfuscatedFile);
do { do {
constantsDecrypterV18.find(); constantsDecrypterV18.Find();
if (constantsDecrypterV18.Detected) { if (constantsDecrypterV18.Detected) {
initializeConstantsDecrypterV18(); InitializeConstantsDecrypterV18();
break; break;
} }
constantsDecrypterV17.find(); constantsDecrypterV17.Find();
if (constantsDecrypterV17.Detected) { if (constantsDecrypterV17.Detected) {
initializeConstantsDecrypterV17(); InitializeConstantsDecrypterV17();
break; break;
} }
constantsDecrypterV15.find(); constantsDecrypterV15.Find();
if (constantsDecrypterV15.Detected) { if (constantsDecrypterV15.Detected) {
initializeConstantsDecrypterV15(); InitializeConstantsDecrypterV15();
break; break;
} }
} while (false); } while (false);
proxyCallFixer = new ProxyCallFixer(module, getFileData()); proxyCallFixer = new ProxyCallFixer(module, GetFileData());
proxyCallFixer.findDelegateCreator(DeobfuscatedFile); proxyCallFixer.FindDelegateCreator(DeobfuscatedFile);
antiDebugger = new AntiDebugger(module); antiDebugger = new AntiDebugger(module);
antiDebugger.find(); antiDebugger.Find();
antiDumping = new AntiDumping(module); antiDumping = new AntiDumping(module);
antiDumping.find(DeobfuscatedFile); antiDumping.Find(DeobfuscatedFile);
stringDecrypter = new StringDecrypter(module); stringDecrypter = new StringDecrypter(module);
stringDecrypter.find(DeobfuscatedFile); stringDecrypter.Find(DeobfuscatedFile);
initializeStringDecrypter(); InitializeStringDecrypter();
unpacker = new Unpacker(module, oldOne == null ? null : oldOne.unpacker); unpacker = new Unpacker(module, oldOne == null ? null : oldOne.unpacker);
unpacker.find(DeobfuscatedFile, this); unpacker.Find(DeobfuscatedFile, this);
initializeObfuscatorName(); InitializeObfuscatorName();
} }
void initializeObfuscatorName() { void InitializeObfuscatorName() {
var versionString = getVersionString(); var versionString = GetVersionString();
if (string.IsNullOrEmpty(versionString)) if (string.IsNullOrEmpty(versionString))
obfuscatorName = DeobfuscatorInfo.THE_NAME; obfuscatorName = DeobfuscatorInfo.THE_NAME;
else else
@ -217,7 +217,7 @@ namespace de4dot.code.deobfuscators.Confuser {
} }
const bool useAttributeVersion = true; const bool useAttributeVersion = true;
string getVersionString() { string GetVersionString() {
var versionProviders = new IVersionProvider[] { var versionProviders = new IVersionProvider[] {
jitMethodsDecrypter, jitMethodsDecrypter,
memoryMethodsDecrypter, memoryMethodsDecrypter,
@ -237,23 +237,23 @@ namespace de4dot.code.deobfuscators.Confuser {
if (versionProvider == null) if (versionProvider == null)
continue; continue;
int minRev, maxRev; int minRev, maxRev;
if (versionProvider.getRevisionRange(out minRev, out maxRev)) { if (versionProvider.GetRevisionRange(out minRev, out maxRev)) {
if (maxRev == int.MaxValue) if (maxRev == int.MaxValue)
Logger.v("r{0}-latest : {1}", minRev, versionProvider.GetType().Name); Logger.v("r{0}-latest : {1}", minRev, versionProvider.GetType().Name);
else else
Logger.v("r{0}-r{1} : {2}", minRev, maxRev, versionProvider.GetType().Name); Logger.v("r{0}-r{1} : {2}", minRev, maxRev, versionProvider.GetType().Name);
vd.addRevs(minRev, maxRev); vd.AddRevs(minRev, maxRev);
} }
} }
if (useAttributeVersion) if (useAttributeVersion)
vd.setVersion(approxVersion); vd.SetVersion(approxVersion);
return vd.getVersionString(); return vd.GetVersionString();
} }
byte[] getFileData() { byte[] GetFileData() {
if (ModuleBytes != null) if (ModuleBytes != null)
return ModuleBytes; return ModuleBytes;
return ModuleBytes = DeobUtils.readModule(module); return ModuleBytes = DeobUtils.ReadModule(module);
} }
[Flags] [Flags]
@ -263,22 +263,22 @@ namespace de4dot.code.deobfuscators.Confuser {
} }
DecryptState decryptState = DecryptState.CanDecryptMethods | DecryptState.CanUnpack; DecryptState decryptState = DecryptState.CanDecryptMethods | DecryptState.CanUnpack;
bool hasUnpacked = false; bool hasUnpacked = false;
public override bool getDecryptedModule(int count, ref byte[] newFileData, ref DumpedMethods dumpedMethods) { public override bool GetDecryptedModule(int count, ref byte[] newFileData, ref DumpedMethods dumpedMethods) {
hasUnpacked = false; hasUnpacked = false;
byte[] fileData = getFileData(); byte[] fileData = GetFileData();
using (var peImage = new MyPEImage(fileData)) { using (var peImage = new MyPEImage(fileData)) {
if ((decryptState & DecryptState.CanDecryptMethods) != 0) { if ((decryptState & DecryptState.CanDecryptMethods) != 0) {
bool decrypted = false; bool decrypted = false;
if (jitMethodsDecrypter != null && jitMethodsDecrypter.Detected) { if (jitMethodsDecrypter != null && jitMethodsDecrypter.Detected) {
jitMethodsDecrypter.initialize(); jitMethodsDecrypter.Initialize();
if (!jitMethodsDecrypter.decrypt(peImage, fileData, ref dumpedMethods)) if (!jitMethodsDecrypter.Decrypt(peImage, fileData, ref dumpedMethods))
return false; return false;
decrypted = true; decrypted = true;
} }
else if (memoryMethodsDecrypter != null && memoryMethodsDecrypter.Detected) { else if (memoryMethodsDecrypter != null && memoryMethodsDecrypter.Detected) {
memoryMethodsDecrypter.initialize(); memoryMethodsDecrypter.Initialize();
if (!memoryMethodsDecrypter.decrypt(peImage, fileData)) if (!memoryMethodsDecrypter.Decrypt(peImage, fileData))
return false; return false;
decrypted = true; decrypted = true;
} }
@ -297,18 +297,18 @@ namespace de4dot.code.deobfuscators.Confuser {
if (unpacker != null && unpacker.Detected) { if (unpacker != null && unpacker.Detected) {
if (options.DecryptMainAsm) { if (options.DecryptMainAsm) {
decryptState |= DecryptState.CanDecryptMethods | DecryptState.CanUnpack; decryptState |= DecryptState.CanDecryptMethods | DecryptState.CanUnpack;
var mainInfo = unpacker.unpackMainAssembly(true); var mainInfo = unpacker.UnpackMainAssembly(true);
newFileData = mainInfo.data; newFileData = mainInfo.data;
realAssemblyInfo = mainInfo.realAssemblyInfo; realAssemblyInfo = mainInfo.realAssemblyInfo;
embeddedAssemblyInfos.AddRange(unpacker.getEmbeddedAssemblyInfos()); embeddedAssemblyInfos.AddRange(unpacker.GetEmbeddedAssemblyInfos());
ModuleBytes = newFileData; ModuleBytes = newFileData;
hasUnpacked = true; hasUnpacked = true;
return true; return true;
} }
else { else {
decryptState &= ~DecryptState.CanUnpack; decryptState &= ~DecryptState.CanUnpack;
mainAsmInfo = unpacker.unpackMainAssembly(false); mainAsmInfo = unpacker.UnpackMainAssembly(false);
embeddedAssemblyInfos.AddRange(unpacker.getEmbeddedAssemblyInfos()); embeddedAssemblyInfos.AddRange(unpacker.GetEmbeddedAssemblyInfos());
return false; return false;
} }
} }
@ -317,7 +317,7 @@ namespace de4dot.code.deobfuscators.Confuser {
return false; return false;
} }
public override IDeobfuscator moduleReloaded(ModuleDefMD module) { public override IDeobfuscator ModuleReloaded(ModuleDefMD module) {
if (module.Assembly != null) if (module.Assembly != null)
realAssemblyInfo = null; realAssemblyInfo = null;
if (realAssemblyInfo != null) { if (realAssemblyInfo != null) {
@ -329,19 +329,19 @@ namespace de4dot.code.deobfuscators.Confuser {
} }
var newOne = new Deobfuscator(options); var newOne = new Deobfuscator(options);
DeobfuscatedFile.setDeobfuscator(newOne); DeobfuscatedFile.SetDeobfuscator(newOne);
newOne.realAssemblyInfo = realAssemblyInfo; newOne.realAssemblyInfo = realAssemblyInfo;
newOne.decryptState = decryptState; newOne.decryptState = decryptState;
newOne.DeobfuscatedFile = DeobfuscatedFile; newOne.DeobfuscatedFile = DeobfuscatedFile;
newOne.ModuleBytes = ModuleBytes; newOne.ModuleBytes = ModuleBytes;
newOne.embeddedAssemblyInfos.AddRange(embeddedAssemblyInfos); newOne.embeddedAssemblyInfos.AddRange(embeddedAssemblyInfos);
newOne.setModule(module); newOne.SetModule(module);
newOne.removeObfuscatorAttribute(); newOne.RemoveObfuscatorAttribute();
newOne.jitMethodsDecrypter = hasUnpacked ? new JitMethodsDecrypter(module, DeobfuscatedFile) : newOne.jitMethodsDecrypter = hasUnpacked ? new JitMethodsDecrypter(module, DeobfuscatedFile) :
new JitMethodsDecrypter(module, DeobfuscatedFile, jitMethodsDecrypter); new JitMethodsDecrypter(module, DeobfuscatedFile, jitMethodsDecrypter);
if ((newOne.decryptState & DecryptState.CanDecryptMethods) != 0) { if ((newOne.decryptState & DecryptState.CanDecryptMethods) != 0) {
try { try {
newOne.jitMethodsDecrypter.find(); newOne.jitMethodsDecrypter.Find();
} }
catch { catch {
} }
@ -351,185 +351,185 @@ namespace de4dot.code.deobfuscators.Confuser {
newOne.memoryMethodsDecrypter = hasUnpacked ? new MemoryMethodsDecrypter(module, DeobfuscatedFile) : newOne.memoryMethodsDecrypter = hasUnpacked ? new MemoryMethodsDecrypter(module, DeobfuscatedFile) :
new MemoryMethodsDecrypter(module, DeobfuscatedFile, memoryMethodsDecrypter); new MemoryMethodsDecrypter(module, DeobfuscatedFile, memoryMethodsDecrypter);
if ((newOne.decryptState & DecryptState.CanDecryptMethods) != 0) { if ((newOne.decryptState & DecryptState.CanDecryptMethods) != 0) {
newOne.memoryMethodsDecrypter.find(); newOne.memoryMethodsDecrypter.Find();
if (newOne.memoryMethodsDecrypter.Detected) if (newOne.memoryMethodsDecrypter.Detected)
return newOne; return newOne;
} }
newOne.initTheRest(this); newOne.InitializeTheRest(this);
return newOne; return newOne;
} }
public override void deobfuscateBegin() { public override void DeobfuscateBegin() {
base.deobfuscateBegin(); base.DeobfuscateBegin();
Logger.v("Detected {0}", obfuscatorName); Logger.v("Detected {0}", obfuscatorName);
initializeConstantsDecrypterV18(); InitializeConstantsDecrypterV18();
initializeConstantsDecrypterV17(); InitializeConstantsDecrypterV17();
initializeConstantsDecrypterV15(); InitializeConstantsDecrypterV15();
initializeStringDecrypter(); InitializeStringDecrypter();
if (jitMethodsDecrypter != null) { if (jitMethodsDecrypter != null) {
addModuleCctorInitCallToBeRemoved(jitMethodsDecrypter.InitMethod); AddModuleCctorInitCallToBeRemoved(jitMethodsDecrypter.InitMethod);
addTypeToBeRemoved(jitMethodsDecrypter.Type, "Method decrypter (JIT) type"); AddTypeToBeRemoved(jitMethodsDecrypter.Type, "Method decrypter (JIT) type");
} }
if (memoryMethodsDecrypter != null) { if (memoryMethodsDecrypter != null) {
addModuleCctorInitCallToBeRemoved(memoryMethodsDecrypter.InitMethod); AddModuleCctorInitCallToBeRemoved(memoryMethodsDecrypter.InitMethod);
addTypeToBeRemoved(memoryMethodsDecrypter.Type, "Method decrypter (memory) type"); AddTypeToBeRemoved(memoryMethodsDecrypter.Type, "Method decrypter (memory) type");
} }
if (options.RemoveAntiDebug && antiDebugger != null) { if (options.RemoveAntiDebug && antiDebugger != null) {
addModuleCctorInitCallToBeRemoved(antiDebugger.InitMethod); AddModuleCctorInitCallToBeRemoved(antiDebugger.InitMethod);
addTypeToBeRemoved(antiDebugger.Type, "Anti debugger type"); AddTypeToBeRemoved(antiDebugger.Type, "Anti debugger type");
if (antiDebugger.Type == DotNetUtils.getModuleType(module)) if (antiDebugger.Type == DotNetUtils.GetModuleType(module))
addMethodToBeRemoved(antiDebugger.InitMethod, "Anti debugger method"); AddMethodToBeRemoved(antiDebugger.InitMethod, "Anti debugger method");
} }
if (options.RemoveAntiDump && antiDumping != null) { if (options.RemoveAntiDump && antiDumping != null) {
addModuleCctorInitCallToBeRemoved(antiDumping.InitMethod); AddModuleCctorInitCallToBeRemoved(antiDumping.InitMethod);
addTypeToBeRemoved(antiDumping.Type, "Anti dumping type"); AddTypeToBeRemoved(antiDumping.Type, "Anti dumping type");
} }
if (proxyCallFixer != null) if (proxyCallFixer != null)
proxyCallFixer.find(); proxyCallFixer.Find();
removeInvalidResources(); RemoveInvalidResources();
dumpEmbeddedAssemblies(); DumpEmbeddedAssemblies();
startedDeobfuscating = true; startedDeobfuscating = true;
} }
void dumpEmbeddedAssemblies() { void DumpEmbeddedAssemblies() {
if (mainAsmInfo != null) { if (mainAsmInfo != null) {
var asm = module.Assembly; var asm = module.Assembly;
var name = (asm == null ? module.Name : asm.Name).String; var name = (asm == null ? module.Name : asm.Name).String;
DeobfuscatedFile.createAssemblyFile(mainAsmInfo.data, name + "_real", mainAsmInfo.extension); DeobfuscatedFile.CreateAssemblyFile(mainAsmInfo.data, name + "_real", mainAsmInfo.extension);
addResourceToBeRemoved(mainAsmInfo.resource, string.Format("Embedded assembly: {0}", mainAsmInfo.asmFullName)); AddResourceToBeRemoved(mainAsmInfo.resource, string.Format("Embedded assembly: {0}", mainAsmInfo.asmFullName));
} }
foreach (var info in embeddedAssemblyInfos) { foreach (var info in embeddedAssemblyInfos) {
if (module.Assembly == null || info.asmFullName != module.Assembly.FullName) if (module.Assembly == null || info.asmFullName != module.Assembly.FullName)
DeobfuscatedFile.createAssemblyFile(info.data, info.asmSimpleName, info.extension); DeobfuscatedFile.CreateAssemblyFile(info.data, info.asmSimpleName, info.extension);
addResourceToBeRemoved(info.resource, string.Format("Embedded assembly: {0}", info.asmFullName)); AddResourceToBeRemoved(info.resource, string.Format("Embedded assembly: {0}", info.asmFullName));
} }
embeddedAssemblyInfos.Clear(); embeddedAssemblyInfos.Clear();
} }
void removeInvalidResources() { void RemoveInvalidResources() {
foreach (var rsrc in module.Resources) { foreach (var rsrc in module.Resources) {
var resource = rsrc as EmbeddedResource; var resource = rsrc as EmbeddedResource;
if (resource == null) if (resource == null)
continue; continue;
if (resource.Offset != 0xFFFFFFFF) if (resource.Offset != 0xFFFFFFFF)
continue; continue;
addResourceToBeRemoved(resource, "Invalid resource"); AddResourceToBeRemoved(resource, "Invalid resource");
} }
} }
bool hasInitializedStringDecrypter = false; bool hasInitializedStringDecrypter = false;
void initializeStringDecrypter() { void InitializeStringDecrypter() {
if (hasInitializedStringDecrypter || (stringDecrypter== null || !stringDecrypter.Detected)) if (hasInitializedStringDecrypter || (stringDecrypter== null || !stringDecrypter.Detected))
return; return;
hasInitializedStringDecrypter = true; hasInitializedStringDecrypter = true;
decryptResources(); DecryptResources();
stringDecrypter.initialize(); stringDecrypter.Initialize();
staticStringInliner.add(stringDecrypter.Method, (method, gim, args) => stringDecrypter.decrypt(staticStringInliner.Method, (int)args[0])); staticStringInliner.Add(stringDecrypter.Method, (method, gim, args) => stringDecrypter.Decrypt(staticStringInliner.Method, (int)args[0]));
DeobfuscatedFile.stringDecryptersAdded(); DeobfuscatedFile.StringDecryptersAdded();
} }
bool hasInitializedConstantsDecrypter = false; bool hasInitializedConstantsDecrypter = false;
void initializeConstantsDecrypterV18() { void InitializeConstantsDecrypterV18() {
if (hasInitializedConstantsDecrypter || (constantsDecrypterV18 == null || !constantsDecrypterV18.Detected)) if (hasInitializedConstantsDecrypter || (constantsDecrypterV18 == null || !constantsDecrypterV18.Detected))
return; return;
hasInitializedConstantsDecrypter = true; hasInitializedConstantsDecrypter = true;
decryptResources(); DecryptResources();
constantsDecrypterV18.initialize(); constantsDecrypterV18.Initialize();
int32ValueInliner = new Int32ValueInliner(); int32ValueInliner = new Int32ValueInliner();
int64ValueInliner = new Int64ValueInliner(); int64ValueInliner = new Int64ValueInliner();
singleValueInliner = new SingleValueInliner(); singleValueInliner = new SingleValueInliner();
doubleValueInliner = new DoubleValueInliner(); doubleValueInliner = new DoubleValueInliner();
foreach (var info in constantsDecrypterV18.Decrypters) { foreach (var info in constantsDecrypterV18.Decrypters) {
staticStringInliner.add(info.method, (method, gim, args) => constantsDecrypterV18.decryptString(method, gim, (uint)args[0], (ulong)args[1])); staticStringInliner.Add(info.method, (method, gim, args) => constantsDecrypterV18.DecryptString(method, gim, (uint)args[0], (ulong)args[1]));
int32ValueInliner.add(info.method, (method, gim, args) => constantsDecrypterV18.decryptInt32(method, gim, (uint)args[0], (ulong)args[1])); int32ValueInliner.Add(info.method, (method, gim, args) => constantsDecrypterV18.DecryptInt32(method, gim, (uint)args[0], (ulong)args[1]));
int64ValueInliner.add(info.method, (method, gim, args) => constantsDecrypterV18.decryptInt64(method, gim, (uint)args[0], (ulong)args[1])); int64ValueInliner.Add(info.method, (method, gim, args) => constantsDecrypterV18.DecryptInt64(method, gim, (uint)args[0], (ulong)args[1]));
singleValueInliner.add(info.method, (method, gim, args) => constantsDecrypterV18.decryptSingle(method, gim, (uint)args[0], (ulong)args[1])); singleValueInliner.Add(info.method, (method, gim, args) => constantsDecrypterV18.DecryptSingle(method, gim, (uint)args[0], (ulong)args[1]));
doubleValueInliner.add(info.method, (method, gim, args) => constantsDecrypterV18.decryptDouble(method, gim, (uint)args[0], (ulong)args[1])); doubleValueInliner.Add(info.method, (method, gim, args) => constantsDecrypterV18.DecryptDouble(method, gim, (uint)args[0], (ulong)args[1]));
} }
DeobfuscatedFile.stringDecryptersAdded(); DeobfuscatedFile.StringDecryptersAdded();
addTypesToBeRemoved(constantsDecrypterV18.Types, "Constants decrypter type"); AddTypesToBeRemoved(constantsDecrypterV18.Types, "Constants decrypter type");
addFieldsToBeRemoved(constantsDecrypterV18.Fields, "Constants decrypter field"); AddFieldsToBeRemoved(constantsDecrypterV18.Fields, "Constants decrypter field");
addMethodToBeRemoved(constantsDecrypterV18.NativeMethod, "Constants decrypter native method"); AddMethodToBeRemoved(constantsDecrypterV18.NativeMethod, "Constants decrypter native method");
addResourceToBeRemoved(constantsDecrypterV18.Resource, "Encrypted constants"); AddResourceToBeRemoved(constantsDecrypterV18.Resource, "Encrypted constants");
} }
bool hasInitializedConstantsDecrypter15 = false; bool hasInitializedConstantsDecrypter15 = false;
void initializeConstantsDecrypterV15() { void InitializeConstantsDecrypterV15() {
initialize(constantsDecrypterV15, ref hasInitializedConstantsDecrypter15); Initialize(constantsDecrypterV15, ref hasInitializedConstantsDecrypter15);
} }
bool hasInitializedConstantsDecrypter17 = false; bool hasInitializedConstantsDecrypter17 = false;
void initializeConstantsDecrypterV17() { void InitializeConstantsDecrypterV17() {
initialize(constantsDecrypterV17, ref hasInitializedConstantsDecrypter17); Initialize(constantsDecrypterV17, ref hasInitializedConstantsDecrypter17);
} }
void initialize(ConstantsDecrypterBase constDecrypter, ref bool hasInitialized) { void Initialize(ConstantsDecrypterBase constDecrypter, ref bool hasInitialized) {
if (hasInitialized || (constDecrypter == null || !constDecrypter.Detected)) if (hasInitialized || (constDecrypter == null || !constDecrypter.Detected))
return; return;
hasInitializedConstantsDecrypter15 = true; hasInitializedConstantsDecrypter15 = true;
decryptResources(); DecryptResources();
constDecrypter.initialize(); constDecrypter.Initialize();
int32ValueInliner = new Int32ValueInliner(); int32ValueInliner = new Int32ValueInliner();
int64ValueInliner = new Int64ValueInliner(); int64ValueInliner = new Int64ValueInliner();
singleValueInliner = new SingleValueInliner(); singleValueInliner = new SingleValueInliner();
doubleValueInliner = new DoubleValueInliner(); doubleValueInliner = new DoubleValueInliner();
foreach (var info in constDecrypter.DecrypterInfos) { foreach (var info in constDecrypter.DecrypterInfos) {
staticStringInliner.add(info.decryptMethod, (method, gim, args) => constDecrypter.decryptString(staticStringInliner.Method, method, args)); staticStringInliner.Add(info.decryptMethod, (method, gim, args) => constDecrypter.DecryptString(staticStringInliner.Method, method, args));
int32ValueInliner.add(info.decryptMethod, (method, gim, args) => constDecrypter.decryptInt32(int32ValueInliner.Method, method, args)); int32ValueInliner.Add(info.decryptMethod, (method, gim, args) => constDecrypter.DecryptInt32(int32ValueInliner.Method, method, args));
int64ValueInliner.add(info.decryptMethod, (method, gim, args) => constDecrypter.decryptInt64(int64ValueInliner.Method, method, args)); int64ValueInliner.Add(info.decryptMethod, (method, gim, args) => constDecrypter.DecryptInt64(int64ValueInliner.Method, method, args));
singleValueInliner.add(info.decryptMethod, (method, gim, args) => constDecrypter.decryptSingle(singleValueInliner.Method, method, args)); singleValueInliner.Add(info.decryptMethod, (method, gim, args) => constDecrypter.DecryptSingle(singleValueInliner.Method, method, args));
doubleValueInliner.add(info.decryptMethod, (method, gim, args) => constDecrypter.decryptDouble(doubleValueInliner.Method, method, args)); doubleValueInliner.Add(info.decryptMethod, (method, gim, args) => constDecrypter.DecryptDouble(doubleValueInliner.Method, method, args));
} }
int32ValueInliner.RemoveUnbox = true; int32ValueInliner.RemoveUnbox = true;
int64ValueInliner.RemoveUnbox = true; int64ValueInliner.RemoveUnbox = true;
singleValueInliner.RemoveUnbox = true; singleValueInliner.RemoveUnbox = true;
doubleValueInliner.RemoveUnbox = true; doubleValueInliner.RemoveUnbox = true;
DeobfuscatedFile.stringDecryptersAdded(); DeobfuscatedFile.StringDecryptersAdded();
addFieldsToBeRemoved(constDecrypter.Fields, "Constants decrypter field"); AddFieldsToBeRemoved(constDecrypter.Fields, "Constants decrypter field");
var moduleType = DotNetUtils.getModuleType(module); var moduleType = DotNetUtils.GetModuleType(module);
foreach (var info in constDecrypter.DecrypterInfos) { foreach (var info in constDecrypter.DecrypterInfos) {
if (info.decryptMethod.DeclaringType == moduleType) if (info.decryptMethod.DeclaringType == moduleType)
addMethodToBeRemoved(info.decryptMethod, "Constants decrypter method"); AddMethodToBeRemoved(info.decryptMethod, "Constants decrypter method");
else else
addTypeToBeRemoved(info.decryptMethod.DeclaringType, "Constants decrypter type"); AddTypeToBeRemoved(info.decryptMethod.DeclaringType, "Constants decrypter type");
} }
addMethodToBeRemoved(constDecrypter.NativeMethod, "Constants decrypter native method"); AddMethodToBeRemoved(constDecrypter.NativeMethod, "Constants decrypter native method");
addResourceToBeRemoved(constDecrypter.Resource, "Encrypted constants"); AddResourceToBeRemoved(constDecrypter.Resource, "Encrypted constants");
} }
void decryptResources() { void DecryptResources() {
var rsrc = resourceDecrypter.mergeResources(); var rsrc = resourceDecrypter.MergeResources();
if (rsrc == null) if (rsrc == null)
return; return;
addResourceToBeRemoved(rsrc, "Encrypted resources"); AddResourceToBeRemoved(rsrc, "Encrypted resources");
addMethodToBeRemoved(resourceDecrypter.Handler, "Resource decrypter handler"); AddMethodToBeRemoved(resourceDecrypter.Handler, "Resource decrypter handler");
addFieldsToBeRemoved(resourceDecrypter.Fields, "Resource decrypter field"); AddFieldsToBeRemoved(resourceDecrypter.Fields, "Resource decrypter field");
} }
void removeObfuscatorAttribute() { void RemoveObfuscatorAttribute() {
foreach (var type in module.Types) { foreach (var type in module.Types) {
if (type.FullName == "ConfusedByAttribute") { if (type.FullName == "ConfusedByAttribute") {
setConfuserVersion(type); SetConfuserVersion(type);
addAttributeToBeRemoved(type, "Obfuscator attribute"); AddAttributeToBeRemoved(type, "Obfuscator attribute");
break; break;
} }
} }
} }
void setConfuserVersion(TypeDef type) { void SetConfuserVersion(TypeDef type) {
var s = DotNetUtils.getCustomArgAsString(getModuleAttribute(type) ?? getAssemblyAttribute(type), 0); var s = DotNetUtils.GetCustomArgAsString(GetModuleAttribute(type) ?? GetAssemblyAttribute(type), 0);
if (s == null) if (s == null)
return; return;
var val = System.Text.RegularExpressions.Regex.Match(s, @"^Confuser v(\d+)\.(\d+)\.(\d+)\.(\d+)$"); var val = System.Text.RegularExpressions.Regex.Match(s, @"^Confuser v(\d+)\.(\d+)\.(\d+)\.(\d+)$");
@ -541,42 +541,42 @@ namespace de4dot.code.deobfuscators.Confuser {
int.Parse(val.Groups[4].ToString())); int.Parse(val.Groups[4].ToString()));
} }
public override void deobfuscateMethodEnd(Blocks blocks) { public override void DeobfuscateMethodEnd(Blocks blocks) {
if (proxyCallFixer != null) if (proxyCallFixer != null)
proxyCallFixer.deobfuscate(blocks); proxyCallFixer.Deobfuscate(blocks);
resourceDecrypter.deobfuscate(blocks); resourceDecrypter.Deobfuscate(blocks);
unpacker.deobfuscate(blocks); unpacker.Deobfuscate(blocks);
if (int32ValueInliner != null) { if (int32ValueInliner != null) {
int32ValueInliner.decrypt(blocks); int32ValueInliner.Decrypt(blocks);
int64ValueInliner.decrypt(blocks); int64ValueInliner.Decrypt(blocks);
singleValueInliner.decrypt(blocks); singleValueInliner.Decrypt(blocks);
doubleValueInliner.decrypt(blocks); doubleValueInliner.Decrypt(blocks);
} }
base.deobfuscateMethodEnd(blocks); base.DeobfuscateMethodEnd(blocks);
} }
public override void deobfuscateEnd() { public override void DeobfuscateEnd() {
if (proxyCallFixer != null) { if (proxyCallFixer != null) {
if (removeProxyDelegates(proxyCallFixer)) if (RemoveProxyDelegates(proxyCallFixer))
addFieldsToBeRemoved(proxyCallFixer.Fields, "Proxy delegate instance field"); AddFieldsToBeRemoved(proxyCallFixer.Fields, "Proxy delegate instance field");
proxyCallFixer.cleanUp(); proxyCallFixer.CleanUp();
} }
if (constantsDecrypterV18 != null) if (constantsDecrypterV18 != null)
constantsDecrypterV18.cleanUp(); constantsDecrypterV18.CleanUp();
if (CanRemoveStringDecrypterType) { if (CanRemoveStringDecrypterType) {
if (stringDecrypter != null) { if (stringDecrypter != null) {
addMethodToBeRemoved(stringDecrypter.Method, "String decrypter method"); AddMethodToBeRemoved(stringDecrypter.Method, "String decrypter method");
addResourceToBeRemoved(stringDecrypter.Resource, "Encrypted strings"); AddResourceToBeRemoved(stringDecrypter.Resource, "Encrypted strings");
} }
} }
module.IsILOnly = true; module.IsILOnly = true;
base.deobfuscateEnd(); base.DeobfuscateEnd();
} }
public override IEnumerable<int> getStringDecrypterMethods() { public override IEnumerable<int> GetStringDecrypterMethods() {
var list = new List<int>(); var list = new List<int>();
if (stringDecrypter != null && stringDecrypter.Method != null) if (stringDecrypter != null && stringDecrypter.Method != null)
list.Add(stringDecrypter.Method.MDToken.ToInt32()); list.Add(stringDecrypter.Method.MDToken.ToInt32());

View File

@ -19,6 +19,6 @@
namespace de4dot.code.deobfuscators.Confuser { namespace de4dot.code.deobfuscators.Confuser {
interface IVersionProvider { interface IVersionProvider {
bool getRevisionRange(out int minRev, out int maxRev); bool GetRevisionRange(out int minRev, out int maxRev);
} }
} }

View File

@ -65,15 +65,15 @@ namespace de4dot.code.deobfuscators.Confuser {
this.version = other.version; this.version = other.version;
} }
protected override bool checkType(TypeDef type, MethodDef initMethod) { protected override bool CheckType(TypeDef type, MethodDef initMethod) {
if (type == null) if (type == null)
return false; return false;
compileMethod = findCompileMethod(type); compileMethod = FindCompileMethod(type);
if (compileMethod == null) if (compileMethod == null)
return false; return false;
decryptMethod = findDecryptMethod(type); decryptMethod = FindDecryptMethod(type);
if (decryptMethod == null) if (decryptMethod == null)
return false; return false;
@ -89,7 +89,7 @@ namespace de4dot.code.deobfuscators.Confuser {
break; break;
case 38: case 38:
switch (countInt32s(compileMethod, 0xFF)) { switch (CountInt32s(compileMethod, 0xFF)) {
case 2: theVersion = ConfuserVersion.v17_r73477; break; case 2: theVersion = ConfuserVersion.v17_r73477; break;
case 4: theVersion = ConfuserVersion.v17_r73479; break; case 4: theVersion = ConfuserVersion.v17_r73479; break;
default: return false; default: return false;
@ -97,20 +97,20 @@ namespace de4dot.code.deobfuscators.Confuser {
break; break;
case 39: case 39:
if (!DotNetUtils.callsMethod(initMethod, "System.Void System.Console::WriteLine(System.Char)")) { if (!DotNetUtils.CallsMethod(initMethod, "System.Void System.Console::WriteLine(System.Char)")) {
if (DotNetUtils.callsMethod(decryptMethod, "System.Security.Cryptography.Rijndael System.Security.Cryptography.Rijndael::Create()")) if (DotNetUtils.CallsMethod(decryptMethod, "System.Security.Cryptography.Rijndael System.Security.Cryptography.Rijndael::Create()"))
theVersion = ConfuserVersion.v17_r74021; theVersion = ConfuserVersion.v17_r74021;
else else
theVersion = ConfuserVersion.v18_r75291; theVersion = ConfuserVersion.v18_r75291;
} }
else if (DotNetUtils.callsMethod(decryptMethod, "System.Security.Cryptography.Rijndael System.Security.Cryptography.Rijndael::Create()")) else if (DotNetUtils.CallsMethod(decryptMethod, "System.Security.Cryptography.Rijndael System.Security.Cryptography.Rijndael::Create()"))
theVersion = ConfuserVersion.v18_r75257; theVersion = ConfuserVersion.v18_r75257;
else else
theVersion = ConfuserVersion.v18_r75288; theVersion = ConfuserVersion.v18_r75288;
break; break;
case 27: case 27:
if (DotNetUtils.callsMethod(initMethod, "System.Int32 System.String::get_Length()")) if (DotNetUtils.CallsMethod(initMethod, "System.Int32 System.String::get_Length()"))
theVersion = ConfuserVersion.v18_r75402; theVersion = ConfuserVersion.v18_r75402;
else else
theVersion = ConfuserVersion.v19_r75725; theVersion = ConfuserVersion.v19_r75725;
@ -121,7 +121,7 @@ namespace de4dot.code.deobfuscators.Confuser {
} }
if (theVersion >= ConfuserVersion.v17_r73477) { if (theVersion >= ConfuserVersion.v17_r73477) {
hookConstructStr = findHookConstructStr(type); hookConstructStr = FindHookConstructStr(type);
if (hookConstructStr == null) if (hookConstructStr == null)
return false; return false;
} }
@ -130,7 +130,7 @@ namespace de4dot.code.deobfuscators.Confuser {
return true; return true;
} }
static int countInt32s(MethodDef method, int val) { static int CountInt32s(MethodDef method, int val) {
int count = 0; int count = 0;
foreach (var instr in method.Body.Instructions) { foreach (var instr in method.Body.Instructions) {
if (!instr.IsLdcI4()) if (!instr.IsLdcI4())
@ -141,7 +141,7 @@ namespace de4dot.code.deobfuscators.Confuser {
return count; return count;
} }
static MethodDef findCompileMethod(TypeDef type) { static MethodDef FindCompileMethod(TypeDef type) {
foreach (var method in type.Methods) { foreach (var method in type.Methods) {
if (!method.IsStatic || method.Body == null) if (!method.IsStatic || method.Body == null)
continue; continue;
@ -164,7 +164,7 @@ namespace de4dot.code.deobfuscators.Confuser {
return null; return null;
} }
static MethodDef findHookConstructStr(TypeDef type) { static MethodDef FindHookConstructStr(TypeDef type) {
foreach (var nested in type.NestedTypes) { foreach (var nested in type.NestedTypes) {
if (nested.Fields.Count != 8 && nested.Fields.Count != 10) if (nested.Fields.Count != 8 && nested.Fields.Count != 10)
continue; continue;
@ -189,79 +189,79 @@ namespace de4dot.code.deobfuscators.Confuser {
return null; return null;
} }
public void initialize() { public void Initialize() {
if (initMethod == null) if (initMethod == null)
return; return;
if (!initializeKeys()) if (!InitializeKeys())
throw new ApplicationException("Could not find all decryption keys"); throw new ApplicationException("Could not find all decryption keys");
if (!initializeMethodDataIndexes(compileMethod)) if (!InitializeMethodDataIndexes(compileMethod))
throw new ApplicationException("Could not find MethodData indexes"); throw new ApplicationException("Could not find MethodData indexes");
} }
bool initializeKeys() { bool InitializeKeys() {
switch (version) { switch (version) {
case ConfuserVersion.v17_r73404: return initializeKeys_v17_r73404(); case ConfuserVersion.v17_r73404: return InitializeKeys_v17_r73404();
case ConfuserVersion.v17_r73430: return initializeKeys_v17_r73404(); case ConfuserVersion.v17_r73430: return InitializeKeys_v17_r73404();
case ConfuserVersion.v17_r73477: return initializeKeys_v17_r73404(); case ConfuserVersion.v17_r73477: return InitializeKeys_v17_r73404();
case ConfuserVersion.v17_r73479: return initializeKeys_v17_r73404(); case ConfuserVersion.v17_r73479: return InitializeKeys_v17_r73404();
case ConfuserVersion.v17_r74021: return initializeKeys_v17_r73404(); case ConfuserVersion.v17_r74021: return InitializeKeys_v17_r73404();
case ConfuserVersion.v18_r75257: return initializeKeys_v17_r73404(); case ConfuserVersion.v18_r75257: return InitializeKeys_v17_r73404();
case ConfuserVersion.v18_r75288: return initializeKeys_v17_r73404(); case ConfuserVersion.v18_r75288: return InitializeKeys_v17_r73404();
case ConfuserVersion.v18_r75291: return initializeKeys_v17_r73404(); case ConfuserVersion.v18_r75291: return InitializeKeys_v17_r73404();
case ConfuserVersion.v18_r75402: return initializeKeys_v18_r75402(); case ConfuserVersion.v18_r75402: return InitializeKeys_v18_r75402();
case ConfuserVersion.v19_r75725: return initializeKeys_v18_r75402(); case ConfuserVersion.v19_r75725: return InitializeKeys_v18_r75402();
default: throw new ApplicationException("Invalid version"); default: throw new ApplicationException("Invalid version");
} }
} }
bool initializeKeys_v17_r73404() { bool InitializeKeys_v17_r73404() {
simpleDeobfuscator.deobfuscate(initMethod); simpleDeobfuscator.Deobfuscate(initMethod);
if (!findLKey0(initMethod, out lkey0)) if (!FindLKey0(initMethod, out lkey0))
return false; return false;
if (!findKey0_v16_r71742(initMethod, out key0)) if (!FindKey0_v16_r71742(initMethod, out key0))
return false; return false;
if (!findKey1(initMethod, out key1)) if (!FindKey1(initMethod, out key1))
return false; return false;
if (!findKey2Key3(initMethod, out key2, out key3)) if (!FindKey2Key3(initMethod, out key2, out key3))
return false; return false;
simpleDeobfuscator.deobfuscate(decryptMethod); simpleDeobfuscator.Deobfuscate(decryptMethod);
if (!findKey6(decryptMethod, out key6)) if (!FindKey6(decryptMethod, out key6))
return false; return false;
return true; return true;
} }
bool initializeKeys_v18_r75402() { bool InitializeKeys_v18_r75402() {
simpleDeobfuscator.deobfuscate(initMethod); simpleDeobfuscator.Deobfuscate(initMethod);
if (!findLKey0(initMethod, out lkey0)) if (!FindLKey0(initMethod, out lkey0))
return false; return false;
if (!findKey0_v16_r71742(initMethod, out key0)) if (!FindKey0_v16_r71742(initMethod, out key0))
return false; return false;
if (!findKey1(initMethod, out key1)) if (!FindKey1(initMethod, out key1))
return false; return false;
if (!findKey2Key3(initMethod, out key2, out key3)) if (!FindKey2Key3(initMethod, out key2, out key3))
return false; return false;
simpleDeobfuscator.deobfuscate(compileMethod); simpleDeobfuscator.Deobfuscate(compileMethod);
if (!findKey4(compileMethod, out key4)) if (!FindKey4(compileMethod, out key4))
return false; return false;
simpleDeobfuscator.deobfuscate(hookConstructStr); simpleDeobfuscator.Deobfuscate(hookConstructStr);
if (!findKey5(hookConstructStr, out key5)) if (!FindKey5(hookConstructStr, out key5))
return false; return false;
simpleDeobfuscator.deobfuscate(decryptMethod); simpleDeobfuscator.Deobfuscate(decryptMethod);
if (!findKey6(decryptMethod, out key6)) if (!FindKey6(decryptMethod, out key6))
return false; return false;
return true; return true;
} }
static bool findKey4(MethodDef method, out uint key) { static bool FindKey4(MethodDef method, out uint key) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int index = 0; index < instrs.Count; index++) { for (int index = 0; index < instrs.Count; index++) {
index = ConfuserUtils.findCallMethod(instrs, index, Code.Call, "System.Void System.Runtime.InteropServices.Marshal::Copy(System.Byte[],System.Int32,System.IntPtr,System.Int32)"); index = ConfuserUtils.FindCallMethod(instrs, index, Code.Call, "System.Void System.Runtime.InteropServices.Marshal::Copy(System.Byte[],System.Int32,System.IntPtr,System.Int32)");
if (index < 0) if (index < 0)
break; break;
if (index + 2 >= instrs.Count) if (index + 2 >= instrs.Count)
@ -280,7 +280,7 @@ namespace de4dot.code.deobfuscators.Confuser {
return false; return false;
} }
static bool findKey5(MethodDef method, out uint key) { static bool FindKey5(MethodDef method, out uint key) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i + 4 < instrs.Count; i++) { for (int i = 0; i + 4 < instrs.Count; i++) {
int index = i; int index = i;
@ -305,50 +305,50 @@ namespace de4dot.code.deobfuscators.Confuser {
return false; return false;
} }
bool initializeMethodDataIndexes(MethodDef compileMethod) { bool InitializeMethodDataIndexes(MethodDef compileMethod) {
switch (version) { switch (version) {
case ConfuserVersion.v17_r73404: return true; case ConfuserVersion.v17_r73404: return true;
case ConfuserVersion.v17_r73430: return true; case ConfuserVersion.v17_r73430: return true;
case ConfuserVersion.v17_r73477: return initializeMethodDataIndexes_v17_r73477(compileMethod); case ConfuserVersion.v17_r73477: return InitializeMethodDataIndexes_v17_r73477(compileMethod);
case ConfuserVersion.v17_r73479: return initializeMethodDataIndexes_v17_r73477(compileMethod); case ConfuserVersion.v17_r73479: return InitializeMethodDataIndexes_v17_r73477(compileMethod);
case ConfuserVersion.v17_r74021: return initializeMethodDataIndexes_v17_r73477(compileMethod); case ConfuserVersion.v17_r74021: return InitializeMethodDataIndexes_v17_r73477(compileMethod);
case ConfuserVersion.v18_r75257: return initializeMethodDataIndexes_v17_r73477(compileMethod); case ConfuserVersion.v18_r75257: return InitializeMethodDataIndexes_v17_r73477(compileMethod);
case ConfuserVersion.v18_r75288: return initializeMethodDataIndexes_v17_r73477(compileMethod); case ConfuserVersion.v18_r75288: return InitializeMethodDataIndexes_v17_r73477(compileMethod);
case ConfuserVersion.v18_r75291: return initializeMethodDataIndexes_v17_r73477(compileMethod); case ConfuserVersion.v18_r75291: return InitializeMethodDataIndexes_v17_r73477(compileMethod);
case ConfuserVersion.v18_r75402: return initializeMethodDataIndexes_v17_r73477(compileMethod); case ConfuserVersion.v18_r75402: return InitializeMethodDataIndexes_v17_r73477(compileMethod);
case ConfuserVersion.v19_r75725: return initializeMethodDataIndexes_v17_r73477(compileMethod); case ConfuserVersion.v19_r75725: return InitializeMethodDataIndexes_v17_r73477(compileMethod);
default: throw new ApplicationException("Invalid version"); default: throw new ApplicationException("Invalid version");
} }
} }
bool initializeMethodDataIndexes_v17_r73477(MethodDef method) { bool InitializeMethodDataIndexes_v17_r73477(MethodDef method) {
simpleDeobfuscator.deobfuscate(method); simpleDeobfuscator.Deobfuscate(method);
var methodDataType = findFirstThreeIndexes(method, out methodDataIndexes.maxStack, out methodDataIndexes.ehs, out methodDataIndexes.options); var methodDataType = FindFirstThreeIndexes(method, out methodDataIndexes.maxStack, out methodDataIndexes.ehs, out methodDataIndexes.options);
if (methodDataType == null) if (methodDataType == null)
return false; return false;
if (!findLocalVarSigTokIndex(method, methodDataType, out methodDataIndexes.localVarSigTok)) if (!FindLocalVarSigTokIndex(method, methodDataType, out methodDataIndexes.localVarSigTok))
return false; return false;
if (!findCodeSizeIndex(method, methodDataType, out methodDataIndexes.codeSize)) if (!FindCodeSizeIndex(method, methodDataType, out methodDataIndexes.codeSize))
return false; return false;
return true; return true;
} }
static TypeDef findFirstThreeIndexes(MethodDef method, out int maxStackIndex, out int ehsIndex, out int optionsIndex) { static TypeDef FindFirstThreeIndexes(MethodDef method, out int maxStackIndex, out int ehsIndex, out int optionsIndex) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count; i++) { for (int i = 0; i < instrs.Count; i++) {
int index1 = findLdfldStind(instrs, i, false, true); int index1 = FindLdfldStind(instrs, i, false, true);
if (index1 < 0) if (index1 < 0)
break; break;
i = index1; i = index1;
int index2 = findLdfldStind(instrs, index1 + 1, true, true); int index2 = FindLdfldStind(instrs, index1 + 1, true, true);
if (index2 < 0) if (index2 < 0)
continue; continue;
int index3 = findLdfldStind(instrs, index2 + 1, true, false); int index3 = FindLdfldStind(instrs, index2 + 1, true, false);
if (index3 < 0) if (index3 < 0)
continue; continue;
@ -360,9 +360,9 @@ namespace de4dot.code.deobfuscators.Confuser {
if (field1.DeclaringType != field2.DeclaringType || field1.DeclaringType != field3.DeclaringType) if (field1.DeclaringType != field2.DeclaringType || field1.DeclaringType != field3.DeclaringType)
continue; continue;
maxStackIndex = getInstanceFieldIndex(field1); maxStackIndex = GetInstanceFieldIndex(field1);
ehsIndex = getInstanceFieldIndex(field2); ehsIndex = GetInstanceFieldIndex(field2);
optionsIndex = getInstanceFieldIndex(field3); optionsIndex = GetInstanceFieldIndex(field3);
return field1.DeclaringType; return field1.DeclaringType;
} }
@ -372,7 +372,7 @@ namespace de4dot.code.deobfuscators.Confuser {
return null; return null;
} }
static bool findLocalVarSigTokIndex(MethodDef method, TypeDef methodDataType, out int localVarSigTokIndex) { static bool FindLocalVarSigTokIndex(MethodDef method, TypeDef methodDataType, out int localVarSigTokIndex) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count - 1; i++) { for (int i = 0; i < instrs.Count - 1; i++) {
var ldfld = instrs[i]; var ldfld = instrs[i];
@ -389,7 +389,7 @@ namespace de4dot.code.deobfuscators.Confuser {
if (calledMethod == null || !calledMethod.IsStatic || calledMethod.DeclaringType != method.DeclaringType) if (calledMethod == null || !calledMethod.IsStatic || calledMethod.DeclaringType != method.DeclaringType)
continue; continue;
localVarSigTokIndex = getInstanceFieldIndex(field); localVarSigTokIndex = GetInstanceFieldIndex(field);
return true; return true;
} }
@ -397,7 +397,7 @@ namespace de4dot.code.deobfuscators.Confuser {
return false; return false;
} }
static bool findCodeSizeIndex(MethodDef method, TypeDef methodDataType, out int codeSizeIndex) { static bool FindCodeSizeIndex(MethodDef method, TypeDef methodDataType, out int codeSizeIndex) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count - 1; i++) { for (int i = 0; i < instrs.Count - 1; i++) {
var ldfld = instrs[i]; var ldfld = instrs[i];
@ -410,7 +410,7 @@ namespace de4dot.code.deobfuscators.Confuser {
if (instrs[i+1].OpCode.Code != Code.Stfld) if (instrs[i+1].OpCode.Code != Code.Stfld)
continue; continue;
codeSizeIndex = getInstanceFieldIndex(field); codeSizeIndex = GetInstanceFieldIndex(field);
return true; return true;
} }
@ -418,7 +418,7 @@ namespace de4dot.code.deobfuscators.Confuser {
return false; return false;
} }
static int getInstanceFieldIndex(FieldDef field) { static int GetInstanceFieldIndex(FieldDef field) {
int i = 0; int i = 0;
foreach (var f in field.DeclaringType.Fields) { foreach (var f in field.DeclaringType.Fields) {
if (f.IsStatic) if (f.IsStatic)
@ -430,7 +430,7 @@ namespace de4dot.code.deobfuscators.Confuser {
throw new ApplicationException("Could not find field"); throw new ApplicationException("Could not find field");
} }
static int findLdfldStind(IList<Instruction> instrs, int index, bool onlyInBlock, bool checkStindi4) { static int FindLdfldStind(IList<Instruction> instrs, int index, bool onlyInBlock, bool checkStindi4) {
for (int i = index; i < instrs.Count - 1; i++) { for (int i = index; i < instrs.Count - 1; i++) {
var ldfld = instrs[i]; var ldfld = instrs[i];
if (onlyInBlock && ldfld.OpCode.FlowControl != FlowControl.Next) if (onlyInBlock && ldfld.OpCode.FlowControl != FlowControl.Next)
@ -448,106 +448,106 @@ namespace de4dot.code.deobfuscators.Confuser {
return -1; return -1;
} }
public bool decrypt(MyPEImage peImage, byte[] fileData, ref DumpedMethods dumpedMethods) { public bool Decrypt(MyPEImage peImage, byte[] fileData, ref DumpedMethods dumpedMethods) {
if (initMethod == null) if (initMethod == null)
return false; return false;
switch (version) { switch (version) {
case ConfuserVersion.v17_r73404: return decrypt_v17_r73404(peImage, fileData, ref dumpedMethods); case ConfuserVersion.v17_r73404: return Decrypt_v17_r73404(peImage, fileData, ref dumpedMethods);
case ConfuserVersion.v17_r73430: return decrypt_v17_r73404(peImage, fileData, ref dumpedMethods); case ConfuserVersion.v17_r73430: return Decrypt_v17_r73404(peImage, fileData, ref dumpedMethods);
case ConfuserVersion.v17_r73477: return decrypt_v17_r73477(peImage, fileData, ref dumpedMethods); case ConfuserVersion.v17_r73477: return Decrypt_v17_r73477(peImage, fileData, ref dumpedMethods);
case ConfuserVersion.v17_r73479: return decrypt_v17_r73479(peImage, fileData, ref dumpedMethods); case ConfuserVersion.v17_r73479: return Decrypt_v17_r73479(peImage, fileData, ref dumpedMethods);
case ConfuserVersion.v17_r74021: return decrypt_v17_r73479(peImage, fileData, ref dumpedMethods); case ConfuserVersion.v17_r74021: return Decrypt_v17_r73479(peImage, fileData, ref dumpedMethods);
case ConfuserVersion.v18_r75257: return decrypt_v17_r73479(peImage, fileData, ref dumpedMethods); case ConfuserVersion.v18_r75257: return Decrypt_v17_r73479(peImage, fileData, ref dumpedMethods);
case ConfuserVersion.v18_r75288: return decrypt_v17_r73479(peImage, fileData, ref dumpedMethods); case ConfuserVersion.v18_r75288: return Decrypt_v17_r73479(peImage, fileData, ref dumpedMethods);
case ConfuserVersion.v18_r75291: return decrypt_v17_r73479(peImage, fileData, ref dumpedMethods); case ConfuserVersion.v18_r75291: return Decrypt_v17_r73479(peImage, fileData, ref dumpedMethods);
case ConfuserVersion.v18_r75402: return decrypt_v18_r75402(peImage, fileData, ref dumpedMethods); case ConfuserVersion.v18_r75402: return Decrypt_v18_r75402(peImage, fileData, ref dumpedMethods);
case ConfuserVersion.v19_r75725: return decrypt_v18_r75402(peImage, fileData, ref dumpedMethods); case ConfuserVersion.v19_r75725: return Decrypt_v18_r75402(peImage, fileData, ref dumpedMethods);
default: throw new ApplicationException("Unknown version"); default: throw new ApplicationException("Unknown version");
} }
} }
bool decrypt_v17_r73404(MyPEImage peImage, byte[] fileData, ref DumpedMethods dumpedMethods) { bool Decrypt_v17_r73404(MyPEImage peImage, byte[] fileData, ref DumpedMethods dumpedMethods) {
methodsData = decryptMethodsData_v17_r73404(peImage); methodsData = DecryptMethodsData_v17_r73404(peImage);
dumpedMethods = decrypt_v17_r73404(peImage, fileData); dumpedMethods = Decrypt_v17_r73404(peImage, fileData);
return dumpedMethods != null; return dumpedMethods != null;
} }
DumpedMethods decrypt_v17_r73404(MyPEImage peImage, byte[] fileData) { DumpedMethods Decrypt_v17_r73404(MyPEImage peImage, byte[] fileData) {
var dumpedMethods = new DumpedMethods(); var dumpedMethods = new DumpedMethods();
var methodDef = peImage.DotNetFile.MetaData.TablesStream.MethodTable; var methodDef = peImage.DotNetFile.MetaData.TablesStream.MethodTable;
for (uint rid = 1; rid <= methodDef.Rows; rid++) { for (uint rid = 1; rid <= methodDef.Rows; rid++) {
var dm = new DumpedMethod(); var dm = new DumpedMethod();
peImage.readMethodTableRowTo(dm, rid); peImage.ReadMethodTableRowTo(dm, rid);
if (dm.mdRVA == 0) if (dm.mdRVA == 0)
continue; continue;
uint bodyOffset = peImage.rvaToOffset(dm.mdRVA); uint bodyOffset = peImage.RvaToOffset(dm.mdRVA);
if (!isEncryptedMethod(fileData, (int)bodyOffset)) if (!IsEncryptedMethod(fileData, (int)bodyOffset))
continue; continue;
int key = BitConverter.ToInt32(fileData, (int)bodyOffset + 6); int key = BitConverter.ToInt32(fileData, (int)bodyOffset + 6);
int mdOffs = BitConverter.ToInt32(fileData, (int)bodyOffset + 2) ^ key; int mdOffs = BitConverter.ToInt32(fileData, (int)bodyOffset + 2) ^ key;
int len = BitConverter.ToInt32(fileData, (int)bodyOffset + 11) ^ ~key; int len = BitConverter.ToInt32(fileData, (int)bodyOffset + 11) ^ ~key;
var codeData = decryptMethodData_v17_r73404(methodsData, mdOffs + 2, (uint)key, len); var codeData = DecryptMethodData_v17_r73404(methodsData, mdOffs + 2, (uint)key, len);
var reader = MemoryImageStream.Create(codeData); var reader = MemoryImageStream.Create(codeData);
var mbHeader = MethodBodyParser.parseMethodBody(reader, out dm.code, out dm.extraSections); var mbHeader = MethodBodyParser.ParseMethodBody(reader, out dm.code, out dm.extraSections);
if (reader.Position != reader.Length) if (reader.Position != reader.Length)
throw new ApplicationException("Invalid method data"); throw new ApplicationException("Invalid method data");
peImage.updateMethodHeaderInfo(dm, mbHeader); peImage.UpdateMethodHeaderInfo(dm, mbHeader);
dumpedMethods.add(dm); dumpedMethods.Add(dm);
} }
return dumpedMethods; return dumpedMethods;
} }
bool decrypt_v17_r73477(MyPEImage peImage, byte[] fileData, ref DumpedMethods dumpedMethods) { bool Decrypt_v17_r73477(MyPEImage peImage, byte[] fileData, ref DumpedMethods dumpedMethods) {
methodsData = decryptMethodsData_v17_r73404(peImage); methodsData = DecryptMethodsData_v17_r73404(peImage);
dumpedMethods = decrypt_v17_r73477(peImage, fileData); dumpedMethods = Decrypt_v17_r73477(peImage, fileData);
return dumpedMethods != null; return dumpedMethods != null;
} }
DumpedMethods decrypt_v17_r73477(MyPEImage peImage, byte[] fileData) { DumpedMethods Decrypt_v17_r73477(MyPEImage peImage, byte[] fileData) {
return decrypt(peImage, fileData, new DecryptMethodData_v17_r73477()); return Decrypt(peImage, fileData, new DecryptMethodData_v17_r73477());
} }
bool decrypt_v17_r73479(MyPEImage peImage, byte[] fileData, ref DumpedMethods dumpedMethods) { bool Decrypt_v17_r73479(MyPEImage peImage, byte[] fileData, ref DumpedMethods dumpedMethods) {
methodsData = decryptMethodsData_v17_r73404(peImage); methodsData = DecryptMethodsData_v17_r73404(peImage);
dumpedMethods = decrypt_v17_r73479(peImage, fileData); dumpedMethods = Decrypt_v17_r73479(peImage, fileData);
return dumpedMethods != null; return dumpedMethods != null;
} }
DumpedMethods decrypt_v17_r73479(MyPEImage peImage, byte[] fileData) { DumpedMethods Decrypt_v17_r73479(MyPEImage peImage, byte[] fileData) {
return decrypt(peImage, fileData, new DecryptMethodData_v17_r73479()); return Decrypt(peImage, fileData, new DecryptMethodData_v17_r73479());
} }
bool decrypt_v18_r75402(MyPEImage peImage, byte[] fileData, ref DumpedMethods dumpedMethods) { bool Decrypt_v18_r75402(MyPEImage peImage, byte[] fileData, ref DumpedMethods dumpedMethods) {
if (peImage.OptionalHeader.CheckSum == 0) if (peImage.OptionalHeader.CheckSum == 0)
return false; return false;
methodsData = decryptMethodsData_v17_r73404(peImage); methodsData = DecryptMethodsData_v17_r73404(peImage);
dumpedMethods = decrypt_v18_r75402(peImage, fileData); dumpedMethods = Decrypt_v18_r75402(peImage, fileData);
return dumpedMethods != null; return dumpedMethods != null;
} }
DumpedMethods decrypt_v18_r75402(MyPEImage peImage, byte[] fileData) { DumpedMethods Decrypt_v18_r75402(MyPEImage peImage, byte[] fileData) {
return decrypt(peImage, fileData, new DecryptMethodData_v18_r75402(this)); return Decrypt(peImage, fileData, new DecryptMethodData_v18_r75402(this));
} }
abstract class DecryptMethodData { abstract class DecryptMethodData {
public abstract void decrypt(byte[] fileData, int offset, uint k1, int size, out uint[] methodData, out byte[] codeData); public abstract void Decrypt(byte[] fileData, int offset, uint k1, int size, out uint[] methodData, out byte[] codeData);
public bool isCodeFollowedByExtraSections(uint options) { public bool IsCodeFollowedByExtraSections(uint options) {
return (options >> 8) == 0; return (options >> 8) == 0;
} }
} }
class DecryptMethodData_v17_r73477 : DecryptMethodData { class DecryptMethodData_v17_r73477 : DecryptMethodData {
public override void decrypt(byte[] fileData, int offset, uint k1, int size, out uint[] methodData, out byte[] codeData) { public override void Decrypt(byte[] fileData, int offset, uint k1, int size, out uint[] methodData, out byte[] codeData) {
var data = new byte[size]; var data = new byte[size];
Array.Copy(fileData, offset, data, 0, data.Length); Array.Copy(fileData, offset, data, 0, data.Length);
var key = BitConverter.GetBytes(k1); var key = BitConverter.GetBytes(k1);
@ -562,7 +562,7 @@ namespace de4dot.code.deobfuscators.Confuser {
} }
class DecryptMethodData_v17_r73479 : DecryptMethodData { class DecryptMethodData_v17_r73479 : DecryptMethodData {
public override void decrypt(byte[] fileData, int offset, uint k1, int size, out uint[] methodData, out byte[] codeData) { public override void Decrypt(byte[] fileData, int offset, uint k1, int size, out uint[] methodData, out byte[] codeData) {
var data = new byte[size]; var data = new byte[size];
Array.Copy(fileData, offset, data, 0, data.Length); Array.Copy(fileData, offset, data, 0, data.Length);
uint k = k1; uint k = k1;
@ -585,7 +585,7 @@ namespace de4dot.code.deobfuscators.Confuser {
this.jitDecrypter = jitDecrypter; this.jitDecrypter = jitDecrypter;
} }
public override void decrypt(byte[] fileData, int offset, uint k1, int size, out uint[] methodData, out byte[] codeData) { public override void Decrypt(byte[] fileData, int offset, uint k1, int size, out uint[] methodData, out byte[] codeData) {
var data = new byte[size]; var data = new byte[size];
Array.Copy(fileData, offset, data, 0, data.Length); Array.Copy(fileData, offset, data, 0, data.Length);
uint k2 = jitDecrypter.key4 * k1; uint k2 = jitDecrypter.key4 * k1;
@ -601,19 +601,19 @@ namespace de4dot.code.deobfuscators.Confuser {
} }
} }
DumpedMethods decrypt(MyPEImage peImage, byte[] fileData, DecryptMethodData decrypter) { DumpedMethods Decrypt(MyPEImage peImage, byte[] fileData, DecryptMethodData decrypter) {
var dumpedMethods = new DumpedMethods(); var dumpedMethods = new DumpedMethods();
var methodDef = peImage.DotNetFile.MetaData.TablesStream.MethodTable; var methodDef = peImage.DotNetFile.MetaData.TablesStream.MethodTable;
for (uint rid = 1; rid <= methodDef.Rows; rid++) { for (uint rid = 1; rid <= methodDef.Rows; rid++) {
var dm = new DumpedMethod(); var dm = new DumpedMethod();
peImage.readMethodTableRowTo(dm, rid); peImage.ReadMethodTableRowTo(dm, rid);
if (dm.mdRVA == 0) if (dm.mdRVA == 0)
continue; continue;
uint bodyOffset = peImage.rvaToOffset(dm.mdRVA); uint bodyOffset = peImage.RvaToOffset(dm.mdRVA);
if (!isEncryptedMethod(fileData, (int)bodyOffset)) if (!IsEncryptedMethod(fileData, (int)bodyOffset))
continue; continue;
int key = BitConverter.ToInt32(fileData, (int)bodyOffset + 6); int key = BitConverter.ToInt32(fileData, (int)bodyOffset + 6);
@ -622,7 +622,7 @@ namespace de4dot.code.deobfuscators.Confuser {
int methodDataOffset = mdOffs + 2; int methodDataOffset = mdOffs + 2;
uint[] methodData; uint[] methodData;
byte[] codeData; byte[] codeData;
decrypter.decrypt(methodsData, methodDataOffset, (uint)key, len, out methodData, out codeData); decrypter.Decrypt(methodsData, methodDataOffset, (uint)key, len, out methodData, out codeData);
dm.mhFlags = 0x03; dm.mhFlags = 0x03;
int maxStack = (int)methodData[methodDataIndexes.maxStack]; int maxStack = (int)methodData[methodDataIndexes.maxStack];
@ -635,12 +635,12 @@ namespace de4dot.code.deobfuscators.Confuser {
int codeSize = (int)methodData[methodDataIndexes.codeSize]; int codeSize = (int)methodData[methodDataIndexes.codeSize];
var codeDataReader = MemoryImageStream.Create(codeData); var codeDataReader = MemoryImageStream.Create(codeData);
if (decrypter.isCodeFollowedByExtraSections(options)) { if (decrypter.IsCodeFollowedByExtraSections(options)) {
dm.code = codeDataReader.ReadBytes(codeSize); dm.code = codeDataReader.ReadBytes(codeSize);
dm.extraSections = readExceptionHandlers(codeDataReader, numExceptions); dm.extraSections = ReadExceptionHandlers(codeDataReader, numExceptions);
} }
else { else {
dm.extraSections = readExceptionHandlers(codeDataReader, numExceptions); dm.extraSections = ReadExceptionHandlers(codeDataReader, numExceptions);
dm.code = codeDataReader.ReadBytes(codeSize); dm.code = codeDataReader.ReadBytes(codeSize);
} }
if (codeDataReader.Position != codeDataReader.Length) if (codeDataReader.Position != codeDataReader.Length)
@ -658,20 +658,20 @@ namespace de4dot.code.deobfuscators.Confuser {
dm.mhFlags |= 0x10; // Set 'init locals' dm.mhFlags |= 0x10; // Set 'init locals'
dm.mhFlags |= (ushort)(options & 0x10); // copy 'init locals' bit dm.mhFlags |= (ushort)(options & 0x10); // copy 'init locals' bit
dumpedMethods.add(dm); dumpedMethods.Add(dm);
} }
return dumpedMethods; return dumpedMethods;
} }
static bool isEncryptedMethod(byte[] fileData, int offset) { static bool IsEncryptedMethod(byte[] fileData, int offset) {
return fileData[offset] == 0x46 && return fileData[offset] == 0x46 &&
fileData[offset + 1] == 0x21 && fileData[offset + 1] == 0x21 &&
fileData[offset + 10] == 0x20 && fileData[offset + 10] == 0x20 &&
fileData[offset + 15] == 0x26; fileData[offset + 15] == 0x26;
} }
static byte[] readExceptionHandlers(IBinaryReader reader, int numExceptions) { static byte[] ReadExceptionHandlers(IBinaryReader reader, int numExceptions) {
if (numExceptions == 0) if (numExceptions == 0)
return null; return null;
@ -694,7 +694,7 @@ namespace de4dot.code.deobfuscators.Confuser {
return memStream.ToArray(); return memStream.ToArray();
} }
byte[] decryptMethodData_v17_r73404(byte[] fileData, int offset, uint k1, int size) { byte[] DecryptMethodData_v17_r73404(byte[] fileData, int offset, uint k1, int size) {
var data = new byte[size]; var data = new byte[size];
var kbytes = BitConverter.GetBytes(k1); var kbytes = BitConverter.GetBytes(k1);
for (int i = 0; i < size; i++) for (int i = 0; i < size; i++)
@ -718,7 +718,7 @@ namespace de4dot.code.deobfuscators.Confuser {
} }
} }
public override bool getRevisionRange(out int minRev, out int maxRev) { public override bool GetRevisionRange(out int minRev, out int maxRev) {
switch (version) { switch (version) {
case ConfuserVersion.Unknown: case ConfuserVersion.Unknown:
minRev = maxRev = 0; minRev = maxRev = 0;

View File

@ -52,25 +52,25 @@ namespace de4dot.code.deobfuscators.Confuser {
this.version = other.version; this.version = other.version;
} }
protected override bool checkType(TypeDef type, MethodDef initMethod) { protected override bool CheckType(TypeDef type, MethodDef initMethod) {
if (type == null) if (type == null)
return false; return false;
if (type.Methods.Count != 3) if (type.Methods.Count != 3)
return false; return false;
var virtProtect = DotNetUtils.getPInvokeMethod(type, "kernel32", "VirtualProtect"); var virtProtect = DotNetUtils.GetPInvokeMethod(type, "kernel32", "VirtualProtect");
if (virtProtect == null) if (virtProtect == null)
return false; return false;
if (!DotNetUtils.hasString(initMethod, "Broken file")) if (!DotNetUtils.HasString(initMethod, "Broken file"))
return false; return false;
if ((decryptMethod = findDecryptMethod(type)) == null) if ((decryptMethod = FindDecryptMethod(type)) == null)
return false; return false;
bool callsFileStreamCtor = DotNetUtils.callsMethod(initMethod, "System.Void System.IO.FileStream::.ctor(System.String,System.IO.FileMode,System.IO.FileAccess,System.IO.FileShare)"); bool callsFileStreamCtor = DotNetUtils.CallsMethod(initMethod, "System.Void System.IO.FileStream::.ctor(System.String,System.IO.FileMode,System.IO.FileAccess,System.IO.FileShare)");
if (!DotNetUtils.hasString(initMethod, "Module error")) if (!DotNetUtils.HasString(initMethod, "Module error"))
version = ConfuserVersion.v14_r57884; version = ConfuserVersion.v14_r57884;
else if (virtProtect.IsPrivate && callsFileStreamCtor) { else if (virtProtect.IsPrivate && callsFileStreamCtor) {
int calls = ConfuserUtils.countCalls(initMethod, "System.Void System.Buffer::BlockCopy(System.Array,System.Int32,System.Array,System.Int32,System.Int32)"); int calls = ConfuserUtils.CountCalls(initMethod, "System.Void System.Buffer::BlockCopy(System.Array,System.Int32,System.Array,System.Int32,System.Int32)");
if (calls <= 1) if (calls <= 1)
version = ConfuserVersion.v14_r58564; version = ConfuserVersion.v14_r58564;
else if (calls == 2) else if (calls == 2)
@ -82,15 +82,15 @@ namespace de4dot.code.deobfuscators.Confuser {
} }
else if (callsFileStreamCtor) else if (callsFileStreamCtor)
version = ConfuserVersion.v14_r58004; version = ConfuserVersion.v14_r58004;
else if (DotNetUtils.callsMethod(initMethod, "System.Int32 System.Object::GetHashCode()")) { else if (DotNetUtils.CallsMethod(initMethod, "System.Int32 System.Object::GetHashCode()")) {
if (DotNetUtils.hasString(initMethod, "<Unknown>")) if (DotNetUtils.HasString(initMethod, "<Unknown>"))
version = ConfuserVersion.v17_r72989; version = ConfuserVersion.v17_r72989;
else else
version = ConfuserVersion.v16_r71742; version = ConfuserVersion.v16_r71742;
} }
else if (DotNetUtils.callsMethod(decryptMethod, "System.Security.Cryptography.Rijndael System.Security.Cryptography.Rijndael::Create()")) else if (DotNetUtils.CallsMethod(decryptMethod, "System.Security.Cryptography.Rijndael System.Security.Cryptography.Rijndael::Create()"))
version = ConfuserVersion.v17_r73605; version = ConfuserVersion.v17_r73605;
else if (DotNetUtils.hasString(initMethod, "<Unknown>")) else if (DotNetUtils.HasString(initMethod, "<Unknown>"))
version = ConfuserVersion.v18_r75288; version = ConfuserVersion.v18_r75288;
else else
version = ConfuserVersion.v19_r75725; version = ConfuserVersion.v19_r75725;
@ -98,15 +98,15 @@ namespace de4dot.code.deobfuscators.Confuser {
return true; return true;
} }
public void initialize() { public void Initialize() {
if (initMethod == null) if (initMethod == null)
return; return;
if (!initializeKeys()) if (!InitializeKeys())
throw new ApplicationException("Could not find all decryption keys"); throw new ApplicationException("Could not find all decryption keys");
} }
bool initializeKeys() { bool InitializeKeys() {
switch (version) { switch (version) {
case ConfuserVersion.v14_r57884: case ConfuserVersion.v14_r57884:
case ConfuserVersion.v14_r58004: case ConfuserVersion.v14_r58004:
@ -115,88 +115,88 @@ namespace de4dot.code.deobfuscators.Confuser {
case ConfuserVersion.v14_r58564: case ConfuserVersion.v14_r58564:
case ConfuserVersion.v14_r58852: case ConfuserVersion.v14_r58852:
case ConfuserVersion.v15_r59014: case ConfuserVersion.v15_r59014:
return initializeKeys_v14_r58564(); return InitializeKeys_v14_r58564();
case ConfuserVersion.v16_r71742: case ConfuserVersion.v16_r71742:
case ConfuserVersion.v17_r72989: case ConfuserVersion.v17_r72989:
return initializeKeys_v16_r71742(); return InitializeKeys_v16_r71742();
case ConfuserVersion.v17_r73605: case ConfuserVersion.v17_r73605:
case ConfuserVersion.v18_r75288: case ConfuserVersion.v18_r75288:
case ConfuserVersion.v19_r75725: case ConfuserVersion.v19_r75725:
return initializeKeys_v17_r73605(); return InitializeKeys_v17_r73605();
default: default:
throw new ApplicationException("Unknown version"); throw new ApplicationException("Unknown version");
} }
} }
bool initializeKeys_v14_r58564() { bool InitializeKeys_v14_r58564() {
simpleDeobfuscator.deobfuscate(initMethod); simpleDeobfuscator.Deobfuscate(initMethod);
if (!findLKey0(initMethod, out lkey0)) if (!FindLKey0(initMethod, out lkey0))
return false; return false;
if (!findKey0_v14_r58564(initMethod, out key0)) if (!FindKey0_v14_r58564(initMethod, out key0))
return false; return false;
if (!findKey2Key3(initMethod, out key2, out key3)) if (!FindKey2Key3(initMethod, out key2, out key3))
return false; return false;
if (!findKey4(initMethod, out key4)) if (!FindKey4(initMethod, out key4))
return false; return false;
if (!findKey5(initMethod, out key5)) if (!FindKey5(initMethod, out key5))
return false; return false;
simpleDeobfuscator.deobfuscate(decryptMethod); simpleDeobfuscator.Deobfuscate(decryptMethod);
if (!findKey6(decryptMethod, out key6)) if (!FindKey6(decryptMethod, out key6))
return false; return false;
return true; return true;
} }
bool initializeKeys_v16_r71742() { bool InitializeKeys_v16_r71742() {
simpleDeobfuscator.deobfuscate(initMethod); simpleDeobfuscator.Deobfuscate(initMethod);
if (!findLKey0(initMethod, out lkey0)) if (!FindLKey0(initMethod, out lkey0))
return false; return false;
if (!findKey0_v16_r71742(initMethod, out key0)) if (!FindKey0_v16_r71742(initMethod, out key0))
return false; return false;
if (!findKey2Key3(initMethod, out key2, out key3)) if (!FindKey2Key3(initMethod, out key2, out key3))
return false; return false;
if (!findKey4(initMethod, out key4)) if (!FindKey4(initMethod, out key4))
return false; return false;
if (!findKey5(initMethod, out key5)) if (!FindKey5(initMethod, out key5))
return false; return false;
simpleDeobfuscator.deobfuscate(decryptMethod); simpleDeobfuscator.Deobfuscate(decryptMethod);
if (!findKey6(decryptMethod, out key6)) if (!FindKey6(decryptMethod, out key6))
return false; return false;
return true; return true;
} }
bool initializeKeys_v17_r73605() { bool InitializeKeys_v17_r73605() {
simpleDeobfuscator.deobfuscate(initMethod); simpleDeobfuscator.Deobfuscate(initMethod);
if (!findLKey0(initMethod, out lkey0)) if (!FindLKey0(initMethod, out lkey0))
return false; return false;
if (!findKey0_v16_r71742(initMethod, out key0)) if (!FindKey0_v16_r71742(initMethod, out key0))
return false; return false;
if (!findKey1(initMethod, out key1)) if (!FindKey1(initMethod, out key1))
return false; return false;
if (!findKey2Key3(initMethod, out key2, out key3)) if (!FindKey2Key3(initMethod, out key2, out key3))
return false; return false;
if (!findKey4(initMethod, out key4)) if (!FindKey4(initMethod, out key4))
return false; return false;
if (!findKey5(initMethod, out key5)) if (!FindKey5(initMethod, out key5))
return false; return false;
simpleDeobfuscator.deobfuscate(decryptMethod); simpleDeobfuscator.Deobfuscate(decryptMethod);
if (!findKey6(decryptMethod, out key6)) if (!FindKey6(decryptMethod, out key6))
return false; return false;
return true; return true;
} }
static bool findKey4(MethodDef method, out uint key) { static bool FindKey4(MethodDef method, out uint key) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count; i++) { for (int i = 0; i < instrs.Count; i++) {
i = findCallvirtReadUInt32(instrs, i); i = FindCallvirtReadUInt32(instrs, i);
if (i < 0) if (i < 0)
break; break;
if (i >= 2) { if (i >= 2) {
@ -228,13 +228,13 @@ namespace de4dot.code.deobfuscators.Confuser {
return false; return false;
} }
static bool findKey5(MethodDef method, out uint key) { static bool FindKey5(MethodDef method, out uint key) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count; i++) { for (int i = 0; i < instrs.Count; i++) {
i = findCallvirtReadUInt32(instrs, i); i = FindCallvirtReadUInt32(instrs, i);
if (i < 0) if (i < 0)
break; break;
int index2 = ConfuserUtils.findCallMethod(instrs, i, Code.Callvirt, "System.Int32 System.IO.BinaryReader::ReadInt32()"); int index2 = ConfuserUtils.FindCallMethod(instrs, i, Code.Callvirt, "System.Int32 System.IO.BinaryReader::ReadInt32()");
if (index2 < 0) if (index2 < 0)
break; break;
if (index2 - i != 6) if (index2 - i != 6)
@ -264,27 +264,27 @@ namespace de4dot.code.deobfuscators.Confuser {
return false; return false;
} }
public bool decrypt(MyPEImage peImage, byte[] fileData) { public bool Decrypt(MyPEImage peImage, byte[] fileData) {
if (initMethod == null) if (initMethod == null)
return false; return false;
switch (version) { switch (version) {
case ConfuserVersion.v14_r57884: return decrypt_v14_r57884(peImage, fileData); case ConfuserVersion.v14_r57884: return Decrypt_v14_r57884(peImage, fileData);
case ConfuserVersion.v14_r58004: return decrypt_v14_r58004(peImage, fileData); case ConfuserVersion.v14_r58004: return Decrypt_v14_r58004(peImage, fileData);
case ConfuserVersion.v14_r58564: return decrypt_v14_r58004(peImage, fileData); case ConfuserVersion.v14_r58564: return Decrypt_v14_r58004(peImage, fileData);
case ConfuserVersion.v14_r58852: return decrypt_v14_r58004(peImage, fileData); case ConfuserVersion.v14_r58852: return Decrypt_v14_r58004(peImage, fileData);
case ConfuserVersion.v15_r59014: return decrypt_v15_r59014(peImage, fileData); case ConfuserVersion.v15_r59014: return Decrypt_v15_r59014(peImage, fileData);
case ConfuserVersion.v16_r71742: return decrypt_v16_r71742(peImage, fileData); case ConfuserVersion.v16_r71742: return Decrypt_v16_r71742(peImage, fileData);
case ConfuserVersion.v17_r72989: return decrypt_v16_r71742(peImage, fileData); case ConfuserVersion.v17_r72989: return Decrypt_v16_r71742(peImage, fileData);
case ConfuserVersion.v17_r73605: return decrypt_v17_r73605(peImage, fileData); case ConfuserVersion.v17_r73605: return Decrypt_v17_r73605(peImage, fileData);
case ConfuserVersion.v18_r75288: return decrypt_v17_r73605(peImage, fileData); case ConfuserVersion.v18_r75288: return Decrypt_v17_r73605(peImage, fileData);
case ConfuserVersion.v19_r75725: return decrypt_v17_r73605(peImage, fileData); case ConfuserVersion.v19_r75725: return Decrypt_v17_r73605(peImage, fileData);
default: throw new ApplicationException("Unknown version"); default: throw new ApplicationException("Unknown version");
} }
} }
bool decrypt_v14_r57884(MyPEImage peImage, byte[] fileData) { bool Decrypt_v14_r57884(MyPEImage peImage, byte[] fileData) {
methodsData = decryptMethodsData_v14_r57884(peImage, false); methodsData = DecryptMethodsData_v14_r57884(peImage, false);
var reader = new BinaryReader(new MemoryStream(methodsData)); var reader = new BinaryReader(new MemoryStream(methodsData));
reader.ReadInt16(); // sig reader.ReadInt16(); // sig
@ -294,48 +294,48 @@ namespace de4dot.code.deobfuscators.Confuser {
uint rva = reader.ReadUInt32(); uint rva = reader.ReadUInt32();
if (rva == 0) if (rva == 0)
continue; continue;
writer.BaseStream.Position = peImage.rvaToOffset(rva); writer.BaseStream.Position = peImage.RvaToOffset(rva);
writer.Write(reader.ReadBytes(reader.ReadInt32())); writer.Write(reader.ReadBytes(reader.ReadInt32()));
} }
return true; return true;
} }
byte[] decryptMethodsData_v14_r57884(MyPEImage peImage, bool hasStrongNameInfo) { byte[] DecryptMethodsData_v14_r57884(MyPEImage peImage, bool hasStrongNameInfo) {
var reader = peImage.Reader; var reader = peImage.Reader;
reader.Position = 0; reader.Position = 0;
var md5SumData = reader.ReadBytes((int)peImage.OptionalHeader.CheckSum ^ (int)key0); var md5SumData = reader.ReadBytes((int)peImage.OptionalHeader.CheckSum ^ (int)key0);
int csOffs = (int)peImage.OptionalHeader.StartOffset + 0x40; int csOffs = (int)peImage.OptionalHeader.StartOffset + 0x40;
Array.Clear(md5SumData, csOffs, 4); Array.Clear(md5SumData, csOffs, 4);
var md5Sum = DeobUtils.md5Sum(md5SumData); var md5Sum = DeobUtils.Md5Sum(md5SumData);
ulong checkSum = reader.ReadUInt64() ^ lkey0; ulong checkSum = reader.ReadUInt64() ^ lkey0;
if (hasStrongNameInfo) { if (hasStrongNameInfo) {
int sn = reader.ReadInt32(); int sn = reader.ReadInt32();
int snLen = reader.ReadInt32(); int snLen = reader.ReadInt32();
if (sn != 0) { if (sn != 0) {
if (peImage.rvaToOffset((uint)peImage.Cor20Header.StrongNameSignature.VirtualAddress) != sn || if (peImage.RvaToOffset((uint)peImage.Cor20Header.StrongNameSignature.VirtualAddress) != sn ||
peImage.Cor20Header.StrongNameSignature.Size != snLen) peImage.Cor20Header.StrongNameSignature.Size != snLen)
throw new ApplicationException("Invalid sn and snLen"); throw new ApplicationException("Invalid sn and snLen");
Array.Clear(md5SumData, sn, snLen); Array.Clear(md5SumData, sn, snLen);
} }
} }
if (checkSum != calcChecksum(md5SumData)) if (checkSum != CalcChecksum(md5SumData))
throw new ApplicationException("Invalid checksum. File has been modified."); throw new ApplicationException("Invalid checksum. File has been modified.");
var iv = reader.ReadBytes(reader.ReadInt32() ^ (int)key2); var iv = reader.ReadBytes(reader.ReadInt32() ^ (int)key2);
var encrypted = reader.ReadBytes(reader.ReadInt32() ^ (int)key3); var encrypted = reader.ReadBytes(reader.ReadInt32() ^ (int)key3);
var decrypted = decrypt(encrypted, iv, md5SumData); var decrypted = Decrypt(encrypted, iv, md5SumData);
if (BitConverter.ToInt16(decrypted, 0) != 0x6FD6) if (BitConverter.ToInt16(decrypted, 0) != 0x6FD6)
throw new ApplicationException("Invalid magic"); throw new ApplicationException("Invalid magic");
return decrypted; return decrypted;
} }
bool decrypt_v14_r58004(MyPEImage peImage, byte[] fileData) { bool Decrypt_v14_r58004(MyPEImage peImage, byte[] fileData) {
methodsData = decryptMethodsData_v14_r57884(peImage, false); methodsData = DecryptMethodsData_v14_r57884(peImage, false);
return decryptImage_v14_r58004(peImage, fileData); return DecryptImage_v14_r58004(peImage, fileData);
} }
bool decryptImage_v14_r58004(MyPEImage peImage, byte[] fileData) { bool DecryptImage_v14_r58004(MyPEImage peImage, byte[] fileData) {
var reader = new BinaryReader(new MemoryStream(methodsData)); var reader = new BinaryReader(new MemoryStream(methodsData));
reader.ReadInt16(); // sig reader.ReadInt16(); // sig
var writer = new BinaryWriter(new MemoryStream(fileData)); var writer = new BinaryWriter(new MemoryStream(fileData));
@ -345,34 +345,34 @@ namespace de4dot.code.deobfuscators.Confuser {
if (offs == 0) if (offs == 0)
continue; continue;
uint rva = reader.ReadUInt32() ^ key4; uint rva = reader.ReadUInt32() ^ key4;
if (peImage.rvaToOffset(rva) != offs) if (peImage.RvaToOffset(rva) != offs)
throw new ApplicationException("Invalid offs & rva"); throw new ApplicationException("Invalid offs & rva");
writer.BaseStream.Position = peImage.rvaToOffset(rva); writer.BaseStream.Position = peImage.RvaToOffset(rva);
writer.Write(reader.ReadBytes(reader.ReadInt32())); writer.Write(reader.ReadBytes(reader.ReadInt32()));
} }
return true; return true;
} }
bool decrypt_v15_r59014(MyPEImage peImage, byte[] fileData) { bool Decrypt_v15_r59014(MyPEImage peImage, byte[] fileData) {
methodsData = decryptMethodsData_v14_r57884(peImage, true); methodsData = DecryptMethodsData_v14_r57884(peImage, true);
return decryptImage_v14_r58004(peImage, fileData); return DecryptImage_v14_r58004(peImage, fileData);
} }
bool decrypt_v16_r71742(MyPEImage peImage, byte[] fileData) { bool Decrypt_v16_r71742(MyPEImage peImage, byte[] fileData) {
methodsData = decryptMethodsData_v16_r71742(peImage, getEncryptedHeaderOffset_v16_r71742(peImage.Sections)); methodsData = DecryptMethodsData_v16_r71742(peImage, GetEncryptedHeaderOffset_v16_r71742(peImage.Sections));
return decryptImage_v16_r71742(peImage, fileData); return DecryptImage_v16_r71742(peImage, fileData);
} }
bool decrypt_v17_r73605(MyPEImage peImage, byte[] fileData) { bool Decrypt_v17_r73605(MyPEImage peImage, byte[] fileData) {
if (peImage.OptionalHeader.CheckSum == 0) if (peImage.OptionalHeader.CheckSum == 0)
return false; return false;
methodsData = decryptMethodsData_v17_r73404(peImage); methodsData = DecryptMethodsData_v17_r73404(peImage);
return decryptImage_v16_r71742(peImage, fileData); return DecryptImage_v16_r71742(peImage, fileData);
} }
bool decryptImage_v16_r71742(MyPEImage peImage, byte[] fileData) { bool DecryptImage_v16_r71742(MyPEImage peImage, byte[] fileData) {
var reader = new BinaryReader(new MemoryStream(methodsData)); var reader = new BinaryReader(new MemoryStream(methodsData));
reader.ReadInt16(); // sig reader.ReadInt16(); // sig
int numInfos = reader.ReadInt32(); int numInfos = reader.ReadInt32();
@ -381,7 +381,7 @@ namespace de4dot.code.deobfuscators.Confuser {
if (offs == 0) if (offs == 0)
continue; continue;
uint rva = reader.ReadUInt32() ^ key5; uint rva = reader.ReadUInt32() ^ key5;
if (peImage.rvaToOffset(rva) != offs) if (peImage.RvaToOffset(rva) != offs)
throw new ApplicationException("Invalid offs & rva"); throw new ApplicationException("Invalid offs & rva");
int len = reader.ReadInt32(); int len = reader.ReadInt32();
for (int j = 0; j < len; j++) for (int j = 0; j < len; j++)
@ -390,7 +390,7 @@ namespace de4dot.code.deobfuscators.Confuser {
return true; return true;
} }
public override bool getRevisionRange(out int minRev, out int maxRev) { public override bool GetRevisionRange(out int minRev, out int maxRev) {
switch (version) { switch (version) {
case ConfuserVersion.Unknown: case ConfuserVersion.Unknown:
minRev = maxRev = 0; minRev = maxRev = 0;

View File

@ -57,20 +57,20 @@ namespace de4dot.code.deobfuscators.Confuser {
this.module = module; this.module = module;
this.simpleDeobfuscator = simpleDeobfuscator; this.simpleDeobfuscator = simpleDeobfuscator;
if (other != null) if (other != null)
this.initMethod = lookup(other.initMethod, "Could not find initMethod"); this.initMethod = Lookup(other.initMethod, "Could not find initMethod");
} }
T lookup<T>(T def, string errorMessage) where T : class, ICodedToken { T Lookup<T>(T def, string errorMessage) where T : class, ICodedToken {
return DeobUtils.lookup(module, def, errorMessage); return DeobUtils.Lookup(module, def, errorMessage);
} }
public abstract bool getRevisionRange(out int minRev, out int maxRev); public abstract bool GetRevisionRange(out int minRev, out int maxRev);
public void find() { public void Find() {
find(DotNetUtils.getModuleTypeCctor(module)); Find(DotNetUtils.GetModuleTypeCctor(module));
} }
bool find(MethodDef method) { bool Find(MethodDef method) {
if (method == null || method.Body == null) if (method == null || method.Body == null)
return false; return false;
foreach (var instr in method.Body.Instructions) { foreach (var instr in method.Body.Instructions) {
@ -85,9 +85,9 @@ namespace de4dot.code.deobfuscators.Confuser {
catch { catch {
continue; continue;
} }
if (!DotNetUtils.isMethod(calledMethod, "System.Void", "()")) if (!DotNetUtils.IsMethod(calledMethod, "System.Void", "()"))
continue; continue;
if (!checkType(calledMethod.DeclaringType, calledMethod)) if (!CheckType(calledMethod.DeclaringType, calledMethod))
continue; continue;
initMethod = calledMethod; initMethod = calledMethod;
@ -96,13 +96,13 @@ namespace de4dot.code.deobfuscators.Confuser {
return false; return false;
} }
protected abstract bool checkType(TypeDef type, MethodDef initMethod); protected abstract bool CheckType(TypeDef type, MethodDef initMethod);
protected static MethodDef findDecryptMethod(TypeDef type) { protected static MethodDef FindDecryptMethod(TypeDef type) {
foreach (var method in type.Methods) { foreach (var method in type.Methods) {
if (!method.IsStatic || method.Body == null) if (!method.IsStatic || method.Body == null)
continue; continue;
if (!DotNetUtils.isMethod(method, "System.Byte[]", "(System.Byte[],System.Byte[],System.Byte[])")) if (!DotNetUtils.IsMethod(method, "System.Byte[]", "(System.Byte[],System.Byte[],System.Byte[])"))
continue; continue;
return method; return method;
@ -110,10 +110,10 @@ namespace de4dot.code.deobfuscators.Confuser {
return null; return null;
} }
protected static bool findLKey0(MethodDef method, out ulong key) { protected static bool FindLKey0(MethodDef method, out ulong key) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int index = 0; index < instrs.Count; index++) { for (int index = 0; index < instrs.Count; index++) {
index = findCallvirtReadUInt64(instrs, index); index = FindCallvirtReadUInt64(instrs, index);
if (index < 0) if (index < 0)
break; break;
if (index + 1 >= instrs.Count) if (index + 1 >= instrs.Count)
@ -130,10 +130,10 @@ namespace de4dot.code.deobfuscators.Confuser {
return false; return false;
} }
protected static bool findKey0_v16_r71742(MethodDef method, out uint key) { protected static bool FindKey0_v16_r71742(MethodDef method, out uint key) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i + 5 < instrs.Count; i++) { for (int i = 0; i + 5 < instrs.Count; i++) {
i = findCallvirtReadUInt32(instrs, i); i = FindCallvirtReadUInt32(instrs, i);
if (i < 0) if (i < 0)
break; break;
@ -161,10 +161,10 @@ namespace de4dot.code.deobfuscators.Confuser {
return false; return false;
} }
protected static bool findKey0_v14_r58564(MethodDef method, out uint key) { protected static bool FindKey0_v14_r58564(MethodDef method, out uint key) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i + 5 < instrs.Count; i++) { for (int i = 0; i + 5 < instrs.Count; i++) {
i = ConfuserUtils.findCallMethod(instrs, i, Code.Callvirt, "System.Int32 System.IO.BinaryReader::ReadInt32()"); i = ConfuserUtils.FindCallMethod(instrs, i, Code.Callvirt, "System.Int32 System.IO.BinaryReader::ReadInt32()");
if (i < 0) if (i < 0)
break; break;
@ -192,22 +192,22 @@ namespace de4dot.code.deobfuscators.Confuser {
return false; return false;
} }
protected static bool findKey1(MethodDef method, out uint key) { protected static bool FindKey1(MethodDef method, out uint key) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int index = 0; index < instrs.Count; index++) { for (int index = 0; index < instrs.Count; index++) {
index = findCallvirtReadUInt32(instrs, index); index = FindCallvirtReadUInt32(instrs, index);
if (index < 0) if (index < 0)
break; break;
if (index == 0) if (index == 0)
continue; continue;
int i = index - 1; int i = index - 1;
if (!checkCallvirtReadUInt32(instrs, ref i)) if (!CheckCallvirtReadUInt32(instrs, ref i))
continue; continue;
if (!checkCallvirtReadUInt32(instrs, ref i)) if (!CheckCallvirtReadUInt32(instrs, ref i))
continue; continue;
if (!checkCallvirtReadUInt32(instrs, ref i)) if (!CheckCallvirtReadUInt32(instrs, ref i))
continue; continue;
if (!checkCallvirtReadUInt32(instrs, ref i)) if (!CheckCallvirtReadUInt32(instrs, ref i))
continue; continue;
if (i + 1 >= instrs.Count) if (i + 1 >= instrs.Count)
@ -226,13 +226,13 @@ namespace de4dot.code.deobfuscators.Confuser {
return false; return false;
} }
static bool checkCallvirtReadUInt32(IList<Instruction> instrs, ref int index) { static bool CheckCallvirtReadUInt32(IList<Instruction> instrs, ref int index) {
if (index + 2 >= instrs.Count) if (index + 2 >= instrs.Count)
return false; return false;
if (!instrs[index].IsLdloc()) if (!instrs[index].IsLdloc())
return false; return false;
if (!ConfuserUtils.isCallMethod(instrs[index + 1], Code.Callvirt, "System.UInt32 System.IO.BinaryReader::ReadUInt32()")) if (!ConfuserUtils.IsCallMethod(instrs[index + 1], Code.Callvirt, "System.UInt32 System.IO.BinaryReader::ReadUInt32()"))
return false; return false;
if (!instrs[index + 2].IsStloc() && instrs[index + 2].OpCode.Code != Code.Pop) if (!instrs[index + 2].IsStloc() && instrs[index + 2].OpCode.Code != Code.Pop)
return false; return false;
@ -241,13 +241,13 @@ namespace de4dot.code.deobfuscators.Confuser {
return true; return true;
} }
protected static bool findKey2Key3(MethodDef method, out uint key2, out uint key3) { protected static bool FindKey2Key3(MethodDef method, out uint key2, out uint key3) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count; i++) { for (int i = 0; i < instrs.Count; i++) {
int index = i; int index = i;
if (!findKey2OrKey3(instrs, ref index, out key2)) if (!FindKey2OrKey3(instrs, ref index, out key2))
continue; continue;
if (!findKey2OrKey3(instrs, ref index, out key3)) if (!FindKey2OrKey3(instrs, ref index, out key3))
continue; continue;
return true; return true;
@ -258,7 +258,7 @@ namespace de4dot.code.deobfuscators.Confuser {
return false; return false;
} }
static bool findKey2OrKey3(IList<Instruction> instrs, ref int index, out uint key) { static bool FindKey2OrKey3(IList<Instruction> instrs, ref int index, out uint key) {
key = 0; key = 0;
if (index + 6 >= instrs.Count) if (index + 6 >= instrs.Count)
return false; return false;
@ -267,14 +267,14 @@ namespace de4dot.code.deobfuscators.Confuser {
return false; return false;
if (!instrs[i++].IsLdloc()) if (!instrs[i++].IsLdloc())
return false; return false;
if (!ConfuserUtils.isCallMethod(instrs[i++], Code.Callvirt, "System.Int32 System.IO.BinaryReader::ReadInt32()")) if (!ConfuserUtils.IsCallMethod(instrs[i++], Code.Callvirt, "System.Int32 System.IO.BinaryReader::ReadInt32()"))
return false; return false;
var ldci4 = instrs[i++]; var ldci4 = instrs[i++];
if (!ldci4.IsLdcI4()) if (!ldci4.IsLdcI4())
return false; return false;
if (instrs[i++].OpCode.Code != Code.Xor) if (instrs[i++].OpCode.Code != Code.Xor)
return false; return false;
if (!ConfuserUtils.isCallMethod(instrs[i++], Code.Callvirt, "System.Byte[] System.IO.BinaryReader::ReadBytes(System.Int32)")) if (!ConfuserUtils.IsCallMethod(instrs[i++], Code.Callvirt, "System.Byte[] System.IO.BinaryReader::ReadBytes(System.Int32)"))
return false; return false;
if (!instrs[i++].IsStloc()) if (!instrs[i++].IsStloc())
return false; return false;
@ -284,7 +284,7 @@ namespace de4dot.code.deobfuscators.Confuser {
return true; return true;
} }
protected static bool findKey6(MethodDef method, out uint key) { protected static bool FindKey6(MethodDef method, out uint key) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i + 4 < instrs.Count; i++) { for (int i = 0; i + 4 < instrs.Count; i++) {
int index = i; int index = i;
@ -310,19 +310,19 @@ namespace de4dot.code.deobfuscators.Confuser {
return false; return false;
} }
protected static int findCallvirtReadUInt32(IList<Instruction> instrs, int index) { protected static int FindCallvirtReadUInt32(IList<Instruction> instrs, int index) {
return ConfuserUtils.findCallMethod(instrs, index, Code.Callvirt, "System.UInt32 System.IO.BinaryReader::ReadUInt32()"); return ConfuserUtils.FindCallMethod(instrs, index, Code.Callvirt, "System.UInt32 System.IO.BinaryReader::ReadUInt32()");
} }
static int findCallvirtReadUInt64(IList<Instruction> instrs, int index) { static int FindCallvirtReadUInt64(IList<Instruction> instrs, int index) {
return ConfuserUtils.findCallMethod(instrs, index, Code.Callvirt, "System.UInt64 System.IO.BinaryReader::ReadUInt64()"); return ConfuserUtils.FindCallMethod(instrs, index, Code.Callvirt, "System.UInt64 System.IO.BinaryReader::ReadUInt64()");
} }
protected byte[] decryptMethodsData_v17_r73404(MyPEImage peImage) { protected byte[] DecryptMethodsData_v17_r73404(MyPEImage peImage) {
return decryptMethodsData_v16_r71742(peImage, getEncryptedHeaderOffset_vXX(peImage.Sections)); return DecryptMethodsData_v16_r71742(peImage, GetEncryptedHeaderOffset_vXX(peImage.Sections));
} }
protected byte[] decryptMethodsData_v16_r71742(MyPEImage peImage, uint encryptedHeaderOffset) { protected byte[] DecryptMethodsData_v16_r71742(MyPEImage peImage, uint encryptedHeaderOffset) {
uint mdRva = peImage.OptionalHeader.CheckSum ^ (uint)key0; uint mdRva = peImage.OptionalHeader.CheckSum ^ (uint)key0;
if ((RVA)mdRva != peImage.Cor20Header.MetaData.VirtualAddress) if ((RVA)mdRva != peImage.Cor20Header.MetaData.VirtualAddress)
throw new ApplicationException("Invalid metadata rva"); throw new ApplicationException("Invalid metadata rva");
@ -333,16 +333,16 @@ namespace de4dot.code.deobfuscators.Confuser {
reader.ReadInt32(); // strong name len reader.ReadInt32(); // strong name len
var iv = reader.ReadBytes(reader.ReadInt32() ^ (int)key2); var iv = reader.ReadBytes(reader.ReadInt32() ^ (int)key2);
var encrypted = reader.ReadBytes(reader.ReadInt32() ^ (int)key3); var encrypted = reader.ReadBytes(reader.ReadInt32() ^ (int)key3);
var streamsBuffer = getStreamsBuffer(peImage); var streamsBuffer = GetStreamsBuffer(peImage);
if (checkSum != calcChecksum(streamsBuffer)) if (checkSum != CalcChecksum(streamsBuffer))
throw new ApplicationException("Invalid checksum. File has been modified."); throw new ApplicationException("Invalid checksum. File has been modified.");
var decrypted = decrypt(encrypted, iv, streamsBuffer); var decrypted = Decrypt(encrypted, iv, streamsBuffer);
if (BitConverter.ToInt16(decrypted, 0) != 0x6FD6) if (BitConverter.ToInt16(decrypted, 0) != 0x6FD6)
throw new ApplicationException("Invalid magic"); throw new ApplicationException("Invalid magic");
return decrypted; return decrypted;
} }
protected uint getEncryptedHeaderOffset_v16_r71742(IList<ImageSectionHeader> sections) { protected uint GetEncryptedHeaderOffset_v16_r71742(IList<ImageSectionHeader> sections) {
for (int i = sections.Count - 1; i >= 0; i--) { for (int i = sections.Count - 1; i >= 0; i--) {
var section = sections[i]; var section = sections[i];
if (section.DisplayName == ".confuse") if (section.DisplayName == ".confuse")
@ -351,16 +351,16 @@ namespace de4dot.code.deobfuscators.Confuser {
throw new ApplicationException("Could not find encrypted section"); throw new ApplicationException("Could not find encrypted section");
} }
uint getEncryptedHeaderOffset_vXX(IList<ImageSectionHeader> sections) { uint GetEncryptedHeaderOffset_vXX(IList<ImageSectionHeader> sections) {
for (int i = sections.Count - 1; i >= 0; i--) { for (int i = sections.Count - 1; i >= 0; i--) {
var section = sections[i]; var section = sections[i];
if (getSectionNameHash(section) == (uint)key1) if (GetSectionNameHash(section) == (uint)key1)
return section.PointerToRawData; return section.PointerToRawData;
} }
throw new ApplicationException("Could not find encrypted section"); throw new ApplicationException("Could not find encrypted section");
} }
static byte[] getStreamsBuffer(MyPEImage peImage) { static byte[] GetStreamsBuffer(MyPEImage peImage) {
var memStream = new MemoryStream(); var memStream = new MemoryStream();
var writer = new BinaryWriter(memStream); var writer = new BinaryWriter(memStream);
var reader = peImage.Reader; var reader = peImage.Reader;
@ -371,20 +371,20 @@ namespace de4dot.code.deobfuscators.Confuser {
return memStream.ToArray(); return memStream.ToArray();
} }
protected static ulong calcChecksum(byte[] data) { protected static ulong CalcChecksum(byte[] data) {
var sum = DeobUtils.md5Sum(data); var sum = DeobUtils.Md5Sum(data);
return BitConverter.ToUInt64(sum, 0) ^ BitConverter.ToUInt64(sum, 8); return BitConverter.ToUInt64(sum, 0) ^ BitConverter.ToUInt64(sum, 8);
} }
static uint getSectionNameHash(ImageSectionHeader section) { static uint GetSectionNameHash(ImageSectionHeader section) {
uint hash = 0; uint hash = 0;
foreach (var c in section.Name) foreach (var c in section.Name)
hash += c; hash += c;
return hash; return hash;
} }
protected byte[] decrypt(byte[] encrypted, byte[] iv, byte[] streamsBuffer) { protected byte[] Decrypt(byte[] encrypted, byte[] iv, byte[] streamsBuffer) {
var decrypted = DeobUtils.aesDecrypt(encrypted, DeobUtils.sha256Sum(streamsBuffer), iv); var decrypted = DeobUtils.AesDecrypt(encrypted, DeobUtils.Sha256Sum(streamsBuffer), iv);
var sha = SHA512.Create(); var sha = SHA512.Create();
var hash = sha.ComputeHash(streamsBuffer); var hash = sha.ComputeHash(streamsBuffer);
for (int i = 0; i < decrypted.Length; i += 64) { for (int i = 0; i < decrypted.Length; i += 64) {

View File

@ -109,8 +109,8 @@ namespace de4dot.code.deobfuscators.Confuser {
public IEnumerable<FieldDef> Fields { public IEnumerable<FieldDef> Fields {
get { get {
var fields = new List<FieldDef>(fieldToMethods.getKeys()); var fields = new List<FieldDef>(fieldToMethods.GetKeys());
var type = DotNetUtils.getModuleType(module); var type = DotNetUtils.GetModuleType(module);
if (fields.Count > 0 && type != null) { if (fields.Count > 0 && type != null) {
foreach (var field in type.Fields) { foreach (var field in type.Fields) {
var fieldType = field.FieldType.TryGetTypeDef(); var fieldType = field.FieldType.TryGetTypeDef();
@ -125,7 +125,7 @@ namespace de4dot.code.deobfuscators.Confuser {
public override IEnumerable<Tuple<MethodDef, string>> OtherMethods { public override IEnumerable<Tuple<MethodDef, string>> OtherMethods {
get { get {
var list = new List<Tuple<MethodDef, string>>(); var list = new List<Tuple<MethodDef, string>>();
foreach (var info in methodToInfo.getValues()) { foreach (var info in methodToInfo.GetValues()) {
list.Add(new Tuple<MethodDef, string> { list.Add(new Tuple<MethodDef, string> {
Item1 = info.creatorMethod, Item1 = info.creatorMethod,
Item2 = "Delegate creator method", Item2 = "Delegate creator method",
@ -135,7 +135,7 @@ namespace de4dot.code.deobfuscators.Confuser {
Item2 = "Calculate RID native method", Item2 = "Calculate RID native method",
}); });
} }
foreach (var methods in fieldToMethods.getValues()) { foreach (var methods in fieldToMethods.GetValues()) {
foreach (var method in methods) { foreach (var method in methods) {
list.Add(new Tuple<MethodDef, string> { list.Add(new Tuple<MethodDef, string> {
Item1 = method, Item1 = method,
@ -156,7 +156,7 @@ namespace de4dot.code.deobfuscators.Confuser {
ourAsm = module.Assembly.FullName; ourAsm = module.Assembly.FullName;
} }
protected override object checkCctor(TypeDef type, MethodDef cctor) { protected override object CheckCctor(TypeDef type, MethodDef cctor) {
// Here if 1.2 r54564 (almost 1.3) or later // Here if 1.2 r54564 (almost 1.3) or later
var fieldToInfo = new FieldDefAndDeclaringTypeDict<DelegateInitInfo>(); var fieldToInfo = new FieldDefAndDeclaringTypeDict<DelegateInitInfo>();
@ -176,33 +176,33 @@ namespace de4dot.code.deobfuscators.Confuser {
var calledMethod = call.Operand as MethodDef; var calledMethod = call.Operand as MethodDef;
if (calledMethod == null) if (calledMethod == null)
continue; continue;
if (!isDelegateCreatorMethod(calledMethod)) if (!IsDelegateCreatorMethod(calledMethod))
continue; continue;
var info = methodToInfo.find(calledMethod); var info = methodToInfo.Find(calledMethod);
if (info == null) if (info == null)
continue; continue;
i++; i++;
fieldToInfo.add(field, new DelegateInitInfo(field, calledMethod)); fieldToInfo.Add(field, new DelegateInitInfo(field, calledMethod));
} }
return fieldToInfo.Count == 0 ? null : fieldToInfo; return fieldToInfo.Count == 0 ? null : fieldToInfo;
} }
protected override void getCallInfo(object context, FieldDef field, out IMethod calledMethod, out OpCode callOpcode) { protected override void GetCallInfo(object context, FieldDef field, out IMethod calledMethod, out OpCode callOpcode) {
var info = context as DelegateInitInfo; var info = context as DelegateInitInfo;
if (info == null) { if (info == null) {
var fieldToInfo = context as FieldDefAndDeclaringTypeDict<DelegateInitInfo>; var fieldToInfo = context as FieldDefAndDeclaringTypeDict<DelegateInitInfo>;
if (fieldToInfo != null) if (fieldToInfo != null)
info = fieldToInfo.find(field); info = fieldToInfo.Find(field);
} }
if (info == null) if (info == null)
throw new ApplicationException("Couldn't get the delegate info"); throw new ApplicationException("Couldn't get the delegate info");
var creatorInfo = methodToInfo.find(info.creatorMethod); var creatorInfo = methodToInfo.Find(info.creatorMethod);
switch (creatorInfo.version) { switch (creatorInfo.version) {
case ConfuserVersion.v10_r42915: case ConfuserVersion.v10_r42915:
case ConfuserVersion.v10_r42919: case ConfuserVersion.v10_r42919:
getCallInfo_v10_r42915(info, creatorInfo, out calledMethod, out callOpcode); GetCallInfo_v10_r42915(info, creatorInfo, out calledMethod, out callOpcode);
break; break;
case ConfuserVersion.v10_r48717: case ConfuserVersion.v10_r48717:
@ -212,36 +212,36 @@ namespace de4dot.code.deobfuscators.Confuser {
case ConfuserVersion.v13_r55604: case ConfuserVersion.v13_r55604:
case ConfuserVersion.v14_r58564: case ConfuserVersion.v14_r58564:
case ConfuserVersion.v14_r58802: case ConfuserVersion.v14_r58802:
getCallInfo_v10_r48717(info, creatorInfo, out calledMethod, out callOpcode); GetCallInfo_v10_r48717(info, creatorInfo, out calledMethod, out callOpcode);
break; break;
case ConfuserVersion.v14_r58857: case ConfuserVersion.v14_r58857:
case ConfuserVersion.v16_r66631: case ConfuserVersion.v16_r66631:
case ConfuserVersion.v16_r70489: case ConfuserVersion.v16_r70489:
case ConfuserVersion.v17_r73479: case ConfuserVersion.v17_r73479:
getCallInfo_v14_r58857(info, creatorInfo, out calledMethod, out callOpcode); GetCallInfo_v14_r58857(info, creatorInfo, out calledMethod, out callOpcode);
break; break;
case ConfuserVersion.v17_r73740_normal: case ConfuserVersion.v17_r73740_normal:
case ConfuserVersion.v17_r74708_normal: case ConfuserVersion.v17_r74708_normal:
getCallInfo_v17_r73740_normal(info, creatorInfo, out calledMethod, out callOpcode); GetCallInfo_v17_r73740_normal(info, creatorInfo, out calledMethod, out callOpcode);
break; break;
case ConfuserVersion.v17_r73740_native: case ConfuserVersion.v17_r73740_native:
case ConfuserVersion.v17_r74708_native: case ConfuserVersion.v17_r74708_native:
getCallInfo_v17_r73740_native(info, creatorInfo, out calledMethod, out callOpcode); GetCallInfo_v17_r73740_native(info, creatorInfo, out calledMethod, out callOpcode);
break; break;
case ConfuserVersion.v18_r75367_normal: case ConfuserVersion.v18_r75367_normal:
case ConfuserVersion.v18_r75369_normal: case ConfuserVersion.v18_r75369_normal:
case ConfuserVersion.v19_r76101_normal: case ConfuserVersion.v19_r76101_normal:
getCallInfo_v18_r75367_normal(info, creatorInfo, out calledMethod, out callOpcode); GetCallInfo_v18_r75367_normal(info, creatorInfo, out calledMethod, out callOpcode);
break; break;
case ConfuserVersion.v18_r75367_native: case ConfuserVersion.v18_r75367_native:
case ConfuserVersion.v18_r75369_native: case ConfuserVersion.v18_r75369_native:
case ConfuserVersion.v19_r76101_native: case ConfuserVersion.v19_r76101_native:
getCallInfo_v18_r75367_native(info, creatorInfo, out calledMethod, out callOpcode); GetCallInfo_v18_r75367_native(info, creatorInfo, out calledMethod, out callOpcode);
break; break;
default: default:
@ -254,14 +254,14 @@ namespace de4dot.code.deobfuscators.Confuser {
} }
} }
void getCallInfo_v10_r42915(DelegateInitInfo info, ProxyCreatorInfo creatorInfo, out IMethod calledMethod, out OpCode callOpcode) { void GetCallInfo_v10_r42915(DelegateInitInfo info, ProxyCreatorInfo creatorInfo, out IMethod calledMethod, out OpCode callOpcode) {
var reader = new BinaryReader(new MemoryStream(info.data)); var reader = new BinaryReader(new MemoryStream(info.data));
bool isCallvirt = false; bool isCallvirt = false;
if (creatorInfo.proxyCreatorType == ProxyCreatorType.CallOrCallvirt) if (creatorInfo.proxyCreatorType == ProxyCreatorType.CallOrCallvirt)
isCallvirt = reader.ReadBoolean(); isCallvirt = reader.ReadBoolean();
var asmRef = readAssemblyNameReference(reader); var asmRef = ReadAssemblyNameReference(reader);
// If < 1.0 r42919, then high byte is 06, else it's cleared. // If < 1.0 r42919, then high byte is 06, else it's cleared.
uint token = (reader.ReadUInt32() & 0x00FFFFFF) | 0x06000000; uint token = (reader.ReadUInt32() & 0x00FFFFFF) | 0x06000000;
if (reader.BaseStream.Position != reader.BaseStream.Length) if (reader.BaseStream.Position != reader.BaseStream.Length)
@ -270,12 +270,12 @@ namespace de4dot.code.deobfuscators.Confuser {
if (asmRef.FullName == ourAsm) if (asmRef.FullName == ourAsm)
calledMethod = module.ResolveToken(token) as IMethod; calledMethod = module.ResolveToken(token) as IMethod;
else else
calledMethod = createMethodReference(asmRef, token); calledMethod = CreateMethodReference(asmRef, token);
callOpcode = getCallOpCode(creatorInfo, isCallvirt); callOpcode = GetCallOpCode(creatorInfo, isCallvirt);
} }
void getCallInfo_v10_r48717(DelegateInitInfo info, ProxyCreatorInfo creatorInfo, out IMethod calledMethod, out OpCode callOpcode) { void GetCallInfo_v10_r48717(DelegateInitInfo info, ProxyCreatorInfo creatorInfo, out IMethod calledMethod, out OpCode callOpcode) {
bool isNew = creatorInfo.version == ConfuserVersion.v14_r58802; bool isNew = creatorInfo.version == ConfuserVersion.v14_r58802;
int offs = creatorInfo.proxyCreatorType == ProxyCreatorType.CallOrCallvirt ? 2 : 1; int offs = creatorInfo.proxyCreatorType == ProxyCreatorType.CallOrCallvirt ? 2 : 1;
@ -303,18 +303,18 @@ namespace de4dot.code.deobfuscators.Confuser {
calledMethod = module.ResolveToken(token) as IMethod; calledMethod = module.ResolveToken(token) as IMethod;
else { else {
var asmRef = module.ResolveAssemblyRef((uint)info.field.Name.String[0] - 2 + 1); var asmRef = module.ResolveAssemblyRef((uint)info.field.Name.String[0] - 2 + 1);
calledMethod = createMethodReference(asmRef, token); calledMethod = CreateMethodReference(asmRef, token);
} }
bool isCallvirt = false; bool isCallvirt = false;
if (creatorInfo.proxyCreatorType == ProxyCreatorType.CallOrCallvirt && info.field.Name.String[callvirtOffs] == '\r') if (creatorInfo.proxyCreatorType == ProxyCreatorType.CallOrCallvirt && info.field.Name.String[callvirtOffs] == '\r')
isCallvirt = true; isCallvirt = true;
callOpcode = getCallOpCode(creatorInfo, isCallvirt); callOpcode = GetCallOpCode(creatorInfo, isCallvirt);
} }
void getCallInfo_v14_r58857(DelegateInitInfo info, ProxyCreatorInfo creatorInfo, out IMethod calledMethod, out OpCode callOpcode) { void GetCallInfo_v14_r58857(DelegateInitInfo info, ProxyCreatorInfo creatorInfo, out IMethod calledMethod, out OpCode callOpcode) {
int offs = creatorInfo.proxyCreatorType == ProxyCreatorType.CallOrCallvirt ? 1 : 0; int offs = creatorInfo.proxyCreatorType == ProxyCreatorType.CallOrCallvirt ? 1 : 0;
var nameInfo = decryptFieldName(info.field.Name.String); var nameInfo = DecryptFieldName(info.field.Name.String);
uint token = BitConverter.ToUInt32(nameInfo, offs) ^ creatorInfo.magic; uint token = BitConverter.ToUInt32(nameInfo, offs) ^ creatorInfo.magic;
uint table = token >> 24; uint table = token >> 24;
@ -326,17 +326,17 @@ namespace de4dot.code.deobfuscators.Confuser {
bool isCallvirt = false; bool isCallvirt = false;
if (creatorInfo.proxyCreatorType == ProxyCreatorType.CallOrCallvirt && nameInfo[0] == '\r') if (creatorInfo.proxyCreatorType == ProxyCreatorType.CallOrCallvirt && nameInfo[0] == '\r')
isCallvirt = true; isCallvirt = true;
callOpcode = getCallOpCode(creatorInfo, isCallvirt); callOpcode = GetCallOpCode(creatorInfo, isCallvirt);
} }
static byte[] decryptFieldName(string name) { static byte[] DecryptFieldName(string name) {
var chars = new char[name.Length]; var chars = new char[name.Length];
for (int i = 0; i < chars.Length; i++) for (int i = 0; i < chars.Length; i++)
chars[i] = (char)((byte)name[i] ^ i); chars[i] = (char)((byte)name[i] ^ i);
return Convert.FromBase64CharArray(chars, 0, chars.Length); return Convert.FromBase64CharArray(chars, 0, chars.Length);
} }
void extract_v17_r73740(ProxyCreatorInfo creatorInfo, byte[] nameInfo, out uint arg, out uint table, out bool isCallvirt) { void Extract_v17_r73740(ProxyCreatorInfo creatorInfo, byte[] nameInfo, out uint arg, out uint table, out bool isCallvirt) {
switch (creatorInfo.proxyCreatorType) { switch (creatorInfo.proxyCreatorType) {
case ProxyCreatorType.CallOrCallvirt: case ProxyCreatorType.CallOrCallvirt:
arg = BitConverter.ToUInt32(nameInfo, 1); arg = BitConverter.ToUInt32(nameInfo, 1);
@ -355,43 +355,43 @@ namespace de4dot.code.deobfuscators.Confuser {
} }
} }
void getCallInfo_v17_r73740_normal(DelegateInitInfo info, ProxyCreatorInfo creatorInfo, out IMethod calledMethod, out OpCode callOpcode) { void GetCallInfo_v17_r73740_normal(DelegateInitInfo info, ProxyCreatorInfo creatorInfo, out IMethod calledMethod, out OpCode callOpcode) {
var nameInfo = decryptFieldName(info.field.Name.String); var nameInfo = DecryptFieldName(info.field.Name.String);
uint arg, table; uint arg, table;
bool isCallvirt; bool isCallvirt;
extract_v17_r73740(creatorInfo, nameInfo, out arg, out table, out isCallvirt); Extract_v17_r73740(creatorInfo, nameInfo, out arg, out table, out isCallvirt);
uint token = (arg ^ creatorInfo.magic) | table; uint token = (arg ^ creatorInfo.magic) | table;
calledMethod = module.ResolveToken((int)token) as IMethod; calledMethod = module.ResolveToken((int)token) as IMethod;
callOpcode = getCallOpCode(creatorInfo, isCallvirt); callOpcode = GetCallOpCode(creatorInfo, isCallvirt);
} }
void getCallInfo_v17_r73740_native(DelegateInitInfo info, ProxyCreatorInfo creatorInfo, out IMethod calledMethod, out OpCode callOpcode) { void GetCallInfo_v17_r73740_native(DelegateInitInfo info, ProxyCreatorInfo creatorInfo, out IMethod calledMethod, out OpCode callOpcode) {
var nameInfo = decryptFieldName(info.field.Name.String); var nameInfo = DecryptFieldName(info.field.Name.String);
uint arg, table; uint arg, table;
bool isCallvirt; bool isCallvirt;
extract_v17_r73740(creatorInfo, nameInfo, out arg, out table, out isCallvirt); Extract_v17_r73740(creatorInfo, nameInfo, out arg, out table, out isCallvirt);
if (x86emu == null) if (x86emu == null)
x86emu = new x86Emulator(fileData); x86emu = new x86Emulator(fileData);
uint token = x86emu.emulate((uint)creatorInfo.nativeMethod.RVA, arg) | table; uint token = x86emu.Emulate((uint)creatorInfo.nativeMethod.RVA, arg) | table;
calledMethod = module.ResolveToken((int)token) as IMethod; calledMethod = module.ResolveToken((int)token) as IMethod;
callOpcode = getCallOpCode(creatorInfo, isCallvirt); callOpcode = GetCallOpCode(creatorInfo, isCallvirt);
} }
void getCallInfo_v18_r75367_normal(DelegateInitInfo info, ProxyCreatorInfo creatorInfo, out IMethod calledMethod, out OpCode callOpcode) { void GetCallInfo_v18_r75367_normal(DelegateInitInfo info, ProxyCreatorInfo creatorInfo, out IMethod calledMethod, out OpCode callOpcode) {
getCallInfo_v18_r75367(info, creatorInfo, out calledMethod, out callOpcode, (creatorInfo2, magic) => creatorInfo2.magic ^ magic); GetCallInfo_v18_r75367(info, creatorInfo, out calledMethod, out callOpcode, (creatorInfo2, magic) => creatorInfo2.magic ^ magic);
} }
void getCallInfo_v18_r75367_native(DelegateInitInfo info, ProxyCreatorInfo creatorInfo, out IMethod calledMethod, out OpCode callOpcode) { void GetCallInfo_v18_r75367_native(DelegateInitInfo info, ProxyCreatorInfo creatorInfo, out IMethod calledMethod, out OpCode callOpcode) {
getCallInfo_v18_r75367(info, creatorInfo, out calledMethod, out callOpcode, (creatorInfo2, magic) => { GetCallInfo_v18_r75367(info, creatorInfo, out calledMethod, out callOpcode, (creatorInfo2, magic) => {
if (x86emu == null) if (x86emu == null)
x86emu = new x86Emulator(fileData); x86emu = new x86Emulator(fileData);
return x86emu.emulate((uint)creatorInfo2.nativeMethod.RVA, magic); return x86emu.Emulate((uint)creatorInfo2.nativeMethod.RVA, magic);
}); });
} }
void getCallInfo_v18_r75367(DelegateInitInfo info, ProxyCreatorInfo creatorInfo, out IMethod calledMethod, out OpCode callOpcode, Func<ProxyCreatorInfo, uint, uint> getRid) { void GetCallInfo_v18_r75367(DelegateInitInfo info, ProxyCreatorInfo creatorInfo, out IMethod calledMethod, out OpCode callOpcode, Func<ProxyCreatorInfo, uint, uint> getRid) {
var sig = module.ReadBlob(info.field.MDToken.Raw); var sig = module.ReadBlob(info.field.MDToken.Raw);
int len = sig.Length; int len = sig.Length;
uint magic = (uint)((sig[len - 2] << 24) | (sig[len - 3] << 16) | (sig[len - 5] << 8) | sig[len - 6]); uint magic = (uint)((sig[len - 2] << 24) | (sig[len - 3] << 16) | (sig[len - 5] << 8) | sig[len - 6]);
@ -401,10 +401,10 @@ namespace de4dot.code.deobfuscators.Confuser {
if (table != 6 && table != 0x0A && table != 0x2B) if (table != 6 && table != 0x0A && table != 0x2B)
throw new ApplicationException("Invalid method token"); throw new ApplicationException("Invalid method token");
calledMethod = module.ResolveToken(token) as IMethod; calledMethod = module.ResolveToken(token) as IMethod;
callOpcode = getCallOpCode(creatorInfo, info.field); callOpcode = GetCallOpCode(creatorInfo, info.field);
} }
static OpCode getCallOpCode(ProxyCreatorInfo info, FieldDef field) { static OpCode GetCallOpCode(ProxyCreatorInfo info, FieldDef field) {
switch (info.proxyCreatorType) { switch (info.proxyCreatorType) {
case ProxyCreatorType.CallOrCallvirt: case ProxyCreatorType.CallOrCallvirt:
if (field.Name.String.Length > 0 && field.Name.String[0] == info.callvirtChar) if (field.Name.String.Length > 0 && field.Name.String[0] == info.callvirtChar)
@ -420,7 +420,7 @@ namespace de4dot.code.deobfuscators.Confuser {
// A method token is not a stable value so this method can fail to return the correct method! // A method token is not a stable value so this method can fail to return the correct method!
// There's nothing I can do about that. It's an obfuscator bug. It was fixed in 1.3 r55346. // There's nothing I can do about that. It's an obfuscator bug. It was fixed in 1.3 r55346.
IMethod createMethodReference(AssemblyRef asmRef, uint methodToken) { IMethod CreateMethodReference(AssemblyRef asmRef, uint methodToken) {
var asm = module.Context.AssemblyResolver.Resolve(asmRef, module); var asm = module.Context.AssemblyResolver.Resolve(asmRef, module);
if (asm == null) if (asm == null)
return null; return null;
@ -432,15 +432,15 @@ namespace de4dot.code.deobfuscators.Confuser {
return module.Import(method); return module.Import(method);
} }
AssemblyRef readAssemblyNameReference(BinaryReader reader) { AssemblyRef ReadAssemblyNameReference(BinaryReader reader) {
var name = readString(reader); var name = ReadString(reader);
var version = new Version(reader.ReadInt16(), reader.ReadInt16(), reader.ReadInt16(), reader.ReadInt16()); var version = new Version(reader.ReadInt16(), reader.ReadInt16(), reader.ReadInt16(), reader.ReadInt16());
var culture = readString(reader); var culture = ReadString(reader);
byte[] pkt = reader.ReadBoolean() ? reader.ReadBytes(8) : null; byte[] pkt = reader.ReadBoolean() ? reader.ReadBytes(8) : null;
return module.UpdateRowId(new AssemblyRefUser(name, version, pkt == null ? null : new PublicKeyToken(pkt), culture)); return module.UpdateRowId(new AssemblyRefUser(name, version, pkt == null ? null : new PublicKeyToken(pkt), culture));
} }
static string readString(BinaryReader reader) { static string ReadString(BinaryReader reader) {
int len = reader.ReadByte(); int len = reader.ReadByte();
var bytes = new byte[len]; var bytes = new byte[len];
for (int i = 0; i < len; i++) for (int i = 0; i < len; i++)
@ -448,7 +448,7 @@ namespace de4dot.code.deobfuscators.Confuser {
return Encoding.UTF8.GetString(bytes); return Encoding.UTF8.GetString(bytes);
} }
static OpCode getCallOpCode(ProxyCreatorInfo info, bool isCallvirt) { static OpCode GetCallOpCode(ProxyCreatorInfo info, bool isCallvirt) {
switch (info.proxyCreatorType) { switch (info.proxyCreatorType) {
case ProxyCreatorType.Newobj: case ProxyCreatorType.Newobj:
return OpCodes.Newobj; return OpCodes.Newobj;
@ -460,8 +460,8 @@ namespace de4dot.code.deobfuscators.Confuser {
} }
} }
public void findDelegateCreator(ISimpleDeobfuscator simpleDeobfuscator) { public void FindDelegateCreator(ISimpleDeobfuscator simpleDeobfuscator) {
var type = DotNetUtils.getModuleType(module); var type = DotNetUtils.GetModuleType(module);
if (type == null) if (type == null)
return; return;
foreach (var method in type.Methods) { foreach (var method in type.Methods) {
@ -469,90 +469,90 @@ namespace de4dot.code.deobfuscators.Confuser {
continue; continue;
ConfuserVersion theVersion = ConfuserVersion.Unknown; ConfuserVersion theVersion = ConfuserVersion.Unknown;
if (DotNetUtils.isMethod(method, "System.Void", "(System.String,System.RuntimeFieldHandle)")) if (DotNetUtils.IsMethod(method, "System.Void", "(System.String,System.RuntimeFieldHandle)"))
theVersion = ConfuserVersion.v10_r42915; theVersion = ConfuserVersion.v10_r42915;
else if (DotNetUtils.isMethod(method, "System.Void", "(System.RuntimeFieldHandle)")) else if (DotNetUtils.IsMethod(method, "System.Void", "(System.RuntimeFieldHandle)"))
theVersion = ConfuserVersion.v10_r48717; theVersion = ConfuserVersion.v10_r48717;
else else
continue; continue;
var proxyType = getProxyCreatorType(method); var proxyType = GetProxyCreatorType(method);
if (proxyType == ProxyCreatorType.None) if (proxyType == ProxyCreatorType.None)
continue; continue;
simpleDeobfuscator.deobfuscate(method); simpleDeobfuscator.Deobfuscate(method);
MethodDef nativeMethod = null; MethodDef nativeMethod = null;
uint magic; uint magic;
if (findMagic_v14_r58564(method, out magic)) { if (FindMagic_v14_r58564(method, out magic)) {
if (!DotNetUtils.callsMethod(method, "System.Byte[] System.Convert::FromBase64String(System.String)")) { if (!DotNetUtils.CallsMethod(method, "System.Byte[] System.Convert::FromBase64String(System.String)")) {
if (!isMethodCreator_v14_r58802(method, proxyType)) if (!IsMethodCreator_v14_r58802(method, proxyType))
theVersion = ConfuserVersion.v14_r58564; theVersion = ConfuserVersion.v14_r58564;
else else
theVersion = ConfuserVersion.v14_r58802; theVersion = ConfuserVersion.v14_r58802;
} }
else if (DotNetUtils.callsMethod(method, "System.Reflection.Module System.Reflection.MemberInfo::get_Module()")) else if (DotNetUtils.CallsMethod(method, "System.Reflection.Module System.Reflection.MemberInfo::get_Module()"))
theVersion = ConfuserVersion.v17_r73479; theVersion = ConfuserVersion.v17_r73479;
else if (proxyType != ProxyCreatorType.CallOrCallvirt || !hasFieldReference(method, "System.Reflection.Emit.OpCode System.Reflection.Emit.OpCodes::Castclass")) else if (proxyType != ProxyCreatorType.CallOrCallvirt || !HasFieldReference(method, "System.Reflection.Emit.OpCode System.Reflection.Emit.OpCodes::Castclass"))
theVersion = ConfuserVersion.v14_r58857; theVersion = ConfuserVersion.v14_r58857;
else if (proxyType == ProxyCreatorType.CallOrCallvirt && DotNetUtils.callsMethod(method, "System.Void System.Reflection.Emit.DynamicMethod::.ctor(System.String,System.Type,System.Type[],System.Boolean)")) else if (proxyType == ProxyCreatorType.CallOrCallvirt && DotNetUtils.CallsMethod(method, "System.Void System.Reflection.Emit.DynamicMethod::.ctor(System.String,System.Type,System.Type[],System.Boolean)"))
theVersion = ConfuserVersion.v16_r66631; theVersion = ConfuserVersion.v16_r66631;
else if (proxyType == ProxyCreatorType.CallOrCallvirt) else if (proxyType == ProxyCreatorType.CallOrCallvirt)
theVersion = ConfuserVersion.v16_r70489; theVersion = ConfuserVersion.v16_r70489;
} }
else if (!DotNetUtils.callsMethod(method, "System.Byte[] System.Convert::FromBase64String(System.String)") && else if (!DotNetUtils.CallsMethod(method, "System.Byte[] System.Convert::FromBase64String(System.String)") &&
DotNetUtils.callsMethod(method, "System.Reflection.MethodBase System.Reflection.Module::ResolveMethod(System.Int32)")) { DotNetUtils.CallsMethod(method, "System.Reflection.MethodBase System.Reflection.Module::ResolveMethod(System.Int32)")) {
if (proxyType == ProxyCreatorType.CallOrCallvirt && !findCallvirtChar(method, out callvirtChar)) if (proxyType == ProxyCreatorType.CallOrCallvirt && !FindCallvirtChar(method, out callvirtChar))
continue; continue;
if ((nativeMethod = findNativeMethod_v18_r75367(method)) != null) if ((nativeMethod = FindNativeMethod_v18_r75367(method)) != null)
theVersion = proxyType != ProxyCreatorType.CallOrCallvirt || callvirtChar == 9 ? ConfuserVersion.v18_r75367_native : ConfuserVersion.v18_r75369_native; theVersion = proxyType != ProxyCreatorType.CallOrCallvirt || callvirtChar == 9 ? ConfuserVersion.v18_r75367_native : ConfuserVersion.v18_r75369_native;
else if (findMagic_v18_r75367(method, out magic)) else if (FindMagic_v18_r75367(method, out magic))
theVersion = proxyType != ProxyCreatorType.CallOrCallvirt || callvirtChar == 9 ? ConfuserVersion.v18_r75367_normal : ConfuserVersion.v18_r75369_normal; theVersion = proxyType != ProxyCreatorType.CallOrCallvirt || callvirtChar == 9 ? ConfuserVersion.v18_r75367_normal : ConfuserVersion.v18_r75369_normal;
else if (findMagic_v19_r76101(method, out magic)) else if (FindMagic_v19_r76101(method, out magic))
theVersion = ConfuserVersion.v19_r76101_normal; theVersion = ConfuserVersion.v19_r76101_normal;
else if ((nativeMethod = findNativeMethod_v19_r76101(method)) != null) else if ((nativeMethod = FindNativeMethod_v19_r76101(method)) != null)
theVersion = ConfuserVersion.v19_r76101_native; theVersion = ConfuserVersion.v19_r76101_native;
else { else {
if (proxyType == ProxyCreatorType.CallOrCallvirt && !DotNetUtils.callsMethod(method, "System.Int32 System.String::get_Length()")) if (proxyType == ProxyCreatorType.CallOrCallvirt && !DotNetUtils.CallsMethod(method, "System.Int32 System.String::get_Length()"))
theVersion = ConfuserVersion.v11_r50378; theVersion = ConfuserVersion.v11_r50378;
int numCalls = ConfuserUtils.countCalls(method, "System.Byte[] System.Text.Encoding::GetBytes(System.Char[],System.Int32,System.Int32)"); int numCalls = ConfuserUtils.CountCalls(method, "System.Byte[] System.Text.Encoding::GetBytes(System.Char[],System.Int32,System.Int32)");
if (numCalls == 2) if (numCalls == 2)
theVersion = ConfuserVersion.v12_r54564; theVersion = ConfuserVersion.v12_r54564;
if (!DotNetUtils.callsMethod(method, "System.Reflection.Assembly System.Reflection.Assembly::Load(System.Reflection.AssemblyName)")) if (!DotNetUtils.CallsMethod(method, "System.Reflection.Assembly System.Reflection.Assembly::Load(System.Reflection.AssemblyName)"))
theVersion = ConfuserVersion.v13_r55346; theVersion = ConfuserVersion.v13_r55346;
if (DotNetUtils.callsMethod(method, "System.Void System.Runtime.CompilerServices.RuntimeHelpers::RunClassConstructor(System.RuntimeTypeHandle)")) if (DotNetUtils.CallsMethod(method, "System.Void System.Runtime.CompilerServices.RuntimeHelpers::RunClassConstructor(System.RuntimeTypeHandle)"))
theVersion = ConfuserVersion.v13_r55604; theVersion = ConfuserVersion.v13_r55604;
} }
} }
else if (is_v17_r73740(method)) { else if (Is_v17_r73740(method)) {
if (DotNetUtils.callsMethod(method, "System.Boolean System.Type::get_IsArray()")) { if (DotNetUtils.CallsMethod(method, "System.Boolean System.Type::get_IsArray()")) {
if ((nativeMethod = findNativeMethod_v17_r73740(method)) != null) if ((nativeMethod = FindNativeMethod_v17_r73740(method)) != null)
theVersion = ConfuserVersion.v17_r74708_native; theVersion = ConfuserVersion.v17_r74708_native;
else if (findMagic_v17_r73740(method, out magic)) else if (FindMagic_v17_r73740(method, out magic))
theVersion = ConfuserVersion.v17_r74708_normal; theVersion = ConfuserVersion.v17_r74708_normal;
else else
continue; continue;
} }
else { else {
if ((nativeMethod = findNativeMethod_v17_r73740(method)) != null) if ((nativeMethod = FindNativeMethod_v17_r73740(method)) != null)
theVersion = ConfuserVersion.v17_r73740_native; theVersion = ConfuserVersion.v17_r73740_native;
else if (findMagic_v17_r73740(method, out magic)) else if (FindMagic_v17_r73740(method, out magic))
theVersion = ConfuserVersion.v17_r73740_normal; theVersion = ConfuserVersion.v17_r73740_normal;
else else
continue; continue;
} }
} }
else if (theVersion == ConfuserVersion.v10_r42915) { else if (theVersion == ConfuserVersion.v10_r42915) {
if (DeobUtils.hasInteger(method, 0x06000000)) if (DeobUtils.HasInteger(method, 0x06000000))
theVersion = ConfuserVersion.v10_r42919; theVersion = ConfuserVersion.v10_r42919;
} }
setDelegateCreatorMethod(method); SetDelegateCreatorMethod(method);
methodToInfo.add(method, new ProxyCreatorInfo(method, proxyType, theVersion, magic, nativeMethod, callvirtChar)); methodToInfo.Add(method, new ProxyCreatorInfo(method, proxyType, theVersion, magic, nativeMethod, callvirtChar));
version = (ConfuserVersion)Math.Max((int)version, (int)theVersion); version = (ConfuserVersion)Math.Max((int)version, (int)theVersion);
} }
} }
static bool hasFieldReference(MethodDef method, string fieldFullName) { static bool HasFieldReference(MethodDef method, string fieldFullName) {
foreach (var instr in method.Body.Instructions) { foreach (var instr in method.Body.Instructions) {
var field = instr.Operand as IField; var field = instr.Operand as IField;
if (field == null) if (field == null)
@ -563,8 +563,8 @@ namespace de4dot.code.deobfuscators.Confuser {
return false; return false;
} }
static bool isMethodCreator_v14_r58802(MethodDef method, ProxyCreatorType proxyType) { static bool IsMethodCreator_v14_r58802(MethodDef method, ProxyCreatorType proxyType) {
int index = getFieldNameIndex(method); int index = GetFieldNameIndex(method);
if (index < 0) if (index < 0)
throw new ApplicationException("Could not find field name index"); throw new ApplicationException("Could not find field name index");
switch (proxyType) { switch (proxyType) {
@ -588,10 +588,10 @@ namespace de4dot.code.deobfuscators.Confuser {
throw new ApplicationException("Could not find field name index"); throw new ApplicationException("Could not find field name index");
} }
static int getFieldNameIndex(MethodDef method) { static int GetFieldNameIndex(MethodDef method) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count; i++) { for (int i = 0; i < instrs.Count; i++) {
i = ConfuserUtils.findCallMethod(instrs, i, Code.Callvirt, "System.Byte[] System.Text.Encoding::GetBytes(System.Char[],System.Int32,System.Int32)"); i = ConfuserUtils.FindCallMethod(instrs, i, Code.Callvirt, "System.Byte[] System.Text.Encoding::GetBytes(System.Char[],System.Int32,System.Int32)");
if (i < 0) if (i < 0)
break; break;
if (i < 2) if (i < 2)
@ -605,7 +605,7 @@ namespace de4dot.code.deobfuscators.Confuser {
return -1; return -1;
} }
static bool findMagic_v19_r76101(MethodDef method, out uint magic) { static bool FindMagic_v19_r76101(MethodDef method, out uint magic) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count - 7; i++) { for (int i = 0; i < instrs.Count - 7; i++) {
var ldci4_1 = instrs[i]; var ldci4_1 = instrs[i];
@ -634,7 +634,7 @@ namespace de4dot.code.deobfuscators.Confuser {
return false; return false;
} }
static MethodDef findNativeMethod_v19_r76101(MethodDef method) { static MethodDef FindNativeMethod_v19_r76101(MethodDef method) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count - 6; i++) { for (int i = 0; i < instrs.Count - 6; i++) {
var ldci4 = instrs[i]; var ldci4 = instrs[i];
@ -662,10 +662,10 @@ namespace de4dot.code.deobfuscators.Confuser {
return null; return null;
} }
static bool findMagic_v18_r75367(MethodDef method, out uint magic) { static bool FindMagic_v18_r75367(MethodDef method, out uint magic) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count; i++) { for (int i = 0; i < instrs.Count; i++) {
i = ConfuserUtils.findCallMethod(instrs, i, Code.Callvirt, "System.Reflection.Module System.Reflection.MemberInfo::get_Module()"); i = ConfuserUtils.FindCallMethod(instrs, i, Code.Callvirt, "System.Reflection.Module System.Reflection.MemberInfo::get_Module()");
if (i < 0 || i + 3 >= instrs.Count) if (i < 0 || i + 3 >= instrs.Count)
break; break;
@ -684,10 +684,10 @@ namespace de4dot.code.deobfuscators.Confuser {
return false; return false;
} }
static MethodDef findNativeMethod_v18_r75367(MethodDef method) { static MethodDef FindNativeMethod_v18_r75367(MethodDef method) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count; i++) { for (int i = 0; i < instrs.Count; i++) {
i = ConfuserUtils.findCallMethod(instrs, i, Code.Callvirt, "System.Reflection.Module System.Reflection.MemberInfo::get_Module()"); i = ConfuserUtils.FindCallMethod(instrs, i, Code.Callvirt, "System.Reflection.Module System.Reflection.MemberInfo::get_Module()");
if (i < 0 || i + 2 >= instrs.Count) if (i < 0 || i + 2 >= instrs.Count)
break; break;
@ -706,10 +706,10 @@ namespace de4dot.code.deobfuscators.Confuser {
return null; return null;
} }
static bool findMagic_v17_r73740(MethodDef method, out uint magic) { static bool FindMagic_v17_r73740(MethodDef method, out uint magic) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count; i++) { for (int i = 0; i < instrs.Count; i++) {
int index = ConfuserUtils.findCallMethod(instrs, i, Code.Call, "System.Int32 System.BitConverter::ToInt32(System.Byte[],System.Int32)"); int index = ConfuserUtils.FindCallMethod(instrs, i, Code.Call, "System.Int32 System.BitConverter::ToInt32(System.Byte[],System.Int32)");
if (index < 0) if (index < 0)
break; break;
if (index < 1 || index + 2 >= instrs.Count) if (index < 1 || index + 2 >= instrs.Count)
@ -730,10 +730,10 @@ namespace de4dot.code.deobfuscators.Confuser {
return false; return false;
} }
static MethodDef findNativeMethod_v17_r73740(MethodDef method) { static MethodDef FindNativeMethod_v17_r73740(MethodDef method) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count; i++) { for (int i = 0; i < instrs.Count; i++) {
int index = ConfuserUtils.findCallMethod(instrs, i, Code.Call, "System.Int32 System.BitConverter::ToInt32(System.Byte[],System.Int32)"); int index = ConfuserUtils.FindCallMethod(instrs, i, Code.Call, "System.Int32 System.BitConverter::ToInt32(System.Byte[],System.Int32)");
if (index < 0) if (index < 0)
break; break;
if (index < 1 || index + 1 >= instrs.Count) if (index < 1 || index + 1 >= instrs.Count)
@ -753,10 +753,10 @@ namespace de4dot.code.deobfuscators.Confuser {
return null; return null;
} }
static bool is_v17_r73740(MethodDef method) { static bool Is_v17_r73740(MethodDef method) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count; i++) { for (int i = 0; i < instrs.Count; i++) {
int index = ConfuserUtils.findCallMethod(instrs, i, Code.Callvirt, "System.Reflection.MethodBase System.Reflection.Module::ResolveMethod(System.Int32)"); int index = ConfuserUtils.FindCallMethod(instrs, i, Code.Callvirt, "System.Reflection.MethodBase System.Reflection.Module::ResolveMethod(System.Int32)");
if (index < 0) if (index < 0)
break; break;
if (index < 3) if (index < 3)
@ -776,13 +776,13 @@ namespace de4dot.code.deobfuscators.Confuser {
return false; return false;
} }
static bool findMagic_v14_r58564(MethodDef method, out uint magic) { static bool FindMagic_v14_r58564(MethodDef method, out uint magic) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count; i++) { for (int i = 0; i < instrs.Count; i++) {
int index = ConfuserUtils.findCallMethod(instrs, i, Code.Call, "System.Int32 System.BitConverter::ToInt32(System.Byte[],System.Int32)"); int index = ConfuserUtils.FindCallMethod(instrs, i, Code.Call, "System.Int32 System.BitConverter::ToInt32(System.Byte[],System.Int32)");
if (index < 0) if (index < 0)
break; break;
int index2 = ConfuserUtils.findCallMethod(instrs, i, Code.Callvirt, "System.Reflection.MethodBase System.Reflection.Module::ResolveMethod(System.Int32)"); int index2 = ConfuserUtils.FindCallMethod(instrs, i, Code.Callvirt, "System.Reflection.MethodBase System.Reflection.Module::ResolveMethod(System.Int32)");
if (index2 < 0 || index2 - index != 3) if (index2 < 0 || index2 - index != 3)
continue; continue;
var ldci4 = instrs[index + 1]; var ldci4 = instrs[index + 1];
@ -798,7 +798,7 @@ namespace de4dot.code.deobfuscators.Confuser {
return false; return false;
} }
static ProxyCreatorType getProxyCreatorType(MethodDef method) { static ProxyCreatorType GetProxyCreatorType(MethodDef method) {
foreach (var instr in method.Body.Instructions) { foreach (var instr in method.Body.Instructions) {
var field = instr.Operand as IField; var field = instr.Operand as IField;
if (field == null) if (field == null)
@ -815,21 +815,21 @@ namespace de4dot.code.deobfuscators.Confuser {
return ProxyCreatorType.None; return ProxyCreatorType.None;
} }
public new void find() { public new void Find() {
if (delegateCreatorMethods.Count == 0) if (delegateCreatorMethods.Count == 0)
return; return;
var cctor = DotNetUtils.getModuleTypeCctor(module); var cctor = DotNetUtils.GetModuleTypeCctor(module);
if (cctor == null) if (cctor == null)
return; return;
Logger.v("Finding all proxy delegates"); Logger.v("Finding all proxy delegates");
var delegateInfos = createDelegateInitInfos(cctor); var delegateInfos = CreateDelegateInitInfos(cctor);
fieldToMethods = createFieldToMethodsDictionary(cctor.DeclaringType); fieldToMethods = CreateFieldToMethodsDictionary(cctor.DeclaringType);
if (delegateInfos.Count < fieldToMethods.Count) if (delegateInfos.Count < fieldToMethods.Count)
throw new ApplicationException("Missing proxy delegates"); throw new ApplicationException("Missing proxy delegates");
var delegateToFields = new Dictionary<TypeDef, List<FieldDef>>(); var delegateToFields = new Dictionary<TypeDef, List<FieldDef>>();
foreach (var field in fieldToMethods.getKeys()) { foreach (var field in fieldToMethods.GetKeys()) {
List<FieldDef> list; List<FieldDef> list;
if (!delegateToFields.TryGetValue(field.FieldType.TryGetTypeDef(), out list)) if (!delegateToFields.TryGetValue(field.FieldType.TryGetTypeDef(), out list))
delegateToFields[field.FieldType.TryGetTypeDef()] = list = new List<FieldDef>(); delegateToFields[field.FieldType.TryGetTypeDef()] = list = new List<FieldDef>();
@ -840,52 +840,52 @@ namespace de4dot.code.deobfuscators.Confuser {
var type = kv.Key; var type = kv.Key;
var fields = kv.Value; var fields = kv.Value;
Logger.v("Found proxy delegate: {0} ({1:X8})", Utils.removeNewlines(type), type.MDToken.ToInt32()); Logger.v("Found proxy delegate: {0} ({1:X8})", Utils.RemoveNewlines(type), type.MDToken.ToInt32());
RemovedDelegateCreatorCalls++; RemovedDelegateCreatorCalls++;
Logger.Instance.indent(); Logger.Instance.Indent();
foreach (var field in fields) { foreach (var field in fields) {
var proxyMethods = fieldToMethods.find(field); var proxyMethods = fieldToMethods.Find(field);
if (proxyMethods == null) if (proxyMethods == null)
continue; continue;
var info = delegateInfos.find(field); var info = delegateInfos.Find(field);
if (info == null) if (info == null)
throw new ApplicationException("Missing proxy info"); throw new ApplicationException("Missing proxy info");
IMethod calledMethod; IMethod calledMethod;
OpCode callOpcode; OpCode callOpcode;
getCallInfo(info, field, out calledMethod, out callOpcode); GetCallInfo(info, field, out calledMethod, out callOpcode);
if (calledMethod == null) if (calledMethod == null)
continue; continue;
foreach (var proxyMethod in proxyMethods) { foreach (var proxyMethod in proxyMethods) {
add(proxyMethod, new DelegateInfo(field, calledMethod, callOpcode)); Add(proxyMethod, new DelegateInfo(field, calledMethod, callOpcode));
Logger.v("Field: {0}, Opcode: {1}, Method: {2} ({3:X8})", Logger.v("Field: {0}, Opcode: {1}, Method: {2} ({3:X8})",
Utils.removeNewlines(field.Name), Utils.RemoveNewlines(field.Name),
callOpcode, callOpcode,
Utils.removeNewlines(calledMethod), Utils.RemoveNewlines(calledMethod),
calledMethod.MDToken.ToUInt32()); calledMethod.MDToken.ToUInt32());
} }
} }
Logger.Instance.deIndent(); Logger.Instance.DeIndent();
delegateTypesDict[type] = true; delegateTypesDict[type] = true;
} }
// 1.2 r54564 (almost 1.3) now moves method proxy init code to the delegate cctors // 1.2 r54564 (almost 1.3) now moves method proxy init code to the delegate cctors
find2(); Find2();
} }
FieldDefAndDeclaringTypeDict<DelegateInitInfo> createDelegateInitInfos(MethodDef method) { FieldDefAndDeclaringTypeDict<DelegateInitInfo> CreateDelegateInitInfos(MethodDef method) {
switch (version) { switch (version) {
case ConfuserVersion.v10_r42915: case ConfuserVersion.v10_r42915:
case ConfuserVersion.v10_r42919: case ConfuserVersion.v10_r42919:
return createDelegateInitInfos_v10_r42915(method); return CreateDelegateInitInfos_v10_r42915(method);
default: default:
return createDelegateInitInfos_v10_r48717(method); return CreateDelegateInitInfos_v10_r48717(method);
} }
} }
FieldDefAndDeclaringTypeDict<DelegateInitInfo> createDelegateInitInfos_v10_r42915(MethodDef method) { FieldDefAndDeclaringTypeDict<DelegateInitInfo> CreateDelegateInitInfos_v10_r42915(MethodDef method) {
var infos = new FieldDefAndDeclaringTypeDict<DelegateInitInfo>(); var infos = new FieldDefAndDeclaringTypeDict<DelegateInitInfo>();
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count - 2; i++) { for (int i = 0; i < instrs.Count - 2; i++) {
@ -903,23 +903,23 @@ namespace de4dot.code.deobfuscators.Confuser {
if (delegateField == null) if (delegateField == null)
continue; continue;
var delegateType = delegateField.FieldType.TryGetTypeDef(); var delegateType = delegateField.FieldType.TryGetTypeDef();
if (!DotNetUtils.derivesFromDelegate(delegateType)) if (!DotNetUtils.DerivesFromDelegate(delegateType))
continue; continue;
var call = instrs[i + 2]; var call = instrs[i + 2];
if (call.OpCode.Code != Code.Call) if (call.OpCode.Code != Code.Call)
continue; continue;
var delegateCreatorMethod = call.Operand as MethodDef; var delegateCreatorMethod = call.Operand as MethodDef;
if (delegateCreatorMethod == null || !isDelegateCreatorMethod(delegateCreatorMethod)) if (delegateCreatorMethod == null || !IsDelegateCreatorMethod(delegateCreatorMethod))
continue; continue;
infos.add(delegateField, new DelegateInitInfo(info, delegateField, delegateCreatorMethod)); infos.Add(delegateField, new DelegateInitInfo(info, delegateField, delegateCreatorMethod));
i += 2; i += 2;
} }
return infos; return infos;
} }
FieldDefAndDeclaringTypeDict<DelegateInitInfo> createDelegateInitInfos_v10_r48717(MethodDef method) { FieldDefAndDeclaringTypeDict<DelegateInitInfo> CreateDelegateInitInfos_v10_r48717(MethodDef method) {
var infos = new FieldDefAndDeclaringTypeDict<DelegateInitInfo>(); var infos = new FieldDefAndDeclaringTypeDict<DelegateInitInfo>();
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count - 1; i++) { for (int i = 0; i < instrs.Count - 1; i++) {
@ -930,39 +930,39 @@ namespace de4dot.code.deobfuscators.Confuser {
if (delegateField == null) if (delegateField == null)
continue; continue;
var delegateType = delegateField.FieldType.TryGetTypeDef(); var delegateType = delegateField.FieldType.TryGetTypeDef();
if (!DotNetUtils.derivesFromDelegate(delegateType)) if (!DotNetUtils.DerivesFromDelegate(delegateType))
continue; continue;
var call = instrs[i + 1]; var call = instrs[i + 1];
if (call.OpCode.Code != Code.Call) if (call.OpCode.Code != Code.Call)
continue; continue;
var delegateCreatorMethod = call.Operand as MethodDef; var delegateCreatorMethod = call.Operand as MethodDef;
if (delegateCreatorMethod == null || !isDelegateCreatorMethod(delegateCreatorMethod)) if (delegateCreatorMethod == null || !IsDelegateCreatorMethod(delegateCreatorMethod))
continue; continue;
infos.add(delegateField, new DelegateInitInfo(delegateField, delegateCreatorMethod)); infos.Add(delegateField, new DelegateInitInfo(delegateField, delegateCreatorMethod));
i += 1; i += 1;
} }
return infos; return infos;
} }
static FieldDefAndDeclaringTypeDict<List<MethodDef>> createFieldToMethodsDictionary(TypeDef type) { static FieldDefAndDeclaringTypeDict<List<MethodDef>> CreateFieldToMethodsDictionary(TypeDef type) {
var dict = new FieldDefAndDeclaringTypeDict<List<MethodDef>>(); var dict = new FieldDefAndDeclaringTypeDict<List<MethodDef>>();
foreach (var method in type.Methods) { foreach (var method in type.Methods) {
if (!method.IsStatic || method.Body == null || method.Name == ".cctor") if (!method.IsStatic || method.Body == null || method.Name == ".cctor")
continue; continue;
var delegateField = getDelegateField(method); var delegateField = GetDelegateField(method);
if (delegateField == null) if (delegateField == null)
continue; continue;
var methods = dict.find(delegateField); var methods = dict.Find(delegateField);
if (methods == null) if (methods == null)
dict.add(delegateField, methods = new List<MethodDef>()); dict.Add(delegateField, methods = new List<MethodDef>());
methods.Add(method); methods.Add(method);
} }
return dict; return dict;
} }
static FieldDef getDelegateField(MethodDef method) { static FieldDef GetDelegateField(MethodDef method) {
if (method == null || method.Body == null) if (method == null || method.Body == null)
return null; return null;
@ -975,7 +975,7 @@ namespace de4dot.code.deobfuscators.Confuser {
continue; continue;
if (field != null) if (field != null)
return null; return null;
if (!DotNetUtils.derivesFromDelegate(field2.FieldType.TryGetTypeDef())) if (!DotNetUtils.DerivesFromDelegate(field2.FieldType.TryGetTypeDef()))
continue; continue;
field = field2; field = field2;
} }
@ -987,10 +987,10 @@ namespace de4dot.code.deobfuscators.Confuser {
return foundInvoke ? field : null; return foundInvoke ? field : null;
} }
static bool findCallvirtChar(MethodDef method, out ushort callvirtChar) { static bool FindCallvirtChar(MethodDef method, out ushort callvirtChar) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int index = 0; index < instrs.Count; index++) { for (int index = 0; index < instrs.Count; index++) {
index = ConfuserUtils.findCallMethod(instrs, index, Code.Callvirt, "System.Char System.String::get_Chars(System.Int32)"); index = ConfuserUtils.FindCallMethod(instrs, index, Code.Callvirt, "System.Char System.String::get_Chars(System.Int32)");
if (index < 0) if (index < 0)
break; break;
@ -1008,17 +1008,17 @@ namespace de4dot.code.deobfuscators.Confuser {
return false; return false;
} }
public void cleanUp() { public void CleanUp() {
if (!Detected) if (!Detected)
return; return;
var cctor = DotNetUtils.getModuleTypeCctor(module); var cctor = DotNetUtils.GetModuleTypeCctor(module);
if (cctor == null) if (cctor == null)
return; return;
cctor.Body.Instructions.Clear(); cctor.Body.Instructions.Clear();
cctor.Body.Instructions.Add(Instruction.Create(OpCodes.Ret)); cctor.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));
} }
public bool getRevisionRange(out int minRev, out int maxRev) { public bool GetRevisionRange(out int minRev, out int maxRev) {
switch (version) { switch (version) {
case ConfuserVersion.Unknown: case ConfuserVersion.Unknown:
minRev = maxRev = 0; minRev = maxRev = 0;

View File

@ -61,49 +61,49 @@ namespace de4dot.code.deobfuscators.Confuser {
this.simpleDeobfuscator = simpleDeobfuscator; this.simpleDeobfuscator = simpleDeobfuscator;
} }
public void find() { public void Find() {
if (checkMethod(DotNetUtils.getModuleTypeCctor(module))) if (CheckMethod(DotNetUtils.GetModuleTypeCctor(module)))
return; return;
} }
bool checkMethod(MethodDef method) { bool CheckMethod(MethodDef method) {
if (method == null || method.Body == null) if (method == null || method.Body == null)
return false; return false;
if (!DotNetUtils.callsMethod(method, "System.Void System.AppDomain::add_ResourceResolve(System.ResolveEventHandler)")) if (!DotNetUtils.CallsMethod(method, "System.Void System.AppDomain::add_ResourceResolve(System.ResolveEventHandler)"))
return false; return false;
simpleDeobfuscator.deobfuscate(method, true); simpleDeobfuscator.Deobfuscate(method, true);
fields.Clear(); fields.Clear();
var tmpHandler = getHandler(method); var tmpHandler = GetHandler(method);
if (tmpHandler == null || tmpHandler.DeclaringType != method.DeclaringType) if (tmpHandler == null || tmpHandler.DeclaringType != method.DeclaringType)
return false; return false;
var tmpResource = findResource(tmpHandler); var tmpResource = FindResource(tmpHandler);
if (tmpResource == null) if (tmpResource == null)
return false; return false;
simpleDeobfuscator.deobfuscate(tmpHandler, true); simpleDeobfuscator.Deobfuscate(tmpHandler, true);
ConfuserVersion tmpVersion = ConfuserVersion.Unknown; ConfuserVersion tmpVersion = ConfuserVersion.Unknown;
if (DotNetUtils.callsMethod(tmpHandler, "System.Object System.AppDomain::GetData(System.String)")) { if (DotNetUtils.CallsMethod(tmpHandler, "System.Object System.AppDomain::GetData(System.String)")) {
if (!DotNetUtils.callsMethod(tmpHandler, "System.Void System.Buffer::BlockCopy(System.Array,System.Int32,System.Array,System.Int32,System.Int32)")) { if (!DotNetUtils.CallsMethod(tmpHandler, "System.Void System.Buffer::BlockCopy(System.Array,System.Int32,System.Array,System.Int32,System.Int32)")) {
if (!findKey0Key1_v14_r55802(tmpHandler, out key0, out key1)) if (!FindKey0Key1_v14_r55802(tmpHandler, out key0, out key1))
return false; return false;
tmpVersion = ConfuserVersion.v14_r55802; tmpVersion = ConfuserVersion.v14_r55802;
} }
else if (findKey0_v17_r73404(tmpHandler, out key0) && findKey1_v17_r73404(tmpHandler, out key1)) else if (FindKey0_v17_r73404(tmpHandler, out key0) && FindKey1_v17_r73404(tmpHandler, out key1))
tmpVersion = ConfuserVersion.v17_r73404; tmpVersion = ConfuserVersion.v17_r73404;
else else
return false; return false;
} }
else { else {
if (addFields(findFields(tmpHandler, method.DeclaringType)) != 1) if (AddFields(FindFields(tmpHandler, method.DeclaringType)) != 1)
return false; return false;
if (findKey0_v17_r73404(tmpHandler, out key0) && findKey1_v17_r73404(tmpHandler, out key1)) if (FindKey0_v17_r73404(tmpHandler, out key0) && FindKey1_v17_r73404(tmpHandler, out key1))
tmpVersion = ConfuserVersion.v17_r73822; tmpVersion = ConfuserVersion.v17_r73822;
else if (findKey0_v18_r75367(tmpHandler, out key0) && findKey1_v17_r73404(tmpHandler, out key1)) else if (FindKey0_v18_r75367(tmpHandler, out key0) && FindKey1_v17_r73404(tmpHandler, out key1))
tmpVersion = ConfuserVersion.v18_r75367; tmpVersion = ConfuserVersion.v18_r75367;
else if (findKey0_v18_r75369(tmpHandler, out key0) && findKey1_v18_r75369(tmpHandler, out key1)) else if (FindKey0_v18_r75369(tmpHandler, out key0) && FindKey1_v18_r75369(tmpHandler, out key1))
tmpVersion = ConfuserVersion.v18_r75369; tmpVersion = ConfuserVersion.v18_r75369;
else else
return false; return false;
@ -116,7 +116,7 @@ namespace de4dot.code.deobfuscators.Confuser {
return true; return true;
} }
static MethodDef getHandler(MethodDef method) { static MethodDef GetHandler(MethodDef method) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count - 2; i++) { for (int i = 0; i < instrs.Count - 2; i++) {
var ldftn = instrs[i]; var ldftn = instrs[i];
@ -144,16 +144,16 @@ namespace de4dot.code.deobfuscators.Confuser {
return null; return null;
} }
int addFields(IEnumerable<FieldDef> moreFields) { int AddFields(IEnumerable<FieldDef> moreFields) {
int count = 0; int count = 0;
foreach (var field in moreFields) { foreach (var field in moreFields) {
if (addField(field)) if (AddField(field))
count++; count++;
} }
return count; return count;
} }
bool addField(FieldDef field) { bool AddField(FieldDef field) {
if (field == null) if (field == null)
return false; return false;
if (fields.ContainsKey(field)) if (fields.ContainsKey(field))
@ -162,7 +162,7 @@ namespace de4dot.code.deobfuscators.Confuser {
return true; return true;
} }
static IEnumerable<FieldDef> findFields(MethodDef method, TypeDef declaringType) { static IEnumerable<FieldDef> FindFields(MethodDef method, TypeDef declaringType) {
var fields = new List<FieldDef>(); var fields = new List<FieldDef>();
foreach (var instr in method.Body.Instructions) { foreach (var instr in method.Body.Instructions) {
var field = instr.Operand as FieldDef; var field = instr.Operand as FieldDef;
@ -172,14 +172,14 @@ namespace de4dot.code.deobfuscators.Confuser {
return fields; return fields;
} }
EmbeddedResource findResource(MethodDef method) { EmbeddedResource FindResource(MethodDef method) {
return DotNetUtils.getResource(module, DotNetUtils.getCodeStrings(method)) as EmbeddedResource; return DotNetUtils.GetResource(module, DotNetUtils.GetCodeStrings(method)) as EmbeddedResource;
} }
static bool findKey0_v18_r75367(MethodDef method, out byte key0) { static bool FindKey0_v18_r75367(MethodDef method, out byte key0) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count; i++) { for (int i = 0; i < instrs.Count; i++) {
i = ConfuserUtils.findCallMethod(instrs, i, Code.Callvirt, "System.Int32 System.IO.Stream::Read(System.Byte[],System.Int32,System.Int32)"); i = ConfuserUtils.FindCallMethod(instrs, i, Code.Callvirt, "System.Int32 System.IO.Stream::Read(System.Byte[],System.Int32,System.Int32)");
if (i < 0) if (i < 0)
break; break;
if (i + 3 >= instrs.Count) if (i + 3 >= instrs.Count)
@ -201,10 +201,10 @@ namespace de4dot.code.deobfuscators.Confuser {
return false; return false;
} }
static bool findKey0_v18_r75369(MethodDef method, out byte key0) { static bool FindKey0_v18_r75369(MethodDef method, out byte key0) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int index = 0; index < instrs.Count; index++) { for (int index = 0; index < instrs.Count; index++) {
index = ConfuserUtils.findCallMethod(instrs, index, Code.Callvirt, "System.Int32 System.IO.Stream::Read(System.Byte[],System.Int32,System.Int32)"); index = ConfuserUtils.FindCallMethod(instrs, index, Code.Callvirt, "System.Int32 System.IO.Stream::Read(System.Byte[],System.Int32,System.Int32)");
if (index < 0) if (index < 0)
break; break;
@ -230,7 +230,7 @@ namespace de4dot.code.deobfuscators.Confuser {
return false; return false;
} }
static bool findKey1_v18_r75369(MethodDef method, out byte key1) { static bool FindKey1_v18_r75369(MethodDef method, out byte key1) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count - 4; i++) { for (int i = 0; i < instrs.Count - 4; i++) {
int index = i; int index = i;
@ -255,7 +255,7 @@ namespace de4dot.code.deobfuscators.Confuser {
return false; return false;
} }
static bool findKey0Key1_v14_r55802(MethodDef method, out byte key0, out byte key1) { static bool FindKey0Key1_v14_r55802(MethodDef method, out byte key0, out byte key1) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count - 5; i++) { for (int i = 0; i < instrs.Count - 5; i++) {
if (!instrs[i].IsLdcI4()) if (!instrs[i].IsLdcI4())
@ -282,10 +282,10 @@ namespace de4dot.code.deobfuscators.Confuser {
return false; return false;
} }
static bool findKey0_v17_r73404(MethodDef method, out byte key) { static bool FindKey0_v17_r73404(MethodDef method, out byte key) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count - 3; i++) { for (int i = 0; i < instrs.Count - 3; i++) {
int index = ConfuserUtils.findCallMethod(instrs, i, Code.Callvirt, "System.Byte[] System.IO.BinaryReader::ReadBytes(System.Int32)"); int index = ConfuserUtils.FindCallMethod(instrs, i, Code.Callvirt, "System.Byte[] System.IO.BinaryReader::ReadBytes(System.Int32)");
if (index < 0) if (index < 0)
break; break;
if (index + 3 >= instrs.Count) if (index + 3 >= instrs.Count)
@ -306,7 +306,7 @@ namespace de4dot.code.deobfuscators.Confuser {
return false; return false;
} }
static bool findKey1_v17_r73404(MethodDef method, out byte key) { static bool FindKey1_v17_r73404(MethodDef method, out byte key) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count - 3; i++) { for (int i = 0; i < instrs.Count - 3; i++) {
var ldci4_1 = instrs[i]; var ldci4_1 = instrs[i];
@ -327,40 +327,40 @@ namespace de4dot.code.deobfuscators.Confuser {
return false; return false;
} }
public EmbeddedResource mergeResources() { public EmbeddedResource MergeResources() {
if (resource == null) if (resource == null)
return null; return null;
DeobUtils.decryptAndAddResources(module, resource.Name.String, () => decryptResource()); DeobUtils.DecryptAndAddResources(module, resource.Name.String, () => DecryptResource());
var tmpResource = resource; var tmpResource = resource;
resource = null; resource = null;
return tmpResource; return tmpResource;
} }
byte[] decryptResource() { byte[] DecryptResource() {
switch (version) { switch (version) {
case ConfuserVersion.v14_r55802: return decrypt_v14_r55802(); case ConfuserVersion.v14_r55802: return Decrypt_v14_r55802();
case ConfuserVersion.v17_r73404: return decrypt_v17_r73404(); case ConfuserVersion.v17_r73404: return Decrypt_v17_r73404();
case ConfuserVersion.v17_r73822: return decrypt_v17_r73404(); case ConfuserVersion.v17_r73822: return Decrypt_v17_r73404();
case ConfuserVersion.v18_r75367: return decrypt_v18_r75367(); case ConfuserVersion.v18_r75367: return Decrypt_v18_r75367();
case ConfuserVersion.v18_r75369: return decrypt_v18_r75367(); case ConfuserVersion.v18_r75369: return Decrypt_v18_r75367();
default: throw new ApplicationException("Unknown version"); default: throw new ApplicationException("Unknown version");
} }
} }
byte[] decrypt_v14_r55802() { byte[] Decrypt_v14_r55802() {
var reader = new BinaryReader(new MemoryStream(DeobUtils.inflate(resource.GetResourceData(), true))); var reader = new BinaryReader(new MemoryStream(DeobUtils.Inflate(resource.GetResourceData(), true)));
var encypted = reader.ReadBytes(reader.ReadInt32()); var encypted = reader.ReadBytes(reader.ReadInt32());
if ((encypted.Length & 1) != 0) if ((encypted.Length & 1) != 0)
throw new ApplicationException("Invalid resource data length"); throw new ApplicationException("Invalid resource data length");
var decrypted = new byte[encypted.Length / 2]; var decrypted = new byte[encypted.Length / 2];
for (int i = 0; i < decrypted.Length; i++) for (int i = 0; i < decrypted.Length; i++)
decrypted[i] = (byte)((encypted[i * 2 + 1] ^ key0) * key1 + (encypted[i * 2] ^ key0)); decrypted[i] = (byte)((encypted[i * 2 + 1] ^ key0) * key1 + (encypted[i * 2] ^ key0));
reader = new BinaryReader(new MemoryStream(DeobUtils.inflate(decrypted, true))); reader = new BinaryReader(new MemoryStream(DeobUtils.Inflate(decrypted, true)));
return reader.ReadBytes(reader.ReadInt32()); return reader.ReadBytes(reader.ReadInt32());
} }
byte[] decrypt_v17_r73404() { byte[] Decrypt_v17_r73404() {
var reader = new BinaryReader(new MemoryStream(DeobUtils.inflate(resource.GetResourceData(), true))); var reader = new BinaryReader(new MemoryStream(DeobUtils.Inflate(resource.GetResourceData(), true)));
var decrypted = reader.ReadBytes(reader.ReadInt32()); var decrypted = reader.ReadBytes(reader.ReadInt32());
byte k = key0; byte k = key0;
for (int i = 0; i < decrypted.Length; i++) { for (int i = 0; i < decrypted.Length; i++) {
@ -370,24 +370,24 @@ namespace de4dot.code.deobfuscators.Confuser {
return decrypted; return decrypted;
} }
byte[] decrypt_v18_r75367() { byte[] Decrypt_v18_r75367() {
var encrypted = resource.GetResourceData(); var encrypted = resource.GetResourceData();
byte k = key0; byte k = key0;
for (int i = 0; i < encrypted.Length; i++) { for (int i = 0; i < encrypted.Length; i++) {
encrypted[i] ^= k; encrypted[i] ^= k;
k *= key1; k *= key1;
} }
var reader = new BinaryReader(new MemoryStream(DeobUtils.inflate(encrypted, true))); var reader = new BinaryReader(new MemoryStream(DeobUtils.Inflate(encrypted, true)));
return reader.ReadBytes(reader.ReadInt32()); return reader.ReadBytes(reader.ReadInt32());
} }
public void deobfuscate(Blocks blocks) { public void Deobfuscate(Blocks blocks) {
if (blocks.Method != installMethod) if (blocks.Method != installMethod)
return; return;
ConfuserUtils.removeResourceHookCode(blocks, handler); ConfuserUtils.RemoveResourceHookCode(blocks, handler);
} }
public bool getRevisionRange(out int minRev, out int maxRev) { public bool GetRevisionRange(out int minRev, out int maxRev) {
switch (version) { switch (version) {
case ConfuserVersion.Unknown: case ConfuserVersion.Unknown:
minRev = maxRev = 0; minRev = maxRev = 0;

View File

@ -54,7 +54,7 @@ namespace de4dot.code.deobfuscators.Confuser {
this.stringDecrypter = stringDecrypter; this.stringDecrypter = stringDecrypter;
} }
public abstract string decrypt(MethodDef caller, int magic); public abstract string Decrypt(MethodDef caller, int magic);
} }
class Decrypter_v10_r42915 : Decrypter { class Decrypter_v10_r42915 : Decrypter {
@ -69,7 +69,7 @@ namespace de4dot.code.deobfuscators.Confuser {
this.key = key; this.key = key;
} }
public override string decrypt(MethodDef caller, int magic) { public override string Decrypt(MethodDef caller, int magic) {
var reader = stringDecrypter.reader; var reader = stringDecrypter.reader;
reader.Position = (caller.MDToken.ToInt32() ^ magic) - stringDecrypter.magic1; reader.Position = (caller.MDToken.ToInt32() ^ magic) - stringDecrypter.magic1;
int len = reader.ReadInt32() ^ (int)~stringDecrypter.magic2; int len = reader.ReadInt32() ^ (int)~stringDecrypter.magic2;
@ -93,7 +93,7 @@ namespace de4dot.code.deobfuscators.Confuser {
: base(stringDecrypter) { : base(stringDecrypter) {
} }
public override string decrypt(MethodDef caller, int magic) { public override string Decrypt(MethodDef caller, int magic) {
var reader = stringDecrypter.reader; var reader = stringDecrypter.reader;
reader.Position = (caller.MDToken.ToInt32() ^ magic) - stringDecrypter.magic1; reader.Position = (caller.MDToken.ToInt32() ^ magic) - stringDecrypter.magic1;
int len = reader.ReadInt32() ^ (int)~stringDecrypter.magic2; int len = reader.ReadInt32() ^ (int)~stringDecrypter.magic2;
@ -101,7 +101,7 @@ namespace de4dot.code.deobfuscators.Confuser {
var instrs = stringDecrypter.decryptMethod.Body.Instructions; var instrs = stringDecrypter.decryptMethod.Body.Instructions;
constReader = new PolyConstantsReader(instrs, false); constReader = new PolyConstantsReader(instrs, false);
int polyIndex = ConfuserUtils.findCallMethod(instrs, 0, Code.Callvirt, "System.Int64 System.IO.BinaryReader::ReadInt64()"); int polyIndex = ConfuserUtils.FindCallMethod(instrs, 0, Code.Callvirt, "System.Int64 System.IO.BinaryReader::ReadInt64()");
if (polyIndex < 0) if (polyIndex < 0)
throw new ApplicationException("Could not find start of decrypt code"); throw new ApplicationException("Could not find start of decrypt code");
@ -110,7 +110,7 @@ namespace de4dot.code.deobfuscators.Confuser {
constReader.Arg = reader.ReadInt64(); constReader.Arg = reader.ReadInt64();
int index = polyIndex; int index = polyIndex;
long val; long val;
if (!constReader.getInt64(ref index, out val) || instrs[index].OpCode.Code != Code.Conv_I8) if (!constReader.GetInt64(ref index, out val) || instrs[index].OpCode.Code != Code.Conv_I8)
throw new ApplicationException("Could not get string int64 value"); throw new ApplicationException("Could not get string int64 value");
Array.Copy(BitConverter.GetBytes(val ^ rand.Next()), 0, decrypted, i, Math.Min(8, len - i)); Array.Copy(BitConverter.GetBytes(val ^ rand.Next()), 0, decrypted, i, Math.Min(8, len - i));
} }
@ -124,39 +124,39 @@ namespace de4dot.code.deobfuscators.Confuser {
: base(stringDecrypter) { : base(stringDecrypter) {
} }
public override string decrypt(MethodDef caller, int magic) { public override string Decrypt(MethodDef caller, int magic) {
var reader = stringDecrypter.reader; var reader = stringDecrypter.reader;
reader.Position = (caller.MDToken.ToInt32() ^ magic) - stringDecrypter.magic1; reader.Position = (caller.MDToken.ToInt32() ^ magic) - stringDecrypter.magic1;
int len = reader.ReadInt32() ^ (int)~stringDecrypter.magic2; int len = reader.ReadInt32() ^ (int)~stringDecrypter.magic2;
var decrypted = new byte[len]; var decrypted = new byte[len];
int startIndex, endIndex; int startIndex, endIndex;
if (!findPolyStartEndIndexes(out startIndex, out endIndex)) if (!FindPolyStartEndIndexes(out startIndex, out endIndex))
throw new ApplicationException("Could not get start/end indexes"); throw new ApplicationException("Could not get start/end indexes");
var constReader = new Arg64ConstantsReader(stringDecrypter.decryptMethod.Body.Instructions, false); var constReader = new Arg64ConstantsReader(stringDecrypter.decryptMethod.Body.Instructions, false);
ConfuserUtils.decryptCompressedInt32Data(constReader, startIndex, endIndex, reader, decrypted); ConfuserUtils.DecryptCompressedInt32Data(constReader, startIndex, endIndex, reader, decrypted);
return Encoding.Unicode.GetString(decrypted); return Encoding.Unicode.GetString(decrypted);
} }
bool findPolyStartEndIndexes(out int startIndex, out int endIndex) { bool FindPolyStartEndIndexes(out int startIndex, out int endIndex) {
startIndex = 0; startIndex = 0;
endIndex = 0; endIndex = 0;
var local = findLocal(stringDecrypter.decryptMethod); var local = FindLocal(stringDecrypter.decryptMethod);
if (local == null) if (local == null)
return false; return false;
if ((endIndex = findEndIndex(stringDecrypter.decryptMethod)) < 0) if ((endIndex = FindEndIndex(stringDecrypter.decryptMethod)) < 0)
return false; return false;
if ((startIndex = findStartIndex(stringDecrypter.decryptMethod, endIndex)) < 0) if ((startIndex = FindStartIndex(stringDecrypter.decryptMethod, endIndex)) < 0)
return false; return false;
return true; return true;
} }
static Local findLocal(MethodDef method) { static Local FindLocal(MethodDef method) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count - 3; i++) { for (int i = 0; i < instrs.Count - 3; i++) {
if (instrs[i].OpCode.Code != Code.And) if (instrs[i].OpCode.Code != Code.And)
@ -172,7 +172,7 @@ namespace de4dot.code.deobfuscators.Confuser {
return null; return null;
} }
static int findEndIndex(MethodDef method) { static int FindEndIndex(MethodDef method) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count - 5; i++) { for (int i = 0; i < instrs.Count - 5; i++) {
if (instrs[i].OpCode.Code != Code.Conv_U1) if (instrs[i].OpCode.Code != Code.Conv_U1)
@ -192,7 +192,7 @@ namespace de4dot.code.deobfuscators.Confuser {
return -1; return -1;
} }
static int findStartIndex(MethodDef method, int endIndex) { static int FindStartIndex(MethodDef method, int endIndex) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = endIndex; i >= 0; i--) { for (int i = endIndex; i >= 0; i--) {
var instr = instrs[i]; var instr = instrs[i];
@ -217,7 +217,7 @@ namespace de4dot.code.deobfuscators.Confuser {
: base(instrs, emulateConvInstrs) { : base(instrs, emulateConvInstrs) {
} }
protected override bool processInstructionInt64(ref int index, Stack<ConstantInfo<long>> stack) { protected override bool ProcessInstructionInt64(ref int index, Stack<ConstantInfo<long>> stack) {
int i = index; int i = index;
if (instructions[i].IsLdloc()) { if (instructions[i].IsLdloc()) {
@ -259,52 +259,52 @@ namespace de4dot.code.deobfuscators.Confuser {
"System.IO.BinaryReader", "System.IO.BinaryReader",
"System.Reflection.Assembly", "System.Reflection.Assembly",
}; };
public void find(ISimpleDeobfuscator simpleDeobfuscator) { public void Find(ISimpleDeobfuscator simpleDeobfuscator) {
var type = DotNetUtils.getModuleType(module); var type = DotNetUtils.GetModuleType(module);
if (type == null) if (type == null)
return; return;
foreach (var method in type.Methods) { foreach (var method in type.Methods) {
if (!method.IsStatic || method.Body == null) if (!method.IsStatic || method.Body == null)
continue; continue;
if (!DotNetUtils.isMethod(method, "System.String", "(System.Int32)")) if (!DotNetUtils.IsMethod(method, "System.String", "(System.Int32)"))
continue; continue;
var localTypes = new LocalTypes(method); var localTypes = new LocalTypes(method);
if (!localTypes.all(requiredLocals)) if (!localTypes.All(requiredLocals))
continue; continue;
simpleDeobfuscator.deobfuscate(method); simpleDeobfuscator.Deobfuscate(method);
bool foundOldMagic1; bool foundOldMagic1;
if (findMagic1(method, out magic1)) if (FindMagic1(method, out magic1))
foundOldMagic1 = true; foundOldMagic1 = true;
else if (findNewMagic1(method, out magic1)) else if (FindNewMagic1(method, out magic1))
foundOldMagic1 = false; foundOldMagic1 = false;
else else
continue; continue;
if (!findMagic2(method, out magic2)) if (!FindMagic2(method, out magic2))
continue; continue;
version = ConfuserVersion.Unknown; version = ConfuserVersion.Unknown;
if (DotNetUtils.callsMethod(method, "System.Text.Encoding System.Text.Encoding::get_UTF8()")) { if (DotNetUtils.CallsMethod(method, "System.Text.Encoding System.Text.Encoding::get_UTF8()")) {
if (foundOldMagic1) { if (foundOldMagic1) {
if (DotNetUtils.callsMethod(method, "System.Object System.AppDomain::GetData(System.String)")) if (DotNetUtils.CallsMethod(method, "System.Object System.AppDomain::GetData(System.String)"))
version = ConfuserVersion.v13_r55604_safe; version = ConfuserVersion.v13_r55604_safe;
else else
version = ConfuserVersion.v10_r42915; version = ConfuserVersion.v10_r42915;
} }
else { else {
if (!findSafeKey1(method, out key1)) if (!FindSafeKey1(method, out key1))
continue; continue;
version = ConfuserVersion.v14_r58802_safe; version = ConfuserVersion.v14_r58802_safe;
} }
} }
else if (!localTypes.exists("System.Random")) { else if (!localTypes.Exists("System.Random")) {
if (foundOldMagic1) if (foundOldMagic1)
version = ConfuserVersion.v11_r49299; version = ConfuserVersion.v11_r49299;
else else
version = ConfuserVersion.v14_r58802_dynamic; version = ConfuserVersion.v14_r58802_dynamic;
} }
else if (localTypes.exists("System.Collections.Generic.Dictionary`2<System.Int32,System.String>")) else if (localTypes.Exists("System.Collections.Generic.Dictionary`2<System.Int32,System.String>"))
version = ConfuserVersion.v10_r48832; version = ConfuserVersion.v10_r48832;
if (version == ConfuserVersion.Unknown) if (version == ConfuserVersion.Unknown)
continue; continue;
@ -314,14 +314,14 @@ namespace de4dot.code.deobfuscators.Confuser {
} }
} }
EmbeddedResource findResource(MethodDef method) { EmbeddedResource FindResource(MethodDef method) {
return DotNetUtils.getResource(module, DotNetUtils.getCodeStrings(method)) as EmbeddedResource; return DotNetUtils.GetResource(module, DotNetUtils.GetCodeStrings(method)) as EmbeddedResource;
} }
static bool findMagic1(MethodDef method, out uint magic) { static bool FindMagic1(MethodDef method, out uint magic) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count; i++) { for (int i = 0; i < instrs.Count; i++) {
int index = ConfuserUtils.findCallMethod(instrs, i, Code.Callvirt, "System.Byte[] System.IO.BinaryReader::ReadBytes(System.Int32)"); int index = ConfuserUtils.FindCallMethod(instrs, i, Code.Callvirt, "System.Byte[] System.IO.BinaryReader::ReadBytes(System.Int32)");
if (index < 0) if (index < 0)
break; break;
if (index < 4) if (index < 4)
@ -345,7 +345,7 @@ namespace de4dot.code.deobfuscators.Confuser {
return false; return false;
} }
static bool findNewMagic1(MethodDef method, out uint magic) { static bool FindNewMagic1(MethodDef method, out uint magic) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count - 4; i++) { for (int i = 0; i < instrs.Count - 4; i++) {
if (instrs[i].OpCode.Code != Code.Ldarg_0) if (instrs[i].OpCode.Code != Code.Ldarg_0)
@ -367,10 +367,10 @@ namespace de4dot.code.deobfuscators.Confuser {
return false; return false;
} }
static bool findMagic2(MethodDef method, out uint magic) { static bool FindMagic2(MethodDef method, out uint magic) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count; i++) { for (int i = 0; i < instrs.Count; i++) {
int index = ConfuserUtils.findCallMethod(instrs, i, Code.Callvirt, "System.UInt32 System.IO.BinaryReader::ReadUInt32()"); int index = ConfuserUtils.FindCallMethod(instrs, i, Code.Callvirt, "System.UInt32 System.IO.BinaryReader::ReadUInt32()");
if (index < 0) if (index < 0)
break; break;
if (index + 4 >= instrs.Count) if (index + 4 >= instrs.Count)
@ -393,10 +393,10 @@ namespace de4dot.code.deobfuscators.Confuser {
return false; return false;
} }
static bool findSafeKey1(MethodDef method, out uint key) { static bool FindSafeKey1(MethodDef method, out uint key) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count; i++) { for (int i = 0; i < instrs.Count; i++) {
int index = ConfuserUtils.findCallMethod(instrs, i, Code.Newobj, "System.Void System.Random::.ctor(System.Int32)"); int index = ConfuserUtils.FindCallMethod(instrs, i, Code.Newobj, "System.Void System.Random::.ctor(System.Int32)");
if (index < 0) if (index < 0)
break; break;
if (index == 0) if (index == 0)
@ -413,14 +413,14 @@ namespace de4dot.code.deobfuscators.Confuser {
return false; return false;
} }
public void initialize() { public void Initialize() {
if (decryptMethod == null) if (decryptMethod == null)
return; return;
resource = findResource(decryptMethod); resource = FindResource(decryptMethod);
if (resource == null) if (resource == null)
throw new ApplicationException("Could not find encrypted strings resource"); throw new ApplicationException("Could not find encrypted strings resource");
reader = MemoryImageStream.Create(DeobUtils.inflate(resource.GetResourceData(), true)); reader = MemoryImageStream.Create(DeobUtils.Inflate(resource.GetResourceData(), true));
switch (version) { switch (version) {
case ConfuserVersion.v10_r42915: case ConfuserVersion.v10_r42915:
@ -446,11 +446,11 @@ namespace de4dot.code.deobfuscators.Confuser {
} }
} }
public string decrypt(MethodDef caller, int magic) { public string Decrypt(MethodDef caller, int magic) {
return decrypter.decrypt(caller, magic); return decrypter.Decrypt(caller, magic);
} }
public bool getRevisionRange(out int minRev, out int maxRev) { public bool GetRevisionRange(out int minRev, out int maxRev) {
switch (version) { switch (version) {
case ConfuserVersion.Unknown: case ConfuserVersion.Unknown:
minRev = maxRev = 0; minRev = maxRev = 0;

View File

@ -36,7 +36,7 @@ namespace de4dot.code.deobfuscators.Confuser {
this.realAssembly = realAssembly; this.realAssembly = realAssembly;
this.entryPointToken = entryPointToken; this.entryPointToken = entryPointToken;
this.kind = kind; this.kind = kind;
this.moduleName = realAssembly.Name.String + DeobUtils.getExtension(kind); this.moduleName = realAssembly.Name.String + DeobUtils.GetExtension(kind);
} }
} }
@ -53,9 +53,9 @@ namespace de4dot.code.deobfuscators.Confuser {
this.resource = resource; this.resource = resource;
this.data = data; this.data = data;
this.asmFullName = asmFullName; this.asmFullName = asmFullName;
this.asmSimpleName = Utils.getAssemblySimpleName(asmFullName); this.asmSimpleName = Utils.GetAssemblySimpleName(asmFullName);
this.kind = kind; this.kind = kind;
this.extension = DeobUtils.getExtension(kind); this.extension = DeobUtils.GetExtension(kind);
} }
public override string ToString() { public override string ToString() {
@ -106,31 +106,31 @@ namespace de4dot.code.deobfuscators.Confuser {
"System.IO.BinaryReader", "System.IO.BinaryReader",
"System.IO.Stream", "System.IO.Stream",
}; };
public void find(ISimpleDeobfuscator simpleDeobfuscator, IDeobfuscator deob) { public void Find(ISimpleDeobfuscator simpleDeobfuscator, IDeobfuscator deob) {
var entryPoint = module.EntryPoint; var entryPoint = module.EntryPoint;
if (entryPoint == null) if (entryPoint == null)
return; return;
if (!new LocalTypes(entryPoint).all(requiredEntryPointLocals)) if (!new LocalTypes(entryPoint).All(requiredEntryPointLocals))
return; return;
var type = entryPoint.DeclaringType; var type = entryPoint.DeclaringType;
if (!new FieldTypes(type).all(requiredFields)) if (!new FieldTypes(type).All(requiredFields))
return; return;
bool use7zip = type.NestedTypes.Count == 6; bool use7zip = type.NestedTypes.Count == 6;
MethodDef decyptMethod; MethodDef decyptMethod;
if (use7zip) if (use7zip)
decyptMethod = findDecryptMethod_7zip(type); decyptMethod = FindDecryptMethod_7zip(type);
else else
decyptMethod = findDecryptMethod_inflate(type); decyptMethod = FindDecryptMethod_inflate(type);
if (decyptMethod == null) if (decyptMethod == null)
return; return;
ConfuserVersion theVersion = ConfuserVersion.Unknown; ConfuserVersion theVersion = ConfuserVersion.Unknown;
var decryptLocals = new LocalTypes(decyptMethod); var decryptLocals = new LocalTypes(decyptMethod);
if (decryptLocals.exists("System.IO.MemoryStream")) { if (decryptLocals.Exists("System.IO.MemoryStream")) {
if (DotNetUtils.callsMethod(entryPoint, "System.Void", "(System.String,System.Byte[])")) if (DotNetUtils.CallsMethod(entryPoint, "System.Void", "(System.String,System.Byte[])"))
theVersion = ConfuserVersion.v10_r42915; theVersion = ConfuserVersion.v10_r42915;
else if (DotNetUtils.callsMethod(entryPoint, "System.Void", "(System.Security.Permissions.PermissionState)")) else if (DotNetUtils.CallsMethod(entryPoint, "System.Void", "(System.Security.Permissions.PermissionState)"))
theVersion = ConfuserVersion.v10_r48717; theVersion = ConfuserVersion.v10_r48717;
else else
theVersion = ConfuserVersion.v14_r57778; theVersion = ConfuserVersion.v14_r57778;
@ -142,10 +142,10 @@ namespace de4dot.code.deobfuscators.Confuser {
if (cctor == null) if (cctor == null)
return; return;
if ((asmResolverMethod = findAssemblyResolverMethod(entryPoint.DeclaringType)) != null) { if ((asmResolverMethod = FindAssemblyResolverMethod(entryPoint.DeclaringType)) != null) {
theVersion = ConfuserVersion.v14_r58802; theVersion = ConfuserVersion.v14_r58802;
simpleDeobfuscator.deobfuscate(asmResolverMethod); simpleDeobfuscator.Deobfuscate(asmResolverMethod);
if (!findKey1(asmResolverMethod, out key1)) if (!FindKey1(asmResolverMethod, out key1))
return; return;
} }
@ -157,23 +157,23 @@ namespace de4dot.code.deobfuscators.Confuser {
case ConfuserVersion.v14_r58564: case ConfuserVersion.v14_r58564:
case ConfuserVersion.v14_r58802: case ConfuserVersion.v14_r58802:
simpleDeobfuscator.deobfuscate(decyptMethod); simpleDeobfuscator.Deobfuscate(decyptMethod);
if (findKey0_v14_r58564(decyptMethod, out key0)) if (FindKey0_v14_r58564(decyptMethod, out key0))
break; break;
if (findKey0_v14_r58852(decyptMethod, out key0)) { if (FindKey0_v14_r58852(decyptMethod, out key0)) {
if (!decryptLocals.exists("System.Security.Cryptography.RijndaelManaged")) { if (!decryptLocals.Exists("System.Security.Cryptography.RijndaelManaged")) {
theVersion = ConfuserVersion.v14_r58852; theVersion = ConfuserVersion.v14_r58852;
break; break;
} }
if (use7zip) { if (use7zip) {
if (new LocalTypes(decyptMethod).exists("System.IO.MemoryStream")) if (new LocalTypes(decyptMethod).Exists("System.IO.MemoryStream"))
theVersion = ConfuserVersion.v17_r75076; theVersion = ConfuserVersion.v17_r75076;
else if (module.Name == "Stub.exe") else if (module.Name == "Stub.exe")
theVersion = ConfuserVersion.v18_r75184; theVersion = ConfuserVersion.v18_r75184;
else else
theVersion = ConfuserVersion.v18_r75367; theVersion = ConfuserVersion.v18_r75367;
} }
else if (isDecryptMethod_v17_r73404(decyptMethod)) else if (IsDecryptMethod_v17_r73404(decyptMethod))
theVersion = ConfuserVersion.v17_r73404; theVersion = ConfuserVersion.v17_r73404;
else else
theVersion = ConfuserVersion.v15_r60785; theVersion = ConfuserVersion.v15_r60785;
@ -185,44 +185,44 @@ namespace de4dot.code.deobfuscators.Confuser {
throw new ApplicationException("Invalid version"); throw new ApplicationException("Invalid version");
} }
simpleDeobfuscator.deobfuscate(cctor); simpleDeobfuscator.Deobfuscate(cctor);
simpleDeobfuscator.decryptStrings(cctor, deob); simpleDeobfuscator.DecryptStrings(cctor, deob);
if (findEntryPointToken(simpleDeobfuscator, cctor, entryPoint, out entryPointToken) && !use7zip) { if (FindEntryPointToken(simpleDeobfuscator, cctor, entryPoint, out entryPointToken) && !use7zip) {
if (DotNetUtils.callsMethod(asmResolverMethod, "System.Void", "(System.String)")) if (DotNetUtils.CallsMethod(asmResolverMethod, "System.Void", "(System.String)"))
theVersion = ConfuserVersion.v17_r73477; theVersion = ConfuserVersion.v17_r73477;
else else
theVersion = ConfuserVersion.v17_r73566; theVersion = ConfuserVersion.v17_r73566;
} }
mainAsmResource = findResource(cctor); mainAsmResource = FindResource(cctor);
if (mainAsmResource == null) if (mainAsmResource == null)
throw new ApplicationException("Could not find main assembly resource"); throw new ApplicationException("Could not find main assembly resource");
version = theVersion; version = theVersion;
} }
bool findEntryPointToken(ISimpleDeobfuscator simpleDeobfuscator, MethodDef cctor, MethodDef entryPoint, out uint token) { bool FindEntryPointToken(ISimpleDeobfuscator simpleDeobfuscator, MethodDef cctor, MethodDef entryPoint, out uint token) {
token = 0; token = 0;
ulong @base; ulong @base;
if (!findBase(cctor, out @base)) if (!FindBase(cctor, out @base))
return false; return false;
var modPowMethod = DotNetUtils.getMethod(cctor.DeclaringType, "System.UInt64", "(System.UInt64,System.UInt64,System.UInt64)"); var modPowMethod = DotNetUtils.GetMethod(cctor.DeclaringType, "System.UInt64", "(System.UInt64,System.UInt64,System.UInt64)");
if (modPowMethod == null) if (modPowMethod == null)
throw new ApplicationException("Could not find modPow()"); throw new ApplicationException("Could not find modPow()");
simpleDeobfuscator.deobfuscate(entryPoint); simpleDeobfuscator.Deobfuscate(entryPoint);
ulong mod; ulong mod;
if (!findMod(entryPoint, out mod)) if (!FindMod(entryPoint, out mod))
throw new ApplicationException("Could not find modulus"); throw new ApplicationException("Could not find modulus");
token = 0x06000000 | (uint)modPow(@base, 0x47, mod); token = 0x06000000 | (uint)ModPow(@base, 0x47, mod);
if ((token >> 24) != 0x06) if ((token >> 24) != 0x06)
throw new ApplicationException("Illegal entry point token"); throw new ApplicationException("Illegal entry point token");
return true; return true;
} }
static ulong modPow(ulong @base, ulong pow, ulong mod) { static ulong ModPow(ulong @base, ulong pow, ulong mod) {
ulong m = 1; ulong m = 1;
while (pow > 0) { while (pow > 0) {
if ((pow & 1) != 0) if ((pow & 1) != 0)
@ -233,7 +233,7 @@ namespace de4dot.code.deobfuscators.Confuser {
return m; return m;
} }
static bool findMod(MethodDef method, out ulong mod) { static bool FindMod(MethodDef method, out ulong mod) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count - 1; i++) { for (int i = 0; i < instrs.Count - 1; i++) {
var ldci8 = instrs[i]; var ldci8 = instrs[i];
@ -246,7 +246,7 @@ namespace de4dot.code.deobfuscators.Confuser {
var calledMethod = call.Operand as IMethod; var calledMethod = call.Operand as IMethod;
if (calledMethod == null) if (calledMethod == null)
continue; continue;
if (!DotNetUtils.isMethod(calledMethod, "System.UInt64", "(System.UInt64,System.UInt64,System.UInt64)")) if (!DotNetUtils.IsMethod(calledMethod, "System.UInt64", "(System.UInt64,System.UInt64,System.UInt64)"))
continue; continue;
mod = (ulong)(long)ldci8.Operand; mod = (ulong)(long)ldci8.Operand;
@ -256,7 +256,7 @@ namespace de4dot.code.deobfuscators.Confuser {
return false; return false;
} }
static bool findBase(MethodDef method, out ulong @base) { static bool FindBase(MethodDef method, out ulong @base) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count - 2; i++) { for (int i = 0; i < instrs.Count - 2; i++) {
var ldci8 = instrs[i]; var ldci8 = instrs[i];
@ -278,13 +278,13 @@ namespace de4dot.code.deobfuscators.Confuser {
return false; return false;
} }
static bool isDecryptMethod_v17_r73404(MethodDef method) { static bool IsDecryptMethod_v17_r73404(MethodDef method) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
if (instrs.Count < 4) if (instrs.Count < 4)
return false; return false;
if (!instrs[0].IsLdarg()) if (!instrs[0].IsLdarg())
return false; return false;
if (!isCallorNewobj(instrs[1]) && !isCallorNewobj(instrs[2])) if (!IsCallorNewobj(instrs[1]) && !IsCallorNewobj(instrs[2]))
return false; return false;
var stloc = instrs[3]; var stloc = instrs[3];
if (!stloc.IsStloc()) if (!stloc.IsStloc())
@ -296,15 +296,15 @@ namespace de4dot.code.deobfuscators.Confuser {
return true; return true;
} }
static bool isCallorNewobj(Instruction instr) { static bool IsCallorNewobj(Instruction instr) {
return instr.OpCode.Code == Code.Call || instr.OpCode.Code == Code.Newobj; return instr.OpCode.Code == Code.Call || instr.OpCode.Code == Code.Newobj;
} }
static MethodDef findAssemblyResolverMethod(TypeDef type) { static MethodDef FindAssemblyResolverMethod(TypeDef type) {
foreach (var method in type.Methods) { foreach (var method in type.Methods) {
if (!method.IsStatic || method.Body == null) if (!method.IsStatic || method.Body == null)
continue; continue;
if (!DotNetUtils.isMethod(method, "System.Reflection.Assembly", "(System.Object,System.ResolveEventArgs)")) if (!DotNetUtils.IsMethod(method, "System.Reflection.Assembly", "(System.Object,System.ResolveEventArgs)"))
continue; continue;
return method; return method;
@ -312,7 +312,7 @@ namespace de4dot.code.deobfuscators.Confuser {
return null; return null;
} }
static bool findKey0_v14_r58564(MethodDef method, out uint key) { static bool FindKey0_v14_r58564(MethodDef method, out uint key) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count - 2; i++) { for (int i = 0; i < instrs.Count - 2; i++) {
if (instrs[i].OpCode.Code != Code.Xor) if (instrs[i].OpCode.Code != Code.Xor)
@ -330,7 +330,7 @@ namespace de4dot.code.deobfuscators.Confuser {
return false; return false;
} }
static bool findKey0_v14_r58852(MethodDef method, out uint key) { static bool FindKey0_v14_r58852(MethodDef method, out uint key) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count - 3; i++) { for (int i = 0; i < instrs.Count - 3; i++) {
var ldci4_1 = instrs[i]; var ldci4_1 = instrs[i];
@ -351,7 +351,7 @@ namespace de4dot.code.deobfuscators.Confuser {
return false; return false;
} }
static bool findKey1(MethodDef method, out uint key) { static bool FindKey1(MethodDef method, out uint key) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count - 4; i++) { for (int i = 0; i < instrs.Count - 4; i++) {
if (instrs[i].OpCode.Code != Code.Ldelem_U1) if (instrs[i].OpCode.Code != Code.Ldelem_U1)
@ -373,21 +373,21 @@ namespace de4dot.code.deobfuscators.Confuser {
return false; return false;
} }
EmbeddedResource findResource(MethodDef method) { EmbeddedResource FindResource(MethodDef method) {
return DotNetUtils.getResource(module, DotNetUtils.getCodeStrings(method)) as EmbeddedResource; return DotNetUtils.GetResource(module, DotNetUtils.GetCodeStrings(method)) as EmbeddedResource;
} }
static string[] requiredDecryptLocals_inflate = new string[] { static string[] requiredDecryptLocals_inflate = new string[] {
"System.Byte[]", "System.Byte[]",
"System.IO.Compression.DeflateStream", "System.IO.Compression.DeflateStream",
}; };
static MethodDef findDecryptMethod_inflate(TypeDef type) { static MethodDef FindDecryptMethod_inflate(TypeDef type) {
foreach (var method in type.Methods) { foreach (var method in type.Methods) {
if (!method.IsStatic || method.Body == null) if (!method.IsStatic || method.Body == null)
continue; continue;
if (!DotNetUtils.isMethod(method, "System.Byte[]", "(System.Byte[])")) if (!DotNetUtils.IsMethod(method, "System.Byte[]", "(System.Byte[])"))
continue; continue;
if (!new LocalTypes(method).all(requiredDecryptLocals_inflate)) if (!new LocalTypes(method).All(requiredDecryptLocals_inflate))
continue; continue;
return method; return method;
@ -402,13 +402,13 @@ namespace de4dot.code.deobfuscators.Confuser {
"System.Security.Cryptography.CryptoStream", "System.Security.Cryptography.CryptoStream",
"System.Security.Cryptography.RijndaelManaged", "System.Security.Cryptography.RijndaelManaged",
}; };
static MethodDef findDecryptMethod_7zip(TypeDef type) { static MethodDef FindDecryptMethod_7zip(TypeDef type) {
foreach (var method in type.Methods) { foreach (var method in type.Methods) {
if (!method.IsStatic || method.Body == null) if (!method.IsStatic || method.Body == null)
continue; continue;
if (!DotNetUtils.isMethod(method, "System.Byte[]", "(System.Byte[])")) if (!DotNetUtils.IsMethod(method, "System.Byte[]", "(System.Byte[])"))
continue; continue;
if (!new LocalTypes(method).all(requiredDecryptLocals_7zip)) if (!new LocalTypes(method).All(requiredDecryptLocals_7zip))
continue; continue;
return method; return method;
@ -416,14 +416,14 @@ namespace de4dot.code.deobfuscators.Confuser {
return null; return null;
} }
public EmbeddedAssemblyInfo unpackMainAssembly(bool createAssembly) { public EmbeddedAssemblyInfo UnpackMainAssembly(bool createAssembly) {
if (mainAsmResource == null) if (mainAsmResource == null)
return null; return null;
var info = createEmbeddedAssemblyInfo(mainAsmResource, decrypt(mainAsmResource)); var info = CreateEmbeddedAssemblyInfo(mainAsmResource, Decrypt(mainAsmResource));
var asm = module.Assembly; var asm = module.Assembly;
if (createAssembly && asm != null && entryPointToken != 0 && info.kind == ModuleKind.NetModule) { if (createAssembly && asm != null && entryPointToken != 0 && info.kind == ModuleKind.NetModule) {
info.extension = DeobUtils.getExtension(module.Kind); info.extension = DeobUtils.GetExtension(module.Kind);
info.kind = module.Kind; info.kind = module.Kind;
var realAsm = module.UpdateRowId(new AssemblyDefUser(asm.Name, new Version(0, 0, 0, 0))); var realAsm = module.UpdateRowId(new AssemblyDefUser(asm.Name, new Version(0, 0, 0, 0)));
@ -437,14 +437,14 @@ namespace de4dot.code.deobfuscators.Confuser {
return info; return info;
} }
public List<EmbeddedAssemblyInfo> getEmbeddedAssemblyInfos() { public List<EmbeddedAssemblyInfo> GetEmbeddedAssemblyInfos() {
var infos = new List<EmbeddedAssemblyInfo>(); var infos = new List<EmbeddedAssemblyInfo>();
foreach (var rsrc in module.Resources) { foreach (var rsrc in module.Resources) {
var resource = rsrc as EmbeddedResource; var resource = rsrc as EmbeddedResource;
if (resource == null || resource == mainAsmResource) if (resource == null || resource == mainAsmResource)
continue; continue;
try { try {
infos.Add(createEmbeddedAssemblyInfo(resource, decrypt(resource))); infos.Add(CreateEmbeddedAssemblyInfo(resource, Decrypt(resource)));
} }
catch { catch {
} }
@ -452,45 +452,45 @@ namespace de4dot.code.deobfuscators.Confuser {
return infos; return infos;
} }
static EmbeddedAssemblyInfo createEmbeddedAssemblyInfo(EmbeddedResource resource, byte[] data) { static EmbeddedAssemblyInfo CreateEmbeddedAssemblyInfo(EmbeddedResource resource, byte[] data) {
var mod = ModuleDefMD.Load(data); var mod = ModuleDefMD.Load(data);
var asmFullName = mod.Assembly != null ? mod.Assembly.FullName : mod.Name.String; var asmFullName = mod.Assembly != null ? mod.Assembly.FullName : mod.Name.String;
return new EmbeddedAssemblyInfo(resource, data, asmFullName, mod.Kind); return new EmbeddedAssemblyInfo(resource, data, asmFullName, mod.Kind);
} }
byte[] decrypt(EmbeddedResource resource) { byte[] Decrypt(EmbeddedResource resource) {
var data = resource.GetResourceData(); var data = resource.GetResourceData();
switch (version) { switch (version) {
case ConfuserVersion.v10_r42915: return decrypt_v10_r42915(data); case ConfuserVersion.v10_r42915: return Decrypt_v10_r42915(data);
case ConfuserVersion.v10_r48717: return decrypt_v10_r42915(data); case ConfuserVersion.v10_r48717: return Decrypt_v10_r42915(data);
case ConfuserVersion.v14_r57778: return decrypt_v10_r42915(data); case ConfuserVersion.v14_r57778: return Decrypt_v10_r42915(data);
case ConfuserVersion.v14_r58564: return decrypt_v14_r58564(data); case ConfuserVersion.v14_r58564: return Decrypt_v14_r58564(data);
case ConfuserVersion.v14_r58802: return decrypt_v14_r58564(data); case ConfuserVersion.v14_r58802: return Decrypt_v14_r58564(data);
case ConfuserVersion.v14_r58852: return decrypt_v14_r58852(data); case ConfuserVersion.v14_r58852: return Decrypt_v14_r58852(data);
case ConfuserVersion.v15_r60785: return decrypt_v15_r60785(data); case ConfuserVersion.v15_r60785: return Decrypt_v15_r60785(data);
case ConfuserVersion.v17_r73404: return decrypt_v17_r73404(data); case ConfuserVersion.v17_r73404: return Decrypt_v17_r73404(data);
case ConfuserVersion.v17_r73477: return decrypt_v17_r73404(data); case ConfuserVersion.v17_r73477: return Decrypt_v17_r73404(data);
case ConfuserVersion.v17_r73566: return decrypt_v17_r73404(data); case ConfuserVersion.v17_r73566: return Decrypt_v17_r73404(data);
case ConfuserVersion.v17_r75076: return decrypt_v17_r75076(data); case ConfuserVersion.v17_r75076: return Decrypt_v17_r75076(data);
case ConfuserVersion.v18_r75184: return decrypt_v17_r75076(data); case ConfuserVersion.v18_r75184: return Decrypt_v17_r75076(data);
case ConfuserVersion.v18_r75367: return decrypt_v17_r75076(data); case ConfuserVersion.v18_r75367: return Decrypt_v17_r75076(data);
default: throw new ApplicationException("Unknown version"); default: throw new ApplicationException("Unknown version");
} }
} }
byte[] decrypt_v10_r42915(byte[] data) { byte[] Decrypt_v10_r42915(byte[] data) {
for (int i = 0; i < data.Length; i++) for (int i = 0; i < data.Length; i++)
data[i] ^= (byte)(i ^ key0); data[i] ^= (byte)(i ^ key0);
return DeobUtils.inflate(data, true); return DeobUtils.Inflate(data, true);
} }
byte[] decrypt_v14_r58564(byte[] data) { byte[] Decrypt_v14_r58564(byte[] data) {
var reader = new BinaryReader(new MemoryStream(decrypt_v10_r42915(data))); var reader = new BinaryReader(new MemoryStream(Decrypt_v10_r42915(data)));
return reader.ReadBytes(reader.ReadInt32()); return reader.ReadBytes(reader.ReadInt32());
} }
byte[] decrypt_v14_r58852(byte[] data) { byte[] Decrypt_v14_r58852(byte[] data) {
var reader = new BinaryReader(new MemoryStream(DeobUtils.inflate(data, true))); var reader = new BinaryReader(new MemoryStream(DeobUtils.Inflate(data, true)));
data = reader.ReadBytes(reader.ReadInt32()); data = reader.ReadBytes(reader.ReadInt32());
for (int i = 0; i < data.Length; i++) { for (int i = 0; i < data.Length; i++) {
if ((i & 1) == 0) if ((i & 1) == 0)
@ -502,15 +502,15 @@ namespace de4dot.code.deobfuscators.Confuser {
return data; return data;
} }
byte[] decrypt_v15_r60785(byte[] data) { byte[] Decrypt_v15_r60785(byte[] data) {
var reader = new BinaryReader(new MemoryStream(DeobUtils.inflate(data, true))); var reader = new BinaryReader(new MemoryStream(DeobUtils.Inflate(data, true)));
byte[] key, iv; byte[] key, iv;
data = decrypt_v15_r60785(reader, out key, out iv); data = Decrypt_v15_r60785(reader, out key, out iv);
reader = new BinaryReader(new MemoryStream(DeobUtils.aesDecrypt(data, key, iv))); reader = new BinaryReader(new MemoryStream(DeobUtils.AesDecrypt(data, key, iv)));
return reader.ReadBytes(reader.ReadInt32()); return reader.ReadBytes(reader.ReadInt32());
} }
byte[] decrypt_v15_r60785(BinaryReader reader, out byte[] key, out byte[] iv) { byte[] Decrypt_v15_r60785(BinaryReader reader, out byte[] key, out byte[] iv) {
var encrypted = reader.ReadBytes(reader.ReadInt32()); var encrypted = reader.ReadBytes(reader.ReadInt32());
iv = reader.ReadBytes(reader.ReadInt32()); iv = reader.ReadBytes(reader.ReadInt32());
key = reader.ReadBytes(reader.ReadInt32()); key = reader.ReadBytes(reader.ReadInt32());
@ -523,22 +523,22 @@ namespace de4dot.code.deobfuscators.Confuser {
return encrypted; return encrypted;
} }
byte[] decrypt_v17_r73404(byte[] data) { byte[] Decrypt_v17_r73404(byte[] data) {
var reader = new BinaryReader(new MemoryStream(data)); var reader = new BinaryReader(new MemoryStream(data));
byte[] key, iv; byte[] key, iv;
data = decrypt_v15_r60785(reader, out key, out iv); data = Decrypt_v15_r60785(reader, out key, out iv);
reader = new BinaryReader(new MemoryStream(DeobUtils.inflate(DeobUtils.aesDecrypt(data, key, iv), true))); reader = new BinaryReader(new MemoryStream(DeobUtils.Inflate(DeobUtils.AesDecrypt(data, key, iv), true)));
return reader.ReadBytes(reader.ReadInt32()); return reader.ReadBytes(reader.ReadInt32());
} }
byte[] decrypt_v17_r75076(byte[] data) { byte[] Decrypt_v17_r75076(byte[] data) {
var reader = new BinaryReader(new MemoryStream(data)); var reader = new BinaryReader(new MemoryStream(data));
byte[] key, iv; byte[] key, iv;
data = decrypt_v15_r60785(reader, out key, out iv); data = Decrypt_v15_r60785(reader, out key, out iv);
return sevenzipDecompress(DeobUtils.aesDecrypt(data, key, iv)); return SevenzipDecompress(DeobUtils.AesDecrypt(data, key, iv));
} }
static byte[] sevenzipDecompress(byte[] data) { static byte[] SevenzipDecompress(byte[] data) {
var reader = new BinaryReader(new MemoryStream(data)); var reader = new BinaryReader(new MemoryStream(data));
int totalSize = reader.ReadInt32(); int totalSize = reader.ReadInt32();
var props = reader.ReadBytes(5); var props = reader.ReadBytes(5);
@ -552,15 +552,15 @@ namespace de4dot.code.deobfuscators.Confuser {
return decompressed; return decompressed;
} }
public void deobfuscate(Blocks blocks) { public void Deobfuscate(Blocks blocks) {
if (asmResolverMethod == null) if (asmResolverMethod == null)
return; return;
if (blocks.Method != DotNetUtils.getModuleTypeCctor(module)) if (blocks.Method != DotNetUtils.GetModuleTypeCctor(module))
return; return;
ConfuserUtils.removeResourceHookCode(blocks, asmResolverMethod); ConfuserUtils.RemoveResourceHookCode(blocks, asmResolverMethod);
} }
public bool getRevisionRange(out int minRev, out int maxRev) { public bool GetRevisionRange(out int minRev, out int maxRev) {
switch (version) { switch (version) {
case ConfuserVersion.Unknown: case ConfuserVersion.Unknown:
minRev = maxRev = 0; minRev = maxRev = 0;

View File

@ -76,7 +76,7 @@ namespace de4dot.code.deobfuscators.Confuser {
} }
} }
public void addRevs(int min, int max) { public void AddRevs(int min, int max) {
if (min < 0 || max < 0 || min > max) if (min < 0 || max < 0 || min > max)
throw new ArgumentOutOfRangeException(); throw new ArgumentOutOfRangeException();
if (!revToVersion.ContainsKey(min) || (max != int.MaxValue && !revToVersion.ContainsKey(max))) if (!revToVersion.ContainsKey(min) || (max != int.MaxValue && !revToVersion.ContainsKey(max)))
@ -88,7 +88,7 @@ namespace de4dot.code.deobfuscators.Confuser {
maxRev = max; maxRev = max;
} }
public void setVersion(Version version) { public void SetVersion(Version version) {
if (version == null) if (version == null)
return; return;
int minRev = int.MaxValue, maxRev = int.MinValue; int minRev = int.MaxValue, maxRev = int.MinValue;
@ -104,10 +104,10 @@ namespace de4dot.code.deobfuscators.Confuser {
return; return;
if (maxRev == revs[revs.Length - 1]) if (maxRev == revs[revs.Length - 1])
maxRev = int.MaxValue; maxRev = int.MaxValue;
addRevs(minRev, maxRev); AddRevs(minRev, maxRev);
} }
public string getVersionString() { public string GetVersionString() {
if (minRev > maxRev || minRev < 0) if (minRev > maxRev || minRev < 0)
return null; return null;
var minVersion = revToVersion[minRev]; var minVersion = revToVersion[minRev];
@ -130,7 +130,7 @@ namespace de4dot.code.deobfuscators.Confuser {
} }
public override string ToString() { public override string ToString() {
return getVersionString() ?? "<no version>"; return GetVersionString() ?? "<no version>";
} }
} }
} }

View File

@ -126,20 +126,20 @@ namespace de4dot.code.deobfuscators.Confuser {
this.reader = peImage.Reader; this.reader = peImage.Reader;
} }
public uint emulate(uint rva, uint arg) { public uint Emulate(uint rva, uint arg) {
return emulate(rva, new uint[] { arg }); return Emulate(rva, new uint[] { arg });
} }
public uint emulate(uint rva, uint[] args) { public uint Emulate(uint rva, uint[] args) {
initialize(args); Initialize(args);
reader.Position = peImage.rvaToOffset(rva); reader.Position = peImage.RvaToOffset(rva);
byte[] prolog, epilog; byte[] prolog, epilog;
if (isBytes(prolog1)) { if (IsBytes(prolog1)) {
prolog = prolog1; prolog = prolog1;
epilog = epilog1; epilog = epilog1;
} }
else if (isBytes(prolog2)) { else if (IsBytes(prolog2)) {
prolog = prolog2; prolog = prolog2;
epilog = epilog2; epilog = epilog2;
} }
@ -147,20 +147,20 @@ namespace de4dot.code.deobfuscators.Confuser {
throw new ApplicationException(string.Format("Missing prolog @ RVA {0:X8}", rva)); throw new ApplicationException(string.Format("Missing prolog @ RVA {0:X8}", rva));
reader.Position += prolog.Length; reader.Position += prolog.Length;
while (!isBytes(epilog)) while (!IsBytes(epilog))
emulate(); Emulate();
return regs[0]; return regs[0];
} }
void initialize(uint[] args) { void Initialize(uint[] args) {
this.args = args; this.args = args;
nextArgIndex = 0; nextArgIndex = 0;
for (int i = 0; i < regs.Length; i++) for (int i = 0; i < regs.Length; i++)
regs[i] = 0; regs[i] = 0;
} }
bool isBytes(IList<byte> bytes) { bool IsBytes(IList<byte> bytes) {
long oldPos = reader.Position; long oldPos = reader.Position;
bool result = true; bool result = true;
for (int i = 0; i < bytes.Count; i++) { for (int i = 0; i < bytes.Count; i++) {
@ -173,57 +173,57 @@ namespace de4dot.code.deobfuscators.Confuser {
return result; return result;
} }
void emulate() { void Emulate() {
var instr = decode(); var instr = Decode();
switch (instr.opCode) { switch (instr.opCode) {
case OpCode.Add_RI: case OpCode.Add_RI:
case OpCode.Add_RR: case OpCode.Add_RR:
writeReg(instr.op1, readOp(instr.op1) + readOp(instr.op2)); WriteReg(instr.op1, ReadOp(instr.op1) + ReadOp(instr.op2));
break; break;
case OpCode.Mov_RI: case OpCode.Mov_RI:
case OpCode.Mov_RR: case OpCode.Mov_RR:
writeReg(instr.op1, readOp(instr.op2)); WriteReg(instr.op1, ReadOp(instr.op2));
break; break;
case OpCode.Neg_R: case OpCode.Neg_R:
writeReg(instr.op1, (uint)-(int)readOp(instr.op1)); WriteReg(instr.op1, (uint)-(int)ReadOp(instr.op1));
break; break;
case OpCode.Not_R: case OpCode.Not_R:
writeReg(instr.op1, ~readOp(instr.op1)); WriteReg(instr.op1, ~ReadOp(instr.op1));
break; break;
case OpCode.Pop_R: case OpCode.Pop_R:
writeReg(instr.op1, getNextArg()); WriteReg(instr.op1, GetNextArg());
break; break;
case OpCode.Sub_RI: case OpCode.Sub_RI:
case OpCode.Sub_RR: case OpCode.Sub_RR:
writeReg(instr.op1, readOp(instr.op1) - readOp(instr.op2)); WriteReg(instr.op1, ReadOp(instr.op1) - ReadOp(instr.op2));
break; break;
case OpCode.Xor_RI: case OpCode.Xor_RI:
case OpCode.Xor_RR: case OpCode.Xor_RR:
writeReg(instr.op1, readOp(instr.op1) ^ readOp(instr.op2)); WriteReg(instr.op1, ReadOp(instr.op1) ^ ReadOp(instr.op2));
break; break;
default: throw new NotSupportedException(); default: throw new NotSupportedException();
} }
} }
uint getNextArg() { uint GetNextArg() {
if (nextArgIndex >= args.Length) if (nextArgIndex >= args.Length)
throw new ApplicationException("No more args"); throw new ApplicationException("No more args");
return args[nextArgIndex++]; return args[nextArgIndex++];
} }
void writeReg(IOperand op, uint val) { void WriteReg(IOperand op, uint val) {
var regOp = (RegOperand)op; var regOp = (RegOperand)op;
regs[regOp.reg] = val; regs[regOp.reg] = val;
} }
uint readOp(IOperand op) { uint ReadOp(IOperand op) {
var regOp = op as RegOperand; var regOp = op as RegOperand;
if (regOp != null) if (regOp != null)
return regs[regOp.reg]; return regs[regOp.reg];
@ -235,19 +235,19 @@ namespace de4dot.code.deobfuscators.Confuser {
throw new NotSupportedException(); throw new NotSupportedException();
} }
Instruction decode() { Instruction Decode() {
byte opc = reader.ReadByte(); byte opc = reader.ReadByte();
switch (opc) { switch (opc) {
case 0x01: // ADD Ed,Gd case 0x01: // ADD Ed,Gd
parseModRM(); ParseModRM();
return new Instruction(OpCode.Add_RR, new RegOperand(rm), new RegOperand(reg)); return new Instruction(OpCode.Add_RR, new RegOperand(rm), new RegOperand(reg));
case 0x29: // SUB Ed,Gd case 0x29: // SUB Ed,Gd
parseModRM(); ParseModRM();
return new Instruction(OpCode.Sub_RR, new RegOperand(rm), new RegOperand(reg)); return new Instruction(OpCode.Sub_RR, new RegOperand(rm), new RegOperand(reg));
case 0x31: // XOR Ed,Gd case 0x31: // XOR Ed,Gd
parseModRM(); ParseModRM();
return new Instruction(OpCode.Xor_RR, new RegOperand(rm), new RegOperand(reg)); return new Instruction(OpCode.Xor_RR, new RegOperand(rm), new RegOperand(reg));
case 0x58: // POP EAX case 0x58: // POP EAX
@ -261,7 +261,7 @@ namespace de4dot.code.deobfuscators.Confuser {
return new Instruction(OpCode.Pop_R, new RegOperand(opc - 0x58)); return new Instruction(OpCode.Pop_R, new RegOperand(opc - 0x58));
case 0x81: // Grp1 Ed,Id case 0x81: // Grp1 Ed,Id
parseModRM(); ParseModRM();
switch (reg) { switch (reg) {
case 0: return new Instruction(OpCode.Add_RI, new RegOperand(rm), new ImmOperand(reader.ReadInt32())); case 0: return new Instruction(OpCode.Add_RI, new RegOperand(rm), new ImmOperand(reader.ReadInt32()));
case 5: return new Instruction(OpCode.Sub_RI, new RegOperand(rm), new ImmOperand(reader.ReadInt32())); case 5: return new Instruction(OpCode.Sub_RI, new RegOperand(rm), new ImmOperand(reader.ReadInt32()));
@ -270,7 +270,7 @@ namespace de4dot.code.deobfuscators.Confuser {
} }
case 0x89: // MOV Ed,Gd case 0x89: // MOV Ed,Gd
parseModRM(); ParseModRM();
return new Instruction(OpCode.Mov_RR, new RegOperand(rm), new RegOperand(reg)); return new Instruction(OpCode.Mov_RR, new RegOperand(rm), new RegOperand(reg));
case 0xB8: // MOV EAX,Id case 0xB8: // MOV EAX,Id
@ -284,7 +284,7 @@ namespace de4dot.code.deobfuscators.Confuser {
return new Instruction(OpCode.Mov_RI, new RegOperand(opc - 0xB8), new ImmOperand(reader.ReadInt32())); return new Instruction(OpCode.Mov_RI, new RegOperand(opc - 0xB8), new ImmOperand(reader.ReadInt32()));
case 0xF7: // Grp3 Ev case 0xF7: // Grp3 Ev
parseModRM(); ParseModRM();
switch (reg) { switch (reg) {
case 2: return new Instruction(OpCode.Not_R, new RegOperand(rm)); case 2: return new Instruction(OpCode.Not_R, new RegOperand(rm));
case 3: return new Instruction(OpCode.Neg_R, new RegOperand(rm)); case 3: return new Instruction(OpCode.Neg_R, new RegOperand(rm));
@ -295,7 +295,7 @@ namespace de4dot.code.deobfuscators.Confuser {
} }
} }
void parseModRM() { void ParseModRM() {
modRM = reader.ReadByte(); modRM = reader.ReadByte();
mod = (byte)((modRM >> 6) & 7); mod = (byte)((modRM >> 6) & 7);
reg = (byte)((modRM >> 3) & 7); reg = (byte)((modRM >> 3) & 7);