} //TODO: Improve detection /* 0x000005B7 6F1500000A IL_001F: callvirt instance uint8[][mscorlib] System.Reflection.Module::ResolveSignature(int32) * 0x000005BC FE0E0100 IL_0024: stloc.1 * 0x000005C0 FE0C0100 IL_0028: ldloc.1 * 0x000005C4 8E IL_002C: ldlen * 0x000005C5 69 IL_002D: conv.i4 * 0x000005C6 FE0E0200 IL_002E: stloc.2 */ private int GetEmulationStartIndex(IList <Instruction> instructions, Local localArray, Local localArraySize) { for (var i = 0; i < instructions.Count; i++) { var instrs = DotNetUtils.GetInstructions(instructions, i, OpCodes.Callvirt, OpCodes.Stloc, OpCodes.Ldloc, OpCodes.Ldlen, OpCodes.Conv_I4, OpCodes.Stloc); if (instrs == null) { continue; } if (!instrs[0].Operand.ToString().Contains("ResolveSignature")) { continue; } if ((Local)instrs[1].Operand != localArray) { continue; } if ((Local)instrs[2].Operand != localArray) { continue; } if ((Local)instrs[5].Operand != localArraySize) { continue; } return(i + 6); } return(-1); }
/* 0x00000371 08 IL_0079: ldloc.2 * 0x00000372 17 IL_007A: ldc.i4.1 * 0x00000373 59 IL_007B: sub * 0x00000374 0C IL_007C: stloc.2 */ private void RemoveDecrementorBlock(ref IList <Instruction> instructions, Local localInt) { for (var i = 0; i < instructions.Count; i++) { var instrs = DotNetUtils.GetInstructions(instructions, i, OpCodes.Ldloc, OpCodes.Ldc_I4, OpCodes.Sub, OpCodes.Stloc); if (instrs == null) { continue; } if ((Local)instrs[0].Operand != localInt) { continue; } if ((int)instrs[1].Operand != 1) { continue; } if ((Local)instrs[3].Operand != localInt) { continue; } instructions[i].OpCode = OpCodes.Nop; instructions[i + 1].OpCode = OpCodes.Nop; instructions[i + 2].OpCode = OpCodes.Nop; instructions[i + 3].OpCode = OpCodes.Nop; return; } }
protected override object CheckCctor(TypeDef type, MethodDef cctor) { var instructions = cctor.Body.Instructions; for (int i = 0; i < instructions.Count; i++) { var instrs = DotNetUtils.GetInstructions(instructions, i, OpCodes.Ldc_I4, OpCodes.Ldc_I4, OpCodes.Ldc_I4, OpCodes.Call); if (instrs == null) { continue; } uint typeToken = (uint)(int)instrs[0].Operand; uint methodToken = (uint)(int)instrs[1].Operand; uint declaringTypeToken = (uint)(int)instrs[2].Operand; var createMethod = instrs[3].Operand as MethodDef; if (!methodToType.TryGetValue(createMethod, out var proxyCreatorType)) { continue; } return(new Context(typeToken, methodToken, declaringTypeToken, proxyCreatorType)); } return(null); }
protected override object CheckCctor(TypeDef type, MethodDef cctor) { if (!_processedMethods.Contains(cctor)) { _simpleDeobfuscator.Deobfuscate(cctor); _processedMethods.Add(cctor); } var contexts = new List <Context>(); var instructions = cctor.Body.Instructions; instructions.SimplifyMacros(cctor.Body.Variables, cctor.Parameters); for (var i = 0; i < instructions.Count; i++) { var instrs = DotNetUtils.GetInstructions(instructions, i, OpCodes.Ldtoken, OpCodes.Ldc_I4, OpCodes.Call); if (instrs == null) { continue; } var fieldToken = ((IField)instrs[0].Operand).MDToken.ToUInt32(); var byteNum = (int)instrs[1].Operand; var createMethod = instrs[2].Operand as MethodDef; if (!DelegateCreatorMethods.Contains(createMethod)) { DelegateCreatorMethods.Add(createMethod); } contexts.Add(new Context(fieldToken, byteNum, createMethod)); } return(contexts.Count == 0 ? null : contexts); }
static FieldDef FindEncryptedStrings(MethodDef initMethod, List <FieldDef> ourFields, out FieldDef dataField) { for (int i = 0; i < initMethod.Body.Instructions.Count; i++) { var instrs = DotNetUtils.GetInstructions(initMethod.Body.Instructions, i, OpCodes.Ldtoken, OpCodes.Call, OpCodes.Stsfld); if (instrs == null) { continue; } dataField = instrs[0].Operand as FieldDef; if (dataField == null || dataField.InitialValue == null || dataField.InitialValue.Length == 0) { continue; } var savedField = instrs[2].Operand as FieldDef; if (savedField == null || !Matches(ourFields, savedField)) { continue; } return(savedField); } dataField = null; return(null); }
protected override object CheckCctor(TypeDef type, MethodDef cctor) { var instructions = cctor.Body.Instructions; for (int i = 0; i < instructions.Count; i++) { ITypeDefOrRef delegateType; IField delegateField; IMethod createMethod; int methodToken, declaringTypeToken; var instrs = DotNetUtils.GetInstructions(instructions, i, OpCodes.Ldtoken, OpCodes.Ldc_I4, OpCodes.Ldc_I4, OpCodes.Ldtoken, OpCodes.Call); if (instrs != null) { delegateType = instrs[0].Operand as ITypeDefOrRef; methodToken = instrs[1].GetLdcI4Value(); declaringTypeToken = instrs[2].GetLdcI4Value(); delegateField = instrs[3].Operand as IField; createMethod = instrs[4].Operand as IMethod; } else if ((instrs = DotNetUtils.GetInstructions(instructions, i, OpCodes.Ldtoken, OpCodes.Ldc_I4, OpCodes.Ldtoken, OpCodes.Call)) != null) { delegateType = instrs[0].Operand as ITypeDefOrRef; methodToken = instrs[1].GetLdcI4Value(); declaringTypeToken = -1; delegateField = instrs[2].Operand as IField; createMethod = instrs[3].Operand as IMethod; } else { continue; } if (delegateType == null) { continue; } if (delegateField == null) { continue; } if (createMethod == null) { continue; } var proxyCreatorType = methodToType.Find(createMethod); if (proxyCreatorType == ProxyCreatorType.None) { continue; } return(new Context(delegateType, methodToken, declaringTypeToken, proxyCreatorType)); } return(null); }
bool InitializeArrays2(ISimpleDeobfuscator simpleDeobfuscator, MethodDef method) { bool foundField = false; simpleDeobfuscator.Deobfuscate(method, true); var instructions = method.Body.Instructions; for (int i = 0; i < instructions.Count; i++) { var ldci4 = instructions[i]; if (!ldci4.IsLdcI4()) { continue; } i++; var instrs = DotNetUtils.GetInstructions(instructions, i, OpCodes.Newarr, OpCodes.Dup, OpCodes.Ldtoken, OpCodes.Call, OpCodes.Stsfld); if (instrs == null) { continue; } var arrayInitField = instrs[2].Operand as FieldDef; if (arrayInitField == null || arrayInitField.InitialValue == null || arrayInitField.InitialValue.Length == 0) { continue; } var calledMethod = instrs[3].Operand as IMethod; if (calledMethod == null || calledMethod.FullName != "System.Void System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(System.Array,System.RuntimeFieldHandle)") { continue; } var targetField = instrs[4].Operand as FieldDef; if (targetField == null || targetField.FieldType.GetElementType() != ElementType.SZArray) { continue; } var etype = ((SZArraySig)targetField.FieldType).Next.GetElementType(); if (etype < ElementType.Boolean || etype > ElementType.U4) { continue; } if (fieldToInfo.Find(targetField) == null) { fieldToInfo.Add(targetField, new FieldInfo(targetField, arrayInitField)); foundField = true; } } return(foundField); }
/// <summary> /// Find and set the ArgumentsField. /// </summary> private void InitializeArgumentsField() { // Get arguments field MethodDef setArgumentsMethod = null; var methods = this.Type.Methods; foreach (var method in methods) { if (!method.IsStatic && method.IsPrivate && method.ReturnType.FullName.Equals("System.Object") && method.Parameters.Count == 5 && method.Parameters[1].Type.FullName.Equals("System.Object[]") && method.Parameters[2].Type.FullName.Equals("System.Type[]") && method.Parameters[3].Type.FullName.Equals("System.Type[]") && method.Parameters[4].Type.FullName.Equals("System.Object[]")) { setArgumentsMethod = method; break; } } if (setArgumentsMethod == null) { throw new Exception("Unable to find the method in which the arguments field is set"); } var instructions = setArgumentsMethod.Body.Instructions; DotNetUtils.GetInstructions(instructions, 4, Code.Stfld.ToOpCode()); Int32 stfldCount = 0; foreach (var instr in instructions) { if (instr.OpCode.Code == Code.Stfld) { stfldCount++; } if (stfldCount == 4) { this.ArgumentsField = (FieldDef)instr.Operand; break; } } if (this.ArgumentsField == null) { throw new Exception("Unable to find arguments field"); } }
IEnumerable <MethodDef> GetResolverHandlers(MethodDef method) { int numHandlers = 0; var instructions = method.Body.Instructions; for (int i = 0; i < instructions.Count; i++) { var instrs = DotNetUtils.GetInstructions(instructions, i, OpCodes.Call, OpCodes.Ldnull, OpCodes.Ldftn, OpCodes.Newobj, OpCodes.Callvirt); if (instrs == null) { continue; } var call = instrs[0]; if (!DotNetUtils.IsMethod(call.Operand as IMethod, "System.AppDomain", "()")) { continue; } var ldftn = instrs[2]; var handlerDef = DotNetUtils.GetMethod(module, ldftn.Operand as IMethod); if (handlerDef == null) { continue; } var newobj = instrs[3]; if (!DotNetUtils.IsMethod(newobj.Operand as IMethod, "System.Void", "(System.Object,System.IntPtr)")) { continue; } var callvirt = instrs[4]; if (!DotNetUtils.IsMethod(callvirt.Operand as IMethod, "System.Void", "(System.ResolveEventHandler)")) { continue; } numHandlers++; yield return(handlerDef); } // If no handlers found, it's possible that the method itself is the handler. if (numHandlers == 0) { yield return(method); } }
ResolverVersion CheckSetupMethod(MethodDef setupMethod) { var instructions = setupMethod.Body.Instructions; int foundCount = 0; for (int i = 0; i < instructions.Count; i++) { var instrs = DotNetUtils.GetInstructions(instructions, i, OpCodes.Ldnull, OpCodes.Ldftn, OpCodes.Newobj); if (instrs == null) { continue; } IMethod methodRef; var ldftn = instrs[1]; var newobj = instrs[2]; methodRef = ldftn.Operand as IMethod; if (methodRef == null || !new SigComparer().Equals(setupMethod.DeclaringType, methodRef.DeclaringType)) { continue; } methodRef = newobj.Operand as IMethod; if (methodRef == null || methodRef.FullName != "System.Void System.ResolveEventHandler::.ctor(System.Object,System.IntPtr)") { continue; } foundCount++; } if (foundCount == 0) { return(ResolverVersion.None); } switch (foundCount) { case 1: return(ResolverVersion.V1); case 2: return(ResolverVersion.V2); default: return(ResolverVersion.None); } }
bool CheckCctor(MethodDef cctor, out FieldDef compressedDataField, out StringDataFlags flags) { flags = 0; var instructions = cctor.Body.Instructions; for (int i = 0; i < instructions.Count; i++) { var ldci4 = instructions[i]; if (!ldci4.IsLdcI4()) { continue; } var instrs = DotNetUtils.GetInstructions(instructions, i + 1, OpCodes.Newarr, OpCodes.Dup, OpCodes.Ldtoken, OpCodes.Call); if (instrs == null) { continue; } var newarr = instrs[0]; if (newarr.Operand.ToString() != "System.Byte") { continue; } var field = instrs[2].Operand as FieldDef; if (field == null || field.InitialValue == null || field.InitialValue.Length == 0) { continue; } int index = i + 1 + instrs.Count; if (index < instructions.Count && instructions[index].OpCode.Code == Code.Call) { flags = GetStringDataFlags(instructions[index].Operand as MethodDef); } compressedDataField = field; return(true); } compressedDataField = null; return(false); }
/* 0x000008F3 03 IL_02BB: ldarg.1 * 0x000008F4 61 IL_02BC: xor */ private int GetCharNum(IList <Instruction> instructions, Parameter byteParam) { for (var i = 0; i < instructions.Count; i++) { var instrs = DotNetUtils.GetInstructions(instructions, i, OpCodes.Ldarg, OpCodes.Xor); if (instrs == null) { continue; } if ((Parameter)instrs[0].Operand != byteParam) { continue; } return((int)instructions[i - 5].Operand); } throw new Exception(); }
protected override bool CheckHandlerMethod(MethodDef method) { if (!method.IsStatic || !method.HasBody) { return(false); } EmbeddedAssemblyInfo info = null; var instructions = method.Body.Instructions; for (int i = 0; i < instructions.Count; i++) { var instrs = DotNetUtils.GetInstructions(instructions, i, OpCodes.Ldstr, OpCodes.Call); if (instrs == null) { continue; } var s = instrs[0].Operand as string; var calledMethod = instrs[1].Operand as IMethod; if (s == null || calledMethod == null) { continue; } info = assemblyResolverInfo.Find(Utils.GetAssemblySimpleName(s)); if (info != null) { break; } } if (info == null) { return(false); } resourceInfo = info; Logger.v("Found embedded assemblies resource {0}", Utils.ToCsharpString(info.resourceName)); return(true); }
private bool InlineArray(ref IList <Instruction> instructions, int value, Local localArray, Local localInt) { for (var i = 0; i < instructions.Count; i++) { var instrs = DotNetUtils.GetInstructions(instructions, i, OpCodes.Ldloc, OpCodes.Ldloc, OpCodes.Ldc_I4, OpCodes.Sub, OpCodes.Dup, OpCodes.Stloc, OpCodes.Ldelem_U1); if (instrs == null) { continue; } if ((Local)instrs[0].Operand != localArray) { continue; } if ((Local)instrs[1].Operand != localInt) { continue; } if ((int)instrs[2].Operand != 1) { continue; } if ((Local)instrs[5].Operand != localInt) { continue; } instructions[i].OpCode = OpCodes.Ldc_I4; instructions[i].Operand = value; instructions[i + 1].OpCode = OpCodes.Nop; instructions[i + 2].OpCode = OpCodes.Nop; instructions[i + 3].OpCode = OpCodes.Nop; instructions[i + 4].OpCode = OpCodes.Nop; instructions[i + 5].OpCode = OpCodes.Nop; instructions[i + 6].OpCode = OpCodes.Nop; return(true); } return(false); }
ArrayInfo GetArrayInfo(MethodDef method) { var instructions = method.Body.Instructions; for (int i = 0; i < instructions.Count; i++) { var ldci4_arraySizeInBytes = instructions[i]; if (!ldci4_arraySizeInBytes.IsLdcI4()) { continue; } i++; var instrs = DotNetUtils.GetInstructions(instructions, i, OpCodes.Newarr, OpCodes.Dup, OpCodes.Ldtoken, OpCodes.Call, OpCodes.Stsfld); if (instrs == null) { continue; } int sizeInBytes = ldci4_arraySizeInBytes.GetLdcI4Value(); var elementType = instrs[0].Operand as ITypeDefOrRef; var initField = instrs[2].Operand as FieldDef; var field = instrs[4].Operand as FieldDef; if (elementType == null) { continue; } if (initField == null || initField.InitialValue == null || initField.InitialValue.Length == 0) { continue; } if (!fields.Find(field)) { continue; } return(new ArrayInfo(sizeInBytes, elementType, initField, field)); } return(null); }
bool CheckInitMethod(MethodDef initMethod) { if (!initMethod.HasBody) { return(false); } var instructions = initMethod.Body.Instructions; for (int i = 0; i < instructions.Count; i++) { var instrs = DotNetUtils.GetInstructions(instructions, i, OpCodes.Ldnull, OpCodes.Ldftn, OpCodes.Newobj); if (instrs == null) { continue; } IMethod methodRef; var ldftn = instrs[1]; var newobj = instrs[2]; methodRef = ldftn.Operand as IMethod; if (methodRef == null || !new SigComparer().Equals(initMethod.DeclaringType, methodRef.DeclaringType)) { continue; } methodRef = newobj.Operand as IMethod; if (methodRef == null || methodRef.FullName != "System.Void System.ResolveEventHandler::.ctor(System.Object,System.IntPtr)") { continue; } return(true); } return(false); }
/* 0x000005CF FE0C0000 IL_0037: ldloc.0 * 0x000005D3 6F1600000A IL_003B: callvirt instance class [mscorlib] System.Type[][mscorlib] System.Reflection.FieldInfo::GetOptionalCustomModifiers() * 0x000005D8 2000000000 IL_0040: ldc.i4.0 * 0x000005DD 9A IL_0045: ldelem.ref * 0x000005DE 6F1400000A IL_0046: callvirt instance int32[mscorlib] System.Reflection.MemberInfo::get_MetadataToken() */ private void ReplaceMetadataToken(ref IList <Instruction> instructions, int metadataToken, Local fieldLocal) { for (var i = 0; i < instructions.Count; i++) { var instrs = DotNetUtils.GetInstructions(instructions, i, OpCodes.Ldloc, OpCodes.Callvirt, OpCodes.Ldc_I4, OpCodes.Ldelem_Ref, OpCodes.Callvirt); if (instrs == null) { continue; } if ((Local)instrs[0].Operand != fieldLocal) { continue; } if (!instrs[1].Operand.ToString().Contains("GetOptionalCustomModifiers")) { continue; } if ((int)instrs[2].Operand != 0) { continue; } if (!instrs[4].Operand.ToString().Contains("get_MetadataToken")) { continue; } instructions[i].OpCode = OpCodes.Ldc_I4; instructions[i].Operand = metadataToken; instructions[i + 1].OpCode = OpCodes.Nop; instructions[i + 2].OpCode = OpCodes.Nop; instructions[i + 3].OpCode = OpCodes.Nop; instructions[i + 4].OpCode = OpCodes.Nop; return; } }
bool CallsMainTypeTamperCheckMethod(MethodDef method) { foreach (var calledMethod in DotNetUtils.GetCalledMethods(module, method)) { if (calledMethod == mainType.TamperCheckMethod) { return(true); } } var instructions = method.Body.Instructions; for (int i = 0; i < instructions.Count; i++) { var instrs = DotNetUtils.GetInstructions(instructions, i, OpCodes.Ldtoken, OpCodes.Call, OpCodes.Call, OpCodes.Ldc_I8, OpCodes.Call); if (instrs == null) { continue; } if (!CheckInvokeCall(instrs[1], "System.Type", "(System.RuntimeTypeHandle)")) { continue; } if (!CheckInvokeCall(instrs[2], "System.Reflection.Assembly", "(System.Object)")) { continue; } if (!CheckInvokeCall(instrs[4], "System.Void", "(System.Reflection.Assembly,System.UInt64)")) { continue; } return(true); } return(false); }
/* 0x00000375 06 IL_007D: ldloc.0 * 0x00000376 6F1500000A IL_007E: callvirt * 0x0000037B 19 IL_0083: ldc.i4.3 * 0x0000037C 6F1600000A IL_0084: callvirt */ private bool ReplaceFieldNameChar(ref IList <Instruction> instructions, string fieldName, Local fieldLocal) { for (var i = 0; i < instructions.Count; i++) { var instrs = DotNetUtils.GetInstructions(instructions, i, OpCodes.Ldloc, OpCodes.Callvirt, OpCodes.Ldc_I4, OpCodes.Callvirt); if (instrs == null) { continue; } if ((Local)instrs[0].Operand != fieldLocal) { continue; } if (!instrs[1].Operand.ToString().Contains("get_Name")) { continue; } if (!instrs[3].Operand.ToString().Contains("get_Chars")) { continue; } var charIndex = (int)instrs[2].Operand; int @char = fieldName[charIndex]; instructions[i].OpCode = OpCodes.Ldc_I4; instructions[i].Operand = @char; instructions[i + 1].OpCode = OpCodes.Nop; instructions[i + 2].OpCode = OpCodes.Nop; instructions[i + 3].OpCode = OpCodes.Nop; return(true); } return(false); }