void DeobfuscateMethod(MethodDef method) { if (!method.IsStatic || method.Body == null) { return; } bool fixReturnType = IsUnknownType(method.MethodSig.GetRetType()); argInfos.Clear(); foreach (var arg in method.Parameters) { if (arg.IsHiddenThisParameter) { continue; } if (!IsUnknownType(arg)) { continue; } argInfos[arg] = new TypeInfo <Parameter>(arg); } if (argInfos.Count == 0 && !fixReturnType) { return; } var methodParams = method.Parameters; PushedArgs pushedArgs; var instructions = method.Body.Instructions; for (int i = 0; i < instructions.Count; i++) { var instr = instructions[i]; switch (instr.OpCode.Code) { case Code.Ret: if (!fixReturnType) { break; } bool wasNewobj; var type = GetLoadedType(method, method, instructions, i, out wasNewobj); if (type == null) { break; } methodReturnInfo.Add(type); break; case Code.Call: case Code.Calli: case Code.Callvirt: case Code.Newobj: pushedArgs = MethodStack.GetPushedArgInstructions(instructions, i); var calledMethod = instr.Operand as IMethod; if (calledMethod == null) { break; } var calledMethodParams = DotNetUtils.GetArgs(calledMethod); for (int j = 0; j < pushedArgs.NumValidArgs; j++) { int calledMethodParamIndex = calledMethodParams.Count - j - 1; var ldInstr = pushedArgs.GetEnd(j); switch (ldInstr.OpCode.Code) { case Code.Ldarg: case Code.Ldarg_S: case Code.Ldarg_0: case Code.Ldarg_1: case Code.Ldarg_2: case Code.Ldarg_3: AddMethodArgType(method, GetParameter(methodParams, ldInstr), DotNetUtils.GetArg(calledMethodParams, calledMethodParamIndex)); break; default: break; } } break; case Code.Castclass: pushedArgs = MethodStack.GetPushedArgInstructions(instructions, i); if (pushedArgs.NumValidArgs < 1) { break; } AddMethodArgType(method, GetParameter(methodParams, pushedArgs.GetEnd(0)), instr.Operand as ITypeDefOrRef); break; case Code.Stloc: case Code.Stloc_S: case Code.Stloc_0: case Code.Stloc_1: case Code.Stloc_2: case Code.Stloc_3: pushedArgs = MethodStack.GetPushedArgInstructions(instructions, i); if (pushedArgs.NumValidArgs < 1) { break; } AddMethodArgType(method, GetParameter(methodParams, pushedArgs.GetEnd(0)), instr.GetLocal(method.Body.Variables)); break; case Code.Stsfld: pushedArgs = MethodStack.GetPushedArgInstructions(instructions, i); if (pushedArgs.NumValidArgs < 1) { break; } AddMethodArgType(method, GetParameter(methodParams, pushedArgs.GetEnd(0)), instr.Operand as IField); break; case Code.Stfld: pushedArgs = MethodStack.GetPushedArgInstructions(instructions, i); if (pushedArgs.NumValidArgs >= 1) { var field = instr.Operand as IField; AddMethodArgType(method, GetParameter(methodParams, pushedArgs.GetEnd(0)), field); if (pushedArgs.NumValidArgs >= 2 && field != null) { AddMethodArgType(method, GetParameter(methodParams, pushedArgs.GetEnd(1)), field.DeclaringType); } } break; case Code.Ldfld: case Code.Ldflda: pushedArgs = MethodStack.GetPushedArgInstructions(instructions, i); if (pushedArgs.NumValidArgs < 1) { break; } AddMethodArgType(method, GetParameter(methodParams, pushedArgs.GetEnd(0)), instr.Operand as IField); break; //TODO: For better results, these should be checked: case Code.Starg: case Code.Starg_S: case Code.Ldelema: case Code.Ldelem: case Code.Ldelem_I: case Code.Ldelem_I1: case Code.Ldelem_I2: case Code.Ldelem_I4: case Code.Ldelem_I8: case Code.Ldelem_R4: case Code.Ldelem_R8: case Code.Ldelem_Ref: case Code.Ldelem_U1: case Code.Ldelem_U2: case Code.Ldelem_U4: case Code.Ldind_I: case Code.Ldind_I1: case Code.Ldind_I2: case Code.Ldind_I4: case Code.Ldind_I8: case Code.Ldind_R4: case Code.Ldind_R8: case Code.Ldind_Ref: case Code.Ldind_U1: case Code.Ldind_U2: case Code.Ldind_U4: case Code.Ldobj: case Code.Stelem: case Code.Stelem_I: case Code.Stelem_I1: case Code.Stelem_I2: case Code.Stelem_I4: case Code.Stelem_I8: case Code.Stelem_R4: case Code.Stelem_R8: case Code.Stelem_Ref: case Code.Stind_I: case Code.Stind_I1: case Code.Stind_I2: case Code.Stind_I4: case Code.Stind_I8: case Code.Stind_R4: case Code.Stind_R8: case Code.Stind_Ref: case Code.Stobj: default: break; } } }