bool VerifyValidArgs(Instruction instr) { int pushes, pops; instr.CalculateStackUsage(out pushes, out pops); if (pops < 0) { return(false); } bool retVal; Value val2, val1; switch (pops) { case 0: return(true); case 1: val1 = instructionEmulator.Pop(); retVal = VerifyValidArg(val1); instructionEmulator.Push(val1); return(retVal); case 2: val2 = instructionEmulator.Pop(); val1 = instructionEmulator.Pop(); retVal = VerifyValidArg(val2) && VerifyValidArg(val1); instructionEmulator.Push(val1); instructionEmulator.Push(val2); return(retVal); } return(false); }
bool FindInts(int index) { if (index < 0) return false; i2 = 0; var instrs = stringMethod.Body.Instructions; var emu = new InstructionEmulator(stringMethod); foreach (var kv in stringMethodConsts.Locals32) emu.SetLocal(kv.Key, new Int32Value(kv.Value)); var fields = new Dictionary<FieldDef, int?>(); for (int i = index; i < instrs.Count - 2; i++) { var instr = instrs[i]; FieldDef field; switch (instr.OpCode.Code) { case Code.Ldsfld: field = instr.Operand as FieldDef; if (field == null || field.DeclaringType != stringMethod.DeclaringType || field.FieldType.GetElementType() != ElementType.I4) goto default; fields[field] = null; emu.Push(new Int32Value(i1)); break; case Code.Stsfld: field = instr.Operand as FieldDef; if (field == null || field.DeclaringType != stringMethod.DeclaringType || field.FieldType.GetElementType() != ElementType.I4) goto default; if (fields.ContainsKey(field) && fields[field] == null) goto default; var val = emu.Pop() as Int32Value; if (val == null || !val.AllBitsValid()) fields[field] = null; else fields[field] = val.Value; break; case Code.Call: var method = instr.Operand as MethodDef; if (!decrypterType.Detected || method != decrypterType.Int64Method) goto done; emu.Push(new Int64Value((long)decrypterType.GetMagic())); break; case Code.Newobj: if (!EmulateDynocode(emu, ref i)) goto default; break; default: if (instr.OpCode.FlowControl != FlowControl.Next) goto done; emu.Emulate(instr); break; } } done: foreach (var val in fields.Values) { if (val == null) continue; magic1 = i2 = val.Value; return true; } return false; }
// 5.1+ // the only changes are the indexes of ldloc and stfld bool EmulateDynocodeNew(InstructionEmulator emu, ref int index) { var instrs = stringMethod.Body.Instructions; var instr = instrs[index]; var ctor = instr.Operand as MethodDef; if (ctor == null || ctor.MethodSig.GetParamCount() != 1 || ctor.MethodSig.Params[0].ElementType != ElementType.I4) return false; if (index + 4 >= instrs.Count) return false; var ldloc = instrs[index + 2]; var stfld = instrs[index + 3]; if (!ldloc.IsLdloc() || stfld.OpCode.Code != Code.Stfld) return false; var enumerableField = stfld.Operand as FieldDef; if (enumerableField == null) return false; var initValue = emu.GetLocal(ldloc.GetLocal(stringMethod.Body.Variables)) as Int32Value; if (initValue == null || !initValue.AllBitsValid()) return false; int leaveIndex = FindLeave(instrs, index); if (leaveIndex < 0) return false; var afterLoop = instrs[leaveIndex].Operand as Instruction; if (afterLoop == null) return false; int newIndex = instrs.IndexOf(afterLoop); var loopLocal = GetDCLoopLocal(index, newIndex); if (loopLocal == null) return false; var initValue2 = emu.GetLocal(loopLocal) as Int32Value; if (initValue2 == null || !initValue2.AllBitsValid()) return false; int loopStart = GetIndexOfCall(instrs, index, leaveIndex, "System.Int32", "()"); int loopEnd = GetIndexOfCall(instrs, loopStart, leaveIndex, "System.Boolean", "()"); if (loopStart < 0 || loopEnd < 0) return false; loopStart++; loopEnd--; dynocode.Initialize(module); var ctorArg = emu.Pop() as Int32Value; if (ctorArg == null || !ctorArg.AllBitsValid()) return false; dynocode.CreateEnumerable(ctor, new object[] { ctorArg.Value }); dynocode.WriteEnumerableField(enumerableField.MDToken.ToUInt32(), initValue.Value); dynocode.CreateEnumerator(); foreach (var val in dynocode) { emu.Push(new Int32Value(val)); for (int i = loopStart; i < loopEnd; i++) emu.Emulate(instrs[i]); } index = newIndex - 1; return true; }
public static Value[] GetInitializedArray(int arraySize, MethodDef method, ref int newarrIndex, Code stelemOpCode) { var resultValueArray = new Value[arraySize]; var emulator = new InstructionEmulator(method); var theArray = new UnknownValue(); emulator.Push(theArray); var instructions = method.Body.Instructions; int i; for (i = newarrIndex + 1; i < instructions.Count; i++) { var instr = instructions[i]; if (instr.OpCode.FlowControl != FlowControl.Next) break; if (instr.OpCode.Code == Code.Newarr) break; switch (instr.OpCode.Code) { case Code.Newarr: case Code.Newobj: goto done; case Code.Stloc: case Code.Stloc_S: case Code.Stloc_0: case Code.Stloc_1: case Code.Stloc_2: case Code.Stloc_3: case Code.Starg: case Code.Starg_S: case Code.Stsfld: case Code.Stfld: if (emulator.Peek() == theArray && i != newarrIndex + 1 && i != newarrIndex + 2) goto done; break; } if (instr.OpCode.Code == stelemOpCode) { var value = emulator.Pop(); var index = emulator.Pop() as Int32Value; var array = emulator.Pop(); if (ReferenceEquals(array, theArray) && index != null && index.AllBitsValid()) { if (0 <= index.Value && index.Value < resultValueArray.Length) resultValueArray[index.Value] = value; } } else emulator.Emulate(instr); } done: if (i != newarrIndex + 1) i--; newarrIndex = i; return resultValueArray; }