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);
List<FieldInfo> fieldInfosTmp;
if (checkHandlerV4(handler, out fieldInfosTmp)) {
if (checkHandlerV4(handler, out fieldInfosTmp) ||
checkHandlerV4_0_4(handler, out fieldInfosTmp)) {
isV3 = false;
fieldInfos = fieldInfosTmp;
return true;
@ -110,29 +111,93 @@ namespace de4dot.code.deobfuscators.DeepSea {
return new LocalTypes(handler).all(handlerLocalTypes_SL);
}
// 4.0.1.18 .. 4.0.3
bool checkHandlerV4(MethodDefinition handler, out List<FieldInfo> fieldInfos) {
fieldInfos = new List<FieldInfo>();
var instrs = handler.Body.Instructions;
for (int i = 0; i < instrs.Count - 2; i++) {
var ldtoken = instrs[i];
for (int i = 0; i < instrs.Count - 3; i++) {
int index = i;
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)
return false;
var ldci4_len = instrs[i + 1];
var ldci4_len = instrs[index++];
if (!DotNetUtils.isLdcI4(ldci4_len))
return false;
if (DotNetUtils.getLdcI4Value(ldci4_len) != field.InitialValue.Length)
return false;
var ldci4_magic = instrs[i + 2];
var ldci4_magic = instrs[index++];
if (!DotNetUtils.isLdcI4(ldci4_magic))
return false;
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));
}
@ -145,7 +210,7 @@ namespace de4dot.code.deobfuscators.DeepSea {
return getAssemblyInfosV4();
}
public IEnumerable<AssemblyInfo> getAssemblyInfosV3() {
IEnumerable<AssemblyInfo> getAssemblyInfosV3() {
var infos = new List<AssemblyInfo>();
foreach (var tmp in module.Resources) {
@ -180,7 +245,7 @@ namespace de4dot.code.deobfuscators.DeepSea {
return new AssemblyInfo(decryptedData, fullName, simpleName, extension, resource);
}
public IEnumerable<AssemblyInfo> getAssemblyInfosV4() {
IEnumerable<AssemblyInfo> getAssemblyInfosV4() {
var infos = new List<AssemblyInfo>();
if (fieldInfos == null)

View File

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

View File

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

View File

@ -25,9 +25,14 @@ namespace de4dot.code.deobfuscators.DeepSea {
class ResourceResolver : ResolverBase {
EmbeddedResource resource;
FieldDefinition resourceField;
MethodDefinition getDataMethod;
int magicV4;
bool isV3;
public MethodDefinition GetDataMethod {
get { return getDataMethod; }
}
public EmbeddedResource Resource {
get { return resource; }
}
@ -47,10 +52,12 @@ namespace de4dot.code.deobfuscators.DeepSea {
}
FieldDefinition resourceFieldTmp;
MethodDefinition getDataMethodTmp;
simpleDeobfuscator.deobfuscate(handler);
if (checkHandlerV4(handler, out resourceFieldTmp, out magicV4)) {
if (checkHandlerV4(handler, out resourceFieldTmp, out getDataMethodTmp, out magicV4)) {
isV3 = false;
resourceField = resourceFieldTmp;
getDataMethod = getDataMethodTmp;
return true;
}
@ -72,25 +79,65 @@ namespace de4dot.code.deobfuscators.DeepSea {
return new LocalTypes(handler).all(handlerLocalTypes_V3);
}
static bool checkHandlerV4(MethodDefinition handler, out FieldDefinition resourceField, out int magic) {
magic = 0;
resourceField = getResourceField(handler);
if (resourceField == null)
return false;
static bool checkHandlerV4(MethodDefinition handler, out FieldDefinition resourceField, out MethodDefinition getDataMethod, out int magic) {
var instrs = handler.Body.Instructions;
for (int i = 0; i < instrs.Count; i++) {
int index = i;
bool foundFieldLen = false;
foreach (var instr in handler.Body.Instructions) {
if (!DotNetUtils.isLdcI4(instr))
if (instrs[index++].OpCode.Code != Code.Ldarg_1)
continue;
int constant = DotNetUtils.getLdcI4Value(instr);
if (constant == resourceField.InitialValue.Length && !foundFieldLen) {
foundFieldLen = true;
var ldtoken = instrs[index++];
if (ldtoken.OpCode.Code != Code.Ldtoken)
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;
}
magic = 0;
resourceField = null;
getDataMethod = null;
return false;
}