Merge branch 'port' into confuser

Conflicts:
	de4dot.code/de4dot.code.csproj
This commit is contained in:
de4dot 2012-11-18 21:10:47 +01:00
commit ff86ca6d24
294 changed files with 8683 additions and 9193 deletions

1
.gitignore vendored
View File

@ -7,3 +7,4 @@
/Debug/
/Release/
/de4dot.snk
/cecil/

6
.gitmodules vendored
View File

@ -1,3 +1,3 @@
[submodule "cecil"]
path = cecil
url = git@github.com:0xd4d/cecil.git
[submodule "dot10"]
path = dot10
url = e:/work/dot10.git

View File

@ -70,14 +70,14 @@
<Project>{045B96F2-AF80-4C4C-8D27-E38635AC705E}</Project>
<Name>blocks</Name>
</ProjectReference>
<ProjectReference Include="..\cecil\Mono.Cecil.csproj">
<Project>{D68133BD-1E63-496E-9EDE-4FBDBF77B486}</Project>
<Name>Mono.Cecil</Name>
</ProjectReference>
<ProjectReference Include="..\de4dot.mdecrypt\de4dot.mdecrypt.csproj">
<Project>{5C93C5E2-196F-4877-BF65-96FEBFCEFCA1}</Project>
<Name>de4dot.mdecrypt</Name>
</ProjectReference>
<ProjectReference Include="..\dot10\src\dot10.csproj">
<Project>{FDFC1237-143F-4919-8318-4926901F4639}</Project>
<Name>dot10</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.

View File

@ -21,7 +21,8 @@ using System;
using System.Collections.Generic;
using System.Reflection;
using System.Threading;
using Mono.MyStuff;
using dot10.DotNet;
using de4dot.blocks;
using de4dot.mdecrypt;
namespace AssemblyData {

View File

@ -17,7 +17,8 @@
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
*/
using Mono.MyStuff;
using dot10.DotNet;
using de4dot.blocks;
using de4dot.mdecrypt;
namespace AssemblyData {

View File

@ -24,7 +24,6 @@ using System.Reflection.Emit;
using System.Text;
namespace AssemblyData {
// Yes, I did type this by hand.
internal delegate void Action();
internal delegate void Action<T1>(T1 arg1);
internal delegate void Action<T1, T2>(T1 arg1, T2 arg2);
@ -45,7 +44,6 @@ namespace AssemblyData {
internal delegate void Action<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16, T17 arg17);
internal delegate void Action<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16, T17 arg17, T18 arg18);
internal delegate void Action<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16, T17 arg17, T18 arg18, T19 arg19);
// No that was a lie.
internal delegate TResult Func<TResult>();
internal delegate TResult Func<T1, TResult>(T1 arg1);
internal delegate TResult Func<T1, T2, TResult>(T1 arg1, T2 arg2);

View File

@ -20,7 +20,7 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using Mono.Cecil;
using dot10.DotNet;
using de4dot.blocks;
namespace AssemblyData.methodsrewriter {
@ -48,38 +48,41 @@ namespace AssemblyData.methodsrewriter {
}
}
TypeResolver getTypeResolver(TypeReference typeReference) {
var key = typeReference.Namespace + "." + typeReference.Name;
TypeResolver getTypeResolver(ITypeDefOrRef typeRef) {
if (typeRef == null)
return null;
var scopeType = typeRef.ScopeType;
var key = scopeType.Namespace + "." + scopeType.TypeName;
List<TypeResolver> list;
if (!types.TryGetValue(key, out list))
return null;
if (typeReference is TypeDefinition) {
if (scopeType is TypeDef) {
foreach (var resolver in list) {
if (resolver.type.MetadataToken == typeReference.MetadataToken.ToInt32())
if (resolver.type.MetadataToken == scopeType.MDToken.Raw)
return resolver;
}
}
foreach (var resolver in list) {
if (ResolverUtils.compareTypes(resolver.type, typeReference))
if (ResolverUtils.compareTypes(resolver.type, scopeType))
return resolver;
}
return null;
}
public FieldInfo resolve(FieldReference fieldReference) {
var resolver = getTypeResolver(fieldReference.DeclaringType);
public FieldInfo resolve(IField fieldRef) {
var resolver = getTypeResolver(fieldRef.DeclaringType);
if (resolver != null)
return resolver.resolve(fieldReference);
return resolveGlobalField(fieldReference);
return resolver.resolve(fieldRef);
return resolveGlobalField(fieldRef);
}
FieldInfo resolveGlobalField(FieldReference fieldReference) {
FieldInfo resolveGlobalField(IField fieldRef) {
initGlobalFields();
foreach (var globalField in globalFields) {
if (ResolverUtils.compareFields(globalField, fieldReference))
if (ResolverUtils.compareFields(globalField, fieldRef))
return globalField;
}
return null;
@ -97,17 +100,17 @@ namespace AssemblyData.methodsrewriter {
}
}
public MethodBase resolve(MethodReference methodReference) {
var resolver = getTypeResolver(methodReference.DeclaringType);
public MethodBase resolve(IMethod methodRef) {
var resolver = getTypeResolver(methodRef.DeclaringType);
if (resolver != null)
return resolver.resolve(methodReference);
return resolveGlobalMethod(methodReference);
return resolver.resolve(methodRef);
return resolveGlobalMethod(methodRef);
}
MethodBase resolveGlobalMethod(MethodReference methodReference) {
MethodBase resolveGlobalMethod(IMethod methodRef) {
initGlobalMethods();
foreach (var globalMethod in globalMethods) {
if (ResolverUtils.compareMethods(globalMethod, methodReference))
if (ResolverUtils.compareMethods(globalMethod, methodRef))
return globalMethod;
}
return null;
@ -125,12 +128,13 @@ namespace AssemblyData.methodsrewriter {
}
}
public Type resolve(TypeReference typeReference) {
var resolver = getTypeResolver(typeReference);
public Type resolve(ITypeDefOrRef typeRef) {
var resolver = getTypeResolver(typeRef);
if (resolver != null)
return resolver.type;
if (typeReference.IsGenericParameter)
var ts = typeRef as TypeSpec;
if (ts != null && ts.TypeSig is GenericSig)
return typeof(MGenericParameter);
return null;

View File

@ -22,13 +22,13 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Reflection.Emit;
using Mono.Cecil;
using Mono.Cecil.Cil;
using dot10.DotNet.Emit;
using dot10.DotNet;
using de4dot.blocks;
using OpCode = Mono.Cecil.Cil.OpCode;
using OpCodes = Mono.Cecil.Cil.OpCodes;
using OperandType = Mono.Cecil.Cil.OperandType;
using OpCode = dot10.DotNet.Emit.OpCode;
using OpCodes = dot10.DotNet.Emit.OpCodes;
using OperandType = dot10.DotNet.Emit.OperandType;
using ROpCode = System.Reflection.Emit.OpCode;
using ROpCodes = System.Reflection.Emit.OpCodes;
@ -94,7 +94,7 @@ namespace AssemblyData.methodsrewriter {
var dm = new DynamicMethod(methodName, methodReturnType, methodParameters, methodInfo.methodBase.Module, true);
var lastInstr = allInstructions[allInstructions.Count - 1];
ilg = dm.GetILGenerator(lastInstr.Offset + lastInstr.GetSize());
ilg = dm.GetILGenerator((int)lastInstr.Offset + lastInstr.GetSize());
initInstrToIndex();
initLocals();
@ -178,8 +178,8 @@ namespace AssemblyData.methodsrewriter {
void initLocals() {
locals = new List<LocalBuilder>();
foreach (var local in methodInfo.methodDefinition.Body.Variables)
locals.Add(ilg.DeclareLocal(Resolver.getRtType(local.VariableType), local.IsPinned));
foreach (var local in methodInfo.methodDef.Body.LocalList)
locals.Add(ilg.DeclareLocal(Resolver.getRtType(local.Type), local.Type.RemoveModifiers().IsPinned));
tempObjLocal = ilg.DeclareLocal(typeof(object));
tempObjArrayLocal = ilg.DeclareLocal(typeof(object[]));
}
@ -256,14 +256,6 @@ namespace AssemblyData.methodsrewriter {
return labels;
}
int getArgIndex(ParameterDefinition arg) {
return arg.Sequence;
}
int getLocalIndex(VariableDefinition local) {
return local.Index;
}
void writeInstr(Instruction instr) {
var opcode = convertOpCode(instr.OpCode);
switch (instr.OpCode.OperandType) {
@ -311,7 +303,7 @@ namespace AssemblyData.methodsrewriter {
case OperandType.InlineType:
case OperandType.InlineMethod:
case OperandType.InlineField:
var obj = Resolver.getRtObject((MemberReference)instr.Operand);
var obj = Resolver.getRtObject((ITokenOperand)instr.Operand);
if (obj is ConstructorInfo)
ilg.Emit(opcode, (ConstructorInfo)obj);
else if (obj is MethodInfo)
@ -324,20 +316,12 @@ namespace AssemblyData.methodsrewriter {
throw new ApplicationException(string.Format("Unknown type: {0}", (obj == null ? obj : obj.GetType())));
break;
case OperandType.InlineArg:
ilg.Emit(opcode, checked((short)getArgIndex((ParameterDefinition)instr.Operand)));
break;
case OperandType.ShortInlineArg:
ilg.Emit(opcode, checked((byte)getArgIndex((ParameterDefinition)instr.Operand)));
break;
case OperandType.InlineVar:
ilg.Emit(opcode, checked((short)getLocalIndex((VariableDefinition)instr.Operand)));
ilg.Emit(opcode, checked((short)((IVariable)instr.Operand).Index));
break;
case OperandType.ShortInlineVar:
ilg.Emit(opcode, checked((byte)getLocalIndex((VariableDefinition)instr.Operand)));
ilg.Emit(opcode, checked((byte)((IVariable)instr.Operand).Index));
break;
case OperandType.InlineSig: //TODO:

View File

@ -19,7 +19,6 @@
using System;
using System.Reflection;
using Mono.Cecil;
namespace AssemblyData.methodsrewriter {
interface IMethodsRewriter {

View File

@ -18,20 +18,20 @@
*/
using System.Reflection;
using Mono.Cecil;
using dot10.DotNet;
namespace AssemblyData.methodsrewriter {
class MField {
public FieldInfo fieldInfo;
public FieldDefinition fieldDefinition;
public FieldDef fieldDef;
public MField(FieldInfo fieldInfo, FieldDefinition fieldDefinition) {
public MField(FieldInfo fieldInfo, FieldDef fieldDef) {
this.fieldInfo = fieldInfo;
this.fieldDefinition = fieldDefinition;
this.fieldDef = fieldDef;
}
public override string ToString() {
return fieldDefinition.ToString();
return fieldDef.ToString();
}
}
}

View File

@ -18,23 +18,23 @@
*/
using System.Reflection;
using Mono.Cecil;
using dot10.DotNet;
namespace AssemblyData.methodsrewriter {
class MMethod {
public MethodBase methodBase;
public MethodDefinition methodDefinition;
public MMethod(MethodBase methodBase, MethodDefinition methodDefinition) {
public MethodDef methodDef;
public MMethod(MethodBase methodBase, MethodDef methodDefinition) {
this.methodBase = methodBase;
this.methodDefinition = methodDefinition;
this.methodDef = methodDefinition;
}
public bool hasInstructions() {
return methodDefinition.Body != null && methodDefinition.Body.Instructions.Count != 0;
return methodDef.Body != null && methodDef.Body.Instructions.Count != 0;
}
public override string ToString() {
return methodDefinition.ToString();
return methodDef.ToString();
}
}
}

View File

@ -20,74 +20,74 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using Mono.Cecil;
using dot10.DotNet;
using de4dot.blocks;
namespace AssemblyData.methodsrewriter {
class MModule {
public Module module;
public ModuleDefinition moduleDefinition;
public ModuleDefMD moduleDef;
TypeDefinitionDict<MType> typeReferenceToType = new TypeDefinitionDict<MType>();
Dictionary<int, MType> tokenToType = new Dictionary<int, MType>();
Dictionary<int, MMethod> tokenToGlobalMethod;
Dictionary<int, MField> tokenToGlobalField;
TypeDefinition moduleType;
TypeDef moduleType;
public MModule(Module module, ModuleDefinition moduleDefinition) {
public MModule(Module module, ModuleDefMD moduleDefinition) {
this.module = module;
this.moduleDefinition = moduleDefinition;
this.moduleDef = moduleDefinition;
initTokenToType();
}
void initTokenToType() {
moduleType = DotNetUtils.getModuleType(moduleDefinition);
foreach (var typeDefinition in moduleDefinition.GetTypes()) {
int token = typeDefinition.MetadataToken.ToInt32();
moduleType = moduleDef.Types[0];
foreach (var typeDef in moduleDef.GetTypes()) {
int token = (int)typeDef.MDToken.Raw;
Type type;
try {
type = module.ResolveType(token);
}
catch {
tokenToType[token] = null;
typeReferenceToType.add(typeDefinition, null);
typeReferenceToType.add(typeDef, null);
continue;
}
var mtype = new MType(type, typeDefinition);
var mtype = new MType(type, typeDef);
tokenToType[token] = mtype;
typeReferenceToType.add(typeDefinition, mtype);
typeReferenceToType.add(typeDef, mtype);
}
}
public MType getType(TypeReference typeReference) {
return typeReferenceToType.find(typeReference);
public MType getType(IType typeRef) {
return typeReferenceToType.find(typeRef);
}
public MMethod getMethod(MethodReference methodReference) {
var type = getType(methodReference.DeclaringType);
public MMethod getMethod(IMethod methodRef) {
var type = getType(methodRef.DeclaringType);
if (type != null)
return type.getMethod(methodReference);
if (!MemberReferenceHelper.compareTypes(moduleType, methodReference.DeclaringType))
return type.getMethod(methodRef);
if (!new SigComparer().Equals(moduleType, methodRef.DeclaringType))
return null;
initGlobalMethods();
foreach (var method in tokenToGlobalMethod.Values) {
if (MemberReferenceHelper.compareMethodReference(methodReference, method.methodDefinition))
if (new SigComparer().Equals(methodRef, method.methodDef))
return method;
}
return null;
}
public MField getField(FieldReference fieldReference) {
var type = getType(fieldReference.DeclaringType);
public MField getField(IField fieldRef) {
var type = getType(fieldRef.DeclaringType);
if (type != null)
return type.getField(fieldReference);
if (!MemberReferenceHelper.compareTypes(moduleType, fieldReference.DeclaringType))
return type.getField(fieldRef);
if (!new SigComparer().Equals(moduleType, fieldRef.DeclaringType))
return null;
initGlobalFields();
foreach (var field in tokenToGlobalField.Values) {
if (MemberReferenceHelper.compareFieldReference(fieldReference, field.fieldDefinition))
if (new SigComparer().Equals(fieldRef, field.fieldDef))
return field;
}
@ -120,7 +120,7 @@ namespace AssemblyData.methodsrewriter {
foreach (var m in moduleType.Methods) {
if (m.Name == ".cctor") //TODO: Use module.GetMethod(token) to get .cctor method
continue;
var token = m.MetadataToken.ToInt32();
var token = (int)m.MDToken.Raw;
tokenToGlobalMethod[token] = new MMethod(tmpTokenToGlobalMethod[token], m);
}
}
@ -135,13 +135,13 @@ namespace AssemblyData.methodsrewriter {
foreach (var f in module.GetFields(flags))
tmpTokenToGlobalField[f.MetadataToken] = f;
foreach (var f in moduleType.Fields) {
var token = f.MetadataToken.ToInt32();
var token = (int)f.MDToken.Raw;
tokenToGlobalField[token] = new MField(tmpTokenToGlobalField[token], f);
}
}
public override string ToString() {
return moduleDefinition.FullyQualifiedName;
return moduleDef.Location;
}
}
}

View File

@ -20,31 +20,31 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using Mono.Cecil;
using dot10.DotNet;
using de4dot.blocks;
namespace AssemblyData.methodsrewriter {
class MType {
public Type type;
public TypeDefinition typeDefinition;
public TypeDef typeDef;
Dictionary<int, MMethod> tokenToMethod;
MethodDefinitionDict<MMethod> methodReferenceToMethod;
Dictionary<int, MField> tokenToField;
FieldDefinitionDict<MField> fieldReferenceToField;
public MType(Type type, TypeDefinition typeDefinition) {
public MType(Type type, TypeDef typeDefinition) {
this.type = type;
this.typeDefinition = typeDefinition;
this.typeDef = typeDefinition;
}
public MMethod getMethod(MethodReference methodReference) {
public MMethod getMethod(IMethod methodRef) {
initMethods();
return methodReferenceToMethod.find(methodReference);
return methodReferenceToMethod.find(methodRef);
}
public MField getField(FieldReference fieldReference) {
public MField getField(IField fieldRef) {
initFields();
return fieldReferenceToField.find(fieldReference);
return fieldReferenceToField.find(fieldRef);
}
public MMethod getMethod(int token) {
@ -60,41 +60,41 @@ namespace AssemblyData.methodsrewriter {
void initMethods() {
if (tokenToMethod != null)
return;
tokenToMethod = new Dictionary<int, MMethod>(typeDefinition.Methods.Count);
tokenToMethod = new Dictionary<int, MMethod>(typeDef.Methods.Count);
methodReferenceToMethod = new MethodDefinitionDict<MMethod>();
var tmpTokenToMethod = new Dictionary<int, MethodBase>();
var flags = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
foreach (var m in ResolverUtils.getMethodBases(type, flags))
tmpTokenToMethod[m.MetadataToken] = m;
foreach (var m in typeDefinition.Methods) {
var token = m.MetadataToken.ToInt32();
foreach (var m in typeDef.Methods) {
var token = (int)m.MDToken.Raw;
var method = new MMethod(tmpTokenToMethod[token], m);
tokenToMethod[token] = method;
methodReferenceToMethod.add(method.methodDefinition, method);
methodReferenceToMethod.add(method.methodDef, method);
}
}
void initFields() {
if (tokenToField != null)
return;
tokenToField = new Dictionary<int, MField>(typeDefinition.Fields.Count);
tokenToField = new Dictionary<int, MField>(typeDef.Fields.Count);
fieldReferenceToField = new FieldDefinitionDict<MField>();
var tmpTokenToField = new Dictionary<int, FieldInfo>();
var flags = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
foreach (var f in type.GetFields(flags))
tmpTokenToField[f.MetadataToken] = f;
foreach (var f in typeDefinition.Fields) {
var token = f.MetadataToken.ToInt32();
foreach (var f in typeDef.Fields) {
var token = (int)f.MDToken.Raw;
var field = new MField(tmpTokenToField[token], f);
tokenToField[token] = field;
fieldReferenceToField.add(field.fieldDefinition, field);
fieldReferenceToField.add(field.fieldDef, field);
}
}
public override string ToString() {
return string.Format("{0:X8} - {1}", typeDefinition.MetadataToken.ToUInt32(), typeDefinition.FullName);
return string.Format("{0:X8} - {1}", typeDef.MDToken.Raw, typeDef.FullName);
}
}
}

View File

@ -22,12 +22,12 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Reflection.Emit;
using Mono.Cecil;
using Mono.Cecil.Cil;
using dot10.DotNet.Emit;
using dot10.DotNet;
using de4dot.blocks;
using OpCode = Mono.Cecil.Cil.OpCode;
using OpCodes = Mono.Cecil.Cil.OpCodes;
using OpCode = dot10.DotNet.Emit.OpCode;
using OpCodes = dot10.DotNet.Emit.OpCodes;
using ROpCode = System.Reflection.Emit.OpCode;
using ROpCodes = System.Reflection.Emit.OpCodes;
@ -191,13 +191,13 @@ namespace AssemblyData.methodsrewriter {
var moduleInfo = Resolver.loadAssembly(realMethod.Module);
var methodInfo = moduleInfo.getMethod(realMethod);
if (!methodInfo.hasInstructions())
throw new ApplicationException(string.Format("Method {0} ({1:X8}) has no body", methodInfo.methodDefinition, methodInfo.methodDefinition.MetadataToken.ToUInt32()));
throw new ApplicationException(string.Format("Method {0} ({1:X8}) has no body", methodInfo.methodDef, methodInfo.methodDef.MDToken.Raw));
var codeGenerator = new CodeGenerator(this, newMethodInfo.delegateMethodName);
codeGenerator.setMethodInfo(methodInfo);
newMethodInfo.delegateType = codeGenerator.DelegateType;
var blocks = new Blocks(methodInfo.methodDefinition);
var blocks = new Blocks(methodInfo.methodDef);
foreach (var block in blocks.MethodBlocks.getAllBlocks())
update(block, newMethodInfo);
@ -230,14 +230,15 @@ namespace AssemblyData.methodsrewriter {
for (int i = 0; i < instrs.Count; i++) {
var instr = instrs[i];
if (instr.OpCode == OpCodes.Newobj) {
var ctor = (MethodReference)instr.Operand;
if (MemberReferenceHelper.verifyType(ctor.DeclaringType, "mscorlib", "System.Diagnostics.StackTrace")) {
var ctor = (IMethod)instr.Operand;
var ctorTypeFullName = ctor.DeclaringType.FullName;
if (ctorTypeFullName == "System.Diagnostics.StackTrace") {
insertLoadThis(block, i + 1);
insertCallOurMethod(block, i + 2, "static_rtFixStackTrace");
i += 2;
continue;
}
else if (MemberReferenceHelper.verifyType(ctor.DeclaringType, "mscorlib", "System.Diagnostics.StackFrame")) {
else if (ctorTypeFullName == "System.Diagnostics.StackFrame") {
insertLoadThis(block, i + 1);
insertCallOurMethod(block, i + 2, "static_rtFixStackFrame");
i += 2;
@ -246,18 +247,19 @@ namespace AssemblyData.methodsrewriter {
}
if (instr.OpCode == OpCodes.Call || instr.OpCode == OpCodes.Callvirt) {
var calledMethod = (MethodReference)instr.Operand;
if (DotNetUtils.isSameAssembly(calledMethod.DeclaringType, "mscorlib")) {
if (calledMethod.ToString() == "System.Reflection.Assembly System.Reflection.Assembly::GetAssembly(System.Type)") {
var calledMethod = (IMethod)instr.Operand;
if (calledMethod.DeclaringType.DefinitionAssembly.IsCorLib()) {
var calledMethodFullName = calledMethod.FullName;
if (calledMethodFullName == "System.Reflection.Assembly System.Reflection.Assembly::GetAssembly(System.Type)") {
block.replace(i, 1, Instruction.Create(OpCodes.Nop));
insertLoadThis(block, i + 1);
insertCallOurMethod(block, i + 2, "static_rtGetAssembly_TypeArg");
i += 2;
continue;
}
else if (calledMethod.ToString() == "System.Reflection.Assembly System.Reflection.Assembly::GetCallingAssembly()" ||
calledMethod.ToString() == "System.Reflection.Assembly System.Reflection.Assembly::GetEntryAssembly()" ||
calledMethod.ToString() == "System.Reflection.Assembly System.Reflection.Assembly::GetExecutingAssembly()") {
else if (calledMethodFullName == "System.Reflection.Assembly System.Reflection.Assembly::GetCallingAssembly()" ||
calledMethodFullName == "System.Reflection.Assembly System.Reflection.Assembly::GetEntryAssembly()" ||
calledMethodFullName == "System.Reflection.Assembly System.Reflection.Assembly::GetExecutingAssembly()") {
block.replace(i, 1, Instruction.Create(OpCodes.Nop));
insertLoadThis(block, i + 1);
block.insert(i + 2, Instruction.Create(OpCodes.Ldc_I4, currentMethodInfo.delegateIndex));
@ -267,7 +269,7 @@ namespace AssemblyData.methodsrewriter {
}
}
var method = Resolver.getMethod((MethodReference)instr.Operand);
var method = Resolver.getMethod((IMethod)instr.Operand);
if (method != null) {
createMethod(method.methodBase);
var newMethodInfo = realMethodToNewMethod[method.methodBase];
@ -276,17 +278,17 @@ namespace AssemblyData.methodsrewriter {
int n = i + 1;
// Pop all pushed args to a temp array
var mparams = getParameters(method.methodDefinition);
var mparams = getParameters(method.methodDef);
if (mparams.Count > 0) {
block.insert(n++, Instruction.Create(OpCodes.Ldc_I4, mparams.Count));
var objectType = method.methodDefinition.Module.TypeSystem.Object;
var objectType = method.methodDef.DeclaringType.Module.CorLibTypes.Object;
block.insert(n++, Instruction.Create(OpCodes.Newarr, objectType));
block.insert(n++, create(OpCodes.Stloc, new Operand(Operand.Type.TempObjArray)));
for (int j = mparams.Count - 1; j >= 0; j--) {
var argType = mparams[j];
if (argType.IsValueType)
block.insert(n++, Instruction.Create(OpCodes.Box, argType));
if (argType.RemovePinnedAndModifiers().IsValueType)
block.insert(n++, Instruction.Create(OpCodes.Box, ((TypeDefOrRefSig)argType).TypeDefOrRef));
block.insert(n++, create(OpCodes.Stloc, new Operand(Operand.Type.TempObj)));
block.insert(n++, create(OpCodes.Ldloc, new Operand(Operand.Type.TempObjArray)));
block.insert(n++, Instruction.Create(OpCodes.Ldc_I4, j));
@ -308,14 +310,14 @@ namespace AssemblyData.methodsrewriter {
block.insert(n++, Instruction.Create(OpCodes.Ldc_I4, j));
block.insert(n++, Instruction.Create(OpCodes.Ldelem_Ref));
var argType = mparams[j];
if (argType.IsValueType)
block.insert(n++, Instruction.Create(OpCodes.Unbox_Any, argType));
if (argType.RemovePinnedAndModifiers().IsValueType)
block.insert(n++, Instruction.Create(OpCodes.Unbox_Any, ((TypeDefOrRefSig)argType).TypeDefOrRef));
else {
// Don't cast it to its correct type. This will sometimes cause
// an exception in some EF obfuscated assembly since we'll be
// trying to cast a System.Reflection.AssemblyName type to some
// other type.
// block.insert(n++, Instruction.Create(OpCodes.Castclass, argType));
// block.insert(n++, Instruction.Create(OpCodes.Castclass, argType.ToTypeDefOrRef()));
}
}
}
@ -329,13 +331,10 @@ namespace AssemblyData.methodsrewriter {
}
}
static List<TypeReference> getParameters(MethodDefinition method) {
int count = method.Parameters.Count + (method.HasImplicitThis ? 1 : 0);
var list = new List<TypeReference>(count);
if (method.HasImplicitThis)
list.Add(method.DeclaringType);
foreach (var argType in method.Parameters)
list.Add(argType.ParameterType);
static IList<TypeSig> getParameters(MethodDef method) {
var list = new List<TypeSig>(method.Parameters.Count);
for (int i = 0; i < method.Parameters.Count; i++)
list.Add(method.Parameters[i].Type);
return list;
}

View File

@ -20,7 +20,7 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using Mono.Cecil;
using dot10.DotNet;
using de4dot.blocks;
namespace AssemblyData.methodsrewriter {
@ -33,47 +33,47 @@ namespace AssemblyData.methodsrewriter {
if (modules.TryGetValue(module, out info))
return info;
info = new MModule(module, ModuleDefinition.ReadModule(module.FullyQualifiedName));
info = new MModule(module, ModuleDefMD.Load(module.FullyQualifiedName));
modules[module] = info;
return info;
}
static MModule getModule(ModuleDefinition moduleDefinition) {
static MModule getModule(ModuleDef moduleDef) {
foreach (var mm in modules.Values) {
if (mm.moduleDefinition == moduleDefinition)
if (mm.moduleDef == moduleDef)
return mm;
}
return null;
}
static MModule getModule(AssemblyNameReference assemblyRef) {
static MModule getModule(AssemblyRef asmRef) {
foreach (var mm in modules.Values) {
var asm = mm.moduleDefinition.Assembly;
if (asm != null && asm.Name.FullName == assemblyRef.FullName)
var asm = mm.moduleDef.Assembly;
if (asm != null && asm.FullName == asmRef.FullName)
return mm;
}
return null;
}
public static MModule getModule(IMetadataScope scope) {
if (scope is ModuleDefinition)
return getModule((ModuleDefinition)scope);
else if (scope is AssemblyNameReference)
return getModule((AssemblyNameReference)scope);
public static MModule getModule(IScope scope) {
if (scope.ScopeType == ScopeType.ModuleDef)
return getModule((ModuleDef)scope);
else if (scope.ScopeType == ScopeType.AssemblyRef)
return getModule((AssemblyRef)scope);
return null;
}
public static MType getType(TypeReference typeReference) {
if (typeReference == null)
public static MType getType(IType typeRef) {
if (typeRef == null)
return null;
var module = getModule(typeReference.Scope);
var module = getModule(typeRef.Scope);
if (module != null)
return module.getType(typeReference);
return module.getType(typeRef);
return null;
}
public static MMethod getMethod(MethodReference methodReference) {
public static MMethod getMethod(IMethod methodReference) {
if (methodReference == null)
return null;
var module = getModule(methodReference.DeclaringType.Scope);
@ -82,7 +82,7 @@ namespace AssemblyData.methodsrewriter {
return null;
}
public static MField getField(FieldReference fieldReference) {
public static MField getField(IField fieldReference) {
if (fieldReference == null)
return null;
var module = getModule(fieldReference.DeclaringType.Scope);
@ -91,114 +91,129 @@ namespace AssemblyData.methodsrewriter {
return null;
}
public static object getRtObject(MemberReference memberReference) {
if (memberReference == null)
public static object getRtObject(ITokenOperand memberRef) {
if (memberRef == null)
return null;
else if (memberReference is TypeReference)
return getRtType((TypeReference)memberReference);
else if (memberReference is FieldReference)
return getRtField((FieldReference)memberReference);
else if (memberReference is MethodReference)
return getRtMethod((MethodReference)memberReference);
var tdr = memberRef as ITypeDefOrRef;
if (tdr != null)
return getRtType(tdr);
var field = memberRef as IField;
if (field != null && field.FieldSig != null)
return getRtField(field);
var method = memberRef as IMethod;
if (method != null && method.MethodSig != null)
return getRtMethod(method);
throw new ApplicationException(string.Format("Unknown MemberReference: {0}", memberReference));
throw new ApplicationException(string.Format("Unknown MemberReference: {0}", memberRef));
}
public static Type getRtType(TypeReference typeReference) {
var mtype = getType(typeReference);
public static Type getRtType(IType typeRef) {
var mtype = getType(typeRef);
if (mtype != null)
return mtype.type;
return Resolver.resolve(typeReference);
return Resolver.resolve(typeRef);
}
public static FieldInfo getRtField(FieldReference fieldReference) {
var mfield = getField(fieldReference);
public static FieldInfo getRtField(IField fieldRef) {
var mfield = getField(fieldRef);
if (mfield != null)
return mfield.fieldInfo;
return Resolver.resolve(fieldReference);
return Resolver.resolve(fieldRef);
}
public static MethodBase getRtMethod(MethodReference methodReference) {
var mmethod = getMethod(methodReference);
public static MethodBase getRtMethod(IMethod methodRef) {
var mmethod = getMethod(methodRef);
if (mmethod != null)
return mmethod.methodBase;
return Resolver.resolve(methodReference);
return Resolver.resolve(methodRef);
}
static AssemblyResolver getAssemblyResolver(TypeReference type) {
var asmName = DotNetUtils.getFullAssemblyName(type);
static AssemblyResolver getAssemblyResolver(ITypeDefOrRef type) {
var asmName = type.DefinitionAssembly.FullName;
AssemblyResolver resolver;
if (!assemblyResolvers.TryGetValue(asmName, out resolver))
assemblyResolvers[asmName] = resolver = new AssemblyResolver(asmName);
return resolver;
}
static Type resolve(TypeReference typeReference) {
if (typeReference == null)
static Type resolve(IType typeRef) {
if (typeRef == null)
return null;
var elemType = typeReference.GetElementType();
var resolver = getAssemblyResolver(elemType);
var resolvedType = resolver.resolve(elemType);
var scopeType = typeRef.ScopeType;
var resolver = getAssemblyResolver(scopeType);
var resolvedType = resolver.resolve(scopeType);
if (resolvedType != null)
return fixType(typeReference, resolvedType);
throw new ApplicationException(string.Format("Could not resolve type {0} ({1:X8}) in assembly {2}", typeReference, typeReference.MetadataToken.ToUInt32(), resolver));
return fixType(typeRef, resolvedType);
throw new ApplicationException(string.Format("Could not resolve type {0} ({1:X8}) in assembly {2}", typeRef, typeRef.MDToken.Raw, resolver));
}
static FieldInfo resolve(FieldReference fieldReference) {
if (fieldReference == null)
static FieldInfo resolve(IField fieldRef) {
if (fieldRef == null)
return null;
var resolver = getAssemblyResolver(fieldReference.DeclaringType);
var fieldInfo = resolver.resolve(fieldReference);
var resolver = getAssemblyResolver(fieldRef.DeclaringType);
var fieldInfo = resolver.resolve(fieldRef);
if (fieldInfo != null)
return fieldInfo;
throw new ApplicationException(string.Format("Could not resolve field {0} ({1:X8}) in assembly {2}", fieldReference, fieldReference.MetadataToken.ToUInt32(), resolver));
throw new ApplicationException(string.Format("Could not resolve field {0} ({1:X8}) in assembly {2}", fieldRef, fieldRef.MDToken.Raw, resolver));
}
static MethodBase resolve(MethodReference methodReference) {
if (methodReference == null)
static MethodBase resolve(IMethod methodRef) {
if (methodRef == null)
return null;
var resolver = getAssemblyResolver(methodReference.DeclaringType);
var methodBase = resolver.resolve(methodReference);
var resolver = getAssemblyResolver(methodRef.DeclaringType);
var methodBase = resolver.resolve(methodRef);
if (methodBase != null)
return methodBase;
throw new ApplicationException(string.Format("Could not resolve method {0} ({1:X8}) in assembly {2}", methodReference, methodReference.MetadataToken.ToUInt32(), resolver));
throw new ApplicationException(string.Format("Could not resolve method {0} ({1:X8}) in assembly {2}", methodRef, methodRef.MDToken.Raw, resolver));
}
static Type fixType(TypeReference typeReference, Type type) {
while (typeReference is TypeSpecification) {
var ts = (TypeSpecification)typeReference;
static Type fixType(IType typeRef, Type type) {
var sig = typeRef as TypeSig;
if (sig == null) {
var ts = typeRef as TypeSpec;
if (ts != null)
sig = ts.TypeSig;
}
while (sig != null) {
switch (sig.ElementType) {
case ElementType.SZArray:
type = type.MakeArrayType();
break;
if (typeReference is ArrayType) {
var arrayType = (ArrayType)typeReference;
if (arrayType.IsVector)
type = type.MakeArrayType();
else
type = type.MakeArrayType(arrayType.Rank);
}
else if (typeReference is ByReferenceType) {
case ElementType.Array:
type = type.MakeArrayType((int)((ArraySig)sig).Rank);
break;
case ElementType.ByRef:
type = type.MakeByRefType();
}
else if (typeReference is PointerType) {
break;
case ElementType.Ptr:
type = type.MakePointerType();
}
else if (typeReference is GenericInstanceType) {
var git = (GenericInstanceType)typeReference;
break;
case ElementType.GenericInst:
var git = (GenericInstSig)sig;
var args = new Type[git.GenericArguments.Count];
bool isGenericTypeDef = true;
for (int i = 0; i < args.Length; i++) {
var typeRef = git.GenericArguments[i];
if (!(typeRef.GetElementType() is GenericParameter))
var arg = git.GenericArguments[i];
if (!(arg is GenericSig))
isGenericTypeDef = false;
args[i] = Resolver.resolve(typeRef);
args[i] = Resolver.resolve(arg);
}
if (!isGenericTypeDef)
type = type.MakeGenericType(args);
break;
default:
break;
}
typeReference = ts.ElementType;
sig = sig.Next;
}
return type;
}

View File

@ -20,146 +20,17 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using Mono.Cecil;
using dot10.DotNet;
using de4dot.blocks;
namespace AssemblyData.methodsrewriter {
static class ResolverUtils {
public static bool compareTypes(Type a, TypeReference b) {
if (a == null && b == null)
return true;
if (a == null || b == null)
return false;
var type = MemberReferenceHelper.getMemberReferenceType(b);
switch (type) {
case CecilType.ArrayType:
return compareArrayTypes(a, (ArrayType)b);
case CecilType.ByReferenceType:
return compareByReferenceTypes(a, (ByReferenceType)b);
case CecilType.FunctionPointerType:
return compareFunctionPointerTypes(a, (FunctionPointerType)b);
case CecilType.GenericInstanceType:
return compareGenericInstanceTypes(a, (GenericInstanceType)b);
case CecilType.GenericParameter:
return compareGenericParameters(a, (GenericParameter)b);
case CecilType.OptionalModifierType:
return compareOptionalModifierTypes(a, (OptionalModifierType)b);
case CecilType.PinnedType:
return comparePinnedTypes(a, (PinnedType)b);
case CecilType.PointerType:
return comparePointerTypes(a, (PointerType)b);
case CecilType.RequiredModifierType:
return compareRequiredModifierTypes(a, (RequiredModifierType)b);
case CecilType.SentinelType:
return compareSentinelTypes(a, (SentinelType)b);
case CecilType.TypeDefinition:
return compareTypeDefinitions(a, (TypeDefinition)b);
case CecilType.TypeReference:
return compareTypeReferences(a, (TypeReference)b);
default:
throw new ApplicationException(string.Format("Unknown cecil type {0}", type));
}
public static bool compareTypes(Type a, IType b) {
return new SigComparer().Equals(a, b);
}
static bool compareArrayTypes(Type a, ArrayType b) {
if (!a.IsArray)
return false;
if (a.GetArrayRank() != b.Rank)
return false;
return compareTypes(a.GetElementType(), b.ElementType);
}
static bool compareByReferenceTypes(Type a, ByReferenceType b) {
if (!a.IsByRef)
return false;
return compareTypes(a.GetElementType(), b.ElementType);
}
static bool compareFunctionPointerTypes(Type a, FunctionPointerType b) {
return compareTypes(a, b.ElementType);
}
static bool compareGenericInstanceTypes(Type a, GenericInstanceType b) {
if (!a.IsGenericType)
return false;
var aGpargs = a.GetGenericArguments();
var bGpargs = b.GenericArguments;
if (aGpargs.Length != bGpargs.Count)
return false;
for (int i = 0; i < aGpargs.Length; i++) {
var aArg = aGpargs[i];
var bArg = bGpargs[i];
if (aArg.IsGenericParameter)
continue;
if (!compareTypes(aArg, bArg))
return false;
}
return compareTypes(a, b.ElementType);
}
static bool compareGenericParameters(Type a, GenericParameter b) {
if (!a.IsGenericParameter)
return false;
if (a.GenericParameterPosition != b.Position)
return false;
return true;
}
static bool compareOptionalModifierTypes(Type a, OptionalModifierType b) {
return compareTypes(a, b.ElementType);
}
static bool comparePinnedTypes(Type a, PinnedType b) {
return compareTypes(a, b.ElementType);
}
static bool comparePointerTypes(Type a, PointerType b) {
if (!a.IsPointer)
return false;
return compareTypes(a.GetElementType(), b.ElementType);
}
static bool compareRequiredModifierTypes(Type a, RequiredModifierType b) {
return compareTypes(a, b.ElementType);
}
static bool compareSentinelTypes(Type a, SentinelType b) {
return compareTypes(a, b.ElementType);
}
static bool compareTypeDefinitions(Type a, TypeDefinition b) {
return compareTypeReferences(a, b);
}
static bool compareTypeReferences(Type a, TypeReference b) {
if (a.IsGenericParameter || a.IsPointer || a.IsByRef || a.IsArray)
return false;
if (a.Name != b.Name)
return false;
if ((a.Namespace ?? "") != b.Namespace)
return false;
var asmRef = DotNetUtils.getAssemblyNameReference(b);
var asmName = a.Assembly.GetName();
if (asmRef == null || asmRef.Name != asmName.Name)
return false;
return compareTypes(a.DeclaringType, b.DeclaringType);
}
public static bool compareFields(FieldInfo a, FieldReference b) {
if (a == null && b == null)
return true;
if (a == null || b == null)
return false;
return a.Name == b.Name &&
compareTypes(a.FieldType, b.FieldType);
public static bool compareFields(FieldInfo a, IField b) {
return new SigComparer().Equals(a, b);
}
public static bool hasThis(MethodBase method) {
@ -170,52 +41,8 @@ namespace AssemblyData.methodsrewriter {
return (method.CallingConvention & CallingConventions.ExplicitThis) != 0;
}
public static bool compareMethods(MethodBase a, MethodReference b) {
if (a == null && b == null)
return true;
if (a == null || b == null)
return false;
if (a.Name != b.Name)
return false;
if (hasThis(a) != b.HasThis || explicitThis(a) != b.ExplicitThis)
return false;
CallingConventions aCallingConvention = a.CallingConvention & (CallingConventions)7;
switch (b.CallingConvention) {
case MethodCallingConvention.Default:
if (aCallingConvention != CallingConventions.Standard && aCallingConvention != CallingConventions.Any)
return false;
break;
case MethodCallingConvention.VarArg:
if (aCallingConvention != CallingConventions.VarArgs && aCallingConvention != CallingConventions.Any)
return false;
break;
default:
return false;
}
if (!compareTypes(getReturnType(a), b.MethodReturnType.ReturnType))
return false;
var aParams = a.GetParameters();
var bParams = b.Parameters;
if (aParams.Length != bParams.Count)
return false;
for (int i = 0; i < aParams.Length; i++) {
if (!compareTypes(aParams[i].ParameterType, bParams[i].ParameterType))
return false;
}
var aGparams = getGenericArguments(a);
var bGparams = b.GenericParameters;
if (aGparams.Length != bGparams.Count)
return false;
return true;
public static bool compareMethods(MethodBase a, IMethod b) {
return new SigComparer().Equals(a, b);
}
public static Type getReturnType(MethodBase methodBase) {
@ -300,15 +127,18 @@ namespace AssemblyData.methodsrewriter {
return list;
}
public static Type makeInstanceType(Type type, TypeReference typeReference) {
var git = typeReference as GenericInstanceType;
public static Type makeInstanceType(Type type, ITypeDefOrRef typeRef) {
var ts = typeRef as TypeSpec;
if (ts == null)
return type;
var git = ts.TypeSig as GenericInstSig;
if (git == null)
return type;
var types = new Type[git.GenericArguments.Count];
bool isTypeDef = true;
for (int i = 0; i < git.GenericArguments.Count; i++) {
var arg = git.GenericArguments[i];
if (!(arg is GenericParameter))
if (!(arg is GenericSig))
isTypeDef = false;
types[i] = Resolver.getRtType(arg);
}

View File

@ -20,7 +20,7 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using Mono.Cecil;
using dot10.DotNet;
using de4dot.blocks;
namespace AssemblyData.methodsrewriter {
@ -29,23 +29,21 @@ namespace AssemblyData.methodsrewriter {
Dictionary<string, List<MethodBase>> methods;
Dictionary<string, List<FieldInfo>> fields;
public TypeInstanceResolver(Type type, TypeReference typeReference) {
this.type = ResolverUtils.makeInstanceType(type, typeReference);
public TypeInstanceResolver(Type type, ITypeDefOrRef typeRef) {
this.type = ResolverUtils.makeInstanceType(type, typeRef);
}
public FieldInfo resolve(FieldReference fieldReference) {
public FieldInfo resolve(IField fieldRef) {
initFields();
List<FieldInfo> list;
if (!fields.TryGetValue(fieldReference.Name, out list))
if (!fields.TryGetValue(fieldRef.Name.String, out list))
return null;
var git = fieldReference.DeclaringType as GenericInstanceType;
if (git != null)
fieldReference = FieldReferenceInstance.make(fieldReference, git);
fieldRef = GenericArgsSubstitutor.create(fieldRef, fieldRef.DeclaringType.ToGenericInstSig());
foreach (var field in list) {
if (ResolverUtils.compareFields(field, fieldReference))
if (ResolverUtils.compareFields(field, fieldRef))
return field;
}
@ -66,19 +64,17 @@ namespace AssemblyData.methodsrewriter {
}
}
public MethodBase resolve(MethodReference methodReference) {
public MethodBase resolve(IMethod methodRef) {
initMethods();
List<MethodBase> list;
if (!methods.TryGetValue(methodReference.Name, out list))
if (!methods.TryGetValue(methodRef.Name.String, out list))
return null;
var git = methodReference.DeclaringType as GenericInstanceType;
var gim = methodReference as GenericInstanceMethod;
methodReference = MethodReferenceInstance.make(methodReference, git, gim);
methodRef = GenericArgsSubstitutor.create(methodRef, methodRef.DeclaringType.ToGenericInstSig());
foreach (var method in list) {
if (ResolverUtils.compareMethods(method, methodReference))
if (ResolverUtils.compareMethods(method, methodRef))
return method;
}

View File

@ -20,32 +20,31 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using Mono.Cecil;
using dot10.DotNet;
using de4dot.blocks;
namespace AssemblyData.methodsrewriter {
class TypeResolver {
public Type type;
Dictionary<TypeReferenceKey, TypeInstanceResolver> typeRefToInstance = new Dictionary<TypeReferenceKey, TypeInstanceResolver>();
Dictionary<ITypeDefOrRef, TypeInstanceResolver> typeRefToInstance = new Dictionary<ITypeDefOrRef, TypeInstanceResolver>(TypeEqualityComparer.Instance);
public TypeResolver(Type type) {
this.type = type;
}
TypeInstanceResolver getTypeInstance(TypeReference typeReference) {
var key = new TypeReferenceKey(typeReference);
TypeInstanceResolver getTypeInstance(ITypeDefOrRef typeRef) {
TypeInstanceResolver instance;
if (!typeRefToInstance.TryGetValue(key, out instance))
typeRefToInstance[key] = instance = new TypeInstanceResolver(type, typeReference);
if (!typeRefToInstance.TryGetValue(typeRef, out instance))
typeRefToInstance[typeRef] = instance = new TypeInstanceResolver(type, typeRef);
return instance;
}
public FieldInfo resolve(FieldReference fieldReference) {
return getTypeInstance(fieldReference.DeclaringType).resolve(fieldReference);
public FieldInfo resolve(IField fieldRef) {
return getTypeInstance(fieldRef.DeclaringType).resolve(fieldRef);
}
public MethodBase resolve(MethodReference methodReference) {
return getTypeInstance(methodReference.DeclaringType).resolve(methodReference);
public MethodBase resolve(IMethod methodRef) {
return getTypeInstance(methodRef.DeclaringType).resolve(methodRef);
}
}
}

View File

@ -1,34 +0,0 @@
<LICENSE>
//
// Author:
// Jb Evain (jbevain@gmail.com)
//
// Copyright (c) 2008 - 2011 Jb Evain
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
</LICENSE>
Official site: https://github.com/jbevain/cecil
My fork: https://github.com/0xd4d/cecil
This version of Mono.Cecil is not the official version. I have added code
to read decrypted methods and other fixes, eg. making it more robust when
processing obfuscated assemblies with invalid metadata.

167
README.md
View File

@ -1,167 +0,0 @@
de4dot - Deobfuscator for .NET
==============================
Features
--------
* Supports some popular obfuscators
* Deobfuscates control flow
* Cross-assembly symbol renaming
* Decrypts strings
* Decrypts resources
* Dumps embedded assemblies
* Dumps encrypted methods
* Deobfuscated files are runnable
* Removes other obfuscator junk
* Supports pure managed .NET files only
* Fixes peverify errors created by the obfuscator
* 100% Open Source
Many features work even if it's an unsupported obfuscator but the result may
or may not be runnable.
Who would need a deobfuscator?
------------------------------
* Security experts who need to deobfuscate obfuscated .NET malware.
* You lost your source code but have a copy of your obfuscated .NET
assemblies. You can then use ILSpy to decompile them.
* You must verify that an obfuscated compiled .NET assembly contains the
claimed source code, and no backdoors.
* Some obfuscators are not Mono-compatible. If you deobfuscate it, it may run
on Mono.
* Some obfuscated programs crash on 64-bit Windows. Deobfuscating it and
removing the obfuscator code solves that problem.
* You can only run verifiable .NET code, but the obfuscated program is
non-verifiable due to the obfuscated code.
* You don't want string decryption and tons of useless CIL instructions to
slow down your favorite program.
Features explained
------------------
### Supports some popular obfuscators
I won't list the supported obfuscators since I'd forget to update it when I
add support for another one. Run `de4dot -h` to get a list of the supported
obfuscators. It's usually very easy to add support for another obfuscator.
Other obfuscators are partially supported. Eg. control flow deobfuscation,
symbol renaming, and dynamic string decryption could possibly work.
### Deobfuscates control flow
Most obfuscators can rearrange the control flow so the code is harder to
understand. A simple method that is 10 lines long and easy to read, could
become 30-40 lines and be very hard to read. Control flow deobfuscation will
remove all of the obfuscated code, leaving just the original code. Dead code
is also removed.
### Cross-assembly symbol renaming
Many obfuscators can rename public classes if they're part of a private
assembly. This deobfuscator will properly rename not only the obfuscated class
and all references within that assembly, but also all references in other
assemblies. If you don't need symbol renaming, you should disable it.
### Decrypts strings
Most, if not all, obfuscators support encrypting the strings. They usually
replace the original string with an encrypted string, or an integer. The
encrypted string or integer is then handed over to the string decrypter which
returns the original string. This deobfuscator supports static decryption and
dynamic decryption. Dynamic decryption will load the assembly and then call
the string decrypter and save the decrypted string. You can tell it which
method is the string decrypter and it will do the rest. The default is to use
static string decryption. Dynamic string decryption can be useful if you're
deobfuscating an assembly obfuscated with an unsupported obfuscator.
### Decrypts resources
Resources are usually encrypted by the obfuscator. The deobfuscator supports
static decryption only.
### Dumps embedded assemblies
Some obfuscators can embed assemblies. They usually encrypt and compress the
assembly and put it in the resources section. These assemblies will be
decypted and decompressed and then saved to disk.
### Dumps encrypted methods
Some obfuscators encrypt all methods and only decrypt each method when
requested by the .NET runtime. The methods are statically decrypted and then
deobfuscated.
### Deobfuscated files are runnable
If it's a supported obfuscator, the output is runnable. This is an important
feature. If you can't run the resulting file, it's almost useless. Note that
you may need to resign all modified assemblies that were signed. Some programs
have internal checks for modifications that aren't part of the obfuscator.
These kinds of protections usually cause a crash on purpose. Those aren't
removed since they're part of the original assembly.
### Removes other obfuscator junk
Many obfuscation products add other junk to the file. Eg., they could add code
to log every single exception, or detect deobfuscation, etc. Since that's not
part of the original file, it's also removed. Some obfuscators add so many
junk classes that it's difficult to find all of them, though. You have to
remove those manually for now.
### Supports pure managed .NET files only
This is a limitation of the Mono.Cecil library. Most .NET assemblies, however,
are pure managed .NET assemblies.
### Fixes peverify errors created by the obfuscator
Usually when an obfuscator adds control flow obfuscation, the resulting code
doesn't pass all peverify tests, resulting in an unverifiable assembly. By
removing that obfuscation, and making sure to re-arrange the code blocks in a
certain order, those obfuscator created errors will be gone. If the assembly
was verifiable before obfuscation, it must be verifiable after deobfuscation.
### 100% Open Source
Can't get any better than this!
Examples
--------
Show help:
de4dot -h
Deobfuscate a few files:
de4dot file1.exe file2.dll file3.exe
Deobfuscate all files found:
de4dot -r c:\path1 -ro c:\out
Detect obfuscator recursively:
de4dot -d -r c:\path1
Deobfuscate and get a detailed log of what was changed:
de4dot -v file1.exe file2.dll file3.exe > log.txt
Deobfuscate and override string decrypter detection, finding and using all
static methods with string and int args that return a string. A dynamic method
is created and used to call the string decrypter method(s). Make sure you
don't include any non-string decrypter methods or you will get an exception:
de4dot --default-strtyp delegate --default-strtok "(System.String, System.Int32)" file1.exe file2.dll
Same as above but use a metadata token:
de4dot --default-strtyp delegate file1.exe --strtok 06000123 file2.dll --strtok 06004567 --strtok 06009ABC
Don't remove obfuscator types, methods, etc:
de4dot --keep-types file1.exe

View File

@ -19,7 +19,7 @@
using System;
using System.Collections.Generic;
using Mono.Cecil.Cil;
using dot10.DotNet.Emit;
namespace de4dot.blocks {
public class Block : BaseBlock {
@ -269,7 +269,7 @@ namespace de4dot.blocks {
for (int i = 0; i < instrs.Count; i++) {
var instr = instrs[i];
if (instr.OpCode != OpCodes.Nop)
dest.Add(clone ? new Instr(DotNetUtils.clone(instr.Instruction)) : instr);
dest.Add(clone ? new Instr(instr.Instruction.Clone()) : instr);
}
}

View File

@ -19,35 +19,35 @@
using System;
using System.Collections.Generic;
using Mono.Cecil;
using Mono.Cecil.Cil;
using dot10.DotNet;
using dot10.DotNet.Emit;
namespace de4dot.blocks {
public class Blocks {
MethodDefinition method;
IList<VariableDefinition> locals;
MethodDef method;
IList<Local> locals;
MethodBlocks methodBlocks;
public MethodBlocks MethodBlocks {
get { return methodBlocks; }
}
public IList<VariableDefinition> Locals {
public IList<Local> Locals {
get { return locals; }
}
public MethodDefinition Method {
public MethodDef Method {
get { return method; }
}
public Blocks(MethodDefinition method) {
public Blocks(MethodDef method) {
this.method = method;
updateBlocks();
}
public void updateBlocks() {
var body = method.Body;
locals = body.Variables;
locals = body.LocalList;
methodBlocks = new InstructionListParser(body.Instructions, body.ExceptionHandlers).parse();
}
@ -79,11 +79,11 @@ namespace de4dot.blocks {
if (locals.Count == 0)
return 0;
var usedLocals = new Dictionary<VariableDefinition, List<LocalVariableInfo>>();
var usedLocals = new Dictionary<Local, List<LocalVariableInfo>>();
foreach (var block in methodBlocks.getAllBlocks()) {
for (int i = 0; i < block.Instructions.Count; i++) {
var instr = block.Instructions[i];
VariableDefinition local;
Local local;
switch (instr.OpCode.Code) {
case Code.Ldloc:
case Code.Ldloc_S:
@ -102,7 +102,7 @@ namespace de4dot.blocks {
case Code.Ldloca_S:
case Code.Ldloca:
local = (VariableDefinition)instr.Operand;
local = (Local)instr.Operand;
break;
default:
@ -122,14 +122,39 @@ namespace de4dot.blocks {
}
int newIndex = -1;
var newLocals = new List<VariableDefinition>(usedLocals.Count);
var newLocals = new List<Local>(usedLocals.Count);
var newLocalsDict = new Dictionary<Local, bool>(usedLocals.Count);
foreach (var local in usedLocals.Keys) {
newIndex++;
newLocals.Add(local);
newLocalsDict[local] = true;
foreach (var info in usedLocals[local])
info.block.Instructions[info.index] = new Instr(optimizeLocalInstr(info.block.Instructions[info.index], local, (uint)newIndex));
}
// We can't remove all locals. Locals that reference another assembly will
// cause the CLR to load that assembly before the method is executed if it
// hasn't been loaded yet. This is a side effect the program may depend on.
// At least one program has this dependency and will crash if we remove the
// unused local. This took a while to figure out...
var keptAssemblies = new Dictionary<string, bool>(StringComparer.Ordinal);
foreach (var local in locals) {
if (newLocalsDict.ContainsKey(local))
continue;
var defAsm = local.Type.DefinitionAssembly;
if (defAsm == null)
continue; // eg. fnptr
if (defAsm == method.DeclaringType.Module.Assembly)
continue; // this assembly is always loaded
if (defAsm.IsCorLib())
continue; // mscorlib is always loaded
var asmName = defAsm.FullName;
if (keptAssemblies.ContainsKey(asmName))
continue;
keptAssemblies[asmName] = true;
newLocals.Add(local);
}
int numRemoved = locals.Count - newLocals.Count;
locals.Clear();
foreach (var local in newLocals)
@ -137,7 +162,7 @@ namespace de4dot.blocks {
return numRemoved;
}
static Instruction optimizeLocalInstr(Instr instr, VariableDefinition local, uint newIndex) {
static Instruction optimizeLocalInstr(Instr instr, Local local, uint newIndex) {
switch (instr.OpCode.Code) {
case Code.Ldloc:
case Code.Ldloc_S:
@ -194,7 +219,7 @@ namespace de4dot.blocks {
}
catch (NullReferenceException) {
//TODO: Send this message to the log
Console.WriteLine("Null ref exception! Invalid metadata token in code? Method: {0:X8}: {1}", method.MetadataToken.ToUInt32(), method.FullName);
Console.WriteLine("Null ref exception! Invalid metadata token in code? Method: {0:X8}: {1}", method.MDToken.Raw, method.FullName);
return;
}
}

View File

@ -19,8 +19,8 @@
using System;
using System.Collections.Generic;
using Mono.Cecil;
using Mono.Cecil.Cil;
using dot10.DotNet;
using dot10.DotNet.Emit;
namespace de4dot.blocks {
class CodeGenerator {
@ -45,10 +45,10 @@ namespace de4dot.blocks {
public int filterStart;
public int handlerStart;
public int handlerEnd;
public TypeReference catchType;
public ITypeDefOrRef catchType;
public ExceptionHandlerType handlerType;
public ExceptionInfo(int tryStart, int tryEnd, int filterStart,
int handlerStart, int handlerEnd, TypeReference catchType,
int handlerStart, int handlerEnd, ITypeDefOrRef catchType,
ExceptionHandlerType handlerType) {
if (tryStart > tryEnd || filterStart > handlerStart ||
tryStart < 0 || tryEnd < 0 || filterStart < 0 || handlerStart < 0 || handlerEnd < 0)
@ -99,10 +99,10 @@ namespace de4dot.blocks {
}
void recalculateInstructionOffsets(IList<Instruction> allInstructions) {
int offset = 0;
uint offset = 0;
foreach (var instr in allInstructions) {
instr.Offset = offset;
offset += instr.GetSize();
offset += (uint)instr.GetSize();
}
}
@ -137,7 +137,7 @@ namespace de4dot.blocks {
if (getShortBranch(instruction, out opcode)) {
const int instrSize = 5; // It's a long branch instruction
var target = (Instruction)instruction.Operand;
int distance = target == null ? int.MaxValue : target.Offset - (instruction.Offset + instrSize);
int distance = target == null ? int.MaxValue : (int)(target.Offset - (instruction.Offset + instrSize));
if (-0x80 <= distance && distance <= 0x7F) {
instruction.OpCode = opcode;
changed = true;

File diff suppressed because it is too large Load Diff

42
blocks/DumpedMethod.cs Normal file
View File

@ -0,0 +1,42 @@
/*
Copyright (C) 2011-2012 de4dot@gmail.com
This file is part of de4dot.
de4dot is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
de4dot is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
namespace de4dot.blocks {
[Serializable]
public class DumpedMethod {
public ushort mhFlags; // method header Flags
public ushort mhMaxStack; // method header MaxStack
public uint mhCodeSize; // method header CodeSize
public uint mhLocalVarSigTok; // method header LocalVarSigTok
public uint mdRVA; // methodDef RVA
public ushort mdImplFlags; // methodDef ImplFlags
public ushort mdFlags; // methodDef Flags
public uint mdName; // methodDef Name (index into #String)
public uint mdSignature; // methodDef Signature (index into #Blob)
public uint mdParamList; // methodDef ParamList (index into Param table)
public uint token; // metadata token
public byte[] code;
public byte[] extraSections;
}
}

54
blocks/DumpedMethods.cs Normal file
View File

@ -0,0 +1,54 @@
/*
Copyright (C) 2011-2012 de4dot@gmail.com
This file is part of de4dot.
de4dot is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
de4dot is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using dot10.DotNet.MD;
using dot10.DotNet;
namespace de4dot.blocks {
[Serializable]
public class DumpedMethods {
Dictionary<uint, DumpedMethod> methods = new Dictionary<uint, DumpedMethod>();
public int Count {
get { return methods.Count; }
}
public void add(uint token, DumpedMethod info) {
methods[token] = info;
}
public DumpedMethod get(MethodDef method) {
return get(method.MDToken.ToUInt32());
}
public DumpedMethod get(uint token) {
DumpedMethod dm;
methods.TryGetValue(token, out dm);
return dm;
}
public void add(DumpedMethod dm) {
if (MDToken.ToTable(dm.token) != Table.Method || MDToken.ToRID(dm.token) == 0)
throw new ArgumentException("Invalid token");
methods[dm.token] = dm;
}
}
}

View File

@ -18,8 +18,6 @@
*/
using System.Collections.Generic;
using Mono.Cecil;
using Mono.Cecil.Cil;
namespace de4dot.blocks {
public class FilterHandlerBlock : ScopeBlock {

View File

@ -19,8 +19,6 @@
using System;
using System.Collections.Generic;
using Mono.Cecil;
using Mono.Cecil.Cil;
namespace de4dot.blocks {
// This class makes sure that each block that is entered with a non-empty stack has at
@ -52,7 +50,7 @@ namespace de4dot.blocks {
int stack = stackStart;
foreach (var instr in block.Instructions)
DotNetUtils.updateStack(instr.Instruction, ref stack, false);
instr.Instruction.UpdateStack(ref stack, false);
stackEnd = stack;
}
}

View File

@ -0,0 +1,313 @@
/*
Copyright (C) 2011-2012 de4dot@gmail.com
This file is part of de4dot.
de4dot is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
de4dot is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
*/
using System.Collections.Generic;
using dot10.DotNet;
namespace de4dot.blocks {
public struct GenericArgsSubstitutor {
IList<TypeSig> genericArgs;
IList<TypeSig> genericMethodArgs;
bool updated;
public static ITypeDefOrRef create(ITypeDefOrRef type, GenericInstSig git) {
if (git == null)
return type;
return create(type, git.GenericArguments);
}
public static ITypeDefOrRef create(ITypeDefOrRef type, IList<TypeSig> genericArgs) {
if (genericArgs == null || genericArgs.Count == 0)
return type;
var ts = type as TypeSpec;
if (ts == null)
return type;
var newSig = create(ts.TypeSig, genericArgs);
return newSig == ts.TypeSig ? type : new TypeSpecUser(newSig);
}
public static TypeSig create(TypeSig type, IList<TypeSig> genericArgs) {
if (type == null || genericArgs == null || genericArgs.Count == 0)
return type;
return new GenericArgsSubstitutor(genericArgs).create(type);
}
public static TypeSig create(TypeSig type, IList<TypeSig> genericArgs, IList<TypeSig> genericMethodArgs) {
if (type == null || ((genericArgs == null || genericArgs.Count == 0) &&
(genericMethodArgs == null || genericMethodArgs.Count == 0)))
return type;
return new GenericArgsSubstitutor(genericArgs, genericMethodArgs).create(type);
}
public static IField create(IField field, GenericInstSig git) {
if (git == null)
return field;
return create(field, git.GenericArguments);
}
public static IField create(IField field, IList<TypeSig> genericArgs) {
if (field == null || genericArgs == null || genericArgs.Count == 0)
return field;
var newSig = create(field.FieldSig, genericArgs);
if (newSig == field.FieldSig)
return field;
var module = field.DeclaringType != null ? field.DeclaringType.Module : null;
return new MemberRefUser(module, field.Name, newSig, field.DeclaringType);
}
public static FieldSig create(FieldSig sig, GenericInstSig git) {
if (git == null)
return sig;
return create(sig, git.GenericArguments);
}
public static FieldSig create(FieldSig sig, IList<TypeSig> genericArgs) {
if (sig == null || genericArgs == null || genericArgs.Count == 0)
return sig;
return new GenericArgsSubstitutor(genericArgs).create(sig);
}
public static IMethod create(IMethod method, GenericInstSig git) {
if (git == null)
return method;
var mdr = method as IMethodDefOrRef;
if (mdr != null)
return create(mdr, git);
var ms = method as MethodSpec;
if (ms != null)
return create(ms, git);
return method;
}
public static MethodSpec create(MethodSpec method, GenericInstSig git) {
if (method == null || git == null)
return method;
var newMethod = create(method.Method, git);
var newInst = create(method.GenericInstMethodSig, git);
bool updated = newMethod != method.Method || newInst != method.GenericInstMethodSig;
return updated ? new MethodSpecUser(newMethod, newInst) : method;
}
public static GenericInstMethodSig create(GenericInstMethodSig sig, GenericInstSig git) {
if (git == null)
return sig;
return create(sig, git.GenericArguments);
}
public static GenericInstMethodSig create(GenericInstMethodSig sig, IList<TypeSig> genericArgs) {
if (sig == null || genericArgs == null || genericArgs.Count == 0)
return sig;
return new GenericArgsSubstitutor(genericArgs).create(sig);
}
public static IMethodDefOrRef create(IMethodDefOrRef method, GenericInstSig git) {
if (git == null)
return method;
return create(method, git.GenericArguments);
}
public static IMethodDefOrRef create(IMethodDefOrRef method, IList<TypeSig> genericArgs) {
return create(method, genericArgs, null);
}
public static IMethodDefOrRef create(IMethodDefOrRef method, GenericInstSig git, IList<TypeSig> genericMethodArgs) {
return create(method, git == null ? null : git.GenericArguments, genericMethodArgs);
}
// Creates a new method but keeps declaring type as is
public static IMethodDefOrRef create(IMethodDefOrRef method, IList<TypeSig> genericArgs, IList<TypeSig> genericMethodArgs) {
if (method == null)
return method;
if ((genericArgs == null || genericArgs.Count == 0) && (genericMethodArgs == null || genericMethodArgs.Count == 0))
return method;
var sig = method.MethodSig;
if (sig == null)
return method;
var newSig = new GenericArgsSubstitutor(genericArgs, genericMethodArgs).create(sig);
if (newSig == sig)
return method;
return new MemberRefUser(method.DeclaringType.Module, method.Name, newSig, method.DeclaringType);
}
GenericArgsSubstitutor(IList<TypeSig> genericArgs) {
this.genericArgs = genericArgs;
this.genericMethodArgs = null;
this.updated = false;
}
GenericArgsSubstitutor(IList<TypeSig> genericArgs, IList<TypeSig> genericMethodArgs) {
this.genericArgs = genericArgs;
this.genericMethodArgs = genericMethodArgs;
this.updated = false;
}
TypeSig create(TypeSig type) {
var newType = create2(type);
return updated ? newType : type;
}
TypeSig create2(TypeSig type) {
if (type == null)
return type;
TypeSig result;
GenericSig varSig;
switch (type.ElementType) {
case ElementType.Void:
case ElementType.Boolean:
case ElementType.Char:
case ElementType.I1:
case ElementType.U1:
case ElementType.I2:
case ElementType.U2:
case ElementType.I4:
case ElementType.U4:
case ElementType.I8:
case ElementType.U8:
case ElementType.R4:
case ElementType.R8:
case ElementType.String:
case ElementType.TypedByRef:
case ElementType.I:
case ElementType.U:
case ElementType.Object:
result = type;
break;
case ElementType.Ptr:
result = new PtrSig(create2(type.Next));
break;
case ElementType.ByRef:
result = new ByRefSig(create2(type.Next));
break;
case ElementType.Array:
var ary = (ArraySig)type;
result = new ArraySig(ary.Next, ary.Rank, ary.Sizes, ary.LowerBounds);
break;
case ElementType.SZArray:
result = new SZArraySig(create2(type.Next));
break;
case ElementType.Pinned:
result = new PinnedSig(create2(type.Next));
break;
case ElementType.ValueType:
case ElementType.Class:
result = type;
break;
case ElementType.Var:
varSig = (GenericSig)type;
if (genericArgs != null && varSig.Number < (uint)genericArgs.Count) {
result = genericArgs[(int)varSig.Number];
updated = true;
}
else
result = type;
break;
case ElementType.MVar:
varSig = (GenericSig)type;
if (genericMethodArgs != null && varSig.Number < (uint)genericMethodArgs.Count) {
result = genericMethodArgs[(int)varSig.Number];
updated = true;
}
else
result = type;
break;
case ElementType.GenericInst:
var gis = (GenericInstSig)type;
var newGis = new GenericInstSig(create2(gis.GenericType) as ClassOrValueTypeSig, gis.GenericArguments.Count);
for (int i = 0; i < gis.GenericArguments.Count; i++)
newGis.GenericArguments.Add(create2(gis.GenericArguments[i]));
result = newGis;
break;
case ElementType.ValueArray:
result = new ValueArraySig(type.Next, ((ValueArraySig)type).Size);
break;
case ElementType.Module:
result = new ModuleSig(((ModuleSig)type).Index, type.Next);
break;
case ElementType.CModReqd:
result = new CModReqdSig(((ModifierSig)type).Modifier, type.Next);
break;
case ElementType.CModOpt:
result = new CModOptSig(((ModifierSig)type).Modifier, type.Next);
break;
case ElementType.FnPtr:
result = new FnPtrSig(create(((FnPtrSig)type).MethodSig));
break;
case ElementType.End:
case ElementType.R:
case ElementType.Sentinel:
case ElementType.Internal:
default:
result = type;
break;
}
return result;
}
MethodSig create(MethodSig sig) {
if (sig == null)
return sig;
var newSig = new MethodSig(sig.GetCallingConvention());
newSig.RetType = create2(sig.RetType);
for (int i = 0; i < sig.Params.Count; i++)
newSig.Params.Add(create2(sig.Params[i]));
newSig.GenParamCount = sig.GenParamCount;
if (sig.ParamsAfterSentinel != null) {
newSig.ParamsAfterSentinel = new List<TypeSig>();
for (int i = 0; i < sig.ParamsAfterSentinel.Count; i++)
newSig.ParamsAfterSentinel.Add(create2(sig.ParamsAfterSentinel[i]));
}
return updated ? newSig : sig;
}
GenericInstMethodSig create(GenericInstMethodSig sig) {
var newSig = new GenericInstMethodSig();
for (int i = 0; i < sig.GenericArguments.Count; i++)
newSig.GenericArguments.Add(create2(sig.GenericArguments[i]));
return updated ? newSig : sig;
}
FieldSig create(FieldSig sig) {
var newSig = new FieldSig(create2(sig.Type));
return updated ? newSig : sig;
}
}
}

View File

@ -18,8 +18,6 @@
*/
using System.Collections.Generic;
using Mono.Cecil;
using Mono.Cecil.Cil;
namespace de4dot.blocks {
// This is the block inside catch(xxx) { }.

View File

@ -18,8 +18,8 @@
*/
using System;
using Mono.Cecil.Cil;
using System.Collections.Generic;
using dot10.DotNet.Emit;
namespace de4dot.blocks {
public class Instr {
@ -44,8 +44,8 @@ namespace de4dot.blocks {
// Returns the variable or null if it's not a ldloc/stloc instruction. It does not return
// a local variable if it's a ldloca/ldloca.s instruction.
public static VariableDefinition getLocalVar(IList<VariableDefinition> locals, Instr instr) {
return DotNetUtils.getLocalVar(locals, instr.Instruction);
public static Local getLocalVar(IList<Local> locals, Instr instr) {
return instr.Instruction.GetLocal(locals);
}
static public bool isFallThrough(OpCode opCode) {
@ -104,23 +104,23 @@ namespace de4dot.blocks {
}
public bool isLdcI4() {
return DotNetUtils.isLdcI4(OpCode.Code);
return instruction.IsLdcI4();
}
public int getLdcI4Value() {
return DotNetUtils.getLdcI4Value(instruction);
return instruction.GetLdcI4Value();
}
public bool isLdarg() {
return DotNetUtils.isLdarg(instruction);
return instruction.IsLdarg();
}
public bool isStloc() {
return DotNetUtils.isStloc(instruction);
return instruction.IsStloc();
}
public bool isLdloc() {
return DotNetUtils.isLdloc(instruction);
return instruction.IsLdloc();
}
public bool isNop() {
@ -132,23 +132,23 @@ namespace de4dot.blocks {
}
public bool isLeave() {
return DotNetUtils.isLeave(instruction);
return instruction.IsLeave();
}
public bool isBr() {
return DotNetUtils.isBr(instruction);
return instruction.IsBr();
}
public bool isBrfalse() {
return DotNetUtils.isBrfalse(instruction);
return instruction.IsBrfalse();
}
public bool isBrtrue() {
return DotNetUtils.isBrtrue(instruction);
return instruction.IsBrtrue();
}
public bool isConditionalBranch() {
return DotNetUtils.isConditionalBranch(OpCode.Code);
return instruction.IsConditionalBranch();
}
public bool getFlippedBranchOpCode(out OpCode opcode) {

View File

@ -19,7 +19,7 @@
using System;
using System.Collections.Generic;
using Mono.Cecil.Cil;
using dot10.DotNet.Emit;
namespace de4dot.blocks {
class InstructionListParser {

736
blocks/MemberDefDict.cs Normal file
View File

@ -0,0 +1,736 @@
/*
Copyright (C) 2011-2012 de4dot@gmail.com
This file is part of de4dot.
de4dot is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
de4dot is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using dot10.DotNet;
namespace de4dot.blocks {
public class TypeDefinitionDict<TValue> {
Dictionary<ScopeAndTokenKey, TValue> tokenToValue = new Dictionary<ScopeAndTokenKey, TValue>();
Dictionary<ScopeAndTokenKey, TypeDef> tokenToKey = new Dictionary<ScopeAndTokenKey, TypeDef>();
Dictionary<IType, TValue> refToValue = new Dictionary<IType, TValue>(TypeEqualityComparer.Instance);
Dictionary<IType, TypeDef> refToKey = new Dictionary<IType, TypeDef>(TypeEqualityComparer.Instance);
public int Count {
get { return tokenToValue.Count; }
}
public IEnumerable<TypeDef> getKeys() {
return tokenToKey.Values;
}
public IEnumerable<TValue> getValues() {
return tokenToValue.Values;
}
ScopeAndTokenKey getTokenKey(TypeDef typeDef) {
return new ScopeAndTokenKey(typeDef);
}
public TValue find(IType typeRef) {
TValue value;
var typeDef = typeRef as TypeDef;
if (typeDef != null)
tokenToValue.TryGetValue(getTokenKey(typeDef), out value);
else if (typeRef != null)
refToValue.TryGetValue(typeRef, out value);
else
value = default(TValue);
return value;
}
public TValue findAny(IType type) {
TValue value;
var typeDef = type as TypeDef;
if (typeDef != null && tokenToValue.TryGetValue(getTokenKey(typeDef), out value))
return value;
refToValue.TryGetValue(type, out value);
return value;
}
public void add(TypeDef typeDef, TValue value) {
var tokenKey = getTokenKey(typeDef);
tokenToValue[tokenKey] = value;
tokenToKey[tokenKey] = typeDef;
if (!refToValue.ContainsKey(typeDef) ||
getAccessibilityOrder(typeDef) < getAccessibilityOrder(refToKey[typeDef])) {
refToKey[typeDef] = typeDef;
refToValue[typeDef] = value;
}
}
// Order: public, family, assembly, private
static int[] accessibilityOrder = new int[8] {
40, // NotPublic
0, // Public
10, // NestedPublic
70, // NestedPrivate
20, // NestedFamily
50, // NestedAssembly
60, // NestedFamANDAssem
30, // NestedFamORAssem
};
static int getAccessibilityOrder(TypeDef typeDef) {
return accessibilityOrder[(int)typeDef.Attributes & 7];
}
public void onTypesRenamed() {
var newTypeRefToValue = new Dictionary<IType, TValue>(refToValue.Count);
foreach (var kvp in refToValue)
newTypeRefToValue[kvp.Key] = kvp.Value;
refToValue = newTypeRefToValue;
}
}
public abstract class FieldDefinitionDictBase<TValue> {
Dictionary<ScopeAndTokenKey, TValue> tokenToValue = new Dictionary<ScopeAndTokenKey, TValue>();
Dictionary<ScopeAndTokenKey, FieldDef> tokenToKey = new Dictionary<ScopeAndTokenKey, FieldDef>();
Dictionary<IFieldReferenceKey, TValue> refToValue = new Dictionary<IFieldReferenceKey, TValue>();
Dictionary<IFieldReferenceKey, FieldDef> refToKey = new Dictionary<IFieldReferenceKey, FieldDef>();
public int Count {
get { return tokenToValue.Count; }
}
public IEnumerable<FieldDef> getKeys() {
return tokenToKey.Values;
}
public IEnumerable<TValue> getValues() {
return tokenToValue.Values;
}
ScopeAndTokenKey getTokenKey(FieldDef fieldDef) {
return new ScopeAndTokenKey(fieldDef);
}
internal abstract IFieldReferenceKey getReferenceKey(IField fieldRef);
public TValue find(IField fieldRef) {
TValue value;
var fieldDef = fieldRef as FieldDef;
if (fieldDef != null)
tokenToValue.TryGetValue(getTokenKey(fieldDef), out value);
else
refToValue.TryGetValue(getReferenceKey(fieldRef), out value);
return value;
}
public TValue findAny(IField fieldRef) {
TValue value;
var fieldDef = fieldRef as FieldDef;
if (fieldDef != null && tokenToValue.TryGetValue(getTokenKey(fieldDef), out value))
return value;
refToValue.TryGetValue(getReferenceKey(fieldRef), out value);
return value;
}
public void add(FieldDef fieldDef, TValue value) {
var tokenKey = getTokenKey(fieldDef);
tokenToValue[tokenKey] = value;
tokenToKey[tokenKey] = fieldDef;
var refKey = getReferenceKey(fieldDef);
if (!refToValue.ContainsKey(refKey) ||
getAccessibilityOrder(fieldDef) < getAccessibilityOrder(refToKey[refKey])) {
refToKey[refKey] = fieldDef;
refToValue[refKey] = value;
}
}
// Order: public, family, assembly, private
static int[] accessibilityOrder = new int[8] {
60, // PrivateScope
50, // Private
40, // FamANDAssem
30, // Assembly
10, // Family
20, // FamORAssem
0, // Public
70, // <reserved>
};
static int getAccessibilityOrder(FieldDef fieldDefinition) {
return accessibilityOrder[(int)fieldDefinition.Attributes & 7];
}
public void onTypesRenamed() {
var newFieldRefToDef = new Dictionary<IFieldReferenceKey, TValue>(refToValue.Count);
foreach (var kvp in refToValue)
newFieldRefToDef[getReferenceKey((FieldDef)kvp.Key.FieldReference)] = kvp.Value;
refToValue = newFieldRefToDef;
}
}
public class FieldDefinitionDict<TValue> : FieldDefinitionDictBase<TValue> {
internal override IFieldReferenceKey getReferenceKey(IField fieldRef) {
return new FieldReferenceKey(fieldRef);
}
}
public class FieldDefinitionAndDeclaringTypeDict<TValue> : FieldDefinitionDictBase<TValue> {
internal override IFieldReferenceKey getReferenceKey(IField fieldRef) {
return new FieldReferenceAndDeclaringTypeKey(fieldRef);
}
}
public abstract class MethodDefinitionDictBase<TValue> {
Dictionary<ScopeAndTokenKey, TValue> tokenToValue = new Dictionary<ScopeAndTokenKey, TValue>();
Dictionary<ScopeAndTokenKey, MethodDef> tokenToKey = new Dictionary<ScopeAndTokenKey, MethodDef>();
Dictionary<IMethodReferenceKey, TValue> refToValue = new Dictionary<IMethodReferenceKey, TValue>();
Dictionary<IMethodReferenceKey, MethodDef> refToKey = new Dictionary<IMethodReferenceKey, MethodDef>();
public int Count {
get { return tokenToValue.Count; }
}
public IEnumerable<MethodDef> getKeys() {
return tokenToKey.Values;
}
public IEnumerable<TValue> getValues() {
return tokenToValue.Values;
}
ScopeAndTokenKey getTokenKey(MethodDef methodDef) {
return new ScopeAndTokenKey(methodDef);
}
internal abstract IMethodReferenceKey getReferenceKey(IMethod methodRef);
public TValue find(IMethod methodRef) {
TValue value;
var methodDef = methodRef as MethodDef;
if (methodDef != null)
tokenToValue.TryGetValue(getTokenKey(methodDef), out value);
else
refToValue.TryGetValue(getReferenceKey(methodRef), out value);
return value;
}
public TValue findAny(IMethod methodRef) {
TValue value;
var methodDef = methodRef as MethodDef;
if (methodDef != null && tokenToValue.TryGetValue(getTokenKey(methodDef), out value))
return value;
refToValue.TryGetValue(getReferenceKey(methodRef), out value);
return value;
}
public void add(MethodDef methodDef, TValue value) {
var tokenKey = getTokenKey(methodDef);
tokenToValue[tokenKey] = value;
tokenToKey[tokenKey] = methodDef;
var refKey = getReferenceKey(methodDef);
if (!refToValue.ContainsKey(refKey) ||
getAccessibilityOrder(methodDef) < getAccessibilityOrder(refToKey[refKey])) {
refToKey[refKey] = methodDef;
refToValue[refKey] = value;
}
}
// Order: public, family, assembly, private
static int[] accessibilityOrder = new int[8] {
60, // PrivateScope
50, // Private
40, // FamANDAssem
30, // Assembly
10, // Family
20, // FamORAssem
0, // Public
70, // <reserved>
};
static int getAccessibilityOrder(MethodDef methodDefinition) {
return accessibilityOrder[(int)methodDefinition.Attributes & 7];
}
public void onTypesRenamed() {
var newFieldRefToDef = new Dictionary<IMethodReferenceKey, TValue>(refToValue.Count);
foreach (var kvp in refToValue)
newFieldRefToDef[getReferenceKey((MethodDef)kvp.Key.MethodReference)] = kvp.Value;
refToValue = newFieldRefToDef;
}
}
public class MethodDefinitionDict<TValue> : MethodDefinitionDictBase<TValue> {
internal override IMethodReferenceKey getReferenceKey(IMethod methodRef) {
return new MethodReferenceKey(methodRef);
}
}
public class MethodDefinitionAndDeclaringTypeDict<TValue> : MethodDefinitionDictBase<TValue> {
internal override IMethodReferenceKey getReferenceKey(IMethod methodRef) {
return new MethodReferenceAndDeclaringTypeKey(methodRef);
}
}
public abstract class EventDefinitionDictBase<TValue> {
Dictionary<ScopeAndTokenKey, TValue> tokenToValue = new Dictionary<ScopeAndTokenKey, TValue>();
Dictionary<ScopeAndTokenKey, EventDef> tokenToKey = new Dictionary<ScopeAndTokenKey, EventDef>();
Dictionary<IEventReferenceKey, TValue> refToValue = new Dictionary<IEventReferenceKey, TValue>();
public int Count {
get { return tokenToValue.Count; }
}
public IEnumerable<EventDef> getKeys() {
return tokenToKey.Values;
}
public IEnumerable<TValue> getValues() {
return tokenToValue.Values;
}
ScopeAndTokenKey getTokenKey(EventDef eventReference) {
return new ScopeAndTokenKey(eventReference);
}
internal abstract IEventReferenceKey getReferenceKey(EventDef eventRef);
public TValue find(EventDef eventRef) {
TValue value;
tokenToValue.TryGetValue(getTokenKey(eventRef), out value);
return value;
}
public TValue findAny(EventDef eventRef) {
TValue value;
if (tokenToValue.TryGetValue(getTokenKey(eventRef), out value))
return value;
refToValue.TryGetValue(getReferenceKey(eventRef), out value);
return value;
}
public void add(EventDef eventDef, TValue value) {
var tokenKey = getTokenKey(eventDef);
tokenToValue[tokenKey] = value;
tokenToKey[tokenKey] = eventDef;
refToValue[getReferenceKey(eventDef)] = value;
}
public void onTypesRenamed() {
var newFieldRefToDef = new Dictionary<IEventReferenceKey, TValue>(refToValue.Count);
foreach (var kvp in refToValue)
newFieldRefToDef[getReferenceKey((EventDef)kvp.Key.EventDef)] = kvp.Value;
refToValue = newFieldRefToDef;
}
}
public class EventDefinitionDict<TValue> : EventDefinitionDictBase<TValue> {
internal override IEventReferenceKey getReferenceKey(EventDef eventRef) {
return new EventReferenceKey(eventRef);
}
}
public class EventDefinitionAndDeclaringTypeDict<TValue> : EventDefinitionDictBase<TValue> {
internal override IEventReferenceKey getReferenceKey(EventDef eventRef) {
return new EventReferenceAndDeclaringTypeKey(eventRef);
}
}
public abstract class PropertyDefinitionDictBase<TValue> {
Dictionary<ScopeAndTokenKey, TValue> tokenToValue = new Dictionary<ScopeAndTokenKey, TValue>();
Dictionary<ScopeAndTokenKey, PropertyDef> tokenToKey = new Dictionary<ScopeAndTokenKey, PropertyDef>();
Dictionary<IPropertyReferenceKey, TValue> refToValue = new Dictionary<IPropertyReferenceKey, TValue>();
public int Count {
get { return tokenToValue.Count; }
}
public IEnumerable<PropertyDef> getKeys() {
return tokenToKey.Values;
}
public IEnumerable<TValue> getValues() {
return tokenToValue.Values;
}
ScopeAndTokenKey getTokenKey(PropertyDef propertyReference) {
return new ScopeAndTokenKey(propertyReference);
}
internal abstract IPropertyReferenceKey getReferenceKey(PropertyDef propertyReference);
public TValue find(PropertyDef propRef) {
TValue value;
tokenToValue.TryGetValue(getTokenKey(propRef), out value);
return value;
}
public TValue findAny(PropertyDef propRef) {
TValue value;
if (tokenToValue.TryGetValue(getTokenKey(propRef), out value))
return value;
refToValue.TryGetValue(getReferenceKey(propRef), out value);
return value;
}
public void add(PropertyDef propDef, TValue value) {
var tokenKey = getTokenKey(propDef);
tokenToValue[tokenKey] = value;
tokenToKey[tokenKey] = propDef;
refToValue[getReferenceKey(propDef)] = value;
}
public void onTypesRenamed() {
var newFieldRefToDef = new Dictionary<IPropertyReferenceKey, TValue>(refToValue.Count);
foreach (var kvp in refToValue)
newFieldRefToDef[getReferenceKey((PropertyDef)kvp.Key.PropertyDef)] = kvp.Value;
refToValue = newFieldRefToDef;
}
}
public class PropertyDefinitionDict<TValue> : PropertyDefinitionDictBase<TValue> {
internal override IPropertyReferenceKey getReferenceKey(PropertyDef propRef) {
return new PropertyReferenceKey(propRef);
}
}
public class PropertyDefinitionAndDeclaringTypeDict<TValue> : PropertyDefinitionDictBase<TValue> {
internal override IPropertyReferenceKey getReferenceKey(PropertyDef propRef) {
return new PropertyReferenceAndDeclaringTypeKey(propRef);
}
}
sealed class ScopeAndTokenKey {
readonly IScope scope;
readonly uint token;
public ScopeAndTokenKey(TypeDef type)
: this(type.Module, type.MDToken.Raw) {
}
public ScopeAndTokenKey(FieldDef field)
: this(field.DeclaringType == null ? null : field.DeclaringType.Module, field.MDToken.Raw) {
}
public ScopeAndTokenKey(MethodDef method)
: this(method.DeclaringType == null ? null : method.DeclaringType.Module, method.MDToken.Raw) {
}
public ScopeAndTokenKey(PropertyDef prop)
: this(prop.DeclaringType == null ? null : prop.DeclaringType.Module, prop.MDToken.Raw) {
}
public ScopeAndTokenKey(EventDef evt)
: this(evt.DeclaringType == null ? null : evt.DeclaringType.Module, evt.MDToken.Raw) {
}
public ScopeAndTokenKey(IScope scope, uint token) {
this.scope = scope;
this.token = token;
}
public override int GetHashCode() {
return (int)token + GetHashCode(scope);
}
public override bool Equals(object obj) {
var other = obj as ScopeAndTokenKey;
if (other == null)
return false;
return token == other.token &&
Equals(scope, other.scope);
}
public override string ToString() {
return string.Format("{0:X8} {1}", token, scope);
}
static bool Equals(IScope a, IScope b) {
if (a == b)
return true;
if (a == null || b == null)
return false;
return getCanonicalizedScopeName(a) == getCanonicalizedScopeName(b);
}
static int GetHashCode(IScope a) {
if (a == null)
return 0;
return getCanonicalizedScopeName(a).GetHashCode();
}
static string getAssemblyName(IScope a) {
switch (a.ScopeType) {
case ScopeType.AssemblyRef:
return ((AssemblyRef)a).Name.String;
case ScopeType.ModuleDef:
var asm = ((ModuleDef)a).Assembly;
if (asm != null)
return asm.Name.String;
break;
}
return null;
}
static string getCanonicalizedScopeName(IScope a) {
if (a == null)
return string.Empty;
var asmName = getAssemblyName(a);
if (asmName != null) {
// The version number should be ignored. Older code may reference an old version of
// the assembly, but if the newer one has been loaded, that one is used.
return asmName.ToUpperInvariant();
}
return a.ScopeName.ToUpperInvariant();
}
}
interface IFieldReferenceKey {
IField FieldReference { get; }
}
interface IMethodReferenceKey {
IMethod MethodReference { get; }
}
interface IEventReferenceKey {
EventDef EventDef { get; }
}
interface IPropertyReferenceKey {
PropertyDef PropertyDef { get; }
}
sealed class FieldReferenceKey : IFieldReferenceKey {
readonly IField fieldRef;
public IField FieldReference {
get { return fieldRef; }
}
public FieldReferenceKey(IField fieldRef) {
this.fieldRef = fieldRef;
}
public override int GetHashCode() {
return new SigComparer().GetHashCode(fieldRef);
}
public override bool Equals(object obj) {
var other = obj as FieldReferenceKey;
if (other == null)
return false;
return new SigComparer().Equals(fieldRef, other.fieldRef);
}
public override string ToString() {
return fieldRef.ToString();
}
}
sealed class MethodReferenceKey : IMethodReferenceKey {
readonly IMethod methodRef;
public IMethod MethodReference {
get { return methodRef; }
}
public MethodReferenceKey(IMethod methodRef) {
this.methodRef = methodRef;
}
public override int GetHashCode() {
return new SigComparer().GetHashCode(methodRef);
}
public override bool Equals(object obj) {
var other = obj as MethodReferenceKey;
if (other == null)
return false;
return new SigComparer().Equals(methodRef, other.methodRef);
}
public override string ToString() {
return methodRef.ToString();
}
}
sealed class FieldReferenceAndDeclaringTypeKey : IFieldReferenceKey {
readonly IField fieldRef;
public IField FieldReference {
get { return fieldRef; }
}
public FieldReferenceAndDeclaringTypeKey(IField fieldRef) {
this.fieldRef = fieldRef;
}
public override int GetHashCode() {
return new SigComparer(SigComparerOptions.CompareMethodFieldDeclaringType).GetHashCode(fieldRef);
}
public override bool Equals(object obj) {
var other = obj as FieldReferenceAndDeclaringTypeKey;
if (other == null)
return false;
return new SigComparer(SigComparerOptions.CompareMethodFieldDeclaringType).Equals(fieldRef, other.fieldRef);
}
public override string ToString() {
return fieldRef.ToString();
}
}
sealed class MethodReferenceAndDeclaringTypeKey : IMethodReferenceKey {
readonly IMethod methodRef;
public IMethod MethodReference {
get { return methodRef; }
}
public MethodReferenceAndDeclaringTypeKey(IMethod methodRef) {
this.methodRef = methodRef;
}
public override int GetHashCode() {
return new SigComparer(SigComparerOptions.CompareMethodFieldDeclaringType).GetHashCode(methodRef);
}
public override bool Equals(object obj) {
var other = obj as MethodReferenceAndDeclaringTypeKey;
if (other == null)
return false;
return new SigComparer(SigComparerOptions.CompareMethodFieldDeclaringType).Equals(methodRef, other.methodRef);
}
public override string ToString() {
return methodRef.ToString();
}
}
sealed class EventReferenceKey : IEventReferenceKey {
readonly EventDef eventRef;
public EventDef EventDef {
get { return eventRef; }
}
public EventReferenceKey(EventDef eventRef) {
this.eventRef = eventRef;
}
public override int GetHashCode() {
return new SigComparer().GetHashCode(eventRef);
}
public override bool Equals(object obj) {
var other = obj as EventReferenceKey;
if (other == null)
return false;
return new SigComparer().Equals(eventRef, other.eventRef);
}
public override string ToString() {
return eventRef.ToString();
}
}
sealed class EventReferenceAndDeclaringTypeKey : IEventReferenceKey {
readonly EventDef eventRef;
public EventDef EventDef {
get { return eventRef; }
}
public EventReferenceAndDeclaringTypeKey(EventDef eventRef) {
this.eventRef = eventRef;
}
public override int GetHashCode() {
return new SigComparer(SigComparerOptions.CompareEventDeclaringType).GetHashCode(eventRef);
}
public override bool Equals(object obj) {
var other = obj as EventReferenceAndDeclaringTypeKey;
if (other == null)
return false;
return new SigComparer(SigComparerOptions.CompareEventDeclaringType).Equals(eventRef, other.eventRef);
}
public override string ToString() {
return eventRef.ToString();
}
}
sealed class PropertyReferenceKey : IPropertyReferenceKey {
readonly PropertyDef propRef;
public PropertyDef PropertyDef {
get { return propRef; }
}
public PropertyReferenceKey(PropertyDef propRef) {
this.propRef = propRef;
}
public override int GetHashCode() {
return new SigComparer().GetHashCode(propRef);
}
public override bool Equals(object obj) {
var other = obj as PropertyReferenceKey;
if (other == null)
return false;
return new SigComparer().Equals(propRef, other.propRef);
}
public override string ToString() {
return propRef.ToString();
}
}
sealed class PropertyReferenceAndDeclaringTypeKey : IPropertyReferenceKey {
readonly PropertyDef propRef;
public PropertyDef PropertyDef {
get { return propRef; }
}
public PropertyReferenceAndDeclaringTypeKey(PropertyDef propRef) {
this.propRef = propRef;
}
public override int GetHashCode() {
return new SigComparer(SigComparerOptions.ComparePropertyDeclaringType).GetHashCode(propRef);
}
public override bool Equals(object obj) {
var other = obj as PropertyReferenceAndDeclaringTypeKey;
if (other == null)
return false;
return new SigComparer(SigComparerOptions.ComparePropertyDeclaringType).Equals(propRef, other.propRef);
}
public override string ToString() {
return propRef.ToString();
}
}
}

View File

@ -17,6 +17,8 @@
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
*/
#if PORT
// Create a new type, method, etc, where all generic parameters have been replaced with the
// corresponding generic argument.
@ -226,3 +228,4 @@ namespace de4dot.blocks {
}
}
}
#endif

View File

@ -17,34 +17,13 @@
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
*/
#if PORT
using System;
using System.Collections.Generic;
using Mono.Cecil;
using Mono.Cecil.Metadata;
namespace de4dot.blocks {
public enum CecilType {
ArrayType,
ByReferenceType,
EventDefinition,
FieldDefinition,
FieldReference,
FunctionPointerType,
GenericInstanceMethod,
GenericInstanceType,
GenericParameter,
MethodDefinition,
MethodReference,
OptionalModifierType,
PinnedType,
PointerType,
PropertyDefinition,
RequiredModifierType,
SentinelType,
TypeDefinition,
TypeReference,
}
namespace de4dot.blocks.OLD_REMOVE {
public class TypeDefinitionDict<TValue> {
Dictionary<ScopeAndTokenKey, TValue> tokenToValue = new Dictionary<ScopeAndTokenKey, TValue>();
Dictionary<ScopeAndTokenKey, TypeDefinition> tokenToKey = new Dictionary<ScopeAndTokenKey, TypeDefinition>();
@ -501,14 +480,14 @@ namespace de4dot.blocks {
}
public override int GetHashCode() {
return MemberReferenceHelper.typeHashCode(typeRef);
throw new NotImplementedException();
}
public override bool Equals(object obj) {
var other = obj as TypeReferenceKey;
if (other == null)
return false;
return MemberReferenceHelper.compareTypes(typeRef, other.typeRef);
throw new NotImplementedException();
}
public override string ToString() {
@ -528,14 +507,14 @@ namespace de4dot.blocks {
}
public override int GetHashCode() {
return MemberReferenceHelper.typeReferenceHashCodeSameVersion(typeRef);
throw new NotImplementedException();
}
public override bool Equals(object obj) {
var other = obj as TypeReferenceSameVersionKey;
if (other == null)
return false;
return MemberReferenceHelper.compareTypeReferenceSameVersion(typeRef, other.typeRef);
throw new NotImplementedException();
}
public override string ToString() {
@ -571,14 +550,14 @@ namespace de4dot.blocks {
}
public override int GetHashCode() {
return MemberReferenceHelper.fieldReferenceHashCode(fieldRef);
throw new NotImplementedException();
}
public override bool Equals(object obj) {
var other = obj as FieldReferenceKey;
if (other == null)
return false;
return MemberReferenceHelper.compareFieldReference(fieldRef, other.fieldRef);
throw new NotImplementedException();
}
public override string ToString() {
@ -598,14 +577,14 @@ namespace de4dot.blocks {
}
public override int GetHashCode() {
return MemberReferenceHelper.propertyReferenceHashCode(propRef);
throw new NotImplementedException();
}
public override bool Equals(object obj) {
var other = obj as PropertyReferenceKey;
if (other == null)
return false;
return MemberReferenceHelper.comparePropertyReference(propRef, other.propRef);
throw new NotImplementedException();
}
public override string ToString() {
@ -625,14 +604,14 @@ namespace de4dot.blocks {
}
public override int GetHashCode() {
return MemberReferenceHelper.eventReferenceHashCode(eventRef);
throw new NotImplementedException();
}
public override bool Equals(object obj) {
var other = obj as EventReferenceKey;
if (other == null)
return false;
return MemberReferenceHelper.compareEventReference(eventRef, other.eventRef);
throw new NotImplementedException();
}
public override string ToString() {
@ -652,14 +631,14 @@ namespace de4dot.blocks {
}
public override int GetHashCode() {
return MemberReferenceHelper.methodReferenceHashCode(methodRef);
throw new NotImplementedException();
}
public override bool Equals(object obj) {
var other = obj as MethodReferenceKey;
if (other == null)
return false;
return MemberReferenceHelper.compareMethodReference(methodRef, other.methodRef);
throw new NotImplementedException();
}
public override string ToString() {
@ -679,16 +658,14 @@ namespace de4dot.blocks {
}
public override int GetHashCode() {
return MemberReferenceHelper.fieldReferenceHashCode(fieldRef) +
MemberReferenceHelper.typeHashCode(fieldRef.DeclaringType);
throw new NotImplementedException();
}
public override bool Equals(object obj) {
var other = obj as FieldReferenceAndDeclaringTypeKey;
if (other == null)
return false;
return MemberReferenceHelper.compareFieldReference(fieldRef, other.fieldRef) &&
MemberReferenceHelper.compareTypes(fieldRef.DeclaringType, other.fieldRef.DeclaringType);
throw new NotImplementedException();
}
public override string ToString() {
@ -708,16 +685,14 @@ namespace de4dot.blocks {
}
public override int GetHashCode() {
return MemberReferenceHelper.propertyReferenceHashCode(propRef) +
MemberReferenceHelper.typeHashCode(propRef.DeclaringType);
throw new NotImplementedException();
}
public override bool Equals(object obj) {
var other = obj as PropertyReferenceAndDeclaringTypeKey;
if (other == null)
return false;
return MemberReferenceHelper.comparePropertyReference(propRef, other.propRef) &&
MemberReferenceHelper.compareTypes(propRef.DeclaringType, other.propRef.DeclaringType);
throw new NotImplementedException();
}
public override string ToString() {
@ -737,16 +712,14 @@ namespace de4dot.blocks {
}
public override int GetHashCode() {
return MemberReferenceHelper.eventReferenceHashCode(eventRef) +
MemberReferenceHelper.typeHashCode(eventRef.DeclaringType);
throw new NotImplementedException();
}
public override bool Equals(object obj) {
var other = obj as EventReferenceAndDeclaringTypeKey;
if (other == null)
return false;
return MemberReferenceHelper.compareEventReference(eventRef, other.eventRef) &&
MemberReferenceHelper.compareTypes(eventRef.DeclaringType, other.eventRef.DeclaringType);
throw new NotImplementedException();
}
public override string ToString() {
@ -766,55 +739,24 @@ namespace de4dot.blocks {
}
public override int GetHashCode() {
return MemberReferenceHelper.methodReferenceHashCode(methodRef) +
MemberReferenceHelper.typeHashCode(methodRef.DeclaringType);
throw new NotImplementedException();
}
public override bool Equals(object obj) {
var other = obj as MethodReferenceAndDeclaringTypeKey;
if (other == null)
return false;
return MemberReferenceHelper.compareMethodReference(methodRef, other.methodRef) &&
MemberReferenceHelper.compareTypes(methodRef.DeclaringType, other.methodRef.DeclaringType);
throw new NotImplementedException();
}
public override string ToString() {
return methodRef.ToString();
}
}
}
namespace de4dot.blocks {
public static class MemberReferenceHelper {
static Dictionary<Type, CecilType> typeToCecilTypeDict = new Dictionary<Type, CecilType>();
static MemberReferenceHelper() {
typeToCecilTypeDict[typeof(ArrayType)] = CecilType.ArrayType;
typeToCecilTypeDict[typeof(ByReferenceType)] = CecilType.ByReferenceType;
typeToCecilTypeDict[typeof(EventDefinition)] = CecilType.EventDefinition;
typeToCecilTypeDict[typeof(FieldDefinition)] = CecilType.FieldDefinition;
typeToCecilTypeDict[typeof(FieldReference)] = CecilType.FieldReference;
typeToCecilTypeDict[typeof(FunctionPointerType)] = CecilType.FunctionPointerType;
typeToCecilTypeDict[typeof(GenericInstanceMethod)] = CecilType.GenericInstanceMethod;
typeToCecilTypeDict[typeof(GenericInstanceType)] = CecilType.GenericInstanceType;
typeToCecilTypeDict[typeof(GenericParameter)] = CecilType.GenericParameter;
typeToCecilTypeDict[typeof(MethodDefinition)] = CecilType.MethodDefinition;
typeToCecilTypeDict[typeof(MethodReference)] = CecilType.MethodReference;
typeToCecilTypeDict[typeof(OptionalModifierType)] = CecilType.OptionalModifierType;
typeToCecilTypeDict[typeof(PinnedType)] = CecilType.PinnedType;
typeToCecilTypeDict[typeof(PointerType)] = CecilType.PointerType;
typeToCecilTypeDict[typeof(PropertyDefinition)] = CecilType.PropertyDefinition;
typeToCecilTypeDict[typeof(RequiredModifierType)] = CecilType.RequiredModifierType;
typeToCecilTypeDict[typeof(SentinelType)] = CecilType.SentinelType;
typeToCecilTypeDict[typeof(TypeDefinition)] = CecilType.TypeDefinition;
typeToCecilTypeDict[typeof(TypeReference)] = CecilType.TypeReference;
}
public static CecilType getMemberReferenceType(MemberReference memberReference) {
CecilType cecilType;
var type = memberReference.GetType();
if (typeToCecilTypeDict.TryGetValue(type, out cecilType))
return cecilType;
throw new ApplicationException(string.Format("Unknown MemberReference type: {0}", type));
}
public static bool verifyType(TypeReference typeReference, string assembly, string type) {
return verifyType(typeReference, assembly, type, "");
}
@ -900,511 +842,21 @@ namespace de4dot.blocks {
return getCanonicalizedScopeAndVersion(a).GetHashCode();
}
public static bool compareEventReference(EventReference a, EventReference b) {
if (ReferenceEquals(a, b))
return true;
if (a == null || b == null)
return false;
return a.Name == b.Name &&
compareTypes(a.EventType, b.EventType);
}
public static int eventReferenceHashCode(EventReference a) {
if (a == null)
return 0;
int res = 0;
res += a.Name.GetHashCode();
res += typeHashCode(a.EventType);
return res;
}
public static bool compareFieldReferenceAndDeclaringType(FieldReference a, FieldReference b) {
if (!compareFieldReference(a, b))
return false;
if (a == null)
return true;
return compareTypes(a.DeclaringType, b.DeclaringType);
}
public static bool compareFieldReference(FieldReference a, FieldReference b) {
if (ReferenceEquals(a, b))
return true;
if (a == null || b == null)
return false;
return a.Name == b.Name &&
compareTypes(a.FieldType, b.FieldType);
}
public static int fieldReferenceHashCode(FieldReference a) {
if (a == null)
return 0;
int res = 0;
res += a.Name.GetHashCode();
res += typeHashCode(a.FieldType);
return res;
public static bool compareMethodReference(MethodReference a, MethodReference b) {
throw new NotImplementedException();
}
public static bool compareMethodReferenceAndDeclaringType(MethodReference a, MethodReference b) {
if (!compareMethodReference(a, b))
return false;
if (a == null)
return true;
return compareTypes(a.DeclaringType, b.DeclaringType);
throw new NotImplementedException();
}
public static bool compareMethodReferenceSignature(MethodReference a, MethodReference b) {
if (ReferenceEquals(a, b))
return true;
if (a == null || b == null)
return false;
if (a.HasThis != b.HasThis || a.ExplicitThis != b.ExplicitThis)
return false;
if (a.CallingConvention != b.CallingConvention)
return false;
if (!compareTypes(a.MethodReturnType.ReturnType, b.MethodReturnType.ReturnType))
return false;
if (a.HasParameters != b.HasParameters)
return false;
if (a.HasParameters) {
if (a.Parameters.Count != b.Parameters.Count)
return false;
for (int i = 0; i < a.Parameters.Count; i++) {
if (!compareTypes(a.Parameters[i].ParameterType, b.Parameters[i].ParameterType))
return false;
}
}
if (a.HasGenericParameters != b.HasGenericParameters)
return false;
if (a.HasGenericParameters && a.GenericParameters.Count != b.GenericParameters.Count)
return false;
return true;
}
public static int methodReferenceSignatureHashCode(MethodReference a) {
if (a == null)
return 0;
int res = 0;
res += a.HasThis.GetHashCode();
res += a.ExplicitThis.GetHashCode();
res += a.CallingConvention.GetHashCode();
res += typeHashCode(a.MethodReturnType.ReturnType);
res += a.HasParameters.GetHashCode();
if (a.HasParameters) {
res += a.Parameters.Count.GetHashCode();
foreach (var param in a.Parameters)
res += typeHashCode(param.ParameterType);
}
res += a.HasGenericParameters.GetHashCode();
if (a.HasGenericParameters)
res += a.GenericParameters.Count.GetHashCode();
return res;
}
public static bool compareMethodReference(MethodReference a, MethodReference b) {
if (ReferenceEquals(a, b))
return true;
if (a == null || b == null)
return false;
if (a.Name != b.Name)
return false;
return compareMethodReferenceSignature(a, b);
}
public static int methodReferenceAndDeclaringTypeHashCode(MethodReference a) {
if (a == null)
return 0;
return methodReferenceHashCode(a) + typeReferenceHashCode(a.DeclaringType);
}
public static int methodReferenceHashCode(MethodReference a) {
if (a == null)
return 0;
int res = 0;
res += a.Name.GetHashCode();
res += methodReferenceSignatureHashCode(a);
return res;
}
public static bool comparePropertyReference(PropertyReference a, PropertyReference b) {
if (ReferenceEquals(a, b))
return true;
if (a == null || b == null)
return false;
if ((a.Parameters == null && b.Parameters != null) || (a.Parameters != null && b.Parameters == null))
return false;
if (a.Parameters != null) {
if (a.Parameters.Count != b.Parameters.Count)
return false;
for (int i = 0; i < a.Parameters.Count; i++) {
if (!compareTypes(a.Parameters[i].ParameterType, b.Parameters[i].ParameterType))
return false;
}
}
return a.Name == b.Name &&
compareTypes(a.PropertyType, b.PropertyType);
}
public static int propertyReferenceHashCode(PropertyReference a) {
if (a == null)
return 0;
int res = 0;
if (a.Parameters != null) {
res += a.Parameters.Count.GetHashCode();
foreach (var param in a.Parameters)
res += typeHashCode(param.ParameterType);
}
res += a.Name.GetHashCode();
res += typeHashCode(a.PropertyType);
return res;
public static bool compareFieldReference(FieldReference a, FieldReference b) {
throw new NotImplementedException();
}
public static bool compareTypes(TypeReference a, TypeReference b) {
if (ReferenceEquals(a, b))
return true;
if (a == null || b == null)
return false;
var atype = a.GetType();
var btype = b.GetType();
if (atype != btype) {
if ((atype == typeof(TypeReference) || atype == typeof(TypeDefinition)) &&
(btype == typeof(TypeReference) || btype == typeof(TypeDefinition)))
return compareTypeReferences(a, b);
return false;
}
var type = getMemberReferenceType(a);
switch (type) {
case CecilType.ArrayType:
return compareArrayTypes((ArrayType)a, (ArrayType)b);
case CecilType.ByReferenceType:
return compareByReferenceTypes((ByReferenceType)a, (ByReferenceType)b);
case CecilType.FunctionPointerType:
return compareFunctionPointerTypes((FunctionPointerType)a, (FunctionPointerType)b);
case CecilType.GenericInstanceType:
return compareGenericInstanceTypes((GenericInstanceType)a, (GenericInstanceType)b);
case CecilType.GenericParameter:
return compareGenericParameters((GenericParameter)a, (GenericParameter)b);
case CecilType.OptionalModifierType:
return compareOptionalModifierTypes((OptionalModifierType)a, (OptionalModifierType)b);
case CecilType.PinnedType:
return comparePinnedTypes((PinnedType)a, (PinnedType)b);
case CecilType.PointerType:
return comparePointerTypes((PointerType)a, (PointerType)b);
case CecilType.RequiredModifierType:
return compareRequiredModifierTypes((RequiredModifierType)a, (RequiredModifierType)b);
case CecilType.SentinelType:
return compareSentinelTypes((SentinelType)a, (SentinelType)b);
case CecilType.TypeDefinition:
return compareTypeDefinitions((TypeDefinition)a, (TypeDefinition)b);
case CecilType.TypeReference:
return compareTypeReferences((TypeReference)a, (TypeReference)b);
default:
throw new ApplicationException(string.Format("Unknown cecil type {0}", type));
}
}
public static int typeHashCode(TypeReference a) {
if (a == null)
return 0;
var type = getMemberReferenceType(a);
switch (type) {
case CecilType.ArrayType:
return arrayTypeHashCode((ArrayType)a);
case CecilType.ByReferenceType:
return byReferenceTypeHashCode((ByReferenceType)a);
case CecilType.FunctionPointerType:
return functionPointerTypeHashCode((FunctionPointerType)a);
case CecilType.GenericInstanceType:
return genericInstanceTypeHashCode((GenericInstanceType)a);
case CecilType.GenericParameter:
return genericParameterHashCode((GenericParameter)a);
case CecilType.OptionalModifierType:
return optionalModifierTypeHashCode((OptionalModifierType)a);
case CecilType.PinnedType:
return pinnedTypeHashCode((PinnedType)a);
case CecilType.PointerType:
return pointerTypeHashCode((PointerType)a);
case CecilType.RequiredModifierType:
return requiredModifierTypeHashCode((RequiredModifierType)a);
case CecilType.SentinelType:
return sentinelTypeHashCode((SentinelType)a);
case CecilType.TypeDefinition:
return typeDefinitionHashCode((TypeDefinition)a);
case CecilType.TypeReference:
return typeReferenceHashCode((TypeReference)a);
default:
throw new ApplicationException(string.Format("Unknown cecil type {0}", type));
}
}
static bool compareArrayTypes(ArrayType a, ArrayType b) {
if (a.Rank != b.Rank || a.IsVector != b.IsVector)
return false;
if (!a.IsVector) {
for (int i = 0; i < a.Dimensions.Count; i++) {
if (!compareArrayDimensions(a.Dimensions[i], b.Dimensions[i]))
return false;
}
}
return compareTypeSpecifications(a, b);
}
static int arrayTypeHashCode(ArrayType a) {
if (a == null)
return 0;
int res = 0;
res += a.Rank.GetHashCode();
res += a.IsVector.GetHashCode();
if (!a.IsVector) {
foreach (var dim in a.Dimensions)
res += arrayDimensionHashCode(dim);
}
res += typeSpecificationHashCode(a);
return res;
}
static bool compareArrayDimensions(ArrayDimension a, ArrayDimension b) {
return a.LowerBound == b.LowerBound && a.UpperBound == b.UpperBound;
}
static int arrayDimensionHashCode(ArrayDimension a) {
return a.LowerBound.GetHashCode() + a.UpperBound.GetHashCode();
}
static bool compareGenericInstanceTypes(GenericInstanceType a, GenericInstanceType b) {
if (a.HasGenericArguments != b.HasGenericArguments)
return false;
if (a.HasGenericArguments) {
if (a.GenericArguments.Count != b.GenericArguments.Count)
return false;
for (int i = 0; i < a.GenericArguments.Count; i++) {
if (!compareTypes(a.GenericArguments[i], b.GenericArguments[i]))
return false;
}
}
return compareTypeSpecifications(a, b);
}
static int genericInstanceTypeHashCode(GenericInstanceType a) {
if (a == null)
return 0;
int res = 0;
res += a.HasGenericArguments.GetHashCode();
if (a.HasGenericArguments) {
res += a.GenericArguments.Count.GetHashCode();
foreach (var arg in a.GenericArguments)
res += typeHashCode(arg);
}
res += typeSpecificationHashCode(a);
return res;
}
static bool comparePointerTypes(PointerType a, PointerType b) {
return compareTypeSpecifications(a, b);
}
static int pointerTypeHashCode(PointerType a) {
if (a == null)
return 0;
return typeSpecificationHashCode(a);
}
static bool compareByReferenceTypes(ByReferenceType a, ByReferenceType b) {
return compareTypeSpecifications(a, b);
}
static int byReferenceTypeHashCode(ByReferenceType a) {
if (a == null)
return 0;
return typeSpecificationHashCode(a);
}
static bool comparePinnedTypes(PinnedType a, PinnedType b) {
return compareTypeSpecifications(a, b);
}
static int pinnedTypeHashCode(PinnedType a) {
if (a == null)
return 0;
return typeSpecificationHashCode(a);
}
static bool compareFunctionPointerTypes(FunctionPointerType a, FunctionPointerType b) {
return compareMethodReference(a.function, b.function) &&
compareTypeSpecifications(a, b);
}
static int functionPointerTypeHashCode(FunctionPointerType a) {
if (a == null)
return 0;
return methodReferenceHashCode(a.function) + typeSpecificationHashCode(a);
}
static bool compareOptionalModifierTypes(OptionalModifierType a, OptionalModifierType b) {
return compareTypes(a.ModifierType, b.ModifierType) &&
compareTypeSpecifications(a, b);
}
static int optionalModifierTypeHashCode(OptionalModifierType a) {
if (a == null)
return 0;
return typeHashCode(a.ModifierType) + typeSpecificationHashCode(a);
}
static bool compareRequiredModifierTypes(RequiredModifierType a, RequiredModifierType b) {
return compareTypes(a.ModifierType, b.ModifierType) &&
compareTypeSpecifications(a, b);
}
static int requiredModifierTypeHashCode(RequiredModifierType a) {
if (a == null)
return 0;
return typeHashCode(a.ModifierType) + typeSpecificationHashCode(a);
}
static bool compareSentinelTypes(SentinelType a, SentinelType b) {
return compareTypeSpecifications(a, b);
}
static int sentinelTypeHashCode(SentinelType a) {
if (a == null)
return 0;
return typeSpecificationHashCode(a);
}
static bool compareTypeSpecifications(TypeSpecification a, TypeSpecification b) {
// It overrides everything of importance in TypeReference. The only thing to check
// is the ElementType.
return compareTypes(a.ElementType, b.ElementType);
}
static int typeSpecificationHashCode(TypeSpecification a) {
if (a == null)
return 0;
return typeHashCode(a.ElementType);
}
static bool compareTypeDefinitions(TypeDefinition a, TypeDefinition b) {
return compareTypeReferences(a, b);
}
static int typeDefinitionHashCode(TypeDefinition a) {
if (a == null)
return 0;
return typeReferenceHashCode(a);
}
static bool compareGenericParameters(GenericParameter a, GenericParameter b) {
return a.Position == b.Position &&
compareGenericParameterProvider(a.Owner, b.Owner);
}
static int genericParameterHashCode(GenericParameter a) {
if (a == null)
return 0;
return a.Position.GetHashCode() + genericParameterProviderHashCode(a.Owner);
}
// a and b must be either exactly a TypeReference or exactly a TypeDefinition
static bool compareTypeReferences(TypeReference a, TypeReference b) {
if ((a.GetType() != typeof(TypeReference) && a.GetType() != typeof(TypeDefinition)) ||
(b.GetType() != typeof(TypeReference) && b.GetType() != typeof(TypeDefinition)))
throw new ApplicationException("arg must be exactly of type TypeReference or TypeDefinition");
if (ReferenceEquals(a, b))
return true;
return a.Name == b.Name &&
a.Namespace == b.Namespace &&
compareTypes(a.DeclaringType, b.DeclaringType) &&
compareScope(a.Scope, b.Scope);
}
// a must be exactly a TypeReference or a TypeDefinition
static int typeReferenceHashCode(TypeReference a) {
if (a == null)
return 0;
if (a.GetType() != typeof(TypeReference) && a.GetType() != typeof(TypeDefinition))
throw new ApplicationException("arg must be exactly of type TypeReference or TypeDefinition");
int res = 0;
res += a.Name.GetHashCode();
res += a.Namespace.GetHashCode();
res += typeHashCode(a.DeclaringType);
res += scopeHashCode(a.Scope);
return res;
}
public static bool compareTypeReferenceSameVersion(TypeReference a, TypeReference b) {
if (ReferenceEquals(a, b))
return true;
if (a == null || b == null)
return false;
if ((a.GetType() != typeof(TypeReference) && a.GetType() != typeof(TypeDefinition)) ||
(b.GetType() != typeof(TypeReference) && b.GetType() != typeof(TypeDefinition)))
throw new ApplicationException("arg must be exactly of type TypeReference or TypeDefinition");
return a.Name == b.Name &&
a.Namespace == b.Namespace &&
compareTypeReferenceSameVersion(a.DeclaringType, b.DeclaringType) &&
compareScopeSameVersion(a.Scope, b.Scope);
}
public static int typeReferenceHashCodeSameVersion(TypeReference a) {
if (a == null)
return 0;
if (a.GetType() != typeof(TypeReference) && a.GetType() != typeof(TypeDefinition))
throw new ApplicationException("arg must be exactly of type TypeReference or TypeDefinition");
int res = 0;
res += a.Name.GetHashCode();
res += a.Namespace.GetHashCode();
res += typeReferenceHashCodeSameVersion(a.DeclaringType);
res += scopeHashCodeSameVersion(a.Scope);
return res;
}
static bool compareGenericParameterProvider(IGenericParameterProvider a, IGenericParameterProvider b) {
if (ReferenceEquals(a, b))
return true;
if (a == null || b == null)
return false;
if (a is TypeReference && b is TypeReference)
return compareTypes((TypeReference)a, (TypeReference)b);
if (a is MethodReference && b is MethodReference)
return true;
return false;
}
static int genericParameterProviderHashCode(IGenericParameterProvider a) {
if (a == null)
return 0;
if (a is TypeReference)
return typeHashCode((TypeReference)a);
if (a is MethodReference)
return 0;
throw new ApplicationException(string.Format("Unknown IGenericParameterProvider type {0}", a.GetType()));
throw new NotImplementedException();
}
}
}
#endif

View File

@ -19,7 +19,7 @@
using System;
using System.Collections.Generic;
using Mono.Cecil.Cil;
using dot10.DotNet.Emit;
namespace de4dot.blocks {
// A normal branch may not transfer out of a protected block (try block), filter handler,

View File

@ -17,8 +17,8 @@
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
*/
using Mono.Cecil;
using Mono.Cecil.Cil;
using dot10.DotNet;
using dot10.DotNet.Emit;
namespace de4dot.blocks {
// Contains the filter handler block and the catch handler block.
@ -27,10 +27,10 @@ namespace de4dot.blocks {
HandlerBlock handlerBlock = new HandlerBlock();
// State for an ExceptionHandler instance
TypeReference catchType;
ITypeDefOrRef catchType;
ExceptionHandlerType handlerType;
public TypeReference CatchType {
public ITypeDefOrRef CatchType {
get { return catchType; }
}

View File

@ -17,6 +17,7 @@
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
*/
#if PORT
using System;
using Mono.Cecil;
@ -26,35 +27,7 @@ namespace de4dot.blocks {
if (a == null)
return null;
var type = MemberReferenceHelper.getMemberReferenceType(a);
switch (type) {
case CecilType.ArrayType:
return updateArrayType((ArrayType)a);
case CecilType.ByReferenceType:
return updateByReferenceType((ByReferenceType)a);
case CecilType.FunctionPointerType:
return updateFunctionPointerType((FunctionPointerType)a);
case CecilType.GenericInstanceType:
return updateGenericInstanceType((GenericInstanceType)a);
case CecilType.GenericParameter:
return updateGenericParameter((GenericParameter)a);
case CecilType.OptionalModifierType:
return updateOptionalModifierType((OptionalModifierType)a);
case CecilType.PinnedType:
return updatePinnedType((PinnedType)a);
case CecilType.PointerType:
return updatePointerType((PointerType)a);
case CecilType.RequiredModifierType:
return updateRequiredModifierType((RequiredModifierType)a);
case CecilType.SentinelType:
return updateSentinelType((SentinelType)a);
case CecilType.TypeDefinition:
return updateTypeDefinition((TypeDefinition)a);
case CecilType.TypeReference:
return updateTypeReference((TypeReference)a);
default:
throw new ApplicationException(string.Format("Unknown cecil type {0}", type));
}
throw new NotImplementedException();
}
protected virtual ArrayType updateArrayType(ArrayType a) {
@ -116,3 +89,4 @@ namespace de4dot.blocks {
}
}
}
#endif

View File

@ -1,4 +1,23 @@
using System.Collections.Generic;
/*
Copyright (C) 2011-2012 de4dot@gmail.com
This file is part of de4dot.
de4dot is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
de4dot is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
*/
using System.Collections.Generic;
namespace de4dot.blocks {
internal delegate TResult Func<TResult>();

View File

@ -40,6 +40,7 @@
<Compile Include="BlocksSorter.cs" />
<Compile Include="cflow\BlockCflowDeobfuscator.cs" />
<Compile Include="cflow\BlockDeobfuscator.cs" />
<Compile Include="cflow\BlocksCflowDeobfuscator.cs" />
<Compile Include="cflow\BranchEmulator.cs" />
<Compile Include="cflow\CachedCflowDeobfuscator.cs" />
<Compile Include="cflow\CflowDeobfuscator.cs" />
@ -60,16 +61,19 @@
<Compile Include="cflow\Value.cs" />
<Compile Include="cflow\ValueStack.cs" />
<Compile Include="CodeGenerator.cs" />
<Compile Include="cflow\BlocksCflowDeobfuscator.cs" />
<Compile Include="DeadBlocksRemover.cs" />
<Compile Include="DotNetUtils.cs" />
<Compile Include="DumpedMethod.cs" />
<Compile Include="DumpedMethods.cs" />
<Compile Include="FilterHandlerBlock.cs" />
<Compile Include="ForwardScanOrder.cs" />
<Compile Include="GenericArgsSubstitutor.cs" />
<Compile Include="HandlerBlock.cs" />
<Compile Include="Instr.cs" />
<Compile Include="InstructionListParser.cs" />
<Compile Include="MemberRefInstance.cs" />
<Compile Include="MemberDefDict.cs" />
<Compile Include="MemberReferenceHelper.cs" />
<Compile Include="MemberRefInstance.cs" />
<Compile Include="MethodBlocks.cs" />
<Compile Include="PE\Cor20Header.cs" />
<Compile Include="PE\DataDirectory.cs" />
@ -95,9 +99,9 @@
<Compile Include="Utils.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\cecil\Mono.Cecil.csproj">
<Project>{D68133BD-1E63-496E-9EDE-4FBDBF77B486}</Project>
<Name>Mono.Cecil</Name>
<ProjectReference Include="..\dot10\src\dot10.csproj">
<Project>{FDFC1237-143F-4919-8318-4926901F4639}</Project>
<Name>dot10</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>

View File

@ -18,7 +18,7 @@
*/
using System;
using Mono.Cecil.Cil;
using dot10.DotNet.Emit;
namespace de4dot.blocks.cflow {
class BlockCflowDeobfuscator : BlockDeobfuscator, IBranchHandler {
@ -33,7 +33,7 @@ namespace de4dot.blocks.cflow {
protected override bool deobfuscate(Block block) {
this.block = block;
if (!DotNetUtils.isConditionalBranch(block.LastInstr.OpCode.Code) && block.LastInstr.OpCode.Code != Code.Switch)
if (!block.LastInstr.isConditionalBranch() && block.LastInstr.OpCode.Code != Code.Switch)
return false;
instructionEmulator.init(blocks);

View File

@ -18,8 +18,7 @@
*/
using System.Collections.Generic;
using Mono.Cecil;
using Mono.Cecil.Cil;
using dot10.DotNet.Emit;
namespace de4dot.blocks.cflow {
public class BlocksCflowDeobfuscator {

View File

@ -17,7 +17,7 @@
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
*/
using Mono.Cecil.Cil;
using dot10.DotNet.Emit;
namespace de4dot.blocks.cflow {
public interface IBranchHandler {

View File

@ -18,14 +18,14 @@
*/
using System.Collections.Generic;
using Mono.Cecil;
using Mono.Cecil.Cil;
using dot10.DotNet;
using dot10.DotNet.Emit;
namespace de4dot.blocks.cflow {
// Only deobfuscates a method once. A copy of the method (now deobfuscated) is returned.
public class CachedCflowDeobfuscator {
BlocksCflowDeobfuscator cflowDeobfuscator = new BlocksCflowDeobfuscator();
Dictionary<MethodDefinition, MethodDefinition> deobfuscated = new Dictionary<MethodDefinition, MethodDefinition>();
Dictionary<MethodDef, MethodDef> deobfuscated = new Dictionary<MethodDef, MethodDef>();
public CachedCflowDeobfuscator() {
}
@ -43,8 +43,8 @@ namespace de4dot.blocks.cflow {
cflowDeobfuscator.add(blocksDeobfuscator);
}
public MethodDefinition deobfuscate(MethodDefinition method) {
MethodDefinition deobfuscatedMethod;
public MethodDef deobfuscate(MethodDef method) {
MethodDef deobfuscatedMethod;
if (deobfuscated.TryGetValue(method, out deobfuscatedMethod))
return deobfuscatedMethod;

View File

@ -18,8 +18,8 @@
*/
using System.Collections.Generic;
using Mono.Cecil;
using Mono.Cecil.Cil;
using dot10.DotNet;
using dot10.DotNet.Emit;
namespace de4dot.blocks.cflow {
public class CflowDeobfuscator : ICflowDeobfuscator {
@ -32,18 +32,18 @@ namespace de4dot.blocks.cflow {
cflowDeobfuscator.add(blocksDeobfuscator);
}
public void deobfuscate(MethodDefinition method) {
public void deobfuscate(MethodDef method) {
deobfuscate(method, (blocks) => {
cflowDeobfuscator.init(blocks);
cflowDeobfuscator.deobfuscate();
});
}
static bool hasNonEmptyBody(MethodDefinition method) {
static bool hasNonEmptyBody(MethodDef method) {
return method.Body != null && method.Body.Instructions.Count > 0;
}
void deobfuscate(MethodDefinition method, Action<Blocks> handler) {
void deobfuscate(MethodDef method, Action<Blocks> handler) {
if (hasNonEmptyBody(method)) {
var blocks = new Blocks(method);

View File

@ -19,19 +19,19 @@
using System;
using System.Collections.Generic;
using Mono.Cecil;
using Mono.Cecil.Cil;
using dot10.DotNet;
using dot10.DotNet.Emit;
using de4dot.blocks;
namespace de4dot.blocks.cflow {
// Very simple constants folder which is all that's needed at the moment
class ConstantsFolder : BlockDeobfuscator {
InstructionEmulator instructionEmulator = new InstructionEmulator();
List<ParameterDefinition> args;
IList<Parameter> args;
protected override void init(List<Block> allBlocks) {
base.init(allBlocks);
args = DotNetUtils.getParameters(blocks.Method);
args = blocks.Method.Parameters;
}
protected override bool deobfuscate(Block block) {
@ -49,7 +49,7 @@ namespace de4dot.blocks.cflow {
case Code.Ldarg_2:
case Code.Ldarg_3:
case Code.Ldarg_S:
changed |= fixLoadInstruction(block, i, instructionEmulator.getArg(DotNetUtils.getParameter(args, instr.Instruction)));
changed |= fixLoadInstruction(block, i, instructionEmulator.getArg(instr.Instruction.GetParameter(args)));
break;
case Code.Ldloc:
@ -58,17 +58,17 @@ namespace de4dot.blocks.cflow {
case Code.Ldloc_2:
case Code.Ldloc_3:
case Code.Ldloc_S:
changed |= fixLoadInstruction(block, i, instructionEmulator.getLocal(DotNetUtils.getLocalVar(blocks.Locals, instr.Instruction)));
changed |= fixLoadInstruction(block, i, instructionEmulator.getLocal(instr.Instruction.GetLocal(blocks.Locals)));
break;
case Code.Ldarga:
case Code.Ldarga_S:
instructionEmulator.makeArgUnknown((ParameterDefinition)instr.Operand);
instructionEmulator.makeArgUnknown((Parameter)instr.Operand);
break;
case Code.Ldloca:
case Code.Ldloca_S:
instructionEmulator.makeLocalUnknown((VariableDefinition)instr.Operand);
instructionEmulator.makeLocalUnknown((Local)instr.Operand);
break;
}
@ -89,7 +89,7 @@ namespace de4dot.blocks.cflow {
var intValue = (Int32Value)value;
if (!intValue.allBitsValid())
return false;
block.Instructions[index] = new Instr(DotNetUtils.createLdci4(intValue.value));
block.Instructions[index] = new Instr(Instruction.CreateLdcI4(intValue.value));
return true;
}
else if (value.isInt64()) {

View File

@ -18,7 +18,7 @@
*/
using System.Collections.Generic;
using Mono.Cecil.Cil;
using dot10.DotNet.Emit;
namespace de4dot.blocks.cflow {
// Removes dead code that is the result of one of our optimizations, or created by the
@ -185,7 +185,7 @@ namespace de4dot.blocks.cflow {
case Code.Ldc_I8:
case Code.Ldc_R4:
case Code.Ldc_R8:
case Code.Ldelem_Any:
case Code.Ldelem:
case Code.Ldelem_I:
case Code.Ldelem_I1:
case Code.Ldelem_I2:
@ -237,7 +237,6 @@ namespace de4dot.blocks.cflow {
case Code.Mul_Ovf_Un:
case Code.Neg:
case Code.Newarr:
case Code.No:
case Code.Nop:
case Code.Not:
case Code.Or:
@ -257,7 +256,7 @@ namespace de4dot.blocks.cflow {
case Code.Sub_Ovf:
case Code.Sub_Ovf_Un:
case Code.Switch:
case Code.Tail:
case Code.Tailcall:
case Code.Throw:
case Code.Unaligned:
case Code.Unbox:
@ -276,7 +275,7 @@ namespace de4dot.blocks.cflow {
case Code.Newobj:
case Code.Starg:
case Code.Starg_S:
case Code.Stelem_Any:
case Code.Stelem:
case Code.Stelem_I:
case Code.Stelem_I1:
case Code.Stelem_I2:
@ -380,7 +379,7 @@ namespace de4dot.blocks.cflow {
}
static void calculateStackUsage(Instruction instr, bool methodHasReturnValue, out int pushes, out int pops) {
DotNetUtils.calculateStackUsage(instr, false, out pushes, out pops);
instr.CalculateStackUsage(false, out pushes, out pops);
}
}
}

View File

@ -19,7 +19,7 @@
using System;
using System.Collections.Generic;
using Mono.Cecil.Cil;
using dot10.DotNet.Emit;
namespace de4dot.blocks.cflow {
// Removes dead stores by replacing the stloc with a pop. Other optimizations will notice it's
@ -80,7 +80,7 @@ namespace de4dot.blocks.cflow {
void findLoadStores() {
foreach (var block in allBlocks) {
foreach (var instr in block.Instructions) {
VariableDefinition local;
Local local;
AccessFlags flags;
switch (instr.OpCode.Code) {
case Code.Ldloc:
@ -105,7 +105,7 @@ namespace de4dot.blocks.cflow {
case Code.Ldloca_S:
case Code.Ldloca:
local = instr.Operand as VariableDefinition;
local = instr.Operand as Local;
flags = AccessFlags.Read | AccessFlags.Write;
break;
@ -128,7 +128,7 @@ namespace de4dot.blocks.cflow {
var instructions = block.Instructions;
for (int i = 0; i < instructions.Count; i++) {
var instr = instructions[i];
VariableDefinition local;
Local local;
switch (instr.OpCode.Code) {
case Code.Stloc:
case Code.Stloc_S:

View File

@ -17,10 +17,10 @@
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
*/
using Mono.Cecil;
using dot10.DotNet;
namespace de4dot.blocks.cflow {
public interface ICflowDeobfuscator {
void deobfuscate(MethodDefinition method);
void deobfuscate(MethodDef method);
}
}

View File

@ -19,29 +19,26 @@
using System;
using System.Collections.Generic;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Cecil.Metadata;
using dot10.DotNet;
using dot10.DotNet.Emit;
namespace de4dot.blocks.cflow {
public class InstructionEmulator {
ValueStack valueStack = new ValueStack();
Dictionary<Value, bool> protectedStackValues = new Dictionary<Value, bool>();
IList<ParameterDefinition> parameterDefinitions;
IList<VariableDefinition> variableDefinitions;
IList<Parameter> parameterDefs;
IList<Local> localDefs;
List<Value> args = new List<Value>();
List<Value> locals = new List<Value>();
int argBase;
MethodDefinition prev_method;
MethodDef prev_method;
List<Value> cached_args = new List<Value>();
List<Value> cached_locals = new List<Value>();
int cached_argBase;
public InstructionEmulator() {
}
public InstructionEmulator(MethodDefinition method) {
public InstructionEmulator(MethodDef method) {
init(method);
}
@ -49,9 +46,9 @@ namespace de4dot.blocks.cflow {
init(blocks.Method);
}
public void init(MethodDefinition method) {
this.parameterDefinitions = method.Parameters;
this.variableDefinitions = method.Body.Variables;
public void init(MethodDef method) {
this.parameterDefs = method.Parameters;
this.localDefs = method.Body.LocalList;
valueStack.init();
protectedStackValues.Clear();
@ -59,20 +56,14 @@ namespace de4dot.blocks.cflow {
prev_method = method;
cached_args.Clear();
cached_argBase = 0;
if (method.HasImplicitThis) {
cached_argBase = 1;
cached_args.Add(new UnknownValue());
}
for (int i = 0; i < parameterDefinitions.Count; i++)
cached_args.Add(getUnknownValue(parameterDefinitions[i].ParameterType));
for (int i = 0; i < parameterDefs.Count; i++)
cached_args.Add(getUnknownValue(parameterDefs[i].Type));
cached_locals.Clear();
for (int i = 0; i < variableDefinitions.Count; i++)
cached_locals.Add(getUnknownValue(variableDefinitions[i].VariableType));
for (int i = 0; i < localDefs.Count; i++)
cached_locals.Add(getUnknownValue(localDefs[i].Type));
}
argBase = cached_argBase;
args.Clear();
args.AddRange(cached_args);
locals.Clear();
@ -83,10 +74,14 @@ namespace de4dot.blocks.cflow {
protectedStackValues[value] = true;
}
static Value getUnknownValue(TypeReference typeReference) {
if (typeReference == null)
static Value getUnknownValue(ITypeDefOrRef type) {
return getUnknownValue(type.ToTypeSig(false));
}
static Value getUnknownValue(TypeSig type) {
if (type == null)
return new UnknownValue();
switch (typeReference.EType) {
switch (type.ElementType) {
case ElementType.Boolean: return Int32Value.createUnknownBool();
case ElementType.I1: return Int32Value.createUnknown();
case ElementType.U1: return Int32Value.createUnknownUInt8();
@ -100,13 +95,13 @@ namespace de4dot.blocks.cflow {
return new UnknownValue();
}
Value truncateValue(Value value, TypeReference typeReference) {
if (typeReference == null)
Value truncateValue(Value value, TypeSig type) {
if (type == null)
return value;
if (protectedStackValues.ContainsKey(value))
return value;
switch (typeReference.EType) {
switch (type.ElementType) {
case ElementType.Boolean:
if (value.isInt32())
return ((Int32Value)value).toBoolean();
@ -167,27 +162,26 @@ namespace de4dot.blocks.cflow {
return getValue(args, i);
}
int index(ParameterDefinition arg) {
return arg.Sequence;
public Value getArg(Parameter arg) {
if (arg == null)
return new UnknownValue();
return getArg(arg.Index);
}
public Value getArg(ParameterDefinition arg) {
return getArg(index(arg));
}
TypeReference getArgType(int index) {
index -= argBase;
if (0 <= index && index < parameterDefinitions.Count)
return parameterDefinitions[index].ParameterType;
TypeSig getArgType(int index) {
if (0 <= index && index < parameterDefs.Count)
return parameterDefs[index].Type;
return null;
}
public void setArg(ParameterDefinition arg, Value value) {
setArg(index(arg), value);
public void setArg(Parameter arg, Value value) {
if (arg != null)
setArg(arg.Index, value);
}
public void makeArgUnknown(ParameterDefinition arg) {
setArg(arg, getUnknownArg(index(arg)));
public void makeArgUnknown(Parameter arg) {
if (arg != null)
setArg(arg, getUnknownArg(arg.Index));
}
void setArg(int index, Value value) {
@ -203,26 +197,30 @@ namespace de4dot.blocks.cflow {
return getValue(locals, i);
}
public Value getLocal(VariableDefinition local) {
public Value getLocal(Local local) {
if (local == null)
return new UnknownValue();
return getLocal(local.Index);
}
public void setLocal(VariableDefinition local, Value value) {
setLocal(local.Index, value);
public void setLocal(Local local, Value value) {
if (local != null)
setLocal(local.Index, value);
}
public void makeLocalUnknown(VariableDefinition local) {
setLocal(local.Index, getUnknownLocal(local.Index));
public void makeLocalUnknown(Local local) {
if (local != null)
setLocal(local.Index, getUnknownLocal(local.Index));
}
void setLocal(int index, Value value) {
if (0 <= index && index < locals.Count)
locals[index] = truncateValue(value, variableDefinitions[index].VariableType);
locals[index] = truncateValue(value, localDefs[index].Type);
}
Value getUnknownLocal(int index) {
if (0 <= index && index < variableDefinitions.Count)
return getUnknownValue(variableDefinitions[index].VariableType);
if (0 <= index && index < localDefs.Count)
return getUnknownValue(localDefs[index].Type);
return new UnknownValue();
}
@ -255,31 +253,31 @@ namespace de4dot.blocks.cflow {
public void emulate(Instruction instr) {
switch (instr.OpCode.Code) {
case Code.Starg:
case Code.Starg_S: emulate_Starg((ParameterDefinition)instr.Operand); break;
case Code.Starg_S: emulate_Starg((Parameter)instr.Operand); break;
case Code.Stloc:
case Code.Stloc_S: emulate_Stloc(((VariableDefinition)instr.Operand).Index); break;
case Code.Stloc_S: emulate_Stloc((Local)instr.Operand); break;
case Code.Stloc_0: emulate_Stloc(0); break;
case Code.Stloc_1: emulate_Stloc(1); break;
case Code.Stloc_2: emulate_Stloc(2); break;
case Code.Stloc_3: emulate_Stloc(3); break;
case Code.Ldarg:
case Code.Ldarg_S: valueStack.push(getArg((ParameterDefinition)instr.Operand)); break;
case Code.Ldarg_S: valueStack.push(getArg((Parameter)instr.Operand)); break;
case Code.Ldarg_0: valueStack.push(getArg(0)); break;
case Code.Ldarg_1: valueStack.push(getArg(1)); break;
case Code.Ldarg_2: valueStack.push(getArg(2)); break;
case Code.Ldarg_3: valueStack.push(getArg(3)); break;
case Code.Ldloc:
case Code.Ldloc_S: valueStack.push(getLocal((VariableDefinition)instr.Operand)); break;
case Code.Ldloc_S: valueStack.push(getLocal((Local)instr.Operand)); break;
case Code.Ldloc_0: valueStack.push(getLocal(0)); break;
case Code.Ldloc_1: valueStack.push(getLocal(1)); break;
case Code.Ldloc_2: valueStack.push(getLocal(2)); break;
case Code.Ldloc_3: valueStack.push(getLocal(3)); break;
case Code.Ldarga:
case Code.Ldarga_S: emulate_Ldarga((ParameterDefinition)instr.Operand); break;
case Code.Ldarga_S: emulate_Ldarga((Parameter)instr.Operand); break;
case Code.Ldloca:
case Code.Ldloca_S: emulate_Ldloca(((VariableDefinition)instr.Operand).Index); break;
case Code.Ldloca_S: emulate_Ldloca((Local)instr.Operand); break;
case Code.Dup: valueStack.copyTop(); break;
@ -369,7 +367,7 @@ namespace de4dot.blocks.cflow {
case Code.Ldelem_U1: valueStack.pop(2); valueStack.push(Int32Value.createUnknownUInt8()); break;
case Code.Ldelem_U2: valueStack.pop(2); valueStack.push(Int32Value.createUnknownUInt16()); break;
case Code.Ldelem_U4: valueStack.pop(2); valueStack.push(Int32Value.createUnknown()); break;
case Code.Ldelem_Any:valueStack.pop(2); valueStack.push(getUnknownValue(instr.Operand as TypeReference)); break;
case Code.Ldelem: valueStack.pop(2); valueStack.push(getUnknownValue(instr.Operand as ITypeDefOrRef)); break;
case Code.Ldind_I1: valueStack.pop(); valueStack.push(Int32Value.createUnknown()); break;
case Code.Ldind_I2: valueStack.pop(); valueStack.push(Int32Value.createUnknown()); break;
@ -457,7 +455,6 @@ namespace de4dot.blocks.cflow {
case Code.Mkrefany:
case Code.Newarr:
case Code.Newobj:
case Code.No:
case Code.Nop:
case Code.Pop:
case Code.Readonly:
@ -465,7 +462,7 @@ namespace de4dot.blocks.cflow {
case Code.Refanyval:
case Code.Ret:
case Code.Rethrow:
case Code.Stelem_Any:
case Code.Stelem:
case Code.Stelem_I:
case Code.Stelem_I1:
case Code.Stelem_I2:
@ -486,7 +483,7 @@ namespace de4dot.blocks.cflow {
case Code.Stobj:
case Code.Stsfld:
case Code.Switch:
case Code.Tail:
case Code.Tailcall:
case Code.Throw:
case Code.Unaligned:
case Code.Volatile:
@ -498,7 +495,7 @@ namespace de4dot.blocks.cflow {
void updateStack(Instruction instr) {
int pushes, pops;
DotNetUtils.calculateStackUsage(instr, false, out pushes, out pops);
instr.CalculateStackUsage(out pushes, out pops);
if (pops == -1)
valueStack.clear();
else {
@ -847,38 +844,46 @@ namespace de4dot.blocks.cflow {
valueStack.pushUnknown();
}
void emulate_Starg(ParameterDefinition arg) {
setArg(index(arg), valueStack.pop());
void emulate_Starg(Parameter arg) {
setArg(arg == null ? -1 : arg.Index, valueStack.pop());
}
void emulate_Stloc(Local local) {
emulate_Stloc(local == null ? -1 : local.Index);
}
void emulate_Stloc(int index) {
setLocal(index, valueStack.pop());
}
void emulate_Ldarga(ParameterDefinition arg) {
void emulate_Ldarga(Parameter arg) {
valueStack.pushUnknown();
makeArgUnknown(arg);
}
void emulate_Ldloca(Local local) {
emulate_Ldloca(local == null ? -1 : local.Index);
}
void emulate_Ldloca(int index) {
valueStack.pushUnknown();
setLocal(index, getUnknownLocal(index));
}
void emulate_Call(Instruction instr) {
emulate_Call(instr, (MethodReference)instr.Operand);
emulate_Call(instr, (IMethod)instr.Operand);
}
void emulate_Callvirt(Instruction instr) {
emulate_Call(instr, (MethodReference)instr.Operand);
emulate_Call(instr, (IMethod)instr.Operand);
}
void emulate_Call(Instruction instr, MethodReference method) {
void emulate_Call(Instruction instr, IMethod method) {
int pushes, pops;
DotNetUtils.calculateStackUsage(instr, false, out pushes, out pops);
instr.CalculateStackUsage(out pushes, out pops);
valueStack.pop(pops);
if (pushes == 1)
valueStack.push(getUnknownValue(method.MethodReturnType.ReturnType));
valueStack.push(getUnknownValue(method.MethodSig.GetRetType()));
else
valueStack.push(pushes);
}
@ -903,16 +908,16 @@ namespace de4dot.blocks.cflow {
void emulate_Ldfld(Instruction instr) {
var val1 = valueStack.pop();
emulateLoadField(instr.Operand as FieldReference);
emulateLoadField(instr.Operand as IField);
}
void emulate_Ldsfld(Instruction instr) {
emulateLoadField(instr.Operand as FieldReference);
emulateLoadField(instr.Operand as IField);
}
void emulateLoadField(FieldReference fieldReference) {
if (fieldReference != null)
valueStack.push(getUnknownValue(fieldReference.FieldType));
void emulateLoadField(IField field) {
if (field != null)
valueStack.push(getUnknownValue(field.FieldSig.GetFieldType()));
else
valueStack.pushUnknown();
}

View File

@ -18,8 +18,8 @@
*/
using System.Collections.Generic;
using Mono.Cecil;
using Mono.Cecil.Cil;
using dot10.DotNet;
using dot10.DotNet.Emit;
namespace de4dot.blocks.cflow {
public class MethodCallInliner : MethodCallInlinerBase {
@ -40,12 +40,12 @@ namespace de4dot.blocks.cflow {
return changed;
}
protected virtual bool canInline(MethodDefinition method) {
protected virtual bool canInline(MethodDef method) {
if (method.GenericParameters.Count > 0)
return false;
if (method == blocks.Method)
return false;
if (!MemberReferenceHelper.compareTypes(method.DeclaringType, blocks.Method.DeclaringType))
if (!new SigComparer().Equals(method.DeclaringType, blocks.Method.DeclaringType))
return false;
if (method.IsStatic)
@ -56,7 +56,7 @@ namespace de4dot.blocks.cflow {
}
bool inlineMethod(Instruction callInstr, int instrIndex) {
var methodToInline = callInstr.Operand as MethodDefinition;
var methodToInline = callInstr.Operand as MethodDef;
if (methodToInline == null)
return false;
@ -113,10 +113,10 @@ namespace de4dot.blocks.cflow {
}
}
protected override bool isCompatibleType(int paramIndex, TypeReference origType, TypeReference newType) {
if (MemberReferenceHelper.compareTypes(origType, newType))
protected override bool isCompatibleType(int paramIndex, IType origType, IType newType) {
if (new SigComparer(SigComparerOptions.IgnoreModifiers).Equals(origType, newType))
return true;
if (newType.IsValueType || origType.IsValueType)
if (isValueType(newType) || isValueType(origType))
return false;
return newType.FullName == "System.Object";
}

View File

@ -18,8 +18,8 @@
*/
using System.Collections.Generic;
using Mono.Cecil;
using Mono.Cecil.Cil;
using dot10.DotNet;
using dot10.DotNet.Emit;
namespace de4dot.blocks.cflow {
public abstract class MethodCallInlinerBase : IBlocksDeobfuscator {
@ -29,6 +29,7 @@ namespace de4dot.blocks.cflow {
protected Blocks blocks;
protected Block block;
int iteration;
AccessChecker accessChecker;
public bool ExecuteOnNoChange { get; set; }
@ -60,7 +61,7 @@ namespace de4dot.blocks.cflow {
this.patchIndex = patchIndex;
this.afterIndex = afterIndex;
this.lastInstr = lastInstr;
this.clonedInstr = new Instr(DotNetUtils.clone(lastInstr));
this.clonedInstr = new Instr(lastInstr.Clone());
}
public void patch(Block block) {
@ -68,7 +69,7 @@ namespace de4dot.blocks.cflow {
}
}
protected bool inlineLoadMethod(int patchIndex, MethodDefinition methodToInline, Instruction loadInstr, int instrIndex) {
protected bool inlineLoadMethod(int patchIndex, MethodDef methodToInline, Instruction loadInstr, int instrIndex) {
if (!isReturn(methodToInline, instrIndex))
return false;
@ -76,19 +77,19 @@ namespace de4dot.blocks.cflow {
for (int i = 0; i < methodArgsCount; i++)
block.insert(patchIndex++, Instruction.Create(OpCodes.Pop));
block.Instructions[patchIndex] = new Instr(DotNetUtils.clone(loadInstr));
block.Instructions[patchIndex] = new Instr(loadInstr.Clone());
return true;
}
protected bool inlineOtherMethod(int patchIndex, MethodDefinition methodToInline, Instruction instr, int instrIndex) {
protected bool inlineOtherMethod(int patchIndex, MethodDef methodToInline, Instruction instr, int instrIndex) {
return inlineOtherMethod(patchIndex, methodToInline, instr, instrIndex, 0);
}
protected bool inlineOtherMethod(int patchIndex, MethodDefinition methodToInline, Instruction instr, int instrIndex, int popLastArgs) {
protected bool inlineOtherMethod(int patchIndex, MethodDef methodToInline, Instruction instr, int instrIndex, int popLastArgs) {
return patchMethod(methodToInline, tryInlineOtherMethod(patchIndex, methodToInline, instr, instrIndex, popLastArgs));
}
protected bool patchMethod(MethodDefinition methodToInline, InstructionPatcher patcher) {
protected bool patchMethod(MethodDef methodToInline, InstructionPatcher patcher) {
if (patcher == null)
return false;
@ -99,11 +100,11 @@ namespace de4dot.blocks.cflow {
return true;
}
protected InstructionPatcher tryInlineOtherMethod(int patchIndex, MethodDefinition methodToInline, Instruction instr, int instrIndex) {
protected InstructionPatcher tryInlineOtherMethod(int patchIndex, MethodDef methodToInline, Instruction instr, int instrIndex) {
return tryInlineOtherMethod(patchIndex, methodToInline, instr, instrIndex, 0);
}
protected InstructionPatcher tryInlineOtherMethod(int patchIndex, MethodDefinition methodToInline, Instruction instr, int instrIndex, int popLastArgs) {
protected InstructionPatcher tryInlineOtherMethod(int patchIndex, MethodDef methodToInline, Instruction instr, int instrIndex, int popLastArgs) {
int loadIndex = 0;
int methodArgsCount = DotNetUtils.getArgsCount(methodToInline);
bool foundLdarga = false;
@ -128,7 +129,7 @@ namespace de4dot.blocks.cflow {
if (!isLdarg)
break;
if (DotNetUtils.getArgIndex(instr) != loadIndex)
if (instr.GetParameterIndex() != loadIndex)
return null;
loadIndex++;
instr = DotNetUtils.getInstruction(methodToInline.Body.Instructions, ref instrIndex);
@ -140,38 +141,44 @@ namespace de4dot.blocks.cflow {
if (foundLdarga)
return null;
var callInstr = instr;
var calledMethod = callInstr.Operand as MethodReference;
var calledMethod = callInstr.Operand as IMethod;
if (calledMethod == null)
return null;
if (!isCompatibleType(-1, calledMethod.MethodReturnType.ReturnType, methodToInline.MethodReturnType.ReturnType))
if (!isCompatibleType(-1, calledMethod.MethodSig.RetType, methodToInline.MethodSig.RetType))
return null;
if (!checkSameMethods(calledMethod, methodToInline, popLastArgs))
return null;
if (!hasAccessTo(instr.Operand))
return null;
return new InstructionPatcher(patchIndex, instrIndex, callInstr);
}
else if (instr.OpCode.Code == Code.Newobj) {
if (foundLdarga)
return null;
var newobjInstr = instr;
var ctor = newobjInstr.Operand as MethodReference;
var ctor = newobjInstr.Operand as IMethod;
if (ctor == null)
return null;
if (!isCompatibleType(-1, ctor.DeclaringType, methodToInline.MethodReturnType.ReturnType))
if (!isCompatibleType(-1, ctor.DeclaringType, methodToInline.MethodSig.RetType))
return null;
var methodArgs = DotNetUtils.getArgs(methodToInline);
var methodArgs = methodToInline.Parameters;
var calledMethodArgs = DotNetUtils.getArgs(ctor);
if (methodArgs.Count + 1 - popLastArgs != calledMethodArgs.Count)
return null;
for (int i = 1; i < calledMethodArgs.Count; i++) {
if (!isCompatibleType(i, calledMethodArgs[i], methodArgs[i - 1]))
if (!isCompatibleType(i, calledMethodArgs[i], methodArgs[i - 1].Type))
return null;
}
if (!hasAccessTo(instr.Operand))
return null;
return new InstructionPatcher(patchIndex, instrIndex, newobjInstr);
}
else if (instr.OpCode.Code == Code.Ldfld || instr.OpCode.Code == Code.Ldflda ||
@ -180,31 +187,46 @@ namespace de4dot.blocks.cflow {
if (methodArgsCount != 1)
return null;
if (!hasAccessTo(instr.Operand))
return null;
return new InstructionPatcher(patchIndex, instrIndex, ldInstr);
}
return null;
}
protected virtual bool isReturn(MethodDefinition methodToInline, int instrIndex) {
bool hasAccessTo(object operand) {
if (operand == null)
return false;
accessChecker.UserType = blocks.Method.DeclaringType;
return accessChecker.CanAccess(operand) ?? getDefaultAccessResult();
}
protected virtual bool getDefaultAccessResult() {
return true;
}
protected virtual bool isReturn(MethodDef methodToInline, int instrIndex) {
var instr = DotNetUtils.getInstruction(methodToInline.Body.Instructions, ref instrIndex);
return instr != null && instr.OpCode.Code == Code.Ret;
}
protected bool checkSameMethods(MethodReference method, MethodDefinition methodToInline) {
protected bool checkSameMethods(IMethod method, MethodDef methodToInline) {
return checkSameMethods(method, methodToInline, 0);
}
protected bool checkSameMethods(MethodReference method, MethodDefinition methodToInline, int ignoreLastMethodToInlineArgs) {
var methodToInlineArgs = DotNetUtils.getArgs(methodToInline);
protected bool checkSameMethods(IMethod method, MethodDef methodToInline, int ignoreLastMethodToInlineArgs) {
var methodToInlineArgs = methodToInline.Parameters;
var methodArgs = DotNetUtils.getArgs(method);
bool hasImplicitThis = method.MethodSig.ImplicitThis;
if (methodToInlineArgs.Count - ignoreLastMethodToInlineArgs != methodArgs.Count)
return false;
for (int i = 0; i < methodArgs.Count; i++) {
var methodArg = methodArgs[i];
var methodToInlineArg = methodToInlineArgs[i];
var methodToInlineArg = methodToInlineArgs[i].Type;
if (!isCompatibleType(i, methodArg, methodToInlineArg)) {
if (i != 0 || !method.HasImplicitThis)
if (i != 0 || !hasImplicitThis)
return false;
if (!isCompatibleValueThisPtr(methodArg, methodToInlineArg))
return false;
@ -214,17 +236,26 @@ namespace de4dot.blocks.cflow {
return true;
}
protected virtual bool isCompatibleType(int paramIndex, TypeReference origType, TypeReference newType) {
return MemberReferenceHelper.compareTypes(origType, newType);
protected virtual bool isCompatibleType(int paramIndex, IType origType, IType newType) {
return new SigComparer().Equals(origType, newType);
}
static bool isCompatibleValueThisPtr(TypeReference origType, TypeReference newType) {
var newByRef = newType as ByReferenceType;
static bool isCompatibleValueThisPtr(IType origType, IType newType) {
var newByRef = newType as ByRefSig;
if (newByRef == null)
return false;
if (!newByRef.ElementType.IsValueType || !origType.IsValueType)
if (!isValueType(newByRef.Next) || !isValueType(origType))
return false;
return MemberReferenceHelper.compareTypes(origType, newByRef.ElementType);
return new SigComparer().Equals(origType, newByRef.Next);
}
protected static bool isValueType(IType type) {
if (type == null)
return false;
var ts = type as TypeSig;
if (ts == null)
return type.IsValueType;
return ts.IsValueType && ts.ElementType != ElementType.Void;
}
}
}

View File

@ -18,12 +18,13 @@
*/
using System.Collections.Generic;
using Mono.Cecil.Cil;
using dot10.DotNet;
using dot10.DotNet.Emit;
namespace de4dot.blocks.cflow {
// Replace stloc + ldloc with dup + stloc
class StLdlocFixer : BlockDeobfuscator {
IList<VariableDefinition> locals;
IList<Local> locals;
protected override void init(List<Block> allBlocks) {
base.init(allBlocks);
@ -49,7 +50,7 @@ namespace de4dot.blocks.cflow {
if (!instructions[i + 1].isLdloc())
break;
var local = Instr.getLocalVar(locals, instr);
if (local.VariableType.FullName != "System.Boolean")
if (local.Type.ElementType != ElementType.Boolean)
continue;
if (local != Instr.getLocalVar(locals, instructions[i + 1]))
break;

View File

@ -19,7 +19,8 @@
using System;
using System.Collections.Generic;
using Mono.Cecil.Cil;
using dot10.DotNet;
using dot10.DotNet.Emit;
namespace de4dot.blocks.cflow {
class SwitchCflowDeobfuscator : BlockDeobfuscator {
@ -64,7 +65,7 @@ namespace de4dot.blocks.cflow {
}
bool isSwitchType2(Block switchBlock) {
VariableDefinition local = null;
Local local = null;
foreach (var instr in switchBlock.Instructions) {
if (!instr.isLdloc())
continue;
@ -178,7 +179,7 @@ namespace de4dot.blocks.cflow {
// swblk:
// ldloc N
// switch (......)
bool deobfuscateLdloc(IList<Block> switchTargets, Block switchFallThrough, Block block, VariableDefinition switchVariable) {
bool deobfuscateLdloc(IList<Block> switchTargets, Block switchFallThrough, Block block, Local switchVariable) {
bool changed = false;
foreach (var source in new List<Block>(block.Sources)) {
if (isBranchBlock(source)) {
@ -366,18 +367,18 @@ namespace de4dot.blocks.cflow {
return changed;
}
static Block createBlock(Dictionary<VariableDefinition, int> consts, Block fallThrough) {
static Block createBlock(Dictionary<Local, int> consts, Block fallThrough) {
var block = new Block();
foreach (var kv in consts) {
block.Instructions.Add(new Instr(DotNetUtils.createLdci4(kv.Value)));
block.Instructions.Add(new Instr(Instruction.CreateLdcI4(kv.Value)));
block.Instructions.Add(new Instr(Instruction.Create(OpCodes.Stloc, kv.Key)));
}
fallThrough.Parent.add(block);
return block;
}
Dictionary<VariableDefinition, int> getBccLocalConstants(Block block) {
var dict = new Dictionary<VariableDefinition, int>();
Dictionary<Local, int> getBccLocalConstants(Block block) {
var dict = new Dictionary<Local, int>();
var instrs = block.Instructions;
for (int i = 0; i < instrs.Count; i++) {
var instr = instrs[i];
@ -397,7 +398,7 @@ namespace de4dot.blocks.cflow {
dict.Remove(local);
}
else if (instr.OpCode.Code == Code.Ldloca || instr.OpCode.Code == Code.Ldloca_S) {
var local = instr.Operand as VariableDefinition;
var local = instr.Operand as Local;
if (local != null)
dict.Remove(local);
}

1
cecil

@ -1 +0,0 @@
Subproject commit 119a3d404ab12a8a19a249e97c1e5f6ca0850b6a

View File

@ -20,52 +20,74 @@
using System;
using System.IO;
using System.Collections.Generic;
using Mono.Cecil;
using Mono.MyStuff;
using dot10.DotNet;
using dot10.DotNet.Writer;
using de4dot.blocks;
namespace de4dot.code {
class AssemblyModule {
string filename;
ModuleDefinition module;
ModuleDefMD module;
ModuleContext moduleContext;
public AssemblyModule(string filename) {
public AssemblyModule(string filename, ModuleContext moduleContext) {
this.filename = Utils.getFullPath(filename);
this.moduleContext = moduleContext;
}
ReaderParameters getReaderParameters() {
return new ReaderParameters(ReadingMode.Deferred) {
AssemblyResolver = AssemblyResolver.Instance
};
public ModuleDefMD load() {
return setModule(ModuleDefMD.Load(filename, moduleContext));
}
public ModuleDefinition load() {
return setModule(ModuleDefinition.ReadModule(filename, getReaderParameters()));
public ModuleDefMD load(byte[] fileData) {
return setModule(ModuleDefMD.Load(fileData, moduleContext));
}
public ModuleDefinition load(byte[] fileData) {
return setModule(ModuleDefinition.ReadModule(new MemoryStream(fileData), getReaderParameters()));
}
ModuleDefinition setModule(ModuleDefinition newModule) {
ModuleDefMD setModule(ModuleDefMD newModule) {
module = newModule;
AssemblyResolver.Instance.addModule(module);
module.FullyQualifiedName = filename;
TheAssemblyResolver.Instance.addModule(module);
module.EnableTypeDefFindCache = true;
module.Location = filename;
return module;
}
public void save(string newFilename, bool updateMaxStack, IWriterListener writerListener) {
var writerParams = new WriterParameters() {
UpdateMaxStack = updateMaxStack,
WriterListener = writerListener,
};
module.Write(newFilename, writerParams);
public void save(string newFilename, bool preserveTokens, bool updateMaxStack, IModuleWriterListener writerListener) {
MetaDataFlags mdFlags = 0;
if (!updateMaxStack)
mdFlags |= MetaDataFlags.KeepOldMaxStack;
if (preserveTokens) {
mdFlags |= MetaDataFlags.PreserveRids |
MetaDataFlags.PreserveUSOffsets |
MetaDataFlags.PreserveBlobOffsets |
MetaDataFlags.PreserveExtraSignatureData;
}
if (module.IsILOnly) {
var writerOptions = new ModuleWriterOptions(module, writerListener);
writerOptions.MetaDataOptions.Flags |= mdFlags;
writerOptions.Logger = Logger.Instance;
module.Write(newFilename, writerOptions);
}
else {
var writerOptions = new NativeModuleWriterOptions(module, writerListener);
writerOptions.MetaDataOptions.Flags |= mdFlags;
writerOptions.Logger = Logger.Instance;
writerOptions.KeepExtraPEData = true;
writerOptions.KeepWin32Resources = true;
module.NativeWrite(newFilename, writerOptions);
}
}
public ModuleDefinition reload(byte[] newModuleData, DumpedMethods dumpedMethods) {
AssemblyResolver.Instance.removeModule(module);
DotNetUtils.typeCaches.invalidate(module);
return setModule(ModuleDefinition.ReadModule(new MemoryStream(newModuleData), getReaderParameters(), dumpedMethods));
public ModuleDefMD reload(byte[] newModuleData, DumpedMethodsRestorer dumpedMethodsRestorer, IStringDecrypter stringDecrypter) {
TheAssemblyResolver.Instance.removeModule(module);
var mod = ModuleDefMD.Load(newModuleData, moduleContext);
if (dumpedMethodsRestorer != null)
dumpedMethodsRestorer.Module = mod;
mod.StringDecrypter = stringDecrypter;
mod.MethodDecrypter = dumpedMethodsRestorer;
mod.TablesStream.ColumnReader = dumpedMethodsRestorer;
mod.TablesStream.MethodRowReader = dumpedMethodsRestorer;
return setModule(mod);
}
public override string ToString() {

View File

@ -17,176 +17,42 @@
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using System.Xml;
using Mono.Cecil;
using dot10.DotNet;
namespace de4dot.code {
public class AssemblyResolver : DefaultAssemblyResolver {
public static readonly AssemblyResolver Instance = new AssemblyResolver();
Dictionary<string, bool> addedDirectories = new Dictionary<string, bool>(StringComparer.OrdinalIgnoreCase);
public class TheAssemblyResolver : dot10.DotNet.AssemblyResolver {
public static readonly TheAssemblyResolver Instance = new TheAssemblyResolver();
static AssemblyResolver() {
Instance.resetSearchPaths();
}
void resetSearchPaths() {
addedDirectories.Clear();
addOtherAssemblySearchPaths();
}
void addOtherAssemblySearchPaths() {
addOtherAssemblySearchPaths(Environment.GetEnvironmentVariable("ProgramFiles"));
addOtherAssemblySearchPaths(Environment.GetEnvironmentVariable("ProgramFiles(x86)"));
}
void addOtherAssemblySearchPaths(string path) {
if (string.IsNullOrEmpty(path))
return;
addSilverlightDirs(Path.Combine(path, @"Microsoft Silverlight"));
addIfExists(path, @"Microsoft SDKs\Silverlight\v2.0\Libraries\Client");
addIfExists(path, @"Microsoft SDKs\Silverlight\v2.0\Libraries\Server");
addIfExists(path, @"Microsoft SDKs\Silverlight\v2.0\Reference Assemblies");
addIfExists(path, @"Microsoft SDKs\Silverlight\v3.0\Libraries\Client");
addIfExists(path, @"Microsoft SDKs\Silverlight\v3.0\Libraries\Server");
addIfExists(path, @"Microsoft SDKs\Silverlight\v4.0\Libraries\Client");
addIfExists(path, @"Microsoft SDKs\Silverlight\v4.0\Libraries\Server");
addIfExists(path, @"Microsoft SDKs\Silverlight\v5.0\Libraries\Client");
addIfExists(path, @"Microsoft SDKs\Silverlight\v5.0\Libraries\Server");
addIfExists(path, @"Microsoft.NET\SDK\CompactFramework\v2.0\WindowsCE");
addIfExists(path, @"Microsoft.NET\SDK\CompactFramework\v3.5\WindowsCE");
addIfExists(path, @"Reference Assemblies\Microsoft\Framework\Silverlight\v3.0");
addIfExists(path, @"Reference Assemblies\Microsoft\Framework\Silverlight\v4.0");
addIfExists(path, @"Reference Assemblies\Microsoft\Framework\Silverlight\v5.0");
addIfExists(path, @"Reference Assemblies\Microsoft\FSharp\2.0\Runtime\v2.0");
addIfExists(path, @"Reference Assemblies\Microsoft\FSharp\2.0\Runtime\v4.0");
addIfExists(path, @"Reference Assemblies\Microsoft\WindowsPowerShell\v1.0");
addIfExists(path, @"Microsoft Visual Studio .NET\Common7\IDE\PublicAssemblies");
addIfExists(path, @"Microsoft Visual Studio .NET\Common7\IDE\PrivateAssemblies");
addIfExists(path, @"Microsoft Visual Studio 8.0\Common7\IDE\PublicAssemblies");
addIfExists(path, @"Microsoft Visual Studio 8.0\Common7\IDE\PrivateAssemblies");
addIfExists(path, @"Microsoft Visual Studio 9.0\Common7\IDE\PublicAssemblies");
addIfExists(path, @"Microsoft Visual Studio 9.0\Common7\IDE\PrivateAssemblies");
addIfExists(path, @"Microsoft Visual Studio 10.0\Common7\IDE\PublicAssemblies");
addIfExists(path, @"Microsoft Visual Studio 10.0\Common7\IDE\PrivateAssemblies");
addIfExists(path, @"Microsoft Visual Studio 11.0\Common7\IDE\PublicAssemblies");
addIfExists(path, @"Microsoft Visual Studio 11.0\Common7\IDE\PrivateAssemblies");
addIfExists(path, @"Microsoft XNA\XNA Game Studio\v2.0\References\Windows\x86");
addIfExists(path, @"Microsoft XNA\XNA Game Studio\v2.0\References\Xbox360");
addIfExists(path, @"Microsoft XNA\XNA Game Studio\v3.0\References\Windows\x86");
addIfExists(path, @"Microsoft XNA\XNA Game Studio\v3.0\References\Xbox360");
addIfExists(path, @"Microsoft XNA\XNA Game Studio\v3.0\References\Zune");
addIfExists(path, @"Microsoft XNA\XNA Game Studio\v3.1\References\Windows\x86");
addIfExists(path, @"Microsoft XNA\XNA Game Studio\v3.1\References\Xbox360");
addIfExists(path, @"Microsoft XNA\XNA Game Studio\v3.1\References\Zune");
addIfExists(path, @"Microsoft XNA\XNA Game Studio\v4.0\References\Windows\x86");
addIfExists(path, @"Microsoft XNA\XNA Game Studio\v4.0\References\Xbox360");
addIfExists(path, @"Windows CE Tools\wce500\Windows Mobile 5.0 Pocket PC SDK\Designtimereferences");
addIfExists(path, @"Windows CE Tools\wce500\Windows Mobile 5.0 Smartphone SDK\Designtimereferences");
addIfExists(path, @"Windows Mobile 5.0 SDK R2\Managed Libraries");
addIfExists(path, @"Windows Mobile 6 SDK\Managed Libraries");
addIfExists(path, @"Windows Mobile 6.5.3 DTK\Managed Libraries");
addIfExists(path, @"Microsoft SQL Server\90\SDK\Assemblies");
addIfExists(path, @"Microsoft SQL Server\100\SDK\Assemblies");
addIfExists(path, @"Microsoft SQL Server\110\SDK\Assemblies");
addIfExists(path, @"Microsoft ASP.NET\ASP.NET MVC 2\Assemblies");
addIfExists(path, @"Microsoft ASP.NET\ASP.NET MVC 3\Assemblies");
addIfExists(path, @"Microsoft ASP.NET\ASP.NET MVC 4\Assemblies");
addIfExists(path, @"Microsoft ASP.NET\ASP.NET Web Pages\v1.0\Assemblies");
addIfExists(path, @"Microsoft ASP.NET\ASP.NET Web Pages\v2.0\Assemblies");
addIfExists(path, @"Microsoft SDKs\F#\3.0\Framework\v4.0");
}
// basePath is eg. "C:\Program Files (x86)\Microsoft Silverlight"
void addSilverlightDirs(string basePath) {
try {
var di = new DirectoryInfo(basePath);
foreach (var dir in di.GetDirectories()) {
if (Regex.IsMatch(dir.Name, @"^\d+(?:\.\d+){3}$"))
addIfExists(basePath, dir.Name);
}
}
catch (Exception) {
}
}
void addIfExists(string basePath, string extraPath) {
try {
var path = Path.Combine(basePath, extraPath);
if (Utils.pathExists(path))
Instance.addSearchDirectory(path);
}
catch (Exception) {
}
public TheAssemblyResolver() {
EnableTypeDefCache = true;
}
public void addSearchDirectory(string dir) {
if (!addedDirectories.ContainsKey(dir)) {
addedDirectories[dir] = true;
AddSearchDirectory(dir);
}
if (!PostSearchPaths.Contains(dir))
PostSearchPaths.Add(dir);
}
public void addModule(ModuleDefinition module) {
if (module.FullyQualifiedName != "") {
addSearchDirectory(Path.GetDirectoryName(module.FullyQualifiedName));
if (module.FullyQualifiedName.EndsWith(".exe", StringComparison.OrdinalIgnoreCase))
addConfigFile(module.FullyQualifiedName + ".config");
}
var assembly = module.Assembly;
if (assembly != null) {
var name = assembly.Name.FullName;
cache[name] = assembly;
}
public void addModule(ModuleDef module) {
AddToCache(module.Assembly);
}
void addConfigFile(string configFilename) {
var dirName = Utils.getDirName(Utils.getFullPath(configFilename));
addSearchDirectory(dirName);
try {
using (var xmlStream = new FileStream(configFilename, FileMode.Open, FileAccess.Read, FileShare.Read)) {
var doc = new XmlDocument();
doc.Load(XmlReader.Create(xmlStream));
foreach (var tmp in doc.GetElementsByTagName("probing")) {
var probingElem = tmp as XmlElement;
if (probingElem == null)
continue;
var privatePath = probingElem.GetAttribute("privatePath");
if (string.IsNullOrEmpty(privatePath))
continue;
foreach (var path in privatePath.Split(';'))
addSearchDirectory(Path.Combine(dirName, path));
}
}
}
catch (IOException) {
}
catch (XmlException) {
}
}
public void removeModule(ModuleDefinition module) {
public void removeModule(ModuleDef module) {
var assembly = module.Assembly;
if (assembly == null)
return;
removeModule(assembly.Name.FullName);
removeModule(assembly.FullName);
}
public void removeModule(string asmFullName) {
if (string.IsNullOrEmpty(asmFullName))
return;
cache.Remove(asmFullName);
//TODO: Remove it from the cache
}
public void clearAll() {
cache.Clear();
resetSearchPaths();
//TODO: cache.Clear();
//TODO: resetSearchPaths();
}
}
}

View File

@ -19,19 +19,17 @@
using System;
using System.Collections.Generic;
using Mono.Cecil;
using dot10.DotNet;
using de4dot.blocks;
namespace de4dot.code {
// "global" data and methods that is shared between all deobfuscators that deobfuscate
// assemblies at the same time.
public class DeobfuscatorContext : IDeobfuscatorContext {
ExternalAssemblies externalAssemblies = new ExternalAssemblies();
Dictionary<string, object> dataDict = new Dictionary<string, object>(StringComparer.Ordinal);
public void clear() {
dataDict.Clear();
externalAssemblies.unloadAll();
}
public void setData(string name, object data) {
@ -48,61 +46,68 @@ namespace de4dot.code {
dataDict.Remove(name);
}
static TypeReference getNonGenericTypeReference(TypeReference typeReference) {
if (typeReference == null)
return null;
if (!typeReference.IsGenericInstance)
return typeReference;
var type = (GenericInstanceType)typeReference;
return type.ElementType;
static ITypeDefOrRef getNonGenericTypeReference(ITypeDefOrRef typeRef) {
var ts = typeRef as TypeSpec;
if (ts == null)
return typeRef;
var gis = ts.ToGenericInstSig();
if (gis == null || gis.GenericType == null)
return typeRef;
return gis.GenericType.TypeDefOrRef;
}
public TypeDefinition resolve(TypeReference type) {
public TypeDef resolveType(ITypeDefOrRef type) {
if (type == null)
return null;
var typeDef = getNonGenericTypeReference(type) as TypeDefinition;
type = getNonGenericTypeReference(type);
var typeDef = type as TypeDef;
if (typeDef != null)
return typeDef;
return externalAssemblies.resolve(type);
var tr = type as TypeRef;
if (tr != null)
return tr.Resolve();
return null;
}
public MethodDefinition resolve(MethodReference method) {
public MethodDef resolveMethod(IMethod method) {
if (method == null)
return null;
var methodDef = method as MethodDefinition;
if (methodDef != null)
return methodDef;
var type = resolve(method.DeclaringType);
var md = method as MethodDef;
if (md != null)
return md;
var mr = method as MemberRef;
if (mr == null || !mr.IsMethodRef)
return null;
var type = resolveType(mr.DeclaringType);
if (type == null)
return null;
foreach (var m in type.Methods) {
if (MemberReferenceHelper.compareMethodReference(method, m))
return m;
}
return null;
return type.Resolve(mr) as MethodDef;
}
public FieldDefinition resolve(FieldReference field) {
public FieldDef resolveField(IField field) {
if (field == null)
return null;
var fieldDef = field as FieldDefinition;
if (fieldDef != null)
return fieldDef;
var type = resolve(field.DeclaringType);
var fd = field as FieldDef;
if (fd != null)
return fd;
var mr = field as MemberRef;
if (mr == null || !mr.IsFieldRef)
return null;
var type = resolveType(mr.DeclaringType);
if (type == null)
return null;
foreach (var f in type.Fields) {
if (MemberReferenceHelper.compareFieldReference(field, f))
return f;
}
return null;
return type.Resolve(mr) as FieldDef;
}
}
}

View File

@ -0,0 +1,75 @@
/*
Copyright (C) 2011-2012 de4dot@gmail.com
This file is part of de4dot.
de4dot is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
de4dot is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
*/
using System.Collections.Generic;
using dot10.PE;
using dot10.DotNet.MD;
using dot10.DotNet.Emit;
using dot10.DotNet;
using de4dot.blocks;
namespace de4dot.code {
class DumpedMethodsRestorer : IRowReader<RawMethodRow>, IColumnReader, IMethodDecrypter {
ModuleDefMD module;
DumpedMethods dumpedMethods;
public ModuleDefMD Module {
set { module = value; }
}
public DumpedMethodsRestorer(DumpedMethods dumpedMethods) {
this.dumpedMethods = dumpedMethods;
}
DumpedMethod getDumpedMethod(uint rid) {
return dumpedMethods.get(0x06000000 | rid);
}
public RawMethodRow ReadRow(uint rid) {
var dm = getDumpedMethod(rid);
if (dm == null)
return null;
return new RawMethodRow(dm.mdRVA, dm.mdImplFlags, dm.mdFlags, dm.mdName, dm.mdSignature, dm.mdParamList);
}
public bool ReadColumn(MDTable table, uint rid, ColumnInfo column, out uint value) {
if (table.Table == Table.Method) {
var row = ReadRow(rid);
if (row != null) {
value = row.Read(column.Index);
return true;
}
}
value = 0;
return false;
}
public bool HasMethodBody(uint rid) {
return getDumpedMethod(rid) != null;
}
public MethodBody GetMethodBody(uint rid, RVA rva, IList<Parameter> parameters) {
var dm = getDumpedMethod(rid);
if (dm == null)
return null;
return MethodBodyReader.Create(module, dm.code, dm.extraSections, parameters, dm.mhFlags, dm.mhMaxStack, dm.mhCodeSize, dm.mhLocalVarSigTok);
}
}
}

View File

@ -1,114 +0,0 @@
/*
Copyright (C) 2011-2012 de4dot@gmail.com
This file is part of de4dot.
de4dot is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
de4dot is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using Mono.Cecil;
using de4dot.blocks;
namespace de4dot.code {
class ExternalAssembly {
AssemblyDefinition asmDef;
public ExternalAssembly(AssemblyDefinition asmDef) {
this.asmDef = asmDef;
}
public TypeDefinition resolve(TypeReference type) {
foreach (var module in asmDef.Modules) {
var typeDef = DotNetUtils.getType(module, type);
if (typeDef != null)
return typeDef;
}
return null;
}
public void unload(string asmFullName) {
foreach (var module in asmDef.Modules) {
DotNetUtils.typeCaches.invalidate(module);
AssemblyResolver.Instance.removeModule(module);
}
AssemblyResolver.Instance.removeModule(asmFullName);
}
}
// Loads assemblies that aren't renamed
class ExternalAssemblies {
Dictionary<string, ExternalAssembly> assemblies = new Dictionary<string, ExternalAssembly>(StringComparer.Ordinal);
Dictionary<string, bool> failedLoads = new Dictionary<string, bool>(StringComparer.Ordinal);
ExternalAssembly load(TypeReference type) {
var asmFullName = DotNetUtils.getFullAssemblyName(type);
if (asmFullName == null)
return null;
ExternalAssembly asm;
if (assemblies.TryGetValue(asmFullName, out asm))
return asm;
AssemblyDefinition asmDef = null;
try {
asmDef = AssemblyResolver.Instance.Resolve(asmFullName);
}
catch (ResolutionException) {
}
catch (AssemblyResolutionException) {
}
if (asmDef == null) {
if (!failedLoads.ContainsKey(asmFullName))
Log.w("Could not load assembly {0}", asmFullName);
failedLoads[asmFullName] = true;
return null;
}
if (assemblies.ContainsKey(asmDef.Name.FullName)) {
assemblies[asmFullName] = assemblies[asmDef.Name.FullName];
return assemblies[asmDef.Name.FullName];
}
if (asmFullName == asmDef.Name.FullName)
Log.v("Loaded assembly {0}", asmFullName);
else
Log.v("Loaded assembly {0} (but wanted {1})", asmDef.Name.FullName, asmFullName);
asm = new ExternalAssembly(asmDef);
assemblies[asmFullName] = asm;
assemblies[asmDef.Name.FullName] = asm;
return asm;
}
public TypeDefinition resolve(TypeReference type) {
if (type == null)
return null;
var asm = load(type);
if (asm == null)
return null;
return asm.resolve(type);
}
public void unloadAll() {
foreach (var pair in assemblies) {
if (pair.Value == null)
continue;
pair.Value.unload(pair.Key);
}
assemblies.Clear();
failedLoads.Clear();
}
}
}

View File

@ -17,7 +17,7 @@
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
*/
using Mono.Cecil;
using dot10.DotNet;
namespace de4dot.code {
public interface IDeobfuscatorContext {
@ -25,8 +25,8 @@ namespace de4dot.code {
void setData(string name, object data);
object getData(string name);
void clearData(string name);
TypeDefinition resolve(TypeReference type);
MethodDefinition resolve(MethodReference method);
FieldDefinition resolve(FieldReference field);
TypeDef resolveType(ITypeDefOrRef type);
MethodDef resolveMethod(IMethod method);
FieldDef resolveField(IField field);
}
}

View File

@ -17,14 +17,15 @@
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using de4dot.code.deobfuscators;
using Mono.Cecil;
using dot10.DotNet;
using de4dot.code.renamer;
namespace de4dot.code {
public interface IObfuscatedFile {
ModuleDefinition ModuleDefinition { get; }
public interface IObfuscatedFile : IDisposable {
ModuleDefMD ModuleDefMD { get; }
IDeobfuscator Deobfuscator { get; }
IDeobfuscatorContext DeobfuscatorContext { get; set; }
string Filename { get; }

View File

@ -1,85 +0,0 @@
/*
Copyright (C) 2011-2012 de4dot@gmail.com
This file is part of de4dot.
de4dot is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
de4dot is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
namespace de4dot.code {
public static class Log {
public static int indentLevel = 0;
const int indentSize = 2;
public enum LogLevel {
error,
warning,
normal,
verbose,
veryverbose,
}
public static LogLevel logLevel = LogLevel.normal;
public static string indentString = "";
public static bool isAtLeast(LogLevel ll) {
return logLevel >= ll;
}
static void initIndentString() {
indentString = new string(' ', indentLevel * indentSize);
}
public static void indent() {
indentLevel++;
initIndentString();
}
public static void deIndent() {
if (indentLevel <= 0)
throw new ApplicationException("Can't de-indent!");
indentLevel--;
initIndentString();
}
public static void log(LogLevel l, string format, params object[] args) {
if (!isAtLeast(l))
return;
var indent = l <= LogLevel.warning ? "" : indentString;
Console.WriteLine(indent + format, args);
}
public static void e(string format, params object[] args) {
log(LogLevel.error, format, args);
}
public static void w(string format, params object[] args) {
log(LogLevel.warning, format, args);
}
public static void n(string format, params object[] args) {
log(LogLevel.normal, format, args);
}
public static void v(string format, params object[] args) {
log(LogLevel.verbose, format, args);
}
public static void vv(string format, params object[] args) {
log(LogLevel.veryverbose, format, args);
}
}
}

165
de4dot.code/Logger.cs Normal file
View File

@ -0,0 +1,165 @@
/*
Copyright (C) 2011-2012 de4dot@gmail.com
This file is part of de4dot.
de4dot is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
de4dot is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using dot10.DotNet;
namespace de4dot.code {
public class Logger : ILogger {
public readonly static Logger Instance = new Logger();
int indentLevel = 0;
readonly int indentSize = 0;
LoggerEvent maxLoggerEvent = LoggerEvent.Info;
string indentString = "";
Dictionary<string, bool> ignoredMessages = new Dictionary<string, bool>(StringComparer.Ordinal);
int numIgnoredMessages;
bool canIgnoreMessages;
public int IndentLevel {
get { return indentLevel; }
set {
if (indentLevel == value)
return;
indentLevel = value;
initIndentString();
}
}
public LoggerEvent MaxLoggerEvent {
get { return maxLoggerEvent; }
set { maxLoggerEvent = value; }
}
public bool CanIgnoreMessages {
get { return canIgnoreMessages; }
set { canIgnoreMessages = value; }
}
public int NumIgnoredMessages {
get { return numIgnoredMessages; }
}
public Logger()
: this(2, true) {
}
public Logger(int indentSize, bool canIgnoreMessages) {
this.indentSize = indentSize;
this.canIgnoreMessages = canIgnoreMessages;
}
void initIndentString() {
if (indentLevel < 0)
indentLevel = 0;
indentString = new string(' ', indentLevel * indentSize);
}
public void indent() {
indentLevel++;
initIndentString();
}
public void deIndent() {
indentLevel--;
initIndentString();
}
public void Log(object sender, LoggerEvent loggerEvent, string format, params object[] args) {
Log(true, sender, loggerEvent, format, args);
}
public void LogErrorDontIgnore(string format, params object[] args) {
Log(false, null, LoggerEvent.Error, format, args);
}
public void Log(bool canIgnore, object sender, LoggerEvent loggerEvent, string format, params object[] args) {
if (IgnoresEvent(loggerEvent))
return;
if (canIgnore && ignoreMessage(loggerEvent, format, args))
return;
switch (loggerEvent) {
case LoggerEvent.Error:
foreach (var l in string.Format(format, args).Split('\n'))
LogMessage(string.Empty, string.Format("ERROR: {0}", l));
break;
case LoggerEvent.Warning:
foreach (var l in string.Format(format, args).Split('\n'))
LogMessage(string.Empty, string.Format("WARNING: {0}", l));
break;
default:
var indent = loggerEvent <= LoggerEvent.Warning ? "" : indentString;
LogMessage(indent, format, args);
break;
}
}
bool ignoreMessage(LoggerEvent loggerEvent, string format, object[] args) {
if (loggerEvent != LoggerEvent.Error && loggerEvent != LoggerEvent.Warning)
return false;
if (!canIgnoreMessages)
return false;
if (ignoredMessages.ContainsKey(format)) {
numIgnoredMessages++;
return true;
}
ignoredMessages[format] = true;
return false;
}
void LogMessage(string indent, string format, params object[] args) {
if (args == null || args.Length == 0)
Console.WriteLine("{0}{1}", indent, format);
else
Console.WriteLine(indent + format, args);
}
public bool IgnoresEvent(LoggerEvent loggerEvent) {
return loggerEvent > maxLoggerEvent;
}
public static void log(LoggerEvent loggerEvent, string format, params object[] args) {
Instance.Log(null, loggerEvent, format, args);
}
public static void e(string format, params object[] args) {
Instance.Log(null, LoggerEvent.Error, format, args);
}
public static void w(string format, params object[] args) {
Instance.Log(null, LoggerEvent.Warning, format, args);
}
public static void n(string format, params object[] args) {
Instance.Log(null, LoggerEvent.Info, format, args);
}
public static void v(string format, params object[] args) {
Instance.Log(null, LoggerEvent.Verbose, format, args);
}
public static void vv(string format, params object[] args) {
Instance.Log(null, LoggerEvent.VeryVerbose, format, args);
}
}
}

View File

@ -19,13 +19,13 @@
using System.Collections.Generic;
using System.Text;
using Mono.Cecil;
using Mono.Cecil.Cil;
using dot10.DotNet;
using dot10.DotNet.Emit;
using de4dot.blocks;
namespace de4dot.code {
class MethodPrinter {
Log.LogLevel logLevel;
LoggerEvent loggerEvent;
IList<Instruction> allInstructions;
IList<ExceptionHandler> allExceptionHandlers;
Dictionary<Instruction, bool> targets = new Dictionary<Instruction, bool>();
@ -41,9 +41,9 @@ namespace de4dot.code {
Dictionary<Instruction, ExInfo> exInfos = new Dictionary<Instruction, ExInfo>();
ExInfo lastExInfo;
public void print(Log.LogLevel logLevel, IList<Instruction> allInstructions, IList<ExceptionHandler> allExceptionHandlers) {
public void print(LoggerEvent loggerEvent, IList<Instruction> allInstructions, IList<ExceptionHandler> allExceptionHandlers) {
try {
this.logLevel = logLevel;
this.loggerEvent = loggerEvent;
this.allInstructions = allInstructions;
this.allExceptionHandlers = allExceptionHandlers;
lastExInfo = new ExInfo();
@ -83,7 +83,7 @@ namespace de4dot.code {
}
var sortedTargets = new List<Instruction>(targets.Keys);
sortedTargets.Sort((a, b) => Utils.compareInt32(a.Offset, b.Offset));
sortedTargets.Sort((a, b) => a.Offset.CompareTo(b.Offset));
for (int i = 0; i < sortedTargets.Count; i++)
labels[sortedTargets[i]] = string.Format("label_{0}", i);
}
@ -121,28 +121,28 @@ namespace de4dot.code {
initTargets();
initExHandlers();
Log.indent();
Logger.Instance.indent();
foreach (var instr in allInstructions) {
if (targets.ContainsKey(instr)) {
Log.deIndent();
Log.log(logLevel, "{0}:", getLabel(instr));
Log.indent();
Logger.Instance.deIndent();
Logger.log(loggerEvent, "{0}:", getLabel(instr));
Logger.Instance.indent();
}
ExInfo exInfo;
if (exInfos.TryGetValue(instr, out exInfo))
printExInfo(exInfo);
var instrString = instr.GetOpCodeString();
var instrString = instr.OpCode.Name;
var operandString = getOperandString(instr);
var memberReference = instr.Operand as MemberReference;
var memberReference = instr.Operand as ITokenOperand;
if (operandString == "")
Log.log(logLevel, "{0}", instrString);
Logger.log(loggerEvent, "{0}", instrString);
else if (memberReference != null)
Log.log(logLevel, "{0,-9} {1} // {2:X8}", instrString, Utils.removeNewlines(operandString), memberReference.MetadataToken.ToUInt32());
Logger.log(loggerEvent, "{0,-9} {1} // {2:X8}", instrString, Utils.removeNewlines(operandString), memberReference.MDToken.ToUInt32());
else
Log.log(logLevel, "{0,-9} {1}", instrString, Utils.removeNewlines(operandString));
Logger.log(loggerEvent, "{0,-9} {1}", instrString, Utils.removeNewlines(operandString));
}
printExInfo(lastExInfo);
Log.deIndent();
Logger.Instance.deIndent();
}
string getOperandString(Instruction instr) {
@ -160,30 +160,30 @@ namespace de4dot.code {
}
else if (instr.Operand is string)
return Utils.toCsharpString((string)instr.Operand);
else if (instr.Operand is ParameterDefinition) {
var arg = (ParameterDefinition)instr.Operand;
var s = instr.GetOperandString();
else if (instr.Operand is Parameter) {
var arg = (Parameter)instr.Operand;
var s = InstructionPrinter.GetOperandString(instr);
if (s != "")
return s;
return string.Format("<arg_{0}>", DotNetUtils.getArgIndex(arg));
return string.Format("<arg_{0}>", arg.Index);
}
else
return instr.GetOperandString();
return InstructionPrinter.GetOperandString(instr);
}
void printExInfo(ExInfo exInfo) {
Log.deIndent();
Logger.Instance.deIndent();
foreach (var ex in exInfo.tryStarts)
Log.log(logLevel, "// try start: {0}", getExceptionString(ex));
Logger.log(loggerEvent, "// try start: {0}", getExceptionString(ex));
foreach (var ex in exInfo.tryEnds)
Log.log(logLevel, "// try end: {0}", getExceptionString(ex));
Logger.log(loggerEvent, "// try end: {0}", getExceptionString(ex));
foreach (var ex in exInfo.filterStarts)
Log.log(logLevel, "// filter start: {0}", getExceptionString(ex));
Logger.log(loggerEvent, "// filter start: {0}", getExceptionString(ex));
foreach (var ex in exInfo.handlerStarts)
Log.log(logLevel, "// handler start: {0}", getExceptionString(ex));
Logger.log(loggerEvent, "// handler start: {0}", getExceptionString(ex));
foreach (var ex in exInfo.handlerEnds)
Log.log(logLevel, "// handler end: {0}", getExceptionString(ex));
Log.indent();
Logger.log(loggerEvent, "// handler end: {0}", getExceptionString(ex));
Logger.Instance.indent();
}
string getExceptionString(ExceptionHandler ex) {

View File

@ -19,17 +19,16 @@
using System;
using System.Collections.Generic;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Cecil.Metadata;
using dot10.DotNet;
using dot10.DotNet.Emit;
using de4dot.blocks;
namespace de4dot.code {
// A simple class that statically detects the values of some local variables
class VariableValues {
IList<Block> allBlocks;
IList<VariableDefinition> locals;
Dictionary<VariableDefinition, Variable> variableToValue = new Dictionary<VariableDefinition, Variable>();
IList<Local> locals;
Dictionary<Local, Variable> variableToValue = new Dictionary<Local, Variable>();
public class Variable {
int writes = 0;
@ -58,7 +57,7 @@ namespace de4dot.code {
}
}
public VariableValues(IList<VariableDefinition> locals, IList<Block> allBlocks) {
public VariableValues(IList<Local> locals, IList<Block> allBlocks) {
this.locals = locals;
this.allBlocks = allBlocks;
init();
@ -136,7 +135,7 @@ namespace de4dot.code {
}
}
public Variable getValue(VariableDefinition variable) {
public Variable getValue(Local variable) {
return variableToValue[variable];
}
}
@ -144,7 +143,7 @@ namespace de4dot.code {
abstract class MethodReturnValueInliner {
protected List<CallResult> callResults;
List<Block> allBlocks;
MethodDefinition theMethod;
MethodDef theMethod;
VariableValues variableValues;
int errors = 0;
bool useUnknownArgs = false;
@ -166,8 +165,8 @@ namespace de4dot.code {
this.callEndIndex = callEndIndex;
}
public MethodReference getMethodReference() {
return (MethodReference)block.Instructions[callEndIndex].Operand;
public IMethod getMethodReference() {
return (IMethod)block.Instructions[callEndIndex].Operand;
}
}
@ -177,14 +176,14 @@ namespace de4dot.code {
public abstract bool HasHandlers { get; }
public MethodDefinition Method {
public MethodDef Method {
get { return theMethod; }
}
protected abstract void inlineAllCalls();
// Returns null if method is not a method we should inline
protected abstract CallResult createCallResult(MethodReference method, GenericInstanceMethod gim, Block block, int callInstrIndex);
protected abstract CallResult createCallResult(IMethod method, MethodSpec gim, Block block, int callInstrIndex);
public int decrypt(Blocks blocks) {
if (!HasHandlers)
@ -192,7 +191,7 @@ namespace de4dot.code {
return decrypt(blocks.Method, blocks.MethodBlocks.getAllBlocks());
}
public int decrypt(MethodDefinition method, List<Block> allBlocks) {
public int decrypt(MethodDef method, List<Block> allBlocks) {
if (!HasHandlers)
return 0;
try {
@ -217,9 +216,9 @@ namespace de4dot.code {
}
}
bool getLocalVariableValue(VariableDefinition variable, out object value) {
bool getLocalVariableValue(Local variable, out object value) {
if (variableValues == null)
variableValues = new VariableValues(theMethod.Body.Variables, allBlocks);
variableValues = new VariableValues(theMethod.Body.LocalList, allBlocks);
var val = variableValues.getValue(variable);
if (!val.isValid()) {
value = null;
@ -239,14 +238,14 @@ namespace de4dot.code {
var instr = block.Instructions[i];
if (instr.OpCode != OpCodes.Call)
continue;
var method = instr.Operand as MethodReference;
var method = instr.Operand as IMethod;
if (method == null)
continue;
MethodReference elementMethod = method;
var gim = method as GenericInstanceMethod;
IMethod elementMethod = method;
var gim = method as MethodSpec;
if (gim != null)
elementMethod = gim.ElementMethod;
elementMethod = gim.Method;
var callResult = createCallResult(elementMethod, gim, block, i);
if (callResult == null)
continue;
@ -259,7 +258,7 @@ namespace de4dot.code {
bool findArgs(CallResult callResult) {
var block = callResult.block;
var method = callResult.getMethodReference();
var methodArgs = DotNetUtils.getParameters(method);
var methodArgs = DotNetUtils.getArgs(method);
int numArgs = methodArgs.Count;
var args = new object[numArgs];
@ -269,9 +268,9 @@ namespace de4dot.code {
if (!getArg(method, block, ref arg, ref instrIndex))
return false;
if (arg is int)
arg = fixIntArg(methodArgs[i].ParameterType, (int)arg);
arg = fixIntArg(methodArgs[i], (int)arg);
else if (arg is long)
arg = fixIntArg(methodArgs[i].ParameterType, (long)arg);
arg = fixIntArg(methodArgs[i], (long)arg);
args[i] = arg;
}
@ -280,8 +279,8 @@ namespace de4dot.code {
return true;
}
object fixIntArg(TypeReference type, long value) {
switch (type.EType) {
object fixIntArg(TypeSig type, long value) {
switch (type.ElementType) {
case ElementType.Boolean: return value != 0;
case ElementType.Char: return (char)value;
case ElementType.I1: return (sbyte)value;
@ -296,15 +295,15 @@ namespace de4dot.code {
throw new ApplicationException(string.Format("Wrong type {0}", type));
}
bool getArg(MethodReference method, Block block, ref object arg, ref int instrIndex) {
bool getArg(IMethod method, Block block, ref object arg, ref int instrIndex) {
while (true) {
if (instrIndex < 0) {
// We're here if there were no cflow deobfuscation, or if there are two or
// more blocks branching to the decrypter method, or the two blocks can't be
// merged because one is outside the exception handler (eg. buggy obfuscator).
Log.w("Could not find all arguments to method {0} ({1:X8})",
Logger.w("Could not find all arguments to method {0} ({1:X8})",
Utils.removeNewlines(method),
method.MetadataToken.ToInt32());
method.MDToken.ToInt32());
errors++;
return false;
}
@ -343,7 +342,7 @@ namespace de4dot.code {
case Code.Ldloc_1:
case Code.Ldloc_2:
case Code.Ldloc_3:
getLocalVariableValue(Instr.getLocalVar(theMethod.Body.Variables, instr), out arg);
getLocalVariableValue(instr.Instruction.GetLocal(theMethod.Body.LocalList), out arg);
break;
case Code.Ldfld:
@ -353,11 +352,11 @@ namespace de4dot.code {
default:
int pushes, pops;
DotNetUtils.calculateStackUsage(instr.Instruction, false, out pushes, out pops);
instr.Instruction.CalculateStackUsage(false, out pushes, out pops);
if (!useUnknownArgs || pushes != 1) {
Log.w("Could not find all arguments to method {0} ({1:X8}), instr: {2}",
Logger.w("Could not find all arguments to method {0} ({1:X8}), instr: {2}",
Utils.removeNewlines(method),
method.MetadataToken.ToInt32(),
method.MDToken.ToInt32(),
instr);
errors++;
return false;
@ -381,10 +380,10 @@ namespace de4dot.code {
callResults.Sort((a, b) => {
int i1 = allBlocks.FindIndex((x) => a.block == x);
int i2 = allBlocks.FindIndex((x) => b.block == x);
if (i1 < i2) return -1;
if (i1 > i2) return 1;
if (i1 != i2)
return i1.CompareTo(i2);
return Utils.compareInt32(a.callStartIndex, b.callStartIndex);
return a.callStartIndex.CompareTo(b.callStartIndex);
});
callResults.Reverse();
inlineReturnValues(callResults);

View File

@ -22,20 +22,20 @@ using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Text;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.MyStuff;
using dot10.DotNet;
using dot10.DotNet.Emit;
using dot10.DotNet.Writer;
using dot10.PE;
using de4dot.code.deobfuscators;
using de4dot.blocks;
using de4dot.blocks.cflow;
using de4dot.code.AssemblyClient;
using de4dot.code.renamer;
using de4dot.PE;
namespace de4dot.code {
public class ObfuscatedFile : IObfuscatedFile, IDeobfuscatedFile {
Options options;
ModuleDefinition module;
ModuleDefMD module;
IDeobfuscator deob;
IDeobfuscatorContext deobfuscatorContext;
AssemblyModule assemblyModule;
@ -46,14 +46,14 @@ namespace de4dot.code {
bool userStringDecrypterMethods = false;
class SavedMethodBodies {
Dictionary<MethodDefinition, SavedMethodBody> savedMethodBodies = new Dictionary<MethodDefinition, SavedMethodBody>();
Dictionary<MethodDef, SavedMethodBody> savedMethodBodies = new Dictionary<MethodDef, SavedMethodBody>();
class SavedMethodBody {
MethodDefinition method;
MethodDef method;
IList<Instruction> instructions;
IList<ExceptionHandler> exceptionHandlers;
public SavedMethodBody(MethodDefinition method) {
public SavedMethodBody(MethodDef method) {
this.method = method;
DotNetUtils.copyBody(method, out instructions, out exceptionHandlers);
}
@ -63,7 +63,7 @@ namespace de4dot.code {
}
}
public void save(MethodDefinition method) {
public void save(MethodDef method) {
if (isSaved(method))
return;
savedMethodBodies[method] = new SavedMethodBody(method);
@ -75,7 +75,7 @@ namespace de4dot.code {
savedMethodBodies.Clear();
}
public bool isSaved(MethodDefinition method) {
public bool isSaved(MethodDef method) {
return savedMethodBodies.ContainsKey(method);
}
}
@ -103,7 +103,7 @@ namespace de4dot.code {
get { return options.NewFilename; }
}
public ModuleDefinition ModuleDefinition {
public ModuleDefMD ModuleDefMD {
get { return module; }
}
@ -132,12 +132,12 @@ namespace de4dot.code {
set { deobfuscatorContext = value; }
}
public ObfuscatedFile(Options options, IAssemblyClientFactory assemblyClientFactory) {
public ObfuscatedFile(Options options, ModuleContext moduleContext, IAssemblyClientFactory assemblyClientFactory) {
this.assemblyClientFactory = assemblyClientFactory;
this.options = options;
userStringDecrypterMethods = options.StringDecrypterMethods.Count > 0;
options.Filename = Utils.getFullPath(options.Filename);
assemblyModule = new AssemblyModule(options.Filename);
assemblyModule = new AssemblyModule(options.Filename, moduleContext);
if (options.NewFilename == null)
options.NewFilename = getDefaultNewFilename();
@ -162,8 +162,8 @@ namespace de4dot.code {
public void load(IEnumerable<IDeobfuscator> deobfuscators) {
loadModule(deobfuscators);
AssemblyResolver.Instance.addSearchDirectory(Utils.getDirName(Filename));
AssemblyResolver.Instance.addSearchDirectory(Utils.getDirName(NewFilename));
TheAssemblyResolver.Instance.addSearchDirectory(Utils.getDirName(Filename));
TheAssemblyResolver.Instance.addSearchDirectory(Utils.getDirName(NewFilename));
detectObfuscator(deobfuscators);
if (deob == null)
throw new ApplicationException("Could not detect obfuscator!");
@ -171,18 +171,23 @@ namespace de4dot.code {
}
void loadModule(IEnumerable<IDeobfuscator> deobfuscators) {
ModuleDefMD oldModule = module;
try {
module = assemblyModule.load();
}
catch (BadImageFormatException) {
if (!unpackNativeImage(deobfuscators))
throw new BadImageFormatException();
Log.v("Unpacked native file");
Logger.v("Unpacked native file");
}
finally {
if (oldModule != null)
oldModule.Dispose();
}
}
bool unpackNativeImage(IEnumerable<IDeobfuscator> deobfuscators) {
var peImage = new PeImage(Utils.readFile(Filename));
var peImage = new PEImage(Filename);
foreach (var deob in deobfuscators) {
byte[] unpackedData = null;
@ -194,13 +199,18 @@ namespace de4dot.code {
if (unpackedData == null)
continue;
var oldModule = module;
try {
module = assemblyModule.load(unpackedData);
}
catch {
Log.w("Could not load unpacked data. Deobfuscator: {0}", deob.TypeLong);
Logger.w("Could not load unpacked data. File: {0}, deobfuscator: {0}", peImage.FileName ?? "(unknown filename)", deob.TypeLong);
continue;
}
finally {
if (oldModule != null)
oldModule.Dispose();
}
this.deob = deob;
return true;
}
@ -283,7 +293,7 @@ namespace de4dot.code {
catch {
val = deob.Type == "un" ? 1 : 0;
}
Log.v("{0,3}: {1}", val, deob.TypeLong);
Logger.v("{0,3}: {1}", val, deob.TypeLong);
if (val > 0 && deob.Type != "un")
allDetected.Add(deob);
if (val > detectVal) {
@ -294,23 +304,27 @@ namespace de4dot.code {
this.deob = null;
if (allDetected.Count > 1) {
Log.n("More than one obfuscator detected:");
Log.indent();
Logger.n("More than one obfuscator detected:");
Logger.Instance.indent();
foreach (var deob in allDetected)
Log.n("{0} (use: -p {1})", deob.Name, deob.Type);
Log.deIndent();
Logger.n("{0} (use: -p {1})", deob.Name, deob.Type);
Logger.Instance.deIndent();
}
return detected;
}
public void save() {
Log.n("Saving {0}", options.NewFilename);
assemblyModule.save(options.NewFilename, options.ControlFlowDeobfuscation, deob as IWriterListener);
bool ShouldPreserveTokens() {
return options.KeepObfuscatorTypes || deob.Type == "un";
}
IList<MethodDefinition> getAllMethods() {
var list = new List<MethodDefinition>();
public void save() {
Logger.n("Saving {0}", options.NewFilename);
assemblyModule.save(options.NewFilename, ShouldPreserveTokens(), options.ControlFlowDeobfuscation, deob as IModuleWriterListener);
}
IList<MethodDef> getAllMethods() {
var list = new List<MethodDef>();
foreach (var type in module.GetTypes()) {
foreach (var method in type.Methods)
@ -349,7 +363,7 @@ namespace de4dot.code {
}
public void deobfuscate() {
Log.n("Cleaning {0}", options.Filename);
Logger.n("Cleaning {0}", options.Filename);
initAssemblyClient();
for (int i = 0; ; i++) {
@ -366,15 +380,23 @@ namespace de4dot.code {
}
void reloadModule(byte[] newModuleData, DumpedMethods dumpedMethods) {
Log.v("Reloading decrypted assembly (original filename: {0})", Filename);
Logger.v("Reloading decrypted assembly (original filename: {0})", Filename);
simpleDeobfuscatorFlags.Clear();
module = assemblyModule.reload(newModuleData, dumpedMethods);
deob = deob.moduleReloaded(module);
using (var oldModule = module) {
module = assemblyModule.reload(newModuleData, createDumpedMethodsRestorer(dumpedMethods), deob as IStringDecrypter);
deob = deob.moduleReloaded(module);
}
initializeDeobfuscator();
deob.DeobfuscatedFile = this;
updateDynamicStringInliner();
}
DumpedMethodsRestorer createDumpedMethodsRestorer(DumpedMethods dumpedMethods) {
if (dumpedMethods == null || dumpedMethods.Count == 0)
return null;
return new DumpedMethodsRestorer(dumpedMethods);
}
void initAssemblyClient() {
if (assemblyClient == null)
return;
@ -429,26 +451,29 @@ namespace de4dot.code {
if (typeString != null && typeString != type.FullName)
continue;
foreach (var method in type.Methods) {
if (!method.IsStatic || method.MethodReturnType.ReturnType.FullName != "System.String")
if (!method.IsStatic)
continue;
if (method.MethodSig.GetRetType().GetElementType() != ElementType.String && method.MethodSig.GetRetType().GetElementType() != ElementType.Object)
continue;
if (methodName != null && methodName != method.Name)
continue;
var sig = method.MethodSig;
if (argsStrings == null) {
if (method.Parameters.Count == 0)
if (sig.Params.Count == 0)
continue;
}
else {
if (argsStrings.Length != method.Parameters.Count)
if (argsStrings.Length != sig.Params.Count)
continue;
for (int i = 0; i < argsStrings.Length; i++) {
if (argsStrings[i] != method.Parameters[i].ParameterType.FullName)
if (argsStrings[i] != sig.Params[i].FullName)
continue;
}
}
Log.v("Adding string decrypter; token: {0:X8}, method: {1}", method.MetadataToken.ToInt32(), Utils.removeNewlines(method.FullName));
tokens.Add(method.MetadataToken.ToInt32());
Logger.v("Adding string decrypter; token: {0:X8}, method: {1}", method.MDToken.ToInt32(), Utils.removeNewlines(method.FullName));
tokens.Add(method.MDToken.ToInt32());
}
}
@ -521,45 +546,52 @@ namespace de4dot.code {
if (!options.ControlFlowDeobfuscation) {
// If it's the unknown type, we don't remove any types that could cause Mono.Cecil
// to throw an exception.
if (deob.Type == "un" || options.KeepObfuscatorTypes)
if (ShouldPreserveTokens())
return;
}
Log.v("Deobfuscating methods");
bool isVerbose = !Logger.Instance.IgnoresEvent(LoggerEvent.Verbose);
bool isVV = !Logger.Instance.IgnoresEvent(LoggerEvent.VeryVerbose);
if (isVerbose)
Logger.v("Deobfuscating methods");
var methodPrinter = new MethodPrinter();
var cflowDeobfuscator = new BlocksCflowDeobfuscator(deob.BlocksDeobfuscators);
foreach (var method in getAllMethods()) {
Log.v("Deobfuscating {0} ({1:X8})", Utils.removeNewlines(method), method.MetadataToken.ToUInt32());
Log.indent();
if (isVerbose) {
Logger.v("Deobfuscating {0} ({1:X8})", Utils.removeNewlines(method), method.MDToken.ToUInt32());
Logger.Instance.indent();
}
int oldIndentLevel = Log.indentLevel;
int oldIndentLevel = Logger.Instance.IndentLevel;
try {
deobfuscate(method, cflowDeobfuscator, methodPrinter);
deobfuscate(method, cflowDeobfuscator, methodPrinter, isVerbose, isVV);
}
catch (ApplicationException) {
throw;
}
catch (Exception ex) {
if (!canLoadMethodBody(method)) {
Log.v("Invalid method body. {0:X8}", method.MetadataToken.ToInt32());
method.Body = new MethodBody(method);
if (isVerbose)
Logger.v("Invalid method body. {0:X8}", method.MDToken.ToInt32());
method.Body = new CilBody();
}
else {
Log.w("Could not deobfuscate method {0:X8}. Hello, E.T.: {1}", // E.T. = exception type
method.MetadataToken.ToInt32(),
Logger.w("Could not deobfuscate method {0:X8}. Hello, E.T.: {1}", // E.T. = exception type
method.MDToken.ToInt32(),
ex.GetType());
}
}
finally {
Log.indentLevel = oldIndentLevel;
Logger.Instance.IndentLevel = oldIndentLevel;
}
removeNoInliningAttribute(method);
Log.deIndent();
if (isVerbose)
Logger.Instance.deIndent();
}
}
static bool canLoadMethodBody(MethodDefinition method) {
static bool canLoadMethodBody(MethodDef method) {
try {
var body = method.Body;
return true;
@ -569,7 +601,7 @@ namespace de4dot.code {
}
}
void deobfuscate(MethodDefinition method, BlocksCflowDeobfuscator cflowDeobfuscator, MethodPrinter methodPrinter) {
void deobfuscate(MethodDef method, BlocksCflowDeobfuscator cflowDeobfuscator, MethodPrinter methodPrinter, bool isVerbose, bool isVV) {
if (!hasNonEmptyBody(method))
return;
@ -587,7 +619,10 @@ namespace de4dot.code {
cflowDeobfuscator.deobfuscate();
if (options.ControlFlowDeobfuscation) {
numRemovedLocals = blocks.optimizeLocals();
// Don't remove any locals if we should preserve tokens or we won't be able
// to always preserve StandAloneSig tokens.
if (!ShouldPreserveTokens())
numRemovedLocals = blocks.optimizeLocals();
blocks.repartitionBlocks();
}
@ -599,22 +634,21 @@ namespace de4dot.code {
blocks.getCode(out allInstructions, out allExceptionHandlers);
DotNetUtils.restoreBody(method, allInstructions, allExceptionHandlers);
if (numRemovedLocals > 0)
Log.v("Removed {0} unused local(s)", numRemovedLocals);
if (isVerbose && numRemovedLocals > 0)
Logger.v("Removed {0} unused local(s)", numRemovedLocals);
int numRemovedInstructions = oldNumInstructions - method.Body.Instructions.Count;
if (numRemovedInstructions > 0)
Log.v("Removed {0} dead instruction(s)", numRemovedInstructions);
if (isVerbose && numRemovedInstructions > 0)
Logger.v("Removed {0} dead instruction(s)", numRemovedInstructions);
const Log.LogLevel dumpLogLevel = Log.LogLevel.veryverbose;
if (Log.isAtLeast(dumpLogLevel)) {
Log.log(dumpLogLevel, "Deobfuscated code:");
Log.indent();
methodPrinter.print(dumpLogLevel, allInstructions, allExceptionHandlers);
Log.deIndent();
if (isVV) {
Logger.log(LoggerEvent.VeryVerbose, "Deobfuscated code:");
Logger.Instance.indent();
methodPrinter.print(LoggerEvent.VeryVerbose, allInstructions, allExceptionHandlers);
Logger.Instance.deIndent();
}
}
bool hasNonEmptyBody(MethodDefinition method) {
bool hasNonEmptyBody(MethodDef method) {
return method.HasBody && method.Body.Instructions.Count > 0;
}
@ -637,11 +671,11 @@ namespace de4dot.code {
}
}
void removeNoInliningAttribute(MethodDefinition method) {
method.ImplAttributes = method.ImplAttributes & ~MethodImplAttributes.NoInlining;
void removeNoInliningAttribute(MethodDef method) {
method.IsNoInlining = false;
for (int i = 0; i < method.CustomAttributes.Count; i++) {
var cattr = method.CustomAttributes[i];
if (cattr.AttributeType.FullName != "System.Runtime.CompilerServices.MethodImplAttribute")
if (cattr.TypeFullName != "System.Runtime.CompilerServices.MethodImplAttribute")
continue;
int options = 0;
if (!getMethodImplOptions(cattr, ref options))
@ -654,9 +688,11 @@ namespace de4dot.code {
}
static bool getMethodImplOptions(CustomAttribute cattr, ref int value) {
if (cattr.IsRawBlob)
return false;
if (cattr.ConstructorArguments.Count != 1)
return false;
if (cattr.ConstructorArguments[0].Type.FullName != "System.Int16" &&
if (cattr.ConstructorArguments[0].Type.ElementType != ElementType.I2 &&
cattr.ConstructorArguments[0].Type.FullName != "System.Runtime.CompilerServices.MethodImplOptions")
return false;
@ -683,20 +719,20 @@ namespace de4dot.code {
enum SimpleDeobFlags {
HasDeobfuscated = 0x1,
}
Dictionary<MethodDefinition, SimpleDeobFlags> simpleDeobfuscatorFlags = new Dictionary<MethodDefinition, SimpleDeobFlags>();
bool check(MethodDefinition method, SimpleDeobFlags flag) {
Dictionary<MethodDef, SimpleDeobFlags> simpleDeobfuscatorFlags = new Dictionary<MethodDef, SimpleDeobFlags>();
bool check(MethodDef method, SimpleDeobFlags flag) {
SimpleDeobFlags oldFlags;
simpleDeobfuscatorFlags.TryGetValue(method, out oldFlags);
simpleDeobfuscatorFlags[method] = oldFlags | flag;
return (oldFlags & flag) == flag;
}
void deobfuscate(MethodDefinition method, string msg, Action<Blocks> handler) {
void deobfuscate(MethodDef method, string msg, Action<Blocks> handler) {
if (savedMethodBodies != null)
savedMethodBodies.save(method);
Log.v("{0}: {1} ({2:X8})", msg, Utils.removeNewlines(method), method.MetadataToken.ToUInt32());
Log.indent();
Logger.v("{0}: {1} ({2:X8})", msg, Utils.removeNewlines(method), method.MDToken.ToUInt32());
Logger.Instance.indent();
if (hasNonEmptyBody(method)) {
try {
@ -710,18 +746,18 @@ namespace de4dot.code {
DotNetUtils.restoreBody(method, allInstructions, allExceptionHandlers);
}
catch {
Log.v("Could not deobfuscate {0:X8}", method.MetadataToken.ToInt32());
Logger.v("Could not deobfuscate {0:X8}", method.MDToken.ToInt32());
}
}
Log.deIndent();
Logger.Instance.deIndent();
}
void ISimpleDeobfuscator.deobfuscate(MethodDefinition method) {
void ISimpleDeobfuscator.deobfuscate(MethodDef method) {
((ISimpleDeobfuscator)this).deobfuscate(method, false);
}
void ISimpleDeobfuscator.deobfuscate(MethodDefinition method, bool force) {
void ISimpleDeobfuscator.deobfuscate(MethodDef method, bool force) {
if (!force && check(method, SimpleDeobFlags.HasDeobfuscated))
return;
@ -732,7 +768,7 @@ namespace de4dot.code {
});
}
void ISimpleDeobfuscator.decryptStrings(MethodDefinition method, IDeobfuscator theDeob) {
void ISimpleDeobfuscator.decryptStrings(MethodDef method, IDeobfuscator theDeob) {
deobfuscate(method, "Static string decryption", (blocks) => theDeob.deobfuscateStrings(blocks));
}
@ -741,7 +777,7 @@ namespace de4dot.code {
extension = ".dll";
var baseDir = Utils.getDirName(options.NewFilename);
var newName = Path.Combine(baseDir, assemblyName + extension);
Log.n("Creating file {0}", newName);
Logger.n("Creating file {0}", newName);
using (var writer = new BinaryWriter(new FileStream(newName, FileMode.Create))) {
writer.Write(data);
}
@ -754,5 +790,13 @@ namespace de4dot.code {
void IDeobfuscatedFile.setDeobfuscator(IDeobfuscator deob) {
this.deob = deob;
}
public void Dispose() {
deobfuscateCleanUp();
if (module != null)
module.Dispose();
module = null;
deob = null;
}
}
}

View File

@ -19,8 +19,8 @@
using System;
using System.Collections.Generic;
using Mono.Cecil;
using Mono.Cecil.Cil;
using dot10.DotNet;
using dot10.DotNet.Emit;
using de4dot.code.AssemblyClient;
using de4dot.blocks;
@ -49,7 +49,7 @@ namespace de4dot.code {
if (ldstrIndex + 1 < block.Instructions.Count) {
var instr = block.Instructions[ldstrIndex + 1];
if (instr.OpCode.Code == Code.Call) {
var calledMethod = instr.Operand as MethodReference;
var calledMethod = instr.Operand as IMethod;
if (calledMethod != null &&
calledMethod.FullName == "System.String System.String::Intern(System.String)") {
block.remove(ldstrIndex + 1, 1);
@ -57,7 +57,7 @@ namespace de4dot.code {
}
}
Log.v("Decrypted string: {0}", Utils.toCsharpString(decryptedString));
Logger.v("Decrypted string: {0}", Utils.toCsharpString(decryptedString));
}
}
}
@ -68,8 +68,8 @@ namespace de4dot.code {
class MyCallResult : CallResult {
public int methodId;
public GenericInstanceMethod gim;
public MyCallResult(Block block, int callEndIndex, int methodId, GenericInstanceMethod gim)
public MethodSpec gim;
public MyCallResult(Block block, int callEndIndex, int methodId, MethodSpec gim)
: base(block, callEndIndex) {
this.methodId = methodId;
this.gim = gim;
@ -93,9 +93,9 @@ namespace de4dot.code {
}
}
protected override CallResult createCallResult(MethodReference method, GenericInstanceMethod gim, Block block, int callInstrIndex) {
protected override CallResult createCallResult(IMethod method, MethodSpec gim, Block block, int callInstrIndex) {
int methodId;
if (!methodTokenToId.TryGetValue(method.MetadataToken.ToInt32(), out methodId))
if (!methodTokenToId.TryGetValue(method.MDToken.ToInt32(), out methodId))
return null;
return new MyCallResult(block, callInstrIndex, methodId, gim);
}
@ -117,7 +117,7 @@ namespace de4dot.code {
AssemblyData.SimpleData.pack(list[i].args);
args[i] = list[i].args;
}
var decryptedStrings = assemblyClient.Service.decryptStrings(methodId, args, Method.MetadataToken.ToInt32());
var decryptedStrings = assemblyClient.Service.decryptStrings(methodId, args, Method.MDToken.ToInt32());
if (decryptedStrings.Length != args.Length)
throw new ApplicationException("Invalid decrypted strings array length");
AssemblyData.SimpleData.unpack(decryptedStrings);
@ -128,27 +128,27 @@ namespace de4dot.code {
}
class StaticStringInliner : StringInlinerBase {
MethodDefinitionAndDeclaringTypeDict<Func<MethodDefinition, GenericInstanceMethod, object[], string>> stringDecrypters = new MethodDefinitionAndDeclaringTypeDict<Func<MethodDefinition, GenericInstanceMethod, object[], string>>();
MethodDefinitionAndDeclaringTypeDict<Func<MethodDef, MethodSpec, object[], string>> stringDecrypters = new MethodDefinitionAndDeclaringTypeDict<Func<MethodDef, MethodSpec, object[], string>>();
public override bool HasHandlers {
get { return stringDecrypters.Count != 0; }
}
public IEnumerable<MethodDefinition> Methods {
public IEnumerable<MethodDef> Methods {
get { return stringDecrypters.getKeys(); }
}
class MyCallResult : CallResult {
public MethodReference methodReference;
public GenericInstanceMethod gim;
public MyCallResult(Block block, int callEndIndex, MethodReference method, GenericInstanceMethod gim)
public IMethod IMethod;
public MethodSpec gim;
public MyCallResult(Block block, int callEndIndex, IMethod method, MethodSpec gim)
: base(block, callEndIndex) {
this.methodReference = method;
this.IMethod = method;
this.gim = gim;
}
}
public void add(MethodDefinition method, Func<MethodDefinition, GenericInstanceMethod, object[], string> handler) {
public void add(MethodDef method, Func<MethodDef, MethodSpec, object[], string> handler) {
if (method != null)
stringDecrypters.add(method, handler);
}
@ -156,12 +156,12 @@ namespace de4dot.code {
protected override void inlineAllCalls() {
foreach (var tmp in callResults) {
var callResult = (MyCallResult)tmp;
var handler = stringDecrypters.find(callResult.methodReference);
callResult.returnValue = handler((MethodDefinition)callResult.methodReference, callResult.gim, callResult.args);
var handler = stringDecrypters.find(callResult.IMethod);
callResult.returnValue = handler((MethodDef)callResult.IMethod, callResult.gim, callResult.args);
}
}
protected override CallResult createCallResult(MethodReference method, GenericInstanceMethod gim, Block block, int callInstrIndex) {
protected override CallResult createCallResult(IMethod method, MethodSpec gim, Block block, int callInstrIndex) {
if (stringDecrypters.find(method) == null)
return null;
return new MyCallResult(block, callInstrIndex, method, gim);

View File

@ -21,6 +21,8 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using dot10.DotNet;
using dot10.IO;
namespace de4dot.code {
// These are in .NET 3.5 and later...
@ -61,6 +63,10 @@ namespace de4dot.code {
return dict.Keys;
}
public static string toCsharpString(UTF8String s) {
return toCsharpString(UTF8String.ToSystemStringOrEmpty(s));
}
public static string toCsharpString(string s) {
var sb = new StringBuilder(s.Length + 2);
sb.Append('"');
@ -209,12 +215,6 @@ namespace de4dot.code {
return true;
}
public static int compareInt32(int a, int b) {
if (a < b) return -1;
if (a > b) return 1;
return 0;
}
public static byte[] readFile(string filename) {
// If the file is on the network, and we read more than 2MB, we'll read from the wrong
// offset in the file! Tested: VMware 8, Win7 x64.
@ -232,22 +232,5 @@ namespace de4dot.code {
return fileData;
}
}
public static uint readEncodedUInt32(BinaryReader reader) {
uint val = 0;
int bits = 0;
for (int i = 0; i < 5; i++) {
byte b = reader.ReadByte();
val |= (uint)(b & 0x7F) << bits;
if ((b & 0x80) == 0)
return val;
bits += 7;
}
throw new ApplicationException("Invalid encoded int32");
}
public static int readEncodedInt32(BinaryReader reader) {
return (int)readEncodedUInt32(reader);
}
}
}

View File

@ -60,8 +60,28 @@
<Compile Include="AssemblyClient\NewAppDomainAssemblyServerLoader.cs" />
<Compile Include="AssemblyClient\NewProcessAssemblyServerLoader.cs" />
<Compile Include="AssemblyClient\SameAppDomainAssemblyServerLoader.cs" />
<Compile Include="AssemblyModule.cs" />
<Compile Include="AssemblyResolver.cs" />
<Compile Include="DeobfuscatorContext.cs" />
<Compile Include="deobfuscators\Agile_NET\CliSecureRtType.cs" />
<Compile Include="deobfuscators\Agile_NET\CsBlowfish.cs" />
<Compile Include="deobfuscators\Agile_NET\Deobfuscator.cs" />
<Compile Include="deobfuscators\Agile_NET\MethodsDecrypter.cs" />
<Compile Include="deobfuscators\Agile_NET\ProxyCallFixer.cs" />
<Compile Include="deobfuscators\Agile_NET\ResourceDecrypter.cs" />
<Compile Include="deobfuscators\Agile_NET\StackFrameHelper.cs" />
<Compile Include="deobfuscators\Agile_NET\StringDecrypter.cs" />
<Compile Include="deobfuscators\Agile_NET\vm\CilOperandInstructionRestorer.cs" />
<Compile Include="deobfuscators\Agile_NET\vm\Csvm.cs" />
<Compile Include="deobfuscators\Agile_NET\vm\CsvmDataReader.cs" />
<Compile Include="deobfuscators\Agile_NET\vm\CsvmMethodData.cs" />
<Compile Include="deobfuscators\Agile_NET\vm\CsvmToCilMethodConverter.cs" />
<Compile Include="deobfuscators\Agile_NET\vm\FieldsInfo.cs" />
<Compile Include="deobfuscators\Agile_NET\vm\OpCodeHandler.cs" />
<Compile Include="deobfuscators\Agile_NET\vm\OpCodeHandlers.cs" />
<Compile Include="deobfuscators\Agile_NET\vm\UnknownHandlerInfo.cs" />
<Compile Include="deobfuscators\Agile_NET\vm\VmOpCodeHandlerDetector.cs" />
<Compile Include="deobfuscators\Agile_NET\vm\VmOperands.cs" />
<Compile Include="deobfuscators\ArrayFinder.cs" />
<Compile Include="deobfuscators\Babel_NET\AssemblyResolver.cs" />
<Compile Include="deobfuscators\Babel_NET\BabelInflater.cs" />
@ -96,109 +116,84 @@
<Compile Include="deobfuscators\Confuser\Unpacker.cs" />
<Compile Include="deobfuscators\Confuser\VersionDetector.cs" />
<Compile Include="deobfuscators\Confuser\x86Emulator.cs" />
<Compile Include="deobfuscators\CryptoObfuscator\CoUtils.cs" />
<Compile Include="deobfuscators\CryptoObfuscator\MethodBodyReader.cs" />
<Compile Include="deobfuscators\CryptoObfuscator\MethodsDecrypter.cs" />
<Compile Include="deobfuscators\dotNET_Reactor\v4\ProxyCallFixer.cs" />
<Compile Include="deobfuscators\ILProtector\MethodReader.cs" />
<Compile Include="deobfuscators\ILProtector\MethodsDecrypter.cs" />
<Compile Include="deobfuscators\DeepSea\ArrayBlockState.cs" />
<Compile Include="deobfuscators\MaxtoCode\CryptDecrypter.cs" />
<Compile Include="deobfuscators\MaxtoCode\Decrypter6.cs" />
<Compile Include="deobfuscators\MaxtoCode\DecrypterInfo.cs" />
<Compile Include="deobfuscators\MaxtoCode\EncryptionInfos.cs" />
<Compile Include="deobfuscators\MaxtoCode\McKey.cs" />
<Compile Include="deobfuscators\MaxtoCode\PeHeader.cs" />
<Compile Include="deobfuscators\MaxtoCode\StringDecrypter.cs" />
<Compile Include="deobfuscators\CryptoObfuscator\ConstantsDecrypter.cs" />
<Compile Include="deobfuscators\MethodBodyReaderBase.cs" />
<Compile Include="deobfuscators\Babel_NET\MethodsDecrypter.cs" />
<Compile Include="deobfuscators\Babel_NET\ProxyCallFixer.cs" />
<Compile Include="deobfuscators\Babel_NET\ResourceDecrypter.cs" />
<Compile Include="deobfuscators\Babel_NET\ResourceResolver.cs" />
<Compile Include="deobfuscators\Babel_NET\StringDecrypter.cs" />
<Compile Include="deobfuscators\Blowfish.cs" />
<Compile Include="deobfuscators\CliSecure\CliSecureRtType.cs" />
<Compile Include="deobfuscators\CliSecure\CsBlowfish.cs" />
<Compile Include="deobfuscators\CliSecure\Deobfuscator.cs" />
<Compile Include="deobfuscators\CliSecure\MethodsDecrypter.cs" />
<Compile Include="deobfuscators\CliSecure\ProxyCallFixer.cs" />
<Compile Include="deobfuscators\CliSecure\ResourceDecrypter.cs" />
<Compile Include="deobfuscators\CliSecure\StackFrameHelper.cs" />
<Compile Include="deobfuscators\CliSecure\StringDecrypter.cs" />
<Compile Include="deobfuscators\CliSecure\vm\CilOperandInstructionRestorer.cs" />
<Compile Include="deobfuscators\CliSecure\vm\Csvm.cs" />
<Compile Include="deobfuscators\CliSecure\vm\CsvmDataReader.cs" />
<Compile Include="deobfuscators\CliSecure\vm\CsvmMethodData.cs" />
<Compile Include="deobfuscators\CliSecure\vm\CsvmToCilMethodConverter.cs" />
<Compile Include="deobfuscators\CliSecure\vm\FieldsInfo.cs" />
<Compile Include="deobfuscators\CliSecure\vm\OpCodeHandler.cs" />
<Compile Include="deobfuscators\CliSecure\vm\OpCodeHandlers.cs" />
<Compile Include="deobfuscators\CliSecure\vm\UnknownHandlerInfo.cs" />
<Compile Include="deobfuscators\CliSecure\vm\VmOpCodeHandlerDetector.cs" />
<Compile Include="deobfuscators\CliSecure\vm\VmOperands.cs" />
<Compile Include="deobfuscators\CodeFort\PasswordFinder.cs" />
<Compile Include="deobfuscators\CodeFort\AssemblyData.cs" />
<Compile Include="deobfuscators\CodeFort\AssemblyDecrypter.cs" />
<Compile Include="deobfuscators\CodeFort\CfMethodCallInliner.cs" />
<Compile Include="deobfuscators\CodeFort\Deobfuscator.cs" />
<Compile Include="deobfuscators\CodeFort\PasswordFinder.cs" />
<Compile Include="deobfuscators\CodeFort\ProxyCallFixer.cs" />
<Compile Include="deobfuscators\CodeFort\StringDecrypter.cs" />
<Compile Include="deobfuscators\CodeVeil\AssemblyResolver.cs" />
<Compile Include="deobfuscators\CodeVeil\Deobfuscator.cs" />
<Compile Include="deobfuscators\CodeVeil\ErexResourceReader.cs" />
<Compile Include="deobfuscators\CodeVeil\InvalidDataException.cs" />
<Compile Include="deobfuscators\CodeVeil\InvalidMethodsFinder.cs" />
<Compile Include="deobfuscators\CodeVeil\MainType.cs" />
<Compile Include="deobfuscators\CodeVeil\MethodsDecrypter.cs" />
<Compile Include="deobfuscators\CodeVeil\ObfuscatorVersion.cs" />
<Compile Include="deobfuscators\CodeVeil\ProxyCallFixer.cs" />
<Compile Include="deobfuscators\CodeVeil\ResourceConverter.cs" />
<Compile Include="deobfuscators\CodeVeil\ResourceDecrypter.cs" />
<Compile Include="deobfuscators\CodeVeil\ResourceInfo.cs" />
<Compile Include="deobfuscators\CodeVeil\ResourceReader.cs" />
<Compile Include="deobfuscators\CodeVeil\StringDecrypter.cs" />
<Compile Include="deobfuscators\CodeVeil\Deobfuscator.cs" />
<Compile Include="deobfuscators\CodeVeil\ProxyCallFixer.cs" />
<Compile Include="deobfuscators\CodeVeil\TamperDetection.cs" />
<Compile Include="deobfuscators\CodeWall\AssemblyDecrypter.cs" />
<Compile Include="deobfuscators\CodeWall\Deobfuscator.cs" />
<Compile Include="deobfuscators\CodeWall\KeyGenerator.cs" />
<Compile Include="deobfuscators\CodeWall\MethodsDecrypter.cs" />
<Compile Include="deobfuscators\CodeWall\randomc\CRandomMersenne.cs" />
<Compile Include="deobfuscators\CodeWall\randomc\CRandomMother.cs" />
<Compile Include="deobfuscators\CodeWall\KeyGenerator.cs" />
<Compile Include="deobfuscators\CodeWall\StringDecrypter.cs" />
<Compile Include="deobfuscators\ConstantsReader.cs" />
<Compile Include="deobfuscators\CryptoObfuscator\AntiDebugger.cs" />
<Compile Include="deobfuscators\CryptoObfuscator\AssemblyResolver.cs" />
<Compile Include="deobfuscators\CryptoObfuscator\ConstantsDecrypter.cs" />
<Compile Include="deobfuscators\CryptoObfuscator\CoUtils.cs" />
<Compile Include="deobfuscators\CryptoObfuscator\Deobfuscator.cs" />
<Compile Include="deobfuscators\CryptoObfuscator\MethodBodyReader.cs" />
<Compile Include="deobfuscators\CryptoObfuscator\MethodsDecrypter.cs" />
<Compile Include="deobfuscators\CryptoObfuscator\ProxyCallFixer.cs" />
<Compile Include="deobfuscators\CryptoObfuscator\ResourceDecrypter.cs" />
<Compile Include="deobfuscators\CryptoObfuscator\ResourceResolver.cs" />
<Compile Include="deobfuscators\CryptoObfuscator\StringDecrypter.cs" />
<Compile Include="deobfuscators\CryptoObfuscator\TamperDetection.cs" />
<Compile Include="deobfuscators\DeepSea\ArrayBlockDeobfuscator.cs" />
<Compile Include="deobfuscators\DeepSea\ArrayBlockState.cs" />
<Compile Include="deobfuscators\DeepSea\AssemblyResolver.cs" />
<Compile Include="deobfuscators\DeepSea\CastDeobfuscator.cs" />
<Compile Include="deobfuscators\DeepSea\Deobfuscator.cs" />
<Compile Include="deobfuscators\DeepSea\DsConstantsReader.cs" />
<Compile Include="deobfuscators\DeepSea\DsInlinedMethodsFinder.cs" />
<Compile Include="deobfuscators\DeepSea\DsMethodCallInliner.cs" />
<Compile Include="deobfuscators\DeepSea\DsUtils.cs" />
<Compile Include="deobfuscators\DeepSea\FieldsRestorer.cs" />
<Compile Include="deobfuscators\DeobfuscatorBase.cs" />
<Compile Include="deobfuscators\DeobfuscatorInfoBase.cs" />
<Compile Include="deobfuscators\DeobUtils.cs" />
<Compile Include="deobfuscators\DeepSea\AssemblyResolver.cs" />
<Compile Include="deobfuscators\DeepSea\DsInlinedMethodsFinder.cs" />
<Compile Include="deobfuscators\DeepSea\ResolverBase.cs" />
<Compile Include="deobfuscators\DeepSea\ResourceResolver.cs" />
<Compile Include="deobfuscators\DeepSea\StringDecrypter.cs" />
<Compile Include="deobfuscators\DeepSea\Deobfuscator.cs" />
<Compile Include="deobfuscators\DeepSea\DsMethodCallInliner.cs" />
<Compile Include="deobfuscators\DeobfuscatorBase.cs" />
<Compile Include="deobfuscators\DeobfuscatorInfoBase.cs" />
<Compile Include="deobfuscators\DeobUtils.cs" />
<Compile Include="deobfuscators\Dotfuscator\Deobfuscator.cs" />
<Compile Include="deobfuscators\Dotfuscator\StringDecrypter.cs" />
<Compile Include="deobfuscators\dotNET_Reactor\MyPEImage.cs" />
<Compile Include="deobfuscators\dotNET_Reactor\v3\AntiStrongName.cs" />
<Compile Include="deobfuscators\dotNET_Reactor\v3\ApplicationModeDecrypter.cs" />
<Compile Include="deobfuscators\dotNET_Reactor\v3\ApplicationModeUnpacker.cs" />
<Compile Include="deobfuscators\dotNET_Reactor\v3\AssemblyResolver.cs" />
<Compile Include="deobfuscators\dotNET_Reactor\v3\DecrypterType.cs" />
<Compile Include="deobfuscators\dotNET_Reactor\v3\DecryptMethod.cs" />
<Compile Include="deobfuscators\dotNET_Reactor\v3\Deobfuscator.cs" />
<Compile Include="deobfuscators\dotNET_Reactor\v3\LibAssemblyResolver.cs" />
<Compile Include="deobfuscators\dotNET_Reactor\v3\MemoryPatcher.cs" />
<Compile Include="deobfuscators\dotNET_Reactor\v3\NativeLibSaver.cs" />
<Compile Include="deobfuscators\dotNET_Reactor\v4\AntiStrongName.cs" />
<Compile Include="deobfuscators\dotNET_Reactor\v4\AssemblyResolver.cs" />
<Compile Include="deobfuscators\dotNET_Reactor\v4\BooleanDecrypter.cs" />
<Compile Include="deobfuscators\dotNET_Reactor\v4\Deobfuscator.cs" />
@ -208,26 +203,20 @@
<Compile Include="deobfuscators\dotNET_Reactor\v4\MethodsDecrypter.cs" />
<Compile Include="deobfuscators\dotNET_Reactor\v4\NativeFileDecrypter.cs" />
<Compile Include="deobfuscators\dotNET_Reactor\v4\NativeImageUnpacker.cs" />
<Compile Include="deobfuscators\dotNET_Reactor\v4\ProxyCallFixer.cs" />
<Compile Include="deobfuscators\dotNET_Reactor\v4\ResourceResolver.cs" />
<Compile Include="deobfuscators\dotNET_Reactor\v4\StringDecrypter.cs" />
<Compile Include="deobfuscators\dotNET_Reactor\v4\AntiStrongName.cs" />
<Compile Include="deobfuscators\dotNET_Reactor\v3\AssemblyResolver.cs" />
<Compile Include="deobfuscators\dotNET_Reactor\v3\DecryptMethod.cs" />
<Compile Include="deobfuscators\dotNET_Reactor\v3\MemoryPatcher.cs" />
<Compile Include="deobfuscators\Eazfuscator_NET\AssemblyResolver.cs" />
<Compile Include="deobfuscators\Eazfuscator_NET\CodeCompilerMethodCallRestorer.cs" />
<Compile Include="deobfuscators\Eazfuscator_NET\EfConstantsReader.cs" />
<Compile Include="deobfuscators\Eazfuscator_NET\DecrypterType.cs" />
<Compile Include="deobfuscators\Eazfuscator_NET\Deobfuscator.cs" />
<Compile Include="deobfuscators\Eazfuscator_NET\EfConstantsReader.cs" />
<Compile Include="deobfuscators\Eazfuscator_NET\EfUtils.cs" />
<Compile Include="deobfuscators\Eazfuscator_NET\ResourceMethodsRestorer.cs" />
<Compile Include="deobfuscators\Eazfuscator_NET\ResourceResolver.cs" />
<Compile Include="deobfuscators\Eazfuscator_NET\StringDecrypter.cs" />
<Compile Include="deobfuscators\Eazfuscator_NET\VersionDetector.cs" />
<Compile Include="deobfuscators\ExceptionLoggerRemover.cs" />
<Compile Include="deobfuscators\ILProtector\Deobfuscator.cs" />
<Compile Include="deobfuscators\ILProtector\MainType.cs" />
<Compile Include="deobfuscators\MethodCallRestorerBase.cs" />
<Compile Include="deobfuscators\Goliath_NET\ArrayDecrypter.cs" />
<Compile Include="deobfuscators\Goliath_NET\ArrayValueInliner.cs" />
<Compile Include="deobfuscators\Goliath_NET\DecrypterBase.cs" />
@ -241,19 +230,33 @@
<Compile Include="deobfuscators\IDeobfuscatedFile.cs" />
<Compile Include="deobfuscators\IDeobfuscator.cs" />
<Compile Include="deobfuscators\IDeobfuscatorInfo.cs" />
<Compile Include="deobfuscators\ILProtector\Deobfuscator.cs" />
<Compile Include="deobfuscators\ILProtector\MainType.cs" />
<Compile Include="deobfuscators\ILProtector\MethodReader.cs" />
<Compile Include="deobfuscators\ILProtector\MethodsDecrypter.cs" />
<Compile Include="deobfuscators\InitializedDataCreator.cs" />
<Compile Include="deobfuscators\InlinedMethodsFinder.cs" />
<Compile Include="deobfuscators\ISimpleDeobfuscator.cs" />
<Compile Include="deobfuscators\MaxtoCode\CryptDecrypter.cs" />
<Compile Include="deobfuscators\MaxtoCode\Decrypter6.cs" />
<Compile Include="deobfuscators\MaxtoCode\DecrypterInfo.cs" />
<Compile Include="deobfuscators\MaxtoCode\Deobfuscator.cs" />
<Compile Include="deobfuscators\MaxtoCode\MethodsDecrypter.cs" />
<Compile Include="deobfuscators\MaxtoCode\EncryptionInfos.cs" />
<Compile Include="deobfuscators\MaxtoCode\MainType.cs" />
<Compile Include="deobfuscators\MethodBodyParser.cs" />
<Compile Include="deobfuscators\MaxtoCode\McKey.cs" />
<Compile Include="deobfuscators\MaxtoCode\MethodsDecrypter.cs" />
<Compile Include="deobfuscators\MaxtoCode\PeHeader.cs" />
<Compile Include="deobfuscators\MaxtoCode\StringDecrypter.cs" />
<Compile Include="deobfuscators\MemberReferenceBuilder.cs" />
<Compile Include="deobfuscators\MethodBodyParser.cs" />
<Compile Include="deobfuscators\MethodCallRestorerBase.cs" />
<Compile Include="deobfuscators\MethodCollection.cs" />
<Compile Include="deobfuscators\MethodsDecrypter.cs" />
<Compile Include="deobfuscators\MethodStack.cs" />
<Compile Include="deobfuscators\MPRESS\Deobfuscator.cs" />
<Compile Include="deobfuscators\MPRESS\Lzmat.cs" />
<Compile Include="deobfuscators\Operations.cs" />
<Compile Include="deobfuscators\ProxyCallFixerBase.cs" />
<Compile Include="deobfuscators\QuickLZ.cs" />
<Compile Include="deobfuscators\RandomNameChecker.cs" />
<Compile Include="deobfuscators\Rummage\Deobfuscator.cs" />
@ -261,14 +264,6 @@
<Compile Include="deobfuscators\Skater_NET\Deobfuscator.cs" />
<Compile Include="deobfuscators\Skater_NET\EnumClassFinder.cs" />
<Compile Include="deobfuscators\Skater_NET\StringDecrypter.cs" />
<Compile Include="deobfuscators\Spices_Net\Deobfuscator.cs" />
<Compile Include="deobfuscators\Spices_Net\QclzDecompressor.cs" />
<Compile Include="deobfuscators\Spices_Net\ResourceNamesRestorer.cs" />
<Compile Include="deobfuscators\Spices_Net\SpicesMethodCallInliner.cs" />
<Compile Include="deobfuscators\Spices_Net\StringDecrypter.cs" />
<Compile Include="deobfuscators\StringCounts.cs" />
<Compile Include="deobfuscators\Operations.cs" />
<Compile Include="deobfuscators\ProxyCallFixerBase.cs" />
<Compile Include="deobfuscators\SmartAssembly\AssemblyResolver.cs" />
<Compile Include="deobfuscators\SmartAssembly\AssemblyResolverInfo.cs" />
<Compile Include="deobfuscators\SmartAssembly\AutomatedErrorReportingFinder.cs" />
@ -285,6 +280,12 @@
<Compile Include="deobfuscators\SmartAssembly\StringDecrypterInfo.cs" />
<Compile Include="deobfuscators\SmartAssembly\StringEncoderClassFinder.cs" />
<Compile Include="deobfuscators\SmartAssembly\TamperProtectionRemover.cs" />
<Compile Include="deobfuscators\Spices_Net\Deobfuscator.cs" />
<Compile Include="deobfuscators\Spices_Net\QclzDecompressor.cs" />
<Compile Include="deobfuscators\Spices_Net\ResourceNamesRestorer.cs" />
<Compile Include="deobfuscators\Spices_Net\SpicesMethodCallInliner.cs" />
<Compile Include="deobfuscators\Spices_Net\StringDecrypter.cs" />
<Compile Include="deobfuscators\StringCounts.cs" />
<Compile Include="deobfuscators\TypesRestorer.cs" />
<Compile Include="deobfuscators\Unknown\Deobfuscator.cs" />
<Compile Include="deobfuscators\UnpackedFile.cs" />
@ -292,10 +293,10 @@
<Compile Include="deobfuscators\ValueInlinerBase.cs" />
<Compile Include="deobfuscators\Xenocode\Deobfuscator.cs" />
<Compile Include="deobfuscators\Xenocode\StringDecrypter.cs" />
<Compile Include="DumpedMethodsRestorer.cs" />
<Compile Include="IDeobfuscatorContext.cs" />
<Compile Include="IObfuscatedFile.cs" />
<Compile Include="Log.cs" />
<Compile Include="AssemblyModule.cs" />
<Compile Include="Logger.cs" />
<Compile Include="MethodPrinter.cs" />
<Compile Include="MethodReturnValueInliner.cs" />
<Compile Include="NameRegexes.cs" />
@ -303,7 +304,6 @@
<Compile Include="Option.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="renamer\asmmodules\EventDef.cs" />
<Compile Include="ExternalAssemblies.cs" />
<Compile Include="renamer\asmmodules\FieldDef.cs" />
<Compile Include="renamer\asmmodules\GenericParamDef.cs" />
<Compile Include="renamer\asmmodules\IResolver.cs" />
@ -331,11 +331,11 @@
<Compile Include="renamer\VariableNameState.cs" />
<Compile Include="resources\BuiltInResourceData.cs" />
<Compile Include="resources\IResourceData.cs" />
<Compile Include="resources\ResourceDataCreator.cs" />
<Compile Include="resources\ResourceElement.cs" />
<Compile Include="resources\ResourceElementSet.cs" />
<Compile Include="resources\ResourceReader.cs" />
<Compile Include="resources\ResourceTypeCode.cs" />
<Compile Include="resources\ResourceDataCreator.cs" />
<Compile Include="resources\ResourceWriter.cs" />
<Compile Include="resources\UserResourceData.cs" />
<Compile Include="resources\UserResourceType.cs" />
@ -362,14 +362,14 @@
<Project>{045B96F2-AF80-4C4C-8D27-E38635AC705E}</Project>
<Name>blocks</Name>
</ProjectReference>
<ProjectReference Include="..\cecil\Mono.Cecil.csproj">
<Project>{D68133BD-1E63-496E-9EDE-4FBDBF77B486}</Project>
<Name>Mono.Cecil</Name>
</ProjectReference>
<ProjectReference Include="..\de4dot.mdecrypt\de4dot.mdecrypt.csproj">
<Project>{5C93C5E2-196F-4877-BF65-96FEBFCEFCA1}</Project>
<Name>de4dot.mdecrypt</Name>
</ProjectReference>
<ProjectReference Include="..\dot10\src\dot10.csproj">
<Project>{FDFC1237-143F-4919-8318-4926901F4639}</Project>
<Name>dot10</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>

View File

@ -20,65 +20,49 @@
using System;
using System.Collections.Generic;
using System.IO;
using Mono.Cecil;
using dot10.DotNet;
using de4dot.blocks;
using de4dot.PE;
namespace de4dot.code.deobfuscators.CliSecure {
namespace de4dot.code.deobfuscators.Agile_NET {
class CliSecureRtType {
ModuleDefinition module;
TypeDefinition cliSecureRtType;
MethodDefinition postInitializeMethod;
MethodDefinition initializeMethod;
MethodDefinition stringDecrypterMethod;
MethodDefinition loadMethod;
ModuleDefMD module;
TypeDef cliSecureRtType;
MethodDef postInitializeMethod;
MethodDef initializeMethod;
MethodDef stringDecrypterMethod;
MethodDef loadMethod;
bool foundSig;
public bool Detected {
get { return foundSig || cliSecureRtType != null; }
}
public TypeDefinition Type {
public TypeDef Type {
get { return cliSecureRtType; }
}
public MethodDefinition StringDecrypterMethod {
public MethodDef StringDecrypterMethod {
get { return stringDecrypterMethod; }
}
public MethodDefinition PostInitializeMethod {
public MethodDef PostInitializeMethod {
get { return postInitializeMethod; }
}
public MethodDefinition InitializeMethod {
public MethodDef InitializeMethod {
get { return initializeMethod; }
}
public MethodDefinition LoadMethod {
public MethodDef LoadMethod {
get { return loadMethod; }
}
public IEnumerable<ModuleReference> DecryptModuleReferences {
get {
var list = new List<ModuleReference>();
addModuleReference(list, "_Initialize");
addModuleReference(list, "_Initialize64");
return list;
}
}
void addModuleReference(List<ModuleReference> list, string methodName) {
var method = DotNetUtils.getPInvokeMethod(cliSecureRtType, methodName);
if (method == null)
return;
list.Add(method.PInvokeInfo.Module);
}
public CliSecureRtType(ModuleDefinition module) {
public CliSecureRtType(ModuleDefMD module) {
this.module = module;
}
public CliSecureRtType(ModuleDefinition module, CliSecureRtType oldOne) {
public CliSecureRtType(ModuleDefMD module, CliSecureRtType oldOne) {
this.module = module;
cliSecureRtType = lookup(oldOne.cliSecureRtType, "Could not find CliSecureRt type");
postInitializeMethod = lookup(oldOne.postInitializeMethod, "Could not find postInitializeMethod method");
@ -88,7 +72,7 @@ namespace de4dot.code.deobfuscators.CliSecure {
foundSig = oldOne.foundSig;
}
T lookup<T>(T def, string errorMessage) where T : MemberReference {
T lookup<T>(T def, string errorMessage) where T : class, ICodedToken {
return DeobUtils.lookup(module, def, errorMessage);
}
@ -147,13 +131,13 @@ namespace de4dot.code.deobfuscators.CliSecure {
foreach (var type in module.Types) {
if (type.Fields.Count != 1)
continue;
if (type.Fields[0].FieldType.FullName != "System.Byte[]")
if (type.Fields[0].FieldSig.GetFieldType().GetFullName() != "System.Byte[]")
continue;
if (type.Methods.Count != 2)
continue;
if (DotNetUtils.getMethod(type, ".cctor") == null)
if (type.FindStaticConstructor() == null)
continue;
var cs = DotNetUtils.getMethod(type, "cs");
var cs = type.FindMethod("cs");
if (cs == null)
continue;
@ -165,7 +149,7 @@ namespace de4dot.code.deobfuscators.CliSecure {
return false;
}
static MethodDefinition findStringDecrypterMethod(TypeDefinition type) {
static MethodDef findStringDecrypterMethod(TypeDef type) {
foreach (var method in type.Methods) {
if (method.Body == null || !method.IsStatic)
continue;
@ -178,7 +162,7 @@ namespace de4dot.code.deobfuscators.CliSecure {
return null;
}
static MethodDefinition findMethod(TypeDefinition type, string returnType, string name, string parameters) {
static MethodDef findMethod(TypeDef type, string returnType, string name, string parameters) {
var methodName = returnType + " " + type.FullName + "::" + name + parameters;
foreach (var method in type.Methods) {
if (method.Body == null || !method.IsStatic)
@ -192,16 +176,17 @@ namespace de4dot.code.deobfuscators.CliSecure {
return null;
}
static bool hasInitializeMethod(TypeDefinition type, string name) {
static bool hasInitializeMethod(TypeDef type, string name) {
var method = DotNetUtils.getPInvokeMethod(type, name);
if (method == null)
return false;
if (method.Parameters.Count != 1)
var sig = method.MethodSig;
if (sig.Params.Count != 1)
return false;
if (method.Parameters[0].ParameterType.FullName != "System.IntPtr")
if (sig.Params[0].GetElementType() != ElementType.I)
return false;
var retType = method.MethodReturnType.ReturnType.FullName;
if (retType != "System.Void" && retType != "System.Int32")
var retType = sig.RetType.GetElementType();
if (retType != ElementType.Void && retType != ElementType.I4)
return false;
return true;
}
@ -209,7 +194,7 @@ namespace de4dot.code.deobfuscators.CliSecure {
bool findNativeCode(byte[] moduleBytes) {
var stream = moduleBytes != null ?
(Stream)new MemoryStream(moduleBytes) :
(Stream)new FileStream(module.FullyQualifiedName, FileMode.Open, FileAccess.Read, FileShare.Read);
(Stream)new FileStream(module.Location, FileMode.Open, FileAccess.Read, FileShare.Read);
using (stream) {
var peImage = new PeImage(stream);
return foundSig = MethodsDecrypter.detect(peImage);
@ -239,7 +224,7 @@ namespace de4dot.code.deobfuscators.CliSecure {
}
}
static bool isOldStringDecrypterMethod(MethodDefinition method) {
static bool isOldStringDecrypterMethod(MethodDef method) {
if (method == null || method.Body == null || !method.IsStatic)
return false;
if (!DotNetUtils.isMethod(method, "System.String", "(System.String)"))

View File

@ -17,7 +17,7 @@
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
*/
namespace de4dot.code.deobfuscators.CliSecure {
namespace de4dot.code.deobfuscators.Agile_NET {
class CsBlowfish : Blowfish {
public CsBlowfish() {
}

View File

@ -19,15 +19,16 @@
using System;
using System.Collections.Generic;
using Mono.Cecil;
using Mono.MyStuff;
using dot10.IO;
using dot10.PE;
using dot10.DotNet;
using de4dot.blocks;
using de4dot.PE;
namespace de4dot.code.deobfuscators.CliSecure {
namespace de4dot.code.deobfuscators.Agile_NET {
public class DeobfuscatorInfo : DeobfuscatorInfoBase {
public const string THE_NAME = "CliSecure";
public const string THE_TYPE = "cs";
public const string THE_NAME = "Agile.NET";
public const string THE_TYPE = "an";
const string DEFAULT_REGEX = @"[a-zA-Z_0-9>}$]$";
BoolOption decryptMethods;
BoolOption decryptResources;
@ -78,7 +79,7 @@ namespace de4dot.code.deobfuscators.CliSecure {
Options options;
string obfuscatorName = DeobfuscatorInfo.THE_NAME;
List<TypeDefinition> cliSecureAttributes = new List<TypeDefinition>();
List<TypeDef> cliSecureAttributes = new List<TypeDef>();
ProxyCallFixer proxyCallFixer;
CliSecureRtType cliSecureRtType;
StringDecrypter stringDecrypter;
@ -112,27 +113,29 @@ namespace de4dot.code.deobfuscators.CliSecure {
this.options = options;
}
public override void init(ModuleDefinition module) {
public override void init(ModuleDefMD module) {
base.init(module);
}
public override byte[] unpackNativeFile(PeImage peImage) {
public override byte[] unpackNativeFile(IPEImage peImage) {
return unpackNativeFile1(peImage) ?? unpackNativeFile2(peImage);
}
// Old CS versions
byte[] unpackNativeFile1(PeImage peImage) {
byte[] unpackNativeFile1(IPEImage peImage) {
const int dataDirNum = 6; // debug dir
const int dotNetDirNum = 14;
if (peImage.OptionalHeader.dataDirectories[dataDirNum].virtualAddress == 0)
var optHeader = peImage.ImageNTHeaders.OptionalHeader;
if (optHeader.DataDirectories[dataDirNum].VirtualAddress == 0)
return null;
if (peImage.OptionalHeader.dataDirectories[dataDirNum].size != 0x48)
if (optHeader.DataDirectories[dataDirNum].Size != 0x48)
return null;
var fileData = peImage.readAllBytes();
int dataDir = (int)peImage.OptionalHeader.offsetOfDataDirectory(dataDirNum);
int dotNetDir = (int)peImage.OptionalHeader.offsetOfDataDirectory(dotNetDirNum);
var fileData = peImage.GetImageAsByteArray();
long dataDirBaseOffset = (long)optHeader.DataDirectories[0].StartOffset;
int dataDir = (int)dataDirBaseOffset + dataDirNum * 8;
int dotNetDir = (int)dataDirBaseOffset + dotNetDirNum * 8;
writeUInt32(fileData, dotNetDir, BitConverter.ToUInt32(fileData, dataDir));
writeUInt32(fileData, dotNetDir + 4, BitConverter.ToUInt32(fileData, dataDir + 4));
writeUInt32(fileData, dataDir, 0);
@ -142,17 +145,12 @@ namespace de4dot.code.deobfuscators.CliSecure {
}
// CS 1.x
byte[] unpackNativeFile2(PeImage peImage) {
var dir = peImage.Resources.getRoot();
if ((dir = dir.getDirectory("ASSEMBLY")) == null)
return null;
if ((dir = dir.getDirectory(101)) == null)
return null;
var data = dir.getData(0);
byte[] unpackNativeFile2(IPEImage peImage) {
var data = peImage.FindWin32ResourceData("ASSEMBLY", 101, 0);
if (data == null)
return null;
return ModuleBytes = peImage.readBytes(data.RVA, (int)data.Size);
return ModuleBytes = data.Data.ReadAllBytes();
}
static void writeUInt32(byte[] data, int offset, uint value) {
@ -213,7 +211,7 @@ namespace de4dot.code.deobfuscators.CliSecure {
var peImage = new PeImage(fileData);
if (!new MethodsDecrypter().decrypt(peImage, module, cliSecureRtType, ref dumpedMethods)) {
Log.v("Methods aren't encrypted or invalid signature");
Logger.v("Methods aren't encrypted or invalid signature");
return false;
}
@ -221,7 +219,7 @@ namespace de4dot.code.deobfuscators.CliSecure {
return true;
}
public override IDeobfuscator moduleReloaded(ModuleDefinition module) {
public override IDeobfuscator moduleReloaded(ModuleDefMD module) {
var newOne = new Deobfuscator(options);
newOne.setModule(module);
newOne.cliSecureAttributes = lookup(module, cliSecureAttributes, "Could not find CliSecure attribute");
@ -233,8 +231,8 @@ namespace de4dot.code.deobfuscators.CliSecure {
return newOne;
}
static List<TypeDefinition> lookup(ModuleDefinition module, List<TypeDefinition> types, string errorMsg) {
var list = new List<TypeDefinition>(types.Count);
static List<TypeDef> lookup(ModuleDefMD module, List<TypeDef> types, string errorMsg) {
var list = new List<TypeDef>(types.Count);
foreach (var type in types)
list.Add(DeobUtils.lookup(module, type, errorMsg));
return list;
@ -274,7 +272,6 @@ namespace de4dot.code.deobfuscators.CliSecure {
if (options.RestoreVmCode) {
csvm.restore();
addAssemblyReferenceToBeRemoved(csvm.VmAssemblyReference, "CSVM assembly reference");
addResourceToBeRemoved(csvm.Resource, "CSVM data resource");
}
}
@ -308,19 +305,20 @@ namespace de4dot.code.deobfuscators.CliSecure {
}
if (options.DecryptMethods) {
addResources("Obfuscator protection files");
addModuleReferencesToBeRemoved(cliSecureRtType.DecryptModuleReferences, "Obfuscator protection files");
addModuleReferences("Obfuscator protection files");
}
module.Attributes |= ModuleAttributes.ILOnly;
base.deobfuscateEnd();
// Call hasNativeMethods() after all types/methods/etc have been removed since
// some of the removed methods could be native methods
if (!module.IsILOnly && !hasNativeMethods())
module.IsILOnly = true;
}
public override IEnumerable<int> getStringDecrypterMethods() {
var list = new List<int>();
if (stringDecrypter.Method != null)
list.Add(stringDecrypter.Method.MetadataToken.ToInt32());
list.Add(stringDecrypter.Method.MDToken.ToInt32());
return list;
}
@ -328,7 +326,7 @@ namespace de4dot.code.deobfuscators.CliSecure {
if (!options.RemoveStackFrameHelper)
return;
if (stackFrameHelper.ExceptionLoggerRemover.remove(blocks))
Log.v("Removed StackFrameHelper code");
Logger.v("Removed StackFrameHelper code");
}
}
}

View File

@ -20,11 +20,11 @@
using System;
using System.Collections.Generic;
using System.IO;
using Mono.MyStuff;
using dot10.DotNet;
using de4dot.PE;
using de4dot.blocks;
namespace de4dot.code.deobfuscators.CliSecure {
namespace de4dot.code.deobfuscators.Agile_NET {
class CodeHeader {
public byte[] signature;
public byte[] decryptionKey;
@ -62,7 +62,7 @@ namespace de4dot.code.deobfuscators.CliSecure {
}
PeImage peImage;
Mono.Cecil.ModuleDefinition module;
ModuleDefMD module;
CliSecureRtType csRtType;
CodeHeader codeHeader = new CodeHeader();
IDecrypter decrypter;
@ -155,7 +155,7 @@ namespace de4dot.code.deobfuscators.CliSecure {
public Decrypter5(PeImage peImage, CodeHeader codeHeader, uint codeHeaderSize)
: base(peImage, codeHeader) {
this.codeHeaderSize = codeHeaderSize;
this.codeHeaderSize = codeHeaderSize;
}
public override MethodBodyHeader decrypt(MethodInfo methodInfo, out byte[] code, out byte[] extraSections) {
@ -434,7 +434,7 @@ namespace de4dot.code.deobfuscators.CliSecure {
Error,
}
public bool decrypt(PeImage peImage, Mono.Cecil.ModuleDefinition module, CliSecureRtType csRtType, ref DumpedMethods dumpedMethods) {
public bool decrypt(PeImage peImage, ModuleDefMD module, CliSecureRtType csRtType, ref DumpedMethods dumpedMethods) {
this.peImage = peImage;
this.csRtType = csRtType;
this.module = module;
@ -444,9 +444,9 @@ namespace de4dot.code.deobfuscators.CliSecure {
case DecryptResult.NotEncrypted: return false;
case DecryptResult.Error:
Log.w("Using dynamic method decryption");
Logger.w("Using dynamic method decryption");
byte[] moduleCctorBytes = getModuleCctorBytes(csRtType);
dumpedMethods = de4dot.code.deobfuscators.MethodsDecrypter.decrypt(module.FullyQualifiedName, moduleCctorBytes);
dumpedMethods = de4dot.code.deobfuscators.MethodsDecrypter.decrypt(module.Location, moduleCctorBytes);
return true;
default:
@ -458,7 +458,7 @@ namespace de4dot.code.deobfuscators.CliSecure {
var initMethod = csRtType.InitializeMethod;
if (initMethod == null)
return null;
uint initToken = initMethod.MetadataToken.ToUInt32();
uint initToken = initMethod.MDToken.ToUInt32();
var moduleCctorBytes = new byte[6];
moduleCctorBytes[0] = 0x28; // call
moduleCctorBytes[1] = (byte)initToken;
@ -542,7 +542,7 @@ namespace de4dot.code.deobfuscators.CliSecure {
var dm = new DumpedMethod();
dm.token = 0x06000001 + (uint)i;
var method = (Mono.Cecil.MethodDefinition)module.LookupToken((int)dm.token);
var method = (MethodDef)module.ResolveMethod(MDToken.ToRID(dm.token));
if (method == null || method.DeclaringType == DotNetUtils.getModuleType(module))
continue;
@ -550,6 +550,7 @@ namespace de4dot.code.deobfuscators.CliSecure {
if (rva == 0)
continue;
uint bodyOffset = peImage.rvaToOffset(rva);
dm.mdRVA = peImage.offsetRead(offset + (uint)methodDefTable.fields[0].offset, methodDefTable.fields[0].size);
dm.mdImplFlags = peImage.offsetReadUInt16(offset + (uint)methodDefTable.fields[1].offset);
dm.mdFlags = peImage.offsetReadUInt16(offset + (uint)methodDefTable.fields[2].offset);
dm.mdName = peImage.offsetRead(offset + (uint)methodDefTable.fields[3].offset, methodDefTable.fields[3].size);
@ -581,6 +582,7 @@ namespace de4dot.code.deobfuscators.CliSecure {
var dm = new DumpedMethod();
dm.token = 0x06000001 + (uint)i;
dm.mdRVA = peImage.offsetRead(offset + (uint)methodDefTable.fields[0].offset, methodDefTable.fields[0].size);
dm.mdImplFlags = peImage.offsetReadUInt16(offset + (uint)methodDefTable.fields[1].offset);
dm.mdFlags = peImage.offsetReadUInt16(offset + (uint)methodDefTable.fields[2].offset);
dm.mdName = peImage.offsetRead(offset + (uint)methodDefTable.fields[3].offset, methodDefTable.fields[3].size);

View File

@ -19,19 +19,17 @@
using System;
using System.Collections.Generic;
using Mono.Cecil;
using Mono.Cecil.Cil;
using dot10.DotNet;
using dot10.DotNet.Emit;
using de4dot.blocks;
namespace de4dot.code.deobfuscators.CliSecure {
namespace de4dot.code.deobfuscators.Agile_NET {
class ProxyCallFixer : ProxyCallFixer1 {
IList<MemberReference> memberReferences;
public ProxyCallFixer(ModuleDefinition module)
public ProxyCallFixer(ModuleDefMD module)
: base(module) {
}
public ProxyCallFixer(ModuleDefinition module, ProxyCallFixer oldOne)
public ProxyCallFixer(ModuleDefMD module, ProxyCallFixer oldOne)
: base(module) {
foreach (var method in oldOne.delegateCreatorMethods)
setDelegateCreatorMethod(lookup(method, "Could not find delegate creator method"));
@ -49,31 +47,28 @@ namespace de4dot.code.deobfuscators.CliSecure {
}
}
protected override object checkCctor(ref TypeDefinition type, MethodDefinition cctor) {
protected override object checkCctor(ref TypeDef type, MethodDef cctor) {
var instrs = cctor.Body.Instructions;
if (instrs.Count != 3)
return null;
if (!DotNetUtils.isLdcI4(instrs[0].OpCode.Code))
if (!instrs[0].IsLdcI4())
return null;
if (instrs[1].OpCode != OpCodes.Call || !isDelegateCreatorMethod(instrs[1].Operand as MethodDefinition))
if (instrs[1].OpCode != OpCodes.Call || !isDelegateCreatorMethod(instrs[1].Operand as MethodDef))
return null;
if (instrs[2].OpCode != OpCodes.Ret)
return null;
int delegateToken = 0x02000001 + DotNetUtils.getLdcI4Value(instrs[0]);
if (type.MetadataToken.ToInt32() != delegateToken) {
Log.w("Delegate token is not current type");
int delegateToken = 0x02000001 + instrs[0].GetLdcI4Value();
if (type.MDToken.ToInt32() != delegateToken) {
Logger.w("Delegate token is not current type");
return null;
}
return new object();
}
protected override void getCallInfo(object context, FieldDefinition field, out MethodReference calledMethod, out OpCode callOpcode) {
if (memberReferences == null)
memberReferences = new List<MemberReference>(module.GetMemberReferences());
var name = field.Name;
protected override void getCallInfo(object context, FieldDef field, out IMethod calledMethod, out OpCode callOpcode) {
var name = field.Name.String;
callOpcode = OpCodes.Call;
if (name.EndsWith("%", StringComparison.Ordinal)) {
callOpcode = OpCodes.Callvirt;
@ -81,9 +76,10 @@ namespace de4dot.code.deobfuscators.CliSecure {
}
byte[] value = Convert.FromBase64String(name);
int methodIndex = BitConverter.ToInt32(value, 0); // 0-based memberRef index
if (methodIndex >= memberReferences.Count)
throw new ApplicationException(string.Format("methodIndex ({0}) >= memberReferences.Count ({1})", methodIndex, memberReferences.Count));
calledMethod = memberReferences[methodIndex] as MethodReference;
var mr = module.ResolveMemberRef((uint)methodIndex + 1);
if (mr == null || !mr.IsMethodRef)
throw new ApplicationException(string.Format("Invalid MemberRef index: {0}", methodIndex));
calledMethod = mr;
}
}
}

View File

@ -20,40 +20,41 @@
using System.IO;
using System.Security.Cryptography;
using System.Text;
using Mono.Cecil;
using dot10.IO;
using dot10.DotNet;
using de4dot.blocks;
namespace de4dot.code.deobfuscators.CliSecure {
namespace de4dot.code.deobfuscators.Agile_NET {
class ResourceDecrypter {
ModuleDefinition module;
TypeDefinition rsrcType;
MethodDefinition rsrcRrrMethod;
MethodDefinition rsrcResolveMethod;
ModuleDefMD module;
TypeDef rsrcType;
MethodDef rsrcRrrMethod;
MethodDef rsrcResolveMethod;
public bool Detected {
get { return rsrcType != null; }
}
public TypeDefinition Type {
public TypeDef Type {
get { return rsrcType; }
}
public MethodDefinition RsrcRrrMethod {
public MethodDef RsrcRrrMethod {
get { return rsrcRrrMethod; }
}
public ResourceDecrypter(ModuleDefinition module) {
public ResourceDecrypter(ModuleDefMD module) {
this.module = module;
}
public ResourceDecrypter(ModuleDefinition module, ResourceDecrypter oldOne) {
public ResourceDecrypter(ModuleDefMD module, ResourceDecrypter oldOne) {
this.module = module;
rsrcType = lookup(oldOne.rsrcType, "Could not find rsrcType");
rsrcRrrMethod = lookup(oldOne.rsrcRrrMethod, "Could not find rsrcRrrMethod");
rsrcResolveMethod = lookup(oldOne.rsrcResolveMethod, "Could not find rsrcResolveMethod");
}
T lookup<T>(T def, string errorMessage) where T : MemberReference {
T lookup<T>(T def, string errorMessage) where T : class, ICodedToken {
return DeobUtils.lookup(module, def, errorMessage);
}
@ -99,24 +100,22 @@ namespace de4dot.code.deobfuscators.CliSecure {
var resource = DotNetUtils.getResource(module, DotNetUtils.getCodeStrings(rsrcResolveMethod)) as EmbeddedResource;
if (resource == null)
return null;
DeobUtils.decryptAndAddResources(module, resource.Name, () => decryptResource(resource));
DeobUtils.decryptAndAddResources(module, resource.Name.String, () => decryptResource(resource));
return resource;
}
byte[] decryptResource(EmbeddedResource resource) {
using (var rsrcStream = resource.GetResourceStream()) {
using (var reader = new BinaryReader(rsrcStream)) {
var key = reader.ReadString();
var data = reader.ReadBytes((int)(rsrcStream.Length - rsrcStream.Position));
var cryptoTransform = new DESCryptoServiceProvider {
Key = Encoding.ASCII.GetBytes(key),
IV = Encoding.ASCII.GetBytes(key),
}.CreateDecryptor();
var memStream = new MemoryStream(data);
using (var reader2 = new BinaryReader(new CryptoStream(memStream, cryptoTransform, CryptoStreamMode.Read))) {
return reader2.ReadBytes((int)memStream.Length);
}
}
var reader = resource.Data;
reader.Position = 0;
var key = reader.ReadString();
var data = reader.ReadRemainingBytes();
var cryptoTransform = new DESCryptoServiceProvider {
Key = Encoding.ASCII.GetBytes(key),
IV = Encoding.ASCII.GetBytes(key),
}.CreateDecryptor();
var memStream = new MemoryStream(data);
using (var reader2 = new BinaryReader(new CryptoStream(memStream, cryptoTransform, CryptoStreamMode.Read))) {
return reader2.ReadBytes((int)memStream.Length);
}
}
}

View File

@ -18,16 +18,16 @@
*/
using System;
using Mono.Cecil;
using dot10.DotNet;
using de4dot.blocks;
namespace de4dot.code.deobfuscators.CliSecure {
namespace de4dot.code.deobfuscators.Agile_NET {
class StackFrameHelper {
ModuleDefinition module;
TypeDefinition stackFrameHelperType;
ModuleDefMD module;
TypeDef stackFrameHelperType;
ExceptionLoggerRemover exceptionLoggerRemover = new ExceptionLoggerRemover();
public TypeDefinition Type {
public TypeDef Type {
get { return stackFrameHelperType; }
}
@ -35,7 +35,7 @@ namespace de4dot.code.deobfuscators.CliSecure {
get { return exceptionLoggerRemover; }
}
public StackFrameHelper(ModuleDefinition module) {
public StackFrameHelper(ModuleDefMD module) {
this.module = module;
}
@ -46,19 +46,18 @@ namespace de4dot.code.deobfuscators.CliSecure {
if (type.Methods.Count > 3)
continue;
MethodDefinition errorMethod = null;
MethodDef errorMethod = null;
foreach (var method in type.Methods) {
if (method.IsRuntimeSpecialName && method.Name == ".ctor" && !method.HasParameters)
if (method.Name == ".ctor")
continue; // .ctor is allowed
if (method.IsRuntimeSpecialName && method.Name == ".cctor" && !method.HasParameters)
if (method.Name == ".cctor")
continue; // .cctor is allowed
if (method.IsStatic && method.CallingConvention == MethodCallingConvention.Default &&
method.ExplicitThis == false && method.HasThis == false &&
method.HasBody && method.IsManaged && method.IsIL && method.HasParameters &&
method.Parameters.Count == 2 && !method.HasGenericParameters &&
var sig = method.MethodSig;
if (sig != null && method.IsStatic && method.HasBody &&
sig.Params.Count == 2 && !method.HasGenericParameters &&
!DotNetUtils.hasReturnValue(method) &&
method.Parameters[0].ParameterType.FullName == "System.Exception" &&
method.Parameters[1].ParameterType.FullName == "System.Object[]") {
sig.Params[0].GetFullName() == "System.Exception" &&
sig.Params[1].GetFullName() == "System.Object[]") {
errorMethod = method;
}
else

View File

@ -19,41 +19,41 @@
using System;
using System.Text;
using Mono.Cecil;
using dot10.DotNet;
namespace de4dot.code.deobfuscators.CliSecure {
namespace de4dot.code.deobfuscators.Agile_NET {
class StringDecrypter {
ModuleDefinition module;
TypeDefinition stringDecrypterType;
MethodDefinition stringDecrypterMethod;
ModuleDefMD module;
TypeDef stringDecrypterType;
MethodDef stringDecrypterMethod;
byte[] stringDecrypterKey;
public bool Detected {
get { return stringDecrypterMethod != null; }
}
public TypeDefinition Type {
public TypeDef Type {
get { return stringDecrypterType; }
}
public MethodDefinition Method {
public MethodDef Method {
get { return stringDecrypterMethod; }
set { stringDecrypterMethod = value; }
}
public StringDecrypter(ModuleDefinition module, MethodDefinition stringDecrypterMethod) {
public StringDecrypter(ModuleDefMD module, MethodDef stringDecrypterMethod) {
this.module = module;
this.stringDecrypterMethod = stringDecrypterMethod;
}
public StringDecrypter(ModuleDefinition module, StringDecrypter oldOne) {
public StringDecrypter(ModuleDefMD module, StringDecrypter oldOne) {
this.module = module;
stringDecrypterType = lookup(oldOne.stringDecrypterType, "Could not find stringDecrypterType");
stringDecrypterMethod = lookup(oldOne.stringDecrypterMethod, "Could not find stringDecrypterMethod");
stringDecrypterKey = oldOne.stringDecrypterKey;
}
T lookup<T>(T def, string errorMessage) where T : MemberReference {
T lookup<T>(T def, string errorMessage) where T : class, ICodedToken {
return DeobUtils.lookup(module, def, errorMessage);
}

View File

@ -17,20 +17,19 @@
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
*/
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Cecil.Metadata;
using dot10.DotNet;
using dot10.DotNet.Emit;
using de4dot.blocks;
namespace de4dot.code.deobfuscators.CliSecure.vm {
namespace de4dot.code.deobfuscators.Agile_NET.vm {
// Tries to restore the operands of the following CIL instructions:
// ldelema
// ldobj
// stobj
class CilOperandInstructionRestorer {
MethodDefinition method;
MethodDef method;
public bool restore(MethodDefinition method) {
public bool restore(MethodDef method) {
this.method = method;
bool atLeastOneFailed = false;
@ -43,13 +42,13 @@ namespace de4dot.code.deobfuscators.CliSecure.vm {
if (instr.Operand != null)
continue;
TypeReference operandType = null;
TypeSig operandType = null;
switch (instr.OpCode.Code) {
case Code.Ldelema:
var arrayType = MethodStack.getLoadedType(method, instrs, i, 1) as ArrayType;
var arrayType = MethodStack.getLoadedType(method, instrs, i, 1) as SZArraySig;
if (arrayType == null)
break;
operandType = arrayType.ElementType;
operandType = arrayType.Next;
break;
case Code.Ldobj:
@ -70,58 +69,58 @@ namespace de4dot.code.deobfuscators.CliSecure.vm {
continue;
}
instr.Operand = operandType;
instr.Operand = operandType.ToTypeDefOrRef();
}
return !atLeastOneFailed;
}
static TypeReference getPtrElementType(TypeReference type) {
static TypeSig getPtrElementType(TypeSig type) {
if (type == null)
return null;
var pt = type as PointerType;
if (pt != null)
return pt.ElementType;
var bt = type as ByReferenceType;
if (bt != null)
return bt.ElementType;
if (type.IsPointer || type.IsByRef)
return type.Next;
return null;
}
bool isValidType(TypeReference type) {
bool isValidType(TypeSig type) {
type = type.RemovePinnedAndModifiers();
if (type == null)
return false;
if (type.EType == ElementType.Void)
if (type.ElementType == ElementType.Void)
return false;
while (type != null) {
switch (MemberReferenceHelper.getMemberReferenceType(type)) {
case CecilType.ArrayType:
case CecilType.GenericInstanceType:
case CecilType.PointerType:
case CecilType.TypeDefinition:
case CecilType.TypeReference:
case CecilType.FunctionPointerType:
switch (type.ElementType) {
case ElementType.SZArray:
case ElementType.Array:
case ElementType.GenericInst:
case ElementType.Ptr:
case ElementType.Class:
case ElementType.ValueType:
case ElementType.FnPtr:
break;
case CecilType.GenericParameter:
var gp = (GenericParameter)type;
if (method.DeclaringType != gp.Owner && method != gp.Owner)
case ElementType.MVar:
var gmvar = (GenericMVar)type;
if (gmvar.Number >= method.MethodSig.GetGenParamCount())
return false;
break;
case CecilType.ByReferenceType:
case CecilType.OptionalModifierType:
case CecilType.PinnedType:
case CecilType.RequiredModifierType:
case CecilType.SentinelType:
case ElementType.Var:
var gvar = (GenericVar)type;
var dt = method.DeclaringType;
if (dt == null || gvar.Number >= dt.GenericParameters.Count)
return false;
break;
case ElementType.ByRef:
default:
return false;
}
if (!(type is TypeSpecification))
if (type.Next == null)
break;
type = ((TypeSpecification)type).ElementType;
type = type.Next;
}
return type != null;

View File

@ -20,15 +20,15 @@
using System;
using System.Collections.Generic;
using System.IO;
using Mono.Cecil;
using dot10.DotNet;
using de4dot.blocks;
namespace de4dot.code.deobfuscators.CliSecure.vm {
namespace de4dot.code.deobfuscators.Agile_NET.vm {
class Csvm {
IDeobfuscatorContext deobfuscatorContext;
ModuleDefinition module;
ModuleDefMD module;
EmbeddedResource resource;
AssemblyNameReference vmAssemblyReference;
AssemblyRef vmAssemblyReference;
public bool Detected {
get { return resource != null && vmAssemblyReference != null; }
@ -38,22 +38,22 @@ namespace de4dot.code.deobfuscators.CliSecure.vm {
get { return Detected ? resource : null; }
}
public AssemblyNameReference VmAssemblyReference {
public AssemblyRef VmAssemblyReference {
get { return Detected ? vmAssemblyReference : null; }
}
public Csvm(IDeobfuscatorContext deobfuscatorContext, ModuleDefinition module) {
public Csvm(IDeobfuscatorContext deobfuscatorContext, ModuleDefMD module) {
this.deobfuscatorContext = deobfuscatorContext;
this.module = module;
}
public Csvm(IDeobfuscatorContext deobfuscatorContext, ModuleDefinition module, Csvm oldOne) {
public Csvm(IDeobfuscatorContext deobfuscatorContext, ModuleDefMD module, Csvm oldOne) {
this.deobfuscatorContext = deobfuscatorContext;
this.module = module;
if (oldOne.resource != null)
this.resource = (EmbeddedResource)module.Resources[oldOne.module.Resources.IndexOf(oldOne.resource)];
if (oldOne.vmAssemblyReference != null)
this.vmAssemblyReference = module.AssemblyReferences[oldOne.module.AssemblyReferences.IndexOf(oldOne.vmAssemblyReference)];
this.vmAssemblyReference = module.ResolveAssemblyRef(oldOne.vmAssemblyReference.Rid);
}
public void find() {
@ -61,13 +61,19 @@ namespace de4dot.code.deobfuscators.CliSecure.vm {
vmAssemblyReference = findVmAssemblyReference();
}
AssemblyNameReference findVmAssemblyReference() {
foreach (var memberRef in module.GetMemberReferences()) {
var method = memberRef as MethodReference;
if (method == null)
AssemblyRef findVmAssemblyReference() {
foreach (var memberRef in module.GetMemberRefs()) {
var sig = memberRef.MethodSig;
if (sig == null)
continue;
if (method.FullName == "System.Object VMRuntime.Libraries.CSVMRuntime::RunMethod(System.String,System.Object[])")
return method.DeclaringType.Scope as AssemblyNameReference;
if (sig.RetType.GetElementType() != ElementType.Object)
continue;
if (sig.Params.Count != 2)
continue;
if (memberRef.Name != "RunMethod")
continue;
if (memberRef.FullName == "System.Object VMRuntime.Libraries.CSVMRuntime::RunMethod(System.String,System.Object[])")
return memberRef.DeclaringType.Scope as AssemblyRef;
}
return null;
}
@ -80,59 +86,59 @@ namespace de4dot.code.deobfuscators.CliSecure.vm {
if (!Detected)
return;
int oldIndent = Log.indentLevel;
int oldIndent = Logger.Instance.IndentLevel;
try {
restore2();
}
finally {
Log.indentLevel = oldIndent;
Logger.Instance.IndentLevel = oldIndent;
}
}
void restore2() {
Log.v("Restoring CSVM methods");
Log.indent();
Logger.v("Restoring CSVM methods");
Logger.Instance.indent();
var opcodeDetector = getVmOpCodeHandlerDetector();
var csvmMethods = new CsvmDataReader(resource.GetResourceStream()).read();
var csvmMethods = new CsvmDataReader(resource.Data).read();
var converter = new CsvmToCilMethodConverter(deobfuscatorContext, module, opcodeDetector);
var methodPrinter = new MethodPrinter();
foreach (var csvmMethod in csvmMethods) {
var cilMethod = module.LookupToken(csvmMethod.Token) as MethodDefinition;
var cilMethod = module.ResolveToken(csvmMethod.Token) as MethodDef;
if (cilMethod == null)
throw new ApplicationException(string.Format("Could not find method {0:X8}", csvmMethod.Token));
converter.convert(cilMethod, csvmMethod);
Log.v("Restored method {0:X8}", cilMethod.MetadataToken.ToInt32());
Logger.v("Restored method {0:X8}", cilMethod.MDToken.ToInt32());
printMethod(methodPrinter, cilMethod);
}
Log.deIndent();
Logger.Instance.deIndent();
}
static void printMethod(MethodPrinter methodPrinter, MethodDefinition method) {
const Log.LogLevel dumpLogLevel = Log.LogLevel.verbose;
if (!Log.isAtLeast(dumpLogLevel))
static void printMethod(MethodPrinter methodPrinter, MethodDef method) {
const LoggerEvent dumpLogLevel = LoggerEvent.Verbose;
if (Logger.Instance.IgnoresEvent(dumpLogLevel))
return;
Log.indent();
Logger.Instance.indent();
Log.v("Locals:");
Log.indent();
for (int i = 0; i < method.Body.Variables.Count; i++)
Log.v("#{0}: {1}", i, method.Body.Variables[i].VariableType);
Log.deIndent();
Logger.v("Locals:");
Logger.Instance.indent();
for (int i = 0; i < method.Body.LocalList.Count; i++)
Logger.v("#{0}: {1}", i, method.Body.LocalList[i].Type);
Logger.Instance.deIndent();
Log.v("Code:");
Log.indent();
Logger.v("Code:");
Logger.Instance.indent();
methodPrinter.print(dumpLogLevel, method.Body.Instructions, method.Body.ExceptionHandlers);
Log.deIndent();
Logger.Instance.deIndent();
Log.deIndent();
Logger.Instance.deIndent();
}
VmOpCodeHandlerDetector getVmOpCodeHandlerDetector() {
var vmFilename = vmAssemblyReference.Name + ".dll";
var vmModulePath = Path.Combine(Path.GetDirectoryName(module.FullyQualifiedName), vmFilename);
Log.v("CSVM filename: {0}", vmFilename);
var vmModulePath = Path.Combine(Path.GetDirectoryName(module.Location), vmFilename);
Logger.v("CSVM filename: {0}", vmFilename);
var dataKey = "cs cached VmOpCodeHandlerDetector";
var dict = (Dictionary<string, VmOpCodeHandlerDetector>)deobfuscatorContext.getData(dataKey);
@ -141,14 +147,14 @@ namespace de4dot.code.deobfuscators.CliSecure.vm {
VmOpCodeHandlerDetector detector;
if (dict.TryGetValue(vmModulePath, out detector))
return detector;
dict[vmModulePath] = detector = new VmOpCodeHandlerDetector(ModuleDefinition.ReadModule(vmModulePath));
dict[vmModulePath] = detector = new VmOpCodeHandlerDetector(ModuleDefMD.Load(vmModulePath));
detector.findHandlers();
Log.v("CSVM opcodes:");
Log.indent();
Logger.v("CSVM opcodes:");
Logger.Instance.indent();
for (int i = 0; i < detector.Handlers.Count; i++)
Log.v("{0:X4}: {1}", i, detector.Handlers[i].Name);
Log.deIndent();
Logger.v("{0:X4}: {1}", i, detector.Handlers[i].Name);
Logger.Instance.deIndent();
return detector;
}

View File

@ -20,15 +20,16 @@
using System;
using System.Collections.Generic;
using System.IO;
using Mono.Cecil;
using dot10.IO;
using dot10.DotNet;
using de4dot.blocks;
namespace de4dot.code.deobfuscators.CliSecure.vm {
namespace de4dot.code.deobfuscators.Agile_NET.vm {
class CsvmDataReader {
BinaryReader reader;
IBinaryReader reader;
public CsvmDataReader(Stream stream) {
reader = new BinaryReader(stream);
public CsvmDataReader(IBinaryReader reader) {
this.reader = reader;
}
public List<CsvmMethodData> read() {

View File

@ -19,7 +19,7 @@
using System;
namespace de4dot.code.deobfuscators.CliSecure.vm {
namespace de4dot.code.deobfuscators.Agile_NET.vm {
class CsvmMethodData {
public Guid Guid { get; set; }
public int Token { get; set; }

View File

@ -20,41 +20,40 @@
using System;
using System.Collections.Generic;
using System.IO;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Cecil.Metadata;
using dot10.DotNet;
using dot10.DotNet.Emit;
using de4dot.blocks;
namespace de4dot.code.deobfuscators.CliSecure.vm {
namespace de4dot.code.deobfuscators.Agile_NET.vm {
class CsvmToCilMethodConverter {
IDeobfuscatorContext deobfuscatorContext;
ModuleDefinition module;
ModuleDefMD module;
VmOpCodeHandlerDetector opCodeDetector;
CilOperandInstructionRestorer operandRestorer = new CilOperandInstructionRestorer();
public CsvmToCilMethodConverter(IDeobfuscatorContext deobfuscatorContext, ModuleDefinition module, VmOpCodeHandlerDetector opCodeDetector) {
public CsvmToCilMethodConverter(IDeobfuscatorContext deobfuscatorContext, ModuleDefMD module, VmOpCodeHandlerDetector opCodeDetector) {
this.deobfuscatorContext = deobfuscatorContext;
this.module = module;
this.opCodeDetector = opCodeDetector;
}
public void convert(MethodDefinition cilMethod, CsvmMethodData csvmMethod) {
public void convert(MethodDef cilMethod, CsvmMethodData csvmMethod) {
var newInstructions = readInstructions(cilMethod, csvmMethod);
var newLocals = readLocals(cilMethod, csvmMethod);
var newExceptions = readExceptions(cilMethod, csvmMethod, newInstructions);
fixInstructionOperands(newInstructions);
fixLocals(newInstructions, cilMethod.Body.Variables);
fixLocals(newInstructions, cilMethod.Body.LocalList);
fixArgs(newInstructions, cilMethod);
DotNetUtils.restoreBody(cilMethod, newInstructions, newExceptions);
if (!operandRestorer.restore(cilMethod))
Log.w("Failed to restore one or more instruction operands in CSVM method {0:X8}", cilMethod.MetadataToken.ToInt32());
Logger.w("Failed to restore one or more instruction operands in CSVM method {0:X8}", cilMethod.MDToken.ToInt32());
restoreConstrainedPrefix(cilMethod);
}
void fixLocals(IList<Instruction> instrs, IList<VariableDefinition> locals) {
void fixLocals(IList<Instruction> instrs, IList<Local> locals) {
foreach (var instr in instrs) {
var op = instr.Operand as LocalOperand;
if (op == null)
@ -64,7 +63,7 @@ namespace de4dot.code.deobfuscators.CliSecure.vm {
}
}
static void updateLocalInstruction(Instruction instr, VariableDefinition local, int index) {
static void updateLocalInstruction(Instruction instr, Local local, int index) {
object operand = null;
OpCode opcode;
@ -129,25 +128,17 @@ namespace de4dot.code.deobfuscators.CliSecure.vm {
instr.Operand = operand;
}
void fixArgs(IList<Instruction> instrs, MethodDefinition method) {
void fixArgs(IList<Instruction> instrs, MethodDef method) {
foreach (var instr in instrs) {
var op = instr.Operand as ArgOperand;
if (op == null)
continue;
int argIndex = op.arg;
if (method.HasImplicitThis)
argIndex--;
ParameterDefinition arg;
if (argIndex == -1)
arg = method.Body.ThisParameter;
else
arg = method.Parameters[argIndex];
updateArgInstruction(instr, arg, op.arg);
updateArgInstruction(instr, method.Parameters[op.arg], op.arg);
}
}
static void updateArgInstruction(Instruction instr, ParameterDefinition arg, int index) {
static void updateArgInstruction(Instruction instr, Parameter arg, int index) {
switch (instr.OpCode.Code) {
case Code.Ldarg:
case Code.Ldarg_S:
@ -206,15 +197,15 @@ namespace de4dot.code.deobfuscators.CliSecure.vm {
}
}
List<Instruction> readInstructions(MethodDefinition cilMethod, CsvmMethodData csvmMethod) {
List<Instruction> readInstructions(MethodDef cilMethod, CsvmMethodData csvmMethod) {
var reader = new BinaryReader(new MemoryStream(csvmMethod.Instructions));
var instrs = new List<Instruction>();
int offset = 0;
uint offset = 0;
while (reader.BaseStream.Position < reader.BaseStream.Length) {
int vmOpCode = reader.ReadUInt16();
var instr = opCodeDetector.Handlers[vmOpCode].Read(reader);
instr.Offset = offset;
offset += getInstructionSize(instr);
offset += (uint)getInstructionSize(instr);
instrs.Add(instr);
}
return instrs;
@ -230,8 +221,8 @@ namespace de4dot.code.deobfuscators.CliSecure.vm {
return instr.OpCode.Size + (op.targetDisplacements.Length + 1) * 4;
}
List<VariableDefinition> readLocals(MethodDefinition cilMethod, CsvmMethodData csvmMethod) {
var locals = new List<VariableDefinition>();
List<Local> readLocals(MethodDef cilMethod, CsvmMethodData csvmMethod) {
var locals = new List<Local>();
var reader = new BinaryReader(new MemoryStream(csvmMethod.Locals));
if (csvmMethod.Locals.Length == 0)
@ -243,67 +234,62 @@ namespace de4dot.code.deobfuscators.CliSecure.vm {
throw new ApplicationException("Invalid number of locals");
for (int i = 0; i < numLocals; i++)
locals.Add(new VariableDefinition(readTypeReference(reader)));
locals.Add(new Local(readTypeReference(reader)));
return locals;
}
TypeReference readTypeReference(BinaryReader reader) {
TypeSig readTypeReference(BinaryReader reader) {
var etype = (ElementType)reader.ReadInt32();
switch (etype) {
case ElementType.Void: return module.TypeSystem.Void;
case ElementType.Boolean: return module.TypeSystem.Boolean;
case ElementType.Char: return module.TypeSystem.Char;
case ElementType.I1: return module.TypeSystem.SByte;
case ElementType.U1: return module.TypeSystem.Byte;
case ElementType.I2: return module.TypeSystem.Int16;
case ElementType.U2: return module.TypeSystem.UInt16;
case ElementType.I4: return module.TypeSystem.Int32;
case ElementType.U4: return module.TypeSystem.UInt32;
case ElementType.I8: return module.TypeSystem.Int64;
case ElementType.U8: return module.TypeSystem.UInt64;
case ElementType.R4: return module.TypeSystem.Single;
case ElementType.R8: return module.TypeSystem.Double;
case ElementType.String: return module.TypeSystem.String;
case ElementType.TypedByRef: return module.TypeSystem.TypedReference;
case ElementType.I: return module.TypeSystem.IntPtr;
case ElementType.U: return module.TypeSystem.UIntPtr;
case ElementType.Object: return module.TypeSystem.Object;
case ElementType.Void: return module.CorLibTypes.Void;
case ElementType.Boolean: return module.CorLibTypes.Boolean;
case ElementType.Char: return module.CorLibTypes.Char;
case ElementType.I1: return module.CorLibTypes.SByte;
case ElementType.U1: return module.CorLibTypes.Byte;
case ElementType.I2: return module.CorLibTypes.Int16;
case ElementType.U2: return module.CorLibTypes.UInt16;
case ElementType.I4: return module.CorLibTypes.Int32;
case ElementType.U4: return module.CorLibTypes.UInt32;
case ElementType.I8: return module.CorLibTypes.Int64;
case ElementType.U8: return module.CorLibTypes.UInt64;
case ElementType.R4: return module.CorLibTypes.Single;
case ElementType.R8: return module.CorLibTypes.Double;
case ElementType.String: return module.CorLibTypes.String;
case ElementType.TypedByRef: return module.CorLibTypes.TypedReference;
case ElementType.I: return module.CorLibTypes.IntPtr;
case ElementType.U: return module.CorLibTypes.UIntPtr;
case ElementType.Object: return module.CorLibTypes.Object;
case ElementType.ValueType:
case ElementType.Var:
case ElementType.MVar:
return (TypeReference)module.LookupToken(reader.ReadInt32());
return (module.ResolveToken(reader.ReadUInt32()) as ITypeDefOrRef).ToTypeSig();
case ElementType.GenericInst:
etype = (ElementType)reader.ReadInt32();
if (etype == ElementType.ValueType)
return (TypeReference)module.LookupToken(reader.ReadInt32());
return (module.ResolveToken(reader.ReadUInt32()) as ITypeDefOrRef).ToTypeSig();
// ElementType.Class
return module.TypeSystem.Object;
return module.CorLibTypes.Object;
case ElementType.Ptr:
case ElementType.Class:
case ElementType.Array:
case ElementType.FnPtr:
case ElementType.SzArray:
case ElementType.SZArray:
case ElementType.ByRef:
case ElementType.CModReqD:
case ElementType.CModReqd:
case ElementType.CModOpt:
case ElementType.Internal:
case ElementType.Modifier:
case ElementType.Sentinel:
case ElementType.Pinned:
case ElementType.Type:
case ElementType.Boxed:
case ElementType.Enum:
case ElementType.None:
default:
return module.TypeSystem.Object;
return module.CorLibTypes.Object;
}
}
List<ExceptionHandler> readExceptions(MethodDefinition cilMethod, CsvmMethodData csvmMethod, List<Instruction> cilInstructions) {
List<ExceptionHandler> readExceptions(MethodDef cilMethod, CsvmMethodData csvmMethod, List<Instruction> cilInstructions) {
var reader = new BinaryReader(new MemoryStream(csvmMethod.Exceptions));
var ehs = new List<ExceptionHandler>();
@ -321,7 +307,7 @@ namespace de4dot.code.deobfuscators.CliSecure.vm {
eh.HandlerStart = getInstruction(cilInstructions, reader.ReadInt32());
eh.HandlerEnd = getInstructionEnd(cilInstructions, reader.ReadInt32());
if (eh.HandlerType == ExceptionHandlerType.Catch)
eh.CatchType = (TypeReference)module.LookupToken(reader.ReadInt32());
eh.CatchType = module.ResolveToken(reader.ReadUInt32()) as ITypeDefOrRef;
else if (eh.HandlerType == ExceptionHandlerType.Filter)
eh.FilterStart = getInstruction(cilInstructions, reader.ReadInt32());
@ -387,12 +373,12 @@ namespace de4dot.code.deobfuscators.CliSecure.vm {
throw new ApplicationException(string.Format("Unknown operand type: {0}", vmOperand.GetType()));
}
FieldReference fixLoadStoreFieldInstruction(Instruction instr, int token, OpCode staticInstr, OpCode instanceInstr) {
var fieldRef = (FieldReference)module.LookupToken(token);
var field = deobfuscatorContext.resolve(fieldRef);
IField fixLoadStoreFieldInstruction(Instruction instr, int token, OpCode staticInstr, OpCode instanceInstr) {
var fieldRef = module.ResolveToken(token) as IField;
var field = deobfuscatorContext.resolveField(fieldRef);
bool isStatic;
if (field == null) {
Log.w("Could not resolve field {0:X8}. Assuming it's not static.", token);
Logger.w("Could not resolve field {0:X8}. Assuming it's not static.", token);
isStatic = false;
}
else
@ -401,14 +387,14 @@ namespace de4dot.code.deobfuscators.CliSecure.vm {
return fieldRef;
}
MemberReference getMemberReference(int token) {
var memberRef = module.LookupToken(token) as MemberReference;
ITokenOperand getMemberReference(int token) {
var memberRef = module.ResolveToken(token) as ITokenOperand;
if (memberRef == null)
throw new ApplicationException(string.Format("Could not find member ref: {0:X8}", token));
return memberRef;
}
static void restoreConstrainedPrefix(MethodDefinition method) {
static void restoreConstrainedPrefix(MethodDef method) {
if (method == null || method.Body == null)
return;
@ -418,15 +404,18 @@ namespace de4dot.code.deobfuscators.CliSecure.vm {
if (instr.OpCode.Code != Code.Callvirt)
continue;
var calledMethod = instr.Operand as MethodReference;
if (calledMethod == null || !calledMethod.HasThis)
var calledMethod = instr.Operand as IMethod;
if (calledMethod == null)
continue;
var thisType = MethodStack.getLoadedType(method, instrs, i, calledMethod.Parameters.Count) as ByReferenceType;
var sig = calledMethod.MethodSig;
if (sig == null || !sig.HasThis)
continue;
var thisType = MethodStack.getLoadedType(method, instrs, i, sig.Params.Count) as ByRefSig;
if (thisType == null)
continue;
if (hasPrefix(instrs, i, Code.Constrained))
continue;
instrs.Insert(i, Instruction.Create(OpCodes.Constrained, thisType.ElementType));
instrs.Insert(i, Instruction.Create(OpCodes.Constrained, thisType.Next.ToTypeDefOrRef()));
i++;
}
}

View File

@ -19,25 +19,25 @@
using System;
using System.Collections.Generic;
using Mono.Cecil;
using dot10.DotNet;
namespace de4dot.code.deobfuscators.CliSecure.vm {
namespace de4dot.code.deobfuscators.Agile_NET.vm {
class FieldsInfo {
public static readonly object EnumType = new object();
Dictionary<string, int> fieldTypes = new Dictionary<string, int>(StringComparer.Ordinal);
int numEnums = 0;
public FieldsInfo(TypeDefinition type)
public FieldsInfo(TypeDef type)
: this(type.Fields) {
}
public FieldsInfo(IEnumerable<FieldDefinition> fields) {
public FieldsInfo(IEnumerable<FieldDef> fields) {
foreach (var field in fields) {
var fieldTypeDef = field.FieldType as TypeDefinition;
var fieldTypeDef = field.FieldSig.GetFieldType().TryGetTypeDef();
if (fieldTypeDef != null && fieldTypeDef.IsEnum)
addEnum();
else
add(field.FieldType);
add(field.FieldSig.GetFieldType());
}
}
@ -50,8 +50,8 @@ namespace de4dot.code.deobfuscators.CliSecure.vm {
}
}
void add(TypeReference type) {
add(type.FullName);
void add(TypeSig type) {
add(type.GetFullName());
}
void add(string typeFullName) {

View File

@ -21,11 +21,10 @@ using System;
using System.Collections.Generic;
using System.IO;
using de4dot.blocks;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Cecil.Metadata;
using dot10.DotNet;
using dot10.DotNet.Emit;
namespace de4dot.code.deobfuscators.CliSecure.vm {
namespace de4dot.code.deobfuscators.Agile_NET.vm {
partial class OpCodeHandler {
public string Name { get; set; }
public OpCodeHandlerSigInfo OpCodeHandlerSigInfo { get; set; }
@ -248,7 +247,7 @@ namespace de4dot.code.deobfuscators.CliSecure.vm {
new InstructionInfo2 { First = false, Second = true, Value = 12, OpCode = OpCodes.Stelem_R4 },
new InstructionInfo2 { First = false, Second = true, Value = 13, OpCode = OpCodes.Stelem_R8 },
new InstructionInfo2 { First = false, Second = true, Value = 28, OpCode = OpCodes.Stelem_Ref },
new InstructionInfo2 { First = false, Second = false, Value = 0, OpCode = OpCodes.Stelem_Any },
new InstructionInfo2 { First = false, Second = false, Value = 0, OpCode = OpCodes.Stelem },
new InstructionInfo2 { First = true, Second = true, Value = 24, OpCode = OpCodes.Ldelem_I },
new InstructionInfo2 { First = true, Second = true, Value = 4, OpCode = OpCodes.Ldelem_I1 },
@ -261,7 +260,7 @@ namespace de4dot.code.deobfuscators.CliSecure.vm {
new InstructionInfo2 { First = true, Second = true, Value = 12, OpCode = OpCodes.Ldelem_R4 },
new InstructionInfo2 { First = true, Second = true, Value = 13, OpCode = OpCodes.Ldelem_R8 },
new InstructionInfo2 { First = true, Second = true, Value = 28, OpCode = OpCodes.Ldelem_Ref },
new InstructionInfo2 { First = true, Second = false, Value = 0, OpCode = OpCodes.Ldelem_Any },
new InstructionInfo2 { First = true, Second = false, Value = 0, OpCode = OpCodes.Ldelem },
};
static Instruction ldelem_read(BinaryReader reader) {
Instruction instr = null;
@ -392,7 +391,7 @@ namespace de4dot.code.deobfuscators.CliSecure.vm {
static Instruction ldc_read(BinaryReader reader) {
switch ((ElementType)reader.ReadByte()) {
case ElementType.I4: return DotNetUtils.createLdci4(reader.ReadInt32());
case ElementType.I4: return Instruction.CreateLdcI4(reader.ReadInt32());
case ElementType.I8: return Instruction.Create(OpCodes.Ldc_I8, reader.ReadInt64());
case ElementType.R4: return Instruction.Create(OpCodes.Ldc_R4, reader.ReadSingle());
case ElementType.R8: return Instruction.Create(OpCodes.Ldc_R8, reader.ReadDouble());
@ -439,7 +438,7 @@ namespace de4dot.code.deobfuscators.CliSecure.vm {
return isEmptyMethod(info.ReadMethod) && isEmptyMethod(info.ExecuteMethod);
}
static bool isEmptyMethod(MethodDefinition method) {
static bool isEmptyMethod(MethodDef method) {
foreach (var instr in method.Body.Instructions) {
if (instr.OpCode.Code == Code.Ret)
return true;
@ -463,7 +462,7 @@ namespace de4dot.code.deobfuscators.CliSecure.vm {
}
static bool rethrow_check(UnknownHandlerInfo info) {
return info.ExecuteMethod.Body.Variables.Count == 0;
return info.ExecuteMethod.Body.LocalList.Count == 0;
}
static Instruction rethrow_read(BinaryReader reader) {

View File

@ -17,7 +17,7 @@
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
*/
namespace de4dot.code.deobfuscators.CliSecure.vm {
namespace de4dot.code.deobfuscators.Agile_NET.vm {
static partial class OpCodeHandlers {
public static readonly OpCodeHandler[][] opcodeHandlers = new OpCodeHandler[][] {
new OpCodeHandler[] {

View File

@ -19,24 +19,24 @@
using System;
using System.Collections.Generic;
using Mono.Cecil;
using Mono.Cecil.Cil;
using dot10.DotNet;
using dot10.DotNet.Emit;
using de4dot.blocks;
namespace de4dot.code.deobfuscators.CliSecure.vm {
namespace de4dot.code.deobfuscators.Agile_NET.vm {
class UnknownHandlerInfo {
TypeDefinition type;
TypeDef type;
CsvmInfo csvmInfo;
FieldsInfo fieldsInfo;
MethodDefinition readMethod, executeMethod;
MethodDef readMethod, executeMethod;
int numStaticMethods, numInstanceMethods, numVirtualMethods, numCtors;
int executeMethodThrows, executeMethodPops;
public MethodDefinition ReadMethod {
public MethodDef ReadMethod {
get { return readMethod; }
}
public MethodDefinition ExecuteMethod {
public MethodDef ExecuteMethod {
get { return executeMethod; }
}
@ -64,7 +64,7 @@ namespace de4dot.code.deobfuscators.CliSecure.vm {
get { return numCtors; }
}
public UnknownHandlerInfo(TypeDefinition type, CsvmInfo csvmInfo) {
public UnknownHandlerInfo(TypeDef type, CsvmInfo csvmInfo) {
this.type = type;
this.csvmInfo = csvmInfo;
fieldsInfo = new FieldsInfo(getFields(type));
@ -74,16 +74,16 @@ namespace de4dot.code.deobfuscators.CliSecure.vm {
executeMethodPops = countPops(executeMethod);
}
static internal IEnumerable<FieldDefinition> getFields(TypeDefinition type) {
var typeFields = new FieldDefinitionAndDeclaringTypeDict<FieldDefinition>();
static internal IEnumerable<FieldDef> getFields(TypeDef type) {
var typeFields = new FieldDefinitionAndDeclaringTypeDict<FieldDef>();
foreach (var field in type.Fields)
typeFields.add(field, field);
var realFields = new Dictionary<FieldDefinition, bool>();
var realFields = new Dictionary<FieldDef, bool>();
foreach (var method in type.Methods) {
if (method.Body == null)
continue;
foreach (var instr in method.Body.Instructions) {
var fieldRef = instr.Operand as FieldReference;
var fieldRef = instr.Operand as IField;
if (fieldRef == null)
continue;
var field = typeFields.find(fieldRef);
@ -119,7 +119,7 @@ namespace de4dot.code.deobfuscators.CliSecure.vm {
throw new ApplicationException("Found another read method");
readMethod = method;
}
else if (!DotNetUtils.hasReturnValue(method) && method.Parameters.Count == 1) {
else if (!DotNetUtils.hasReturnValue(method) && method.MethodSig.GetParamCount() == 1) {
if (executeMethod != null)
throw new ApplicationException("Found another execute method");
executeMethod = method;
@ -132,7 +132,7 @@ namespace de4dot.code.deobfuscators.CliSecure.vm {
throw new ApplicationException("Could not find execute method");
}
static int countThrows(MethodDefinition method) {
static int countThrows(MethodDef method) {
int count = 0;
foreach (var instr in method.Body.Instructions) {
if (instr.OpCode.Code == Code.Throw)
@ -141,13 +141,13 @@ namespace de4dot.code.deobfuscators.CliSecure.vm {
return count;
}
int countPops(MethodDefinition method) {
int countPops(MethodDef method) {
int count = 0;
foreach (var instr in method.Body.Instructions) {
if (instr.OpCode.Code != Code.Call && instr.OpCode.Code != Code.Callvirt)
continue;
var calledMethod = instr.Operand as MethodReference;
if (!MemberReferenceHelper.compareMethodReferenceAndDeclaringType(calledMethod, csvmInfo.PopMethod))
var calledMethod = instr.Operand as IMethod;
if (!MethodEqualityComparer.CompareDeclaringTypes.Equals(calledMethod, csvmInfo.PopMethod))
continue;
count++;

View File

@ -19,12 +19,12 @@
using System;
using System.Collections.Generic;
using Mono.Cecil;
using Mono.Cecil.Cil;
using dot10.DotNet;
using dot10.DotNet.Emit;
using de4dot.blocks;
using de4dot.blocks.cflow;
namespace de4dot.code.deobfuscators.CliSecure.vm {
namespace de4dot.code.deobfuscators.Agile_NET.vm {
class OpCodeHandlerSigInfo {
public object[] RequiredFieldTypes { get; set; }
public string[] ExecuteMethodLocals { get; set; }
@ -37,21 +37,21 @@ namespace de4dot.code.deobfuscators.CliSecure.vm {
}
class CsvmInfo {
public TypeDefinition StackValue { get; set; }
public TypeDefinition Stack { get; set; }
public MethodDefinition PopMethod { get; set; }
public MethodDefinition PeekMethod { get; set; }
public TypeDef StackValue { get; set; }
public TypeDef Stack { get; set; }
public MethodDef PopMethod { get; set; }
public MethodDef PeekMethod { get; set; }
}
class VmOpCodeHandlerDetector {
ModuleDefinition module;
ModuleDefMD module;
List<OpCodeHandler> opCodeHandlers;
public List<OpCodeHandler> Handlers {
get { return opCodeHandlers; }
}
public VmOpCodeHandlerDetector(ModuleDefinition module) {
public VmOpCodeHandlerDetector(ModuleDefMD module) {
this.module = module;
}
@ -73,7 +73,7 @@ namespace de4dot.code.deobfuscators.CliSecure.vm {
return csvmInfo;
}
TypeDefinition findStackValueType() {
TypeDef findStackValueType() {
foreach (var type in module.Types) {
if (isStackType(type))
return type;
@ -81,17 +81,17 @@ namespace de4dot.code.deobfuscators.CliSecure.vm {
return null;
}
static bool isStackType(TypeDefinition type) {
static bool isStackType(TypeDef type) {
if (type.Fields.Count != 2)
return false;
int enumTypes = 0;
int objectTypes = 0;
foreach (var field in type.Fields) {
var fieldType = field.FieldType as TypeDefinition;
var fieldType = field.FieldSig.GetFieldType().TryGetTypeDef();
if (fieldType != null && fieldType.IsEnum)
enumTypes++;
if (field.FieldType.FullName == "System.Object")
if (field.FieldSig.GetFieldType().GetElementType() == ElementType.Object)
objectTypes++;
}
if (enumTypes != 1 || objectTypes != 1)
@ -100,7 +100,7 @@ namespace de4dot.code.deobfuscators.CliSecure.vm {
return true;
}
TypeDefinition findStackType(TypeDefinition stackValueType) {
TypeDef findStackType(TypeDef stackValueType) {
foreach (var type in module.Types) {
if (isStackType(type, stackValueType))
return type;
@ -108,7 +108,7 @@ namespace de4dot.code.deobfuscators.CliSecure.vm {
return null;
}
bool isStackType(TypeDefinition type, TypeDefinition stackValueType) {
bool isStackType(TypeDef type, TypeDef stackValueType) {
if (type.Interfaces.Count != 2)
return false;
if (!implementsInterface(type, "System.Collections.ICollection"))
@ -124,11 +124,14 @@ namespace de4dot.code.deobfuscators.CliSecure.vm {
foreach (var field in type.Fields) {
if (field.IsLiteral)
continue;
if (field.FieldType is ArrayType && ((ArrayType)field.FieldType).ElementType == stackValueType)
var fieldType = field.FieldSig.GetFieldType();
if (fieldType == null)
continue;
if (fieldType.IsSZArray && fieldType.Next.TryGetTypeDef() == stackValueType)
stackValueTypes++;
if (field.FieldType.FullName == "System.Int32")
if (fieldType.ElementType == ElementType.I4)
int32Types++;
if (field.FieldType.FullName == "System.Object")
if (fieldType.ElementType == ElementType.Object)
objectTypes++;
}
if (stackValueTypes != 2 || int32Types != 2 || objectTypes != 1)
@ -137,9 +140,9 @@ namespace de4dot.code.deobfuscators.CliSecure.vm {
return true;
}
static bool implementsInterface(TypeDefinition type, string ifaceName) {
static bool implementsInterface(TypeDef type, string ifaceName) {
foreach (var iface in type.Interfaces) {
if (iface.FullName == ifaceName)
if (iface.Interface.FullName == ifaceName)
return true;
}
return false;
@ -147,7 +150,8 @@ namespace de4dot.code.deobfuscators.CliSecure.vm {
void initStackTypeMethods(CsvmInfo csvmInfo) {
foreach (var method in csvmInfo.Stack.Methods) {
if (method.Parameters.Count == 0 && method.MethodReturnType.ReturnType == csvmInfo.StackValue) {
var sig = method.MethodSig;
if (sig != null && sig.Params.Count == 0 && sig.RetType.TryGetTypeDef() == csvmInfo.StackValue) {
if (hasAdd(method))
csvmInfo.PopMethod = method;
else
@ -156,7 +160,7 @@ namespace de4dot.code.deobfuscators.CliSecure.vm {
}
}
static bool hasAdd(MethodDefinition method) {
static bool hasAdd(MethodDef method) {
foreach (var instr in method.Body.Instructions) {
if (instr.OpCode.Code == Code.Add)
return true;
@ -164,7 +168,7 @@ namespace de4dot.code.deobfuscators.CliSecure.vm {
return false;
}
List<TypeDefinition> findVmHandlerTypes() {
List<TypeDef> findVmHandlerTypes() {
var requiredFields = new string[] {
null,
"System.Collections.Generic.Dictionary`2<System.UInt16,System.Type>",
@ -172,7 +176,7 @@ namespace de4dot.code.deobfuscators.CliSecure.vm {
};
var cflowDeobfuscator = new CflowDeobfuscator();
foreach (var type in module.Types) {
var cctor = DotNetUtils.getMethod(type, ".cctor");
var cctor = type.FindStaticConstructor();
if (cctor == null)
continue;
requiredFields[0] = type.FullName;
@ -190,13 +194,13 @@ namespace de4dot.code.deobfuscators.CliSecure.vm {
return null;
}
static List<TypeDefinition> findVmHandlerTypes(MethodDefinition method) {
var list = new List<TypeDefinition>();
static List<TypeDef> findVmHandlerTypes(MethodDef method) {
var list = new List<TypeDef>();
foreach (var instr in method.Body.Instructions) {
if (instr.OpCode.Code != Code.Ldtoken)
continue;
var type = instr.Operand as TypeDefinition;
var type = instr.Operand as TypeDef;
if (type == null)
continue;
@ -206,7 +210,7 @@ namespace de4dot.code.deobfuscators.CliSecure.vm {
return list;
}
void detectHandlers(List<TypeDefinition> handlerTypes, CsvmInfo csvmInfo) {
void detectHandlers(List<TypeDef> handlerTypes, CsvmInfo csvmInfo) {
opCodeHandlers = new List<OpCodeHandler>();
var detected = new List<OpCodeHandler>();

View File

@ -17,7 +17,7 @@
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
*/
namespace de4dot.code.deobfuscators.CliSecure.vm {
namespace de4dot.code.deobfuscators.Agile_NET.vm {
interface IVmOperand {
}

View File

@ -18,26 +18,26 @@
*/
using System.Collections.Generic;
using Mono.Cecil;
using Mono.Cecil.Cil;
using dot10.DotNet;
using dot10.DotNet.Emit;
using de4dot.blocks;
using de4dot.blocks.cflow;
namespace de4dot.code.deobfuscators {
static class ArrayFinder {
public static List<byte[]> getArrays(MethodDefinition method) {
public static List<byte[]> getArrays(MethodDef method) {
return getArrays(method, null);
}
public static List<byte[]> getArrays(MethodDefinition method, TypeReference arrayElemntType) {
public static List<byte[]> getArrays(MethodDef method, IType arrayElementType) {
var arrays = new List<byte[]>();
var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count; i++) {
TypeReference type;
IType type;
var ary = getArray(instrs, ref i, out type);
if (ary == null)
break;
if (arrayElemntType != null && !MemberReferenceHelper.compareTypes(type, arrayElemntType))
if (arrayElementType != null && !new SigComparer().Equals(type, arrayElementType))
continue;
arrays.Add(ary);
@ -45,7 +45,7 @@ namespace de4dot.code.deobfuscators {
return arrays;
}
public static byte[] getArray(IList<Instruction> instrs, ref int index, out TypeReference type) {
public static byte[] getArray(IList<Instruction> instrs, ref int index, out IType type) {
for (int i = index; i < instrs.Count - 2; i++) {
var newarr = instrs[i++];
if (newarr.OpCode.Code != Code.Newarr)
@ -57,12 +57,12 @@ namespace de4dot.code.deobfuscators {
var ldtoken = instrs[i++];
if (ldtoken.OpCode.Code != Code.Ldtoken)
continue;
var field = ldtoken.Operand as FieldDefinition;
var field = ldtoken.Operand as FieldDef;
if (field == null || field.InitialValue == null)
continue;
index = i - 3;
type = newarr.Operand as TypeReference;
type = newarr.Operand as IType;
return field.InitialValue;
}
@ -71,14 +71,14 @@ namespace de4dot.code.deobfuscators {
return null;
}
public static byte[] getInitializedByteArray(MethodDefinition method, int arraySize) {
public static byte[] getInitializedByteArray(MethodDef method, int arraySize) {
int newarrIndex = findNewarr(method, arraySize);
if (newarrIndex < 0)
return null;
return getInitializedByteArray(arraySize, method, ref newarrIndex);
}
public static byte[] getInitializedByteArray(int arraySize, MethodDefinition method, ref int newarrIndex) {
public static byte[] getInitializedByteArray(int arraySize, MethodDef method, ref int newarrIndex) {
var resultValueArray = getInitializedArray(arraySize, method, ref newarrIndex, Code.Stelem_I1);
var resultArray = new byte[resultValueArray.Length];
@ -91,7 +91,7 @@ namespace de4dot.code.deobfuscators {
return resultArray;
}
public static short[] getInitializedInt16Array(int arraySize, MethodDefinition method, ref int newarrIndex) {
public static short[] getInitializedInt16Array(int arraySize, MethodDef method, ref int newarrIndex) {
var resultValueArray = getInitializedArray(arraySize, method, ref newarrIndex, Code.Stelem_I2);
var resultArray = new short[resultValueArray.Length];
@ -104,7 +104,7 @@ namespace de4dot.code.deobfuscators {
return resultArray;
}
public static int[] getInitializedInt32Array(int arraySize, MethodDefinition method, ref int newarrIndex) {
public static int[] getInitializedInt32Array(int arraySize, MethodDef method, ref int newarrIndex) {
var resultValueArray = getInitializedArray(arraySize, method, ref newarrIndex, Code.Stelem_I4);
var resultArray = new int[resultValueArray.Length];
@ -117,7 +117,7 @@ namespace de4dot.code.deobfuscators {
return resultArray;
}
public static uint[] getInitializedUInt32Array(int arraySize, MethodDefinition method, ref int newarrIndex) {
public static uint[] getInitializedUInt32Array(int arraySize, MethodDef method, ref int newarrIndex) {
var resultArray = getInitializedInt32Array(arraySize, method, ref newarrIndex);
if (resultArray == null)
return null;
@ -128,7 +128,7 @@ namespace de4dot.code.deobfuscators {
return ary;
}
public static Value[] getInitializedArray(int arraySize, MethodDefinition method, ref int newarrIndex, Code stelemOpCode) {
public static Value[] getInitializedArray(int arraySize, MethodDef method, ref int newarrIndex, Code stelemOpCode) {
var resultValueArray = new Value[arraySize];
var emulator = new InstructionEmulator(method);
@ -183,7 +183,7 @@ done:
return resultValueArray;
}
static int findNewarr(MethodDefinition method, int arraySize) {
static int findNewarr(MethodDef method, int arraySize) {
for (int i = 0; ; i++) {
int size;
if (!findNewarr(method, ref i, out size))
@ -193,17 +193,17 @@ done:
}
}
public static bool findNewarr(MethodDefinition method, ref int i, out int size) {
public static bool findNewarr(MethodDef method, ref int i, out int size) {
var instructions = method.Body.Instructions;
for (; i < instructions.Count; i++) {
var instr = instructions[i];
if (instr.OpCode.Code != Code.Newarr || i < 1)
continue;
var ldci4 = instructions[i - 1];
if (!DotNetUtils.isLdcI4(ldci4))
if (!ldci4.IsLdcI4())
continue;
size = DotNetUtils.getLdcI4Value(ldci4);
size = ldci4.GetLdcI4Value();
return true;
}

View File

@ -19,15 +19,16 @@
using System;
using System.IO;
using Mono.Cecil;
using dot10.IO;
using dot10.DotNet;
using de4dot.blocks;
namespace de4dot.code.deobfuscators.Babel_NET {
class AssemblyResolver {
ModuleDefinition module;
ModuleDefMD module;
ResourceDecrypter resourceDecrypter;
TypeDefinition resolverType;
MethodDefinition registerMethod;
TypeDef resolverType;
MethodDef registerMethod;
EmbeddedResource encryptedResource;
EmbeddedAssemblyInfo[] embeddedAssemblyInfos = new EmbeddedAssemblyInfo[0];
@ -47,11 +48,11 @@ namespace de4dot.code.deobfuscators.Babel_NET {
get { return resolverType != null; }
}
public TypeDefinition Type {
public TypeDef Type {
get { return resolverType; }
}
public MethodDefinition InitMethod {
public MethodDef InitMethod {
get { return registerMethod; }
}
@ -63,7 +64,7 @@ namespace de4dot.code.deobfuscators.Babel_NET {
get { return embeddedAssemblyInfos; }
}
public AssemblyResolver(ModuleDefinition module, ResourceDecrypter resourceDecrypter) {
public AssemblyResolver(ModuleDefMD module, ResourceDecrypter resourceDecrypter) {
this.module = module;
this.resourceDecrypter = resourceDecrypter;
}
@ -80,7 +81,7 @@ namespace de4dot.code.deobfuscators.Babel_NET {
if (!new FieldTypes(type).exactly(requiredTypes))
continue;
MethodDefinition regMethod, handler;
MethodDef regMethod, handler;
if (!BabelUtils.findRegisterMethod(type, out regMethod, out handler))
continue;
@ -95,7 +96,7 @@ namespace de4dot.code.deobfuscators.Babel_NET {
}
}
static MethodDefinition findDecryptMethod(TypeDefinition type) {
static MethodDef findDecryptMethod(TypeDef type) {
foreach (var method in type.Methods) {
if (!DotNetUtils.isMethod(method, "System.Void", "(System.IO.Stream)"))
continue;
@ -110,18 +111,18 @@ namespace de4dot.code.deobfuscators.Babel_NET {
encryptedResource = BabelUtils.findEmbeddedResource(module, resolverType, simpleDeobfuscator, deob);
if (encryptedResource == null) {
Log.w("Could not find embedded assemblies resource");
Logger.w("Could not find embedded assemblies resource");
return;
}
var decrypted = resourceDecrypter.decrypt(encryptedResource.GetResourceData());
var decrypted = resourceDecrypter.decrypt(encryptedResource.Data.ReadAllBytes());
var reader = new BinaryReader(new MemoryStream(decrypted));
int numAssemblies = reader.ReadInt32();
embeddedAssemblyInfos = new EmbeddedAssemblyInfo[numAssemblies];
for (int i = 0; i < numAssemblies; i++) {
string name = reader.ReadString();
var data = reader.ReadBytes(reader.ReadInt32());
var mod = ModuleDefinition.ReadModule(new MemoryStream(data));
var mod = ModuleDefMD.Load(data);
embeddedAssemblyInfos[i] = new EmbeddedAssemblyInfo(name, DeobUtils.getExtension(mod.Kind), data);
}
}

View File

@ -18,8 +18,8 @@
*/
using System.Collections.Generic;
using Mono.Cecil;
using Mono.Cecil.Cil;
using dot10.DotNet;
using dot10.DotNet.Emit;
using de4dot.blocks;
using de4dot.blocks.cflow;
@ -35,12 +35,12 @@ namespace de4dot.code.deobfuscators.Babel_NET {
branchEmulator = new BranchEmulator(emulator, this);
}
public static List<MethodDefinition> find(ModuleDefinition module, IEnumerable<MethodDefinition> notInlinedMethods) {
var notInlinedMethodsDict = new Dictionary<MethodDefinition, bool>();
public static List<MethodDef> find(ModuleDefMD module, IEnumerable<MethodDef> notInlinedMethods) {
var notInlinedMethodsDict = new Dictionary<MethodDef, bool>();
foreach (var method in notInlinedMethods)
notInlinedMethodsDict[method] = true;
var inlinedMethods = new List<MethodDefinition>();
var inlinedMethods = new List<MethodDef>();
foreach (var type in module.GetTypes()) {
foreach (var method in type.Methods) {
@ -83,23 +83,23 @@ namespace de4dot.code.deobfuscators.Babel_NET {
return changed;
}
static bool canInline(MethodDefinition method) {
static bool canInline(MethodDef method) {
if (!DotNetUtils.isMethod(method, "System.Int32", "(System.Int32)"))
return false;
if (!method.IsAssembly)
return false;
if (method.GenericParameters.Count > 0)
if (method.MethodSig.GetGenParamCount() > 0)
return false;
return method.IsStatic;
}
bool canInline2(MethodDefinition method) {
bool canInline2(MethodDef method) {
return canInline(method) && method != blocks.Method;
}
bool inlineMethod(Instruction callInstr, int instrIndex) {
var methodToInline = callInstr.Operand as MethodDefinition;
var methodToInline = callInstr.Operand as MethodDef;
if (methodToInline == null)
return false;
@ -120,11 +120,11 @@ namespace de4dot.code.deobfuscators.Babel_NET {
return false;
block.Instructions[instrIndex - 1] = new Instr(Instruction.Create(OpCodes.Nop));
block.Instructions[instrIndex] = new Instr(DotNetUtils.createLdci4(newValue));
block.Instructions[instrIndex] = new Instr(Instruction.CreateLdcI4(newValue));
return true;
}
bool getNewValue(MethodDefinition method, int arg, out int newValue) {
bool getNewValue(MethodDef method, int arg, out int newValue) {
newValue = 0;
emulator.init(method);
emulator.setArg(method.Parameters[0], new Int32Value(arg));
@ -233,10 +233,10 @@ namespace de4dot.code.deobfuscators.Babel_NET {
}
}
protected override bool isCompatibleType(int paramIndex, TypeReference origType, TypeReference newType) {
if (MemberReferenceHelper.compareTypes(origType, newType))
protected override bool isCompatibleType(int paramIndex, IType origType, IType newType) {
if (new SigComparer(SigComparerOptions.IgnoreModifiers).Equals(origType, newType))
return true;
if (newType.IsValueType || origType.IsValueType)
if (isValueType(newType) || isValueType(origType))
return false;
return newType.FullName == "System.Object";
}

View File

@ -19,24 +19,24 @@
using System.Collections.Generic;
using System.Text;
using Mono.Cecil;
using Mono.Cecil.Cil;
using dot10.DotNet;
using dot10.DotNet.Emit;
using de4dot.blocks;
namespace de4dot.code.deobfuscators.Babel_NET {
static class BabelUtils {
public static EmbeddedResource findEmbeddedResource(ModuleDefinition module, TypeDefinition decrypterType) {
public static EmbeddedResource findEmbeddedResource(ModuleDefMD module, TypeDef decrypterType) {
return findEmbeddedResource(module, decrypterType, (method) => { });
}
public static EmbeddedResource findEmbeddedResource(ModuleDefinition module, TypeDefinition decrypterType, ISimpleDeobfuscator simpleDeobfuscator, IDeobfuscator deob) {
public static EmbeddedResource findEmbeddedResource(ModuleDefMD module, TypeDef decrypterType, ISimpleDeobfuscator simpleDeobfuscator, IDeobfuscator deob) {
return findEmbeddedResource(module, decrypterType, (method) => {
simpleDeobfuscator.deobfuscate(method);
simpleDeobfuscator.decryptStrings(method, deob);
});
}
public static EmbeddedResource findEmbeddedResource(ModuleDefinition module, TypeDefinition decrypterType, Action<MethodDefinition> fixMethod) {
public static EmbeddedResource findEmbeddedResource(ModuleDefMD module, TypeDef decrypterType, Action<MethodDef> fixMethod) {
foreach (var method in decrypterType.Methods) {
if (!DotNetUtils.isMethod(method, "System.String", "()"))
continue;
@ -50,7 +50,7 @@ namespace de4dot.code.deobfuscators.Babel_NET {
return null;
}
static EmbeddedResource findEmbeddedResource1(ModuleDefinition module, MethodDefinition method) {
static EmbeddedResource findEmbeddedResource1(ModuleDefMD module, MethodDef method) {
foreach (var s in DotNetUtils.getCodeStrings(method)) {
var resource = DotNetUtils.getResource(module, s) as EmbeddedResource;
if (resource != null)
@ -59,7 +59,7 @@ namespace de4dot.code.deobfuscators.Babel_NET {
return null;
}
static EmbeddedResource findEmbeddedResource2(ModuleDefinition module, MethodDefinition method) {
static EmbeddedResource findEmbeddedResource2(ModuleDefMD module, MethodDef method) {
var strings = new List<string>(DotNetUtils.getCodeStrings(method));
if (strings.Count != 1)
return null;
@ -75,7 +75,7 @@ namespace de4dot.code.deobfuscators.Babel_NET {
return DotNetUtils.getResource(module, sb.ToString()) as EmbeddedResource;
}
static bool getXorKey2(MethodDefinition method, out int xorKey) {
static bool getXorKey2(MethodDef method, out int xorKey) {
var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count - 2; i++) {
var ldelem = instrs[i];
@ -83,13 +83,13 @@ namespace de4dot.code.deobfuscators.Babel_NET {
continue;
var ldci4 = instrs[i + 1];
if (!DotNetUtils.isLdcI4(ldci4))
if (!ldci4.IsLdcI4())
continue;
if (instrs[i + 2].OpCode.Code != Code.Xor)
continue;
xorKey = DotNetUtils.getLdcI4Value(ldci4);
xorKey = ldci4.GetLdcI4Value();
return true;
}
@ -97,7 +97,7 @@ namespace de4dot.code.deobfuscators.Babel_NET {
return false;
}
public static bool findRegisterMethod(TypeDefinition type, out MethodDefinition regMethod, out MethodDefinition handler) {
public static bool findRegisterMethod(TypeDef type, out MethodDef regMethod, out MethodDef handler) {
foreach (var method in type.Methods) {
if (!method.IsStatic || method.Body == null)
continue;
@ -107,12 +107,12 @@ namespace de4dot.code.deobfuscators.Babel_NET {
foreach (var instr in method.Body.Instructions) {
if (instr.OpCode.Code != Code.Ldftn)
continue;
var handlerRef = instr.Operand as MethodReference;
var handlerRef = instr.Operand as IMethod;
if (handlerRef == null)
continue;
if (!DotNetUtils.isMethod(handlerRef, "System.Reflection.Assembly", "(System.Object,System.ResolveEventArgs)"))
continue;
if (!MemberReferenceHelper.compareTypes(type, handlerRef.DeclaringType))
if (!new SigComparer().Equals(type, handlerRef.DeclaringType))
continue;
handler = DotNetUtils.getMethod(type, handlerRef);
if (handler == null)

View File

@ -21,21 +21,22 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using Mono.Cecil;
using Mono.Cecil.Cil;
using dot10.IO;
using dot10.DotNet;
using dot10.DotNet.Emit;
using de4dot.blocks;
namespace de4dot.code.deobfuscators.Babel_NET {
class ConstantsDecrypter {
ModuleDefinition module;
ModuleDefMD module;
ResourceDecrypter resourceDecrypter;
InitializedDataCreator initializedDataCreator;
TypeDefinition decrypterType;
MethodDefinition int32Decrypter;
MethodDefinition int64Decrypter;
MethodDefinition singleDecrypter;
MethodDefinition doubleDecrypter;
MethodDefinition arrayDecrypter;
TypeDef decrypterType;
MethodDef int32Decrypter;
MethodDef int64Decrypter;
MethodDef singleDecrypter;
MethodDef doubleDecrypter;
MethodDef arrayDecrypter;
EmbeddedResource encryptedResource;
int[] decryptedInts;
long[] decryptedLongs;
@ -54,31 +55,31 @@ namespace de4dot.code.deobfuscators.Babel_NET {
get { return encryptedResource; }
}
public TypeDefinition Type {
public TypeDef Type {
get { return decrypterType; }
}
public MethodDefinition Int32Decrypter {
public MethodDef Int32Decrypter {
get { return int32Decrypter; }
}
public MethodDefinition Int64Decrypter {
public MethodDef Int64Decrypter {
get { return int64Decrypter; }
}
public MethodDefinition SingleDecrypter {
public MethodDef SingleDecrypter {
get { return singleDecrypter; }
}
public MethodDefinition DoubleDecrypter {
public MethodDef DoubleDecrypter {
get { return doubleDecrypter; }
}
public MethodDefinition ArrayDecrypter {
public MethodDef ArrayDecrypter {
get { return arrayDecrypter; }
}
public ConstantsDecrypter(ModuleDefinition module, ResourceDecrypter resourceDecrypter, InitializedDataCreator initializedDataCreator) {
public ConstantsDecrypter(ModuleDefMD module, ResourceDecrypter resourceDecrypter, InitializedDataCreator initializedDataCreator) {
this.module = module;
this.resourceDecrypter = resourceDecrypter;
this.initializedDataCreator = initializedDataCreator;
@ -99,7 +100,7 @@ namespace de4dot.code.deobfuscators.Babel_NET {
}
}
bool isConstantDecrypter(TypeDefinition type) {
bool isConstantDecrypter(TypeDef type) {
if (type.HasEvents)
return false;
if (type.NestedTypes.Count != 1)
@ -109,7 +110,7 @@ namespace de4dot.code.deobfuscators.Babel_NET {
if (!checkNestedFields(nested))
return false;
resourceDecrypter.DecryptMethod = ResourceDecrypter.findDecrypterMethod(DotNetUtils.getMethod(nested, ".ctor"));
resourceDecrypter.DecryptMethod = ResourceDecrypter.findDecrypterMethod(nested.FindMethod(".ctor"));
if (DotNetUtils.getMethod(type, "System.Int32", "(System.Int32)") == null)
return false;
@ -131,11 +132,11 @@ namespace de4dot.code.deobfuscators.Babel_NET {
"System.Single[]",
"System.Double[]",
};
bool checkNestedFields(TypeDefinition nested) {
bool checkNestedFields(TypeDef nested) {
if (!new FieldTypes(nested).all(requiredTypes))
return false;
foreach (var field in nested.Fields) {
if (MemberReferenceHelper.compareTypes(nested, field.FieldType))
if (new SigComparer().Equals(nested, field.FieldSig.GetFieldType()))
return true;
}
return false;
@ -147,11 +148,11 @@ namespace de4dot.code.deobfuscators.Babel_NET {
encryptedResource = BabelUtils.findEmbeddedResource(module, decrypterType, simpleDeobfuscator, deob);
if (encryptedResource == null) {
Log.w("Could not find encrypted constants resource");
Logger.w("Could not find encrypted constants resource");
return;
}
var decrypted = resourceDecrypter.decrypt(encryptedResource.GetResourceData());
var decrypted = resourceDecrypter.decrypt(encryptedResource.Data.ReadAllBytes());
var reader = new BinaryReader(new MemoryStream(decrypted));
int count;
@ -193,11 +194,11 @@ namespace de4dot.code.deobfuscators.Babel_NET {
}
struct ArrayInfo {
public FieldDefinition encryptedField;
public ArrayType arrayType;
public FieldDef encryptedField;
public SZArraySig arrayType;
public int start, len;
public ArrayInfo(int start, int len, FieldDefinition encryptedField, ArrayType arrayType) {
public ArrayInfo(int start, int len, FieldDef encryptedField, SZArraySig arrayType) {
this.start = start;
this.len = len;
this.encryptedField = encryptedField;
@ -232,30 +233,30 @@ namespace de4dot.code.deobfuscators.Babel_NET {
var ldtoken = instrs[index++];
if (ldtoken.OpCode.Code != Code.Ldtoken)
continue;
var field = ldtoken.Operand as FieldDefinition;
var field = ldtoken.Operand as FieldDef;
if (field == null)
continue;
var call1 = instrs[index++];
if (call1.OpCode.Code != Code.Call && call1.OpCode.Code != Code.Callvirt)
continue;
if (!DotNetUtils.isMethod(call1.Operand as MethodReference, "System.Void", "(System.Array,System.RuntimeFieldHandle)"))
if (!DotNetUtils.isMethod(call1.Operand as IMethod, "System.Void", "(System.Array,System.RuntimeFieldHandle)"))
continue;
var call2 = instrs[index++];
if (call2.OpCode.Code != Code.Call && call2.OpCode.Code != Code.Callvirt)
continue;
if (!MemberReferenceHelper.compareMethodReferenceAndDeclaringType(call2.Operand as MethodReference, arrayDecrypter))
if (!MethodEqualityComparer.CompareDeclaringTypes.Equals(call2.Operand as IMethod, arrayDecrypter))
continue;
var castclass = instrs[index++];
if (castclass.OpCode.Code != Code.Castclass)
continue;
var arrayType = castclass.Operand as ArrayType;
var arrayType = (castclass.Operand as ITypeDefOrRef).ToSZArraySig();
if (arrayType == null)
continue;
if (arrayType.ElementType.PrimitiveSize == -1) {
Log.w("Can't decrypt non-primitive type array in method {0}", blocks.Method.MetadataToken.ToInt32());
if (arrayType.Next.ElementType.GetPrimitiveSize() == -1) {
Logger.w("Can't decrypt non-primitive type array in method {0:X8}", blocks.Method.MDToken.ToInt32());
continue;
}
@ -264,11 +265,11 @@ namespace de4dot.code.deobfuscators.Babel_NET {
infos.Reverse();
foreach (var info in infos) {
var elemSize = info.arrayType.ElementType.PrimitiveSize;
var elemSize = info.arrayType.Next.ElementType.GetPrimitiveSize();
var decrypted = decryptArray(info.encryptedField.InitialValue, elemSize);
initializedDataCreator.addInitializeArrayCode(block, info.start, info.len, info.arrayType.ElementType, decrypted);
Log.v("Decrypted {0} array: {1} elements", info.arrayType.ElementType.ToString(), decrypted.Length / elemSize);
initializedDataCreator.addInitializeArrayCode(block, info.start, info.len, info.arrayType.Next.ToTypeDefOrRef(), decrypted);
Logger.v("Decrypted {0} array: {1} elements", info.arrayType.Next.ToString(), decrypted.Length / elemSize);
}
}
}

View File

@ -19,7 +19,7 @@
using System.Collections.Generic;
using System.Text.RegularExpressions;
using Mono.Cecil;
using dot10.DotNet;
using de4dot.blocks;
using de4dot.blocks.cflow;
@ -132,7 +132,7 @@ namespace de4dot.code.deobfuscators.Babel_NET {
this.options = options;
}
public override void init(ModuleDefinition module) {
public override void init(ModuleDefMD module) {
base.init(module);
}
@ -182,10 +182,10 @@ namespace de4dot.code.deobfuscators.Babel_NET {
}
}
void checkVersion(TypeDefinition attr) {
var versionField = DotNetUtils.getFieldByName(attr, "Version");
if (versionField != null && versionField.IsLiteral && versionField.Constant != null && versionField.Constant is string) {
var val = Regex.Match((string)versionField.Constant, @"^(\d+\.\d+\.\d+\.\d+)$");
void checkVersion(TypeDef attr) {
var versionField = attr.FindField("Version");
if (versionField != null && versionField.IsLiteral && versionField.Constant != null && versionField.Constant.Value is string) {
var val = Regex.Match((string)versionField.Constant.Value, @"^(\d+\.\d+\.\d+\.\d+)$");
if (val.Groups.Count < 2)
return;
obfuscatorName = string.Format("{0} {1}", DeobfuscatorInfo.THE_NAME, val.Groups[1].ToString());
@ -206,7 +206,7 @@ namespace de4dot.code.deobfuscators.Babel_NET {
if (Operations.DecryptStrings != OpDecryptString.None) {
if (stringDecrypter.Resource != null)
Log.v("Adding string decrypter. Resource: {0}", Utils.toCsharpString(stringDecrypter.Resource.Name));
Logger.v("Adding string decrypter. Resource: {0}", Utils.toCsharpString(stringDecrypter.Resource.Name));
staticStringInliner.add(stringDecrypter.DecryptMethod, (method, gim, args) => {
return stringDecrypter.decrypt(args);
});
@ -296,7 +296,7 @@ namespace de4dot.code.deobfuscators.Babel_NET {
public override IEnumerable<int> getStringDecrypterMethods() {
var list = new List<int>();
if (stringDecrypter.DecryptMethod != null)
list.Add(stringDecrypter.DecryptMethod.MetadataToken.ToInt32());
list.Add(stringDecrypter.DecryptMethod.MDToken.ToInt32());
return list;
}
}

View File

@ -22,10 +22,14 @@ using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.IO;
using System.Text;
using Mono.Cecil;
using Mono.Cecil.Cil;
using dot10.IO;
using dot10.DotNet;
using dot10.DotNet.Emit;
using de4dot.blocks;
using CR = System.Runtime.InteropServices;
using DR = dot10.DotNet;
namespace de4dot.code.deobfuscators.Babel_NET {
class ImageReader {
static int METHODS_SIG = 0x0000BEBA;
@ -43,19 +47,19 @@ namespace de4dot.code.deobfuscators.Babel_NET {
ByRef = 4,
}
ModuleDefinition module;
BinaryReader reader;
ModuleDefMD module;
IBinaryReader reader;
string[] strings;
AssemblyNameReference[] assemblyNames;
AssemblyRef[] assemblyNames;
Dictionary<string, int> methodOffsets;
List<TypeReference> typeReferences;
List<TypeSig> typeReferences;
MemberReferenceConverter memberReferenceConverter;
IDeobfuscatorContext deobfuscatorContext;
public ImageReader(IDeobfuscatorContext deobfuscatorContext, ModuleDefinition module, byte[] data) {
public ImageReader(IDeobfuscatorContext deobfuscatorContext, ModuleDefMD module, byte[] data) {
this.deobfuscatorContext = deobfuscatorContext;
this.module = module;
this.reader = new BinaryReader(new MemoryStream(data));
this.reader = MemoryImageStream.Create(data);
this.memberReferenceConverter = new MemberReferenceConverter(module);
}
@ -67,14 +71,14 @@ namespace de4dot.code.deobfuscators.Babel_NET {
if (metadataOffset < 0)
return false;
long pos = metadataOffset + 4;
reader.BaseStream.Position = pos;
reader.Position = pos;
int version = reader.ReadInt16(); // major, minor
if (version == 0x0001) {
initializeV10();
return true;
}
reader.BaseStream.Position = pos;
reader.Position = pos;
initializeV55();
return true;
}
@ -104,22 +108,22 @@ namespace de4dot.code.deobfuscators.Babel_NET {
initializeTypeReferences(typeReferencesOffset);
}
public void restore(string name, MethodDefinition method) {
public void restore(string name, MethodDef method) {
var babelMethod = getMethod(name);
var body = method.Body;
body.MaxStackSize = babelMethod.MaxStack;
body.MaxStack = babelMethod.MaxStack;
body.InitLocals = babelMethod.InitLocals;
body.Variables.Clear();
body.LocalList.Clear();
foreach (var local in babelMethod.Locals)
body.Variables.Add(local);
body.LocalList.Add(local);
var toNewOperand = new Dictionary<object, object>();
if (babelMethod.ThisParameter != null)
toNewOperand[babelMethod.ThisParameter] = body.ThisParameter;
for (int i = 0; i < method.Parameters.Count; i++)
toNewOperand[babelMethod.Parameters[i]] = method.Parameters[i];
toNewOperand[babelMethod.ThisParameter] = method.Parameters[0];
for (int i = 0; i < babelMethod.Parameters.Length; i++)
toNewOperand[babelMethod.Parameters[i]] = method.Parameters[i + method.Parameters.MethodSigIndexBase];
body.Instructions.Clear();
foreach (var instr in babelMethod.Instructions) {
@ -137,7 +141,7 @@ namespace de4dot.code.deobfuscators.Babel_NET {
BabelMethodDefinition getMethod(string name) {
int offset = methodOffsets[name];
methodOffsets.Remove(name);
reader.BaseStream.Position = offset;
reader.Position = offset;
return new MethodDefinitionReader(this, reader).read();
}
@ -145,20 +149,20 @@ namespace de4dot.code.deobfuscators.Babel_NET {
return strings[readVariableLengthInt32()];
}
public TypeReference readTypeReference() {
public TypeSig readTypeSig() {
return typeReferences[readVariableLengthInt32()];
}
public TypeReference[] readTypeReferences() {
var refs = new TypeReference[readVariableLengthInt32()];
public TypeSig[] readTypeSigs() {
var refs = new TypeSig[readVariableLengthInt32()];
for (int i = 0; i < refs.Length; i++)
refs[i] = readTypeReference();
refs[i] = readTypeSig();
return refs;
}
public FieldReference readFieldReference() {
public IField readFieldReference() {
var name = readString();
var declaringType = readTypeReference();
var declaringType = readTypeSig();
var fields = getFields(resolve(declaringType), name);
if (fields == null || fields.Count != 1) {
@ -170,18 +174,13 @@ namespace de4dot.code.deobfuscators.Babel_NET {
return memberReferenceConverter.convert(fields[0]);
}
static List<FieldDefinition> getFields(TypeDefinition type, string name) {
static List<FieldDef> getFields(TypeDef type, string name) {
if (type == null)
return null;
var fields = new List<FieldDefinition>();
foreach (var field in type.Fields) {
if (field.Name == name)
fields.Add(field);
}
return fields;
return new List<FieldDef>(type.FindFields(name));
}
public MethodReference readMethodReference() {
public IMethod readMethodReference() {
var babelMethodRef = new MethodReferenceReader(this, reader).read();
var method = getMethodReference(babelMethodRef);
@ -191,16 +190,15 @@ namespace de4dot.code.deobfuscators.Babel_NET {
Utils.removeNewlines(babelMethodRef.DeclaringType)));
}
var git = babelMethodRef.DeclaringType as GenericInstanceType;
var git = babelMethodRef.DeclaringType.ToGenericInstSig();
if (git == null)
return method;
var newMethod = memberReferenceConverter.copy(method);
newMethod.DeclaringType = babelMethodRef.DeclaringType;
return newMethod;
var mr = new MemberRefUser(module, method.Name, method.MethodSig.Clone(), babelMethodRef.DeclaringType.ToTypeDefOrRef());
return module.UpdateRowId(mr);
}
MethodReference getMethodReference(BabelMethodreference babelMethodRef) {
IMethod getMethodReference(BabelMethodreference babelMethodRef) {
var declaringType = resolve(babelMethodRef.DeclaringType);
if (declaringType == null)
return null;
@ -215,20 +213,19 @@ namespace de4dot.code.deobfuscators.Babel_NET {
return methods[0];
}
List<MethodReference> getMethods(TypeDefinition declaringType, BabelMethodreference babelMethodRef) {
var methods = new List<MethodReference>();
List<IMethod> getMethods(TypeDef declaringType, BabelMethodreference babelMethodRef) {
var methods = new List<IMethod>();
var git = babelMethodRef.DeclaringType as GenericInstanceType;
IGenericInstance gim = babelMethodRef.IsGenericMethod ? babelMethodRef : null;
var gis = babelMethodRef.DeclaringType as GenericInstSig;
var gim = babelMethodRef.GenericArguments;
foreach (var method in declaringType.Methods) {
if (compareMethod(MethodReferenceInstance.make(method, git, gim), babelMethodRef)) {
if (compareMethod(GenericArgsSubstitutor.create(method, gis, gim), babelMethodRef)) {
if (!babelMethodRef.IsGenericMethod)
methods.Add(memberReferenceConverter.convert(method));
else {
var gim2 = new GenericInstanceMethod(memberReferenceConverter.convert(method));
foreach (var arg in babelMethodRef.GenericArguments)
gim2.GenericArguments.Add(arg);
methods.Add(gim2);
var gim2 = new GenericInstMethodSig(babelMethodRef.GenericArguments);
var ms = module.UpdateRowId(new MethodSpecUser(memberReferenceConverter.convert(method), gim2));
methods.Add(ms);
}
}
}
@ -236,66 +233,71 @@ namespace de4dot.code.deobfuscators.Babel_NET {
return methods;
}
bool compareMethod(MethodReference method, BabelMethodreference babelMethodRef) {
if (method.Parameters.Count != babelMethodRef.Parameters.Length)
bool compareMethod(IMethod method, BabelMethodreference babelMethodRef) {
var sig = method.MethodSig;
if (sig.Params.Count != babelMethodRef.Parameters.Length)
return false;
if (method.Name != babelMethodRef.Name)
return false;
if (method.HasThis != babelMethodRef.HasThis)
if (sig.HasThis != babelMethodRef.HasThis)
return false;
if (method.GenericParameters.Count != babelMethodRef.GenericArguments.Length)
if (sig.GenParamCount != babelMethodRef.GenericArguments.Length)
return false;
if (!MemberReferenceHelper.compareTypes(method.MethodReturnType.ReturnType, babelMethodRef.ReturnType))
if (!new SigComparer().Equals(sig.RetType, babelMethodRef.ReturnType))
return false;
for (int i = 0; i < babelMethodRef.Parameters.Length; i++) {
if (!MemberReferenceHelper.compareTypes(method.Parameters[i].ParameterType, babelMethodRef.Parameters[i].ParameterType))
if (!new SigComparer().Equals(sig.Params[i], babelMethodRef.Parameters[i].Type))
return false;
}
return true;
}
TypeDefinition resolve(TypeReference type) {
if (type is TypeDefinition)
return (TypeDefinition)type;
TypeDef resolve(TypeSig type) {
type = type.RemovePinnedAndModifiers();
if (type.IsGenericInstance)
type = ((GenericInstanceType)type).ElementType;
var gis = type as GenericInstSig;
if (gis != null)
type = gis.GenericType;
if (type.Module == module && isModuleAssembly(type.Scope))
return DotNetUtils.getType(module, type);
var tdrs = type as TypeDefOrRefSig;
if (tdrs == null)
return null;
return deobfuscatorContext.resolve(type);
var td = tdrs.TypeDef;
if (td != null)
return td;
var tr = tdrs.TypeRef;
if (tr != null)
return tr.Resolve();
return null;
}
public CallSite readCallSite() {
var returnType = readTypeReference();
var paramTypes = readTypeReferences();
var callingConvention = (CallingConvention)reader.ReadInt32();
public MethodSig readCallSite() {
var returnType = readTypeSig();
var paramTypes = readTypeSigs();
var callingConvention = (CR.CallingConvention)reader.ReadInt32();
var cs = new CallSite(returnType);
foreach (var paramType in paramTypes)
cs.Parameters.Add(new ParameterDefinition(paramType));
cs.CallingConvention = convertCallingConvention(callingConvention);
return cs;
return new MethodSig(convertCallingConvention(callingConvention), 0, returnType, paramTypes);
}
static MethodCallingConvention convertCallingConvention(CallingConvention callingConvention) {
static DR.CallingConvention convertCallingConvention(CR.CallingConvention callingConvention) {
switch (callingConvention) {
case CallingConvention.Winapi: return MethodCallingConvention.Default;
case CallingConvention.Cdecl: return MethodCallingConvention.C;
case CallingConvention.StdCall: return MethodCallingConvention.StdCall;
case CallingConvention.ThisCall: return MethodCallingConvention.ThisCall;
case CallingConvention.FastCall: return MethodCallingConvention.FastCall;
case CR.CallingConvention.Winapi: return DR.CallingConvention.Default;
case CR.CallingConvention.Cdecl: return DR.CallingConvention.C;
case CR.CallingConvention.StdCall: return DR.CallingConvention.StdCall;
case CR.CallingConvention.ThisCall: return DR.CallingConvention.ThisCall;
case CR.CallingConvention.FastCall: return DR.CallingConvention.FastCall;
default: throw new ApplicationException(string.Format("Unknown CallingConvention {0}", callingConvention));
}
}
void initializeStrings(int headerOffset) {
reader.BaseStream.Position = headerOffset;
reader.Position = headerOffset;
if (reader.ReadInt32() != STRINGS_SIG)
throw new ApplicationException("Invalid strings sig");
@ -305,27 +307,17 @@ namespace de4dot.code.deobfuscators.Babel_NET {
}
void initializeAssemblyNames(int headerOffset) {
reader.BaseStream.Position = headerOffset;
reader.Position = headerOffset;
if (reader.ReadInt32() != ASSEMBLY_NAMES_SIG)
throw new ApplicationException("Invalid assembly names sig");
assemblyNames = new AssemblyNameReference[readVariableLengthInt32()];
assemblyNames = new AssemblyRef[readVariableLengthInt32()];
for (int i = 0; i < assemblyNames.Length; i++)
assemblyNames[i] = getModuleAssemblyReference(AssemblyNameReference.Parse(readString()));
}
bool isModuleAssembly(IMetadataScope scope) {
return DotNetUtils.isReferenceToModule(module, scope);
}
AssemblyNameReference getModuleAssemblyReference(AssemblyNameReference asmRef) {
if (isModuleAssembly(asmRef))
return module.Assembly.Name;
return memberReferenceConverter.convert(asmRef);
assemblyNames[i] = module.UpdateRowId(new AssemblyRefUser(new AssemblyNameInfo(readString())));
}
void initializeMethodNames(int headerOffset) {
reader.BaseStream.Position = headerOffset;
reader.Position = headerOffset;
if (reader.ReadInt32() != METHOD_NAMES_SIG)
throw new ApplicationException("Invalid methods sig");
@ -338,14 +330,14 @@ namespace de4dot.code.deobfuscators.Babel_NET {
}
void initializeTypeReferences(int headerOffset) {
reader.BaseStream.Position = headerOffset;
reader.Position = headerOffset;
if (reader.ReadInt32() != TYPEREFS_SIG)
throw new ApplicationException("Invalid typerefs sig");
int numTypeRefs = reader.ReadInt32();
typeReferences = new List<TypeReference>(numTypeRefs + 1);
typeReferences = new List<TypeSig>(numTypeRefs + 1);
typeReferences.Add(null);
var genericArgFixes = new Dictionary<GenericInstanceType, List<int>>();
var genericArgFixes = new Dictionary<GenericInstSig, List<int>>();
for (int i = 0; i < numTypeRefs; i++) {
TypeId typeId = (TypeId)reader.ReadByte();
switch (typeId) {
@ -384,35 +376,30 @@ namespace de4dot.code.deobfuscators.Babel_NET {
}
}
TypeReference readTypeRef() {
TypeSig readTypeRef() {
string ns, name;
parseReflectionTypeName(readString(), out ns, out name);
var asmRef = assemblyNames[readVariableLengthInt32()];
var declaringType = readTypeReference();
var typeReference = new TypeReference(ns, name, module, asmRef) {
DeclaringType = declaringType,
};
typeReference.UpdateElementType();
var declaringType = readTypeSig();
var typeReference = new TypeRefUser(module, ns, name);
if (declaringType != null)
typeReference.ResolutionScope = getTypeRef(declaringType);
else
typeReference.ResolutionScope = asmRef;
typeReference = memberReferenceConverter.convert(typeReference);
typeReference.IsValueType = isValueType(typeReference);
return typeReference;
return memberReferenceConverter.convert(typeReference);
}
bool isValueType(TypeReference typeRef) {
var typeDef = typeRef as TypeDefinition;
if (typeDef != null)
return typeDef.IsValueType;
if (typeRef.Module == module && isModuleAssembly(typeRef.Scope))
typeDef = DotNetUtils.getType(module, typeRef);
else
typeDef = resolve(typeRef);
if (typeDef != null)
return typeDef.IsValueType;
Log.w("Could not determine whether type '{0}' is a value type", Utils.removeNewlines(typeRef));
return false; // Assume it's a reference type
TypeRef getTypeRef(TypeSig type) {
var tdr = type as TypeDefOrRefSig;
if (tdr == null)
throw new ApplicationException("Not a type ref");
if (tdr.TypeRef != null)
return tdr.TypeRef;
var td = tdr.TypeDef;
if (td != null)
return new Importer(module).Import(td) as TypeRef;
throw new ApplicationException("Not a type ref");
}
static void parseReflectionTypeName(string fullName, out string ns, out string name) {
@ -461,8 +448,8 @@ namespace de4dot.code.deobfuscators.Babel_NET {
return sb.ToString();
}
GenericInstanceType readGenericInstanceType(out List<int> genericArgs) {
var git = new GenericInstanceType(readTypeReference());
GenericInstSig readGenericInstanceType(out List<int> genericArgs) {
var git = new GenericInstSig(readTypeSig() as ClassOrValueTypeSig);
int numArgs = readVariableLengthInt32();
genericArgs = new List<int>(numArgs);
for (int i = 0; i < numArgs; i++)
@ -470,28 +457,40 @@ namespace de4dot.code.deobfuscators.Babel_NET {
return git;
}
PointerType readPointerType() {
return new PointerType(readTypeReference());
PtrSig readPointerType() {
return new PtrSig(readTypeSig());
}
ArrayType readArrayType() {
return new ArrayType(readTypeReference(), readVariableLengthInt32());
TypeSig readArrayType() {
var typeSig = readTypeSig();
int rank = readVariableLengthInt32();
if (rank == 1)
return new SZArraySig(typeSig);
return new ArraySig(typeSig, rank);
}
ByReferenceType readByReferenceType() {
return new ByReferenceType(readTypeReference());
ByRefSig readByReferenceType() {
return new ByRefSig(readTypeSig());
}
public uint readVariableLengthUInt32() {
uint val;
reader.ReadCompressedUInt32(out val);
return val;
}
public int readVariableLengthInt32() {
return DeobUtils.readVariableLengthInt32(reader);
uint val;
reader.ReadCompressedUInt32(out val);
return (int)val;
}
int getMetadataOffset() {
reader.BaseStream.Position = reader.BaseStream.Length - 4;
reader.Position = reader.Length - 4;
for (int i = 0; i < 30; i++) {
if (reader.ReadInt32() == METADATA_SIG)
return (int)reader.BaseStream.Position - 4;
reader.BaseStream.Position -= 8;
return (int)reader.Position - 4;
reader.Position -= 8;
}
return -1;
}

View File

@ -18,17 +18,17 @@
*/
using ICSharpCode.SharpZipLib.Zip.Compression;
using Mono.Cecil;
using Mono.Cecil.Cil;
using dot10.DotNet;
using dot10.DotNet.Emit;
using de4dot.blocks;
namespace de4dot.code.deobfuscators.Babel_NET {
class InflaterCreator {
public static Inflater create(MethodDefinition method, bool noHeader) {
public static Inflater create(MethodDef method, bool noHeader) {
return create(findInflaterType(method), noHeader);
}
public static Inflater create(TypeDefinition inflaterType, bool noHeader) {
public static Inflater create(TypeDef inflaterType, bool noHeader) {
if (inflaterType == null)
return createNormal(noHeader);
var initHeaderMethod = findInitHeaderMethod(inflaterType);
@ -46,23 +46,23 @@ namespace de4dot.code.deobfuscators.Babel_NET {
static Inflater createNormal(bool noHeader, string errorMessage) {
if (errorMessage != null)
Log.w("{0}", errorMessage);
Logger.w("{0}", errorMessage);
return new Inflater(noHeader);
}
static TypeDefinition findInflaterType(MethodDefinition method) {
static TypeDef findInflaterType(MethodDef method) {
if (method == null || method.Body == null)
return null;
foreach (var instr in method.Body.Instructions) {
if (instr.OpCode.Code != Code.Call)
continue;
var calledMethod = instr.Operand as MethodDefinition;
var calledMethod = instr.Operand as MethodDef;
if (calledMethod == null || !calledMethod.IsStatic)
continue;
var type = calledMethod.DeclaringType;
foreach (var nested in type.NestedTypes) {
if (DeobUtils.hasInteger(DotNetUtils.getMethod(nested, ".ctor"), 0x8001))
if (DeobUtils.hasInteger(nested.FindMethod(".ctor"), 0x8001))
return type;
}
}
@ -70,7 +70,7 @@ namespace de4dot.code.deobfuscators.Babel_NET {
return null;
}
static MethodDefinition findInitHeaderMethod(TypeDefinition inflaterType) {
static MethodDef findInitHeaderMethod(TypeDef inflaterType) {
foreach (var nested in inflaterType.NestedTypes) {
var method = findInitHeaderMethod2(nested);
if (method != null)
@ -79,7 +79,7 @@ namespace de4dot.code.deobfuscators.Babel_NET {
return null;
}
static MethodDefinition findInitHeaderMethod2(TypeDefinition nested) {
static MethodDef findInitHeaderMethod2(TypeDef nested) {
foreach (var method in nested.Methods) {
if (method.IsStatic || method.Body == null)
continue;
@ -92,13 +92,13 @@ namespace de4dot.code.deobfuscators.Babel_NET {
return null;
}
static int? getMagic(MethodDefinition method) {
static int? getMagic(MethodDef method) {
if (method == null || method.Body == null)
return null;
var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count - 3; i++) {
var ldci4_1 = instrs[i];
if (!DotNetUtils.isLdcI4(ldci4_1) || DotNetUtils.getLdcI4Value(ldci4_1) != 16)
if (!ldci4_1.IsLdcI4() || ldci4_1.GetLdcI4Value() != 16)
continue;
var callvirt = instrs[i + 1];
@ -106,13 +106,13 @@ namespace de4dot.code.deobfuscators.Babel_NET {
continue;
var ldci4_2 = instrs[i + 2];
if (!DotNetUtils.isLdcI4(ldci4_2))
if (!ldci4_2.IsLdcI4())
continue;
if (instrs[i + 3].OpCode.Code != Code.Xor)
continue;
return DotNetUtils.getLdcI4Value(ldci4_2);
return ldci4_2.GetLdcI4Value();
}
return null;

View File

@ -18,128 +18,62 @@
*/
using System;
using Mono.Cecil;
using dot10.DotNet;
using de4dot.blocks;
namespace de4dot.code.deobfuscators.Babel_NET {
class TypeReferenceConverter : TypeReferenceUpdaterBase {
MemberReferenceConverter memberReferenceConverter;
ModuleDefinition Module {
get { return memberReferenceConverter.Module; }
}
public TypeReferenceConverter(MemberReferenceConverter memberReferenceConverter) {
this.memberReferenceConverter = memberReferenceConverter;
}
public TypeReference convert(TypeReference a) {
var newOne = update(a);
if (!(a is GenericParameter) && !MemberReferenceHelper.compareTypes(newOne, a))
throw new ApplicationException("Could not convert type reference");
return newOne;
}
protected override TypeReference updateTypeReference(TypeReference a) {
if (a.Module == Module)
return a;
var newTypeRef = new TypeReference(a.Namespace, a.Name, Module, memberReferenceConverter.convert(a.Scope), a.IsValueType);
foreach (var gp in a.GenericParameters)
newTypeRef.GenericParameters.Add(new GenericParameter(gp.Name, newTypeRef));
newTypeRef.DeclaringType = update(a.DeclaringType);
newTypeRef.UpdateElementType();
return newTypeRef;
}
}
// Converts type references/definitions in one module to this module
class MemberReferenceConverter {
ModuleDefinition module;
ModuleDefMD module;
public ModuleDefinition Module {
public ModuleDefMD Module {
get { return module; }
}
public MemberReferenceConverter(ModuleDefinition module) {
public MemberReferenceConverter(ModuleDefMD module) {
this.module = module;
}
bool isInOurModule(MemberReference memberRef) {
bool isInOurModule(IMemberRef memberRef) {
return memberRef.Module == module;
}
public TypeReference convert(TypeReference typeRef) {
if (typeRef == null)
return null;
typeRef = new TypeReferenceConverter(this).convert(typeRef);
return tryGetTypeDefinition(typeRef);
Importer createImporter() {
return new Importer(module, ImporterOptions.TryToUseTypeDefs);
}
public FieldReference convert(FieldReference fieldRef) {
public TypeSig convert(TypeRef typeRef) {
return createImporter().Import(typeRef).ToTypeSig();
}
ITypeDefOrRef convert(ITypeDefOrRef tdr) {
return (ITypeDefOrRef)createImporter().Import(tdr);
}
TypeSig convert2(TypeSig ts) {
return createImporter().Import(ts);
}
public TypeSig convert(TypeSig ts) {
return createImporter().Import(ts);
}
public IField convert(IField fieldRef) {
if (isInOurModule(fieldRef))
return tryGetFieldDefinition(fieldRef);
return new FieldReference(fieldRef.Name, convert(fieldRef.FieldType), convert(fieldRef.DeclaringType));
return createImporter().Import(fieldRef);
}
public MethodReference convert(MethodReference methodRef) {
if (methodRef.GetType() != typeof(MethodReference) && methodRef.GetType() != typeof(MethodDefinition))
public IMethodDefOrRef convert(IMethod methodRef) {
if (!(methodRef is MemberRef || methodRef is MethodDef) || methodRef.MethodSig == null)
throw new ApplicationException("Invalid method reference type");
if (isInOurModule(methodRef))
return tryGetMethodDefinition(methodRef);
return copy(methodRef);
return (IMethodDefOrRef)tryGetMethodDefinition(methodRef);
return (IMethodDefOrRef)createImporter().Import(methodRef);
}
public MethodReference copy(MethodReference methodRef) {
if (methodRef.GetType() != typeof(MethodReference) && methodRef.GetType() != typeof(MethodDefinition))
throw new ApplicationException("Invalid method reference type");
var newMethodRef = new MethodReference(methodRef.Name, convert(methodRef.MethodReturnType.ReturnType), convert(methodRef.DeclaringType));
newMethodRef.HasThis = methodRef.HasThis;
newMethodRef.ExplicitThis = methodRef.ExplicitThis;
newMethodRef.CallingConvention = methodRef.CallingConvention;
foreach (var param in methodRef.Parameters)
newMethodRef.Parameters.Add(new ParameterDefinition(param.Name, param.Attributes, convert(param.ParameterType)));
foreach (var gp in methodRef.GenericParameters)
newMethodRef.GenericParameters.Add(new GenericParameter(gp.Name, newMethodRef));
return newMethodRef;
}
public IMetadataScope convert(IMetadataScope scope) {
switch (scope.MetadataScopeType) {
case MetadataScopeType.AssemblyNameReference:
return convert((AssemblyNameReference)scope);
case MetadataScopeType.ModuleDefinition:
var mod = (ModuleDefinition)scope;
if (mod.Assembly != null)
return convert((AssemblyNameReference)mod.Assembly.Name);
return convert((ModuleReference)scope);
case MetadataScopeType.ModuleReference:
return convert((ModuleReference)scope);
default:
throw new ApplicationException("Unknown MetadataScopeType");
}
}
public AssemblyNameReference convert(AssemblyNameReference asmRef) {
return DotNetUtils.addAssemblyReference(module, asmRef);
}
public ModuleReference convert(ModuleReference modRef) {
return DotNetUtils.addModuleReference(module, modRef);
}
public TypeReference tryGetTypeDefinition(TypeReference typeRef) {
return DotNetUtils.getType(module, typeRef) ?? typeRef;
}
public FieldReference tryGetFieldDefinition(FieldReference fieldRef) {
var fieldDef = fieldRef as FieldDefinition;
public IField tryGetFieldDefinition(IField fieldRef) {
var fieldDef = fieldRef as FieldDef;
if (fieldDef != null)
return fieldDef;
@ -149,8 +83,8 @@ namespace de4dot.code.deobfuscators.Babel_NET {
return DotNetUtils.getField(declaringType, fieldRef);
}
public MethodReference tryGetMethodDefinition(MethodReference methodRef) {
var methodDef = methodRef as MethodDefinition;
public IMethod tryGetMethodDefinition(IMethod methodRef) {
var methodDef = methodRef as MethodDef;
if (methodDef != null)
return methodDef;

View File

@ -18,75 +18,83 @@
*/
using System;
using System.Collections.Generic;
using System.IO;
using Mono.Cecil;
using Mono.Cecil.Cil;
using dot10.IO;
using dot10.DotNet;
using dot10.DotNet.Emit;
namespace de4dot.code.deobfuscators.Babel_NET {
class MethodBodyReader : MethodBodyReaderBase {
ImageReader imageReader;
public int Flags2 { get; set; }
public short MaxStack { get; set; }
public ushort MaxStack { get; set; }
public MethodBodyReader(ImageReader imageReader, BinaryReader reader)
public MethodBodyReader(ImageReader imageReader, IBinaryReader reader)
: base(reader) {
this.imageReader = imageReader;
}
public void read(ParameterDefinition[] parameters) {
public void read(IList<Parameter> parameters) {
this.parameters = parameters;
Flags2 = reader.ReadInt16();
MaxStack = reader.ReadInt16();
setLocals(imageReader.readTypeReferences());
readInstructions(imageReader.readVariableLengthInt32());
MaxStack = reader.ReadUInt16();
SetLocals(imageReader.readTypeSigs());
ReadInstructions(imageReader.readVariableLengthInt32());
readExceptionHandlers(imageReader.readVariableLengthInt32());
}
protected override FieldReference readInlineField(Instruction instr) {
protected override IField ReadInlineField(Instruction instr) {
return imageReader.readFieldReference();
}
protected override MethodReference readInlineMethod(Instruction instr) {
protected override IMethod ReadInlineMethod(Instruction instr) {
return imageReader.readMethodReference();
}
protected override CallSite readInlineSig(Instruction instr) {
protected override MethodSig ReadInlineSig(Instruction instr) {
return imageReader.readCallSite();
}
protected override string readInlineString(Instruction instr) {
protected override string ReadInlineString(Instruction instr) {
return imageReader.readString();
}
protected override MemberReference readInlineTok(Instruction instr) {
protected override ITokenOperand ReadInlineTok(Instruction instr) {
switch (reader.ReadByte()) {
case 0: return imageReader.readTypeReference();
case 0: return imageReader.readTypeSig().ToTypeDefOrRef();
case 1: return imageReader.readFieldReference();
case 2: return imageReader.readMethodReference();
default: throw new ApplicationException("Unknown token type");
}
}
protected override TypeReference readInlineType(Instruction instr) {
return imageReader.readTypeReference();
protected override ITypeDefOrRef ReadInlineType(Instruction instr) {
return imageReader.readTypeSig().ToTypeDefOrRef();
}
protected override ExceptionHandler readExceptionHandler() {
void readExceptionHandlers(int numExceptionHandlers) {
exceptionHandlers = new List<ExceptionHandler>(numExceptionHandlers);
for (int i = 0; i < numExceptionHandlers; i++)
Add(readExceptionHandler());
}
ExceptionHandler readExceptionHandler() {
var ehType = (ExceptionHandlerType)reader.ReadByte();
int tryOffset = imageReader.readVariableLengthInt32();
int tryLength = imageReader.readVariableLengthInt32();
int handlerOffset = imageReader.readVariableLengthInt32();
int handlerLength = imageReader.readVariableLengthInt32();
var catchType = imageReader.readTypeReference();
int filterOffset = imageReader.readVariableLengthInt32();
uint tryOffset = imageReader.readVariableLengthUInt32();
uint tryLength = imageReader.readVariableLengthUInt32();
uint handlerOffset = imageReader.readVariableLengthUInt32();
uint handlerLength = imageReader.readVariableLengthUInt32();
var catchType = imageReader.readTypeSig().ToTypeDefOrRef();
uint filterOffset = imageReader.readVariableLengthUInt32();
var eh = new ExceptionHandler(ehType);
eh.TryStart = getInstruction(tryOffset);
eh.TryEnd = getInstructionOrNull(tryOffset + tryLength);
eh.TryStart = GetInstructionThrow(tryOffset);
eh.TryEnd = GetInstruction(tryOffset + tryLength);
if (ehType == ExceptionHandlerType.Filter)
eh.FilterStart = getInstruction(filterOffset);
eh.HandlerStart = getInstruction(handlerOffset);
eh.HandlerEnd = getInstructionOrNull(handlerOffset + handlerLength);
eh.FilterStart = GetInstructionThrow(filterOffset);
eh.HandlerStart = GetInstructionThrow(handlerOffset);
eh.HandlerEnd = GetInstruction(handlerOffset + handlerLength);
eh.CatchType = catchType;
return eh;
}

View File

@ -20,17 +20,17 @@
using System;
using System.Collections.Generic;
using System.IO;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Collections.Generic;
using dot10.IO;
using dot10.DotNet;
using dot10.DotNet.Emit;
namespace de4dot.code.deobfuscators.Babel_NET {
class BabelMethodreference : IGenericInstance {
class BabelMethodreference {
public string Name { get; set; }
public TypeReference DeclaringType { get; set; }
public TypeReference ReturnType { get; set; }
public ParameterDefinition[] Parameters { get; set; }
public TypeReference[] GenericArguments { get; set; }
public TypeSig DeclaringType { get; set; }
public TypeSig ReturnType { get; set; }
public Parameter[] Parameters { get; set; }
public TypeSig[] GenericArguments { get; set; }
public int Flags { get; set; }
public bool HasThis {
@ -40,27 +40,14 @@ namespace de4dot.code.deobfuscators.Babel_NET {
public bool IsGenericMethod {
get { return (Flags & 2) != 0; }
}
bool IGenericInstance.HasGenericArguments {
get { return IsGenericMethod; }
}
Collection<TypeReference> IGenericInstance.GenericArguments {
get { return new Collection<TypeReference>(GenericArguments); }
}
MetadataToken IMetadataTokenProvider.MetadataToken {
get { throw new NotImplementedException(); }
set { throw new NotImplementedException(); }
}
}
class BabelMethodDefinition : BabelMethodreference {
ParameterDefinition thisParameter;
Parameter thisParameter;
public int Flags2 { get; set; }
public short MaxStack { get; set; }
public IList<VariableDefinition> Locals { get; set; }
public ushort MaxStack { get; set; }
public IList<Local> Locals { get; set; }
public IList<Instruction> Instructions { get; set; }
public IList<ExceptionHandler> ExceptionHandlers { get; set; }
@ -80,13 +67,13 @@ namespace de4dot.code.deobfuscators.Babel_NET {
get { return (Flags2 & 0x80) != 0; }
}
public ParameterDefinition ThisParameter {
public Parameter ThisParameter {
get {
if (!HasThis)
return null;
if (thisParameter != null)
return thisParameter;
return thisParameter = new ParameterDefinition(DeclaringType);
return thisParameter = new Parameter(0, Parameter.HIDDEN_THIS_METHOD_SIG_INDEX, DeclaringType);
}
}
@ -98,10 +85,10 @@ namespace de4dot.code.deobfuscators.Babel_NET {
ExceptionHandlers = mbr.ExceptionHandlers;
}
public ParameterDefinition[] getRealParameters() {
public IList<Parameter> getRealParameters() {
if (ThisParameter == null)
return Parameters;
var parameters = new ParameterDefinition[Parameters.Length + 1];
var parameters = new Parameter[Parameters.Length + 1];
parameters[0] = ThisParameter;
Array.Copy(Parameters, 0, parameters, 1, Parameters.Length);
return parameters;
@ -110,14 +97,14 @@ namespace de4dot.code.deobfuscators.Babel_NET {
class MethodReferenceReader {
ImageReader imageReader;
BinaryReader reader;
IBinaryReader reader;
BabelMethodreference bmr;
public MethodReferenceReader(ImageReader imageReader, BinaryReader reader)
public MethodReferenceReader(ImageReader imageReader, IBinaryReader reader)
: this(imageReader, reader, new BabelMethodreference()) {
}
public MethodReferenceReader(ImageReader imageReader, BinaryReader reader, BabelMethodreference bmr) {
public MethodReferenceReader(ImageReader imageReader, IBinaryReader reader, BabelMethodreference bmr) {
this.imageReader = imageReader;
this.reader = reader;
this.bmr = bmr;
@ -125,23 +112,24 @@ namespace de4dot.code.deobfuscators.Babel_NET {
public BabelMethodreference read() {
bmr.Name = imageReader.readString();
bmr.DeclaringType = imageReader.readTypeReference();
bmr.ReturnType = imageReader.readTypeReference();
bmr.Parameters = readParameters();
bmr.DeclaringType = imageReader.readTypeSig();
bmr.ReturnType = imageReader.readTypeSig();
var argTypes = imageReader.readTypeSigs();
bmr.Flags = reader.ReadByte();
if (bmr.IsGenericMethod)
bmr.GenericArguments = imageReader.readTypeReferences();
bmr.GenericArguments = imageReader.readTypeSigs();
else
bmr.GenericArguments = new TypeReference[0];
bmr.GenericArguments = new TypeSig[0];
bmr.Parameters = readParameters(argTypes, bmr.HasThis);
return bmr;
}
ParameterDefinition[] readParameters() {
var typeReferences = imageReader.readTypeReferences();
var parameters = new ParameterDefinition[typeReferences.Length];
for (int i = 0; i < parameters.Length; i++)
parameters[i] = new ParameterDefinition(typeReferences[i]);
return parameters;
Parameter[] readParameters(IList<TypeSig> argTypes, bool hasThis) {
var ps = new Parameter[argTypes.Count];
int bi = hasThis ? 1 : 0;
for (int i = 0; i < ps.Length; i++)
ps[i] = new Parameter(bi + i, i, argTypes[i]);
return ps;
}
}
@ -150,7 +138,7 @@ namespace de4dot.code.deobfuscators.Babel_NET {
MethodBodyReader methodBodyReader;
BabelMethodDefinition bmd;
public MethodDefinitionReader(ImageReader imageReader, BinaryReader reader) {
public MethodDefinitionReader(ImageReader imageReader, IBinaryReader reader) {
this.bmd = new BabelMethodDefinition();
this.methodReferenceReader = new MethodReferenceReader(imageReader, reader, bmd);
this.methodBodyReader = new MethodBodyReader(imageReader, reader);

Some files were not shown because too many files have changed in this diff Show More