public static TypeReference getLoadedType(MethodDefinition method, IList <Instruction> instructions, int instrIndex, int argIndexFromEnd, out bool wasNewobj) { wasNewobj = false; var pushedArgs = MethodStack.getPushedArgInstructions(instructions, instrIndex); var pushInstr = pushedArgs.getEnd(argIndexFromEnd); if (pushInstr == null) { return(null); } TypeReference type; VariableDefinition local; switch (pushInstr.OpCode.Code) { case Code.Ldstr: type = method.Module.TypeSystem.String; break; case Code.Conv_I: case Code.Conv_Ovf_I: case Code.Conv_Ovf_I_Un: type = method.Module.TypeSystem.IntPtr; break; case Code.Conv_U: case Code.Conv_Ovf_U: case Code.Conv_Ovf_U_Un: type = method.Module.TypeSystem.UIntPtr; break; case Code.Conv_I8: case Code.Conv_Ovf_I8: case Code.Conv_Ovf_I8_Un: type = method.Module.TypeSystem.Int64; break; case Code.Conv_U8: case Code.Conv_Ovf_U8: case Code.Conv_Ovf_U8_Un: type = method.Module.TypeSystem.UInt64; break; case Code.Conv_R8: case Code.Ldc_R8: case Code.Ldelem_R8: case Code.Ldind_R8: type = method.Module.TypeSystem.Double; break; case Code.Call: case Code.Calli: case Code.Callvirt: var calledMethod = pushInstr.Operand as MethodReference; if (calledMethod == null) { return(null); } type = calledMethod.MethodReturnType.ReturnType; break; case Code.Newarr: type = pushInstr.Operand as TypeReference; if (type == null) { return(null); } type = new ArrayType(type); wasNewobj = true; break; case Code.Newobj: var ctor = pushInstr.Operand as MethodReference; if (ctor == null) { return(null); } type = ctor.DeclaringType; wasNewobj = true; break; case Code.Castclass: case Code.Isinst: case Code.Unbox_Any: case Code.Ldelem_Any: case Code.Ldobj: type = pushInstr.Operand as TypeReference; break; case Code.Ldarg: case Code.Ldarg_S: case Code.Ldarg_0: case Code.Ldarg_1: case Code.Ldarg_2: case Code.Ldarg_3: type = DotNetUtils.getArgType(method, pushInstr); break; case Code.Ldloc: case Code.Ldloc_S: case Code.Ldloc_0: case Code.Ldloc_1: case Code.Ldloc_2: case Code.Ldloc_3: local = DotNetUtils.getLocalVar(method.Body.Variables, pushInstr); if (local == null) { return(null); } type = local.VariableType; break; case Code.Ldloca: case Code.Ldloca_S: local = pushInstr.Operand as VariableDefinition; if (local == null) { return(null); } type = createByReferenceType(local.VariableType); break; case Code.Ldarga: case Code.Ldarga_S: type = createByReferenceType(DotNetUtils.getArgType(method, pushInstr)); break; case Code.Ldfld: case Code.Ldsfld: var field = pushInstr.Operand as FieldReference; if (field == null) { return(null); } type = field.FieldType; break; case Code.Ldflda: case Code.Ldsflda: var field2 = pushInstr.Operand as FieldReference; if (field2 == null) { return(null); } type = createByReferenceType(field2.FieldType); break; case Code.Ldelema: case Code.Unbox: type = createByReferenceType(pushInstr.Operand as TypeReference); break; default: return(null); } return(type); }
public bool deobfuscate(List <Block> allBlocks) { if (!init(allBlocks)) { return(false); } bool changed = false; var indexesToRemove = new List <int>(); foreach (var block in allBlocks) { indexesToRemove.Clear(); var instrs = block.Instructions; for (int i = 0; i < instrs.Count - 1; i++) { var instr = instrs[i]; if (instr.OpCode.Code == Code.Ldloca || instr.OpCode.Code == Code.Ldloca_S) { var local = instr.Operand as VariableDefinition; if (local == null) { continue; } localInfos[local].invalid(); } else if (instr.isLdloc()) { var local = DotNetUtils.getLocalVar(blocks.Locals, instr.Instruction); if (local == null) { continue; } var localInfo = localInfos[local]; var cast = instrs[i + 1]; if (localInfo.CastType == null) { continue; } if (!isCast(cast)) { throw new ApplicationException("Not a cast instr"); } indexesToRemove.Add(i + 1); } } if (indexesToRemove.Count > 0) { block.remove(indexesToRemove); changed = true; } } foreach (var info in localInfos.Values) { if (info.CastType == null) { continue; } info.local.VariableType = info.CastType; } if (changed) { foreach (var block in allBlocks) { var instrs = block.Instructions; for (int i = 0; i < instrs.Count - 1; i++) { var instr = instrs[i]; int castIndex = i + 1; if (instr.OpCode.Code == Code.Dup) { if (i == 0) { continue; } castIndex = i; instr = instrs[i - 1]; } if (instr.isLdarg()) { addCast(block, castIndex, i + 1, DotNetUtils.getArgType(blocks.Method, instr.Instruction)); } else if (instr.OpCode.Code == Code.Ldfld || instr.OpCode.Code == Code.Ldsfld) { var field = instr.Operand as FieldReference; if (field == null) { continue; } addCast(block, castIndex, i + 1, field.FieldType); } else if (instr.OpCode.Code == Code.Call || instr.OpCode.Code == Code.Callvirt) { var calledMethod = instr.Operand as MethodReference; if (calledMethod == null || !DotNetUtils.hasReturnValue(calledMethod)) { continue; } addCast(block, castIndex, i + 1, calledMethod.MethodReturnType.ReturnType); } } } } return(changed); }