Support latest DeepSea version (4.0.4.32)

This commit is contained in:
de4dot 2012-03-13 20:28:01 +01:00
parent ada90b1294
commit a405edf0fd
4 changed files with 146 additions and 31 deletions

View File

@ -76,7 +76,8 @@ namespace de4dot.code.deobfuscators.DeepSea {
simpleDeobfuscator.deobfuscate(handler); simpleDeobfuscator.deobfuscate(handler);
List<FieldInfo> fieldInfosTmp; List<FieldInfo> fieldInfosTmp;
if (checkHandlerV4(handler, out fieldInfosTmp)) { if (checkHandlerV4(handler, out fieldInfosTmp) ||
checkHandlerV4_0_4(handler, out fieldInfosTmp)) {
isV3 = false; isV3 = false;
fieldInfos = fieldInfosTmp; fieldInfos = fieldInfosTmp;
return true; return true;
@ -110,29 +111,93 @@ namespace de4dot.code.deobfuscators.DeepSea {
return new LocalTypes(handler).all(handlerLocalTypes_SL); return new LocalTypes(handler).all(handlerLocalTypes_SL);
} }
// 4.0.1.18 .. 4.0.3
bool checkHandlerV4(MethodDefinition handler, out List<FieldInfo> fieldInfos) { bool checkHandlerV4(MethodDefinition handler, out List<FieldInfo> fieldInfos) {
fieldInfos = new List<FieldInfo>(); fieldInfos = new List<FieldInfo>();
var instrs = handler.Body.Instructions; var instrs = handler.Body.Instructions;
for (int i = 0; i < instrs.Count - 2; i++) { for (int i = 0; i < instrs.Count - 3; i++) {
var ldtoken = instrs[i]; int index = i;
var ldtoken = instrs[index++];
if (ldtoken.OpCode.Code != Code.Ldtoken) if (ldtoken.OpCode.Code != Code.Ldtoken)
continue; continue;
var field = ldtoken.Operand as FieldDefinition; var field = ldtoken.Operand as FieldDefinition;
if (field == null || field.InitialValue == null || field.InitialValue.Length == 0) if (field == null || field.InitialValue == null || field.InitialValue.Length == 0)
return false; return false;
var ldci4_len = instrs[i + 1]; var ldci4_len = instrs[index++];
if (!DotNetUtils.isLdcI4(ldci4_len)) if (!DotNetUtils.isLdcI4(ldci4_len))
return false; return false;
if (DotNetUtils.getLdcI4Value(ldci4_len) != field.InitialValue.Length) if (DotNetUtils.getLdcI4Value(ldci4_len) != field.InitialValue.Length)
return false; return false;
var ldci4_magic = instrs[i + 2]; var ldci4_magic = instrs[index++];
if (!DotNetUtils.isLdcI4(ldci4_magic)) if (!DotNetUtils.isLdcI4(ldci4_magic))
return false; return false;
int magic = DotNetUtils.getLdcI4Value(ldci4_magic); int magic = DotNetUtils.getLdcI4Value(ldci4_magic);
var call = instrs[index++];
if (call.OpCode.Code == Code.Tail)
call = instrs[index++];
if (call.OpCode.Code != Code.Call)
return false;
if (!DotNetUtils.isMethod(call.Operand as MethodReference, "System.Reflection.Assembly", "(System.RuntimeFieldHandle,System.Int32,System.Int32)"))
return false;
fieldInfos.Add(new FieldInfo(field, magic));
}
return fieldInfos.Count != 0;
}
// 4.0.4+
bool checkHandlerV4_0_4(MethodDefinition handler, out List<FieldInfo> fieldInfos) {
fieldInfos = new List<FieldInfo>();
var instrs = handler.Body.Instructions;
for (int i = 0; i < instrs.Count - 8; i++) {
int index = i;
var ldci4_len = instrs[index++];
if (!DotNetUtils.isLdcI4(ldci4_len))
continue;
if (instrs[index++].OpCode.Code != Code.Newarr)
continue;
if (!DotNetUtils.isStloc(instrs[index++]))
continue;
if (!DotNetUtils.isLdloc(instrs[index++]))
continue;
var ldtoken = instrs[index++];
if (ldtoken.OpCode.Code != Code.Ldtoken)
continue;
var field = ldtoken.Operand as FieldDefinition;
if (field == null || field.InitialValue == null || field.InitialValue.Length == 0)
continue;
var call1 = instrs[index++];
if (call1.OpCode.Code != Code.Call)
continue;
if (!DotNetUtils.isMethod(call1.Operand as MethodReference, "System.Void", "(System.Array,System.RuntimeFieldHandle)"))
continue;
if (!DotNetUtils.isLdloc(instrs[index++]))
continue;
var ldci4_magic = instrs[index++];
if (!DotNetUtils.isLdcI4(ldci4_magic))
continue;
int magic = DotNetUtils.getLdcI4Value(ldci4_magic);
var call2 = instrs[index++];
if (call2.OpCode.Code == Code.Tail)
call2 = instrs[index++];
if (call2.OpCode.Code != Code.Call)
continue;
if (!DotNetUtils.isMethod(call2.Operand as MethodReference, "System.Reflection.Assembly", "(System.Byte[],System.Int32)"))
continue;
fieldInfos.Add(new FieldInfo(field, magic)); fieldInfos.Add(new FieldInfo(field, magic));
} }
@ -145,7 +210,7 @@ namespace de4dot.code.deobfuscators.DeepSea {
return getAssemblyInfosV4(); return getAssemblyInfosV4();
} }
public IEnumerable<AssemblyInfo> getAssemblyInfosV3() { IEnumerable<AssemblyInfo> getAssemblyInfosV3() {
var infos = new List<AssemblyInfo>(); var infos = new List<AssemblyInfo>();
foreach (var tmp in module.Resources) { foreach (var tmp in module.Resources) {
@ -180,7 +245,7 @@ namespace de4dot.code.deobfuscators.DeepSea {
return new AssemblyInfo(decryptedData, fullName, simpleName, extension, resource); return new AssemblyInfo(decryptedData, fullName, simpleName, extension, resource);
} }
public IEnumerable<AssemblyInfo> getAssemblyInfosV4() { IEnumerable<AssemblyInfo> getAssemblyInfosV4() {
var infos = new List<AssemblyInfo>(); var infos = new List<AssemblyInfo>();
if (fieldInfos == null) if (fieldInfos == null)

View File

@ -208,6 +208,7 @@ done:
addCallToBeRemoved(module.EntryPoint, resourceResolver.InitMethod); addCallToBeRemoved(module.EntryPoint, resourceResolver.InitMethod);
addMethodToBeRemoved(resourceResolver.InitMethod, "Resource resolver init method"); addMethodToBeRemoved(resourceResolver.InitMethod, "Resource resolver init method");
addMethodToBeRemoved(resourceResolver.HandlerMethod, "Resource resolver handler method"); addMethodToBeRemoved(resourceResolver.HandlerMethod, "Resource resolver handler method");
addMethodToBeRemoved(resourceResolver.GetDataMethod, "Resource resolver 'get resource data' method");
} }
void dumpEmbeddedAssemblies() { void dumpEmbeddedAssemblies() {

View File

@ -18,6 +18,7 @@
*/ */
using System; using System;
using System.Collections.Generic;
using Mono.Cecil; using Mono.Cecil;
using Mono.Cecil.Cil; using Mono.Cecil.Cil;
using de4dot.blocks; using de4dot.blocks;
@ -80,16 +81,16 @@ namespace de4dot.code.deobfuscators.DeepSea {
if (!checkResolverInitMethodInternal(resolverInitMethod)) if (!checkResolverInitMethodInternal(resolverInitMethod))
return false; return false;
var resolveHandlerMethod = getLdftnMethod(resolverInitMethod); foreach (var resolveHandlerMethod in getLdftnMethods(resolverInitMethod)) {
if (resolveHandlerMethod == null) if (!checkHandlerMethod(resolveHandlerMethod))
return false; continue;
if (!checkHandlerMethod(resolveHandlerMethod)) initMethod = resolverInitMethod;
return false; resolveHandler = resolveHandlerMethod;
return true;
}
initMethod = resolverInitMethod; return false;
resolveHandler = resolveHandlerMethod;
return true;
} }
protected abstract bool checkResolverInitMethodInternal(MethodDefinition resolverInitMethod); protected abstract bool checkResolverInitMethodInternal(MethodDefinition resolverInitMethod);
@ -107,15 +108,16 @@ namespace de4dot.code.deobfuscators.DeepSea {
return false; return false;
} }
MethodDefinition getLdftnMethod(MethodDefinition method) { IEnumerable<MethodDefinition> getLdftnMethods(MethodDefinition method) {
var list = new List<MethodDefinition>();
foreach (var instr in method.Body.Instructions) { foreach (var instr in method.Body.Instructions) {
if (instr.OpCode.Code != Code.Ldftn) if (instr.OpCode.Code != Code.Ldftn)
continue; continue;
var loadedMethod = instr.Operand as MethodDefinition; var loadedMethod = instr.Operand as MethodDefinition;
if (loadedMethod != null) if (loadedMethod != null)
return loadedMethod; list.Add(loadedMethod);
} }
return null; return list;
} }
bool checkHandlerMethod(MethodDefinition handler) { bool checkHandlerMethod(MethodDefinition handler) {

View File

@ -25,9 +25,14 @@ namespace de4dot.code.deobfuscators.DeepSea {
class ResourceResolver : ResolverBase { class ResourceResolver : ResolverBase {
EmbeddedResource resource; EmbeddedResource resource;
FieldDefinition resourceField; FieldDefinition resourceField;
MethodDefinition getDataMethod;
int magicV4; int magicV4;
bool isV3; bool isV3;
public MethodDefinition GetDataMethod {
get { return getDataMethod; }
}
public EmbeddedResource Resource { public EmbeddedResource Resource {
get { return resource; } get { return resource; }
} }
@ -47,10 +52,12 @@ namespace de4dot.code.deobfuscators.DeepSea {
} }
FieldDefinition resourceFieldTmp; FieldDefinition resourceFieldTmp;
MethodDefinition getDataMethodTmp;
simpleDeobfuscator.deobfuscate(handler); simpleDeobfuscator.deobfuscate(handler);
if (checkHandlerV4(handler, out resourceFieldTmp, out magicV4)) { if (checkHandlerV4(handler, out resourceFieldTmp, out getDataMethodTmp, out magicV4)) {
isV3 = false; isV3 = false;
resourceField = resourceFieldTmp; resourceField = resourceFieldTmp;
getDataMethod = getDataMethodTmp;
return true; return true;
} }
@ -72,25 +79,65 @@ namespace de4dot.code.deobfuscators.DeepSea {
return new LocalTypes(handler).all(handlerLocalTypes_V3); return new LocalTypes(handler).all(handlerLocalTypes_V3);
} }
static bool checkHandlerV4(MethodDefinition handler, out FieldDefinition resourceField, out int magic) { static bool checkHandlerV4(MethodDefinition handler, out FieldDefinition resourceField, out MethodDefinition getDataMethod, out int magic) {
magic = 0; var instrs = handler.Body.Instructions;
resourceField = getResourceField(handler); for (int i = 0; i < instrs.Count; i++) {
if (resourceField == null) int index = i;
return false;
bool foundFieldLen = false; if (instrs[index++].OpCode.Code != Code.Ldarg_1)
foreach (var instr in handler.Body.Instructions) {
if (!DotNetUtils.isLdcI4(instr))
continue; continue;
int constant = DotNetUtils.getLdcI4Value(instr);
if (constant == resourceField.InitialValue.Length && !foundFieldLen) { var ldtoken = instrs[index++];
foundFieldLen = true; if (ldtoken.OpCode.Code != Code.Ldtoken)
continue; continue;
var field = ldtoken.Operand as FieldDefinition;
string methodSig = "(System.ResolveEventArgs,System.RuntimeFieldHandle,System.Int32,System.String,System.Int32)";
var method = ldtoken.Operand as MethodDefinition;
if (method != null) {
// >= 4.0.4
if (!DotNetUtils.isMethod(method, "System.Byte[]", "()"))
continue;
field = getResourceField(method);
methodSig = "(System.ResolveEventArgs,System.RuntimeMethodHandle,System.Int32,System.String,System.Int32)";
} }
magic = constant; else {
// 4.0.1.18 .. 4.0.3
}
if (field.InitialValue == null || field.InitialValue.Length == 0)
continue;
var ldci4_len = instrs[index++];
if (!DotNetUtils.isLdcI4(ldci4_len))
continue;
if (DotNetUtils.getLdcI4Value(ldci4_len) != field.InitialValue.Length)
continue;
if (instrs[index++].OpCode.Code != Code.Ldstr)
continue;
var ldci4_magic = instrs[index++];
if (!DotNetUtils.isLdcI4(ldci4_magic))
continue;
magic = DotNetUtils.getLdcI4Value(ldci4_magic);
var call = instrs[index++];
if (call.OpCode.Code == Code.Tail)
call = instrs[index++];
if (call.OpCode.Code != Code.Call)
continue;
if (!DotNetUtils.isMethod(call.Operand as MethodReference, "System.Reflection.Assembly", methodSig))
continue;
resourceField = field;
getDataMethod = method;
return true; return true;
} }
magic = 0;
resourceField = null;
getDataMethod = null;
return false; return false;
} }