Merge branch 'port' into confuser
Conflicts: de4dot.code/de4dot.code.csproj
This commit is contained in:
commit
ff86ca6d24
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -7,3 +7,4 @@
|
|||
/Debug/
|
||||
/Release/
|
||||
/de4dot.snk
|
||||
/cecil/
|
||||
|
|
6
.gitmodules
vendored
6
.gitmodules
vendored
|
@ -1,3 +1,3 @@
|
|||
[submodule "cecil"]
|
||||
path = cecil
|
||||
url = git@github.com:0xd4d/cecil.git
|
||||
[submodule "dot10"]
|
||||
path = dot10
|
||||
url = e:/work/dot10.git
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using Mono.Cecil;
|
||||
|
||||
namespace AssemblyData.methodsrewriter {
|
||||
interface IMethodsRewriter {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
167
README.md
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
42
blocks/DumpedMethod.cs
Normal 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
54
blocks/DumpedMethods.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -18,8 +18,6 @@
|
|||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Mono.Cecil;
|
||||
using Mono.Cecil.Cil;
|
||||
|
||||
namespace de4dot.blocks {
|
||||
public class FilterHandlerBlock : ScopeBlock {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
313
blocks/GenericArgsSubstitutor.cs
Normal file
313
blocks/GenericArgsSubstitutor.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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) { }.
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
736
blocks/MemberDefDict.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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; }
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>();
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
cecil
|
@ -1 +0,0 @@
|
|||
Subproject commit 119a3d404ab12a8a19a249e97c1e5f6ca0850b6a
|
|
@ -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() {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
75
de4dot.code/DumpedMethodsRestorer.cs
Normal file
75
de4dot.code/DumpedMethodsRestorer.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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
165
de4dot.code/Logger.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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)"))
|
|
@ -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() {
|
||||
}
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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;
|
|
@ -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;
|
||||
}
|
|
@ -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() {
|
|
@ -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; }
|
|
@ -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++;
|
||||
}
|
||||
}
|
|
@ -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) {
|
|
@ -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) {
|
|
@ -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[] {
|
|
@ -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++;
|
|
@ -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>();
|
||||
|
|
@ -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 {
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue
Block a user