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);
|
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)
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user