Support latest DeepSea version (4.0.4.32)
This commit is contained in:
parent
ada90b1294
commit
a405edf0fd
|
@ -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)
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Mono.Cecil;
|
||||
using Mono.Cecil.Cil;
|
||||
using de4dot.blocks;
|
||||
|
@ -80,18 +81,18 @@ 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))
|
||||
return false;
|
||||
continue;
|
||||
|
||||
initMethod = resolverInitMethod;
|
||||
resolveHandler = resolveHandlerMethod;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected abstract bool checkResolverInitMethodInternal(MethodDefinition resolverInitMethod);
|
||||
|
||||
protected static bool checkIfCalled(MethodDefinition method, string fullName) {
|
||||
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user