Update fields restorer

This commit is contained in:
de4dot 2012-05-10 20:20:29 +02:00
parent 1d2a78979f
commit cd014f1d72

View File

@ -21,6 +21,7 @@ using System;
using System.Collections.Generic;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Cecil.Metadata;
using de4dot.blocks;
namespace de4dot.code.deobfuscators.DeepSea {
@ -35,7 +36,7 @@ namespace de4dot.code.deobfuscators.DeepSea {
get {
var list = new List<TypeDefinition>(structToOwners.Count);
foreach (var structType in structToOwners.getKeys()) {
if (structType.Methods.Count != 0)
if (!hasNoMethods(structType))
continue;
list.Add(structType);
@ -44,6 +45,21 @@ namespace de4dot.code.deobfuscators.DeepSea {
}
}
static bool hasNoMethods(TypeDefinition type) {
if (type.Methods.Count == 0)
return true;
if (type.BaseType == null)
return false;
if (type.BaseType.EType != ElementType.Object)
return false;
if (type.Methods.Count != 1)
return false;
var ctor = type.Methods[0];
if (ctor.Name != ".ctor" || ctor.Parameters.Count != 0)
return false;
return true;
}
public FieldsRestorer(ModuleDefinition module) {
this.module = module;
}
@ -78,7 +94,9 @@ namespace de4dot.code.deobfuscators.DeepSea {
foreach (var type in module.GetTypes()) {
foreach (var field in getPossibleFields(type)) {
var fieldType = DotNetUtils.getType(module, field.FieldType);
if (fieldType == null || !fieldType.IsValueType)
if (fieldType == null)
continue;
if (!checkBaseType(fieldType))
continue;
if ((fieldType.Attributes & ~TypeAttributes.Sealed) != TypeAttributes.NestedAssembly)
continue;
@ -90,9 +108,9 @@ namespace de4dot.code.deobfuscators.DeepSea {
continue;
if (fieldType.HasEvents || fieldType.HasProperties || fieldType.HasInterfaces)
continue;
if (hasNonStaticMethods(fieldType))
if (checkMethods(fieldType))
continue;
if (hasStaticFields(fieldType))
if (!checkFields(fieldType))
continue;
List<TypeDefinition> list;
@ -132,7 +150,9 @@ namespace de4dot.code.deobfuscators.DeepSea {
if (field.Attributes != FieldAttributes.Private)
continue;
var fieldType = DotNetUtils.getType(module, field.FieldType);
if (fieldType == null || !fieldType.IsValueType)
if (fieldType == null)
continue;
if (!checkBaseType(fieldType))
continue;
var list = typeToFields.find(fieldType);
if (list == null)
@ -146,6 +166,12 @@ namespace de4dot.code.deobfuscators.DeepSea {
}
}
static bool checkBaseType(TypeDefinition type) {
if (type == null || type.BaseType == null)
return false;
return type.BaseType.FullName == "System.ValueType" || type.BaseType.EType == ElementType.Object;
}
void removeType(Dictionary<TypeDefinition, List<TypeDefinition>> candidates, TypeReference type) {
var typeDef = DotNetUtils.getType(module, type);
if (typeDef == null)
@ -153,10 +179,12 @@ namespace de4dot.code.deobfuscators.DeepSea {
candidates.Remove(typeDef);
}
static bool hasNonStaticMethods(TypeDefinition type) {
static bool checkMethods(TypeDefinition type) {
foreach (var method in type.Methods) {
if (method.Name == ".cctor")
continue;
if (type.BaseType != null && type.BaseType.EType == ElementType.Object && method.Name == ".ctor" && method.Parameters.Count == 0)
continue;
if (!method.IsStatic)
return true;
if (method.GenericParameters.Count > 0)
@ -169,22 +197,31 @@ namespace de4dot.code.deobfuscators.DeepSea {
return false;
}
static bool hasStaticFields(TypeDefinition type) {
static bool checkFields(TypeDefinition type) {
if (type.Fields.Count == 0)
return false;
foreach (var field in type.Fields) {
if (field.IsStatic)
return true;
return false;
if (!field.IsAssembly)
return false;
}
return false;
return true;
}
public void deobfuscate(Blocks blocks) {
deobfuscateNormal(blocks);
fixFieldCtorCalls(blocks);
}
void deobfuscateNormal(Blocks blocks) {
var instrsToRemove = new List<int>();
foreach (var block in blocks.MethodBlocks.getAllBlocks()) {
instrsToRemove.Clear();
var instrs = block.Instructions;
for (int i = instrs.Count - 1; i >= 0; i--) {
var instr = instrs[i];
if (instr.OpCode.Code != Code.Ldflda)
if (instr.OpCode.Code != Code.Ldflda && instr.OpCode.Code != Code.Ldfld)
continue;
var structField = instr.Operand as FieldReference;
if (structField == null || !structFieldsToFix.find(structField))
@ -199,6 +236,40 @@ namespace de4dot.code.deobfuscators.DeepSea {
}
}
void fixFieldCtorCalls(Blocks blocks) {
if (blocks.Method.Name != ".ctor")
return;
var instrsToRemove = new List<int>();
foreach (var block in blocks.MethodBlocks.getAllBlocks()) {
var instrs = block.Instructions;
for (int i = 0; i < instrs.Count; i++) {
var stfld = instrs[i];
if (stfld.OpCode.Code != Code.Stfld)
continue;
var field = stfld.Operand as FieldReference;
if (field == null)
continue;
if (!structFieldsToFix.find(field))
continue;
var instrs2 = toInstructionList(instrs);
var instrPushes = DotNetUtils.getArgPushes(instrs2, i);
if (instrPushes == null || instrPushes.Count != 2)
continue;
block.remove(i, 1);
block.remove(instrs2.IndexOf(instrPushes[1]), 1);
block.remove(instrs2.IndexOf(instrPushes[0]), 1);
i -= 3;
}
}
}
static IList<Instruction> toInstructionList(IEnumerable<Instr> instrs) {
var newInstrs = new List<Instruction>();
foreach (var instr in instrs)
newInstrs.Add(instr.Instruction);
return newInstrs;
}
FieldDefinition getNewField(FieldReference structField, FieldReference oldFieldRef) {
var fieldsDict = typeToFieldsDict.find(structField.DeclaringType);
if (fieldsDict == null)